annotate lib/FuzzMutate/RandomIRBuilder.cpp @ 134:3a76565eade5 LLVM5.0.1

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