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