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