57 #define DEBUG_TYPE "sancov"
64 "__sanitizer_cov_trace_pc_indir";
66 "__sanitizer_cov_trace_func_enter";
68 "__sanitizer_cov_trace_basic_block";
83 "__sanitizer_cov_trace_pc_guard";
85 "__sanitizer_cov_trace_pc_guard_init";
88 "sanitizer-coverage-level",
89 cl::desc(
"Sanitizer Coverage. 0: none, 1: entry block, 2: all blocks, "
90 "3: all blocks and critical edges, "
91 "4: above plus indirect calls"),
95 "sanitizer-coverage-block-threshold",
96 cl::desc(
"Use a callback with a guard check inside it if there are"
97 " more than this number of blocks."),
102 cl::desc(
"Experimental basic-block tracing: insert "
103 "callbacks at every basic block"),
107 cl::desc(
"Experimental pc tracing"),
111 cl::desc(
"pc tracing with a guard"),
116 cl::desc(
"Tracing of CMP and similar instructions"),
120 cl::desc(
"Tracing of DIV instructions"),
124 cl::desc(
"Tracing of GEP instructions"),
129 cl::desc(
"Reduce the number of instrumented blocks"),
139 cl::desc(
"Experimental 8-bit counters"),
146 switch (LegacyCoverageLevel) {
182 class SanitizerCoverageModule :
public ModulePass {
184 SanitizerCoverageModule(
189 bool runOnModule(
Module &M)
override;
192 StringRef getPassName()
const override {
return "SanitizerCoverageModule"; }
200 void InjectCoverageForIndirectCalls(
Function &
F,
210 void CreateFunctionGuardArray(
size_t NumGuards,
Function &
F);
214 unsigned NumberOfInstrumentedBlocks() {
215 return SanCovFunction->getNumUses() +
216 SanCovWithCheckFunction->getNumUses() + SanCovTraceBB->getNumUses() +
217 SanCovTraceEnter->getNumUses();
221 Function *SanCovIndirCallFunction, *SanCovTracePCIndir;
222 Function *SanCovTraceEnter, *SanCovTraceBB, *SanCovTracePC, *SanCovTracePCGuard;
223 Function *SanCovTraceCmpFunction[4];
224 Function *SanCovTraceDivFunction[2];
226 Function *SanCovTraceSwitchFunction;
228 Type *IntptrTy, *IntptrPtrTy, *Int64Ty, *Int64PtrTy, *
Int32Ty, *Int32PtrTy;
236 bool HasSancovGuardsSection;
243 bool SanitizerCoverageModule::runOnModule(
Module &M) {
249 HasSancovGuardsSection =
false;
266 SanCovIndirCallFunction =
269 SanCovTraceCmpFunction[0] =
278 SanCovTraceCmpFunction[3] =
282 SanCovTraceDivFunction[0] =
285 SanCovTraceDivFunction[1] =
288 SanCovTraceGepFunction =
291 SanCovTraceSwitchFunction =
314 if (!Options.TracePCGuard)
317 nullptr,
"__sancov_gen_cov_tmp");
318 if (Options.Use8bitCounters)
319 EightBitCounterArray =
321 nullptr,
"__sancov_gen_cov_tmp");
326 auto N = NumberOfInstrumentedBlocks();
329 if (!Options.TracePCGuard) {
338 GuardArray->replaceAllUsesWith(
339 IRB.CreatePointerCast(RealGuardArray, Int32PtrTy));
340 GuardArray->eraseFromParent();
344 if (Options.Use8bitCounters) {
346 static const int CounterAlignment = 16;
351 RealEightBitCounterArray->
setAlignment(CounterAlignment);
352 EightBitCounterArray->replaceAllUsesWith(
353 IRB.CreatePointerCast(RealEightBitCounterArray, Int8PtrTy));
354 EightBitCounterArray->eraseFromParent();
362 ModNameStrConst,
"__sancov_gen_modname");
363 if (Options.TracePCGuard) {
364 if (HasSancovGuardsSection) {
368 const char *
Prefix[2] = {
"__start_",
"__stop_"};
369 for (
int i = 0;
i < 2;
i++) {
377 {Int32PtrTy, Int32PtrTy},
378 {IRB.CreatePointerCast(Bounds[0], Int32PtrTy),
379 IRB.CreatePointerCast(Bounds[1], Int32PtrTy)});
383 }
else if (!Options.TracePC) {
387 {Int32PtrTy, IntptrTy, Int8PtrTy, Int8PtrTy},
388 {IRB.CreatePointerCast(RealGuardArray, Int32PtrTy),
390 Options.Use8bitCounters
391 ? IRB.CreatePointerCast(RealEightBitCounterArray, Int8PtrTy)
393 IRB.CreatePointerCast(ModuleName, Int8PtrTy)});
444 bool SanitizerCoverageModule::runOnFunction(
Function &
F) {
447 if (F.
getName().
find(
".module_ctor") != std::string::npos)
453 if (F.
getName() ==
"__local_stdio_printf_options" ||
454 F.
getName() ==
"__local_stdio_scanf_options")
472 &getAnalysis<DominatorTreeWrapperPass>(
F).getDomTree();
474 &getAnalysis<PostDominatorTreeWrapperPass>(
F).getPostDomTree();
479 for (
auto &Inst : BB) {
480 if (Options.IndirectCalls) {
482 if (CS && !
CS.getCalledFunction())
485 if (Options.TraceCmp) {
486 if (isa<ICmpInst>(&Inst))
488 if (isa<SwitchInst>(&Inst))
491 if (Options.TraceDiv)
493 if (BO->getOpcode() == Instruction::SDiv ||
494 BO->getOpcode() == Instruction::UDiv)
496 if (Options.TraceGep)
502 InjectCoverage(F, BlocksToInstrument);
503 InjectCoverageForIndirectCalls(F, IndirCalls);
504 InjectTraceForCmp(F, CmpTraceTargets);
505 InjectTraceForSwitch(F, SwitchTraceTargets);
506 InjectTraceForDiv(F, DivTraceTargets);
507 InjectTraceForGep(F, GepTraceTargets);
510 void SanitizerCoverageModule::CreateFunctionGuardArray(
size_t NumGuards,
512 if (!Options.TracePCGuard)
return;
513 HasSancovGuardsSection =
true;
519 FunctionGuardArray->setComdat(
Comdat);
523 bool SanitizerCoverageModule::InjectCoverage(
Function &F,
525 if (AllBlocks.
empty())
return false;
526 switch (Options.CoverageType) {
530 CreateFunctionGuardArray(1, F);
535 CreateFunctionGuardArray(AllBlocks.
size(),
F);
536 for (
size_t i = 0,
N = AllBlocks.
size();
i <
N;
i++)
537 InjectCoverageAtBlock(F, *AllBlocks[
i], i, UseCalls);
550 void SanitizerCoverageModule::InjectCoverageForIndirectCalls(
552 if (IndirCalls.
empty())
554 const int CacheSize = 16;
555 const int CacheAlignment = 64;
557 for (
auto I : IndirCalls) {
560 Value *Callee =
CS.getCalledValue();
561 if (isa<InlineAsm>(Callee))
567 if (Options.TracePC || Options.TracePCGuard)
568 IRB.CreateCall(SanCovTracePCIndir,
569 IRB.CreatePointerCast(Callee, IntptrTy));
571 IRB.CreateCall(SanCovIndirCallFunction,
572 {IRB.CreatePointerCast(Callee, IntptrTy),
573 IRB.CreatePointerCast(CalleeCache, IntptrTy)});
581 void SanitizerCoverageModule::InjectTraceForSwitch(
583 for (
auto I : SwitchTraceTargets) {
587 Value *Cond =
SI->getCondition();
589 Int64Ty->getScalarSizeInBits())
595 Int64Ty->getScalarSizeInBits())
596 Cond = IRB.CreateIntCast(Cond, Int64Ty,
false);
597 for (
auto It :
SI->cases()) {
600 Int64Ty->getScalarSizeInBits())
604 std::sort(Initializers.
begin() + 2, Initializers.
end(),
606 return cast<ConstantInt>(
A)->getLimitedValue() <
607 cast<ConstantInt>(
B)->getLimitedValue();
613 "__sancov_gen_cov_switch_values");
614 IRB.CreateCall(SanCovTraceSwitchFunction,
615 {Cond, IRB.CreatePointerCast(GV, Int64PtrTy)});
620 void SanitizerCoverageModule::InjectTraceForDiv(
622 for (
auto BO : DivTraceTargets) {
624 Value *A1 = BO->getOperand(1);
625 if (isa<ConstantInt>(A1))
continue;
628 uint64_t TypeSize =
DL->getTypeStoreSizeInBits(A1->
getType());
629 int CallbackIdx = TypeSize == 32 ? 0 :
630 TypeSize == 64 ? 1 : -1;
631 if (CallbackIdx < 0)
continue;
633 IRB.CreateCall(SanCovTraceDivFunction[CallbackIdx],
634 {IRB.CreateIntCast(A1, Ty,
true)});
638 void SanitizerCoverageModule::InjectTraceForGep(
640 for (
auto GEP : GepTraceTargets) {
642 for (
auto I =
GEP->idx_begin();
I !=
GEP->idx_end(); ++
I)
643 if (!isa<ConstantInt>(*
I) && (*I)->getType()->isIntegerTy())
644 IRB.CreateCall(SanCovTraceGepFunction,
645 {IRB.CreateIntCast(*
I, IntptrTy,
true)});
649 void SanitizerCoverageModule::InjectTraceForCmp(
651 for (
auto I : CmpTraceTargets) {
658 uint64_t TypeSize =
DL->getTypeStoreSizeInBits(A0->
getType());
659 int CallbackIdx = TypeSize == 8 ? 0 :
662 TypeSize == 64 ? 3 : -1;
663 if (CallbackIdx < 0)
continue;
665 auto Ty = Type::getIntNTy(*C, TypeSize);
667 SanCovTraceCmpFunction[CallbackIdx],
668 {IRB.CreateIntCast(A0, Ty,
true), IRB.CreateIntCast(A1, Ty,
true)});
673 void SanitizerCoverageModule::SetNoSanitizeMetadata(
Instruction *
I) {
675 MDNode::get(*C,
None));
679 size_t Idx,
bool UseCalls) {
685 EntryLoc = DebugLoc::get(
SP->getScopeLine(), 0,
SP);
691 EntryLoc = IP->getDebugLoc();
695 IRB.SetCurrentDebugLocation(EntryLoc);
696 if (Options.TracePC) {
697 IRB.CreateCall(SanCovTracePC);
698 IRB.CreateCall(EmptyAsm, {});
699 }
else if (Options.TracePCGuard) {
700 auto GuardPtr = IRB.CreateIntToPtr(
701 IRB.CreateAdd(IRB.CreatePointerCast(FunctionGuardArray, IntptrTy),
702 ConstantInt::get(IntptrTy, Idx * 4)),
705 auto GuardLoad = IRB.CreateLoad(GuardPtr);
706 GuardLoad->setAtomic(AtomicOrdering::Monotonic);
707 GuardLoad->setAlignment(8);
708 SetNoSanitizeMetadata(GuardLoad);
709 auto Cmp = IRB.CreateICmpNE(
710 GuardLoad, Constant::getNullValue(GuardLoad->getType()));
713 IRB.SetInsertPoint(
Ins);
714 IRB.SetCurrentDebugLocation(EntryLoc);
716 IRB.CreateCall(SanCovTracePCGuard, GuardPtr);
717 IRB.CreateCall(EmptyAsm, {});
719 Value *GuardP = IRB.CreateAdd(
720 IRB.CreatePointerCast(GuardArray, IntptrTy),
721 ConstantInt::get(IntptrTy, (1 + NumberOfInstrumentedBlocks()) * 4));
722 GuardP = IRB.CreateIntToPtr(GuardP, Int32PtrTy);
723 if (Options.TraceBB) {
724 IRB.CreateCall(IsEntryBB ? SanCovTraceEnter : SanCovTraceBB, GuardP);
725 }
else if (UseCalls) {
726 IRB.CreateCall(SanCovWithCheckFunction, GuardP);
729 Load->
setAtomic(AtomicOrdering::Monotonic);
731 SetNoSanitizeMetadata(Load);
733 IRB.CreateICmpSGE(Constant::getNullValue(Load->
getType()), Load);
736 IRB.SetInsertPoint(Ins);
737 IRB.SetCurrentDebugLocation(EntryLoc);
739 IRB.CreateCall(SanCovFunction, GuardP);
740 IRB.CreateCall(EmptyAsm, {});
744 if (Options.Use8bitCounters) {
745 IRB.SetInsertPoint(&*IP);
747 IRB.CreatePointerCast(EightBitCounterArray, IntptrTy),
748 ConstantInt::get(IntptrTy, NumberOfInstrumentedBlocks() - 1));
749 P = IRB.CreateIntToPtr(P, IRB.getInt8PtrTy());
751 Value *Inc = IRB.CreateAdd(LI, ConstantInt::get(IRB.getInt8Ty(), 1));
753 SetNoSanitizeMetadata(LI);
754 SetNoSanitizeMetadata(SI);
760 "SanitizerCoverage: TODO."
766 "SanitizerCoverage: TODO."
771 return new SanitizerCoverageModule(Options);
void setVisibility(VisibilityTypes V)
static const char *const SanCovTraceEnterName
void push_back(const T &Elt)
A parsed version of the target data layout string in and methods for querying it. ...
static Constant * getString(LLVMContext &Context, StringRef Initializer, bool AddNull=true)
This method constructs a CDS and initializes it with a text string.
static const uint64_t SanCtorAndDtorPriority
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
Function * checkSanitizerInterfaceFunction(Constant *FuncOrBitcast)
A Module instance is used to store all the information related to an LLVM module. ...
static cl::opt< unsigned > ClCoverageBlockThreshold("sanitizer-coverage-block-threshold", cl::desc("Use a callback with a guard check inside it if there are"" more than this number of blocks."), cl::Hidden, cl::init(500))
static bool isFullPostDominator(const BasicBlock *BB, const PostDominatorTree *PDT)
static const char *const SanCovName
Like Internal, but omit from symbol table.
Externally visible function.
uint64_t alignTo(uint64_t Value, uint64_t Align, uint64_t Skew=0)
Returns the next integer (mod 2**64) that is greater than or equal to Value and is a multiple of Alig...
An instruction for reading from memory.
static IntegerType * getInt64Ty(LLVMContext &C)
unsigned SplitAllCriticalEdges(Function &F, const CriticalEdgeSplittingOptions &Options=CriticalEdgeSplittingOptions())
Loop over all of the edges in the CFG, breaking critical edges as they are found. ...
static const char *const SanCovTracePCName
static const char *const SanCovModuleInitName
void setAlignment(unsigned Align)
static IntegerType * getInt16Ty(LLVMContext &C)
static cl::opt< int > ClCoverageLevel("sanitizer-coverage-level", cl::desc("Sanitizer Coverage. 0: none, 1: entry block, 2: all blocks, ""3: all blocks and critical edges, ""4: above plus indirect calls"), cl::Hidden, cl::init(0))
static const char *const SanCovTraceSwitchName
static Constant * getNullValue(Type *Ty)
Constructor to create a '0' constant of arbitrary type.
StringRef getName() const
Return a constant reference to the value's name.
AnalysisUsage & addRequired()
#define INITIALIZE_PASS_DEPENDENCY(depName)
static const char *const SanCovTraceCmp2
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
Constant * getPersonalityFn() const
Get the personality function associated with this function.
Interval::succ_iterator succ_begin(Interval *I)
succ_begin/succ_end - define methods so that Intervals may be used just like BasicBlocks can with the...
static const char *const SanCovTraceGep
void setAtomic(AtomicOrdering Ordering, SynchronizationScope SynchScope=CrossThread)
LLVM_NODISCARD LLVM_ATTRIBUTE_ALWAYS_INLINE bool startswith(StringRef Prefix) const
Check if this string starts with the given Prefix.
static cl::opt< bool > ClDIVTracing("sanitizer-coverage-trace-divs", cl::desc("Tracing of DIV instructions"), cl::Hidden, cl::init(false))
Class to represent array types.
static bool shouldInstrumentBlock(const Function &F, const BasicBlock *BB, const DominatorTree *DT, const PostDominatorTree *PDT)
static FunctionType * get(Type *Result, ArrayRef< Type * > Params, bool isVarArg)
This static method is the primary way of constructing a FunctionType.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory)...
static cl::opt< bool > ClCMPTracing("sanitizer-coverage-trace-compares", cl::desc("Tracing of CMP and similar instructions"), cl::Hidden, cl::init(false))
static GCRegistry::Add< OcamlGC > B("ocaml","ocaml 3.10-compatible GC")
An instruction for storing to memory.
static const char *const SanCovTracePCGuardName
Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree...
size_t size() const
size - Get the array size.
Interval::succ_iterator succ_end(Interval *I)
an instruction for type-safe pointer arithmetic to access elements of arrays and structs ...
static const char *const SanCovTracePCIndirName
initializer< Ty > init(const Ty &Val)
static const char *const SanCovTraceCmp1
LLVM_NODISCARD LLVM_ATTRIBUTE_ALWAYS_INLINE size_t find(char C, size_t From=0) const
Search for the first character C in the string.
Constant * getOrInsertFunction(StringRef Name, FunctionType *T, AttributeSet AttributeList)
Look up the specified function in the module symbol table.
LLVM Basic Block Representation.
bool dominates(const DomTreeNodeBase< NodeT > *A, const DomTreeNodeBase< NodeT > *B) const
dominates - Returns true iff A dominates B.
The instances of the Type class are immutable: once they are created, they are never changed...
This is an important class for using LLVM in a threaded context.
static const char *const SanCovTraceDiv4
static cl::opt< bool > ClExperimentalTracing("sanitizer-coverage-experimental-tracing", cl::desc("Experimental basic-block tracing: insert ""callbacks at every basic block"), cl::Hidden, cl::init(false))
const Comdat * getComdat() const
This is an important base class in LLVM.
LLVM_ATTRIBUTE_ALWAYS_INLINE iterator begin()
static Constant * get(ArrayType *T, ArrayRef< Constant * > V)
Interval::pred_iterator pred_begin(Interval *I)
pred_begin/pred_end - define methods so that Intervals may be used just like BasicBlocks can with the...
bool hasPersonalityFn() const
Check whether this function has a personality function.
EHPersonality classifyEHPersonality(const Value *Pers)
See if the given exception handling personality function is one that we understand.
Represent the analysis usage information of a pass.
static Type * getVoidTy(LLVMContext &C)
This instruction compares its operands according to the predicate given to the constructor.
INITIALIZE_PASS_END(RegBankSelect, DEBUG_TYPE,"Assign register bank of generic virtual registers", false, false) RegBankSelect
Interval::pred_iterator pred_end(Interval *I)
static cl::opt< bool > ClPruneBlocks("sanitizer-coverage-prune-blocks", cl::desc("Reduce the number of instrumented blocks"), cl::Hidden, cl::init(true))
static cl::opt< bool > ClTracePCGuard("sanitizer-coverage-trace-pc-guard", cl::desc("pc tracing with a guard"), cl::Hidden, cl::init(false))
static const char *const SanCovTraceCmp4
bool empty() const
empty - Check if the array is empty.
void setAlignment(unsigned Align)
static const char *const SanCovTraceCmp8
MDNode * createBranchWeights(uint32_t TrueWeight, uint32_t FalseWeight)
Return metadata containing two branch weights.
void setMetadata(unsigned KindID, MDNode *Node)
Set the metadata of the specified kind to the specified node.
bool dominates(const Instruction *Def, const Use &U) const
Return true if Def dominates a use in User.
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
std::pair< Function *, Function * > createSanitizerCtorAndInitFunctions(Module &M, StringRef CtorName, StringRef InitName, ArrayRef< Type * > InitArgTypes, ArrayRef< Value * > InitArgs, StringRef VersionCheckName=StringRef())
Creates sanitizer constructor function, and calls sanitizer's init function from it.
Iterator for intrusive lists based on ilist_node.
static const char *const SanCovModuleCtorName
static PointerType * getUnqual(Type *ElementType)
This constructs a pointer to an object of the specified type in the generic address space (address sp...
static bool isFullDominator(const BasicBlock *BB, const DominatorTree *DT)
unsigned getScalarSizeInBits() const LLVM_READONLY
If this is a vector type, return the getPrimitiveSizeInBits value for the element type...
const Module * getModule() const
Return the module owning the function this instruction belongs to or nullptr it the function does not...
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small...
Module.h This file contains the declarations for the Module class.
Type * getType() const
All values are typed, get the type of this value.
TerminatorInst * SplitBlockAndInsertIfThen(Value *Cond, Instruction *SplitBefore, bool Unreachable, MDNode *BranchWeights=nullptr, DominatorTree *DT=nullptr, LoopInfo *LI=nullptr)
Split the containing block at the specified instruction - everything before SplitBefore stays in the ...
static IntegerType * getIntNTy(LLVMContext &C, unsigned N)
enum llvm::SanitizerCoverageOptions::Type CoverageType
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.
void appendToGlobalCtors(Module &M, Function *F, int Priority, Constant *Data=nullptr)
Append F to the list of global ctors of module M with the given Priority.
const BasicBlock & getEntryBlock() const
BasicBlock::iterator PrepareToSplitEntryBlock(BasicBlock &BB, BasicBlock::iterator IP)
Instrumentation passes often insert conditional checks into entry blocks.
static GCRegistry::Add< ShadowStackGC > C("shadow-stack","Very portable GC for uncooperative code generators")
DISubprogram * getSubprogram() const
Get the attached subprogram.
bool isIntegerTy() const
True if this is an instance of IntegerType.
static cl::opt< bool > ClUse8bitCounters("sanitizer-coverage-8bit-counters", cl::desc("Experimental 8-bit counters"), cl::Hidden, cl::init(false))
static Constant * getCast(unsigned ops, Constant *C, Type *Ty, bool OnlyIfReduced=false)
Convenience function for getting a Cast operation.
PostDominatorTree Class - Concrete subclass of DominatorTree that is used to compute the post-dominat...
static cl::opt< bool > ClExperimentalTracePC("sanitizer-coverage-trace-pc", cl::desc("Experimental pc tracing"), cl::Hidden, cl::init(false))
static const char *const SanCovWithCheckName
const DataLayout & getDataLayout() const
Get the data layout for the module's target platform.
LLVM_ATTRIBUTE_ALWAYS_INLINE iterator end()
static IntegerType * getInt32Ty(LLVMContext &C)
static cl::opt< bool > ClGEPTracing("sanitizer-coverage-trace-geps", cl::desc("Tracing of GEP instructions"), cl::Hidden, cl::init(false))
static const char *const SanCovTraceDiv8
static const char *const SanCovTracePCGuardSection
TerminatorInst * getTerminator()
Returns the terminator instruction if the block is well formed or null if the block is not well forme...
LLVM_ATTRIBUTE_ALWAYS_INLINE size_type size() const
ModulePass class - This class is used to implement unstructured interprocedural optimizations and ana...
static ArrayType * get(Type *ElementType, uint64_t NumElements)
This static method is the primary way to construct an ArrayType.
ModulePass * createSanitizerCoverageModulePass(const SanitizerCoverageOptions &Options=SanitizerCoverageOptions())
Rename collisions when linking (static functions).
static InlineAsm * get(FunctionType *Ty, StringRef AsmString, StringRef Constraints, bool hasSideEffects, bool isAlignStack=false, AsmDialect asmDialect=AD_ATT)
InlineAsm::get - Return the specified uniqued inline asm string.
INITIALIZE_PASS_BEGIN(SanitizerCoverageModule,"sancov","SanitizerCoverage: TODO.""ModulePass", false, false) INITIALIZE_PASS_END(SanitizerCoverageModule
bool isAsynchronousEHPersonality(EHPersonality Pers)
Returns true if this personality function catches asynchronous exceptions.
static const char *const SanCovTracePCGuardInitName
Module * getParent()
Get the module that this global value is contained inside of...
LLVM Value Representation.
void initializeSanitizerCoverageModulePass(PassRegistry &)
StringRef - Represent a constant reference to a string, i.e.
Legacy analysis pass which computes a DominatorTree.
static const char *const SanCovIndirCallName
iterator getFirstInsertionPt()
Returns an iterator to the first instruction in this block that is suitable for inserting a non-PHI i...
unsigned getMDKindID(StringRef Name) const
Return a unique non-zero ID for the specified metadata kind.
static GCRegistry::Add< ErlangGC > A("erlang","erlang-compatible garbage collector")
static IntegerType * getInt8Ty(LLVMContext &C)
static const char *const SanCovTraceBBName
LLVMContext & getContext() const
Get the global data context.