49#define DEBUG_TYPE "tysan"
57 "__tysan_shadow_memory_address";
65STATISTIC(NumInstrumentedAccesses,
"Number of instrumented accesses");
74 void instrumentGlobals(
Module &M);
81 void initializeCallbacks(
Module &M);
88 bool IsWrite,
Value *ShadowBase,
89 Value *AppMemMask,
bool ForceSetType,
90 bool SanitizeFunction,
91 TypeDescriptorsMapTy &TypeDescriptors,
99 std::string getAnonymousStructIdentifier(
const MDNode *MD,
100 TypeNameMapTy &TypeNames);
101 bool generateTypeDescriptor(
const MDNode *MD,
102 TypeDescriptorsMapTy &TypeDescriptors,
103 TypeNameMapTy &TypeNames,
Module &M);
104 bool generateBaseTypeDescriptor(
const MDNode *MD,
105 TypeDescriptorsMapTy &TypeDescriptors,
106 TypeNameMapTy &TypeNames,
Module &M);
108 const Triple TargetTriple;
119 Function *TysanGlobalsSetTypeFunction;
123TypeSanitizer::TypeSanitizer(
Module &M)
124 : TargetTriple(
Triple(
M.getTargetTriple())),
125 AnonNameRegex(
"^_ZTS.*N[1-9][0-9]*_GLOBAL__N") {
127 IntptrTy =
DL.getIntPtrType(
M.getContext());
128 PtrShift =
countr_zero(IntptrTy->getPrimitiveSizeInBits() / 8);
130 TysanGlobalsSetTypeFunction =
M.getFunction(
"__tysan_set_globals_types");
131 initializeCallbacks(M);
134void TypeSanitizer::initializeCallbacks(
Module &M) {
136 OrdTy = IRB.getInt32Ty();
153void TypeSanitizer::instrumentGlobals(
Module &M) {
154 TysanGlobalsSetTypeFunction =
nullptr;
156 NamedMDNode *Globals =
M.getNamedMetadata(
"llvm.tysan.globals");
168 Value *ShadowBase = getShadowBase(*TysanGlobalsSetTypeFunction);
169 Value *AppMemMask = getAppMemMask(*TysanGlobalsSetTypeFunction);
170 TypeDescriptorsMapTy TypeDescriptors;
171 TypeNameMapTy TypeNames;
173 for (
const auto &GMD : Globals->
operands()) {
174 auto *GV = mdconst::dyn_extract_or_null<GlobalVariable>(GMD->getOperand(0));
177 const MDNode *TBAAMD = cast<MDNode>(GMD->getOperand(1));
178 if (!generateBaseTypeDescriptor(TBAAMD, TypeDescriptors, TypeNames, M))
182 TysanGlobalsSetTypeFunction->getEntryBlock().getTerminator());
183 Type *AccessTy = GV->getValueType();
185 uint64_t AccessSize =
DL.getTypeStoreSize(AccessTy);
186 instrumentWithShadowUpdate(IRB, TBAAMD, GV, AccessSize,
false,
false,
187 ShadowBase, AppMemMask,
true,
false,
188 TypeDescriptors,
DL);
191 if (TysanGlobalsSetTypeFunction) {
192 IRBuilder<> IRB(cast<Function>(TysanCtorFunction.getCallee())
195 IRB.CreateCall(TysanGlobalsSetTypeFunction, {});
199static const char LUT[] =
"0123456789abcdef";
204 Output.reserve(Output.size() + 3 *
Length);
205 for (
size_t i = 0; i <
Length; ++i) {
206 const unsigned char c =
Name[i];
217 Output.push_back(
'_');
218 Output.push_back(
LUT[c >> 4]);
219 Output.push_back(
LUT[c & 15]);
226TypeSanitizer::getAnonymousStructIdentifier(
const MDNode *MD,
227 TypeNameMapTy &TypeNames) {
235 auto TNI = TypeNames.find(MemberNode);
236 std::string MemberName;
237 if (TNI != TypeNames.end()) {
238 MemberName = TNI->second;
246 if (MemberName.empty())
247 MemberName = getAnonymousStructIdentifier(MemberNode, TypeNames);
248 if (MemberName.empty())
250 TypeNames[MemberNode] = MemberName;
257 mdconst::extract<ConstantInt>(MD->
getOperand(i + 1))->getZExtValue();
263 Hash.
final(HashResult);
264 return "__anonymous_" + std::string(HashResult.
digest().
str());
267bool TypeSanitizer::generateBaseTypeDescriptor(
268 const MDNode *MD, TypeDescriptorsMapTy &TypeDescriptors,
269 TypeNameMapTy &TypeNames,
Module &M) {
279 Name = getAnonymousStructIdentifier(MD, TypeNames);
282 TypeNames[MD] =
Name;
286 dyn_cast_or_null<GlobalVariable>(
M.getNamedValue(EncodedName));
288 TypeDescriptors[MD] = GV;
299 auto TDI = TypeDescriptors.find(MemberNode);
300 if (TDI != TypeDescriptors.end()) {
303 if (!generateBaseTypeDescriptor(MemberNode, TypeDescriptors, TypeNames,
307 Member = TypeDescriptors[MemberNode];
311 mdconst::extract<ConstantInt>(MD->
getOperand(i + 1))->getZExtValue();
329 PushTDSub(ConstantInt::get(IntptrTy, 2));
330 PushTDSub(ConstantInt::get(IntptrTy, Members.
size()));
338 bool ShouldBeComdat = !AnonNameRegex.match(NameNode->
getString());
339 for (
auto &Member : Members) {
341 PushTDSub(ConstantInt::get(IntptrTy,
Member.second));
354 M.insertGlobalVariable(TDGV);
356 if (ShouldBeComdat) {
357 if (TargetTriple.isOSBinFormatELF()) {
358 Comdat *TDComdat =
M.getOrInsertComdat(EncodedName);
364 TypeDescriptors[MD] = TDGV;
368bool TypeSanitizer::generateTypeDescriptor(
369 const MDNode *MD, TypeDescriptorsMapTy &TypeDescriptors,
370 TypeNameMapTy &TypeNames,
Module &M) {
389 auto TDI = TypeDescriptors.find(BaseNode);
390 if (TDI != TypeDescriptors.end()) {
393 if (!generateBaseTypeDescriptor(BaseNode, TypeDescriptors, TypeNames, M))
396 Base = TypeDescriptors[BaseNode];
400 TDI = TypeDescriptors.find(AccessNode);
401 if (TDI != TypeDescriptors.end()) {
404 if (!generateBaseTypeDescriptor(AccessNode, TypeDescriptors, TypeNames, M))
407 Access = TypeDescriptors[AccessNode];
411 mdconst::extract<ConstantInt>(MD->
getOperand(2))->getZExtValue();
412 std::string EncodedName =
413 std::string(
Base->getName()) +
"_o_" + utostr(
Offset);
416 dyn_cast_or_null<GlobalVariable>(
M.getNamedValue(EncodedName));
418 TypeDescriptors[MD] = GV;
429 ConstantInt::get(IntptrTy,
Offset));
431 bool ShouldBeComdat = cast<GlobalVariable>(
Base)->getLinkage() ==
439 M.insertGlobalVariable(TDGV);
441 if (ShouldBeComdat) {
442 if (TargetTriple.isOSBinFormatELF()) {
443 Comdat *TDComdat =
M.getOrInsertComdat(EncodedName);
449 TypeDescriptors[MD] = TDGV;
457 return IRB.CreateLoad(IntptrTy, GlobalShadowAddress,
"shadow.base");
462 Value *GlobalAppMemMask =
464 return IRB.CreateLoad(IntptrTy, GlobalAppMemMask,
"app.mem.mask");
471 SmallVectorImpl<std::pair<Instruction *, MemoryLocation>> &MemoryAccesses,
477 if (Inst.getMetadata(LLVMContext::MD_nosanitize))
480 if (isa<LoadInst>(Inst) || isa<StoreInst>(Inst) ||
481 isa<AtomicCmpXchgInst>(Inst) || isa<AtomicRMWInst>(Inst)) {
495 MemoryAccesses.push_back(std::make_pair(&Inst, MLoc));
496 }
else if (isa<CallInst>(Inst) || isa<InvokeInst>(Inst)) {
497 if (
CallInst *CI = dyn_cast<CallInst>(&Inst))
500 if (isa<MemIntrinsic>(Inst)) {
502 }
else if (
auto *
II = dyn_cast<IntrinsicInst>(&Inst)) {
503 if (
II->getIntrinsicID() == Intrinsic::lifetime_start ||
504 II->getIntrinsicID() == Intrinsic::lifetime_end)
507 }
else if (isa<AllocaInst>(Inst)) {
516 if (&
F == TysanCtorFunction.getCallee() || &
F == TysanGlobalsSetTypeFunction)
518 initializeCallbacks(*
F.getParent());
529 for (
auto &
A :
F.args())
530 if (
A.hasByValAttr())
534 TypeDescriptorsMapTy TypeDescriptors;
535 TypeNameMapTy TypeNames;
537 for (
const MDNode *MD : TBAAMetadata) {
538 if (TypeDescriptors.count(MD))
541 if (!generateTypeDescriptor(MD, TypeDescriptors, TypeNames, M))
548 bool SanitizeFunction =
F.hasFnAttribute(Attribute::SanitizeType);
549 bool NeedsInstrumentation =
550 MemTypeResetInsts.
empty() && MemoryAccesses.
empty();
551 Instruction *ShadowBase = NeedsInstrumentation ? nullptr : getShadowBase(
F);
552 Instruction *AppMemMask = NeedsInstrumentation ? nullptr : getAppMemMask(
F);
553 for (
const auto &[
I, MLoc] : MemoryAccesses) {
555 assert(MLoc.Size.isPrecise());
556 if (instrumentWithShadowUpdate(
557 IRB, MLoc.AATags.TBAA,
const_cast<Value *
>(MLoc.Ptr),
558 MLoc.Size.getValue(),
I->mayReadFromMemory(),
I->mayWriteToMemory(),
559 ShadowBase, AppMemMask,
false, SanitizeFunction, TypeDescriptors,
561 ++NumInstrumentedAccesses;
566 for (
auto Inst : MemTypeResetInsts)
567 Res |= instrumentMemInst(Inst, ShadowBase, AppMemMask,
DL);
578 AppMemMask,
"app.ptr.masked"),
579 PtrShift,
"app.ptr.shifted"),
580 ShadowBase,
"shadow.ptr.int");
583bool TypeSanitizer::instrumentWithShadowUpdate(
585 bool IsRead,
bool IsWrite,
Value *ShadowBase,
Value *AppMemMask,
586 bool ForceSetType,
bool SanitizeFunction,
587 TypeDescriptorsMapTy &TypeDescriptors,
const DataLayout &
DL) {
590 TDGV = TypeDescriptors[TBAAMD];
597 ShadowBase, AppMemMask);
598 Type *Int8PtrPtrTy = PointerType::get(IRB.
getPtrTy(), 0);
602 auto SetType = [&]() {
607 for (
uint64_t i = 1; i < AccessSize; ++i) {
610 ConstantInt::get(IntptrTy, i << PtrShift),
611 "shadow.byte." +
Twine(i) +
".offset"),
612 Int8PtrPtrTy,
"shadow.byte." +
Twine(i) +
".ptr");
631 "should have handled case above");
635 if (!SanitizeFunction) {
643 NullTDTerm->
getParent()->setName(
"set.type");
702 Constant *
Flags = ConstantInt::get(OrdTy,
int(IsRead) | (
int(IsWrite) << 1));
708 &GoodTDTerm, UnlikelyBW);
723 Value *
Size = ConstantInt::get(OrdTy, AccessSize);
725 for (
uint64_t i = 1; i < AccessSize; ++i) {
727 IRB.
CreateAdd(ShadowDataInt, ConstantInt::get(IntptrTy, i << PtrShift)),
752 for (
uint64_t i = 1; i < AccessSize; ++i) {
754 IRB.
CreateAdd(ShadowDataInt, ConstantInt::get(IntptrTy, i << PtrShift)),
759 NotAllBadTD, IRB.
CreateICmpSGE(ILdTD, ConstantInt::get(IntptrTy, 0)));
777 if (
auto *
I = dyn_cast<Instruction>(V)) {
782 auto *
A = cast<Argument>(V);
784 BB = &
F->getEntryBlock();
788 if (IP->comesBefore(ShadowBase))
790 if (IP->comesBefore(AppMemMask))
795 bool NeedsMemMove =
false;
798 if (
auto *
A = dyn_cast<Argument>(V)) {
799 assert(
A->hasByValAttr() &&
"Type reset for non-byval argument?");
803 ConstantInt::get(IntptrTy,
DL.getTypeAllocSize(
A->getParamByValType()));
805 auto *
I = cast<Instruction>(V);
806 if (
auto *
MI = dyn_cast<MemIntrinsic>(
I)) {
807 if (
MI->getDestAddressSpace() != 0)
810 Dest =
MI->getDest();
813 if (
auto *MTI = dyn_cast<MemTransferInst>(
MI)) {
814 if (MTI->getSourceAddressSpace() == 0) {
815 Src = MTI->getSource();
816 NeedsMemMove = isa<MemMoveInst>(MTI);
819 }
else if (
auto *
II = dyn_cast<IntrinsicInst>(
I)) {
820 if (
II->getIntrinsicID() != Intrinsic::lifetime_start &&
821 II->getIntrinsicID() != Intrinsic::lifetime_end)
824 Size =
II->getArgOperand(0);
825 Dest =
II->getArgOperand(1);
826 }
else if (
auto *AI = dyn_cast<AllocaInst>(
I)) {
835 ConstantInt::get(IntptrTy,
836 DL.getTypeAllocSize(AI->getAllocatedType())));
844 ShadowBase = getShadowBase(*
F);
846 AppMemMask = getAppMemMask(*
F);
857 Align(1ull << PtrShift));
881 TypeSanitizer TySan(*
F.getParent());
889 std::tie(TysanCtorFunction, std::ignore) =
894 TypeSanitizer TySan(M);
895 TySan.instrumentGlobals(M);
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
Expand Atomic instructions
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
Module.h This file contains the declarations for the Module class.
This file provides utility analysis objects describing memory locations.
uint64_t IntrinsicInst * II
FunctionAnalysisManager FAM
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This file implements a set that has insertion order iteration characteristics.
This file defines the SmallSet class.
This file defines the SmallVector class.
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
static const char *const kTysanInitName
static Value * convertToShadowDataInt(IRBuilder<> &IRB, Value *Ptr, Type *IntptrTy, uint64_t PtrShift, Value *ShadowBase, Value *AppMemMask)
static const char *const kTysanShadowMemoryAddress
static const char *const kTysanGVNamePrefix
static const char *const kTysanModuleCtorName
static const char *const kTysanAppMemMask
void collectMemAccessInfo(Function &F, const TargetLibraryInfo &TLI, SmallVectorImpl< std::pair< Instruction *, MemoryLocation > > &MemoryAccesses, SmallSetVector< const MDNode *, 8 > &TBAAMetadata, SmallVectorImpl< Value * > &MemTypeResetInsts)
Collect all loads and stores, and for what TBAA nodes we need to generate type descriptors.
static cl::opt< bool > ClWritesAlwaysSetType("tysan-writes-always-set-type", cl::desc("Writes always set the type"), cl::Hidden, cl::init(false))
static const char *const kTysanCheckName
static std::string encodeName(StringRef Name)
A container for analyses that lazily runs them and caches their results.
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
AttributeList addFnAttribute(LLVMContext &C, Attribute::AttrKind Kind) const
Add a function attribute to the list.
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...
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...
This class represents a function call, abstracting a target machine's calling convention.
static Constant * getString(LLVMContext &Context, StringRef Initializer, bool AddNull=true)
This method constructs a CDS and initializes it with a text string.
static ConstantInt * getSigned(IntegerType *Ty, int64_t V)
Return a ConstantInt with the specified value for the specified type.
static Constant * get(StructType *T, ArrayRef< Constant * > V)
This is an important base class in LLVM.
static Constant * getNullValue(Type *Ty)
Constructor to create a '0' constant of arbitrary type.
A parsed version of the target data layout string in and methods for querying it.
A handy container for a FunctionType+Callee-pointer pair, which can be passed around as a single enti...
static Function * Create(FunctionType *Ty, LinkageTypes Linkage, unsigned AddrSpace, const Twine &N="", Module *M=nullptr)
void setComdat(Comdat *C)
@ InternalLinkage
Rename collisions when linking (static functions).
@ LinkOnceODRLinkage
Same, but only replaced by something equivalent.
Value * CreateZExtOrTrunc(Value *V, Type *DestTy, const Twine &Name="")
Create a ZExt or Trunc from the integer value V to DestTy.
Value * CreateICmpSGE(Value *LHS, Value *RHS, const Twine &Name="")
CallInst * CreateMemSet(Value *Ptr, Value *Val, uint64_t Size, MaybeAlign Align, bool isVolatile=false, MDNode *TBAATag=nullptr, MDNode *ScopeTag=nullptr, MDNode *NoAliasTag=nullptr)
Create and insert a memset to the specified pointer and the specified value.
BasicBlock::iterator GetInsertPoint() const
Value * CreateIntToPtr(Value *V, Type *DestTy, const Twine &Name="")
ConstantInt * getInt8(uint8_t C)
Get a constant 8-bit value.
Value * CreateICmpNE(Value *LHS, Value *RHS, const Twine &Name="")
Value * CreateBitCast(Value *V, Type *DestTy, const Twine &Name="")
LoadInst * CreateLoad(Type *Ty, Value *Ptr, const char *Name)
Provided to resolve 'CreateLoad(Ty, Ptr, "...")' correctly, instead of converting the string to 'bool...
Value * CreateShl(Value *LHS, Value *RHS, const Twine &Name="", bool HasNUW=false, bool HasNSW=false)
LLVMContext & getContext() const
Value * CreateAnd(Value *LHS, Value *RHS, const Twine &Name="")
StoreInst * CreateStore(Value *Val, Value *Ptr, bool isVolatile=false)
Value * CreateAdd(Value *LHS, Value *RHS, const Twine &Name="", bool HasNUW=false, bool HasNSW=false)
Value * CreatePtrToInt(Value *V, Type *DestTy, const Twine &Name="")
ConstantInt * getFalse()
Get the constant value for i1 false.
Value * CreateIsNotNull(Value *Arg, const Twine &Name="")
Return a boolean value testing if Arg != 0.
CallInst * CreateCall(FunctionType *FTy, Value *Callee, ArrayRef< Value * > Args={}, const Twine &Name="", MDNode *FPMathTag=nullptr)
Value * CreateOr(Value *LHS, Value *RHS, const Twine &Name="")
PointerType * getPtrTy(unsigned AddrSpace=0)
Fetch the type representing a pointer.
Value * CreateIsNull(Value *Arg, const Twine &Name="")
Return a boolean value testing if Arg == 0.
void SetInsertPoint(BasicBlock *TheBB)
This specifies that created instructions should be appended to the end of the specified block.
void SetInstDebugLocation(Instruction *I) const
If this builder has a current debug location, set it on the specified instruction.
CallInst * CreateMemCpy(Value *Dst, MaybeAlign DstAlign, Value *Src, MaybeAlign SrcAlign, uint64_t Size, bool isVolatile=false, MDNode *TBAATag=nullptr, MDNode *TBAAStructTag=nullptr, MDNode *ScopeTag=nullptr, MDNode *NoAliasTag=nullptr)
Create and insert a memcpy between the specified pointers.
CallInst * CreateMemMove(Value *Dst, MaybeAlign DstAlign, Value *Src, MaybeAlign SrcAlign, uint64_t Size, bool isVolatile=false, MDNode *TBAATag=nullptr, MDNode *ScopeTag=nullptr, MDNode *NoAliasTag=nullptr)
Value * CreateMul(Value *LHS, Value *RHS, const Twine &Name="", bool HasNUW=false, bool HasNSW=false)
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
Class to represent integer types.
This is an important class for using LLVM in a threaded context.
void update(ArrayRef< uint8_t > Data)
Updates the hash for the byte stream provided.
void final(MD5Result &Result)
Finishes off the hash and puts the result in result.
MDNode * createBranchWeights(uint32_t TrueWeight, uint32_t FalseWeight, bool IsExpected=false)
Return metadata containing two branch weights.
const MDOperand & getOperand(unsigned I) const
unsigned getNumOperands() const
Return number of MDNode operands.
LLVMContext & getContext() const
StringRef getString() const
Representation for a specific memory location.
static MemoryLocation get(const LoadInst *LI)
Return a location with information about the memory reference by the given instruction.
AAMDNodes AATags
The metadata nodes which describes the aliasing of the location (each member is null if that kind of ...
const Value * Ptr
The address of the start of the location.
A Module instance is used to store all the information related to an LLVM module.
iterator_range< op_iterator > operands()
A set of analyses that are preserved following a run of a transformation pass.
static PreservedAnalyses none()
Convenience factory function for the empty preserved set.
static ReturnInst * Create(LLVMContext &C, Value *retVal=nullptr, InsertPosition InsertBefore=nullptr)
bool insert(const value_type &X)
Insert a new element into the SetVector.
A SetVector that performs no allocations if smaller than a certain size.
StringRef str() const
Explicit conversion to StringRef.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
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.
std::string str() const
str - Get the contents as an std::string.
Class to represent struct types.
static StructType * get(LLVMContext &Context, ArrayRef< Type * > Elements, bool isPacked=false)
This static method is the primary way to create a literal StructType.
Analysis pass providing the TargetLibraryInfo.
Provides information about what library functions are available for the current target.
Triple - Helper class for working with autoconf configuration names.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
The instances of the Type class are immutable: once they are created, they are never changed.
unsigned getPointerAddressSpace() const
Get the address space of this pointer or pointer vector type.
static Type * getVoidTy(LLVMContext &C)
bool isSized(SmallPtrSetImpl< Type * > *Visited=nullptr) const
Return true if it makes sense to take the size of this type.
LLVM Value Representation.
Type * getType() const
All values are typed, get the type of this value.
bool isSwiftError() const
Return true if this value is a swifterror value.
const ParentTy * getParent() const
self_iterator getIterator()
NodeTy * getNextNode()
Get the next node, or nullptr for the list tail.
@ C
The default llvm calling convention, compatible with C.
initializer< Ty > init(const Ty &Val)
This is an optimization pass for GlobalISel generic memory operations.
int countr_zero(T Val)
Count number of 0's from the least significant bit to the most stopping at the first 1.
std::pair< Function *, FunctionCallee > createSanitizerCtorAndInitFunctions(Module &M, StringRef CtorName, StringRef InitName, ArrayRef< Type * > InitArgTypes, ArrayRef< Value * > InitArgs, StringRef VersionCheckName=StringRef(), bool Weak=false)
Creates sanitizer constructor function, and calls sanitizer's init function from it.
void SplitBlockAndInsertIfThenElse(Value *Cond, BasicBlock::iterator SplitBefore, Instruction **ThenTerm, Instruction **ElseTerm, MDNode *BranchWeights=nullptr, DomTreeUpdater *DTU=nullptr, LoopInfo *LI=nullptr)
SplitBlockAndInsertIfThenElse is similar to SplitBlockAndInsertIfThen, but also creates the ElseBlock...
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.
Instruction * SplitBlockAndInsertIfThen(Value *Cond, BasicBlock::iterator SplitBefore, bool Unreachable, MDNode *BranchWeights=nullptr, DomTreeUpdater *DTU=nullptr, LoopInfo *LI=nullptr, BasicBlock *ThenBlock=nullptr)
Split the containing block at the specified instruction - everything before SplitBefore stays in the ...
void maybeMarkSanitizerLibraryCallNoBuiltin(CallInst *CI, const TargetLibraryInfo *TLI)
Given a CallInst, check if it calls a string function known to CodeGen, and mark it with NoBuiltin if...
void appendToUsed(Module &M, ArrayRef< GlobalValue * > Values)
Adds global values to the llvm.used list.
MDNode * TBAA
The tag for type-based alias analysis.
This struct is a compact representation of a valid (non-zero power of two) alignment.
SmallString< 32 > digest() const
PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM)
PreservedAnalyses run(Function &F, FunctionAnalysisManager &FAM)