37 auto RS = makeSampler<Function *>(IB.Rand);
39 if (!
F.isDeclaration())
42 while (RS.totalWeight() < IB.MinFunctionNum) {
43 Function *
F = IB.createFunctionDefinition(M);
46 mutate(*RS.getSelection(), IB);
61 return M.getInstructionCount() + M.size() + M.global_size() + M.alias_size();
65 std::vector<Type *> Types;
66 for (
const auto &Getter : AllowedTypes)
67 Types.push_back(Getter(M.getContext()));
71 auto RS = makeSampler<IRMutationStrategy *>(IB.Rand);
72 for (
const auto &Strategy : Strategies)
73 RS.sample(Strategy.get(),
74 Strategy->getWeight(CurSize, MaxSize, RS.totalWeight()));
75 if (RS.totalWeight() == 0)
77 auto Strategy = RS.getSelection();
79 Strategy->mutate(M, IB);
97 std::vector<fuzzerop::OpDescriptor> Ops;
107std::optional<fuzzerop::OpDescriptor>
110 return Op.SourcePreds[0].matches({}, Src);
128 if (Insts.
size() < 1)
132 size_t IP = uniform<size_t>(IB.Rand, 0, Insts.
size() - 1);
139 Srcs.
push_back(IB.findOrCreateSource(BB, InstsBefore));
143 auto OpDesc = chooseOperation(Srcs[0], IB);
148 for (
const auto &Pred :
ArrayRef(OpDesc->SourcePreds).
slice(1))
149 Srcs.
push_back(IB.findOrCreateSource(BB, InstsBefore, Srcs, Pred));
151 if (
Value *
Op = OpDesc->BuilderFunc(Srcs, Insts[IP]->getIterator())) {
153 IB.connectToSink(BB, InstsAfter,
Op);
160 if (CurrentSize > MaxSize - 200)
161 return CurrentWeight ? CurrentWeight * 100 : 1;
164 int64_t Line = (-2 *
static_cast<int64_t
>(CurrentWeight)) *
165 (
static_cast<int64_t
>(MaxSize) -
166 static_cast<int64_t
>(CurrentSize) - 1000) /
175 auto RS = makeSampler<Instruction *>(IB.Rand);
178 if (Inst.isTerminator() || Inst.isEHPad() || Inst.isSwiftError() ||
188 mutate(*RS.getSelection(), IB);
206 auto RS = makeSampler<Value *>(IB.Rand);
211 if (Pred.matches({}, &*
I))
216 RS.sample(IB.newSource(*BB, InstsBefore, {}, Pred), 1);
224 SmallVector<std::function<void()>, 8> Modifications;
231 case Instruction::Add:
232 case Instruction::Mul:
233 case Instruction::Sub:
234 case Instruction::Shl:
235 Modifications.push_back(
237 Modifications.push_back(
240 case Instruction::ICmp:
241 CI = cast<ICmpInst>(&Inst);
244 Modifications.push_back(
249 case Instruction::GetElementPtr:
250 GEP = cast<GetElementPtrInst>(&Inst);
251 Modifications.push_back(
252 [
GEP]() {
GEP->setIsInBounds(!
GEP->isInBounds()); });
255 case Instruction::UDiv:
256 case Instruction::SDiv:
257 case Instruction::LShr:
258 case Instruction::AShr:
262 case Instruction::FCmp:
263 CI = cast<FCmpInst>(&Inst);
266 Modifications.push_back(
273 if (isa<FPMathOperator>(&Inst)) {
275 Modifications.push_back(
278 Modifications.push_back(
281 Modifications.push_back(
285 Modifications.push_back(
287 Modifications.push_back(
289 Modifications.push_back(
291 Modifications.push_back(
296 std::pair<int, int> NoneItem({-1, -1}), ShuffleItems(NoneItem);
298 case Instruction::SDiv:
299 case Instruction::UDiv:
300 case Instruction::SRem:
301 case Instruction::URem:
302 case Instruction::FDiv:
303 case Instruction::FRem: {
307 if (
Constant *
C = dyn_cast<Constant>(Operand)) {
308 if (!
C->isZeroValue()) {
309 ShuffleItems = {0, 1};
314 case Instruction::Select:
315 ShuffleItems = {1, 2};
317 case Instruction::Add:
318 case Instruction::Sub:
319 case Instruction::Mul:
320 case Instruction::Shl:
321 case Instruction::LShr:
322 case Instruction::AShr:
323 case Instruction::And:
324 case Instruction::Or:
325 case Instruction::Xor:
326 case Instruction::FAdd:
327 case Instruction::FSub:
328 case Instruction::FMul:
329 case Instruction::ICmp:
330 case Instruction::FCmp:
331 case Instruction::ShuffleVector:
332 ShuffleItems = {0, 1};
335 if (ShuffleItems != NoneItem) {
336 Modifications.push_back([&Inst, &ShuffleItems]() {
354 tmp = uniform<uint64_t>(IB.Rand, 0, MaxValue);
355 }
while (CasesTaken.
count(tmp) != 0);
374 auto IsUnsupportedTy = [](
Type *
T) {
375 return T->isMetadataTy() ||
T->isTokenTy();
377 if (!
F || IsUnsupportedTy(
F->getReturnType()) ||
378 any_of(
F->getFunctionType()->params(), IsUnsupportedTy)) {
379 F = IB.createFunctionDeclaration(*M);
384 if (!
F->arg_empty()) {
395 return isRetVoid ? nullptr : Call;
401 if (Insts.
size() < 1)
405 uint64_t IP = uniform<uint64_t>(IB.Rand, 0, Insts.
size() - 1);
413 for (
const auto &Pred :
ArrayRef(SourcePreds)) {
414 Srcs.
push_back(IB.findOrCreateSource(BB, InstsBefore, Srcs, Pred));
417 if (
Value *
Op = BuilderFunc(Srcs, Insts[IP]->getIterator())) {
419 IB.connectToSink(BB, InstsAfter,
Op);
427 if (Insts.
size() < 1)
431 uint64_t IP = uniform<uint64_t>(IB.Rand, 0, Insts.
size() - 1);
444 if (uniform<uint64_t>(IB.Rand, 0, 1)) {
449 IB.findOrCreateSource(*Source, InstsBeforeSplit, {},
455 connectBlocksToSink({IfTrue, IfFalse}, Sink, IB);
461 return Ty->isIntegerTy();
463 assert(RS &&
"There is no integer type in all allowed types, is the "
465 Type *Ty = RS.getSelection();
472 Value *
Cond = IB.findOrCreateSource(*Source, InstsBeforeSplit, {},
475 uint64_t NumCases = uniform<uint64_t>(IB.Rand, 1, MaxNumCases);
476 NumCases = (NumCases > MaxCaseVal) ? MaxCaseVal + 1 : NumCases;
484 for (
uint64_t i = 0; i < NumCases; i++) {
487 ConstantInt *OnValue = ConstantInt::get(IntTy, CaseVal);
488 Switch->addCase(OnValue, CaseBlock);
489 Blocks.push_back(CaseBlock);
493 connectBlocksToSink(
Blocks, Sink, IB);
502 uint64_t DirectSinkIdx = uniform<uint64_t>(IB.Rand, 0,
Blocks.size() - 1);
505 CFGToSink ToSink = (i == DirectSinkIdx)
506 ? CFGToSink::DirectSink
507 :
static_cast<CFGToSink
>(uniform<uint64_t>(
508 IB.Rand, 0, CFGToSink::EndOfCFGToLink - 1));
513 case CFGToSink::Return: {
515 Value *RetValue =
nullptr;
516 if (!
RetTy->isVoidTy())
522 case CFGToSink::DirectSink: {
526 case CFGToSink::SinkOrSelfLoop: {
529 uint64_t coin = uniform<uint64_t>(
IB.Rand, 0, 1);
535 case CFGToSink::EndOfCFGToLink:
545 Type *Ty = IB.randomType();
551 Value *Src = IncomingValues[Pred];
555 for (
auto I = Pred->begin();
I != Pred->end(); ++
I)
560 IncomingValues[Pred] = Src;
562 PHI->addIncoming(Src, Pred);
567 IB.connectToSink(BB, InstsAfter,
PHI);
579 if (Insts.
size() < 1)
590 IB.connectToSink(BB, InstsAfter, Inst);
596 std::map<size_t, Instruction *> AliveInsts;
597 std::map<Instruction *, size_t> AliveInstsLookup;
598 size_t InsertIdx = 0;
603 AliveInsts.insert({InsertIdx, &
I});
604 AliveInstsLookup.insert({&
I, InsertIdx++});
606 I.removeFromParent();
612 auto hasAliveParent = [&AliveInsts, &AliveInstsLookup](
size_t Index) {
613 for (
Value *O : AliveInsts[
Index]->operands()) {
615 if (
P && AliveInstsLookup.count(
P))
623 auto getAliveChildren = [&AliveInstsLookup](
Instruction *
I) {
625 for (
Value *U :
I->users()) {
627 if (
P && AliveInstsLookup.count(
P))
628 Children.insert(AliveInstsLookup[
P]);
634 for (
const auto &[
Index, Inst] : AliveInsts) {
635 if (!hasAliveParent(
Index))
639 while (!RootIndices.
empty()) {
640 auto RS = makeSampler<size_t>(IB.Rand);
641 for (
size_t RootIdx : RootIndices)
642 RS.sample(RootIdx, 1);
643 size_t RootIdx = RS.getSelection();
645 RootIndices.erase(RootIdx);
647 AliveInsts.erase(RootIdx);
648 AliveInstsLookup.erase(Root);
651 for (
size_t Child : getAliveChildren(Root)) {
652 if (!hasAliveParent(Child)) {
653 RootIndices.insert(Child);
661 I->insertBefore(Terminator);
670 return std::make_unique<Module>(
"M", Context);
678 if (
Error E = M.takeError()) {
682 return std::move(M.get());
691 if (Buf.size() > MaxSize)
693 memcpy(Dest, Buf.data(), Buf.size());
Expand Atomic instructions
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.
Module.h This file contains the declarations for the Module class.
ConstantRange Range(APInt(BitWidth, Low), APInt(BitWidth, High))
FunctionAnalysisManager FAM
This file defines the Pass Instrumentation classes that provide instrumentation points into the pass ...
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.
iterator begin()
Instruction iterator methods.
const_iterator getFirstInsertionPt() const
Returns an iterator to the first instruction in this block that is suitable for inserting a non-PHI i...
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.
InstListType::iterator iterator
Instruction iterators...
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, InsertPosition 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="", InsertPosition 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.
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...
InstListType::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
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.
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="", InsertPosition 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_v< PassT, PassManager > > 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, InsertPosition 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, InsertPosition 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.
const ParentTy * getParent() const
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.