46#define DEBUG_TYPE "memprof"
65 "__memprof_version_mismatch_check_v";
68 "__memprof_shadow_memory_dynamic_address";
77 "memprof-guard-against-version-mismatch",
83 cl::desc(
"instrument read instructions"),
92 "memprof-instrument-atomics",
97 "memprof-use-callbacks",
98 cl::desc(
"Use callbacks instead of inline instrumentation sequences."),
103 cl::desc(
"Prefix for memory access callbacks"),
111 cl::desc(
"scale of memprof shadow mapping"),
116 cl::desc(
"granularity of memprof shadow mapping"),
120 cl::desc(
"Instrument scalar stack variables"),
138 cl::desc(
"Collect access count histograms"),
143 cl::desc(
"The default memprof options"),
147STATISTIC(NumInstrumentedReads,
"Number of instrumented reads");
148STATISTIC(NumInstrumentedWrites,
"Number of instrumented writes");
149STATISTIC(NumSkippedStackReads,
"Number of non-instrumented stack reads");
150STATISTIC(NumSkippedStackWrites,
"Number of non-instrumented stack writes");
156struct ShadowMapping {
160 Mask = ~(Granularity - 1);
173struct InterestingMemoryAccess {
174 Value *Addr =
nullptr;
177 Value *MaybeMask =
nullptr;
184 C = &(
M.getContext());
185 LongSize =
M.getDataLayout().getPointerSizeInBits();
186 IntptrTy = Type::getIntNTy(*C, LongSize);
187 PtrTy = PointerType::getUnqual(*C);
193 std::optional<InterestingMemoryAccess>
194 isInterestingMemoryAccess(Instruction *
I)
const;
196 void instrumentMop(Instruction *
I,
const DataLayout &
DL,
197 InterestingMemoryAccess &
Access);
199 Value *Addr,
bool IsWrite);
200 void instrumentMaskedLoadOrStore(
const DataLayout &
DL,
Value *Mask,
203 void instrumentMemIntrinsic(MemIntrinsic *
MI);
205 bool instrumentFunction(Function &
F);
206 bool maybeInsertMemProfInitAtFunctionEntry(Function &
F);
207 bool insertDynamicShadowAtFunctionEntry(Function &
F);
210 void initializeCallbacks(
Module &M);
216 ShadowMapping Mapping;
219 FunctionCallee MemProfMemoryAccessCallback[2];
221 FunctionCallee MemProfMemmove, MemProfMemcpy, MemProfMemset;
222 Value *DynamicShadowOffset =
nullptr;
225class ModuleMemProfiler {
227 ModuleMemProfiler(
Module &M) { TargetTriple =
M.getTargetTriple(); }
229 bool instrumentModule(
Module &);
233 ShadowMapping Mapping;
234 Function *MemProfCtorFunction =
nullptr;
244 "Memprof with histogram only supports default mapping granularity");
246 MemProfiler Profiler(M);
247 if (Profiler.instrumentFunction(
F))
257 ModuleMemProfiler Profiler(M);
258 if (Profiler.instrumentModule(M))
265 Shadow = IRB.
CreateAnd(Shadow, Mapping.Mask);
266 Shadow = IRB.
CreateLShr(Shadow, Mapping.Scale);
268 assert(DynamicShadowOffset);
269 return IRB.
CreateAdd(Shadow, DynamicShadowOffset);
277 {
MI->getOperand(0),
MI->getOperand(1),
286 MI->eraseFromParent();
289std::optional<InterestingMemoryAccess>
290MemProfiler::isInterestingMemoryAccess(
Instruction *
I)
const {
292 if (DynamicShadowOffset ==
I)
295 InterestingMemoryAccess
Access;
301 Access.AccessTy = LI->getType();
302 Access.Addr = LI->getPointerOperand();
307 Access.AccessTy =
SI->getValueOperand()->getType();
308 Access.Addr =
SI->getPointerOperand();
313 Access.AccessTy = RMW->getValOperand()->getType();
314 Access.Addr = RMW->getPointerOperand();
319 Access.AccessTy = XCHG->getCompareOperand()->getType();
320 Access.Addr = XCHG->getPointerOperand();
322 auto *
F = CI->getCalledFunction();
323 if (
F && (
F->getIntrinsicID() == Intrinsic::masked_load ||
324 F->getIntrinsicID() == Intrinsic::masked_store)) {
325 unsigned OpOffset = 0;
326 if (
F->getIntrinsicID() == Intrinsic::masked_store) {
331 Access.AccessTy = CI->getArgOperand(0)->getType();
336 Access.AccessTy = CI->getType();
340 auto *
BasePtr = CI->getOperand(0 + OpOffset);
341 Access.MaybeMask = CI->getOperand(2 + OpOffset);
359 if (
Access.Addr->isSwiftError())
363 auto *Addr =
Access.Addr->stripInBoundsOffsets();
367 if (GV->hasSection()) {
370 auto OF =
I->getModule()->getTargetTriple().getObjectFormat();
377 if (GV->getName().starts_with(
"__llvm"))
386 Type *AccessTy,
bool IsWrite) {
388 unsigned Num = VTy->getNumElements();
389 auto *
Zero = ConstantInt::get(IntptrTy, 0);
390 for (
unsigned Idx = 0; Idx < Num; ++Idx) {
391 Value *InstrumentedAddress =
nullptr;
406 InsertBefore = ThenTerm;
410 InstrumentedAddress =
411 IRB.
CreateGEP(VTy, Addr, {
Zero, ConstantInt::get(IntptrTy, Idx)});
417 InterestingMemoryAccess &
Access) {
421 ++NumSkippedStackWrites;
423 ++NumSkippedStackReads;
428 NumInstrumentedWrites++;
430 NumInstrumentedReads++;
443void MemProfiler::instrumentAddress(
Instruction *OrigIns,
450 IRB.
CreateCall(MemProfMemoryAccessCallback[IsWrite], AddrLong);
457 Value *ShadowPtr = memToShadow(AddrLong, IRB);
468 Value *Inc = ConstantInt::get(ShadowTy, 1);
469 ShadowValue = IRB.
CreateAdd(ShadowValue, Inc);
477 if (!MemProfFilename)
480 "Unexpected MemProfProfileFilename metadata with empty string");
482 M.getContext(), MemProfFilename->
getString(),
true);
484 M, ProfileNameConst->
getType(),
true,
486 const Triple &TT = M.getTargetTriple();
487 if (TT.supportsCOMDAT()) {
501 const Triple &TT = M.getTargetTriple();
502 if (TT.supportsCOMDAT()) {
504 MemprofHistogramFlag->setComdat(M.getOrInsertComdat(VarName));
516 const Triple &TT = M.getTargetTriple();
517 if (TT.supportsCOMDAT()) {
523bool ModuleMemProfiler::instrumentModule(
Module &M) {
527 std::string VersionCheckName =
530 std::tie(MemProfCtorFunction, std::ignore) =
533 {}, VersionCheckName);
535 const uint64_t Priority = getCtorAndDtorPriority(TargetTriple);
547void MemProfiler::initializeCallbacks(
Module &M) {
550 for (
size_t AccessIsWrite = 0; AccessIsWrite <= 1; AccessIsWrite++) {
551 const std::string TypeStr = AccessIsWrite ?
"store" :
"load";
552 const std::string HistPrefix =
ClHistogram ?
"hist_" :
"";
555 MemProfMemoryAccessCallback[AccessIsWrite] =
M.getOrInsertFunction(
559 MemProfMemmove =
M.getOrInsertFunction(
562 PtrTy, PtrTy, PtrTy, IntptrTy);
568bool MemProfiler::maybeInsertMemProfInitAtFunctionEntry(
Function &
F) {
576 if (
F.getName().contains(
" load]")) {
586bool MemProfiler::insertDynamicShadowAtFunctionEntry(
Function &
F) {
588 Value *GlobalDynamicAddress =
F.getParent()->getOrInsertGlobal(
592 DynamicShadowOffset = IRB.
CreateLoad(IntptrTy, GlobalDynamicAddress);
596bool MemProfiler::instrumentFunction(
Function &
F) {
601 if (
F.getName().starts_with(
"__memprof_"))
604 bool FunctionModified =
false;
609 if (maybeInsertMemProfInitAtFunctionEntry(
F))
610 FunctionModified =
true;
614 initializeCallbacks(*
F.getParent());
620 for (
auto &Inst : BB) {
626 if (ToInstrument.
empty()) {
627 LLVM_DEBUG(
dbgs() <<
"MEMPROF done instrumenting: " << FunctionModified
628 <<
" " <<
F <<
"\n");
630 return FunctionModified;
633 FunctionModified |= insertDynamicShadowAtFunctionEntry(
F);
635 int NumInstrumented = 0;
636 for (
auto *Inst : ToInstrument) {
639 std::optional<InterestingMemoryAccess>
Access =
640 isInterestingMemoryAccess(Inst);
642 instrumentMop(Inst,
F.getDataLayout(), *
Access);
649 if (NumInstrumented > 0)
650 FunctionModified =
true;
652 LLVM_DEBUG(
dbgs() <<
"MEMPROF done instrumenting: " << FunctionModified <<
" "
655 return FunctionModified;
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static cl::opt< int > ClDebugMin("asan-debug-min", cl::desc("Debug min inst"), cl::Hidden, cl::init(-1))
static cl::opt< std::string > ClMemoryAccessCallbackPrefix("asan-memory-access-callback-prefix", cl::desc("Prefix for memory access callbacks"), cl::Hidden, cl::init("__asan_"))
static cl::opt< bool > ClInsertVersionCheck("asan-guard-against-version-mismatch", cl::desc("Guard against compiler/runtime version mismatch."), cl::Hidden, cl::init(true))
static cl::opt< bool > ClInstrumentWrites("asan-instrument-writes", cl::desc("instrument write instructions"), cl::Hidden, cl::init(true))
static cl::opt< int > ClDebugMax("asan-debug-max", cl::desc("Debug max inst"), cl::Hidden, cl::init(-1))
static cl::opt< bool > ClStack("asan-stack", cl::desc("Handle stack memory"), cl::Hidden, cl::init(true))
static cl::opt< bool > ClInstrumentAtomics("asan-instrument-atomics", cl::desc("instrument atomic instructions (rmw, cmpxchg)"), cl::Hidden, cl::init(true))
static cl::opt< int > ClMappingScale("asan-mapping-scale", cl::desc("scale of asan shadow mapping"), cl::Hidden, cl::init(0))
static cl::opt< std::string > ClDebugFunc("asan-debug-func", cl::Hidden, cl::desc("Debug func"))
static cl::opt< bool > ClInstrumentReads("asan-instrument-reads", cl::desc("instrument read instructions"), cl::Hidden, cl::init(true))
Module.h This file contains the declarations for the Module class.
Machine Check Debug Module
static cl::opt< int > ClMappingGranularity("memprof-mapping-granularity", cl::desc("granularity of memprof shadow mapping"), cl::Hidden, cl::init(DefaultMemGranularity))
constexpr char MemProfVersionCheckNamePrefix[]
static cl::opt< int > ClDebugMin("memprof-debug-min", cl::desc("Debug min inst"), cl::Hidden, cl::init(-1))
void createMemprofHistogramFlagVar(Module &M)
constexpr uint64_t MemProfEmscriptenCtorAndDtorPriority
static cl::opt< std::string > MemprofRuntimeDefaultOptions("memprof-runtime-default-options", cl::desc("The default memprof options"), cl::Hidden, cl::init(""))
static cl::opt< std::string > ClDebugFunc("memprof-debug-func", cl::Hidden, cl::desc("Debug func"))
constexpr char MemProfShadowMemoryDynamicAddress[]
constexpr uint64_t MemProfCtorAndDtorPriority
constexpr int LLVM_MEM_PROFILER_VERSION
static cl::opt< bool > ClUseCalls("memprof-use-callbacks", cl::desc("Use callbacks instead of inline instrumentation sequences."), cl::Hidden, cl::init(false))
static cl::opt< bool > ClInstrumentAtomics("memprof-instrument-atomics", cl::desc("instrument atomic instructions (rmw, cmpxchg)"), cl::Hidden, cl::init(true))
static cl::opt< bool > ClInsertVersionCheck("memprof-guard-against-version-mismatch", cl::desc("Guard against compiler/runtime version mismatch."), cl::Hidden, cl::init(true))
constexpr char MemProfInitName[]
constexpr char MemProfFilenameVar[]
static cl::opt< bool > ClStack("memprof-instrument-stack", cl::desc("Instrument scalar stack variables"), cl::Hidden, cl::init(false))
static cl::opt< bool > ClHistogram("memprof-histogram", cl::desc("Collect access count histograms"), cl::Hidden, cl::init(false))
constexpr uint64_t DefaultMemGranularity
void createMemprofDefaultOptionsVar(Module &M)
constexpr uint64_t HistogramGranularity
constexpr uint64_t DefaultShadowScale
static cl::opt< std::string > ClMemoryAccessCallbackPrefix("memprof-memory-access-callback-prefix", cl::desc("Prefix for memory access callbacks"), cl::Hidden, cl::init("__memprof_"))
constexpr char MemProfModuleCtorName[]
static cl::opt< bool > ClInstrumentReads("memprof-instrument-reads", cl::desc("instrument read instructions"), cl::Hidden, cl::init(true))
static cl::opt< int > ClDebugMax("memprof-debug-max", cl::desc("Debug max inst"), cl::Hidden, cl::init(-1))
static cl::opt< bool > ClInstrumentWrites("memprof-instrument-writes", cl::desc("instrument write instructions"), cl::Hidden, cl::init(true))
static cl::opt< int > ClDebug("memprof-debug", cl::desc("debug"), cl::Hidden, cl::init(0))
static cl::opt< int > ClMappingScale("memprof-mapping-scale", cl::desc("scale of memprof shadow mapping"), cl::Hidden, cl::init(DefaultShadowScale))
constexpr char MemProfHistogramFlagVar[]
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)
Class for arbitrary precision integers.
A container for analyses that lazily runs them and caches their results.
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,...
static LLVM_ABI Constant * getString(LLVMContext &Context, StringRef Initializer, bool AddNull=true)
This method constructs a CDS and initializes it with a text string.
This is an important base class in LLVM.
static LLVM_ABI Constant * getIntegerValue(Type *Ty, const APInt &V)
Return the value for an integer or pointer constant, or a vector thereof, with the given scalar value...
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 LLVM_ABI FunctionType * get(Type *Result, ArrayRef< Type * > Params, bool isVarArg)
This static method is the primary way of constructing a FunctionType.
LLVM_ABI void setComdat(Comdat *C)
void setLinkage(LinkageTypes LT)
@ ExternalLinkage
Externally visible function.
@ WeakAnyLinkage
Keep one copy of named function when linking (weak)
@ AvailableExternallyLinkage
Available for inspection, not emission.
Value * CreateICmpULT(Value *LHS, Value *RHS, const Twine &Name="")
Value * CreateExtractElement(Value *Vec, Value *Idx, const Twine &Name="")
Value * CreatePointerCast(Value *V, Type *DestTy, const Twine &Name="")
Value * CreateIntToPtr(Value *V, Type *DestTy, const Twine &Name="")
Value * CreateLShr(Value *LHS, Value *RHS, const Twine &Name="", bool isExact=false)
IntegerType * getInt32Ty()
Fetch the type representing a 32-bit integer.
Value * CreateGEP(Type *Ty, Value *Ptr, ArrayRef< Value * > IdxList, const Twine &Name="", GEPNoWrapFlags NW=GEPNoWrapFlags::none())
LoadInst * CreateLoad(Type *Ty, Value *Ptr, const char *Name)
Provided to resolve 'CreateLoad(Ty, Ptr, "...")' correctly, instead of converting the string to 'bool...
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)
CallInst * CreateCall(FunctionType *FTy, Value *Callee, ArrayRef< Value * > Args={}, const Twine &Name="", MDNode *FPMathTag=nullptr)
Value * CreateIntCast(Value *V, Type *DestTy, bool isSigned, const Twine &Name="")
void SetInsertPoint(BasicBlock *TheBB)
This specifies that created instructions should be appended to the end of the specified block.
Type * getVoidTy()
Fetch the type representing void.
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
An instruction for reading from memory.
LLVM_ABI StringRef getString() const
This is the common base class for memset/memcpy/memmove.
LLVM_ABI MemProfilerPass()
LLVM_ABI PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM)
LLVM_ABI PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM)
LLVM_ABI ModuleMemProfilerPass()
A Module instance is used to store all the information related to an LLVM module.
static LLVM_ABI PointerType * get(Type *ElementType, unsigned AddressSpace)
This constructs a pointer to an object of the specified type in a numbered address space.
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.
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.
constexpr bool empty() const
empty - Check if the string is empty.
Triple - Helper class for working with autoconf configuration names.
bool isOSEmscripten() const
Tests whether the OS is Emscripten.
The instances of the Type class are immutable: once they are created, they are never changed.
LLVM_ABI unsigned getPointerAddressSpace() const
Get the address space of this pointer or pointer vector type.
static LLVM_ABI IntegerType * getInt8Ty(LLVMContext &C)
static LLVM_ABI IntegerType * getInt1Ty(LLVMContext &C)
LLVM Value Representation.
Type * getType() const
All values are typed, get the type of this value.
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
void instrumentAddress(Module &M, IRBuilder<> &IRB, Instruction *OrigIns, Instruction *InsertBefore, Value *Addr, Align Alignment, TypeSize TypeStoreSize, bool IsWrite, Value *SizeArgument, bool UseCalls, bool Recover, int AsanScale, int AsanOffset)
Instrument the memory operand Addr.
constexpr std::underlying_type_t< E > Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
@ C
The default llvm calling convention, compatible with C.
initializer< Ty > init(const Ty &Val)
llvm::StringRef getMemprofOptionsSymbolName()
This is an optimization pass for GlobalISel generic memory operations.
FunctionAddr VTableAddr Value
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
LLVM_ABI std::string getInstrProfSectionName(InstrProfSectKind IPSK, Triple::ObjectFormatType OF, bool AddSegmentInfo=true)
Return the name of the profile section corresponding to IPSK.
auto dyn_cast_or_null(const Y &Val)
LLVM_ABI FunctionCallee declareSanitizerInitFunction(Module &M, StringRef InitName, ArrayRef< Type * > InitArgTypes, bool Weak=false)
LLVM_ABI 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.
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
IRBuilder(LLVMContext &, FolderTy, InserterTy, MDNode *, ArrayRef< OperandBundleDef >) -> IRBuilder< FolderTy, InserterTy >
LLVM_ABI void appendToCompilerUsed(Module &M, ArrayRef< GlobalValue * > Values)
Adds global values to the llvm.compiler.used list.
LLVM_ABI void createProfileFileNameVar(Module &M, StringRef InstrProfileOutput)
LLVM_ABI 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.
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
LLVM_ABI 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 ...
LLVM_ABI const Value * getUnderlyingObject(const Value *V, unsigned MaxLookup=MaxLookupSearchDepth)
This method strips off any GEP address adjustments, pointer casts or llvm.threadlocal....