IRMutator.h revision 353358
1326938Sdim//===-- IRMutator.h - Mutation engine for fuzzing IR ------------*- C++ -*-===// 2326938Sdim// 3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4353358Sdim// See https://llvm.org/LICENSE.txt for license information. 5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6326938Sdim// 7326938Sdim//===----------------------------------------------------------------------===// 8326938Sdim// 9326938Sdim// Provides the IRMutator class, which drives mutations on IR based on a 10326938Sdim// configurable set of strategies. Some common strategies are also included 11326938Sdim// here. 12326938Sdim// 13326938Sdim//===----------------------------------------------------------------------===// 14326938Sdim 15326938Sdim#ifndef LLVM_FUZZMUTATE_IRMUTATOR_H 16326938Sdim#define LLVM_FUZZMUTATE_IRMUTATOR_H 17326938Sdim 18327134Sdim#include "llvm/ADT/Optional.h" 19326938Sdim#include "llvm/FuzzMutate/OpDescriptor.h" 20326938Sdim#include "llvm/Support/ErrorHandling.h" 21326938Sdim 22326938Sdimnamespace llvm { 23326938Sdimclass BasicBlock; 24326938Sdimclass Function; 25326938Sdimclass Instruction; 26326938Sdimclass Module; 27326938Sdim 28326938Sdimstruct RandomIRBuilder; 29326938Sdim 30326938Sdim/// Base class for describing how to mutate a module. mutation functions for 31326938Sdim/// each IR unit forward to the contained unit. 32326938Sdimclass IRMutationStrategy { 33326938Sdimpublic: 34326938Sdim virtual ~IRMutationStrategy() = default; 35326938Sdim 36326938Sdim /// Provide a weight to bias towards choosing this strategy for a mutation. 37326938Sdim /// 38326938Sdim /// The value of the weight is arbitrary, but a good default is "the number of 39326938Sdim /// distinct ways in which this strategy can mutate a unit". This can also be 40326938Sdim /// used to prefer strategies that shrink the overall size of the result when 41326938Sdim /// we start getting close to \c MaxSize. 42326938Sdim virtual uint64_t getWeight(size_t CurrentSize, size_t MaxSize, 43326938Sdim uint64_t CurrentWeight) = 0; 44326938Sdim 45326938Sdim /// @{ 46326938Sdim /// Mutators for each IR unit. By default these forward to a contained 47326938Sdim /// instance of the next smaller unit. 48326938Sdim virtual void mutate(Module &M, RandomIRBuilder &IB); 49326938Sdim virtual void mutate(Function &F, RandomIRBuilder &IB); 50326938Sdim virtual void mutate(BasicBlock &BB, RandomIRBuilder &IB); 51326938Sdim virtual void mutate(Instruction &I, RandomIRBuilder &IB) { 52326938Sdim llvm_unreachable("Strategy does not implement any mutators"); 53326938Sdim } 54326938Sdim /// @} 55326938Sdim}; 56326938Sdim 57326938Sdimusing TypeGetter = std::function<Type *(LLVMContext &)>; 58326938Sdim 59326938Sdim/// Entry point for configuring and running IR mutations. 60326938Sdimclass IRMutator { 61326938Sdim std::vector<TypeGetter> AllowedTypes; 62326938Sdim std::vector<std::unique_ptr<IRMutationStrategy>> Strategies; 63326938Sdim 64326938Sdimpublic: 65326938Sdim IRMutator(std::vector<TypeGetter> &&AllowedTypes, 66326938Sdim std::vector<std::unique_ptr<IRMutationStrategy>> &&Strategies) 67326938Sdim : AllowedTypes(std::move(AllowedTypes)), 68326938Sdim Strategies(std::move(Strategies)) {} 69326938Sdim 70326938Sdim void mutateModule(Module &M, int Seed, size_t CurSize, size_t MaxSize); 71326938Sdim}; 72326938Sdim 73326938Sdim/// Strategy that injects operations into the function. 74326938Sdimclass InjectorIRStrategy : public IRMutationStrategy { 75326938Sdim std::vector<fuzzerop::OpDescriptor> Operations; 76326938Sdim 77327134Sdim Optional<fuzzerop::OpDescriptor> chooseOperation(Value *Src, 78327134Sdim RandomIRBuilder &IB); 79326938Sdim 80326938Sdimpublic: 81326938Sdim InjectorIRStrategy(std::vector<fuzzerop::OpDescriptor> &&Operations) 82326938Sdim : Operations(std::move(Operations)) {} 83326938Sdim static std::vector<fuzzerop::OpDescriptor> getDefaultOps(); 84326938Sdim 85326938Sdim uint64_t getWeight(size_t CurrentSize, size_t MaxSize, 86326938Sdim uint64_t CurrentWeight) override { 87326938Sdim return Operations.size(); 88326938Sdim } 89326938Sdim 90326938Sdim using IRMutationStrategy::mutate; 91326938Sdim void mutate(Function &F, RandomIRBuilder &IB) override; 92326938Sdim void mutate(BasicBlock &BB, RandomIRBuilder &IB) override; 93326938Sdim}; 94326938Sdim 95326938Sdimclass InstDeleterIRStrategy : public IRMutationStrategy { 96326938Sdimpublic: 97326938Sdim uint64_t getWeight(size_t CurrentSize, size_t MaxSize, 98326938Sdim uint64_t CurrentWeight) override; 99326938Sdim 100326938Sdim using IRMutationStrategy::mutate; 101326938Sdim void mutate(Function &F, RandomIRBuilder &IB) override; 102326938Sdim void mutate(Instruction &Inst, RandomIRBuilder &IB) override; 103326938Sdim}; 104326938Sdim 105326938Sdim} // end llvm namespace 106326938Sdim 107326938Sdim#endif // LLVM_FUZZMUTATE_IRMUTATOR_H 108