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