diff options
author | Justin Bogner <mail@justinbogner.com> | 2017-08-21 22:28:47 +0000 |
---|---|---|
committer | Justin Bogner <mail@justinbogner.com> | 2017-08-21 22:28:47 +0000 |
commit | 6e39755d84a8ac2f223b6779cffc17735b478114 (patch) | |
tree | 1adfda35175b25bb86a4fa1da8af5a48d2d037db /llvm/lib | |
parent | f5c873648208cf0df3a21f0c5e948efbcec7dbae (diff) | |
download | bcm5719-llvm-6e39755d84a8ac2f223b6779cffc17735b478114.tar.gz bcm5719-llvm-6e39755d84a8ac2f223b6779cffc17735b478114.zip |
Revert "Re-apply "Introduce FuzzMutate library""
The dependencies for the new library seem to be misconfigured on some
linux configs:
http://bb.pgr.jp/builders/llvm-i686-linux-RA/builds/5435/steps/build_all/logs/stdio
This reverts r311392.
llvm-svn: 311393
Diffstat (limited to 'llvm/lib')
-rw-r--r-- | llvm/lib/CMakeLists.txt | 1 | ||||
-rw-r--r-- | llvm/lib/FuzzMutate/CMakeLists.txt | 12 | ||||
-rw-r--r-- | llvm/lib/FuzzMutate/IRMutator.cpp | 183 | ||||
-rw-r--r-- | llvm/lib/FuzzMutate/LLVMBuild.txt | 22 | ||||
-rw-r--r-- | llvm/lib/FuzzMutate/OpDescriptor.cpp | 38 | ||||
-rw-r--r-- | llvm/lib/FuzzMutate/Operations.cpp | 312 | ||||
-rw-r--r-- | llvm/lib/FuzzMutate/RandomIRBuilder.cpp | 140 |
7 files changed, 0 insertions, 708 deletions
diff --git a/llvm/lib/CMakeLists.txt b/llvm/lib/CMakeLists.txt index 5e20d503482..71b0a0aa0d3 100644 --- a/llvm/lib/CMakeLists.txt +++ b/llvm/lib/CMakeLists.txt @@ -2,7 +2,6 @@ # CMakeLists.txt add_subdirectory(IR) -add_subdirectory(FuzzMutate) add_subdirectory(IRReader) add_subdirectory(CodeGen) add_subdirectory(BinaryFormat) diff --git a/llvm/lib/FuzzMutate/CMakeLists.txt b/llvm/lib/FuzzMutate/CMakeLists.txt deleted file mode 100644 index 4aec682b01f..00000000000 --- a/llvm/lib/FuzzMutate/CMakeLists.txt +++ /dev/null @@ -1,12 +0,0 @@ -add_llvm_library(LLVMFuzzMutate - IRMutator.cpp - OpDescriptor.cpp - Operations.cpp - RandomIRBuilder.cpp - - ADDITIONAL_HEADER_DIRS - ${LLVM_MAIN_INCLUDE_DIR}/llvm/FuzzMutate - - DEPENDS - intrinsics_gen - ) diff --git a/llvm/lib/FuzzMutate/IRMutator.cpp b/llvm/lib/FuzzMutate/IRMutator.cpp deleted file mode 100644 index 6545446a984..00000000000 --- a/llvm/lib/FuzzMutate/IRMutator.cpp +++ /dev/null @@ -1,183 +0,0 @@ -//===-- IRMutator.cpp -----------------------------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "llvm/FuzzMutate/IRMutator.h" -#include "llvm/Analysis/TargetLibraryInfo.h" -#include "llvm/FuzzMutate/Operations.h" -#include "llvm/FuzzMutate/Random.h" -#include "llvm/FuzzMutate/RandomIRBuilder.h" -#include "llvm/IR/BasicBlock.h" -#include "llvm/IR/Function.h" -#include "llvm/IR/Instructions.h" -#include "llvm/IR/InstIterator.h" -#include "llvm/IR/Module.h" -#include "llvm/Transforms/Scalar/DCE.h" - -using namespace llvm; - -static void createEmptyFunction(Module &M) { - // TODO: Some arguments and a return value would probably be more interesting. - LLVMContext &Context = M.getContext(); - Function *F = Function::Create(FunctionType::get(Type::getVoidTy(Context), {}, - /*isVarArg=*/false), - GlobalValue::ExternalLinkage, "f", &M); - BasicBlock *BB = BasicBlock::Create(Context, "BB", F); - ReturnInst::Create(Context, BB); -} - -void IRMutationStrategy::mutate(Module &M, RandomIRBuilder &IB) { - if (M.empty()) - createEmptyFunction(M); - - auto RS = makeSampler<Function *>(IB.Rand); - for (Function &F : M) - if (!F.isDeclaration()) - RS.sample(&F, /*Weight=*/1); - mutate(*RS.getSelection(), IB); -} - -void IRMutationStrategy::mutate(Function &F, RandomIRBuilder &IB) { - mutate(*makeSampler(IB.Rand, make_pointer_range(F)).getSelection(), IB); -} - -void IRMutationStrategy::mutate(BasicBlock &BB, RandomIRBuilder &IB) { - mutate(*makeSampler(IB.Rand, make_pointer_range(BB)).getSelection(), IB); -} - -void IRMutator::mutateModule(Module &M, int Seed, size_t CurSize, - size_t MaxSize) { - std::vector<Type *> Types; - for (const auto &Getter : AllowedTypes) - Types.push_back(Getter(M.getContext())); - RandomIRBuilder IB(Seed, Types); - - auto RS = makeSampler<IRMutationStrategy *>(IB.Rand); - for (const auto &Strategy : Strategies) - RS.sample(Strategy.get(), - Strategy->getWeight(CurSize, MaxSize, RS.totalWeight())); - auto Strategy = RS.getSelection(); - - Strategy->mutate(M, IB); -} - -static void eliminateDeadCode(Function &F) { - FunctionPassManager FPM; - FPM.addPass(DCEPass()); - FunctionAnalysisManager FAM; - FAM.registerPass([&] { return TargetLibraryAnalysis(); }); - FPM.run(F, FAM); -} - -void InjectorIRStrategy::mutate(Function &F, RandomIRBuilder &IB) { - IRMutationStrategy::mutate(F, IB); - eliminateDeadCode(F); -} - -std::vector<fuzzerop::OpDescriptor> InjectorIRStrategy::getDefaultOps() { - std::vector<fuzzerop::OpDescriptor> Ops; - describeFuzzerIntOps(Ops); - describeFuzzerFloatOps(Ops); - describeFuzzerControlFlowOps(Ops); - describeFuzzerPointerOps(Ops); - describeFuzzerAggregateOps(Ops); - describeFuzzerVectorOps(Ops); - return Ops; -} - -fuzzerop::OpDescriptor -InjectorIRStrategy::chooseOperation(Value *Src, RandomIRBuilder &IB) { - auto OpMatchesPred = [&Src](fuzzerop::OpDescriptor &Op) { - return Op.SourcePreds[0].matches({}, Src); - }; - auto RS = makeSampler(IB.Rand, make_filter_range(Operations, OpMatchesPred)); - if (RS.isEmpty()) - report_fatal_error("No available operations for src type"); - return *RS; -} - -void InjectorIRStrategy::mutate(BasicBlock &BB, RandomIRBuilder &IB) { - SmallVector<Instruction *, 32> Insts; - for (auto I = BB.getFirstInsertionPt(), E = BB.end(); I != E; ++I) - Insts.push_back(&*I); - - // Choose an insertion point for our new instruction. - size_t IP = uniform<size_t>(IB.Rand, 0, Insts.size() - 1); - - auto InstsBefore = makeArrayRef(Insts).slice(0, IP); - auto InstsAfter = makeArrayRef(Insts).slice(IP); - - // Choose a source, which will be used to constrain the operation selection. - SmallVector<Value *, 2> Srcs; - Srcs.push_back(IB.findOrCreateSource(BB, InstsBefore)); - - // Choose an operation that's constrained to be valid for the type of the - // source, collect any other sources it needs, and then build it. - fuzzerop::OpDescriptor OpDesc = chooseOperation(Srcs[0], IB); - for (const auto &Pred : makeArrayRef(OpDesc.SourcePreds).slice(1)) - Srcs.push_back(IB.findOrCreateSource(BB, InstsBefore, Srcs, Pred)); - if (Value *Op = OpDesc.BuilderFunc(Srcs, Insts[IP])) { - // Find a sink and wire up the results of the operation. - IB.connectToSink(BB, InstsAfter, Op); - } -} - -uint64_t InstDeleterIRStrategy::getWeight(size_t CurrentSize, size_t MaxSize, - uint64_t CurrentWeight) { - // If we have less than 200 bytes, panic and try to always delete. - if (CurrentSize > MaxSize - 200) - return CurrentWeight ? CurrentWeight * 100 : 1; - // Draw a line starting from when we only have 1k left and increasing linearly - // to double the current weight. - int Line = (-2 * CurrentWeight) * (MaxSize - CurrentSize + 1000); - // Clamp negative weights to zero. - if (Line < 0) - return 0; - return Line; -} - -void InstDeleterIRStrategy::mutate(Function &F, RandomIRBuilder &IB) { - auto RS = makeSampler<Instruction *>(IB.Rand); - // Avoid terminators so we don't have to worry about keeping the CFG coherent. - for (Instruction &Inst : instructions(F)) - if (!Inst.isTerminator()) - RS.sample(&Inst, /*Weight=*/1); - assert(!RS.isEmpty() && "No instructions to delete"); - // Delete the instruction. - mutate(*RS.getSelection(), IB); - // Clean up any dead code that's left over after removing the instruction. - eliminateDeadCode(F); -} - -void InstDeleterIRStrategy::mutate(Instruction &Inst, RandomIRBuilder &IB) { - assert(!Inst.isTerminator() && "Deleting terminators invalidates CFG"); - - if (Inst.getType()->isVoidTy()) { - // Instructions with void type (ie, store) have no uses to worry about. Just - // erase it and move on. - Inst.eraseFromParent(); - return; - } - - // Otherwise we need to find some other value with the right type to keep the - // users happy. - auto Pred = fuzzerop::onlyType(Inst.getType()); - auto RS = makeSampler<Value *>(IB.Rand); - SmallVector<Instruction *, 32> InstsBefore; - BasicBlock *BB = Inst.getParent(); - for (auto I = BB->getFirstInsertionPt(), E = Inst.getIterator(); I != E; - ++I) { - if (Pred.matches({}, &*I)) - RS.sample(&*I, /*Weight=*/1); - InstsBefore.push_back(&*I); - } - if (!RS) - RS.sample(IB.newSource(*BB, InstsBefore, {}, Pred), /*Weight=*/1); - - Inst.replaceAllUsesWith(RS.getSelection()); -} diff --git a/llvm/lib/FuzzMutate/LLVMBuild.txt b/llvm/lib/FuzzMutate/LLVMBuild.txt deleted file mode 100644 index 732c371a54f..00000000000 --- a/llvm/lib/FuzzMutate/LLVMBuild.txt +++ /dev/null @@ -1,22 +0,0 @@ -;===- ./lib/FuzzMutate/LLVMBuild.txt ---------------------------*- Conf -*--===; -; -; The LLVM Compiler Infrastructure -; -; This file is distributed under the University of Illinois Open Source -; License. See LICENSE.TXT for details. -; -;===------------------------------------------------------------------------===; -; -; This is an LLVMBuild description file for the components in this subdirectory. -; -; For more information on the LLVMBuild system, please see: -; -; http://llvm.org/docs/LLVMBuild.html -; -;===------------------------------------------------------------------------===; - -[component_0] -type = Library -name = FuzzMutate -parent = Libraries -required_libraries = Analysis Core IR Support Transforms diff --git a/llvm/lib/FuzzMutate/OpDescriptor.cpp b/llvm/lib/FuzzMutate/OpDescriptor.cpp deleted file mode 100644 index 1c5d8f606ae..00000000000 --- a/llvm/lib/FuzzMutate/OpDescriptor.cpp +++ /dev/null @@ -1,38 +0,0 @@ -//===-- OpDescriptor.cpp --------------------------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "llvm/FuzzMutate/OpDescriptor.h" -#include "llvm/IR/Constants.h" - -using namespace llvm; -using namespace fuzzerop; - -void fuzzerop::makeConstantsWithType(Type *T, std::vector<Constant *> &Cs) { - if (auto *IntTy = dyn_cast<IntegerType>(T)) { - uint64_t W = IntTy->getBitWidth(); - Cs.push_back(ConstantInt::get(IntTy, APInt::getMaxValue(W))); - Cs.push_back(ConstantInt::get(IntTy, APInt::getMinValue(W))); - Cs.push_back(ConstantInt::get(IntTy, APInt::getSignedMaxValue(W))); - Cs.push_back(ConstantInt::get(IntTy, APInt::getSignedMinValue(W))); - Cs.push_back(ConstantInt::get(IntTy, APInt::getOneBitSet(W, W / 2))); - } else if (T->isFloatingPointTy()) { - auto &Ctx = T->getContext(); - auto &Sem = T->getFltSemantics(); - Cs.push_back(ConstantFP::get(Ctx, APFloat::getZero(Sem))); - Cs.push_back(ConstantFP::get(Ctx, APFloat::getLargest(Sem))); - Cs.push_back(ConstantFP::get(Ctx, APFloat::getSmallest(Sem))); - } else - Cs.push_back(UndefValue::get(T)); -} - -std::vector<Constant *> fuzzerop::makeConstantsWithType(Type *T) { - std::vector<Constant *> Result; - makeConstantsWithType(T, Result); - return Result; -} diff --git a/llvm/lib/FuzzMutate/Operations.cpp b/llvm/lib/FuzzMutate/Operations.cpp deleted file mode 100644 index 083d9aa039e..00000000000 --- a/llvm/lib/FuzzMutate/Operations.cpp +++ /dev/null @@ -1,312 +0,0 @@ -//===-- Operations.cpp ----------------------------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "llvm/FuzzMutate/Operations.h" -#include "llvm/IR/BasicBlock.h" -#include "llvm/IR/Constants.h" -#include "llvm/IR/Function.h" -#include "llvm/IR/Instructions.h" - -using namespace llvm; -using namespace fuzzerop; - -void llvm::describeFuzzerIntOps(std::vector<fuzzerop::OpDescriptor> &Ops) { - Ops.push_back(binOpDescriptor(1, Instruction::Add)); - Ops.push_back(binOpDescriptor(1, Instruction::Sub)); - Ops.push_back(binOpDescriptor(1, Instruction::Mul)); - Ops.push_back(binOpDescriptor(1, Instruction::SDiv)); - Ops.push_back(binOpDescriptor(1, Instruction::UDiv)); - Ops.push_back(binOpDescriptor(1, Instruction::SRem)); - Ops.push_back(binOpDescriptor(1, Instruction::URem)); - Ops.push_back(binOpDescriptor(1, Instruction::Shl)); - Ops.push_back(binOpDescriptor(1, Instruction::LShr)); - Ops.push_back(binOpDescriptor(1, Instruction::AShr)); - Ops.push_back(binOpDescriptor(1, Instruction::And)); - Ops.push_back(binOpDescriptor(1, Instruction::Or)); - Ops.push_back(binOpDescriptor(1, Instruction::Xor)); - - Ops.push_back(cmpOpDescriptor(1, Instruction::ICmp, CmpInst::ICMP_EQ)); - Ops.push_back(cmpOpDescriptor(1, Instruction::ICmp, CmpInst::ICMP_NE)); - Ops.push_back(cmpOpDescriptor(1, Instruction::ICmp, CmpInst::ICMP_UGT)); - Ops.push_back(cmpOpDescriptor(1, Instruction::ICmp, CmpInst::ICMP_UGE)); - Ops.push_back(cmpOpDescriptor(1, Instruction::ICmp, CmpInst::ICMP_ULT)); - Ops.push_back(cmpOpDescriptor(1, Instruction::ICmp, CmpInst::ICMP_ULE)); - Ops.push_back(cmpOpDescriptor(1, Instruction::ICmp, CmpInst::ICMP_SGT)); - Ops.push_back(cmpOpDescriptor(1, Instruction::ICmp, CmpInst::ICMP_SGE)); - Ops.push_back(cmpOpDescriptor(1, Instruction::ICmp, CmpInst::ICMP_SLT)); - Ops.push_back(cmpOpDescriptor(1, Instruction::ICmp, CmpInst::ICMP_SLE)); -} - -void llvm::describeFuzzerFloatOps(std::vector<fuzzerop::OpDescriptor> &Ops) { - Ops.push_back(binOpDescriptor(1, Instruction::FAdd)); - Ops.push_back(binOpDescriptor(1, Instruction::FSub)); - Ops.push_back(binOpDescriptor(1, Instruction::FMul)); - Ops.push_back(binOpDescriptor(1, Instruction::FDiv)); - Ops.push_back(binOpDescriptor(1, Instruction::FRem)); - - Ops.push_back(cmpOpDescriptor(1, Instruction::FCmp, CmpInst::FCMP_FALSE)); - Ops.push_back(cmpOpDescriptor(1, Instruction::FCmp, CmpInst::FCMP_OEQ)); - Ops.push_back(cmpOpDescriptor(1, Instruction::FCmp, CmpInst::FCMP_OGT)); - Ops.push_back(cmpOpDescriptor(1, Instruction::FCmp, CmpInst::FCMP_OGE)); - Ops.push_back(cmpOpDescriptor(1, Instruction::FCmp, CmpInst::FCMP_OLT)); - Ops.push_back(cmpOpDescriptor(1, Instruction::FCmp, CmpInst::FCMP_OLE)); - Ops.push_back(cmpOpDescriptor(1, Instruction::FCmp, CmpInst::FCMP_ONE)); - Ops.push_back(cmpOpDescriptor(1, Instruction::FCmp, CmpInst::FCMP_ORD)); - Ops.push_back(cmpOpDescriptor(1, Instruction::FCmp, CmpInst::FCMP_UNO)); - Ops.push_back(cmpOpDescriptor(1, Instruction::FCmp, CmpInst::FCMP_UEQ)); - Ops.push_back(cmpOpDescriptor(1, Instruction::FCmp, CmpInst::FCMP_UGT)); - Ops.push_back(cmpOpDescriptor(1, Instruction::FCmp, CmpInst::FCMP_UGE)); - Ops.push_back(cmpOpDescriptor(1, Instruction::FCmp, CmpInst::FCMP_ULT)); - Ops.push_back(cmpOpDescriptor(1, Instruction::FCmp, CmpInst::FCMP_ULE)); - Ops.push_back(cmpOpDescriptor(1, Instruction::FCmp, CmpInst::FCMP_UNE)); - Ops.push_back(cmpOpDescriptor(1, Instruction::FCmp, CmpInst::FCMP_TRUE)); -} - -void llvm::describeFuzzerControlFlowOps( - std::vector<fuzzerop::OpDescriptor> &Ops) { - Ops.push_back(splitBlockDescriptor(1)); -} - -void llvm::describeFuzzerPointerOps(std::vector<fuzzerop::OpDescriptor> &Ops) { - Ops.push_back(gepDescriptor(1)); -} - -void llvm::describeFuzzerAggregateOps( - std::vector<fuzzerop::OpDescriptor> &Ops) { - Ops.push_back(extractValueDescriptor(1)); - Ops.push_back(insertValueDescriptor(1)); -} - -void llvm::describeFuzzerVectorOps(std::vector<fuzzerop::OpDescriptor> &Ops) { - Ops.push_back(extractElementDescriptor(1)); - Ops.push_back(insertElementDescriptor(1)); - Ops.push_back(shuffleVectorDescriptor(1)); -} - -OpDescriptor llvm::fuzzerop::binOpDescriptor(unsigned Weight, - Instruction::BinaryOps Op) { - auto buildOp = [Op](ArrayRef<Value *> Srcs, Instruction *Inst) { - return BinaryOperator::Create(Op, Srcs[0], Srcs[1], "B", Inst); - }; - switch (Op) { - case Instruction::Add: - case Instruction::Sub: - case Instruction::Mul: - case Instruction::SDiv: - case Instruction::UDiv: - case Instruction::SRem: - case Instruction::URem: - case Instruction::Shl: - case Instruction::LShr: - case Instruction::AShr: - case Instruction::And: - case Instruction::Or: - case Instruction::Xor: - return {Weight, {anyIntType(), matchFirstType()}, buildOp}; - case Instruction::FAdd: - case Instruction::FSub: - case Instruction::FMul: - case Instruction::FDiv: - case Instruction::FRem: - return {Weight, {anyFloatType(), matchFirstType()}, buildOp}; - case Instruction::BinaryOpsEnd: - llvm_unreachable("Value out of range of enum"); - } - llvm_unreachable("Covered switch"); -} - -OpDescriptor llvm::fuzzerop::cmpOpDescriptor(unsigned Weight, - Instruction::OtherOps CmpOp, - CmpInst::Predicate Pred) { - auto buildOp = [CmpOp, Pred](ArrayRef<Value *> Srcs, Instruction *Inst) { - return CmpInst::Create(CmpOp, Pred, Srcs[0], Srcs[1], "C", Inst); - }; - - switch (CmpOp) { - case Instruction::ICmp: - return {Weight, {anyIntType(), matchFirstType()}, buildOp}; - case Instruction::FCmp: - return {Weight, {anyFloatType(), matchFirstType()}, buildOp}; - default: - llvm_unreachable("CmpOp must be ICmp or FCmp"); - } -} - -OpDescriptor llvm::fuzzerop::splitBlockDescriptor(unsigned Weight) { - auto buildSplitBlock = [](ArrayRef<Value *> Srcs, Instruction *Inst) { - BasicBlock *Block = Inst->getParent(); - BasicBlock *Next = Block->splitBasicBlock(Inst, "BB"); - if (Block != &Block->getParent()->getEntryBlock()) { - // Loop back on this block by replacing the unconditional forward branch - // with a conditional with a backedge. - BranchInst::Create(Block, Next, Srcs[0], Block->getTerminator()); - Block->getTerminator()->eraseFromParent(); - - // We need values for each phi in the block. Since there isn't a good way - // to do a variable number of input values currently, we just fill them - // with undef. - for (PHINode &PHI : Block->phis()) - PHI.addIncoming(UndefValue::get(PHI.getType()), Block); - } - return nullptr; - }; - SourcePred isInt1Ty{[](ArrayRef<Value *>, const Value *V) { - return V->getType()->isIntegerTy(1); - }, - None}; - return {Weight, {isInt1Ty}, buildSplitBlock}; -} - -OpDescriptor llvm::fuzzerop::gepDescriptor(unsigned Weight) { - auto buildGEP = [](ArrayRef<Value *> Srcs, Instruction *Inst) { - Type *Ty = cast<PointerType>(Srcs[0]->getType())->getElementType(); - auto Indices = makeArrayRef(Srcs).drop_front(1); - return GetElementPtrInst::Create(Ty, Srcs[0], Indices, "G", Inst); - }; - // TODO: Handle aggregates and vectors - // TODO: Support multiple indices. - // TODO: Try to avoid meaningless accesses. - return {Weight, {anyPtrType(), anyIntType()}, buildGEP}; -} - -static uint64_t getAggregateNumElements(Type *T) { - assert(T->isAggregateType() && "Not a struct or array"); - if (isa<StructType>(T)) - return T->getStructNumElements(); - return T->getArrayNumElements(); -} - -static SourcePred validExtractValueIndex() { - auto Pred = [](ArrayRef<Value *> Cur, const Value *V) { - if (auto *CI = dyn_cast<ConstantInt>(V)) - if (!CI->uge(getAggregateNumElements(Cur[0]->getType()))) - return true; - return false; - }; - auto Make = [](ArrayRef<Value *> Cur, ArrayRef<Type *> Ts) { - std::vector<Constant *> Result; - auto *Int32Ty = Type::getInt32Ty(Cur[0]->getContext()); - uint64_t N = getAggregateNumElements(Cur[0]->getType()); - // Create indices at the start, end, and middle, but avoid dups. - Result.push_back(ConstantInt::get(Int32Ty, 0)); - if (N > 1) - Result.push_back(ConstantInt::get(Int32Ty, N - 1)); - if (N > 2) - Result.push_back(ConstantInt::get(Int32Ty, N / 2)); - return Result; - }; - return {Pred, Make}; -} - -OpDescriptor llvm::fuzzerop::extractValueDescriptor(unsigned Weight) { - auto buildExtract = [](ArrayRef<Value *> Srcs, Instruction *Inst) { - // TODO: It's pretty inefficient to shuffle this all through constants. - unsigned Idx = cast<ConstantInt>(Srcs[1])->getZExtValue(); - return ExtractValueInst::Create(Srcs[0], {Idx}, "E", Inst); - }; - // TODO: Should we handle multiple indices? - return {Weight, {anyAggregateType(), validExtractValueIndex()}, buildExtract}; -} - -static SourcePred matchScalarInAggregate() { - auto Pred = [](ArrayRef<Value *> Cur, const Value *V) { - if (isa<ArrayType>(Cur[0]->getType())) - return V->getType() == Cur[0]->getType(); - auto *STy = cast<StructType>(Cur[0]->getType()); - for (int I = 0, E = STy->getNumElements(); I < E; ++I) - if (STy->getTypeAtIndex(I) == V->getType()) - return true; - return false; - }; - auto Make = [](ArrayRef<Value *> Cur, ArrayRef<Type *>) { - if (isa<ArrayType>(Cur[0]->getType())) - return makeConstantsWithType(Cur[0]->getType()); - std::vector<Constant *> Result; - auto *STy = cast<StructType>(Cur[0]->getType()); - for (int I = 0, E = STy->getNumElements(); I < E; ++I) - makeConstantsWithType(STy->getTypeAtIndex(I), Result); - return Result; - }; - return {Pred, Make}; -} - -static SourcePred validInsertValueIndex() { - auto Pred = [](ArrayRef<Value *> Cur, const Value *V) { - auto *CTy = cast<CompositeType>(Cur[0]->getType()); - if (auto *CI = dyn_cast<ConstantInt>(V)) - if (CI->getBitWidth() == 32) - if (CTy->getTypeAtIndex(CI->getZExtValue()) == V->getType()) - return true; - return false; - }; - auto Make = [](ArrayRef<Value *> Cur, ArrayRef<Type *> Ts) { - std::vector<Constant *> Result; - auto *Int32Ty = Type::getInt32Ty(Cur[0]->getContext()); - auto *CTy = cast<CompositeType>(Cur[0]->getType()); - for (int I = 0, E = getAggregateNumElements(CTy); I < E; ++I) - if (CTy->getTypeAtIndex(I) == Cur[1]->getType()) - Result.push_back(ConstantInt::get(Int32Ty, I)); - return Result; - }; - return {Pred, Make}; -} - -OpDescriptor llvm::fuzzerop::insertValueDescriptor(unsigned Weight) { - auto buildInsert = [](ArrayRef<Value *> Srcs, Instruction *Inst) { - // TODO: It's pretty inefficient to shuffle this all through constants. - unsigned Idx = cast<ConstantInt>(Srcs[2])->getZExtValue(); - return InsertValueInst::Create(Srcs[0], Srcs[1], {Idx}, "I", Inst); - }; - return { - Weight, - {anyAggregateType(), matchScalarInAggregate(), validInsertValueIndex()}, - buildInsert}; -} - -OpDescriptor llvm::fuzzerop::extractElementDescriptor(unsigned Weight) { - auto buildExtract = [](ArrayRef<Value *> Srcs, Instruction *Inst) { - return ExtractElementInst::Create(Srcs[0], Srcs[1], "E", Inst); - }; - // TODO: Try to avoid undefined accesses. - return {Weight, {anyVectorType(), anyIntType()}, buildExtract}; -} - -OpDescriptor llvm::fuzzerop::insertElementDescriptor(unsigned Weight) { - auto buildInsert = [](ArrayRef<Value *> Srcs, Instruction *Inst) { - return InsertElementInst::Create(Srcs[0], Srcs[1], Srcs[2], "I", Inst); - }; - // TODO: Try to avoid undefined accesses. - return {Weight, - {anyVectorType(), matchScalarOfFirstType(), anyIntType()}, - buildInsert}; -} - -static SourcePred validShuffleVectorIndex() { - auto Pred = [](ArrayRef<Value *> Cur, const Value *V) { - return ShuffleVectorInst::isValidOperands(Cur[0], Cur[1], V); - }; - auto Make = [](ArrayRef<Value *> Cur, ArrayRef<Type *> Ts) { - auto *FirstTy = cast<VectorType>(Cur[0]->getType()); - auto *Int32Ty = Type::getInt32Ty(Cur[0]->getContext()); - // TODO: It's straighforward to make up reasonable values, but listing them - // exhaustively would be insane. Come up with a couple of sensible ones. - return std::vector<Constant *>{ - UndefValue::get(VectorType::get(Int32Ty, FirstTy->getNumElements()))}; - }; - return {Pred, Make}; -} - -OpDescriptor llvm::fuzzerop::shuffleVectorDescriptor(unsigned Weight) { - auto buildShuffle = [](ArrayRef<Value *> Srcs, Instruction *Inst) { - return new ShuffleVectorInst(Srcs[0], Srcs[1], Srcs[2], "S", Inst); - }; - return {Weight, - {anyVectorType(), matchFirstType(), validShuffleVectorIndex()}, - buildShuffle}; -} diff --git a/llvm/lib/FuzzMutate/RandomIRBuilder.cpp b/llvm/lib/FuzzMutate/RandomIRBuilder.cpp deleted file mode 100644 index 42e30464b0d..00000000000 --- a/llvm/lib/FuzzMutate/RandomIRBuilder.cpp +++ /dev/null @@ -1,140 +0,0 @@ -//===-- RandomIRBuilder.cpp -----------------------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "llvm/FuzzMutate/RandomIRBuilder.h" -#include "llvm/ADT/STLExtras.h" -#include "llvm/FuzzMutate/Random.h" -#include "llvm/IR/BasicBlock.h" -#include "llvm/IR/Constants.h" -#include "llvm/IR/Function.h" -#include "llvm/IR/Instructions.h" -#include "llvm/IR/IntrinsicInst.h" -#include "llvm/IR/Module.h" - -using namespace llvm; -using namespace fuzzerop; - -Value *RandomIRBuilder::findOrCreateSource(BasicBlock &BB, - ArrayRef<Instruction *> Insts) { - return findOrCreateSource(BB, Insts, {}, anyType()); -} - -Value *RandomIRBuilder::findOrCreateSource(BasicBlock &BB, - ArrayRef<Instruction *> Insts, - ArrayRef<Value *> Srcs, - SourcePred Pred) { - auto MatchesPred = [&Srcs, &Pred](Instruction *Inst) { - return Pred.matches(Srcs, Inst); - }; - auto RS = makeSampler(Rand, make_filter_range(Insts, MatchesPred)); - // Also consider choosing no source, meaning we want a new one. - RS.sample(nullptr, /*Weight=*/1); - if (Instruction *Src = RS.getSelection()) - return Src; - return newSource(BB, Insts, Srcs, Pred); -} - -Value *RandomIRBuilder::newSource(BasicBlock &BB, ArrayRef<Instruction *> Insts, - ArrayRef<Value *> Srcs, SourcePred Pred) { - // Generate some constants to choose from. - auto RS = makeSampler<Value *>(Rand); - RS.sample(Pred.generate(Srcs, KnownTypes)); - assert(!RS.isEmpty() && "Failed to generate sources"); - - // If we can find a pointer to load from, use it half the time. - Value *Ptr = findPointer(BB, Insts, Srcs, Pred); - if (Ptr) - RS.sample(Ptr, RS.totalWeight()); - - Value *Result = RS.getSelection(); - if (Result != Ptr) - return Result; - - // If we choose the pointer, we need to create a load. - auto IP = BB.getFirstInsertionPt(); - if (auto *I = dyn_cast<Instruction>(Ptr)) - IP = ++I->getIterator(); - return new LoadInst(Ptr, "L", &*IP); -} - -static bool isCompatibleReplacement(const Instruction *I, const Use &Operand, - const Value *Replacement) { - if (Operand->getType() != Replacement->getType()) - return false; - switch (I->getOpcode()) { - case Instruction::GetElementPtr: - case Instruction::ExtractElement: - case Instruction::ExtractValue: - // TODO: We could potentially validate these, but for now just leave indices - // alone. - if (Operand.getOperandNo() > 1) - return false; - break; - case Instruction::InsertValue: - case Instruction::InsertElement: - if (Operand.getOperandNo() > 2) - return false; - break; - default: - break; - } - return true; -} - -void RandomIRBuilder::connectToSink(BasicBlock &BB, - ArrayRef<Instruction *> Insts, Value *V) { - auto RS = makeSampler<Use *>(Rand); - for (auto &I : Insts) { - if (isa<IntrinsicInst>(I)) - // TODO: Replacing operands of intrinsics would be interesting, but - // there's no easy way to verify that a given replacement is valid given - // that intrinsics can impose arbitrary constraints. - continue; - for (Use &U : I->operands()) - if (isCompatibleReplacement(I, U, V)) - RS.sample(&U, 1); - } - // Also consider choosing no sink, meaning we want a new one. - RS.sample(nullptr, /*Weight=*/1); - - if (Use *Sink = RS.getSelection()) { - User *U = Sink->getUser(); - unsigned OpNo = Sink->getOperandNo(); - U->setOperand(OpNo, V); - return; - } - newSink(BB, Insts, V); -} - -void RandomIRBuilder::newSink(BasicBlock &BB, ArrayRef<Instruction *> Insts, - Value *V) { - Value *Ptr = findPointer(BB, Insts, {V}, matchFirstType()); - if (!Ptr) { - if (uniform(Rand, 0, 1)) - Ptr = new AllocaInst(V->getType(), 0, "A", &*BB.getFirstInsertionPt()); - else - Ptr = UndefValue::get(PointerType::get(V->getType(), 0)); - } - - new StoreInst(V, Ptr, Insts.back()); -} - -Value *RandomIRBuilder::findPointer(BasicBlock &BB, - ArrayRef<Instruction *> Insts, - ArrayRef<Value *> Srcs, SourcePred Pred) { - auto IsMatchingPtr = [&Srcs, &Pred](Instruction *Inst) { - if (auto PtrTy = dyn_cast<PointerType>(Inst->getType())) - // TODO: Check if this is horribly expensive. - return Pred.matches(Srcs, UndefValue::get(PtrTy->getElementType())); - return false; - }; - if (auto RS = makeSampler(Rand, make_filter_range(Insts, IsMatchingPtr))) - return RS.getSelection(); - return nullptr; -} |