Skip to content

Commit

Permalink
[FuzzMutate] Support opaque pointers
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
nikic committed Mar 10, 2022
1 parent 808d9d2 commit 3c47dd4
Show file tree
Hide file tree
Showing 3 changed files with 22 additions and 8 deletions.
3 changes: 2 additions & 1 deletion llvm/include/llvm/FuzzMutate/OpDescriptor.h
Expand Up @@ -146,7 +146,8 @@ static inline SourcePred sizedPtrType() {
return false;

if (const auto *PtrT = dyn_cast<PointerType>(V->getType()))
return PtrT->getPointerElementType()->isSized();
return PtrT->isOpaque() ||
PtrT->getNonOpaquePointerElementType()->isSized();
return false;
};
auto Make = [](ArrayRef<Value *>, ArrayRef<Type *> Ts) {
Expand Down
13 changes: 10 additions & 3 deletions llvm/lib/FuzzMutate/Operations.cpp
Expand Up @@ -169,14 +169,21 @@ OpDescriptor llvm::fuzzerop::splitBlockDescriptor(unsigned Weight) {

OpDescriptor llvm::fuzzerop::gepDescriptor(unsigned Weight) {
auto buildGEP = [](ArrayRef<Value *> 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<Value *>, const Value *V) { return V->getType()->isSized(); },
None);
return {Weight, {sizedPtrType(), sizedType, anyIntType()}, buildGEP};
}

static uint64_t getAggregateNumElements(Type *T) {
Expand Down
14 changes: 10 additions & 4 deletions llvm/lib/FuzzMutate/RandomIRBuilder.cpp
Expand Up @@ -53,8 +53,11 @@ Value *RandomIRBuilder::newSource(BasicBlock &BB, ArrayRef<Instruction *> 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))
Expand Down Expand Up @@ -139,9 +142,12 @@ Value *RandomIRBuilder::findPointer(BasicBlock &BB,
if (Inst->isTerminator())
return false;

if (auto PtrTy = dyn_cast<PointerType>(Inst->getType())) {
if (auto *PtrTy = dyn_cast<PointerType>(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;

Expand Down

0 comments on commit 3c47dd4

Please sign in to comment.