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;
200 IntptrTy =
DL.getIntPtrType(Ctx);
206 TsanFuncEntry = M.getOrInsertFunction(
"__tsan_func_entry", Attr,
207 IRB.getVoidTy(), IRB.getPtrTy());
209 M.getOrInsertFunction(
"__tsan_func_exit", Attr, IRB.getVoidTy());
210 TsanIgnoreBegin = M.getOrInsertFunction(
"__tsan_ignore_thread_begin", Attr,
213 M.getOrInsertFunction(
"__tsan_ignore_thread_end", Attr, IRB.getVoidTy());
216 const unsigned ByteSize = 1U << i;
217 const unsigned BitSize = ByteSize * 8;
218 std::string ByteSizeStr = utostr(ByteSize);
219 std::string BitSizeStr = utostr(BitSize);
221 TsanRead[i] = M.getOrInsertFunction(ReadName, Attr, IRB.getVoidTy(),
225 TsanWrite[i] = M.getOrInsertFunction(WriteName, Attr, IRB.getVoidTy(),
228 SmallString<64> UnalignedReadName(
"__tsan_unaligned_read" + ByteSizeStr);
229 TsanUnalignedRead[i] = M.getOrInsertFunction(
230 UnalignedReadName, Attr, IRB.getVoidTy(), IRB.getPtrTy());
232 SmallString<64> UnalignedWriteName(
"__tsan_unaligned_write" + ByteSizeStr);
233 TsanUnalignedWrite[i] = M.getOrInsertFunction(
234 UnalignedWriteName, Attr, IRB.getVoidTy(), IRB.getPtrTy());
236 SmallString<64> VolatileReadName(
"__tsan_volatile_read" + ByteSizeStr);
237 TsanVolatileRead[i] = M.getOrInsertFunction(
238 VolatileReadName, Attr, IRB.getVoidTy(), IRB.getPtrTy());
240 SmallString<64> VolatileWriteName(
"__tsan_volatile_write" + ByteSizeStr);
241 TsanVolatileWrite[i] = M.getOrInsertFunction(
242 VolatileWriteName, Attr, IRB.getVoidTy(), IRB.getPtrTy());
244 SmallString<64> UnalignedVolatileReadName(
"__tsan_unaligned_volatile_read" +
246 TsanUnalignedVolatileRead[i] = M.getOrInsertFunction(
247 UnalignedVolatileReadName, Attr, IRB.getVoidTy(), IRB.getPtrTy());
250 "__tsan_unaligned_volatile_write" + ByteSizeStr);
251 TsanUnalignedVolatileWrite[i] = M.getOrInsertFunction(
252 UnalignedVolatileWriteName, Attr, IRB.getVoidTy(), IRB.getPtrTy());
255 TsanCompoundRW[i] = M.getOrInsertFunction(
256 CompoundRWName, Attr, IRB.getVoidTy(), IRB.getPtrTy());
258 SmallString<64> UnalignedCompoundRWName(
"__tsan_unaligned_read_write" +
260 TsanUnalignedCompoundRW[i] = M.getOrInsertFunction(
261 UnalignedCompoundRWName, Attr, IRB.getVoidTy(), IRB.getPtrTy());
265 SmallString<32> AtomicLoadName(
"__tsan_atomic" + BitSizeStr +
"_load");
267 M.getOrInsertFunction(AtomicLoadName,
269 BitSize <= 32, Attr),
273 using Idxs = std::vector<unsigned>;
274 Idxs Idxs2Or12 ((BitSize <= 32) ? Idxs({1, 2}) : Idxs({2}));
275 Idxs Idxs34Or1234((BitSize <= 32) ? Idxs({1, 2, 3, 4}) : Idxs({3, 4}));
276 SmallString<32> AtomicStoreName(
"__tsan_atomic" + BitSizeStr +
"_store");
277 TsanAtomicStore[i] =
M.getOrInsertFunction(
279 TLI.
getAttrList(&Ctx, Idxs2Or12,
true,
false, Attr),
280 IRB.getVoidTy(), PtrTy, Ty, OrdTy);
284 TsanAtomicRMW[
Op][i] =
nullptr;
285 const char *NamePart =
nullptr;
287 NamePart =
"_exchange";
289 NamePart =
"_fetch_add";
291 NamePart =
"_fetch_sub";
293 NamePart =
"_fetch_and";
295 NamePart =
"_fetch_or";
297 NamePart =
"_fetch_xor";
299 NamePart =
"_fetch_nand";
303 TsanAtomicRMW[
Op][i] =
M.getOrInsertFunction(
306 BitSize <= 32, Attr),
307 Ty, PtrTy, Ty, OrdTy);
311 "_compare_exchange_val");
312 TsanAtomicCAS[i] =
M.getOrInsertFunction(
315 BitSize <= 32, Attr),
316 Ty, PtrTy, Ty, Ty, OrdTy, OrdTy);
319 M.getOrInsertFunction(
"__tsan_vptr_update", Attr, IRB.getVoidTy(),
320 IRB.getPtrTy(), IRB.getPtrTy());
321 TsanVptrLoad =
M.getOrInsertFunction(
"__tsan_vptr_read", Attr,
322 IRB.getVoidTy(), IRB.getPtrTy());
323 TsanAtomicThreadFence =
M.getOrInsertFunction(
324 "__tsan_atomic_thread_fence",
326 IRB.getVoidTy(), OrdTy);
328 TsanAtomicSignalFence =
M.getOrInsertFunction(
329 "__tsan_atomic_signal_fence",
331 IRB.getVoidTy(), OrdTy);
334 M.getOrInsertFunction(
"__tsan_memmove", Attr, IRB.getPtrTy(),
335 IRB.getPtrTy(), IRB.getPtrTy(), IntptrTy);
337 M.getOrInsertFunction(
"__tsan_memcpy", Attr, IRB.getPtrTy(),
338 IRB.getPtrTy(), IRB.getPtrTy(), IntptrTy);
339 MemsetFn =
M.getOrInsertFunction(
342 IRB.getPtrTy(), IRB.getPtrTy(), IRB.getInt32Ty(), IntptrTy);
346 if (
MDNode *
Tag =
I->getMetadata(LLVMContext::MD_tbaa))
347 return Tag->isTBAAVtableAccess();
355 Addr =
Addr->stripInBoundsOffsets();
358 if (GV->hasSection()) {
371 Type *PtrTy = cast<PointerType>(
Addr->getType()->getScalarType());
379bool ThreadSanitizer::addrPointsToConstantData(
Value *
Addr) {
382 Addr =
GEP->getPointerOperand();
385 if (GV->isConstant()) {
387 NumOmittedReadsFromConstantGlobals++;
393 NumOmittedReadsFromVtable++;
412void ThreadSanitizer::chooseInstructionsToInstrument(
418 const bool IsWrite = isa<StoreInst>(*
I);
419 Value *
Addr = IsWrite ? cast<StoreInst>(
I)->getPointerOperand()
420 : cast<LoadInst>(
I)->getPointerOperand();
426 const auto WriteEntry = WriteTargets.
find(
Addr);
428 auto &WI =
All[WriteEntry->second];
431 const bool AnyVolatile =
433 cast<StoreInst>(WI.Inst)->isVolatile());
437 WI.Flags |= InstructionInfo::kCompoundRW;
438 NumOmittedReadsBeforeWrite++;
443 if (addrPointsToConstantData(
Addr)) {
454 NumOmittedNonCaptured++;
463 WriteTargets[
Addr] =
All.size() - 1;
474 if (isa<LoadInst>(
I) || isa<StoreInst>(
I))
479void ThreadSanitizer::InsertRuntimeIgnores(
Function &
F) {
481 IRB.CreateCall(TsanIgnoreBegin);
485 AtExit->CreateCall(TsanIgnoreEnd);
489bool ThreadSanitizer::sanitizeFunction(
Function &
F,
498 if (
F.hasFnAttribute(Attribute::Naked))
503 if (
F.hasFnAttribute(Attribute::DisableSanitizerInstrumentation))
513 bool SanitizeFunction =
F.hasFnAttribute(Attribute::SanitizeThread);
518 for (
auto &Inst : BB) {
520 if (Inst.hasMetadata(LLVMContext::MD_nosanitize))
524 else if (isa<LoadInst>(Inst) || isa<StoreInst>(Inst))
526 else if ((isa<CallInst>(Inst) && !isa<DbgInfoIntrinsic>(Inst)) ||
527 isa<InvokeInst>(Inst)) {
528 if (
CallInst *CI = dyn_cast<CallInst>(&Inst))
530 if (isa<MemIntrinsic>(Inst))
533 chooseInstructionsToInstrument(LocalLoadsAndStores, AllLoadsAndStores,
537 chooseInstructionsToInstrument(LocalLoadsAndStores, AllLoadsAndStores,
DL);
546 for (
const auto &II : AllLoadsAndStores) {
547 Res |= instrumentLoadOrStore(II,
DL);
553 for (
auto *Inst : AtomicAccesses) {
554 Res |= instrumentAtomic(Inst,
DL);
558 for (
auto *Inst : MemIntrinCalls) {
559 Res |= instrumentMemIntrinsic(Inst);
562 if (
F.hasFnAttribute(
"sanitize_thread_no_checking_at_run_time")) {
563 assert(!
F.hasFnAttribute(Attribute::SanitizeThread));
565 InsertRuntimeIgnores(
F);
571 Value *ReturnAddress = IRB.CreateCall(
574 IRB.CreateCall(TsanFuncEntry, ReturnAddress);
579 AtExit->CreateCall(TsanFuncExit, {});
586bool ThreadSanitizer::instrumentLoadOrStore(
const InstructionInfo &II,
589 const bool IsWrite = isa<StoreInst>(*II.Inst);
590 Value *
Addr = IsWrite ? cast<StoreInst>(II.Inst)->getPointerOperand()
591 : cast<LoadInst>(II.Inst)->getPointerOperand();
597 if (
Addr->isSwiftError())
600 int Idx = getMemoryAccessFuncIndex(OrigTy,
Addr,
DL);
605 Value *StoredValue = cast<StoreInst>(II.Inst)->getValueOperand();
609 if (isa<VectorType>(StoredValue->
getType()))
610 StoredValue = IRB.CreateExtractElement(
611 StoredValue, ConstantInt::get(IRB.getInt32Ty(), 0));
613 StoredValue = IRB.CreateIntToPtr(StoredValue, IRB.getPtrTy());
615 IRB.CreateCall(TsanVptrUpdate, {
Addr, StoredValue});
616 NumInstrumentedVtableWrites++;
620 IRB.CreateCall(TsanVptrLoad,
Addr);
621 NumInstrumentedVtableReads++;
625 const Align Alignment = IsWrite ? cast<StoreInst>(II.Inst)->getAlign()
626 : cast<LoadInst>(II.Inst)->getAlign();
627 const bool IsCompoundRW =
630 (IsWrite ? cast<StoreInst>(II.Inst)->isVolatile()
631 : cast<LoadInst>(II.Inst)->isVolatile());
632 assert((!IsVolatile || !IsCompoundRW) &&
"Compound volatile invalid!");
638 OnAccessFunc = TsanCompoundRW[
Idx];
640 OnAccessFunc = IsWrite ? TsanVolatileWrite[
Idx] : TsanVolatileRead[
Idx];
642 OnAccessFunc = IsWrite ? TsanWrite[
Idx] : TsanRead[
Idx];
645 OnAccessFunc = TsanUnalignedCompoundRW[
Idx];
647 OnAccessFunc = IsWrite ? TsanUnalignedVolatileWrite[
Idx]
648 : TsanUnalignedVolatileRead[
Idx];
650 OnAccessFunc = IsWrite ? TsanUnalignedWrite[
Idx] : TsanUnalignedRead[
Idx];
652 IRB.CreateCall(OnAccessFunc,
Addr);
653 if (IsCompoundRW || IsWrite)
654 NumInstrumentedWrites++;
655 if (IsCompoundRW || !IsWrite)
656 NumInstrumentedReads++;
685bool ThreadSanitizer::instrumentMemIntrinsic(
Instruction *
I) {
688 Value *Cast1 = IRB.CreateIntCast(
M->getArgOperand(1), IRB.getInt32Ty(),
false);
689 Value *Cast2 = IRB.CreateIntCast(
M->getArgOperand(2), IntptrTy,
false);
692 {
M->getArgOperand(0),
695 I->eraseFromParent();
698 isa<MemCpyInst>(M) ? MemcpyFn : MemmoveFn,
699 {
M->getArgOperand(0),
701 IRB.CreateIntCast(
M->getArgOperand(2), IntptrTy,
false)});
702 I->eraseFromParent();
717 if (
LoadInst *LI = dyn_cast<LoadInst>(
I)) {
719 Type *OrigTy = LI->getType();
720 int Idx = getMemoryAccessFuncIndex(OrigTy,
Addr,
DL);
725 Value *
C = IRB.CreateCall(TsanAtomicLoad[
Idx], Args);
726 Value *Cast = IRB.CreateBitOrPointerCast(
C, OrigTy);
727 I->replaceAllUsesWith(Cast);
728 }
else if (
StoreInst *SI = dyn_cast<StoreInst>(
I)) {
731 getMemoryAccessFuncIndex(
SI->getValueOperand()->getType(),
Addr,
DL);
734 const unsigned ByteSize = 1U <<
Idx;
735 const unsigned BitSize = ByteSize * 8;
738 IRB.CreateBitOrPointerCast(
SI->getValueOperand(), Ty),
740 IRB.CreateCall(TsanAtomicStore[
Idx], Args);
741 SI->eraseFromParent();
745 getMemoryAccessFuncIndex(RMWI->getValOperand()->getType(),
Addr,
DL);
751 const unsigned ByteSize = 1U <<
Idx;
752 const unsigned BitSize = ByteSize * 8;
754 Value *Val = RMWI->getValOperand();
757 Value *
C = IRB.CreateCall(
F, Args);
758 I->replaceAllUsesWith(IRB.CreateBitOrPointerCast(
C, Val->
getType()));
759 I->eraseFromParent();
762 Type *OrigOldValTy = CASI->getNewValOperand()->getType();
763 int Idx = getMemoryAccessFuncIndex(OrigOldValTy,
Addr,
DL);
766 const unsigned ByteSize = 1U <<
Idx;
767 const unsigned BitSize = ByteSize * 8;
770 IRB.CreateBitOrPointerCast(CASI->getCompareOperand(), Ty);
772 IRB.CreateBitOrPointerCast(CASI->getNewValOperand(), Ty);
781 if (Ty != OrigOldValTy) {
783 OldVal = IRB.CreateIntToPtr(
C, OrigOldValTy);
788 Res = IRB.CreateInsertValue(Res,
Success, 1);
790 I->replaceAllUsesWith(Res);
791 I->eraseFromParent();
792 }
else if (
FenceInst *FI = dyn_cast<FenceInst>(
I)) {
795 ? TsanAtomicSignalFence
796 : TsanAtomicThreadFence;
797 IRB.CreateCall(
F, Args);
798 FI->eraseFromParent();
803int ThreadSanitizer::getMemoryAccessFuncIndex(
Type *OrigTy,
Value *
Addr,
809 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.
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.
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.
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...
Type * getLoadStoreType(Value *I)
A helper function that returns the type of a load or store instruction.
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)