|  | //===-- RandomIRBuilder.cpp -----------------------------------------------===// | 
|  | // | 
|  | // 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 | 
|  | // | 
|  | //===----------------------------------------------------------------------===// | 
|  |  | 
|  | #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" | 
|  |  | 
|  | 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)); | 
|  |  | 
|  | // If we can find a pointer to load from, use it half the time. | 
|  | Value *Ptr = findPointer(BB, Insts, Srcs, Pred); | 
|  | if (Ptr) { | 
|  | // Create load from the chosen pointer | 
|  | auto IP = BB.getFirstInsertionPt(); | 
|  | if (auto *I = dyn_cast<Instruction>(Ptr)) { | 
|  | IP = ++I->getIterator(); | 
|  | assert(IP != BB.end() && "guaranteed by the findPointer"); | 
|  | } | 
|  | auto *NewLoad = new LoadInst(Ptr, "L", &*IP); | 
|  |  | 
|  | // Only sample this load if it really matches the descriptor | 
|  | if (Pred.matches(Srcs, NewLoad)) | 
|  | RS.sample(NewLoad, RS.totalWeight()); | 
|  | else | 
|  | NewLoad->eraseFromParent(); | 
|  | } | 
|  |  | 
|  | assert(!RS.isEmpty() && "Failed to generate sources"); | 
|  | return RS.getSelection(); | 
|  | } | 
|  |  | 
|  | 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: | 
|  | case Instruction::ShuffleVector: | 
|  | 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) { | 
|  | // Invoke instructions sometimes produce valid pointers but currently | 
|  | // we can't insert loads or stores from them | 
|  | if (Inst->isTerminator()) | 
|  | return false; | 
|  |  | 
|  | if (auto PtrTy = dyn_cast<PointerType>(Inst->getType())) { | 
|  | // We can never generate loads from non first class or non sized types | 
|  | if (!PtrTy->getElementType()->isSized() || | 
|  | !PtrTy->getElementType()->isFirstClassType()) | 
|  | return false; | 
|  |  | 
|  | // 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; | 
|  | } |