1 //===-- RandomIRBuilder.cpp -----------------------------------------------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #include "llvm/FuzzMutate/RandomIRBuilder.h" 11 #include "llvm/ADT/STLExtras.h" 12 #include "llvm/FuzzMutate/Random.h" 13 #include "llvm/IR/BasicBlock.h" 14 #include "llvm/IR/Constants.h" 15 #include "llvm/IR/Function.h" 16 #include "llvm/IR/Instructions.h" 17 #include "llvm/IR/IntrinsicInst.h" 18 19 using namespace llvm; 20 using namespace fuzzerop; 21 22 Value *RandomIRBuilder::findOrCreateSource(BasicBlock &BB, 23 ArrayRef<Instruction *> Insts) { 24 return findOrCreateSource(BB, Insts, {}, anyType()); 25 } 26 27 Value *RandomIRBuilder::findOrCreateSource(BasicBlock &BB, 28 ArrayRef<Instruction *> Insts, 29 ArrayRef<Value *> Srcs, 30 SourcePred Pred) { 31 auto MatchesPred = [&Srcs, &Pred](Instruction *Inst) { 32 return Pred.matches(Srcs, Inst); 33 }; 34 auto RS = makeSampler(Rand, make_filter_range(Insts, MatchesPred)); 35 // Also consider choosing no source, meaning we want a new one. 36 RS.sample(nullptr, /*Weight=*/1); 37 if (Instruction *Src = RS.getSelection()) 38 return Src; 39 return newSource(BB, Insts, Srcs, Pred); 40 } 41 42 Value *RandomIRBuilder::newSource(BasicBlock &BB, ArrayRef<Instruction *> Insts, 43 ArrayRef<Value *> Srcs, SourcePred Pred) { 44 // Generate some constants to choose from. 45 auto RS = makeSampler<Value *>(Rand); 46 RS.sample(Pred.generate(Srcs, KnownTypes)); 47 48 // If we can find a pointer to load from, use it half the time. 49 Value *Ptr = findPointer(BB, Insts, Srcs, Pred); 50 if (Ptr) { 51 // Create load from the chosen pointer 52 auto IP = BB.getFirstInsertionPt(); 53 if (auto *I = dyn_cast<Instruction>(Ptr)) { 54 IP = ++I->getIterator(); 55 assert(IP != BB.end() && "guaranteed by the findPointer"); 56 } 57 auto *NewLoad = new LoadInst(Ptr, "L", &*IP); 58 59 // Only sample this load if it really matches the descriptor 60 if (Pred.matches(Srcs, NewLoad)) 61 RS.sample(NewLoad, RS.totalWeight()); 62 else 63 NewLoad->eraseFromParent(); 64 } 65 66 assert(!RS.isEmpty() && "Failed to generate sources"); 67 return RS.getSelection(); 68 } 69 70 static bool isCompatibleReplacement(const Instruction *I, const Use &Operand, 71 const Value *Replacement) { 72 if (Operand->getType() != Replacement->getType()) 73 return false; 74 switch (I->getOpcode()) { 75 case Instruction::GetElementPtr: 76 case Instruction::ExtractElement: 77 case Instruction::ExtractValue: 78 // TODO: We could potentially validate these, but for now just leave indices 79 // alone. 80 if (Operand.getOperandNo() >= 1) 81 return false; 82 break; 83 case Instruction::InsertValue: 84 case Instruction::InsertElement: 85 case Instruction::ShuffleVector: 86 if (Operand.getOperandNo() >= 2) 87 return false; 88 break; 89 default: 90 break; 91 } 92 return true; 93 } 94 95 void RandomIRBuilder::connectToSink(BasicBlock &BB, 96 ArrayRef<Instruction *> Insts, Value *V) { 97 auto RS = makeSampler<Use *>(Rand); 98 for (auto &I : Insts) { 99 if (isa<IntrinsicInst>(I)) 100 // TODO: Replacing operands of intrinsics would be interesting, but 101 // there's no easy way to verify that a given replacement is valid given 102 // that intrinsics can impose arbitrary constraints. 103 continue; 104 for (Use &U : I->operands()) 105 if (isCompatibleReplacement(I, U, V)) 106 RS.sample(&U, 1); 107 } 108 // Also consider choosing no sink, meaning we want a new one. 109 RS.sample(nullptr, /*Weight=*/1); 110 111 if (Use *Sink = RS.getSelection()) { 112 User *U = Sink->getUser(); 113 unsigned OpNo = Sink->getOperandNo(); 114 U->setOperand(OpNo, V); 115 return; 116 } 117 newSink(BB, Insts, V); 118 } 119 120 void RandomIRBuilder::newSink(BasicBlock &BB, ArrayRef<Instruction *> Insts, 121 Value *V) { 122 Value *Ptr = findPointer(BB, Insts, {V}, matchFirstType()); 123 if (!Ptr) { 124 if (uniform(Rand, 0, 1)) 125 Ptr = new AllocaInst(V->getType(), 0, "A", &*BB.getFirstInsertionPt()); 126 else 127 Ptr = UndefValue::get(PointerType::get(V->getType(), 0)); 128 } 129 130 new StoreInst(V, Ptr, Insts.back()); 131 } 132 133 Value *RandomIRBuilder::findPointer(BasicBlock &BB, 134 ArrayRef<Instruction *> Insts, 135 ArrayRef<Value *> Srcs, SourcePred Pred) { 136 auto IsMatchingPtr = [&Srcs, &Pred](Instruction *Inst) { 137 // Invoke instructions sometimes produce valid pointers but currently 138 // we can't insert loads or stores from them 139 if (Inst->isTerminator()) 140 return false; 141 142 if (auto PtrTy = dyn_cast<PointerType>(Inst->getType())) { 143 // We can never generate loads from non first class or non sized types 144 if (!PtrTy->getElementType()->isSized() || 145 !PtrTy->getElementType()->isFirstClassType()) 146 return false; 147 148 // TODO: Check if this is horribly expensive. 149 return Pred.matches(Srcs, UndefValue::get(PtrTy->getElementType())); 150 } 151 return false; 152 }; 153 if (auto RS = makeSampler(Rand, make_filter_range(Insts, IsMatchingPtr))) 154 return RS.getSelection(); 155 return nullptr; 156 } 157