LLVM: lib/FuzzMutate/RandomIRBuilder.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
21
22using namespace llvm;
23using namespace fuzzerop;
24
25
26
28 std::vector<BasicBlock *> ret;
31
32
34 return ret;
36 while (Node && Node->getBlock()) {
37 ret.push_back(Node->getBlock());
38
40 }
41 return ret;
42}
43
44
45
48 std::vector<BasicBlock *> ret;
50
51
52 if (!Parent)
53 return ret;
55 ret.push_back(Child->getBlock());
57 while (Idx < ret.size()) {
61 ret.push_back(Child->getBlock());
62 }
63 return ret;
64}
65
68
69 BasicBlock *EntryBB = &F->getEntryBlock();
75 return Alloca;
76}
77
78std::pair<GlobalVariable *, bool>
81 auto MatchesPred = [&Srcs, &Pred](GlobalVariable *GV) {
82
83
85 };
86 bool DidCreate = false;
90 }
92 RS.sample(nullptr, 1);
94 if (!GV) {
95 DidCreate = true;
97 auto TRS = makeSampler<Constant *>(Rand);
101 GV = new GlobalVariable(*M, Ty, false, LinkageTypes::ExternalLinkage, Init,
102 "G", nullptr,
104 M->getDataLayout().getDefaultGlobalsAddressSpace());
105 }
106 return {GV, DidCreate};
107}
108
112}
113
118 bool allowConstant) {
119 auto MatchesPred = [&Srcs, &Pred](Value *V) { return Pred.matches(Srcs, V); };
123 std::shuffle(SrcTys.begin(), SrcTys.end(), Rand);
124 for (uint64_t SrcTy : SrcTys) {
125 switch (SrcTy) {
128 if (!RS.isEmpty()) {
129 return RS.getSelection();
130 }
131 break;
132 }
136 for (uint64_t i = 0; i < F->arg_size(); i++) {
137 Args.push_back(F->getArg(i));
138 }
140 if (!RS.isEmpty()) {
141 return RS.getSelection();
142 }
143 break;
144 }
147 std::shuffle(Dominators.begin(), Dominators.end(), Rand);
151 Instructions.push_back(&I);
152 }
153 auto RS =
155
156 if (!RS.isEmpty()) {
157 return RS.getSelection();
158 }
159 }
160 break;
161 }
165 Type *Ty = GV->getValueType();
169 } else {
170 LoadGV = new LoadInst(Ty, GV, "LGV", &BB);
171 }
172
173
174 if (DidCreate) {
175 if (Pred.matches(Srcs, LoadGV)) {
176 return LoadGV;
177 }
179
180 if (GV->use_empty()) {
181 GV->eraseFromParent();
182 }
183 }
184 break;
185 }
187 return newSource(BB, Insts, Srcs, Pred, allowConstant);
188 }
189 default:
192 }
193 }
194 }
196}
197
200 bool allowConstant) {
201
202 auto RS = makeSampler<Value *>(Rand);
204
205
207 if (Ptr) {
208
210 if (auto *I = dyn_cast(Ptr)) {
211 IP = ++I->getIterator();
212 assert(IP != BB.end() && "guaranteed by the findPointer");
213 }
214
215 Type *AccessTy = RS.getSelection()->getType();
216 auto *NewLoad = new LoadInst(AccessTy, Ptr, "L", IP);
217
218
219 if (Pred.matches(Srcs, NewLoad))
220 RS.sample(NewLoad, RS.totalWeight());
221 else
222 NewLoad->eraseFromParent();
223 }
224
225 Value *newSrc = RS.getSelection();
226
227
228
229 if (!allowConstant && isa(newSrc)) {
234 newSrc = new LoadInst(Ty, Alloca, "L",
236 } else {
237 newSrc = new LoadInst(Ty, Alloca, "L", &BB);
238 }
239 }
240 return newSrc;
241}
242
244 const Value *Replacement) {
245 unsigned int OperandNo = Operand.getOperandNo();
247 return false;
248 switch (I->getOpcode()) {
249 case Instruction::GetElementPtr:
250 case Instruction::ExtractElement:
251 case Instruction::ExtractValue:
252
253
254 if (OperandNo >= 1)
255 return false;
256 break;
257 case Instruction::InsertValue:
258 case Instruction::InsertElement:
259 case Instruction::ShuffleVector:
260 if (OperandNo >= 2)
261 return false;
262 break;
263
264
265
266 case Instruction::Switch:
267 case Instruction::Br:
268 if (OperandNo >= 1)
269 return false;
270 break;
271 case Instruction::Call:
272 case Instruction::Invoke:
273 case Instruction::CallBr: {
274 const Function *Callee = cast(I)->getCalledFunction();
275
276 if (!Callee)
277 return false;
278
279
280
281 if (!Callee->getIntrinsicID() && OperandNo == 0)
282 return false;
283 return !Callee->hasParamAttribute(OperandNo, Attribute::ImmArg);
284 }
285 default:
286 break;
287 }
288 return true;
289}
290
297 std::shuffle(SinkTys.begin(), SinkTys.end(), Rand);
298 auto findSinkAndConnect =
300 auto RS = makeSampler<Use *>(Rand);
301 for (auto &I : Instructions) {
302 for (Use &U : I->operands())
304 RS.sample(&U, 1);
305 }
306 if (!RS.isEmpty()) {
307 Use *Sink = RS.getSelection();
308 User *U = Sink->getUser();
309 unsigned OpNo = Sink->getOperandNo();
310 U->setOperand(OpNo, V);
311 return cast(U);
312 }
313 return nullptr;
314 };
316 for (uint64_t SinkTy : SinkTys) {
317 switch (SinkTy) {
319 Sink = findSinkAndConnect(Insts);
320 if (Sink)
321 return Sink;
322 break;
325 std::shuffle(Dominators.begin(), Dominators.end(), Rand);
328 if (isa(I.getType()))
329 return new StoreInst(V, &I, Insts.back()->getIterator());
330 }
331 }
332 break;
333 }
336 std::shuffle(Dominatees.begin(), Dominatees.end(), Rand);
337 for (BasicBlock *Dominee : Dominatees) {
338 std::vector<Instruction *> Instructions;
340 Instructions.push_back(&I);
341 Sink = findSinkAndConnect(Instructions);
342 if (Sink) {
343 return Sink;
344 }
345 }
346 break;
347 }
349
350 return newSink(BB, Insts, V);
353 auto [GV, DidCreate] =
355 return new StoreInst(V, GV, Insts.back()->getIterator());
356 }
358 default:
360 }
361 }
363}
364
368 if () {
370 Type *Ty = V->getType();
372 } else {
374 }
375 }
376
378}
379
382 auto IsMatchingPtr = [](Instruction *Inst) {
383
384
385 if (Inst->isTerminator())
386 return false;
387
389 };
391 return RS.getSelection();
392 return nullptr;
393}
394
398}
399
403
405 for (uint64_t i = 0; i < ArgNum; i++) {
407 }
408
410 false),
412 return F;
413}
417}
418
422
423
424
434 } else {
436 }
437
438 return F;
439}
443}
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
This file contains the declarations for the subclasses of Constant, which represent the different fla...
Returns the sub type a function will return at a given Idx Should correspond to the result type of an ExtractValue instruction executed with just that one unsigned Idx
Module.h This file contains the declarations for the Module class.
static bool isCompatibleReplacement(const Instruction *I, const Use &Operand, const Value *Replacement)
static std::vector< BasicBlock * > getDominators(BasicBlock *BB)
Return a vector of Blocks that dominates this block, excluding current block.
static std::vector< BasicBlock * > getDominatees(BasicBlock *BB)
Return a vector of Blocks that is dominated by this block, excluding current block.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
an instruction to allocate memory on the stack
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
const T & back() const
back - Get the last element.
LLVM Basic Block Representation.
const_iterator getFirstInsertionPt() const
Returns an iterator to the first instruction in this block that is suitable for inserting a non-PHI i...
static BasicBlock * Create(LLVMContext &Context, const Twine &Name="", Function *Parent=nullptr, BasicBlock *InsertBefore=nullptr)
Creates a new BasicBlock.
const Function * getParent() const
Return the enclosing method, or null if none.
const Instruction * getTerminator() const LLVM_READONLY
Returns the terminator instruction if the block is well formed or null if the block is not well forme...
This is an important base class in LLVM.
A parsed version of the target data layout string in and methods for querying it.
iterator_range< iterator > children()
DomTreeNodeBase< NodeT > * getNode(const NodeT *BB) const
getNode - return the (Post)DominatorTree node for the specified basic block.
Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree.
static FunctionType * get(Type *Result, ArrayRef< Type * > Params, bool isVarArg)
This static method is the primary way of constructing a FunctionType.
static Function * Create(FunctionType *Ty, LinkageTypes Linkage, unsigned AddrSpace, const Twine &N="", Module *M=nullptr)
Module * getParent()
Get the module that this global value is contained inside of...
LinkageTypes
An enumeration for the kinds of linkage for global values.
@ ExternalLinkage
Externally visible function.
InstListType::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
This is an important class for using LLVM in a threaded context.
An instruction for reading from memory.
A Module instance is used to store all the information related to an LLVM module.
static PointerType * get(Type *ElementType, unsigned AddressSpace)
This constructs a pointer to an object of the specified type in a numbered address space.
static PoisonValue * get(Type *T)
Static factory methods - Return an 'poison' object of the specified type.
static ReturnInst * Create(LLVMContext &C, Value *retVal=nullptr, InsertPosition InsertBefore=nullptr)
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
An instruction for storing to memory.
The instances of the Type class are immutable: once they are created, they are never changed.
bool isPointerTy() const
True if this is an instance of PointerType.
static Type * getVoidTy(LLVMContext &C)
A Use represents the edge between a Value definition and its users.
unsigned getOperandNo() const
Return the operand # of this use in its User.
LLVM Value Representation.
Type * getType() const
All values are typed, get the type of this value.
A matcher/generator for finding suitable values for the next source in an operation's partially compl...
bool matches(ArrayRef< Value * > Cur, const Value *New)
Returns true if New is compatible for the argument after Cur.
std::vector< Constant * > generate(ArrayRef< Value * > Cur, ArrayRef< Type * > BaseTypes)
Generates a list of potential values for the argument after Cur.
self_iterator getIterator()
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
static SourcePred onlyType(Type *Only)
static SourcePred anyType()
This is an optimization pass for GlobalISel generic memory operations.
ReservoirSampler< ElT, GenT > makeSampler(GenT &RandGen, RangeT &&Items)
iterator_range< filter_iterator< detail::IterOfRange< RangeT >, PredicateT > > make_filter_range(RangeT &&Range, PredicateT Pred)
Convenience function that takes a range of elements and a predicate, and return a new filter_iterator...
T uniform(GenT &Gen, T Min, T Max)
Return a uniformly distributed random value between Min and Max.
Function * createFunctionDeclaration(Module &M, uint64_t ArgNum)
SmallVector< Type *, 16 > KnownTypes
std::pair< GlobalVariable *, bool > findOrCreateGlobalVariable(Module *M, ArrayRef< Value * > Srcs, fuzzerop::SourcePred Pred)
Find or create a global variable.
Value * findOrCreateSource(BasicBlock &BB, ArrayRef< Instruction * > Insts)
Find a "source" for some operation, which will be used in one of the operation's operands.
AllocaInst * createStackMemory(Function *F, Type *Ty, Value *Init=nullptr)
Create a stack memory at the head of the function, store Init to the memory if provided.
Instruction * newSink(BasicBlock &BB, ArrayRef< Instruction * > Insts, Value *V)
Create a user for V in BB.
Function * createFunctionDefinition(Module &M, uint64_t ArgNum)
Value * newSource(BasicBlock &BB, ArrayRef< Instruction * > Insts, ArrayRef< Value * > Srcs, fuzzerop::SourcePred Pred, bool allowConstant=true)
Create some Value suitable as a source for some operation.
Instruction * connectToSink(BasicBlock &BB, ArrayRef< Instruction * > Insts, Value *V)
Find a viable user for V in Insts, which should all be contained in BB.
@ SinkToInstInCurBlock
TODO: Also consider pointers in function argument.
Value * findPointer(BasicBlock &BB, ArrayRef< Instruction * > Insts)
Type * randomType()
Return a uniformly choosen type from AllowedTypes.