Mercurial > hg > CbC > CbC_llvm
view lib/FuzzMutate/RandomIRBuilder.cpp @ 124:4fa72497ed5d
fix
author | mir3636 |
---|---|
date | Thu, 30 Nov 2017 20:04:56 +0900 |
parents | 803732b1fca8 |
children | 3a76565eade5 |
line wrap: on
line source
//===-- 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; }