36 auto RS = makeSampler<Function *>(IB.Rand);
38 if (!
F.isDeclaration())
41 while (RS.totalWeight() < IB.MinFunctionNum) {
42 Function *
F = IB.createFunctionDefinition(M);
45 mutate(*RS.getSelection(), IB);
60 return M.getInstructionCount() + M.size() + M.global_size() + M.alias_size();
64 std::vector<Type *> Types;
65 for (
const auto &Getter : AllowedTypes)
66 Types.push_back(Getter(M.getContext()));
70 auto RS = makeSampler<IRMutationStrategy *>(IB.Rand);
71 for (
const auto &Strategy : Strategies)
72 RS.sample(Strategy.get(),
73 Strategy->getWeight(CurSize, MaxSize, RS.totalWeight()));
74 if (RS.totalWeight() == 0)
76 auto Strategy = RS.getSelection();
78 Strategy->mutate(M, IB);
96 std::vector<fuzzerop::OpDescriptor> Ops;
106std::optional<fuzzerop::OpDescriptor>
109 return Op.SourcePreds[0].matches({}, Src);
127 if (Insts.
size() < 1)
131 size_t IP = uniform<size_t>(IB.Rand, 0, Insts.
size() - 1);
138 Srcs.
push_back(IB.findOrCreateSource(BB, InstsBefore));
142 auto OpDesc = chooseOperation(Srcs[0], IB);
147 for (
const auto &Pred :
ArrayRef(OpDesc->SourcePreds).
slice(1))
148 Srcs.
push_back(IB.findOrCreateSource(BB, InstsBefore, Srcs, Pred));
150 if (
Value *
Op = OpDesc->BuilderFunc(Srcs, Insts[IP])) {
152 IB.connectToSink(BB, InstsAfter,
Op);
159 if (CurrentSize > MaxSize - 200)
160 return CurrentWeight ? CurrentWeight * 100 : 1;
163 int64_t Line = (-2 *
static_cast<int64_t
>(CurrentWeight)) *
164 (
static_cast<int64_t
>(MaxSize) -
165 static_cast<int64_t
>(CurrentSize) - 1000) /
174 auto RS = makeSampler<Instruction *>(IB.Rand);
177 if (Inst.isTerminator() || Inst.isEHPad() || Inst.isSwiftError() ||
187 mutate(*RS.getSelection(), IB);
205 auto RS = makeSampler<Value *>(IB.Rand);
210 if (Pred.matches({}, &*
I))
215 RS.sample(IB.newSource(*BB, InstsBefore, {}, Pred), 1);
223 SmallVector<std::function<void()>, 8> Modifications;
230 case Instruction::Add:
231 case Instruction::Mul:
232 case Instruction::Sub:
233 case Instruction::Shl:
234 Modifications.push_back(
236 Modifications.push_back(
239 case Instruction::ICmp:
240 CI = cast<ICmpInst>(&Inst);
243 Modifications.push_back(
248 case Instruction::GetElementPtr:
249 GEP = cast<GetElementPtrInst>(&Inst);
250 Modifications.push_back(
251 [
GEP]() {
GEP->setIsInBounds(!
GEP->isInBounds()); });
254 case Instruction::UDiv:
255 case Instruction::SDiv:
256 case Instruction::LShr:
257 case Instruction::AShr:
261 case Instruction::FCmp:
262 CI = cast<FCmpInst>(&Inst);
265 Modifications.push_back(
272 if (isa<FPMathOperator>(&Inst)) {
274 Modifications.push_back(
277 Modifications.push_back(
280 Modifications.push_back(
284 Modifications.push_back(
286 Modifications.push_back(
288 Modifications.push_back(
290 Modifications.push_back(
295 std::pair<int, int> NoneItem({-1, -1}), ShuffleItems(NoneItem);
297 case Instruction::SDiv:
298 case Instruction::UDiv:
299 case Instruction::SRem:
300 case Instruction::URem:
301 case Instruction::FDiv:
302 case Instruction::FRem: {
306 if (
Constant *
C = dyn_cast<Constant>(Operand)) {
307 if (!
C->isZeroValue()) {
308 ShuffleItems = {0, 1};
313 case Instruction::Select:
314 ShuffleItems = {1, 2};
316 case Instruction::Add:
317 case Instruction::Sub:
318 case Instruction::Mul:
319 case Instruction::Shl:
320 case Instruction::LShr:
321 case Instruction::AShr:
322 case Instruction::And:
323 case Instruction::Or:
324 case Instruction::Xor:
325 case Instruction::FAdd:
326 case Instruction::FSub:
327 case Instruction::FMul:
328 case Instruction::ICmp:
329 case Instruction::FCmp:
330 case Instruction::ShuffleVector:
331 ShuffleItems = {0, 1};
334 if (ShuffleItems != NoneItem) {
335 Modifications.push_back([&Inst, &ShuffleItems]() {
353 tmp = uniform<uint64_t>(IB.Rand, 0, MaxValue);
354 }
while (CasesTaken.
count(tmp) != 0);
373 auto IsUnsupportedTy = [](
Type *
T) {
374 return T->isMetadataTy() ||
T->isTokenTy();
376 if (!
F || IsUnsupportedTy(
F->getReturnType()) ||
377 any_of(
F->getFunctionType()->params(), IsUnsupportedTy)) {
378 F = IB.createFunctionDeclaration(*M);
383 if (!
F->arg_empty()) {
394 return isRetVoid ? nullptr : Call;
400 if (Insts.
size() < 1)
404 uint64_t IP = uniform<uint64_t>(IB.Rand, 0, Insts.
size() - 1);
412 for (
const auto &Pred :
ArrayRef(SourcePreds)) {
413 Srcs.
push_back(IB.findOrCreateSource(BB, InstsBefore, Srcs, Pred));
416 if (
Value *
Op = BuilderFunc(Srcs, Insts[IP])) {
418 IB.connectToSink(BB, InstsAfter,
Op);
426 if (Insts.
size() < 1)
430 uint64_t IP = uniform<uint64_t>(IB.Rand, 0, Insts.
size() - 1);
443 if (uniform<uint64_t>(IB.Rand, 0, 1)) {
448 IB.findOrCreateSource(*Source, InstsBeforeSplit, {},
454 connectBlocksToSink({IfTrue, IfFalse}, Sink, IB);
460 return Ty->isIntegerTy();
462 assert(RS &&
"There is no integer type in all allowed types, is the "
464 Type *Ty = RS.getSelection();
471 Value *
Cond = IB.findOrCreateSource(*Source, InstsBeforeSplit, {},
474 uint64_t NumCases = uniform<uint64_t>(IB.Rand, 1, MaxNumCases);
475 NumCases = (NumCases > MaxCaseVal) ? MaxCaseVal + 1 : NumCases;
483 for (
uint64_t i = 0; i < NumCases; i++) {
487 Switch->addCase(OnValue, CaseBlock);
488 Blocks.push_back(CaseBlock);
492 connectBlocksToSink(
Blocks, Sink, IB);
501 uint64_t DirectSinkIdx = uniform<uint64_t>(IB.Rand, 0,
Blocks.size() - 1);
504 CFGToSink ToSink = (i == DirectSinkIdx)
505 ? CFGToSink::DirectSink
506 :
static_cast<CFGToSink
>(uniform<uint64_t>(
507 IB.Rand, 0, CFGToSink::EndOfCFGToLink - 1));
512 case CFGToSink::Return: {
514 Value *RetValue =
nullptr;
515 if (!
RetTy->isVoidTy())
521 case CFGToSink::DirectSink: {
525 case CFGToSink::SinkOrSelfLoop: {
528 uint64_t coin = uniform<uint64_t>(
IB.Rand, 0, 1);
534 case CFGToSink::EndOfCFGToLink:
544 Type *Ty = IB.randomType();
550 Value *Src = IncomingValues[Pred];
554 for (
auto I = Pred->begin();
I != Pred->end(); ++
I)
559 IncomingValues[Pred] = Src;
561 PHI->addIncoming(Src, Pred);
566 IB.connectToSink(BB, InstsAfter,
PHI);
578 if (Insts.
size() < 1)
589 IB.connectToSink(BB, InstsAfter, Inst);
595 std::map<size_t, Instruction *> AliveInsts;
596 std::map<Instruction *, size_t> AliveInstsLookup;
597 size_t InsertIdx = 0;
602 AliveInsts.insert({InsertIdx, &
I});
603 AliveInstsLookup.insert({&
I, InsertIdx++});
605 I.removeFromParent();
611 auto hasAliveParent = [&AliveInsts, &AliveInstsLookup](
size_t Index) {
612 for (
Value *O : AliveInsts[
Index]->operands()) {
614 if (
P && AliveInstsLookup.count(
P))
622 auto getAliveChildren = [&AliveInstsLookup](
Instruction *
I) {
624 for (
Value *U :
I->users()) {
626 if (
P && AliveInstsLookup.count(
P))
627 Children.insert(AliveInstsLookup[
P]);
633 for (
const auto &[
Index, Inst] : AliveInsts) {
634 if (!hasAliveParent(
Index))
638 while (!RootIndices.
empty()) {
639 auto RS = makeSampler<size_t>(IB.Rand);
640 for (
size_t RootIdx : RootIndices)
641 RS.sample(RootIdx, 1);
642 size_t RootIdx = RS.getSelection();
644 RootIndices.erase(RootIdx);
646 AliveInsts.erase(RootIdx);
647 AliveInstsLookup.erase(Root);
650 for (
size_t Child : getAliveChildren(Root)) {
651 if (!hasAliveParent(Child)) {
652 RootIndices.insert(Child);
660 I->insertBefore(Terminator);
669 return std::make_unique<Module>(
"M",
Context);
677 if (
Error E = M.takeError()) {
681 return std::move(M.get());
690 if (Buf.size() > MaxSize)
692 memcpy(Dest, Buf.data(), Buf.size());
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
Returns the sub type a function will return at a given Idx Should correspond to the result type of an ExtractValue instruction executed with just that one unsigned Idx
DenseMap< Block *, BlockRelaxAux > Blocks
static void eliminateDeadCode(Function &F)
static iterator_range< BasicBlock::iterator > getInsertionRange(BasicBlock &BB)
static uint64_t getUniqueCaseValue(SmallSet< uint64_t, 4 > &CasesTaken, uint64_t MaxValue, RandomIRBuilder &IB)
Return a case value that is not already taken to make sure we don't have two cases with same value.
Select target instructions out of generic instructions
Module.h This file contains the declarations for the Module class.
FunctionAnalysisManager FAM
const SmallVectorImpl< MachineOperand > & Cond
static ManagedStatic< cl::opt< uint64_t >, CreateSeed > Seed
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This file defines the SmallSet class.
A container for analyses that lazily runs them and caches their results.
bool registerPass(PassBuilderT &&PassBuilder)
Register an analysis pass with the manager.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
ArrayRef< T > slice(size_t N, size_t M) const
slice(n, m) - Chop off the first N elements of the array, and keep M elements in the array.
LLVM Basic Block Representation.
const_iterator getFirstInsertionPt() const
Returns an iterator to the first instruction in this block that is suitable for inserting a non-PHI i...
const Instruction & front() const
static BasicBlock * Create(LLVMContext &Context, const Twine &Name="", Function *Parent=nullptr, BasicBlock *InsertBefore=nullptr)
Creates a new BasicBlock.
const Function * getParent() const
Return the enclosing method, or null if none.
bool isEHPad() const
Return true if this basic block is an exception handling block.
const Instruction * getTerminator() const LLVM_READONLY
Returns the terminator instruction if the block is well formed or null if the block is not well forme...
const CallInst * getTerminatingMustTailCall() const
Returns the call instruction marked 'musttail' prior to the terminating return instruction of this ba...
Conditional or Unconditional Branch instruction.
static BranchInst * Create(BasicBlock *IfTrue, Instruction *InsertBefore=nullptr)
This class represents a function call, abstracting a target machine's calling convention.
static CallInst * Create(FunctionType *Ty, Value *F, const Twine &NameStr="", Instruction *InsertBefore=nullptr)
This class is the base class for the comparison instructions.
void setPredicate(Predicate P)
Set the predicate for this instruction to the specified value.
Predicate
This enumeration lists the possible predicates for CmpInst subclasses.
This is the shared class of boolean and integer constants.
static Constant * get(Type *Ty, uint64_t V, bool IsSigned=false)
If Ty is a vector type, return a Constant with a splat of the given value.
This is an important base class in LLVM.
Basic Dead Code Elimination pass.
This class represents an Operation in the Expression.
Lightweight error class with error context and mandatory checking.
Class to represent function types.
ArrayRef< Type * > params() const
const BasicBlock & getEntryBlock() const
an instruction for type-safe pointer arithmetic to access elements of arrays and structs
Module * getParent()
Get the module that this global value is contained inside of...
virtual void mutate(Module &M, RandomIRBuilder &IB)
void mutateModule(Module &M, int Seed, size_t MaxSize)
Mutate given module.
static size_t getModuleSize(const Module &M)
Calculate the size of module as the number of objects in it, i.e.
static std::vector< fuzzerop::OpDescriptor > getDefaultOps()
void mutate(Function &F, RandomIRBuilder &IB) override
void mutate(BasicBlock &BB, RandomIRBuilder &IB) override
void mutate(BasicBlock &BB, RandomIRBuilder &IB) override
void mutate(BasicBlock &BB, RandomIRBuilder &IB) override
uint64_t getWeight(size_t CurrentSize, size_t MaxSize, uint64_t CurrentWeight) override
Provide a weight to bias towards choosing this strategy for a mutation.
void mutate(Function &F, RandomIRBuilder &IB) override
void mutate(Instruction &Inst, RandomIRBuilder &IB) override
void setHasNoUnsignedWrap(bool b=true)
Set or clear the nuw flag on this instruction, which must be an operator which supports this flag.
bool hasNoNaNs() const LLVM_READONLY
Determine whether the no-NaNs flag is set.
bool hasNoUnsignedWrap() const LLVM_READONLY
Determine whether the no unsigned wrap flag is set.
bool hasNoInfs() const LLVM_READONLY
Determine whether the no-infs flag is set.
void setHasNoSignedZeros(bool B)
Set or clear the no-signed-zeros flag on this instruction, which must be an operator which supports t...
bool hasNoSignedZeros() const LLVM_READONLY
Determine whether the no-signed-zeros flag is set.
bool hasNoSignedWrap() const LLVM_READONLY
Determine whether the no signed wrap flag is set.
void setHasAllowContract(bool B)
Set or clear the allow-contract flag on this instruction, which must be an operator which supports th...
void setHasNoSignedWrap(bool b=true)
Set or clear the nsw flag on this instruction, which must be an operator which supports this flag.
void setHasNoNaNs(bool B)
Set or clear the no-nans flag on this instruction, which must be an operator which supports this flag...
void setHasApproxFunc(bool B)
Set or clear the approximate-math-functions flag on this instruction, which must be an operator which...
void setHasAllowReassoc(bool B)
Set or clear the reassociation flag on this instruction, which must be an operator which supports thi...
const BasicBlock * getParent() const
bool isExact() const LLVM_READONLY
Determine whether the exact flag is set.
bool isTerminator() const
bool hasAllowReciprocal() const LLVM_READONLY
Determine whether the allow-reciprocal flag is set.
void setHasNoInfs(bool B)
Set or clear the no-infs flag on this instruction, which must be an operator which supports this flag...
FastMathFlags getFastMathFlags() const LLVM_READONLY
Convenience function for getting all the fast-math flags, which must be an operator which supports th...
bool hasApproxFunc() const LLVM_READONLY
Determine whether the approximate-math-functions flag is set.
unsigned getOpcode() const
Returns a member of one of the enums like Instruction::Add.
void setIsExact(bool b=true)
Set or clear the exact flag on this instruction, which must be an operator which supports this flag.
void setHasAllowReciprocal(bool B)
Set or clear the allow-reciprocal flag on this instruction, which must be an operator which supports ...
bool hasAllowContract() const LLVM_READONLY
Determine whether the allow-contract flag is set.
SymbolTableList< Instruction >::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
void setFast(bool B)
Set or clear all fast-math-flags on this instruction, which must be an operator which supports this f...
bool hasAllowReassoc() const LLVM_READONLY
Determine whether the allow-reassociation flag is set.
Class to represent integer types.
unsigned getBitWidth() const
Get the number of bits in this IntegerType.
This is an important class for using LLVM in a threaded context.
static std::unique_ptr< MemoryBuffer > getMemBuffer(StringRef InputData, StringRef BufferName="", bool RequiresNullTerminator=true)
Open the specified memory range as a MemoryBuffer.
A Module instance is used to store all the information related to an LLVM module.
static PHINode * Create(Type *Ty, unsigned NumReservedValues, const Twine &NameStr="", Instruction *InsertBefore=nullptr)
Constructors - NumReservedValues is a hint for the number of incoming edges that this phi node will h...
Pseudo-analysis pass that exposes the PassInstrumentation to pass managers.
LLVM_ATTRIBUTE_MINSIZE std::enable_if_t<!std::is_same< PassT, PassManager >::value > addPass(PassT &&Pass)
PreservedAnalyses run(IRUnitT &IR, AnalysisManagerT &AM, ExtraArgTs... ExtraArgs)
Run all of the passes in this manager over the given unit of IR.
static ReturnInst * Create(LLVMContext &C, Value *retVal=nullptr, Instruction *InsertBefore=nullptr)
Instances of this class encapsulate one diagnostic report, allowing printing to a raw_ostream as a ca...
void mutate(BasicBlock &BB, RandomIRBuilder &IB) override
void mutate(Function &F, RandomIRBuilder &IB) override
A SetVector that performs no allocations if smaller than a certain size.
SmallSet - This maintains a set of unique values, optimizing for the case when the set is small (less...
size_type count(const T &V) const
count - Return 1 if the element is in the set, 0 otherwise.
std::pair< const_iterator, bool > insert(const T &V)
insert - Insert an element into the set if it isn't already there.
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
StringRef - Represent a constant reference to a string, i.e.
static SwitchInst * Create(Value *Value, BasicBlock *Default, unsigned NumCases, Instruction *InsertBefore=nullptr)
Analysis pass providing the TargetLibraryInfo.
The instances of the Type class are immutable: once they are created, they are never changed.
static IntegerType * getInt1Ty(LLVMContext &C)
static Type * getVoidTy(LLVMContext &C)
bool isTokenTy() const
Return true if this is 'token'.
bool isVoidTy() const
Return true if this is 'void'.
void setOperand(unsigned i, Value *Val)
Value * getOperand(unsigned i) const
LLVM Value Representation.
Type * getType() const
All values are typed, get the type of this value.
void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
self_iterator getIterator()
A range adaptor for a pair of iterators.
A raw_ostream that writes to an std::string.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ C
The default llvm calling convention, compatible with C.
std::optional< const char * > toString(const std::optional< DWARFFormValue > &V)
Take an optional DWARFFormValue and try to extract a string value from it.
static SourcePred onlyType(Type *Only)
This is an optimization pass for GlobalISel generic memory operations.
void ReplaceInstWithInst(BasicBlock *BB, BasicBlock::iterator &BI, Instruction *I)
Replace the instruction specified by BI with the instruction specified by I.
void describeFuzzerIntOps(std::vector< fuzzerop::OpDescriptor > &Ops)
Getters for the default sets of operations, per general category.
Expected< std::unique_ptr< Module > > parseBitcodeFile(MemoryBufferRef Buffer, LLVMContext &Context, ParserCallbacks Callbacks={})
Read the specified bitcode file, returning the module.
void WriteBitcodeToFile(const Module &M, raw_ostream &Out, bool ShouldPreserveUseListOrder=false, const ModuleSummaryIndex *Index=nullptr, bool GenerateHash=false, ModuleHash *ModHash=nullptr)
Write the specified module to the specified raw output stream.
std::unique_ptr< Module > parseAndVerify(const uint8_t *Data, size_t Size, LLVMContext &Context)
Try to parse module and verify it.
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
std::unique_ptr< Module > parseModule(const uint8_t *Data, size_t Size, LLVMContext &Context)
Fuzzer friendly interface for the llvm bitcode parser.
iterator_range< early_inc_iterator_impl< detail::IterOfRange< RangeT > > > make_early_inc_range(RangeT &&Range)
Make a range that does early increment to allow mutation of the underlying range without disrupting i...
void describeFuzzerAggregateOps(std::vector< fuzzerop::OpDescriptor > &Ops)
size_t writeModule(const Module &M, uint8_t *Dest, size_t MaxSize)
Fuzzer friendly interface for the llvm bitcode printer.
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
ReservoirSampler< ElT, GenT > makeSampler(GenT &RandGen, RangeT &&Items)
void describeFuzzerVectorOps(std::vector< fuzzerop::OpDescriptor > &Ops)
iterator_range< filter_iterator< detail::IterOfRange< RangeT >, PredicateT > > make_filter_range(RangeT &&Range, PredicateT Pred)
Convenience function that takes a range of elements and a predicate, and return a new filter_iterator...
raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
DWARFExpression::Operation Op
void describeFuzzerFloatOps(std::vector< fuzzerop::OpDescriptor > &Ops)
void describeFuzzerControlFlowOps(std::vector< fuzzerop::OpDescriptor > &Ops)
auto predecessors(const MachineBasicBlock *BB)
iterator_range< pointer_iterator< WrappedIteratorT > > make_pointer_range(RangeT &&Range)
void describeFuzzerPointerOps(std::vector< fuzzerop::OpDescriptor > &Ops)
unsigned pred_size(const MachineBasicBlock *BB)
bool verifyModule(const Module &M, raw_ostream *OS=nullptr, bool *BrokenDebugInfo=nullptr)
Check a module for errors.
A description of some operation we can build while fuzzing IR.