Path: blob/main/contrib/llvm-project/llvm/lib/FuzzMutate/IRMutator.cpp
35233 views
//===-- IRMutator.cpp -----------------------------------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include "llvm/FuzzMutate/IRMutator.h"9#include "llvm/ADT/STLExtras.h"10#include "llvm/ADT/SmallSet.h"11#include "llvm/Analysis/TargetLibraryInfo.h"12#include "llvm/Bitcode/BitcodeReader.h"13#include "llvm/Bitcode/BitcodeWriter.h"14#include "llvm/FuzzMutate/Operations.h"15#include "llvm/FuzzMutate/Random.h"16#include "llvm/FuzzMutate/RandomIRBuilder.h"17#include "llvm/IR/BasicBlock.h"18#include "llvm/IR/FMF.h"19#include "llvm/IR/Function.h"20#include "llvm/IR/InstIterator.h"21#include "llvm/IR/Instructions.h"22#include "llvm/IR/Module.h"23#include "llvm/IR/Operator.h"24#include "llvm/IR/PassInstrumentation.h"25#include "llvm/IR/Verifier.h"26#include "llvm/Support/MemoryBuffer.h"27#include "llvm/Support/SourceMgr.h"28#include "llvm/Transforms/Scalar/DCE.h"29#include "llvm/Transforms/Utils/BasicBlockUtils.h"30#include <map>31#include <optional>3233using namespace llvm;3435void IRMutationStrategy::mutate(Module &M, RandomIRBuilder &IB) {36auto RS = makeSampler<Function *>(IB.Rand);37for (Function &F : M)38if (!F.isDeclaration())39RS.sample(&F, /*Weight=*/1);4041while (RS.totalWeight() < IB.MinFunctionNum) {42Function *F = IB.createFunctionDefinition(M);43RS.sample(F, /*Weight=*/1);44}45mutate(*RS.getSelection(), IB);46}4748void IRMutationStrategy::mutate(Function &F, RandomIRBuilder &IB) {49auto Range = make_filter_range(make_pointer_range(F),50[](BasicBlock *BB) { return !BB->isEHPad(); });5152mutate(*makeSampler(IB.Rand, Range).getSelection(), IB);53}5455void IRMutationStrategy::mutate(BasicBlock &BB, RandomIRBuilder &IB) {56mutate(*makeSampler(IB.Rand, make_pointer_range(BB)).getSelection(), IB);57}5859size_t llvm::IRMutator::getModuleSize(const Module &M) {60return M.getInstructionCount() + M.size() + M.global_size() + M.alias_size();61}6263void IRMutator::mutateModule(Module &M, int Seed, size_t MaxSize) {64std::vector<Type *> Types;65for (const auto &Getter : AllowedTypes)66Types.push_back(Getter(M.getContext()));67RandomIRBuilder IB(Seed, Types);6869size_t CurSize = IRMutator::getModuleSize(M);70auto RS = makeSampler<IRMutationStrategy *>(IB.Rand);71for (const auto &Strategy : Strategies)72RS.sample(Strategy.get(),73Strategy->getWeight(CurSize, MaxSize, RS.totalWeight()));74if (RS.totalWeight() == 0)75return;76auto Strategy = RS.getSelection();7778Strategy->mutate(M, IB);79}8081static void eliminateDeadCode(Function &F) {82FunctionPassManager FPM;83FPM.addPass(DCEPass());84FunctionAnalysisManager FAM;85FAM.registerPass([&] { return TargetLibraryAnalysis(); });86FAM.registerPass([&] { return PassInstrumentationAnalysis(); });87FPM.run(F, FAM);88}8990void InjectorIRStrategy::mutate(Function &F, RandomIRBuilder &IB) {91IRMutationStrategy::mutate(F, IB);92eliminateDeadCode(F);93}9495std::vector<fuzzerop::OpDescriptor> InjectorIRStrategy::getDefaultOps() {96std::vector<fuzzerop::OpDescriptor> Ops;97describeFuzzerIntOps(Ops);98describeFuzzerFloatOps(Ops);99describeFuzzerControlFlowOps(Ops);100describeFuzzerPointerOps(Ops);101describeFuzzerAggregateOps(Ops);102describeFuzzerVectorOps(Ops);103return Ops;104}105106std::optional<fuzzerop::OpDescriptor>107InjectorIRStrategy::chooseOperation(Value *Src, RandomIRBuilder &IB) {108auto OpMatchesPred = [&Src](fuzzerop::OpDescriptor &Op) {109return Op.SourcePreds[0].matches({}, Src);110};111auto RS = makeSampler(IB.Rand, make_filter_range(Operations, OpMatchesPred));112if (RS.isEmpty())113return std::nullopt;114return *RS;115}116117static inline iterator_range<BasicBlock::iterator>118getInsertionRange(BasicBlock &BB) {119auto End = BB.getTerminatingMustTailCall() ? std::prev(BB.end()) : BB.end();120return make_range(BB.getFirstInsertionPt(), End);121}122123void InjectorIRStrategy::mutate(BasicBlock &BB, RandomIRBuilder &IB) {124SmallVector<Instruction *, 32> Insts;125for (Instruction &I : getInsertionRange(BB))126Insts.push_back(&I);127if (Insts.size() < 1)128return;129130// Choose an insertion point for our new instruction.131size_t IP = uniform<size_t>(IB.Rand, 0, Insts.size() - 1);132133auto InstsBefore = ArrayRef(Insts).slice(0, IP);134auto InstsAfter = ArrayRef(Insts).slice(IP);135136// Choose a source, which will be used to constrain the operation selection.137SmallVector<Value *, 2> Srcs;138Srcs.push_back(IB.findOrCreateSource(BB, InstsBefore));139140// Choose an operation that's constrained to be valid for the type of the141// source, collect any other sources it needs, and then build it.142auto OpDesc = chooseOperation(Srcs[0], IB);143// Bail if no operation was found144if (!OpDesc)145return;146147for (const auto &Pred : ArrayRef(OpDesc->SourcePreds).slice(1))148Srcs.push_back(IB.findOrCreateSource(BB, InstsBefore, Srcs, Pred));149150if (Value *Op = OpDesc->BuilderFunc(Srcs, Insts[IP])) {151// Find a sink and wire up the results of the operation.152IB.connectToSink(BB, InstsAfter, Op);153}154}155156uint64_t InstDeleterIRStrategy::getWeight(size_t CurrentSize, size_t MaxSize,157uint64_t CurrentWeight) {158// If we have less than 200 bytes, panic and try to always delete.159if (CurrentSize > MaxSize - 200)160return CurrentWeight ? CurrentWeight * 100 : 1;161// Draw a line starting from when we only have 1k left and increasing linearly162// to double the current weight.163int64_t Line = (-2 * static_cast<int64_t>(CurrentWeight)) *164(static_cast<int64_t>(MaxSize) -165static_cast<int64_t>(CurrentSize) - 1000) /1661000;167// Clamp negative weights to zero.168if (Line < 0)169return 0;170return Line;171}172173void InstDeleterIRStrategy::mutate(Function &F, RandomIRBuilder &IB) {174auto RS = makeSampler<Instruction *>(IB.Rand);175for (Instruction &Inst : instructions(F)) {176// TODO: We can't handle these instructions.177if (Inst.isTerminator() || Inst.isEHPad() || Inst.isSwiftError() ||178isa<PHINode>(Inst))179continue;180181RS.sample(&Inst, /*Weight=*/1);182}183if (RS.isEmpty())184return;185186// Delete the instruction.187mutate(*RS.getSelection(), IB);188// Clean up any dead code that's left over after removing the instruction.189eliminateDeadCode(F);190}191192void InstDeleterIRStrategy::mutate(Instruction &Inst, RandomIRBuilder &IB) {193assert(!Inst.isTerminator() && "Deleting terminators invalidates CFG");194195if (Inst.getType()->isVoidTy()) {196// Instructions with void type (ie, store) have no uses to worry about. Just197// erase it and move on.198Inst.eraseFromParent();199return;200}201202// Otherwise we need to find some other value with the right type to keep the203// users happy.204auto Pred = fuzzerop::onlyType(Inst.getType());205auto RS = makeSampler<Value *>(IB.Rand);206SmallVector<Instruction *, 32> InstsBefore;207BasicBlock *BB = Inst.getParent();208for (auto I = BB->getFirstInsertionPt(), E = Inst.getIterator(); I != E;209++I) {210if (Pred.matches({}, &*I))211RS.sample(&*I, /*Weight=*/1);212InstsBefore.push_back(&*I);213}214if (!RS)215RS.sample(IB.newSource(*BB, InstsBefore, {}, Pred), /*Weight=*/1);216217Inst.replaceAllUsesWith(RS.getSelection());218Inst.eraseFromParent();219}220221void InstModificationIRStrategy::mutate(Instruction &Inst,222RandomIRBuilder &IB) {223SmallVector<std::function<void()>, 8> Modifications;224CmpInst *CI = nullptr;225GetElementPtrInst *GEP = nullptr;226switch (Inst.getOpcode()) {227default:228break;229// Add nsw, nuw flag230case Instruction::Add:231case Instruction::Mul:232case Instruction::Sub:233case Instruction::Shl:234Modifications.push_back(235[&Inst]() { Inst.setHasNoSignedWrap(!Inst.hasNoSignedWrap()); });236Modifications.push_back(237[&Inst]() { Inst.setHasNoUnsignedWrap(!Inst.hasNoUnsignedWrap()); });238break;239case Instruction::ICmp:240CI = cast<ICmpInst>(&Inst);241for (unsigned p = CmpInst::FIRST_ICMP_PREDICATE;242p <= CmpInst::LAST_ICMP_PREDICATE; p++) {243Modifications.push_back(244[CI, p]() { CI->setPredicate(static_cast<CmpInst::Predicate>(p)); });245}246break;247// Add inbound flag.248case Instruction::GetElementPtr:249GEP = cast<GetElementPtrInst>(&Inst);250Modifications.push_back(251[GEP]() { GEP->setIsInBounds(!GEP->isInBounds()); });252break;253// Add exact flag.254case Instruction::UDiv:255case Instruction::SDiv:256case Instruction::LShr:257case Instruction::AShr:258Modifications.push_back([&Inst] { Inst.setIsExact(!Inst.isExact()); });259break;260261case Instruction::FCmp:262CI = cast<FCmpInst>(&Inst);263for (unsigned p = CmpInst::FIRST_FCMP_PREDICATE;264p <= CmpInst::LAST_FCMP_PREDICATE; p++) {265Modifications.push_back(266[CI, p]() { CI->setPredicate(static_cast<CmpInst::Predicate>(p)); });267}268break;269}270271// Add fast math flag if possible.272if (isa<FPMathOperator>(&Inst)) {273// Try setting everything unless they are already on.274Modifications.push_back(275[&Inst] { Inst.setFast(!Inst.getFastMathFlags().all()); });276// Try unsetting everything unless they are already off.277Modifications.push_back(278[&Inst] { Inst.setFast(!Inst.getFastMathFlags().none()); });279// Individual setting by flipping the bit280Modifications.push_back(281[&Inst] { Inst.setHasAllowReassoc(!Inst.hasAllowReassoc()); });282Modifications.push_back([&Inst] { Inst.setHasNoNaNs(!Inst.hasNoNaNs()); });283Modifications.push_back([&Inst] { Inst.setHasNoInfs(!Inst.hasNoInfs()); });284Modifications.push_back(285[&Inst] { Inst.setHasNoSignedZeros(!Inst.hasNoSignedZeros()); });286Modifications.push_back(287[&Inst] { Inst.setHasAllowReciprocal(!Inst.hasAllowReciprocal()); });288Modifications.push_back(289[&Inst] { Inst.setHasAllowContract(!Inst.hasAllowContract()); });290Modifications.push_back(291[&Inst] { Inst.setHasApproxFunc(!Inst.hasApproxFunc()); });292}293294// Randomly switch operands of instructions295std::pair<int, int> NoneItem({-1, -1}), ShuffleItems(NoneItem);296switch (Inst.getOpcode()) {297case Instruction::SDiv:298case Instruction::UDiv:299case Instruction::SRem:300case Instruction::URem:301case Instruction::FDiv:302case Instruction::FRem: {303// Verify that the after shuffle the second operand is not304// constant 0.305Value *Operand = Inst.getOperand(0);306if (Constant *C = dyn_cast<Constant>(Operand)) {307if (!C->isZeroValue()) {308ShuffleItems = {0, 1};309}310}311break;312}313case Instruction::Select:314ShuffleItems = {1, 2};315break;316case Instruction::Add:317case Instruction::Sub:318case Instruction::Mul:319case Instruction::Shl:320case Instruction::LShr:321case Instruction::AShr:322case Instruction::And:323case Instruction::Or:324case Instruction::Xor:325case Instruction::FAdd:326case Instruction::FSub:327case Instruction::FMul:328case Instruction::ICmp:329case Instruction::FCmp:330case Instruction::ShuffleVector:331ShuffleItems = {0, 1};332break;333}334if (ShuffleItems != NoneItem) {335Modifications.push_back([&Inst, &ShuffleItems]() {336Value *Op0 = Inst.getOperand(ShuffleItems.first);337Inst.setOperand(ShuffleItems.first, Inst.getOperand(ShuffleItems.second));338Inst.setOperand(ShuffleItems.second, Op0);339});340}341342auto RS = makeSampler(IB.Rand, Modifications);343if (RS)344RS.getSelection()();345}346347/// Return a case value that is not already taken to make sure we don't have two348/// cases with same value.349static uint64_t getUniqueCaseValue(SmallSet<uint64_t, 4> &CasesTaken,350uint64_t MaxValue, RandomIRBuilder &IB) {351uint64_t tmp;352do {353tmp = uniform<uint64_t>(IB.Rand, 0, MaxValue);354} while (CasesTaken.count(tmp) != 0);355CasesTaken.insert(tmp);356return tmp;357}358359void InsertFunctionStrategy::mutate(BasicBlock &BB, RandomIRBuilder &IB) {360Module *M = BB.getParent()->getParent();361// If nullptr is selected, we will create a new function declaration.362SmallVector<Function *, 32> Functions({nullptr});363for (Function &F : M->functions()) {364Functions.push_back(&F);365}366367auto RS = makeSampler(IB.Rand, Functions);368Function *F = RS.getSelection();369// Some functions accept metadata type or token type as arguments.370// We don't call those functions for now.371// For example, `@llvm.dbg.declare(metadata, metadata, metadata)`372// https://llvm.org/docs/SourceLevelDebugging.html#llvm-dbg-declare373auto IsUnsupportedTy = [](Type *T) {374return T->isMetadataTy() || T->isTokenTy();375};376if (!F || IsUnsupportedTy(F->getReturnType()) ||377any_of(F->getFunctionType()->params(), IsUnsupportedTy)) {378F = IB.createFunctionDeclaration(*M);379}380381FunctionType *FTy = F->getFunctionType();382SmallVector<fuzzerop::SourcePred, 2> SourcePreds;383if (!F->arg_empty()) {384for (Type *ArgTy : FTy->params()) {385SourcePreds.push_back(fuzzerop::onlyType(ArgTy));386}387}388bool isRetVoid = (F->getReturnType() == Type::getVoidTy(M->getContext()));389auto BuilderFunc = [FTy, F, isRetVoid](ArrayRef<Value *> Srcs,390Instruction *Inst) {391StringRef Name = isRetVoid ? nullptr : "C";392CallInst *Call = CallInst::Create(FTy, F, Srcs, Name, Inst);393// Don't return this call inst if it return void as it can't be sinked.394return isRetVoid ? nullptr : Call;395};396397SmallVector<Instruction *, 32> Insts;398for (Instruction &I : getInsertionRange(BB))399Insts.push_back(&I);400if (Insts.size() < 1)401return;402403// Choose an insertion point for our new call instruction.404uint64_t IP = uniform<uint64_t>(IB.Rand, 0, Insts.size() - 1);405406auto InstsBefore = ArrayRef(Insts).slice(0, IP);407auto InstsAfter = ArrayRef(Insts).slice(IP);408409// Choose a source, which will be used to constrain the operation selection.410SmallVector<Value *, 2> Srcs;411412for (const auto &Pred : ArrayRef(SourcePreds)) {413Srcs.push_back(IB.findOrCreateSource(BB, InstsBefore, Srcs, Pred));414}415416if (Value *Op = BuilderFunc(Srcs, Insts[IP])) {417// Find a sink and wire up the results of the operation.418IB.connectToSink(BB, InstsAfter, Op);419}420}421422void InsertCFGStrategy::mutate(BasicBlock &BB, RandomIRBuilder &IB) {423SmallVector<Instruction *, 32> Insts;424for (Instruction &I : getInsertionRange(BB))425Insts.push_back(&I);426if (Insts.size() < 1)427return;428429// Choose a point where we split the block.430uint64_t IP = uniform<uint64_t>(IB.Rand, 0, Insts.size() - 1);431auto InstsBeforeSplit = ArrayRef(Insts).slice(0, IP);432433// `Sink` inherits Blocks' terminator, `Source` will have a BranchInst434// directly jumps to `Sink`. Here, we have to create a new terminator for435// `Source`.436BasicBlock *Block = Insts[IP]->getParent();437BasicBlock *Source = Block;438BasicBlock *Sink = Block->splitBasicBlock(Insts[IP], "BB");439440Function *F = BB.getParent();441LLVMContext &C = F->getParent()->getContext();442// A coin decides if it is branch or switch443if (uniform<uint64_t>(IB.Rand, 0, 1)) {444// Branch445BasicBlock *IfTrue = BasicBlock::Create(C, "T", F);446BasicBlock *IfFalse = BasicBlock::Create(C, "F", F);447Value *Cond =448IB.findOrCreateSource(*Source, InstsBeforeSplit, {},449fuzzerop::onlyType(Type::getInt1Ty(C)), false);450BranchInst *Branch = BranchInst::Create(IfTrue, IfFalse, Cond);451// Remove the old terminator.452ReplaceInstWithInst(Source->getTerminator(), Branch);453// Connect these blocks to `Sink`454connectBlocksToSink({IfTrue, IfFalse}, Sink, IB);455} else {456// Switch457// Determine Integer type, it IS possible we use a boolean to switch.458auto RS =459makeSampler(IB.Rand, make_filter_range(IB.KnownTypes, [](Type *Ty) {460return Ty->isIntegerTy();461}));462assert(RS && "There is no integer type in all allowed types, is the "463"setting correct?");464Type *Ty = RS.getSelection();465IntegerType *IntTy = cast<IntegerType>(Ty);466467uint64_t BitSize = IntTy->getBitWidth();468uint64_t MaxCaseVal =469(BitSize >= 64) ? (uint64_t)-1 : ((uint64_t)1 << BitSize) - 1;470// Create Switch inst in Block471Value *Cond = IB.findOrCreateSource(*Source, InstsBeforeSplit, {},472fuzzerop::onlyType(IntTy), false);473BasicBlock *DefaultBlock = BasicBlock::Create(C, "SW_D", F);474uint64_t NumCases = uniform<uint64_t>(IB.Rand, 1, MaxNumCases);475NumCases = (NumCases > MaxCaseVal) ? MaxCaseVal + 1 : NumCases;476SwitchInst *Switch = SwitchInst::Create(Cond, DefaultBlock, NumCases);477// Remove the old terminator.478ReplaceInstWithInst(Source->getTerminator(), Switch);479480// Create blocks, for each block assign a case value.481SmallVector<BasicBlock *, 4> Blocks({DefaultBlock});482SmallSet<uint64_t, 4> CasesTaken;483for (uint64_t i = 0; i < NumCases; i++) {484uint64_t CaseVal = getUniqueCaseValue(CasesTaken, MaxCaseVal, IB);485BasicBlock *CaseBlock = BasicBlock::Create(C, "SW_C", F);486ConstantInt *OnValue = ConstantInt::get(IntTy, CaseVal);487Switch->addCase(OnValue, CaseBlock);488Blocks.push_back(CaseBlock);489}490491// Connect these blocks to `Sink`492connectBlocksToSink(Blocks, Sink, IB);493}494}495496/// The caller has to guarantee that these blocks are "empty", i.e. it doesn't497/// even have terminator.498void InsertCFGStrategy::connectBlocksToSink(ArrayRef<BasicBlock *> Blocks,499BasicBlock *Sink,500RandomIRBuilder &IB) {501uint64_t DirectSinkIdx = uniform<uint64_t>(IB.Rand, 0, Blocks.size() - 1);502for (uint64_t i = 0; i < Blocks.size(); i++) {503// We have at least one block that directly goes to sink.504CFGToSink ToSink = (i == DirectSinkIdx)505? CFGToSink::DirectSink506: static_cast<CFGToSink>(uniform<uint64_t>(507IB.Rand, 0, CFGToSink::EndOfCFGToLink - 1));508BasicBlock *BB = Blocks[i];509Function *F = BB->getParent();510LLVMContext &C = F->getParent()->getContext();511switch (ToSink) {512case CFGToSink::Return: {513Type *RetTy = F->getReturnType();514Value *RetValue = nullptr;515if (!RetTy->isVoidTy())516RetValue =517IB.findOrCreateSource(*BB, {}, {}, fuzzerop::onlyType(RetTy));518ReturnInst::Create(C, RetValue, BB);519break;520}521case CFGToSink::DirectSink: {522BranchInst::Create(Sink, BB);523break;524}525case CFGToSink::SinkOrSelfLoop: {526SmallVector<BasicBlock *, 2> Branches({Sink, BB});527// A coin decides which block is true branch.528uint64_t coin = uniform<uint64_t>(IB.Rand, 0, 1);529Value *Cond = IB.findOrCreateSource(530*BB, {}, {}, fuzzerop::onlyType(Type::getInt1Ty(C)), false);531BranchInst::Create(Branches[coin], Branches[1 - coin], Cond, BB);532break;533}534case CFGToSink::EndOfCFGToLink:535llvm_unreachable("EndOfCFGToLink executed, something's wrong.");536}537}538}539540void InsertPHIStrategy::mutate(BasicBlock &BB, RandomIRBuilder &IB) {541// Can't insert PHI node to entry node.542if (&BB == &BB.getParent()->getEntryBlock())543return;544Type *Ty = IB.randomType();545PHINode *PHI = PHINode::Create(Ty, llvm::pred_size(&BB), "", &BB.front());546547// Use a map to make sure the same incoming basic block has the same value.548DenseMap<BasicBlock *, Value *> IncomingValues;549for (BasicBlock *Pred : predecessors(&BB)) {550Value *Src = IncomingValues[Pred];551// If `Pred` is not in the map yet, we'll get a nullptr.552if (!Src) {553SmallVector<Instruction *, 32> Insts;554for (auto I = Pred->begin(); I != Pred->end(); ++I)555Insts.push_back(&*I);556// There is no need to inform IB what previously used values are if we are557// using `onlyType`558Src = IB.findOrCreateSource(*Pred, Insts, {}, fuzzerop::onlyType(Ty));559IncomingValues[Pred] = Src;560}561PHI->addIncoming(Src, Pred);562}563SmallVector<Instruction *, 32> InstsAfter;564for (Instruction &I : getInsertionRange(BB))565InstsAfter.push_back(&I);566IB.connectToSink(BB, InstsAfter, PHI);567}568569void SinkInstructionStrategy::mutate(Function &F, RandomIRBuilder &IB) {570for (BasicBlock &BB : F) {571this->mutate(BB, IB);572}573}574void SinkInstructionStrategy::mutate(BasicBlock &BB, RandomIRBuilder &IB) {575SmallVector<Instruction *, 32> Insts;576for (Instruction &I : getInsertionRange(BB))577Insts.push_back(&I);578if (Insts.size() < 1)579return;580// Choose an Instruction to mutate.581uint64_t Idx = uniform<uint64_t>(IB.Rand, 0, Insts.size() - 1);582Instruction *Inst = Insts[Idx];583// `Idx + 1` so we don't sink to ourselves.584auto InstsAfter = ArrayRef(Insts).slice(Idx + 1);585Type *Ty = Inst->getType();586// Don't sink terminators, void function calls, token, etc.587if (!Ty->isVoidTy() && !Ty->isTokenTy())588// Find a new sink and wire up the results of the operation.589IB.connectToSink(BB, InstsAfter, Inst);590}591592void ShuffleBlockStrategy::mutate(BasicBlock &BB, RandomIRBuilder &IB) {593// A deterministic alternative to SmallPtrSet with the same lookup594// performance.595std::map<size_t, Instruction *> AliveInsts;596std::map<Instruction *, size_t> AliveInstsLookup;597size_t InsertIdx = 0;598for (auto &I : make_early_inc_range(make_range(599BB.getFirstInsertionPt(), BB.getTerminator()->getIterator()))) {600// First gather all instructions that can be shuffled. Don't take601// terminator.602AliveInsts.insert({InsertIdx, &I});603AliveInstsLookup.insert({&I, InsertIdx++});604// Then remove these instructions from the block605I.removeFromParent();606}607608// Shuffle these instructions using topological sort.609// Returns false if all current instruction's dependencies in this block have610// been shuffled. If so, this instruction can be shuffled too.611auto hasAliveParent = [&AliveInsts, &AliveInstsLookup](size_t Index) {612for (Value *O : AliveInsts[Index]->operands()) {613Instruction *P = dyn_cast<Instruction>(O);614if (P && AliveInstsLookup.count(P))615return true;616}617return false;618};619// Get all alive instructions that depend on the current instruction.620// Takes Instruction* instead of index because the instruction is already621// shuffled.622auto getAliveChildren = [&AliveInstsLookup](Instruction *I) {623SmallSetVector<size_t, 8> Children;624for (Value *U : I->users()) {625Instruction *P = dyn_cast<Instruction>(U);626if (P && AliveInstsLookup.count(P))627Children.insert(AliveInstsLookup[P]);628}629return Children;630};631SmallSet<size_t, 8> RootIndices;632SmallVector<Instruction *, 8> Insts;633for (const auto &[Index, Inst] : AliveInsts) {634if (!hasAliveParent(Index))635RootIndices.insert(Index);636}637// Topological sort by randomly selecting a node without a parent, or root.638while (!RootIndices.empty()) {639auto RS = makeSampler<size_t>(IB.Rand);640for (size_t RootIdx : RootIndices)641RS.sample(RootIdx, 1);642size_t RootIdx = RS.getSelection();643644RootIndices.erase(RootIdx);645Instruction *Root = AliveInsts[RootIdx];646AliveInsts.erase(RootIdx);647AliveInstsLookup.erase(Root);648Insts.push_back(Root);649650for (size_t Child : getAliveChildren(Root)) {651if (!hasAliveParent(Child)) {652RootIndices.insert(Child);653}654}655}656657Instruction *Terminator = BB.getTerminator();658// Then put instructions back.659for (Instruction *I : Insts) {660I->insertBefore(Terminator);661}662}663664std::unique_ptr<Module> llvm::parseModule(const uint8_t *Data, size_t Size,665LLVMContext &Context) {666667if (Size <= 1)668// We get bogus data given an empty corpus - just create a new module.669return std::make_unique<Module>("M", Context);670671auto Buffer = MemoryBuffer::getMemBuffer(672StringRef(reinterpret_cast<const char *>(Data), Size), "Fuzzer input",673/*RequiresNullTerminator=*/false);674675SMDiagnostic Err;676auto M = parseBitcodeFile(Buffer->getMemBufferRef(), Context);677if (Error E = M.takeError()) {678errs() << toString(std::move(E)) << "\n";679return nullptr;680}681return std::move(M.get());682}683684size_t llvm::writeModule(const Module &M, uint8_t *Dest, size_t MaxSize) {685std::string Buf;686{687raw_string_ostream OS(Buf);688WriteBitcodeToFile(M, OS);689}690if (Buf.size() > MaxSize)691return 0;692memcpy(Dest, Buf.data(), Buf.size());693return Buf.size();694}695696std::unique_ptr<Module> llvm::parseAndVerify(const uint8_t *Data, size_t Size,697LLVMContext &Context) {698auto M = parseModule(Data, Size, Context);699if (!M || verifyModule(*M, &errs()))700return nullptr;701702return M;703}704705706