1 //===- RandomIRBuilder.h - Utils for randomly mutation IR -------*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // Provides the Mutator class, which is used to mutate IR for fuzzing. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #ifndef LLVM_FUZZMUTATE_RANDOMIRBUILDER_H 14 #define LLVM_FUZZMUTATE_RANDOMIRBUILDER_H 15 16 #include "llvm/ADT/ArrayRef.h" 17 #include "llvm/ADT/SmallVector.h" 18 #include "llvm/Support/Compiler.h" 19 #include <random> 20 21 namespace llvm { 22 class AllocaInst; 23 class BasicBlock; 24 class Function; 25 class GlobalVariable; 26 class Instruction; 27 class LLVMContext; 28 class Module; 29 class Type; 30 class Value; 31 32 namespace fuzzerop { 33 class SourcePred; 34 } 35 36 using RandomEngine = std::mt19937; 37 38 struct RandomIRBuilder { 39 RandomEngine Rand; 40 SmallVector<Type *, 16> KnownTypes; 41 42 uint64_t MinArgNum = 0; 43 uint64_t MaxArgNum = 5; 44 uint64_t MinFunctionNum = 1; 45 RandomIRBuilderRandomIRBuilder46 RandomIRBuilder(int Seed, ArrayRef<Type *> AllowedTypes) 47 : Rand(Seed), KnownTypes(AllowedTypes) {} 48 49 // TODO: Try to make this a bit less of a random mishmash of functions. 50 51 /// Create a stack memory at the head of the function, store \c Init to the 52 /// memory if provided. 53 LLVM_ABI AllocaInst *createStackMemory(Function *F, Type *Ty, 54 Value *Init = nullptr); 55 /// Find or create a global variable. It will be initialized by random 56 /// constants that satisfies \c Pred. It will also report whether this global 57 /// variable found or created. 58 LLVM_ABI std::pair<GlobalVariable *, bool> 59 findOrCreateGlobalVariable(Module *M, ArrayRef<Value *> Srcs, 60 fuzzerop::SourcePred Pred); 61 enum SourceType { 62 SrcFromInstInCurBlock, 63 FunctionArgument, 64 InstInDominator, 65 SrcFromGlobalVariable, 66 NewConstOrStack, 67 EndOfValueSource, 68 }; 69 /// Find a "source" for some operation, which will be used in one of the 70 /// operation's operands. This either selects an instruction in \c Insts or 71 /// returns some new arbitrary Value. 72 LLVM_ABI Value *findOrCreateSource(BasicBlock &BB, 73 ArrayRef<Instruction *> Insts); 74 /// Find a "source" for some operation, which will be used in one of the 75 /// operation's operands. This either selects an instruction in \c Insts that 76 /// matches \c Pred, or returns some new Value that matches \c Pred. The 77 /// values in \c Srcs should be source operands that have already been 78 /// selected. 79 LLVM_ABI Value *findOrCreateSource(BasicBlock &BB, 80 ArrayRef<Instruction *> Insts, 81 ArrayRef<Value *> Srcs, 82 fuzzerop::SourcePred Pred, 83 bool allowConstant = true); 84 /// Create some Value suitable as a source for some operation. 85 LLVM_ABI Value *newSource(BasicBlock &BB, ArrayRef<Instruction *> Insts, 86 ArrayRef<Value *> Srcs, fuzzerop::SourcePred Pred, 87 bool allowConstant = true); 88 89 enum SinkType { 90 /// TODO: Also consider pointers in function argument. 91 SinkToInstInCurBlock, 92 PointersInDominator, 93 InstInDominatee, 94 NewStore, 95 SinkToGlobalVariable, 96 EndOfValueSink, 97 }; 98 /// Find a viable user for \c V in \c Insts, which should all be contained in 99 /// \c BB. This may also create some new instruction in \c BB and use that. 100 LLVM_ABI Instruction *connectToSink(BasicBlock &BB, 101 ArrayRef<Instruction *> Insts, Value *V); 102 /// Create a user for \c V in \c BB. 103 LLVM_ABI Instruction *newSink(BasicBlock &BB, ArrayRef<Instruction *> Insts, 104 Value *V); 105 LLVM_ABI Value *findPointer(BasicBlock &BB, ArrayRef<Instruction *> Insts); 106 /// Return a uniformly choosen type from \c AllowedTypes 107 LLVM_ABI Type *randomType(); 108 LLVM_ABI Function *createFunctionDeclaration(Module &M, uint64_t ArgNum); 109 LLVM_ABI Function *createFunctionDeclaration(Module &M); 110 LLVM_ABI Function *createFunctionDefinition(Module &M, uint64_t ArgNum); 111 LLVM_ABI Function *createFunctionDefinition(Module &M); 112 }; 113 114 } // namespace llvm 115 116 #endif // LLVM_FUZZMUTATE_RANDOMIRBUILDER_H 117