diff options
author | Devtools Arcadia <arcadia-devtools@yandex-team.ru> | 2022-02-07 18:08:42 +0300 |
---|---|---|
committer | Devtools Arcadia <arcadia-devtools@mous.vla.yp-c.yandex.net> | 2022-02-07 18:08:42 +0300 |
commit | 1110808a9d39d4b808aef724c861a2e1a38d2a69 (patch) | |
tree | e26c9fed0de5d9873cce7e00bc214573dc2195b7 /contrib/libs/llvm12/include/llvm/FuzzMutate | |
download | ydb-1110808a9d39d4b808aef724c861a2e1a38d2a69.tar.gz |
intermediate changes
ref:cde9a383711a11544ce7e107a78147fb96cc4029
Diffstat (limited to 'contrib/libs/llvm12/include/llvm/FuzzMutate')
6 files changed, 695 insertions, 0 deletions
diff --git a/contrib/libs/llvm12/include/llvm/FuzzMutate/FuzzerCLI.h b/contrib/libs/llvm12/include/llvm/FuzzMutate/FuzzerCLI.h new file mode 100644 index 0000000000..8b2dd1b41a --- /dev/null +++ b/contrib/libs/llvm12/include/llvm/FuzzMutate/FuzzerCLI.h @@ -0,0 +1,90 @@ +#pragma once + +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-parameter" +#endif + +//===-- FuzzerCLI.h - Common logic for CLIs of fuzzers ----------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// Common logic needed to implement LLVM's fuzz targets' CLIs - including LLVM +// concepts like cl::opt and libFuzzer concepts like -ignore_remaining_args=1. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_FUZZMUTATE_FUZZER_CLI_H +#define LLVM_FUZZMUTATE_FUZZER_CLI_H + +#include "llvm/IR/LLVMContext.h" +#include "llvm/Support/DataTypes.h" + +namespace llvm { + +class StringRef; + +/// Parse cl::opts from a fuzz target commandline. +/// +/// This handles all arguments after -ignore_remaining_args=1 as cl::opts. +void parseFuzzerCLOpts(int ArgC, char *ArgV[]); + +/// Handle backend options that are encoded in the executable name. +/// +/// Parses some common backend options out of a specially crafted executable +/// name (argv[0]). For example, a name like llvm-foo-fuzzer--aarch64-gisel +/// might set up an AArch64 triple and the Global ISel selector. This should be +/// called *before* parseFuzzerCLOpts if calling both. +/// +/// This is meant to be used for environments like OSS-Fuzz that aren't capable +/// of passing in command line arguments in the normal way. +void handleExecNameEncodedBEOpts(StringRef ExecName); + +/// Handle optimizer options which are encoded in the executable name. +/// Same semantics as in 'handleExecNameEncodedBEOpts'. +void handleExecNameEncodedOptimizerOpts(StringRef ExecName); + +using FuzzerTestFun = int (*)(const uint8_t *Data, size_t Size); +using FuzzerInitFun = int (*)(int *argc, char ***argv); + +/// Runs a fuzz target on the inputs specified on the command line. +/// +/// Useful for testing fuzz targets without linking to libFuzzer. Finds inputs +/// in the argument list in a libFuzzer compatible way. +int runFuzzerOnInputs(int ArgC, char *ArgV[], FuzzerTestFun TestOne, + FuzzerInitFun Init = [](int *, char ***) { return 0; }); + +/// Fuzzer friendly interface for the llvm bitcode parser. +/// +/// \param Data Bitcode we are going to parse +/// \param Size Size of the 'Data' in bytes +/// \return New module or nullptr in case of error +std::unique_ptr<Module> parseModule(const uint8_t *Data, size_t Size, + LLVMContext &Context); + +/// Fuzzer friendly interface for the llvm bitcode printer. +/// +/// \param M Module to print +/// \param Dest Location to store serialized module +/// \param MaxSize Size of the destination buffer +/// \return Number of bytes that were written. When module size exceeds MaxSize +/// returns 0 and leaves Dest unchanged. +size_t writeModule(const Module &M, uint8_t *Dest, size_t MaxSize); + +/// Try to parse module and verify it. May output verification errors to the +/// errs(). +/// \return New module or nullptr in case of error. +std::unique_ptr<Module> parseAndVerify(const uint8_t *Data, size_t Size, + LLVMContext &Context); + +} // end llvm namespace + +#endif // LLVM_FUZZMUTATE_FUZZER_CLI_H + +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif diff --git a/contrib/libs/llvm12/include/llvm/FuzzMutate/IRMutator.h b/contrib/libs/llvm12/include/llvm/FuzzMutate/IRMutator.h new file mode 100644 index 0000000000..48bf5f18a5 --- /dev/null +++ b/contrib/libs/llvm12/include/llvm/FuzzMutate/IRMutator.h @@ -0,0 +1,129 @@ +#pragma once + +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-parameter" +#endif + +//===-- IRMutator.h - Mutation engine for fuzzing IR ------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// Provides the IRMutator class, which drives mutations on IR based on a +// configurable set of strategies. Some common strategies are also included +// here. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_FUZZMUTATE_IRMUTATOR_H +#define LLVM_FUZZMUTATE_IRMUTATOR_H + +#include "llvm/ADT/Optional.h" +#include "llvm/FuzzMutate/OpDescriptor.h" +#include "llvm/Support/ErrorHandling.h" + +namespace llvm { +class BasicBlock; +class Function; +class Instruction; +class Module; + +struct RandomIRBuilder; + +/// Base class for describing how to mutate a module. mutation functions for +/// each IR unit forward to the contained unit. +class IRMutationStrategy { +public: + virtual ~IRMutationStrategy() = default; + + /// Provide a weight to bias towards choosing this strategy for a mutation. + /// + /// The value of the weight is arbitrary, but a good default is "the number of + /// distinct ways in which this strategy can mutate a unit". This can also be + /// used to prefer strategies that shrink the overall size of the result when + /// we start getting close to \c MaxSize. + virtual uint64_t getWeight(size_t CurrentSize, size_t MaxSize, + uint64_t CurrentWeight) = 0; + + /// @{ + /// Mutators for each IR unit. By default these forward to a contained + /// instance of the next smaller unit. + virtual void mutate(Module &M, RandomIRBuilder &IB); + virtual void mutate(Function &F, RandomIRBuilder &IB); + virtual void mutate(BasicBlock &BB, RandomIRBuilder &IB); + virtual void mutate(Instruction &I, RandomIRBuilder &IB) { + llvm_unreachable("Strategy does not implement any mutators"); + } + /// @} +}; + +using TypeGetter = std::function<Type *(LLVMContext &)>; + +/// Entry point for configuring and running IR mutations. +class IRMutator { + std::vector<TypeGetter> AllowedTypes; + std::vector<std::unique_ptr<IRMutationStrategy>> Strategies; + +public: + IRMutator(std::vector<TypeGetter> &&AllowedTypes, + std::vector<std::unique_ptr<IRMutationStrategy>> &&Strategies) + : AllowedTypes(std::move(AllowedTypes)), + Strategies(std::move(Strategies)) {} + + void mutateModule(Module &M, int Seed, size_t CurSize, size_t MaxSize); +}; + +/// Strategy that injects operations into the function. +class InjectorIRStrategy : public IRMutationStrategy { + std::vector<fuzzerop::OpDescriptor> Operations; + + Optional<fuzzerop::OpDescriptor> chooseOperation(Value *Src, + RandomIRBuilder &IB); + +public: + InjectorIRStrategy(std::vector<fuzzerop::OpDescriptor> &&Operations) + : Operations(std::move(Operations)) {} + static std::vector<fuzzerop::OpDescriptor> getDefaultOps(); + + uint64_t getWeight(size_t CurrentSize, size_t MaxSize, + uint64_t CurrentWeight) override { + return Operations.size(); + } + + using IRMutationStrategy::mutate; + void mutate(Function &F, RandomIRBuilder &IB) override; + void mutate(BasicBlock &BB, RandomIRBuilder &IB) override; +}; + +class InstDeleterIRStrategy : public IRMutationStrategy { +public: + uint64_t getWeight(size_t CurrentSize, size_t MaxSize, + uint64_t CurrentWeight) override; + + using IRMutationStrategy::mutate; + void mutate(Function &F, RandomIRBuilder &IB) override; + void mutate(Instruction &Inst, RandomIRBuilder &IB) override; +}; + +class InstModificationIRStrategy : public IRMutationStrategy { +public: + uint64_t getWeight(size_t CurrentSize, size_t MaxSize, + uint64_t CurrentWeight) override { + return 4; + } + + using IRMutationStrategy::mutate; + void mutate(Instruction &Inst, RandomIRBuilder &IB) override; +}; + +} // end llvm namespace + +#endif // LLVM_FUZZMUTATE_IRMUTATOR_H + +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif diff --git a/contrib/libs/llvm12/include/llvm/FuzzMutate/OpDescriptor.h b/contrib/libs/llvm12/include/llvm/FuzzMutate/OpDescriptor.h new file mode 100644 index 0000000000..a91ac373f1 --- /dev/null +++ b/contrib/libs/llvm12/include/llvm/FuzzMutate/OpDescriptor.h @@ -0,0 +1,233 @@ +#pragma once + +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-parameter" +#endif + +//===-- OpDescriptor.h ------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// Provides the fuzzerop::Descriptor class and related tools for describing +// operations an IR fuzzer can work with. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_FUZZMUTATE_OPDESCRIPTOR_H +#define LLVM_FUZZMUTATE_OPDESCRIPTOR_H + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/IR/Constants.h" +#include "llvm/IR/DerivedTypes.h" +#include "llvm/IR/Instructions.h" +#include "llvm/IR/Type.h" +#include "llvm/IR/Value.h" +#include <functional> + +namespace llvm { +namespace fuzzerop { + +/// @{ +/// Populate a small list of potentially interesting constants of a given type. +void makeConstantsWithType(Type *T, std::vector<Constant *> &Cs); +std::vector<Constant *> makeConstantsWithType(Type *T); +/// @} + +/// A matcher/generator for finding suitable values for the next source in an +/// operation's partially completed argument list. +/// +/// Given that we're building some operation X and may have already filled some +/// subset of its operands, this predicate determines if some value New is +/// suitable for the next operand or generates a set of values that are +/// suitable. +class SourcePred { +public: + /// Given a list of already selected operands, returns whether a given new + /// operand is suitable for the next operand. + using PredT = std::function<bool(ArrayRef<Value *> Cur, const Value *New)>; + /// Given a list of already selected operands and a set of valid base types + /// for a fuzzer, generates a list of constants that could be used for the + /// next operand. + using MakeT = std::function<std::vector<Constant *>( + ArrayRef<Value *> Cur, ArrayRef<Type *> BaseTypes)>; + +private: + PredT Pred; + MakeT Make; + +public: + /// Create a fully general source predicate. + SourcePred(PredT Pred, MakeT Make) : Pred(Pred), Make(Make) {} + SourcePred(PredT Pred, NoneType) : Pred(Pred) { + Make = [Pred](ArrayRef<Value *> Cur, ArrayRef<Type *> BaseTypes) { + // Default filter just calls Pred on each of the base types. + std::vector<Constant *> Result; + for (Type *T : BaseTypes) { + Constant *V = UndefValue::get(T); + if (Pred(Cur, V)) + makeConstantsWithType(T, Result); + } + if (Result.empty()) + report_fatal_error("Predicate does not match for base types"); + return Result; + }; + } + + /// Returns true if \c New is compatible for the argument after \c Cur + bool matches(ArrayRef<Value *> Cur, const Value *New) { + return Pred(Cur, New); + } + + /// Generates a list of potential values for the argument after \c Cur. + std::vector<Constant *> generate(ArrayRef<Value *> Cur, + ArrayRef<Type *> BaseTypes) { + return Make(Cur, BaseTypes); + } +}; + +/// A description of some operation we can build while fuzzing IR. +struct OpDescriptor { + unsigned Weight; + SmallVector<SourcePred, 2> SourcePreds; + std::function<Value *(ArrayRef<Value *>, Instruction *)> BuilderFunc; +}; + +static inline SourcePred onlyType(Type *Only) { + auto Pred = [Only](ArrayRef<Value *>, const Value *V) { + return V->getType() == Only; + }; + auto Make = [Only](ArrayRef<Value *>, ArrayRef<Type *>) { + return makeConstantsWithType(Only); + }; + return {Pred, Make}; +} + +static inline SourcePred anyType() { + auto Pred = [](ArrayRef<Value *>, const Value *V) { + return !V->getType()->isVoidTy(); + }; + auto Make = None; + return {Pred, Make}; +} + +static inline SourcePred anyIntType() { + auto Pred = [](ArrayRef<Value *>, const Value *V) { + return V->getType()->isIntegerTy(); + }; + auto Make = None; + return {Pred, Make}; +} + +static inline SourcePred anyFloatType() { + auto Pred = [](ArrayRef<Value *>, const Value *V) { + return V->getType()->isFloatingPointTy(); + }; + auto Make = None; + return {Pred, Make}; +} + +static inline SourcePred anyPtrType() { + auto Pred = [](ArrayRef<Value *>, const Value *V) { + return V->getType()->isPointerTy() && !V->isSwiftError(); + }; + auto Make = [](ArrayRef<Value *>, ArrayRef<Type *> Ts) { + std::vector<Constant *> Result; + // TODO: Should these point at something? + for (Type *T : Ts) + Result.push_back(UndefValue::get(PointerType::getUnqual(T))); + return Result; + }; + return {Pred, Make}; +} + +static inline SourcePred sizedPtrType() { + auto Pred = [](ArrayRef<Value *>, const Value *V) { + if (V->isSwiftError()) + return false; + + if (const auto *PtrT = dyn_cast<PointerType>(V->getType())) + return PtrT->getElementType()->isSized(); + return false; + }; + auto Make = [](ArrayRef<Value *>, ArrayRef<Type *> Ts) { + std::vector<Constant *> Result; + + for (Type *T : Ts) + if (T->isSized()) + Result.push_back(UndefValue::get(PointerType::getUnqual(T))); + + return Result; + }; + return {Pred, Make}; +} + +static inline SourcePred anyAggregateType() { + auto Pred = [](ArrayRef<Value *>, const Value *V) { + // We can't index zero sized arrays. + if (isa<ArrayType>(V->getType())) + return V->getType()->getArrayNumElements() > 0; + + // Structs can also be zero sized. I.e opaque types. + if (isa<StructType>(V->getType())) + return V->getType()->getStructNumElements() > 0; + + return V->getType()->isAggregateType(); + }; + // TODO: For now we only find aggregates in BaseTypes. It might be better to + // manufacture them out of the base types in some cases. + auto Find = None; + return {Pred, Find}; +} + +static inline SourcePred anyVectorType() { + auto Pred = [](ArrayRef<Value *>, const Value *V) { + return V->getType()->isVectorTy(); + }; + // TODO: For now we only find vectors in BaseTypes. It might be better to + // manufacture vectors out of the base types, but it's tricky to be sure + // that's actually a reasonable type. + auto Make = None; + return {Pred, Make}; +} + +/// Match values that have the same type as the first source. +static inline SourcePred matchFirstType() { + auto Pred = [](ArrayRef<Value *> Cur, const Value *V) { + assert(!Cur.empty() && "No first source yet"); + return V->getType() == Cur[0]->getType(); + }; + auto Make = [](ArrayRef<Value *> Cur, ArrayRef<Type *>) { + assert(!Cur.empty() && "No first source yet"); + return makeConstantsWithType(Cur[0]->getType()); + }; + return {Pred, Make}; +} + +/// Match values that have the first source's scalar type. +static inline SourcePred matchScalarOfFirstType() { + auto Pred = [](ArrayRef<Value *> Cur, const Value *V) { + assert(!Cur.empty() && "No first source yet"); + return V->getType() == Cur[0]->getType()->getScalarType(); + }; + auto Make = [](ArrayRef<Value *> Cur, ArrayRef<Type *>) { + assert(!Cur.empty() && "No first source yet"); + return makeConstantsWithType(Cur[0]->getType()->getScalarType()); + }; + return {Pred, Make}; +} + +} // end fuzzerop namespace +} // end llvm namespace + +#endif // LLVM_FUZZMUTATE_OPDESCRIPTOR_H + +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif diff --git a/contrib/libs/llvm12/include/llvm/FuzzMutate/Operations.h b/contrib/libs/llvm12/include/llvm/FuzzMutate/Operations.h new file mode 100644 index 0000000000..64614aeaf0 --- /dev/null +++ b/contrib/libs/llvm12/include/llvm/FuzzMutate/Operations.h @@ -0,0 +1,64 @@ +#pragma once + +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-parameter" +#endif + +//===-- Operations.h - ----------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// Implementations of common fuzzer operation descriptors for building an IR +// mutator. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_FUZZMUTATE_OPERATIONS_H +#define LLVM_FUZZMUTATE_OPERATIONS_H + +#include "llvm/FuzzMutate/OpDescriptor.h" +#include "llvm/IR/InstrTypes.h" +#include "llvm/IR/Instruction.h" + +namespace llvm { + +/// Getters for the default sets of operations, per general category. +/// @{ +void describeFuzzerIntOps(std::vector<fuzzerop::OpDescriptor> &Ops); +void describeFuzzerFloatOps(std::vector<fuzzerop::OpDescriptor> &Ops); +void describeFuzzerControlFlowOps(std::vector<fuzzerop::OpDescriptor> &Ops); +void describeFuzzerPointerOps(std::vector<fuzzerop::OpDescriptor> &Ops); +void describeFuzzerAggregateOps(std::vector<fuzzerop::OpDescriptor> &Ops); +void describeFuzzerVectorOps(std::vector<fuzzerop::OpDescriptor> &Ops); +/// @} + +namespace fuzzerop { + +/// Descriptors for individual operations. +/// @{ +OpDescriptor binOpDescriptor(unsigned Weight, Instruction::BinaryOps Op); +OpDescriptor cmpOpDescriptor(unsigned Weight, Instruction::OtherOps CmpOp, + CmpInst::Predicate Pred); +OpDescriptor splitBlockDescriptor(unsigned Weight); +OpDescriptor gepDescriptor(unsigned Weight); +OpDescriptor extractValueDescriptor(unsigned Weight); +OpDescriptor insertValueDescriptor(unsigned Weight); +OpDescriptor extractElementDescriptor(unsigned Weight); +OpDescriptor insertElementDescriptor(unsigned Weight); +OpDescriptor shuffleVectorDescriptor(unsigned Weight); +/// @} + +} // end fuzzerop namespace + +} // end llvm namespace + +#endif // LLVM_FUZZMUTATE_OPERATIONS_H + +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif diff --git a/contrib/libs/llvm12/include/llvm/FuzzMutate/Random.h b/contrib/libs/llvm12/include/llvm/FuzzMutate/Random.h new file mode 100644 index 0000000000..2f04bf63b1 --- /dev/null +++ b/contrib/libs/llvm12/include/llvm/FuzzMutate/Random.h @@ -0,0 +1,107 @@ +#pragma once + +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-parameter" +#endif + +//===--- Random.h - Utilities for random sampling -------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// Utilities for random sampling. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_FUZZMUTATE_RANDOM_H +#define LLVM_FUZZMUTATE_RANDOM_H + +#include <random> +#include "llvm/Support/raw_ostream.h" +namespace llvm { + +/// Return a uniformly distributed random value between \c Min and \c Max +template <typename T, typename GenT> T uniform(GenT &Gen, T Min, T Max) { + return std::uniform_int_distribution<T>(Min, Max)(Gen); +} + +/// Return a uniformly distributed random value of type \c T +template <typename T, typename GenT> T uniform(GenT &Gen) { + return uniform<T>(Gen, std::numeric_limits<T>::min(), + std::numeric_limits<T>::max()); +} + +/// Randomly selects an item by sampling into a set with an unknown number of +/// elements, which may each be weighted to be more likely choices. +template <typename T, typename GenT> class ReservoirSampler { + GenT &RandGen; + std::remove_const_t<T> Selection = {}; + uint64_t TotalWeight = 0; + +public: + ReservoirSampler(GenT &RandGen) : RandGen(RandGen) {} + + uint64_t totalWeight() const { return TotalWeight; } + bool isEmpty() const { return TotalWeight == 0; } + + const T &getSelection() const { + assert(!isEmpty() && "Nothing selected"); + return Selection; + } + + explicit operator bool() const { return !isEmpty();} + const T &operator*() const { return getSelection(); } + + /// Sample each item in \c Items with unit weight + template <typename RangeT> ReservoirSampler &sample(RangeT &&Items) { + for (auto &I : Items) + sample(I, 1); + return *this; + } + + /// Sample a single item with the given weight. + ReservoirSampler &sample(const T &Item, uint64_t Weight) { + if (!Weight) + // If the weight is zero, do nothing. + return *this; + TotalWeight += Weight; + // Consider switching from the current element to this one. + if (uniform<uint64_t>(RandGen, 1, TotalWeight) <= Weight) + Selection = Item; + return *this; + } +}; + +template <typename GenT, typename RangeT, + typename ElT = std::remove_reference_t< + decltype(*std::begin(std::declval<RangeT>()))>> +ReservoirSampler<ElT, GenT> makeSampler(GenT &RandGen, RangeT &&Items) { + ReservoirSampler<ElT, GenT> RS(RandGen); + RS.sample(Items); + return RS; +} + +template <typename GenT, typename T> +ReservoirSampler<T, GenT> makeSampler(GenT &RandGen, const T &Item, + uint64_t Weight) { + ReservoirSampler<T, GenT> RS(RandGen); + RS.sample(Item, Weight); + return RS; +} + +template <typename T, typename GenT> +ReservoirSampler<T, GenT> makeSampler(GenT &RandGen) { + return ReservoirSampler<T, GenT>(RandGen); +} + +} // End llvm namespace + +#endif // LLVM_FUZZMUTATE_RANDOM_H + +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif diff --git a/contrib/libs/llvm12/include/llvm/FuzzMutate/RandomIRBuilder.h b/contrib/libs/llvm12/include/llvm/FuzzMutate/RandomIRBuilder.h new file mode 100644 index 0000000000..2838f6ae0c --- /dev/null +++ b/contrib/libs/llvm12/include/llvm/FuzzMutate/RandomIRBuilder.h @@ -0,0 +1,72 @@ +#pragma once + +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-parameter" +#endif + +//===- RandomIRBuilder.h - Utils for randomly mutation IR -------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// Provides the Mutator class, which is used to mutate IR for fuzzing. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_FUZZMUTATE_RANDOMIRBUILDER_H +#define LLVM_FUZZMUTATE_RANDOMIRBUILDER_H + +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/FuzzMutate/IRMutator.h" +#include "llvm/FuzzMutate/Random.h" +#include <random> + +namespace llvm { + +using RandomEngine = std::mt19937; + +struct RandomIRBuilder { + RandomEngine Rand; + SmallVector<Type *, 16> KnownTypes; + + RandomIRBuilder(int Seed, ArrayRef<Type *> AllowedTypes) + : Rand(Seed), KnownTypes(AllowedTypes.begin(), AllowedTypes.end()) {} + + // TODO: Try to make this a bit less of a random mishmash of functions. + + /// Find a "source" for some operation, which will be used in one of the + /// operation's operands. This either selects an instruction in \c Insts or + /// returns some new arbitrary Value. + Value *findOrCreateSource(BasicBlock &BB, ArrayRef<Instruction *> Insts); + /// Find a "source" for some operation, which will be used in one of the + /// operation's operands. This either selects an instruction in \c Insts that + /// matches \c Pred, or returns some new Value that matches \c Pred. The + /// values in \c Srcs should be source operands that have already been + /// selected. + Value *findOrCreateSource(BasicBlock &BB, ArrayRef<Instruction *> Insts, + ArrayRef<Value *> Srcs, fuzzerop::SourcePred Pred); + /// Create some Value suitable as a source for some operation. + Value *newSource(BasicBlock &BB, ArrayRef<Instruction *> Insts, + ArrayRef<Value *> Srcs, fuzzerop::SourcePred Pred); + /// Find a viable user for \c V in \c Insts, which should all be contained in + /// \c BB. This may also create some new instruction in \c BB and use that. + void connectToSink(BasicBlock &BB, ArrayRef<Instruction *> Insts, Value *V); + /// Create a user for \c V in \c BB. + void newSink(BasicBlock &BB, ArrayRef<Instruction *> Insts, Value *V); + Value *findPointer(BasicBlock &BB, ArrayRef<Instruction *> Insts, + ArrayRef<Value *> Srcs, fuzzerop::SourcePred Pred); + Type *chooseType(LLVMContext &Context, ArrayRef<Value *> Srcs, + fuzzerop::SourcePred Pred); +}; + +} // end llvm namespace + +#endif // LLVM_FUZZMUTATE_RANDOMIRBUILDER_H + +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif |