You've already forked linux-packaging-mono
Imported Upstream version 5.18.0.207
Former-commit-id: 3b152f462918d427ce18620a2cbe4f8b79650449
This commit is contained in:
parent
8e12397d70
commit
eb85e2fc17
156
external/llvm/lib/FuzzMutate/RandomIRBuilder.cpp
vendored
156
external/llvm/lib/FuzzMutate/RandomIRBuilder.cpp
vendored
@ -1,156 +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"
|
||||
|
||||
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 (isa<TerminatorInst>(Inst))
|
||||
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;
|
||||
}
|
Reference in New Issue
Block a user