diff options
author | orivej <orivej@yandex-team.ru> | 2022-02-10 16:45:01 +0300 |
---|---|---|
committer | Daniil Cherednik <dcherednik@yandex-team.ru> | 2022-02-10 16:45:01 +0300 |
commit | 2d37894b1b037cf24231090eda8589bbb44fb6fc (patch) | |
tree | be835aa92c6248212e705f25388ebafcf84bc7a1 /contrib/libs/llvm12/include/llvm/FuzzMutate | |
parent | 718c552901d703c502ccbefdfc3c9028d608b947 (diff) | |
download | ydb-2d37894b1b037cf24231090eda8589bbb44fb6fc.tar.gz |
Restoring authorship annotation for <orivej@yandex-team.ru>. Commit 2 of 2.
Diffstat (limited to 'contrib/libs/llvm12/include/llvm/FuzzMutate')
6 files changed, 684 insertions, 684 deletions
diff --git a/contrib/libs/llvm12/include/llvm/FuzzMutate/FuzzerCLI.h b/contrib/libs/llvm12/include/llvm/FuzzMutate/FuzzerCLI.h index 621ed995ed..8b2dd1b41a 100644 --- a/contrib/libs/llvm12/include/llvm/FuzzMutate/FuzzerCLI.h +++ b/contrib/libs/llvm12/include/llvm/FuzzMutate/FuzzerCLI.h @@ -1,90 +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 +#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 index 40ce41e6a8..48bf5f18a5 100644 --- a/contrib/libs/llvm12/include/llvm/FuzzMutate/IRMutator.h +++ b/contrib/libs/llvm12/include/llvm/FuzzMutate/IRMutator.h @@ -1,114 +1,114 @@ -#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; -}; - +#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, @@ -120,10 +120,10 @@ public: void mutate(Instruction &Inst, RandomIRBuilder &IB) override; }; -} // end llvm namespace - -#endif // LLVM_FUZZMUTATE_IRMUTATOR_H - -#ifdef __GNUC__ -#pragma GCC diagnostic pop -#endif +} // 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 index dfac913234..a91ac373f1 100644 --- a/contrib/libs/llvm12/include/llvm/FuzzMutate/OpDescriptor.h +++ b/contrib/libs/llvm12/include/llvm/FuzzMutate/OpDescriptor.h @@ -1,233 +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 +#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 index da34f2c0ed..64614aeaf0 100644 --- a/contrib/libs/llvm12/include/llvm/FuzzMutate/Operations.h +++ b/contrib/libs/llvm12/include/llvm/FuzzMutate/Operations.h @@ -1,64 +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 +#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 index c28b484e87..2f04bf63b1 100644 --- a/contrib/libs/llvm12/include/llvm/FuzzMutate/Random.h +++ b/contrib/libs/llvm12/include/llvm/FuzzMutate/Random.h @@ -1,107 +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 +#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 index 14dc16004f..2838f6ae0c 100644 --- a/contrib/libs/llvm12/include/llvm/FuzzMutate/RandomIRBuilder.h +++ b/contrib/libs/llvm12/include/llvm/FuzzMutate/RandomIRBuilder.h @@ -1,72 +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 +#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 |