24#include "llvm/IR/IntrinsicsAMDGPU.h"
39 auto RS = makeSampler<Function *>(IB.Rand);
41 if (!
F.isDeclaration())
44 while (RS.totalWeight() < IB.MinFunctionNum) {
45 Function *
F = IB.createFunctionDefinition(M);
48 mutate(*RS.getSelection(), IB);
63 return M.getInstructionCount() + M.size() + M.global_size() + M.alias_size();
67 std::vector<Type *> Types;
68 for (
const auto &Getter : AllowedTypes)
69 Types.push_back(Getter(M.getContext()));
73 auto RS = makeSampler<IRMutationStrategy *>(IB.Rand);
74 for (
const auto &Strategy : Strategies)
75 RS.sample(Strategy.get(),
76 Strategy->getWeight(CurSize, MaxSize, RS.totalWeight()));
77 if (RS.totalWeight() == 0)
79 auto Strategy = RS.getSelection();
81 Strategy->mutate(M, IB);
99 std::vector<fuzzerop::OpDescriptor> Ops;
109std::optional<fuzzerop::OpDescriptor>
112 return Op.SourcePreds[0].matches({}, Src);
146 End = std::prev(BB.
end());
161 if (Insts.
size() < 1)
165 size_t IP = uniform<size_t>(IB.Rand, 0, Insts.
size() - 1);
172 Srcs.
push_back(IB.findOrCreateSource(BB, InstsBefore));
176 auto OpDesc = chooseOperation(Srcs[0], IB);
181 for (
const auto &Pred :
ArrayRef(OpDesc->SourcePreds).
slice(1))
182 Srcs.
push_back(IB.findOrCreateSource(BB, InstsBefore, Srcs, Pred));
184 if (
Value *
Op = OpDesc->BuilderFunc(Srcs, Insts[IP]->getIterator())) {
186 IB.connectToSink(BB, InstsAfter,
Op);
193 if (CurrentSize > MaxSize - 200)
194 return CurrentWeight ? CurrentWeight * 100 : 1;
197 int64_t Line = (-2 *
static_cast<int64_t
>(CurrentWeight)) *
198 (
static_cast<int64_t
>(MaxSize) -
199 static_cast<int64_t
>(CurrentSize) - 1000) /
208 auto RS = makeSampler<Instruction *>(IB.Rand);
211 if (Inst.isTerminator() || Inst.isEHPad() || Inst.isSwiftError() ||
221 mutate(*RS.getSelection(), IB);
239 auto RS = makeSampler<Value *>(IB.Rand);
244 if (Pred.matches({}, &*
I))
249 RS.sample(IB.newSource(*BB, InstsBefore, {}, Pred), 1);
257 SmallVector<std::function<void()>, 8> Modifications;
264 case Instruction::Add:
265 case Instruction::Mul:
266 case Instruction::Sub:
267 case Instruction::Shl:
268 Modifications.push_back(
270 Modifications.push_back(
273 case Instruction::ICmp:
274 CI = cast<ICmpInst>(&Inst);
277 Modifications.push_back(
282 case Instruction::GetElementPtr:
283 GEP = cast<GetElementPtrInst>(&Inst);
284 Modifications.push_back(
285 [
GEP]() {
GEP->setIsInBounds(!
GEP->isInBounds()); });
288 case Instruction::UDiv:
289 case Instruction::SDiv:
290 case Instruction::LShr:
291 case Instruction::AShr:
295 case Instruction::FCmp:
296 CI = cast<FCmpInst>(&Inst);
299 Modifications.push_back(
306 if (isa<FPMathOperator>(&Inst)) {
308 Modifications.push_back(
311 Modifications.push_back(
314 Modifications.push_back(
318 Modifications.push_back(
320 Modifications.push_back(
322 Modifications.push_back(
324 Modifications.push_back(
329 std::pair<int, int> NoneItem({-1, -1}), ShuffleItems(NoneItem);
331 case Instruction::SDiv:
332 case Instruction::UDiv:
333 case Instruction::SRem:
334 case Instruction::URem:
335 case Instruction::FDiv:
336 case Instruction::FRem: {
340 if (
Constant *
C = dyn_cast<Constant>(Operand)) {
341 if (!
C->isZeroValue()) {
342 ShuffleItems = {0, 1};
347 case Instruction::Select:
348 ShuffleItems = {1, 2};
350 case Instruction::Add:
351 case Instruction::Sub:
352 case Instruction::Mul:
353 case Instruction::Shl:
354 case Instruction::LShr:
355 case Instruction::AShr:
356 case Instruction::And:
357 case Instruction::Or:
358 case Instruction::Xor:
359 case Instruction::FAdd:
360 case Instruction::FSub:
361 case Instruction::FMul:
362 case Instruction::ICmp:
363 case Instruction::FCmp:
364 case Instruction::ShuffleVector:
365 ShuffleItems = {0, 1};
368 if (ShuffleItems != NoneItem) {
369 Modifications.push_back([&Inst, &ShuffleItems]() {
387 tmp = uniform<uint64_t>(IB.Rand, 0, MaxValue);
388 }
while (CasesTaken.
count(tmp) != 0);
404 auto IsUnsupportedTy = [](
Type *
T) {
405 return T->isMetadataTy() ||
T->isTokenTy();
408 if (IsUnsupportedTy(
F->getReturnType()) ||
409 any_of(
F->getFunctionType()->params(), IsUnsupportedTy)) {
419 Attribute::StructRet, Attribute::ByVal,
420 Attribute::InAlloca, Attribute::InReg,
421 Attribute::StackAlignment, Attribute::SwiftSelf,
422 Attribute::SwiftAsync, Attribute::SwiftError,
423 Attribute::Preallocated, Attribute::ByRef,
424 Attribute::ZExt, Attribute::SExt};
427 return A.hasAttribute(kind);
431 auto FuncAttrs =
F->getAttributes();
432 if (IsABIAttribute(FuncAttrs.getRetAttrs())) {
435 for (
size_t i = 0; i <
F->arg_size(); i++) {
436 if (IsABIAttribute(FuncAttrs.getParamAttrs(i))) {
448 if (
F->isIntrinsic() &&
F->getIntrinsicID() == Intrinsic::amdgcn_cs_chain) {
467 F = IB.createFunctionDeclaration(*M);
472 if (!
F->arg_empty()) {
482 Call->setCallingConv(
F->getCallingConv());
484 return isRetVoid ? nullptr : Call;
489 if (Insts.
size() < 1)
493 uint64_t IP = uniform<uint64_t>(IB.Rand, 0, Insts.
size() - 1);
501 for (
const auto &Pred :
ArrayRef(SourcePreds)) {
502 Srcs.
push_back(IB.findOrCreateSource(BB, InstsBefore, Srcs, Pred));
505 if (
Value *
Op = BuilderFunc(Srcs, Insts[IP]->getIterator())) {
507 IB.connectToSink(BB, InstsAfter,
Op);
514 if (Insts.
size() < 1)
518 uint64_t IP = uniform<uint64_t>(IB.Rand, 0, Insts.
size() - 1);
531 if (uniform<uint64_t>(IB.Rand, 0, 1)) {
536 IB.findOrCreateSource(*Source, InstsBeforeSplit, {},
542 connectBlocksToSink({IfTrue, IfFalse}, Sink, IB);
548 return Ty->isIntegerTy();
550 assert(RS &&
"There is no integer type in all allowed types, is the "
552 Type *Ty = RS.getSelection();
559 Value *
Cond = IB.findOrCreateSource(*Source, InstsBeforeSplit, {},
562 uint64_t NumCases = uniform<uint64_t>(IB.Rand, 1, MaxNumCases);
563 NumCases = (NumCases > MaxCaseVal) ? MaxCaseVal + 1 : NumCases;
571 for (
uint64_t i = 0; i < NumCases; i++) {
574 ConstantInt *OnValue = ConstantInt::get(IntTy, CaseVal);
575 Switch->addCase(OnValue, CaseBlock);
576 Blocks.push_back(CaseBlock);
580 connectBlocksToSink(
Blocks, Sink, IB);
589 uint64_t DirectSinkIdx = uniform<uint64_t>(IB.Rand, 0,
Blocks.size() - 1);
592 CFGToSink ToSink = (i == DirectSinkIdx)
593 ? CFGToSink::DirectSink
594 :
static_cast<CFGToSink
>(uniform<uint64_t>(
595 IB.Rand, 0, CFGToSink::EndOfCFGToLink - 1));
600 case CFGToSink::Return: {
602 Value *RetValue =
nullptr;
603 if (!
RetTy->isVoidTy())
609 case CFGToSink::DirectSink: {
613 case CFGToSink::SinkOrSelfLoop: {
616 uint64_t coin = uniform<uint64_t>(
IB.Rand, 0, 1);
622 case CFGToSink::EndOfCFGToLink:
632 Type *Ty = IB.randomType();
638 Value *Src = IncomingValues[Pred];
642 for (
auto I = Pred->begin();
I != Pred->end(); ++
I)
647 IncomingValues[Pred] = Src;
649 PHI->addIncoming(Src, Pred);
653 IB.connectToSink(BB, InstsAfter,
PHI);
664 if (Insts.
size() < 1)
675 IB.connectToSink(BB, InstsAfter, Inst);
681 std::map<size_t, Instruction *> AliveInsts;
682 std::map<Instruction *, size_t> AliveInstsLookup;
683 size_t InsertIdx = 0;
689 AliveInsts.insert({InsertIdx, &
I});
690 AliveInstsLookup.insert({&
I, InsertIdx++});
692 I.removeFromParent();
698 auto hasAliveParent = [&AliveInsts, &AliveInstsLookup](
size_t Index) {
699 for (
Value *O : AliveInsts[Index]->operands()) {
701 if (
P && AliveInstsLookup.count(
P))
709 auto getAliveChildren = [&AliveInstsLookup](
Instruction *
I) {
711 for (
Value *U :
I->users()) {
713 auto It = AliveInstsLookup.find(
P);
714 if (It != AliveInstsLookup.end())
715 Children.insert(It->second);
722 for (
const auto &[Index, Inst] : AliveInsts) {
723 if (!hasAliveParent(Index))
724 RootIndices.
insert(Index);
727 while (!RootIndices.
empty()) {
728 auto RS = makeSampler<size_t>(IB.Rand);
729 for (
size_t RootIdx : RootIndices)
730 RS.sample(RootIdx, 1);
731 size_t RootIdx = RS.getSelection();
733 RootIndices.erase(RootIdx);
735 AliveInsts.erase(RootIdx);
736 AliveInstsLookup.erase(Root);
739 for (
size_t Child : getAliveChildren(Root)) {
740 if (!hasAliveParent(Child)) {
741 RootIndices.insert(Child);
749 I->insertBefore(Terminator->getIterator());
758 return std::make_unique<Module>(
"M",
Context);
766 if (
Error E = M.takeError()) {
770 return std::move(M.get());
779 if (Buf.size() > MaxSize)
781 memcpy(Dest, Buf.data(), Buf.size());
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
Expand Atomic instructions
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
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 Instruction * getEffectiveTerminator(BasicBlock &BB)
static bool isUnsupportedFunction(Function *F)
Determines whether a function is unsupported by the current mutator's implementation.
static void eliminateDeadCode(Function &F)
static iterator_range< BasicBlock::iterator > getInsertionRange(BasicBlock &BB)
static BasicBlock::iterator getEndIterator(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))
uint64_t IntrinsicInst * II
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
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.
AttrKind
This enumeration lists the attributes that can be associated with parameters, function results,...
LLVM Basic Block Representation.
iterator begin()
Instruction iterator methods.
LLVM_ABI 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...
LLVM_ABI 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)
LLVM_ABI void mutateModule(Module &M, int Seed, size_t MaxSize)
Mutate given module.
static LLVM_ABI 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
LLVM_ABI void setHasNoUnsignedWrap(bool b=true)
Set or clear the nuw flag on this instruction, which must be an operator which supports this flag.
LLVM_ABI bool hasNoNaNs() const LLVM_READONLY
Determine whether the no-NaNs flag is set.
LLVM_ABI bool hasNoUnsignedWrap() const LLVM_READONLY
Determine whether the no unsigned wrap flag is set.
LLVM_ABI bool hasNoInfs() const LLVM_READONLY
Determine whether the no-infs flag is set.
LLVM_ABI void setHasNoSignedZeros(bool B)
Set or clear the no-signed-zeros flag on this instruction, which must be an operator which supports t...
LLVM_ABI bool hasNoSignedZeros() const LLVM_READONLY
Determine whether the no-signed-zeros flag is set.
LLVM_ABI bool hasNoSignedWrap() const LLVM_READONLY
Determine whether the no signed wrap flag is set.
LLVM_ABI void setHasAllowContract(bool B)
Set or clear the allow-contract flag on this instruction, which must be an operator which supports th...
LLVM_ABI void setHasNoSignedWrap(bool b=true)
Set or clear the nsw flag on this instruction, which must be an operator which supports this flag.
LLVM_ABI void setHasNoNaNs(bool B)
Set or clear the no-nans flag on this instruction, which must be an operator which supports this flag...
LLVM_ABI void setHasApproxFunc(bool B)
Set or clear the approximate-math-functions flag on this instruction, which must be an operator which...
LLVM_ABI void setHasAllowReassoc(bool B)
Set or clear the reassociation flag on this instruction, which must be an operator which supports thi...
LLVM_ABI InstListType::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
LLVM_ABI bool isExact() const LLVM_READONLY
Determine whether the exact flag is set.
bool isTerminator() const
LLVM_ABI bool hasAllowReciprocal() const LLVM_READONLY
Determine whether the allow-reciprocal flag is set.
LLVM_ABI void setHasNoInfs(bool B)
Set or clear the no-infs flag on this instruction, which must be an operator which supports this flag...
LLVM_ABI FastMathFlags getFastMathFlags() const LLVM_READONLY
Convenience function for getting all the fast-math flags, which must be an operator which supports th...
LLVM_ABI 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.
LLVM_ABI void setIsExact(bool b=true)
Set or clear the exact flag on this instruction, which must be an operator which supports this flag.
LLVM_ABI void setHasAllowReciprocal(bool B)
Set or clear the allow-reciprocal flag on this instruction, which must be an operator which supports ...
LLVM_ABI bool hasAllowContract() const LLVM_READONLY
Determine whether the allow-contract flag is set.
LLVM_ABI void setFast(bool B)
Set or clear all fast-math-flags on this instruction, which must be an operator which supports this f...
LLVM_ABI 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.
A wrapper class for inspecting calls to intrinsic functions.
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 LLVM_ABI IntegerType * getInt1Ty(LLVMContext &C)
static LLVM_ABI Type * getVoidTy(LLVMContext &C)
bool isTokenTy() const
Return true if this is 'token'.
bool isVoidTy() const
Return true if this is 'void'.
This function has undefined behavior.
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.
LLVM_ABI 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.
static SourcePred onlyType(Type *Only)
This is an optimization pass for GlobalISel generic memory operations.
LLVM_ABI void ReplaceInstWithInst(BasicBlock *BB, BasicBlock::iterator &BI, Instruction *I)
Replace the instruction specified by BI with the instruction specified by I.
LLVM_ABI void describeFuzzerIntOps(std::vector< fuzzerop::OpDescriptor > &Ops)
Getters for the default sets of operations, per general category.
LLVM_ABI Expected< std::unique_ptr< Module > > parseBitcodeFile(MemoryBufferRef Buffer, LLVMContext &Context, ParserCallbacks Callbacks={})
Read the specified bitcode file, returning the module.
LLVM_ABI 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.
LLVM_ABI 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.
LLVM_ABI 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...
auto pred_size(const MachineBasicBlock *BB)
LLVM_ABI void describeFuzzerAggregateOps(std::vector< fuzzerop::OpDescriptor > &Ops)
LLVM_ABI 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)
LLVM_ABI 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...
LLVM_ABI raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
DWARFExpression::Operation Op
LLVM_ABI void describeFuzzerFloatOps(std::vector< fuzzerop::OpDescriptor > &Ops)
LLVM_ABI void describeFuzzerControlFlowOps(std::vector< fuzzerop::OpDescriptor > &Ops)
auto predecessors(const MachineBasicBlock *BB)
iterator_range< pointer_iterator< WrappedIteratorT > > make_pointer_range(RangeT &&Range)
LLVM_ABI void describeFuzzerPointerOps(std::vector< fuzzerop::OpDescriptor > &Ops)
const char * toString(DWARFSectionKind Kind)
constexpr bool isCallableCC(CallingConv::ID CC)
LLVM_ABI 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.