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