xref: /freebsd-src/contrib/llvm-project/llvm/lib/FuzzMutate/RandomIRBuilder.cpp (revision 06c3fb2749bda94cb5201f81ffdb8fa6c3161b2e)
10b57cec5SDimitry Andric //===-- RandomIRBuilder.cpp -----------------------------------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric 
90b57cec5SDimitry Andric #include "llvm/FuzzMutate/RandomIRBuilder.h"
100b57cec5SDimitry Andric #include "llvm/ADT/STLExtras.h"
1181ad6265SDimitry Andric #include "llvm/FuzzMutate/OpDescriptor.h"
120b57cec5SDimitry Andric #include "llvm/FuzzMutate/Random.h"
130b57cec5SDimitry Andric #include "llvm/IR/BasicBlock.h"
140b57cec5SDimitry Andric #include "llvm/IR/Constants.h"
15bdd1243dSDimitry Andric #include "llvm/IR/DataLayout.h"
16*06c3fb27SDimitry Andric #include "llvm/IR/Dominators.h"
17*06c3fb27SDimitry Andric #include "llvm/IR/Function.h"
180b57cec5SDimitry Andric #include "llvm/IR/Instructions.h"
190b57cec5SDimitry Andric #include "llvm/IR/IntrinsicInst.h"
20*06c3fb27SDimitry Andric #include "llvm/IR/Module.h"
210b57cec5SDimitry Andric 
220b57cec5SDimitry Andric using namespace llvm;
230b57cec5SDimitry Andric using namespace fuzzerop;
240b57cec5SDimitry Andric 
25*06c3fb27SDimitry Andric /// Return a vector of Blocks that dominates this block, excluding current
26*06c3fb27SDimitry Andric /// block.
getDominators(BasicBlock * BB)27*06c3fb27SDimitry Andric static std::vector<BasicBlock *> getDominators(BasicBlock *BB) {
28*06c3fb27SDimitry Andric   std::vector<BasicBlock *> ret;
29*06c3fb27SDimitry Andric   DominatorTree DT(*BB->getParent());
30*06c3fb27SDimitry Andric   DomTreeNode *Node = DT.getNode(BB);
31*06c3fb27SDimitry Andric   // It's possible that an orphan block is not in the dom tree. In that case we
32*06c3fb27SDimitry Andric   // just return nothing.
33*06c3fb27SDimitry Andric   if (!Node)
34*06c3fb27SDimitry Andric     return ret;
35*06c3fb27SDimitry Andric   Node = Node->getIDom();
36*06c3fb27SDimitry Andric   while (Node && Node->getBlock()) {
37*06c3fb27SDimitry Andric     ret.push_back(Node->getBlock());
38*06c3fb27SDimitry Andric     // Get parent block.
39*06c3fb27SDimitry Andric     Node = Node->getIDom();
40*06c3fb27SDimitry Andric   }
41*06c3fb27SDimitry Andric   return ret;
42*06c3fb27SDimitry Andric }
43*06c3fb27SDimitry Andric 
44*06c3fb27SDimitry Andric /// Return a vector of Blocks that is dominated by this block, excluding current
45*06c3fb27SDimitry Andric /// block
getDominatees(BasicBlock * BB)46*06c3fb27SDimitry Andric static std::vector<BasicBlock *> getDominatees(BasicBlock *BB) {
47*06c3fb27SDimitry Andric   DominatorTree DT(*BB->getParent());
48*06c3fb27SDimitry Andric   std::vector<BasicBlock *> ret;
49*06c3fb27SDimitry Andric   DomTreeNode *Parent = DT.getNode(BB);
50*06c3fb27SDimitry Andric   // It's possible that an orphan block is not in the dom tree. In that case we
51*06c3fb27SDimitry Andric   // just return nothing.
52*06c3fb27SDimitry Andric   if (!Parent)
53*06c3fb27SDimitry Andric     return ret;
54*06c3fb27SDimitry Andric   for (DomTreeNode *Child : Parent->children())
55*06c3fb27SDimitry Andric     ret.push_back(Child->getBlock());
56*06c3fb27SDimitry Andric   uint64_t Idx = 0;
57*06c3fb27SDimitry Andric   while (Idx < ret.size()) {
58*06c3fb27SDimitry Andric     DomTreeNode *Node = DT[ret[Idx]];
59*06c3fb27SDimitry Andric     Idx++;
60*06c3fb27SDimitry Andric     for (DomTreeNode *Child : Node->children())
61*06c3fb27SDimitry Andric       ret.push_back(Child->getBlock());
62*06c3fb27SDimitry Andric   }
63*06c3fb27SDimitry Andric   return ret;
64*06c3fb27SDimitry Andric }
65*06c3fb27SDimitry Andric 
createStackMemory(Function * F,Type * Ty,Value * Init)66*06c3fb27SDimitry Andric AllocaInst *RandomIRBuilder::createStackMemory(Function *F, Type *Ty,
67*06c3fb27SDimitry Andric                                                Value *Init) {
68*06c3fb27SDimitry Andric   /// TODO: For all Allocas, maybe allocate an array.
69*06c3fb27SDimitry Andric   BasicBlock *EntryBB = &F->getEntryBlock();
70*06c3fb27SDimitry Andric   DataLayout DL(F->getParent());
71*06c3fb27SDimitry Andric   AllocaInst *Alloca = new AllocaInst(Ty, DL.getAllocaAddrSpace(), "A",
72*06c3fb27SDimitry Andric                                       &*EntryBB->getFirstInsertionPt());
73*06c3fb27SDimitry Andric   if (Init)
74*06c3fb27SDimitry Andric     new StoreInst(Init, Alloca, Alloca->getNextNode());
75*06c3fb27SDimitry Andric   return Alloca;
76*06c3fb27SDimitry Andric }
77*06c3fb27SDimitry Andric 
78*06c3fb27SDimitry Andric std::pair<GlobalVariable *, bool>
findOrCreateGlobalVariable(Module * M,ArrayRef<Value * > Srcs,fuzzerop::SourcePred Pred)79*06c3fb27SDimitry Andric RandomIRBuilder::findOrCreateGlobalVariable(Module *M, ArrayRef<Value *> Srcs,
80*06c3fb27SDimitry Andric                                             fuzzerop::SourcePred Pred) {
81*06c3fb27SDimitry Andric   auto MatchesPred = [&Srcs, &Pred](GlobalVariable *GV) {
82*06c3fb27SDimitry Andric     // Can't directly compare GV's type, as it would be a pointer to the actual
83*06c3fb27SDimitry Andric     // type.
84*06c3fb27SDimitry Andric     return Pred.matches(Srcs, UndefValue::get(GV->getValueType()));
85*06c3fb27SDimitry Andric   };
86*06c3fb27SDimitry Andric   bool DidCreate = false;
87*06c3fb27SDimitry Andric   SmallVector<GlobalVariable *, 4> GlobalVars;
88*06c3fb27SDimitry Andric   for (GlobalVariable &GV : M->globals()) {
89*06c3fb27SDimitry Andric     GlobalVars.push_back(&GV);
90*06c3fb27SDimitry Andric   }
91*06c3fb27SDimitry Andric   auto RS = makeSampler(Rand, make_filter_range(GlobalVars, MatchesPred));
92*06c3fb27SDimitry Andric   RS.sample(nullptr, 1);
93*06c3fb27SDimitry Andric   GlobalVariable *GV = RS.getSelection();
94*06c3fb27SDimitry Andric   if (!GV) {
95*06c3fb27SDimitry Andric     DidCreate = true;
96*06c3fb27SDimitry Andric     using LinkageTypes = GlobalVariable::LinkageTypes;
97*06c3fb27SDimitry Andric     auto TRS = makeSampler<Constant *>(Rand);
98*06c3fb27SDimitry Andric     TRS.sample(Pred.generate(Srcs, KnownTypes));
99*06c3fb27SDimitry Andric     Constant *Init = TRS.getSelection();
100*06c3fb27SDimitry Andric     Type *Ty = Init->getType();
101*06c3fb27SDimitry Andric     GV = new GlobalVariable(*M, Ty, false, LinkageTypes::ExternalLinkage, Init,
102*06c3fb27SDimitry Andric                             "G", nullptr,
103*06c3fb27SDimitry Andric                             GlobalValue::ThreadLocalMode::NotThreadLocal,
104*06c3fb27SDimitry Andric                             M->getDataLayout().getDefaultGlobalsAddressSpace());
105*06c3fb27SDimitry Andric   }
106*06c3fb27SDimitry Andric   return {GV, DidCreate};
107*06c3fb27SDimitry Andric }
108*06c3fb27SDimitry Andric 
findOrCreateSource(BasicBlock & BB,ArrayRef<Instruction * > Insts)1090b57cec5SDimitry Andric Value *RandomIRBuilder::findOrCreateSource(BasicBlock &BB,
1100b57cec5SDimitry Andric                                            ArrayRef<Instruction *> Insts) {
1110b57cec5SDimitry Andric   return findOrCreateSource(BB, Insts, {}, anyType());
1120b57cec5SDimitry Andric }
1130b57cec5SDimitry Andric 
findOrCreateSource(BasicBlock & BB,ArrayRef<Instruction * > Insts,ArrayRef<Value * > Srcs,SourcePred Pred,bool allowConstant)1140b57cec5SDimitry Andric Value *RandomIRBuilder::findOrCreateSource(BasicBlock &BB,
1150b57cec5SDimitry Andric                                            ArrayRef<Instruction *> Insts,
1160b57cec5SDimitry Andric                                            ArrayRef<Value *> Srcs,
117bdd1243dSDimitry Andric                                            SourcePred Pred,
118bdd1243dSDimitry Andric                                            bool allowConstant) {
119*06c3fb27SDimitry Andric   auto MatchesPred = [&Srcs, &Pred](Value *V) { return Pred.matches(Srcs, V); };
120*06c3fb27SDimitry Andric   SmallVector<uint64_t, 8> SrcTys;
121*06c3fb27SDimitry Andric   for (uint64_t i = 0; i < EndOfValueSource; i++)
122*06c3fb27SDimitry Andric     SrcTys.push_back(i);
123*06c3fb27SDimitry Andric   std::shuffle(SrcTys.begin(), SrcTys.end(), Rand);
124*06c3fb27SDimitry Andric   for (uint64_t SrcTy : SrcTys) {
125*06c3fb27SDimitry Andric     switch (SrcTy) {
126*06c3fb27SDimitry Andric     case SrcFromInstInCurBlock: {
1270b57cec5SDimitry Andric       auto RS = makeSampler(Rand, make_filter_range(Insts, MatchesPred));
128*06c3fb27SDimitry Andric       if (!RS.isEmpty()) {
129*06c3fb27SDimitry Andric         return RS.getSelection();
130*06c3fb27SDimitry Andric       }
131*06c3fb27SDimitry Andric       break;
132*06c3fb27SDimitry Andric     }
133*06c3fb27SDimitry Andric     case FunctionArgument: {
134*06c3fb27SDimitry Andric       Function *F = BB.getParent();
135*06c3fb27SDimitry Andric       SmallVector<Argument *, 8> Args;
136*06c3fb27SDimitry Andric       for (uint64_t i = 0; i < F->arg_size(); i++) {
137*06c3fb27SDimitry Andric         Args.push_back(F->getArg(i));
138*06c3fb27SDimitry Andric       }
139*06c3fb27SDimitry Andric       auto RS = makeSampler(Rand, make_filter_range(Args, MatchesPred));
140*06c3fb27SDimitry Andric       if (!RS.isEmpty()) {
141*06c3fb27SDimitry Andric         return RS.getSelection();
142*06c3fb27SDimitry Andric       }
143*06c3fb27SDimitry Andric       break;
144*06c3fb27SDimitry Andric     }
145*06c3fb27SDimitry Andric     case InstInDominator: {
146*06c3fb27SDimitry Andric       auto Dominators = getDominators(&BB);
147*06c3fb27SDimitry Andric       std::shuffle(Dominators.begin(), Dominators.end(), Rand);
148*06c3fb27SDimitry Andric       for (BasicBlock *Dom : Dominators) {
149*06c3fb27SDimitry Andric         SmallVector<Instruction *, 16> Instructions;
150*06c3fb27SDimitry Andric         for (Instruction &I : *Dom) {
151*06c3fb27SDimitry Andric           Instructions.push_back(&I);
152*06c3fb27SDimitry Andric         }
153*06c3fb27SDimitry Andric         auto RS =
154*06c3fb27SDimitry Andric             makeSampler(Rand, make_filter_range(Instructions, MatchesPred));
1550b57cec5SDimitry Andric         // Also consider choosing no source, meaning we want a new one.
156*06c3fb27SDimitry Andric         if (!RS.isEmpty()) {
157*06c3fb27SDimitry Andric           return RS.getSelection();
158*06c3fb27SDimitry Andric         }
159*06c3fb27SDimitry Andric       }
160*06c3fb27SDimitry Andric       break;
161*06c3fb27SDimitry Andric     }
162*06c3fb27SDimitry Andric     case SrcFromGlobalVariable: {
163*06c3fb27SDimitry Andric       Module *M = BB.getParent()->getParent();
164*06c3fb27SDimitry Andric       auto [GV, DidCreate] = findOrCreateGlobalVariable(M, Srcs, Pred);
165*06c3fb27SDimitry Andric       Type *Ty = GV->getValueType();
166*06c3fb27SDimitry Andric       LoadInst *LoadGV = nullptr;
167*06c3fb27SDimitry Andric       if (BB.getTerminator()) {
168*06c3fb27SDimitry Andric         LoadGV = new LoadInst(Ty, GV, "LGV", &*BB.getFirstInsertionPt());
169*06c3fb27SDimitry Andric       } else {
170*06c3fb27SDimitry Andric         LoadGV = new LoadInst(Ty, GV, "LGV", &BB);
171*06c3fb27SDimitry Andric       }
172*06c3fb27SDimitry Andric       // Because we might be generating new values, we have to check if it
173*06c3fb27SDimitry Andric       // matches again.
174*06c3fb27SDimitry Andric       if (DidCreate) {
175*06c3fb27SDimitry Andric         if (Pred.matches(Srcs, LoadGV)) {
176*06c3fb27SDimitry Andric           return LoadGV;
177*06c3fb27SDimitry Andric         }
178*06c3fb27SDimitry Andric         LoadGV->eraseFromParent();
179*06c3fb27SDimitry Andric         // If no one is using this GlobalVariable, delete it too.
180*06c3fb27SDimitry Andric         if (GV->use_empty()) {
181*06c3fb27SDimitry Andric           GV->eraseFromParent();
182*06c3fb27SDimitry Andric         }
183*06c3fb27SDimitry Andric       }
184*06c3fb27SDimitry Andric       break;
185*06c3fb27SDimitry Andric     }
186*06c3fb27SDimitry Andric     case NewConstOrStack: {
187bdd1243dSDimitry Andric       return newSource(BB, Insts, Srcs, Pred, allowConstant);
1880b57cec5SDimitry Andric     }
189*06c3fb27SDimitry Andric     default:
190*06c3fb27SDimitry Andric     case EndOfValueSource: {
191*06c3fb27SDimitry Andric       llvm_unreachable("EndOfValueSource executed");
192*06c3fb27SDimitry Andric     }
193*06c3fb27SDimitry Andric     }
194*06c3fb27SDimitry Andric   }
195*06c3fb27SDimitry Andric   llvm_unreachable("Can't find a source");
196*06c3fb27SDimitry Andric }
1970b57cec5SDimitry Andric 
newSource(BasicBlock & BB,ArrayRef<Instruction * > Insts,ArrayRef<Value * > Srcs,SourcePred Pred,bool allowConstant)1980b57cec5SDimitry Andric Value *RandomIRBuilder::newSource(BasicBlock &BB, ArrayRef<Instruction *> Insts,
199bdd1243dSDimitry Andric                                   ArrayRef<Value *> Srcs, SourcePred Pred,
200bdd1243dSDimitry Andric                                   bool allowConstant) {
2010b57cec5SDimitry Andric   // Generate some constants to choose from.
2020b57cec5SDimitry Andric   auto RS = makeSampler<Value *>(Rand);
2030b57cec5SDimitry Andric   RS.sample(Pred.generate(Srcs, KnownTypes));
2040b57cec5SDimitry Andric 
2050b57cec5SDimitry Andric   // If we can find a pointer to load from, use it half the time.
206*06c3fb27SDimitry Andric   Value *Ptr = findPointer(BB, Insts);
2070b57cec5SDimitry Andric   if (Ptr) {
2080b57cec5SDimitry Andric     // Create load from the chosen pointer
2090b57cec5SDimitry Andric     auto IP = BB.getFirstInsertionPt();
2100b57cec5SDimitry Andric     if (auto *I = dyn_cast<Instruction>(Ptr)) {
2110b57cec5SDimitry Andric       IP = ++I->getIterator();
2120b57cec5SDimitry Andric       assert(IP != BB.end() && "guaranteed by the findPointer");
2130b57cec5SDimitry Andric     }
214*06c3fb27SDimitry Andric     // Pick the type independently.
215*06c3fb27SDimitry Andric     Type *AccessTy = RS.getSelection()->getType();
21681ad6265SDimitry Andric     auto *NewLoad = new LoadInst(AccessTy, Ptr, "L", &*IP);
2170b57cec5SDimitry Andric 
2180b57cec5SDimitry Andric     // Only sample this load if it really matches the descriptor
2190b57cec5SDimitry Andric     if (Pred.matches(Srcs, NewLoad))
2200b57cec5SDimitry Andric       RS.sample(NewLoad, RS.totalWeight());
2210b57cec5SDimitry Andric     else
2220b57cec5SDimitry Andric       NewLoad->eraseFromParent();
2230b57cec5SDimitry Andric   }
2240b57cec5SDimitry Andric 
225bdd1243dSDimitry Andric   Value *newSrc = RS.getSelection();
226bdd1243dSDimitry Andric   // Generate a stack alloca and store the constant to it if constant is not
227bdd1243dSDimitry Andric   // allowed, our hope is that later mutations can generate some values and
228bdd1243dSDimitry Andric   // store to this placeholder.
229bdd1243dSDimitry Andric   if (!allowConstant && isa<Constant>(newSrc)) {
230bdd1243dSDimitry Andric     Type *Ty = newSrc->getType();
231bdd1243dSDimitry Andric     Function *F = BB.getParent();
232*06c3fb27SDimitry Andric     AllocaInst *Alloca = createStackMemory(F, Ty, newSrc);
233bdd1243dSDimitry Andric     if (BB.getTerminator()) {
234bdd1243dSDimitry Andric       newSrc = new LoadInst(Ty, Alloca, /*ArrLen,*/ "L", BB.getTerminator());
235bdd1243dSDimitry Andric     } else {
236bdd1243dSDimitry Andric       newSrc = new LoadInst(Ty, Alloca, /*ArrLen,*/ "L", &BB);
237bdd1243dSDimitry Andric     }
238bdd1243dSDimitry Andric   }
239bdd1243dSDimitry Andric   return newSrc;
2400b57cec5SDimitry Andric }
2410b57cec5SDimitry Andric 
isCompatibleReplacement(const Instruction * I,const Use & Operand,const Value * Replacement)2420b57cec5SDimitry Andric static bool isCompatibleReplacement(const Instruction *I, const Use &Operand,
2430b57cec5SDimitry Andric                                     const Value *Replacement) {
244bdd1243dSDimitry Andric   unsigned int OperandNo = Operand.getOperandNo();
2450b57cec5SDimitry Andric   if (Operand->getType() != Replacement->getType())
2460b57cec5SDimitry Andric     return false;
2470b57cec5SDimitry Andric   switch (I->getOpcode()) {
2480b57cec5SDimitry Andric   case Instruction::GetElementPtr:
2490b57cec5SDimitry Andric   case Instruction::ExtractElement:
2500b57cec5SDimitry Andric   case Instruction::ExtractValue:
2510b57cec5SDimitry Andric     // TODO: We could potentially validate these, but for now just leave indices
2520b57cec5SDimitry Andric     // alone.
253bdd1243dSDimitry Andric     if (OperandNo >= 1)
2540b57cec5SDimitry Andric       return false;
2550b57cec5SDimitry Andric     break;
2560b57cec5SDimitry Andric   case Instruction::InsertValue:
2570b57cec5SDimitry Andric   case Instruction::InsertElement:
2580b57cec5SDimitry Andric   case Instruction::ShuffleVector:
259bdd1243dSDimitry Andric     if (OperandNo >= 2)
260bdd1243dSDimitry Andric       return false;
261bdd1243dSDimitry Andric     break;
262bdd1243dSDimitry Andric   // For Br/Switch, we only try to modify the 1st Operand (condition).
263bdd1243dSDimitry Andric   // Modify other operands, like switch case may accidently change case from
264bdd1243dSDimitry Andric   // ConstantInt to a register, which is illegal.
265bdd1243dSDimitry Andric   case Instruction::Switch:
266bdd1243dSDimitry Andric   case Instruction::Br:
267bdd1243dSDimitry Andric     if (OperandNo >= 1)
2680b57cec5SDimitry Andric       return false;
2690b57cec5SDimitry Andric     break;
270*06c3fb27SDimitry Andric   case Instruction::Call:
271*06c3fb27SDimitry Andric   case Instruction::Invoke:
272*06c3fb27SDimitry Andric   case Instruction::CallBr: {
273*06c3fb27SDimitry Andric     const Function *Callee = cast<CallBase>(I)->getCalledFunction();
274*06c3fb27SDimitry Andric     // If it's an indirect call, give up.
275*06c3fb27SDimitry Andric     if (!Callee)
276*06c3fb27SDimitry Andric       return false;
277*06c3fb27SDimitry Andric     // If callee is not an intrinsic, operand 0 is the function to be called.
278*06c3fb27SDimitry Andric     // Since we cannot assume that the replacement is a function pointer,
279*06c3fb27SDimitry Andric     // we give up.
280*06c3fb27SDimitry Andric     if (!Callee->getIntrinsicID() && OperandNo == 0)
281*06c3fb27SDimitry Andric       return false;
282*06c3fb27SDimitry Andric     return !Callee->hasParamAttribute(OperandNo, Attribute::ImmArg);
283*06c3fb27SDimitry Andric   }
2840b57cec5SDimitry Andric   default:
2850b57cec5SDimitry Andric     break;
2860b57cec5SDimitry Andric   }
2870b57cec5SDimitry Andric   return true;
2880b57cec5SDimitry Andric }
2890b57cec5SDimitry Andric 
connectToSink(BasicBlock & BB,ArrayRef<Instruction * > Insts,Value * V)290*06c3fb27SDimitry Andric Instruction *RandomIRBuilder::connectToSink(BasicBlock &BB,
291*06c3fb27SDimitry Andric                                             ArrayRef<Instruction *> Insts,
292*06c3fb27SDimitry Andric                                             Value *V) {
293*06c3fb27SDimitry Andric   SmallVector<uint64_t, 8> SinkTys;
294*06c3fb27SDimitry Andric   for (uint64_t i = 0; i < EndOfValueSink; i++)
295*06c3fb27SDimitry Andric     SinkTys.push_back(i);
296*06c3fb27SDimitry Andric   std::shuffle(SinkTys.begin(), SinkTys.end(), Rand);
297*06c3fb27SDimitry Andric   auto findSinkAndConnect =
298*06c3fb27SDimitry Andric       [this, V](ArrayRef<Instruction *> Instructions) -> Instruction * {
2990b57cec5SDimitry Andric     auto RS = makeSampler<Use *>(Rand);
300*06c3fb27SDimitry Andric     for (auto &I : Instructions) {
3010b57cec5SDimitry Andric       for (Use &U : I->operands())
3020b57cec5SDimitry Andric         if (isCompatibleReplacement(I, U, V))
3030b57cec5SDimitry Andric           RS.sample(&U, 1);
3040b57cec5SDimitry Andric     }
305*06c3fb27SDimitry Andric     if (!RS.isEmpty()) {
306*06c3fb27SDimitry Andric       Use *Sink = RS.getSelection();
3070b57cec5SDimitry Andric       User *U = Sink->getUser();
3080b57cec5SDimitry Andric       unsigned OpNo = Sink->getOperandNo();
3090b57cec5SDimitry Andric       U->setOperand(OpNo, V);
310*06c3fb27SDimitry Andric       return cast<Instruction>(U);
3110b57cec5SDimitry Andric     }
312*06c3fb27SDimitry Andric     return nullptr;
313*06c3fb27SDimitry Andric   };
314*06c3fb27SDimitry Andric   Instruction *Sink = nullptr;
315*06c3fb27SDimitry Andric   for (uint64_t SinkTy : SinkTys) {
316*06c3fb27SDimitry Andric     switch (SinkTy) {
317*06c3fb27SDimitry Andric     case SinkToInstInCurBlock:
318*06c3fb27SDimitry Andric       Sink = findSinkAndConnect(Insts);
319*06c3fb27SDimitry Andric       if (Sink)
320*06c3fb27SDimitry Andric         return Sink;
321*06c3fb27SDimitry Andric       break;
322*06c3fb27SDimitry Andric     case PointersInDominator: {
323*06c3fb27SDimitry Andric       auto Dominators = getDominators(&BB);
324*06c3fb27SDimitry Andric       std::shuffle(Dominators.begin(), Dominators.end(), Rand);
325*06c3fb27SDimitry Andric       for (BasicBlock *Dom : Dominators) {
326*06c3fb27SDimitry Andric         for (Instruction &I : *Dom) {
327*06c3fb27SDimitry Andric           if (isa<PointerType>(I.getType()))
328*06c3fb27SDimitry Andric             return new StoreInst(V, &I, Insts.back());
329*06c3fb27SDimitry Andric         }
330*06c3fb27SDimitry Andric       }
331*06c3fb27SDimitry Andric       break;
332*06c3fb27SDimitry Andric     }
333*06c3fb27SDimitry Andric     case InstInDominatee: {
334*06c3fb27SDimitry Andric       auto Dominatees = getDominatees(&BB);
335*06c3fb27SDimitry Andric       std::shuffle(Dominatees.begin(), Dominatees.end(), Rand);
336*06c3fb27SDimitry Andric       for (BasicBlock *Dominee : Dominatees) {
337*06c3fb27SDimitry Andric         std::vector<Instruction *> Instructions;
338*06c3fb27SDimitry Andric         for (Instruction &I : *Dominee)
339*06c3fb27SDimitry Andric           Instructions.push_back(&I);
340*06c3fb27SDimitry Andric         Sink = findSinkAndConnect(Instructions);
341*06c3fb27SDimitry Andric         if (Sink) {
342*06c3fb27SDimitry Andric           return Sink;
343*06c3fb27SDimitry Andric         }
344*06c3fb27SDimitry Andric       }
345*06c3fb27SDimitry Andric       break;
346*06c3fb27SDimitry Andric     }
347*06c3fb27SDimitry Andric     case NewStore:
348*06c3fb27SDimitry Andric       /// TODO: allocate a new stack memory.
349*06c3fb27SDimitry Andric       return newSink(BB, Insts, V);
350*06c3fb27SDimitry Andric     case SinkToGlobalVariable: {
351*06c3fb27SDimitry Andric       Module *M = BB.getParent()->getParent();
352*06c3fb27SDimitry Andric       auto [GV, DidCreate] =
353*06c3fb27SDimitry Andric           findOrCreateGlobalVariable(M, {}, fuzzerop::onlyType(V->getType()));
354*06c3fb27SDimitry Andric       return new StoreInst(V, GV, Insts.back());
355*06c3fb27SDimitry Andric     }
356*06c3fb27SDimitry Andric     case EndOfValueSink:
357*06c3fb27SDimitry Andric     default:
358*06c3fb27SDimitry Andric       llvm_unreachable("EndOfValueSink executed");
359*06c3fb27SDimitry Andric     }
360*06c3fb27SDimitry Andric   }
361*06c3fb27SDimitry Andric   llvm_unreachable("Can't find a sink");
3620b57cec5SDimitry Andric }
3630b57cec5SDimitry Andric 
newSink(BasicBlock & BB,ArrayRef<Instruction * > Insts,Value * V)364*06c3fb27SDimitry Andric Instruction *RandomIRBuilder::newSink(BasicBlock &BB,
365*06c3fb27SDimitry Andric                                       ArrayRef<Instruction *> Insts, Value *V) {
366*06c3fb27SDimitry Andric   Value *Ptr = findPointer(BB, Insts);
3670b57cec5SDimitry Andric   if (!Ptr) {
368*06c3fb27SDimitry Andric     if (uniform(Rand, 0, 1)) {
369*06c3fb27SDimitry Andric       Type *Ty = V->getType();
370*06c3fb27SDimitry Andric       Ptr = createStackMemory(BB.getParent(), Ty, UndefValue::get(Ty));
371*06c3fb27SDimitry Andric     } else {
3720b57cec5SDimitry Andric       Ptr = UndefValue::get(PointerType::get(V->getType(), 0));
3730b57cec5SDimitry Andric     }
374*06c3fb27SDimitry Andric   }
3750b57cec5SDimitry Andric 
376*06c3fb27SDimitry Andric   return new StoreInst(V, Ptr, Insts.back());
3770b57cec5SDimitry Andric }
3780b57cec5SDimitry Andric 
findPointer(BasicBlock & BB,ArrayRef<Instruction * > Insts)3790b57cec5SDimitry Andric Value *RandomIRBuilder::findPointer(BasicBlock &BB,
380*06c3fb27SDimitry Andric                                     ArrayRef<Instruction *> Insts) {
381*06c3fb27SDimitry Andric   auto IsMatchingPtr = [](Instruction *Inst) {
3820b57cec5SDimitry Andric     // Invoke instructions sometimes produce valid pointers but currently
3830b57cec5SDimitry Andric     // we can't insert loads or stores from them
3840b57cec5SDimitry Andric     if (Inst->isTerminator())
3850b57cec5SDimitry Andric       return false;
3860b57cec5SDimitry Andric 
387*06c3fb27SDimitry Andric     return Inst->getType()->isPointerTy();
3880b57cec5SDimitry Andric   };
3890b57cec5SDimitry Andric   if (auto RS = makeSampler(Rand, make_filter_range(Insts, IsMatchingPtr)))
3900b57cec5SDimitry Andric     return RS.getSelection();
3910b57cec5SDimitry Andric   return nullptr;
3920b57cec5SDimitry Andric }
393bdd1243dSDimitry Andric 
randomType()394bdd1243dSDimitry Andric Type *RandomIRBuilder::randomType() {
395bdd1243dSDimitry Andric   uint64_t TyIdx = uniform<uint64_t>(Rand, 0, KnownTypes.size() - 1);
396bdd1243dSDimitry Andric   return KnownTypes[TyIdx];
397bdd1243dSDimitry Andric }
398*06c3fb27SDimitry Andric 
createFunctionDeclaration(Module & M,uint64_t ArgNum)399*06c3fb27SDimitry Andric Function *RandomIRBuilder::createFunctionDeclaration(Module &M,
400*06c3fb27SDimitry Andric                                                      uint64_t ArgNum) {
401*06c3fb27SDimitry Andric   Type *RetType = randomType();
402*06c3fb27SDimitry Andric 
403*06c3fb27SDimitry Andric   SmallVector<Type *, 2> Args;
404*06c3fb27SDimitry Andric   for (uint64_t i = 0; i < ArgNum; i++) {
405*06c3fb27SDimitry Andric     Args.push_back(randomType());
406*06c3fb27SDimitry Andric   }
407*06c3fb27SDimitry Andric 
408*06c3fb27SDimitry Andric   Function *F = Function::Create(FunctionType::get(RetType, Args,
409*06c3fb27SDimitry Andric                                                    /*isVarArg=*/false),
410*06c3fb27SDimitry Andric                                  GlobalValue::ExternalLinkage, "f", &M);
411*06c3fb27SDimitry Andric   return F;
412*06c3fb27SDimitry Andric }
createFunctionDeclaration(Module & M)413*06c3fb27SDimitry Andric Function *RandomIRBuilder::createFunctionDeclaration(Module &M) {
414*06c3fb27SDimitry Andric   return createFunctionDeclaration(
415*06c3fb27SDimitry Andric       M, uniform<uint64_t>(Rand, MinArgNum, MaxArgNum));
416*06c3fb27SDimitry Andric }
417*06c3fb27SDimitry Andric 
createFunctionDefinition(Module & M,uint64_t ArgNum)418*06c3fb27SDimitry Andric Function *RandomIRBuilder::createFunctionDefinition(Module &M,
419*06c3fb27SDimitry Andric                                                     uint64_t ArgNum) {
420*06c3fb27SDimitry Andric   Function *F = this->createFunctionDeclaration(M, ArgNum);
421*06c3fb27SDimitry Andric 
422*06c3fb27SDimitry Andric   // TODO: Some arguments and a return value would probably be more
423*06c3fb27SDimitry Andric   // interesting.
424*06c3fb27SDimitry Andric   LLVMContext &Context = M.getContext();
425*06c3fb27SDimitry Andric   DataLayout DL(&M);
426*06c3fb27SDimitry Andric   BasicBlock *BB = BasicBlock::Create(Context, "BB", F);
427*06c3fb27SDimitry Andric   Type *RetTy = F->getReturnType();
428*06c3fb27SDimitry Andric   if (RetTy != Type::getVoidTy(Context)) {
429*06c3fb27SDimitry Andric     Instruction *RetAlloca =
430*06c3fb27SDimitry Andric         new AllocaInst(RetTy, DL.getAllocaAddrSpace(), "RP", BB);
431*06c3fb27SDimitry Andric     Instruction *RetLoad = new LoadInst(RetTy, RetAlloca, "", BB);
432*06c3fb27SDimitry Andric     ReturnInst::Create(Context, RetLoad, BB);
433*06c3fb27SDimitry Andric   } else {
434*06c3fb27SDimitry Andric     ReturnInst::Create(Context, BB);
435*06c3fb27SDimitry Andric   }
436*06c3fb27SDimitry Andric 
437*06c3fb27SDimitry Andric   return F;
438*06c3fb27SDimitry Andric }
createFunctionDefinition(Module & M)439*06c3fb27SDimitry Andric Function *RandomIRBuilder::createFunctionDefinition(Module &M) {
440*06c3fb27SDimitry Andric   return createFunctionDefinition(
441*06c3fb27SDimitry Andric       M, uniform<uint64_t>(Rand, MinArgNum, MaxArgNum));
442*06c3fb27SDimitry Andric }
443