From 3c47dd47a42a87b9724a558a6baeab5a8d6e4a69 Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Thu, 10 Mar 2022 14:18:37 +0100 Subject: [PATCH] [FuzzMutate] Support opaque pointers Avoid checks that are irrelevant for opaque pointers, and pick load/GEP types independently of the pointer type. The GEP case at least could be done more efficiently by directly generating a type, but this would require some significant API changes. --- llvm/include/llvm/FuzzMutate/OpDescriptor.h | 3 ++- llvm/lib/FuzzMutate/Operations.cpp | 13 ++++++++++--- llvm/lib/FuzzMutate/RandomIRBuilder.cpp | 14 ++++++++++---- 3 files changed, 22 insertions(+), 8 deletions(-) diff --git a/llvm/include/llvm/FuzzMutate/OpDescriptor.h b/llvm/include/llvm/FuzzMutate/OpDescriptor.h index 43c8109..1d49cd5 100644 --- a/llvm/include/llvm/FuzzMutate/OpDescriptor.h +++ b/llvm/include/llvm/FuzzMutate/OpDescriptor.h @@ -146,7 +146,8 @@ static inline SourcePred sizedPtrType() { return false; if (const auto *PtrT = dyn_cast(V->getType())) - return PtrT->getPointerElementType()->isSized(); + return PtrT->isOpaque() || + PtrT->getNonOpaquePointerElementType()->isSized(); return false; }; auto Make = [](ArrayRef, ArrayRef Ts) { diff --git a/llvm/lib/FuzzMutate/Operations.cpp b/llvm/lib/FuzzMutate/Operations.cpp index 221a3a8..7db24bb 100644 --- a/llvm/lib/FuzzMutate/Operations.cpp +++ b/llvm/lib/FuzzMutate/Operations.cpp @@ -169,14 +169,21 @@ OpDescriptor llvm::fuzzerop::splitBlockDescriptor(unsigned Weight) { OpDescriptor llvm::fuzzerop::gepDescriptor(unsigned Weight) { auto buildGEP = [](ArrayRef Srcs, Instruction *Inst) { - Type *Ty = Srcs[0]->getType()->getPointerElementType(); - auto Indices = makeArrayRef(Srcs).drop_front(1); + // TODO: It would be better to generate a random type here, rather than + // generating a random value and picking its type. + Type *Ty = Srcs[0]->getType()->isOpaquePointerTy() + ? Srcs[1]->getType() + : Srcs[0]->getType()->getNonOpaquePointerElementType(); + auto Indices = makeArrayRef(Srcs).drop_front(2); return GetElementPtrInst::Create(Ty, Srcs[0], Indices, "G", Inst); }; // TODO: Handle aggregates and vectors // TODO: Support multiple indices. // TODO: Try to avoid meaningless accesses. - return {Weight, {sizedPtrType(), anyIntType()}, buildGEP}; + SourcePred sizedType( + [](ArrayRef, const Value *V) { return V->getType()->isSized(); }, + None); + return {Weight, {sizedPtrType(), sizedType, anyIntType()}, buildGEP}; } static uint64_t getAggregateNumElements(Type *T) { diff --git a/llvm/lib/FuzzMutate/RandomIRBuilder.cpp b/llvm/lib/FuzzMutate/RandomIRBuilder.cpp index 27c3bdf..0579dde 100644 --- a/llvm/lib/FuzzMutate/RandomIRBuilder.cpp +++ b/llvm/lib/FuzzMutate/RandomIRBuilder.cpp @@ -53,8 +53,11 @@ Value *RandomIRBuilder::newSource(BasicBlock &BB, ArrayRef Insts, IP = ++I->getIterator(); assert(IP != BB.end() && "guaranteed by the findPointer"); } - auto *NewLoad = - new LoadInst(Ptr->getType()->getPointerElementType(), Ptr, "L", &*IP); + // For opaque pointers, pick the type independently. + Type *AccessTy = Ptr->getType()->isOpaquePointerTy() + ? RS.getSelection()->getType() + : Ptr->getType()->getNonOpaquePointerElementType(); + auto *NewLoad = new LoadInst(AccessTy, Ptr, "L", &*IP); // Only sample this load if it really matches the descriptor if (Pred.matches(Srcs, NewLoad)) @@ -139,9 +142,12 @@ Value *RandomIRBuilder::findPointer(BasicBlock &BB, if (Inst->isTerminator()) return false; - if (auto PtrTy = dyn_cast(Inst->getType())) { + if (auto *PtrTy = dyn_cast(Inst->getType())) { + if (PtrTy->isOpaque()) + return true; + // We can never generate loads from non first class or non sized types - Type *ElemTy = PtrTy->getPointerElementType(); + Type *ElemTy = PtrTy->getNonOpaquePointerElementType(); if (!ElemTy->isSized() || !ElemTy->isFirstClassType()) return false; -- 2.7.4