52#define DEBUG_TYPE "tsan"
55 "tsan-instrument-memory-accesses",
cl::init(
true),
59 cl::desc(
"Instrument function entry and exit"),
62 "tsan-handle-cxx-exceptions",
cl::init(
true),
63 cl::desc(
"Handle C++ exceptions (insert cleanup blocks for unwinding)"),
70 "tsan-instrument-memintrinsics",
cl::init(
true),
73 "tsan-distinguish-volatile",
cl::init(
false),
74 cl::desc(
"Emit special instrumentation for accesses to volatiles"),
77 "tsan-instrument-read-before-write",
cl::init(
false),
78 cl::desc(
"Do not eliminate read instrumentation for read-before-writes"),
81 "tsan-compound-read-before-write",
cl::init(
false),
82 cl::desc(
"Emit special compound instrumentation for reads-before-writes"),
85STATISTIC(NumInstrumentedReads,
"Number of instrumented reads");
86STATISTIC(NumInstrumentedWrites,
"Number of instrumented writes");
88 "Number of reads ignored due to following writes");
89STATISTIC(NumAccessesWithBadSize,
"Number of accesses with bad size");
90STATISTIC(NumInstrumentedVtableWrites,
"Number of vtable ptr writes");
91STATISTIC(NumInstrumentedVtableReads,
"Number of vtable ptr reads");
93 "Number of reads from constant globals");
94STATISTIC(NumOmittedReadsFromVtable,
"Number of vtable reads");
95STATISTIC(NumOmittedNonCaptured,
"Number of accesses ignored due to capturing");
108struct ThreadSanitizer {
113 <<
"warning: Option -tsan-compound-read-before-write has no effect "
114 "when -tsan-instrument-read-before-write is set.\n";
123 struct InstructionInfo {
126 static constexpr unsigned kCompoundRW = (1U << 0);
128 explicit InstructionInfo(
Instruction *Inst) : Inst(Inst) {}
135 bool instrumentLoadOrStore(
const InstructionInfo &
II,
const DataLayout &
DL);
141 bool addrPointsToConstantData(
Value *
Addr);
151 static const size_t kNumberOfAccessSizes = 5;
165 [kNumberOfAccessSizes];
174void insertModuleCtor(
Module &M) {
186 ThreadSanitizer TSan;
203 IntptrTy =
DL.getIntPtrType(Ctx);
209 TsanFuncEntry = M.getOrInsertFunction(
"__tsan_func_entry", Attr,
210 IRB.getVoidTy(), IRB.getPtrTy());
212 M.getOrInsertFunction(
"__tsan_func_exit", Attr, IRB.getVoidTy());
213 TsanIgnoreBegin = M.getOrInsertFunction(
"__tsan_ignore_thread_begin", Attr,
216 M.getOrInsertFunction(
"__tsan_ignore_thread_end", Attr, IRB.getVoidTy());
219 const unsigned ByteSize = 1U << i;
220 const unsigned BitSize = ByteSize * 8;
221 std::string ByteSizeStr = utostr(ByteSize);
222 std::string BitSizeStr = utostr(BitSize);
224 TsanRead[i] = M.getOrInsertFunction(ReadName, Attr, IRB.getVoidTy(),
228 TsanWrite[i] = M.getOrInsertFunction(WriteName, Attr, IRB.getVoidTy(),
231 SmallString<64> UnalignedReadName(
"__tsan_unaligned_read" + ByteSizeStr);
232 TsanUnalignedRead[i] = M.getOrInsertFunction(
233 UnalignedReadName, Attr, IRB.getVoidTy(), IRB.getPtrTy());
235 SmallString<64> UnalignedWriteName(
"__tsan_unaligned_write" + ByteSizeStr);
236 TsanUnalignedWrite[i] = M.getOrInsertFunction(
237 UnalignedWriteName, Attr, IRB.getVoidTy(), IRB.getPtrTy());
239 SmallString<64> VolatileReadName(
"__tsan_volatile_read" + ByteSizeStr);
240 TsanVolatileRead[i] = M.getOrInsertFunction(
241 VolatileReadName, Attr, IRB.getVoidTy(), IRB.getPtrTy());
243 SmallString<64> VolatileWriteName(
"__tsan_volatile_write" + ByteSizeStr);
244 TsanVolatileWrite[i] = M.getOrInsertFunction(
245 VolatileWriteName, Attr, IRB.getVoidTy(), IRB.getPtrTy());
247 SmallString<64> UnalignedVolatileReadName(
"__tsan_unaligned_volatile_read" +
249 TsanUnalignedVolatileRead[i] = M.getOrInsertFunction(
250 UnalignedVolatileReadName, Attr, IRB.getVoidTy(), IRB.getPtrTy());
253 "__tsan_unaligned_volatile_write" + ByteSizeStr);
254 TsanUnalignedVolatileWrite[i] = M.getOrInsertFunction(
255 UnalignedVolatileWriteName, Attr, IRB.getVoidTy(), IRB.getPtrTy());
258 TsanCompoundRW[i] = M.getOrInsertFunction(
259 CompoundRWName, Attr, IRB.getVoidTy(), IRB.getPtrTy());
261 SmallString<64> UnalignedCompoundRWName(
"__tsan_unaligned_read_write" +
263 TsanUnalignedCompoundRW[i] = M.getOrInsertFunction(
264 UnalignedCompoundRWName, Attr, IRB.getVoidTy(), IRB.getPtrTy());
268 SmallString<32> AtomicLoadName(
"__tsan_atomic" + BitSizeStr +
"_load");
270 M.getOrInsertFunction(AtomicLoadName,
272 BitSize <= 32, Attr),
276 using Idxs = std::vector<unsigned>;
277 Idxs Idxs2Or12 ((BitSize <= 32) ? Idxs({1, 2}) : Idxs({2}));
278 Idxs Idxs34Or1234((BitSize <= 32) ? Idxs({1, 2, 3, 4}) : Idxs({3, 4}));
279 SmallString<32> AtomicStoreName(
"__tsan_atomic" + BitSizeStr +
"_store");
280 TsanAtomicStore[i] =
M.getOrInsertFunction(
282 TLI.
getAttrList(&Ctx, Idxs2Or12,
true,
false, Attr),
283 IRB.getVoidTy(), PtrTy, Ty, OrdTy);
287 TsanAtomicRMW[
Op][i] =
nullptr;
288 const char *NamePart =
nullptr;
290 NamePart =
"_exchange";
292 NamePart =
"_fetch_add";
294 NamePart =
"_fetch_sub";
296 NamePart =
"_fetch_and";
298 NamePart =
"_fetch_or";
300 NamePart =
"_fetch_xor";
302 NamePart =
"_fetch_nand";
306 TsanAtomicRMW[
Op][i] =
M.getOrInsertFunction(
309 BitSize <= 32, Attr),
310 Ty, PtrTy, Ty, OrdTy);
314 "_compare_exchange_val");
315 TsanAtomicCAS[i] =
M.getOrInsertFunction(
318 BitSize <= 32, Attr),
319 Ty, PtrTy, Ty, Ty, OrdTy, OrdTy);
322 M.getOrInsertFunction(
"__tsan_vptr_update", Attr, IRB.getVoidTy(),
323 IRB.getPtrTy(), IRB.getPtrTy());
324 TsanVptrLoad =
M.getOrInsertFunction(
"__tsan_vptr_read", Attr,
325 IRB.getVoidTy(), IRB.getPtrTy());
326 TsanAtomicThreadFence =
M.getOrInsertFunction(
327 "__tsan_atomic_thread_fence",
329 IRB.getVoidTy(), OrdTy);
331 TsanAtomicSignalFence =
M.getOrInsertFunction(
332 "__tsan_atomic_signal_fence",
334 IRB.getVoidTy(), OrdTy);
337 M.getOrInsertFunction(
"__tsan_memmove", Attr, IRB.getPtrTy(),
338 IRB.getPtrTy(), IRB.getPtrTy(), IntptrTy);
340 M.getOrInsertFunction(
"__tsan_memcpy", Attr, IRB.getPtrTy(),
341 IRB.getPtrTy(), IRB.getPtrTy(), IntptrTy);
342 MemsetFn =
M.getOrInsertFunction(
345 IRB.getPtrTy(), IRB.getPtrTy(), IRB.getInt32Ty(), IntptrTy);
349 if (
MDNode *
Tag =
I->getMetadata(LLVMContext::MD_tbaa))
350 return Tag->isTBAAVtableAccess();
358 Addr =
Addr->stripInBoundsOffsets();
361 if (GV->hasSection()) {
374 Type *PtrTy = cast<PointerType>(
Addr->getType()->getScalarType());
382bool ThreadSanitizer::addrPointsToConstantData(
Value *
Addr) {
385 Addr =
GEP->getPointerOperand();
388 if (GV->isConstant()) {
390 NumOmittedReadsFromConstantGlobals++;
396 NumOmittedReadsFromVtable++;
415void ThreadSanitizer::chooseInstructionsToInstrument(
421 const bool IsWrite = isa<StoreInst>(*
I);
422 Value *
Addr = IsWrite ? cast<StoreInst>(
I)->getPointerOperand()
423 : cast<LoadInst>(
I)->getPointerOperand();
429 const auto WriteEntry = WriteTargets.
find(
Addr);
431 auto &WI =
All[WriteEntry->second];
434 const bool AnyVolatile =
436 cast<StoreInst>(WI.Inst)->isVolatile());
440 WI.Flags |= InstructionInfo::kCompoundRW;
441 NumOmittedReadsBeforeWrite++;
446 if (addrPointsToConstantData(
Addr)) {
457 NumOmittedNonCaptured++;
466 WriteTargets[
Addr] =
All.size() - 1;
477 if (isa<LoadInst>(
I) || isa<StoreInst>(
I))
482void ThreadSanitizer::InsertRuntimeIgnores(
Function &
F) {
484 IRB.CreateCall(TsanIgnoreBegin);
488 AtExit->CreateCall(TsanIgnoreEnd);
492bool ThreadSanitizer::sanitizeFunction(
Function &
F,
501 if (
F.hasFnAttribute(Attribute::Naked))
506 if (
F.hasFnAttribute(Attribute::DisableSanitizerInstrumentation))
516 bool SanitizeFunction =
F.hasFnAttribute(Attribute::SanitizeThread);
521 for (
auto &Inst : BB) {
523 if (Inst.hasMetadata(LLVMContext::MD_nosanitize))
527 else if (isa<LoadInst>(Inst) || isa<StoreInst>(Inst))
529 else if ((isa<CallInst>(Inst) && !isa<DbgInfoIntrinsic>(Inst)) ||
530 isa<InvokeInst>(Inst)) {
531 if (
CallInst *CI = dyn_cast<CallInst>(&Inst))
533 if (isa<MemIntrinsic>(Inst))
536 chooseInstructionsToInstrument(LocalLoadsAndStores, AllLoadsAndStores,
540 chooseInstructionsToInstrument(LocalLoadsAndStores, AllLoadsAndStores,
DL);
549 for (
const auto &
II : AllLoadsAndStores) {
550 Res |= instrumentLoadOrStore(
II,
DL);
556 for (
auto *Inst : AtomicAccesses) {
557 Res |= instrumentAtomic(Inst,
DL);
561 for (
auto *Inst : MemIntrinCalls) {
562 Res |= instrumentMemIntrinsic(Inst);
565 if (
F.hasFnAttribute(
"sanitize_thread_no_checking_at_run_time")) {
566 assert(!
F.hasFnAttribute(Attribute::SanitizeThread));
568 InsertRuntimeIgnores(
F);
574 Value *ReturnAddress = IRB.CreateCall(
577 IRB.CreateCall(TsanFuncEntry, ReturnAddress);
582 AtExit->CreateCall(TsanFuncExit, {});
589bool ThreadSanitizer::instrumentLoadOrStore(
const InstructionInfo &
II,
592 const bool IsWrite = isa<StoreInst>(*
II.Inst);
593 Value *
Addr = IsWrite ? cast<StoreInst>(
II.Inst)->getPointerOperand()
594 : cast<LoadInst>(
II.Inst)->getPointerOperand();
600 if (
Addr->isSwiftError())
603 int Idx = getMemoryAccessFuncIndex(OrigTy,
Addr,
DL);
608 Value *StoredValue = cast<StoreInst>(
II.Inst)->getValueOperand();
612 if (isa<VectorType>(StoredValue->
getType()))
613 StoredValue = IRB.CreateExtractElement(
614 StoredValue, ConstantInt::get(IRB.getInt32Ty(), 0));
616 StoredValue = IRB.CreateIntToPtr(StoredValue, IRB.getPtrTy());
618 IRB.CreateCall(TsanVptrUpdate, {
Addr, StoredValue});
619 NumInstrumentedVtableWrites++;
623 IRB.CreateCall(TsanVptrLoad,
Addr);
624 NumInstrumentedVtableReads++;
628 const Align Alignment = IsWrite ? cast<StoreInst>(
II.Inst)->getAlign()
629 : cast<LoadInst>(
II.Inst)->getAlign();
630 const bool IsCompoundRW =
633 (IsWrite ? cast<StoreInst>(
II.Inst)->isVolatile()
634 : cast<LoadInst>(
II.Inst)->isVolatile());
635 assert((!IsVolatile || !IsCompoundRW) &&
"Compound volatile invalid!");
641 OnAccessFunc = TsanCompoundRW[
Idx];
643 OnAccessFunc = IsWrite ? TsanVolatileWrite[
Idx] : TsanVolatileRead[
Idx];
645 OnAccessFunc = IsWrite ? TsanWrite[
Idx] : TsanRead[
Idx];
648 OnAccessFunc = TsanUnalignedCompoundRW[
Idx];
650 OnAccessFunc = IsWrite ? TsanUnalignedVolatileWrite[
Idx]
651 : TsanUnalignedVolatileRead[
Idx];
653 OnAccessFunc = IsWrite ? TsanUnalignedWrite[
Idx] : TsanUnalignedRead[
Idx];
655 IRB.CreateCall(OnAccessFunc,
Addr);
656 if (IsCompoundRW || IsWrite)
657 NumInstrumentedWrites++;
658 if (IsCompoundRW || !IsWrite)
659 NumInstrumentedReads++;
688bool ThreadSanitizer::instrumentMemIntrinsic(
Instruction *
I) {
691 Value *Cast1 = IRB.CreateIntCast(
M->getArgOperand(1), IRB.getInt32Ty(),
false);
692 Value *Cast2 = IRB.CreateIntCast(
M->getArgOperand(2), IntptrTy,
false);
695 {
M->getArgOperand(0),
698 I->eraseFromParent();
701 isa<MemCpyInst>(M) ? MemcpyFn : MemmoveFn,
702 {
M->getArgOperand(0),
704 IRB.CreateIntCast(
M->getArgOperand(2), IntptrTy,
false)});
705 I->eraseFromParent();
720 if (
LoadInst *LI = dyn_cast<LoadInst>(
I)) {
722 Type *OrigTy = LI->getType();
723 int Idx = getMemoryAccessFuncIndex(OrigTy,
Addr,
DL);
728 Value *
C = IRB.CreateCall(TsanAtomicLoad[
Idx], Args);
729 Value *Cast = IRB.CreateBitOrPointerCast(
C, OrigTy);
730 I->replaceAllUsesWith(Cast);
731 }
else if (
StoreInst *SI = dyn_cast<StoreInst>(
I)) {
734 getMemoryAccessFuncIndex(
SI->getValueOperand()->getType(),
Addr,
DL);
737 const unsigned ByteSize = 1U <<
Idx;
738 const unsigned BitSize = ByteSize * 8;
741 IRB.CreateBitOrPointerCast(
SI->getValueOperand(), Ty),
743 IRB.CreateCall(TsanAtomicStore[
Idx], Args);
744 SI->eraseFromParent();
748 getMemoryAccessFuncIndex(RMWI->getValOperand()->getType(),
Addr,
DL);
754 const unsigned ByteSize = 1U <<
Idx;
755 const unsigned BitSize = ByteSize * 8;
757 Value *Val = RMWI->getValOperand();
760 Value *
C = IRB.CreateCall(
F, Args);
761 I->replaceAllUsesWith(IRB.CreateBitOrPointerCast(
C, Val->
getType()));
762 I->eraseFromParent();
765 Type *OrigOldValTy = CASI->getNewValOperand()->getType();
766 int Idx = getMemoryAccessFuncIndex(OrigOldValTy,
Addr,
DL);
769 const unsigned ByteSize = 1U <<
Idx;
770 const unsigned BitSize = ByteSize * 8;
773 IRB.CreateBitOrPointerCast(CASI->getCompareOperand(), Ty);
775 IRB.CreateBitOrPointerCast(CASI->getNewValOperand(), Ty);
784 if (Ty != OrigOldValTy) {
786 OldVal = IRB.CreateIntToPtr(
C, OrigOldValTy);
791 Res = IRB.CreateInsertValue(Res,
Success, 1);
793 I->replaceAllUsesWith(Res);
794 I->eraseFromParent();
795 }
else if (
FenceInst *FI = dyn_cast<FenceInst>(
I)) {
798 ? TsanAtomicSignalFence
799 : TsanAtomicThreadFence;
800 IRB.CreateCall(
F, Args);
801 FI->eraseFromParent();
806int ThreadSanitizer::getMemoryAccessFuncIndex(
Type *OrigTy,
Value *
Addr,
816 NumAccessesWithBadSize++;
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static cl::opt< bool > ClInstrumentAtomics("asan-instrument-atomics", cl::desc("instrument atomic instructions (rmw, cmpxchg)"), cl::Hidden, cl::init(true))
static const size_t kNumberOfAccessSizes
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
This file defines the DenseMap class.
static cl::opt< bool > ClInstrumentMemIntrinsics("hwasan-instrument-mem-intrinsics", cl::desc("instrument memory intrinsics"), cl::Hidden, cl::init(true))
Module.h This file contains the declarations for the Module class.
uint64_t IntrinsicInst * II
FunctionAnalysisManager FAM
ModuleAnalysisManager MAM
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This file defines the SmallString 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 void initialize(TargetLibraryInfoImpl &TLI, const Triple &T, ArrayRef< StringLiteral > StandardNames)
Initialize the set of available library functions based on the specified target triple.
static bool shouldInstrumentReadWriteFromAddress(const Module *M, Value *Addr)
static bool isVtableAccess(Instruction *I)
static bool isTsanAtomic(const Instruction *I)
const char kTsanModuleCtorName[]
static cl::opt< bool > ClInstrumentFuncEntryExit("tsan-instrument-func-entry-exit", cl::init(true), cl::desc("Instrument function entry and exit"), cl::Hidden)
static ConstantInt * createOrdering(IRBuilder<> *IRB, AtomicOrdering ord)
static cl::opt< bool > ClInstrumentMemIntrinsics("tsan-instrument-memintrinsics", cl::init(true), cl::desc("Instrument memintrinsics (memset/memcpy/memmove)"), cl::Hidden)
const char kTsanInitName[]
static cl::opt< bool > ClDistinguishVolatile("tsan-distinguish-volatile", cl::init(false), cl::desc("Emit special instrumentation for accesses to volatiles"), cl::Hidden)
static cl::opt< bool > ClCompoundReadBeforeWrite("tsan-compound-read-before-write", cl::init(false), cl::desc("Emit special compound instrumentation for reads-before-writes"), cl::Hidden)
static cl::opt< bool > ClInstrumentAtomics("tsan-instrument-atomics", cl::init(true), cl::desc("Instrument atomics"), cl::Hidden)
static cl::opt< bool > ClHandleCxxExceptions("tsan-handle-cxx-exceptions", cl::init(true), cl::desc("Handle C++ exceptions (insert cleanup blocks for unwinding)"), cl::Hidden)
static cl::opt< bool > ClInstrumentReadBeforeWrite("tsan-instrument-read-before-write", cl::init(false), cl::desc("Do not eliminate read instrumentation for read-before-writes"), cl::Hidden)
static cl::opt< bool > ClInstrumentMemoryAccesses("tsan-instrument-memory-accesses", cl::init(true), cl::desc("Instrument memory accesses"), cl::Hidden)
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.
An instruction that atomically checks whether a specified value is in a memory location,...
an instruction that atomically reads a memory location, combines it with another value,...
AttributeList addFnAttribute(LLVMContext &C, Attribute::AttrKind Kind) const
Add a function attribute to the list.
This class represents a function call, abstracting a target machine's calling convention.
This is the shared class of boolean and integer constants.
This class represents an Operation in the Expression.
A parsed version of the target data layout string in and methods for querying it.
iterator find(const_arg_type_t< KeyT > Val)
EscapeEnumerator - This is a little algorithm to find all escape points from a function so that "fina...
An instruction for ordering other memory operations.
A handy container for a FunctionType+Callee-pointer pair, which can be passed around as a single enti...
an instruction for type-safe pointer arithmetic to access elements of arrays and structs
ConstantInt * getInt32(uint32_t C)
Get a constant 32-bit value.
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.
An instruction for reading from memory.
This class wraps the llvm.memset and llvm.memset.inline intrinsics.
This class wraps the llvm.memcpy/memmove intrinsics.
A Module instance is used to store all the information related to an LLVM module.
static PointerType * get(Type *ElementType, unsigned AddressSpace)
This constructs a pointer to an object of the specified type in a numbered address space.
static PoisonValue * get(Type *T)
Static factory methods - Return an 'poison' object of the specified type.
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 PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
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.
An instruction for storing to memory.
StringRef - Represent a constant reference to a string, i.e.
Analysis pass providing the TargetLibraryInfo.
Provides information about what library functions are available for the current target.
AttributeList getAttrList(LLVMContext *C, ArrayRef< unsigned > ArgNos, bool Signed, bool Ret=false, AttributeList AL=AttributeList()) const
Triple - Helper class for working with autoconf configuration names.
ObjectFormatType getObjectFormat() const
Get the object format for this triple.
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 IntegerType * getIntNTy(LLVMContext &C, unsigned N)
bool isSized(SmallPtrSetImpl< Type * > *Visited=nullptr) const
Return true if it makes sense to take the size of this type.
bool isScalableTy() const
Return true if this is a type whose size is a known multiple of vscale.
static IntegerType * getInt32Ty(LLVMContext &C)
bool isIntegerTy() const
True if this is an instance of IntegerType.
LLVM Value Representation.
Type * getType() const
All values are typed, get the type of this value.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char IsVolatile[]
Key for Kernel::Arg::Metadata::mIsVolatile.
constexpr char Args[]
Key for Kernel::Metadata::mArgs.
@ C
The default llvm calling convention, compatible with C.
Function * getDeclaration(Module *M, ID id, ArrayRef< Type * > Tys=std::nullopt)
Create or insert an LLVM Function declaration for an intrinsic, and return it.
@ SingleThread
Synchronized with respect to signal handlers executing in the same thread.
initializer< Ty > init(const Ty &Val)
This is an optimization pass for GlobalISel generic memory operations.
const Value * getUnderlyingObject(const Value *V, unsigned MaxLookup=6)
This method strips off any GEP address adjustments, pointer casts or llvm.threadlocal....
std::string getInstrProfSectionName(InstrProfSectKind IPSK, Triple::ObjectFormatType OF, bool AddSegmentInfo=true)
Return the name of the profile section corresponding to IPSK.
int countr_zero(T Val)
Count number of 0's from the least significant bit to the most stopping at the first 1.
auto reverse(ContainerTy &&C)
std::pair< Function *, FunctionCallee > getOrCreateSanitizerCtorAndInitFunctions(Module &M, StringRef CtorName, StringRef InitName, ArrayRef< Type * > InitArgTypes, ArrayRef< Value * > InitArgs, function_ref< void(Function *, FunctionCallee)> FunctionsCreatedCallback, StringRef VersionCheckName=StringRef(), bool Weak=false)
Creates sanitizer constructor function lazily.
std::optional< SyncScope::ID > getAtomicSyncScopeID(const Instruction *I)
A helper function that returns an atomic operation's sync scope; returns std::nullopt if it is not an...
bool PointerMayBeCaptured(const Value *V, bool ReturnCaptures, bool StoreCaptures, unsigned MaxUsesToExplore=0)
PointerMayBeCaptured - Return true if this pointer value may be captured by the enclosing function (w...
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
AtomicOrdering
Atomic ordering for LLVM's memory model.
DWARFExpression::Operation Op
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.
Type * getLoadStoreType(const Value *I)
A helper function that returns the type of a load or store instruction.
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...
bool checkIfAlreadyInstrumented(Module &M, StringRef Flag)
Check if module has flag attached, if not add the flag.
This struct is a compact representation of a valid (non-zero power of two) alignment.
uint64_t value() const
This is a hole in the type system and should not be abused.
static void ensureDebugInfo(IRBuilder<> &IRB, const Function &F)
PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM)
PreservedAnalyses run(Function &F, FunctionAnalysisManager &FAM)