Line data Source code
1 : //===-- IRMutator.h - Mutation engine for fuzzing IR ------------*- C++ -*-===//
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 : // Provides the IRMutator class, which drives mutations on IR based on a
11 : // configurable set of strategies. Some common strategies are also included
12 : // here.
13 : //
14 : //===----------------------------------------------------------------------===//
15 :
16 : #ifndef LLVM_FUZZMUTATE_IRMUTATOR_H
17 : #define LLVM_FUZZMUTATE_IRMUTATOR_H
18 :
19 : #include "llvm/ADT/Optional.h"
20 : #include "llvm/FuzzMutate/OpDescriptor.h"
21 : #include "llvm/Support/ErrorHandling.h"
22 :
23 : namespace llvm {
24 : class BasicBlock;
25 : class Function;
26 : class Instruction;
27 : class Module;
28 :
29 : struct RandomIRBuilder;
30 :
31 : /// Base class for describing how to mutate a module. mutation functions for
32 : /// each IR unit forward to the contained unit.
33 : class IRMutationStrategy {
34 : public:
35 0 : virtual ~IRMutationStrategy() = default;
36 :
37 : /// Provide a weight to bias towards choosing this strategy for a mutation.
38 : ///
39 : /// The value of the weight is arbitrary, but a good default is "the number of
40 : /// distinct ways in which this strategy can mutate a unit". This can also be
41 : /// used to prefer strategies that shrink the overall size of the result when
42 : /// we start getting close to \c MaxSize.
43 : virtual uint64_t getWeight(size_t CurrentSize, size_t MaxSize,
44 : uint64_t CurrentWeight) = 0;
45 :
46 : /// @{
47 : /// Mutators for each IR unit. By default these forward to a contained
48 : /// instance of the next smaller unit.
49 : virtual void mutate(Module &M, RandomIRBuilder &IB);
50 : virtual void mutate(Function &F, RandomIRBuilder &IB);
51 : virtual void mutate(BasicBlock &BB, RandomIRBuilder &IB);
52 0 : virtual void mutate(Instruction &I, RandomIRBuilder &IB) {
53 0 : llvm_unreachable("Strategy does not implement any mutators");
54 : }
55 : /// @}
56 : };
57 :
58 : using TypeGetter = std::function<Type *(LLVMContext &)>;
59 :
60 : /// Entry point for configuring and running IR mutations.
61 0 : class IRMutator {
62 : std::vector<TypeGetter> AllowedTypes;
63 : std::vector<std::unique_ptr<IRMutationStrategy>> Strategies;
64 :
65 : public:
66 : IRMutator(std::vector<TypeGetter> &&AllowedTypes,
67 : std::vector<std::unique_ptr<IRMutationStrategy>> &&Strategies)
68 10 : : AllowedTypes(std::move(AllowedTypes)),
69 : Strategies(std::move(Strategies)) {}
70 :
71 : void mutateModule(Module &M, int Seed, size_t CurSize, size_t MaxSize);
72 : };
73 :
74 : /// Strategy that injects operations into the function.
75 : class InjectorIRStrategy : public IRMutationStrategy {
76 : std::vector<fuzzerop::OpDescriptor> Operations;
77 :
78 : Optional<fuzzerop::OpDescriptor> chooseOperation(Value *Src,
79 : RandomIRBuilder &IB);
80 :
81 : public:
82 : InjectorIRStrategy(std::vector<fuzzerop::OpDescriptor> &&Operations)
83 8 : : Operations(std::move(Operations)) {}
84 : static std::vector<fuzzerop::OpDescriptor> getDefaultOps();
85 :
86 1 : uint64_t getWeight(size_t CurrentSize, size_t MaxSize,
87 : uint64_t CurrentWeight) override {
88 2 : return Operations.size();
89 : }
90 :
91 : using IRMutationStrategy::mutate;
92 : void mutate(Function &F, RandomIRBuilder &IB) override;
93 : void mutate(BasicBlock &BB, RandomIRBuilder &IB) override;
94 : };
95 :
96 9 : class InstDeleterIRStrategy : public IRMutationStrategy {
97 : public:
98 : uint64_t getWeight(size_t CurrentSize, size_t MaxSize,
99 : uint64_t CurrentWeight) override;
100 :
101 : using IRMutationStrategy::mutate;
102 : void mutate(Function &F, RandomIRBuilder &IB) override;
103 : void mutate(Instruction &Inst, RandomIRBuilder &IB) override;
104 : };
105 :
106 : } // end llvm namespace
107 :
108 : #endif // LLVM_FUZZMUTATE_IRMUTATOR_H
|