1 //===- MemProfiler.cpp - memory allocation and access profiler ------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 // This file is a part of MemProfiler. Memory accesses are instrumented
10 // to increment the access count held in a shadow memory location, or
11 // alternatively to call into the runtime. Memory intrinsic calls (memmove,
12 // memcpy, memset) are changed to call the memory profiling runtime version
15 //===----------------------------------------------------------------------===//
17 #include "llvm/Transforms/Instrumentation/MemProfiler.h"
18 #include "llvm/ADT/SmallVector.h"
19 #include "llvm/ADT/Statistic.h"
20 #include "llvm/ADT/StringRef.h"
21 #include "llvm/ADT/Triple.h"
22 #include "llvm/IR/Constant.h"
23 #include "llvm/IR/DataLayout.h"
24 #include "llvm/IR/Function.h"
25 #include "llvm/IR/GlobalValue.h"
26 #include "llvm/IR/IRBuilder.h"
27 #include "llvm/IR/Instruction.h"
28 #include "llvm/IR/LLVMContext.h"
29 #include "llvm/IR/Module.h"
30 #include "llvm/IR/Type.h"
31 #include "llvm/IR/Value.h"
32 #include "llvm/InitializePasses.h"
33 #include "llvm/Pass.h"
34 #include "llvm/Support/CommandLine.h"
35 #include "llvm/Support/Debug.h"
36 #include "llvm/Transforms/Instrumentation.h"
37 #include "llvm/Transforms/Utils/BasicBlockUtils.h"
38 #include "llvm/Transforms/Utils/ModuleUtils.h"
42 #define DEBUG_TYPE "memprof"
44 constexpr int LLVM_MEM_PROFILER_VERSION
= 1;
46 // Size of memory mapped to a single shadow location.
47 constexpr uint64_t DefaultShadowGranularity
= 64;
49 // Scale from granularity down to shadow size.
50 constexpr uint64_t DefaultShadowScale
= 3;
52 constexpr char MemProfModuleCtorName
[] = "memprof.module_ctor";
53 constexpr uint64_t MemProfCtorAndDtorPriority
= 1;
54 // On Emscripten, the system needs more than one priorities for constructors.
55 constexpr uint64_t MemProfEmscriptenCtorAndDtorPriority
= 50;
56 constexpr char MemProfInitName
[] = "__memprof_init";
57 constexpr char MemProfVersionCheckNamePrefix
[] =
58 "__memprof_version_mismatch_check_v";
60 constexpr char MemProfShadowMemoryDynamicAddress
[] =
61 "__memprof_shadow_memory_dynamic_address";
63 constexpr char MemProfFilenameVar
[] = "__memprof_profile_filename";
65 // Command-line flags.
67 static cl::opt
<bool> ClInsertVersionCheck(
68 "memprof-guard-against-version-mismatch",
69 cl::desc("Guard against compiler/runtime version mismatch."), cl::Hidden
,
72 // This flag may need to be replaced with -f[no-]memprof-reads.
73 static cl::opt
<bool> ClInstrumentReads("memprof-instrument-reads",
74 cl::desc("instrument read instructions"),
75 cl::Hidden
, cl::init(true));
78 ClInstrumentWrites("memprof-instrument-writes",
79 cl::desc("instrument write instructions"), cl::Hidden
,
82 static cl::opt
<bool> ClInstrumentAtomics(
83 "memprof-instrument-atomics",
84 cl::desc("instrument atomic instructions (rmw, cmpxchg)"), cl::Hidden
,
87 static cl::opt
<bool> ClUseCalls(
88 "memprof-use-callbacks",
89 cl::desc("Use callbacks instead of inline instrumentation sequences."),
90 cl::Hidden
, cl::init(false));
92 static cl::opt
<std::string
>
93 ClMemoryAccessCallbackPrefix("memprof-memory-access-callback-prefix",
94 cl::desc("Prefix for memory access callbacks"),
95 cl::Hidden
, cl::init("__memprof_"));
97 // These flags allow to change the shadow mapping.
98 // The shadow mapping looks like
99 // Shadow = ((Mem & mask) >> scale) + offset
101 static cl::opt
<int> ClMappingScale("memprof-mapping-scale",
102 cl::desc("scale of memprof shadow mapping"),
103 cl::Hidden
, cl::init(DefaultShadowScale
));
106 ClMappingGranularity("memprof-mapping-granularity",
107 cl::desc("granularity of memprof shadow mapping"),
108 cl::Hidden
, cl::init(DefaultShadowGranularity
));
112 static cl::opt
<int> ClDebug("memprof-debug", cl::desc("debug"), cl::Hidden
,
115 static cl::opt
<std::string
> ClDebugFunc("memprof-debug-func", cl::Hidden
,
116 cl::desc("Debug func"));
118 static cl::opt
<int> ClDebugMin("memprof-debug-min", cl::desc("Debug min inst"),
119 cl::Hidden
, cl::init(-1));
121 static cl::opt
<int> ClDebugMax("memprof-debug-max", cl::desc("Debug max inst"),
122 cl::Hidden
, cl::init(-1));
124 STATISTIC(NumInstrumentedReads
, "Number of instrumented reads");
125 STATISTIC(NumInstrumentedWrites
, "Number of instrumented writes");
129 /// This struct defines the shadow mapping using the rule:
130 /// shadow = ((mem & mask) >> Scale) ADD DynamicShadowOffset.
131 struct ShadowMapping
{
133 Scale
= ClMappingScale
;
134 Granularity
= ClMappingGranularity
;
135 Mask
= ~(Granularity
- 1);
140 uint64_t Mask
; // Computed as ~(Granularity-1)
143 static uint64_t getCtorAndDtorPriority(Triple
&TargetTriple
) {
144 return TargetTriple
.isOSEmscripten() ? MemProfEmscriptenCtorAndDtorPriority
145 : MemProfCtorAndDtorPriority
;
148 struct InterestingMemoryAccess
{
149 Value
*Addr
= nullptr;
153 Value
*MaybeMask
= nullptr;
156 /// Instrument the code in module to profile memory accesses.
159 MemProfiler(Module
&M
) {
160 C
= &(M
.getContext());
161 LongSize
= M
.getDataLayout().getPointerSizeInBits();
162 IntptrTy
= Type::getIntNTy(*C
, LongSize
);
165 /// If it is an interesting memory access, populate information
166 /// about the access and return a InterestingMemoryAccess struct.
167 /// Otherwise return None.
168 Optional
<InterestingMemoryAccess
>
169 isInterestingMemoryAccess(Instruction
*I
) const;
171 void instrumentMop(Instruction
*I
, const DataLayout
&DL
,
172 InterestingMemoryAccess
&Access
);
173 void instrumentAddress(Instruction
*OrigIns
, Instruction
*InsertBefore
,
174 Value
*Addr
, uint32_t TypeSize
, bool IsWrite
);
175 void instrumentMaskedLoadOrStore(const DataLayout
&DL
, Value
*Mask
,
176 Instruction
*I
, Value
*Addr
,
177 unsigned Alignment
, uint32_t TypeSize
,
179 void instrumentMemIntrinsic(MemIntrinsic
*MI
);
180 Value
*memToShadow(Value
*Shadow
, IRBuilder
<> &IRB
);
181 bool instrumentFunction(Function
&F
);
182 bool maybeInsertMemProfInitAtFunctionEntry(Function
&F
);
183 bool insertDynamicShadowAtFunctionEntry(Function
&F
);
186 void initializeCallbacks(Module
&M
);
191 ShadowMapping Mapping
;
193 // These arrays is indexed by AccessIsWrite
194 FunctionCallee MemProfMemoryAccessCallback
[2];
195 FunctionCallee MemProfMemoryAccessCallbackSized
[2];
197 FunctionCallee MemProfMemmove
, MemProfMemcpy
, MemProfMemset
;
198 Value
*DynamicShadowOffset
= nullptr;
201 class MemProfilerLegacyPass
: public FunctionPass
{
205 explicit MemProfilerLegacyPass() : FunctionPass(ID
) {
206 initializeMemProfilerLegacyPassPass(*PassRegistry::getPassRegistry());
209 StringRef
getPassName() const override
{ return "MemProfilerFunctionPass"; }
211 bool runOnFunction(Function
&F
) override
{
212 MemProfiler
Profiler(*F
.getParent());
213 return Profiler
.instrumentFunction(F
);
217 class ModuleMemProfiler
{
219 ModuleMemProfiler(Module
&M
) { TargetTriple
= Triple(M
.getTargetTriple()); }
221 bool instrumentModule(Module
&);
225 ShadowMapping Mapping
;
226 Function
*MemProfCtorFunction
= nullptr;
229 class ModuleMemProfilerLegacyPass
: public ModulePass
{
233 explicit ModuleMemProfilerLegacyPass() : ModulePass(ID
) {
234 initializeModuleMemProfilerLegacyPassPass(*PassRegistry::getPassRegistry());
237 StringRef
getPassName() const override
{ return "ModuleMemProfiler"; }
239 void getAnalysisUsage(AnalysisUsage
&AU
) const override
{}
241 bool runOnModule(Module
&M
) override
{
242 ModuleMemProfiler
MemProfiler(M
);
243 return MemProfiler
.instrumentModule(M
);
247 } // end anonymous namespace
249 MemProfilerPass::MemProfilerPass() {}
251 PreservedAnalyses
MemProfilerPass::run(Function
&F
,
252 AnalysisManager
<Function
> &AM
) {
253 Module
&M
= *F
.getParent();
254 MemProfiler
Profiler(M
);
255 if (Profiler
.instrumentFunction(F
))
256 return PreservedAnalyses::none();
257 return PreservedAnalyses::all();
260 ModuleMemProfilerPass::ModuleMemProfilerPass() {}
262 PreservedAnalyses
ModuleMemProfilerPass::run(Module
&M
,
263 AnalysisManager
<Module
> &AM
) {
264 ModuleMemProfiler
Profiler(M
);
265 if (Profiler
.instrumentModule(M
))
266 return PreservedAnalyses::none();
267 return PreservedAnalyses::all();
270 char MemProfilerLegacyPass::ID
= 0;
272 INITIALIZE_PASS_BEGIN(MemProfilerLegacyPass
, "memprof",
273 "MemProfiler: profile memory allocations and accesses.",
275 INITIALIZE_PASS_END(MemProfilerLegacyPass
, "memprof",
276 "MemProfiler: profile memory allocations and accesses.",
279 FunctionPass
*llvm::createMemProfilerFunctionPass() {
280 return new MemProfilerLegacyPass();
283 char ModuleMemProfilerLegacyPass::ID
= 0;
285 INITIALIZE_PASS(ModuleMemProfilerLegacyPass
, "memprof-module",
286 "MemProfiler: profile memory allocations and accesses."
290 ModulePass
*llvm::createModuleMemProfilerLegacyPassPass() {
291 return new ModuleMemProfilerLegacyPass();
294 Value
*MemProfiler::memToShadow(Value
*Shadow
, IRBuilder
<> &IRB
) {
295 // (Shadow & mask) >> scale
296 Shadow
= IRB
.CreateAnd(Shadow
, Mapping
.Mask
);
297 Shadow
= IRB
.CreateLShr(Shadow
, Mapping
.Scale
);
298 // (Shadow >> scale) | offset
299 assert(DynamicShadowOffset
);
300 return IRB
.CreateAdd(Shadow
, DynamicShadowOffset
);
303 // Instrument memset/memmove/memcpy
304 void MemProfiler::instrumentMemIntrinsic(MemIntrinsic
*MI
) {
306 if (isa
<MemTransferInst
>(MI
)) {
308 isa
<MemMoveInst
>(MI
) ? MemProfMemmove
: MemProfMemcpy
,
309 {IRB
.CreatePointerCast(MI
->getOperand(0), IRB
.getInt8PtrTy()),
310 IRB
.CreatePointerCast(MI
->getOperand(1), IRB
.getInt8PtrTy()),
311 IRB
.CreateIntCast(MI
->getOperand(2), IntptrTy
, false)});
312 } else if (isa
<MemSetInst
>(MI
)) {
315 {IRB
.CreatePointerCast(MI
->getOperand(0), IRB
.getInt8PtrTy()),
316 IRB
.CreateIntCast(MI
->getOperand(1), IRB
.getInt32Ty(), false),
317 IRB
.CreateIntCast(MI
->getOperand(2), IntptrTy
, false)});
319 MI
->eraseFromParent();
322 Optional
<InterestingMemoryAccess
>
323 MemProfiler::isInterestingMemoryAccess(Instruction
*I
) const {
324 // Do not instrument the load fetching the dynamic shadow address.
325 if (DynamicShadowOffset
== I
)
328 InterestingMemoryAccess Access
;
330 const DataLayout
&DL
= I
->getModule()->getDataLayout();
331 if (LoadInst
*LI
= dyn_cast
<LoadInst
>(I
)) {
332 if (!ClInstrumentReads
)
334 Access
.IsWrite
= false;
335 Access
.TypeSize
= DL
.getTypeStoreSizeInBits(LI
->getType());
336 Access
.Alignment
= LI
->getAlignment();
337 Access
.Addr
= LI
->getPointerOperand();
338 } else if (StoreInst
*SI
= dyn_cast
<StoreInst
>(I
)) {
339 if (!ClInstrumentWrites
)
341 Access
.IsWrite
= true;
343 DL
.getTypeStoreSizeInBits(SI
->getValueOperand()->getType());
344 Access
.Alignment
= SI
->getAlignment();
345 Access
.Addr
= SI
->getPointerOperand();
346 } else if (AtomicRMWInst
*RMW
= dyn_cast
<AtomicRMWInst
>(I
)) {
347 if (!ClInstrumentAtomics
)
349 Access
.IsWrite
= true;
351 DL
.getTypeStoreSizeInBits(RMW
->getValOperand()->getType());
352 Access
.Alignment
= 0;
353 Access
.Addr
= RMW
->getPointerOperand();
354 } else if (AtomicCmpXchgInst
*XCHG
= dyn_cast
<AtomicCmpXchgInst
>(I
)) {
355 if (!ClInstrumentAtomics
)
357 Access
.IsWrite
= true;
359 DL
.getTypeStoreSizeInBits(XCHG
->getCompareOperand()->getType());
360 Access
.Alignment
= 0;
361 Access
.Addr
= XCHG
->getPointerOperand();
362 } else if (auto *CI
= dyn_cast
<CallInst
>(I
)) {
363 auto *F
= CI
->getCalledFunction();
364 if (F
&& (F
->getIntrinsicID() == Intrinsic::masked_load
||
365 F
->getIntrinsicID() == Intrinsic::masked_store
)) {
366 unsigned OpOffset
= 0;
367 if (F
->getIntrinsicID() == Intrinsic::masked_store
) {
368 if (!ClInstrumentWrites
)
370 // Masked store has an initial operand for the value.
372 Access
.IsWrite
= true;
374 if (!ClInstrumentReads
)
376 Access
.IsWrite
= false;
379 auto *BasePtr
= CI
->getOperand(0 + OpOffset
);
380 auto *Ty
= cast
<PointerType
>(BasePtr
->getType())->getElementType();
381 Access
.TypeSize
= DL
.getTypeStoreSizeInBits(Ty
);
382 if (auto *AlignmentConstant
=
383 dyn_cast
<ConstantInt
>(CI
->getOperand(1 + OpOffset
)))
384 Access
.Alignment
= (unsigned)AlignmentConstant
->getZExtValue();
386 Access
.Alignment
= 1; // No alignment guarantees. We probably got Undef
387 Access
.MaybeMask
= CI
->getOperand(2 + OpOffset
);
388 Access
.Addr
= BasePtr
;
395 // Do not instrument acesses from different address spaces; we cannot deal
397 Type
*PtrTy
= cast
<PointerType
>(Access
.Addr
->getType()->getScalarType());
398 if (PtrTy
->getPointerAddressSpace() != 0)
401 // Ignore swifterror addresses.
402 // swifterror memory addresses are mem2reg promoted by instruction
403 // selection. As such they cannot have regular uses like an instrumentation
404 // function and it makes no sense to track them as memory.
405 if (Access
.Addr
->isSwiftError())
411 void MemProfiler::instrumentMaskedLoadOrStore(const DataLayout
&DL
, Value
*Mask
,
412 Instruction
*I
, Value
*Addr
,
414 uint32_t TypeSize
, bool IsWrite
) {
415 auto *VTy
= cast
<FixedVectorType
>(
416 cast
<PointerType
>(Addr
->getType())->getElementType());
417 uint64_t ElemTypeSize
= DL
.getTypeStoreSizeInBits(VTy
->getScalarType());
418 unsigned Num
= VTy
->getNumElements();
419 auto *Zero
= ConstantInt::get(IntptrTy
, 0);
420 for (unsigned Idx
= 0; Idx
< Num
; ++Idx
) {
421 Value
*InstrumentedAddress
= nullptr;
422 Instruction
*InsertBefore
= I
;
423 if (auto *Vector
= dyn_cast
<ConstantVector
>(Mask
)) {
424 // dyn_cast as we might get UndefValue
425 if (auto *Masked
= dyn_cast
<ConstantInt
>(Vector
->getOperand(Idx
))) {
426 if (Masked
->isZero())
427 // Mask is constant false, so no instrumentation needed.
429 // If we have a true or undef value, fall through to instrumentAddress.
430 // with InsertBefore == I
434 Value
*MaskElem
= IRB
.CreateExtractElement(Mask
, Idx
);
435 Instruction
*ThenTerm
= SplitBlockAndInsertIfThen(MaskElem
, I
, false);
436 InsertBefore
= ThenTerm
;
439 IRBuilder
<> IRB(InsertBefore
);
440 InstrumentedAddress
=
441 IRB
.CreateGEP(VTy
, Addr
, {Zero
, ConstantInt::get(IntptrTy
, Idx
)});
442 instrumentAddress(I
, InsertBefore
, InstrumentedAddress
, ElemTypeSize
,
447 void MemProfiler::instrumentMop(Instruction
*I
, const DataLayout
&DL
,
448 InterestingMemoryAccess
&Access
) {
450 NumInstrumentedWrites
++;
452 NumInstrumentedReads
++;
454 if (Access
.MaybeMask
) {
455 instrumentMaskedLoadOrStore(DL
, Access
.MaybeMask
, I
, Access
.Addr
,
456 Access
.Alignment
, Access
.TypeSize
,
459 // Since the access counts will be accumulated across the entire allocation,
460 // we only update the shadow access count for the first location and thus
461 // don't need to worry about alignment and type size.
462 instrumentAddress(I
, I
, Access
.Addr
, Access
.TypeSize
, Access
.IsWrite
);
466 void MemProfiler::instrumentAddress(Instruction
*OrigIns
,
467 Instruction
*InsertBefore
, Value
*Addr
,
468 uint32_t TypeSize
, bool IsWrite
) {
469 IRBuilder
<> IRB(InsertBefore
);
470 Value
*AddrLong
= IRB
.CreatePointerCast(Addr
, IntptrTy
);
473 IRB
.CreateCall(MemProfMemoryAccessCallback
[IsWrite
], AddrLong
);
477 // Create an inline sequence to compute shadow location, and increment the
479 Type
*ShadowTy
= Type::getInt64Ty(*C
);
480 Type
*ShadowPtrTy
= PointerType::get(ShadowTy
, 0);
481 Value
*ShadowPtr
= memToShadow(AddrLong
, IRB
);
482 Value
*ShadowAddr
= IRB
.CreateIntToPtr(ShadowPtr
, ShadowPtrTy
);
483 Value
*ShadowValue
= IRB
.CreateLoad(ShadowTy
, ShadowAddr
);
484 Value
*Inc
= ConstantInt::get(Type::getInt64Ty(*C
), 1);
485 ShadowValue
= IRB
.CreateAdd(ShadowValue
, Inc
);
486 IRB
.CreateStore(ShadowValue
, ShadowAddr
);
489 // Create the variable for the profile file name.
490 void createProfileFileNameVar(Module
&M
) {
491 const MDString
*MemProfFilename
=
492 dyn_cast_or_null
<MDString
>(M
.getModuleFlag("MemProfProfileFilename"));
493 if (!MemProfFilename
)
495 assert(!MemProfFilename
->getString().empty() &&
496 "Unexpected MemProfProfileFilename metadata with empty string");
497 Constant
*ProfileNameConst
= ConstantDataArray::getString(
498 M
.getContext(), MemProfFilename
->getString(), true);
499 GlobalVariable
*ProfileNameVar
= new GlobalVariable(
500 M
, ProfileNameConst
->getType(), /*isConstant=*/true,
501 GlobalValue::WeakAnyLinkage
, ProfileNameConst
, MemProfFilenameVar
);
502 Triple
TT(M
.getTargetTriple());
503 if (TT
.supportsCOMDAT()) {
504 ProfileNameVar
->setLinkage(GlobalValue::ExternalLinkage
);
505 ProfileNameVar
->setComdat(M
.getOrInsertComdat(MemProfFilenameVar
));
509 bool ModuleMemProfiler::instrumentModule(Module
&M
) {
510 // Create a module constructor.
511 std::string MemProfVersion
= std::to_string(LLVM_MEM_PROFILER_VERSION
);
512 std::string VersionCheckName
=
513 ClInsertVersionCheck
? (MemProfVersionCheckNamePrefix
+ MemProfVersion
)
515 std::tie(MemProfCtorFunction
, std::ignore
) =
516 createSanitizerCtorAndInitFunctions(M
, MemProfModuleCtorName
,
517 MemProfInitName
, /*InitArgTypes=*/{},
518 /*InitArgs=*/{}, VersionCheckName
);
520 const uint64_t Priority
= getCtorAndDtorPriority(TargetTriple
);
521 appendToGlobalCtors(M
, MemProfCtorFunction
, Priority
);
523 createProfileFileNameVar(M
);
528 void MemProfiler::initializeCallbacks(Module
&M
) {
531 for (size_t AccessIsWrite
= 0; AccessIsWrite
<= 1; AccessIsWrite
++) {
532 const std::string TypeStr
= AccessIsWrite
? "store" : "load";
534 SmallVector
<Type
*, 3> Args2
= {IntptrTy
, IntptrTy
};
535 SmallVector
<Type
*, 2> Args1
{1, IntptrTy
};
536 MemProfMemoryAccessCallbackSized
[AccessIsWrite
] =
537 M
.getOrInsertFunction(ClMemoryAccessCallbackPrefix
+ TypeStr
+ "N",
538 FunctionType::get(IRB
.getVoidTy(), Args2
, false));
540 MemProfMemoryAccessCallback
[AccessIsWrite
] =
541 M
.getOrInsertFunction(ClMemoryAccessCallbackPrefix
+ TypeStr
,
542 FunctionType::get(IRB
.getVoidTy(), Args1
, false));
544 MemProfMemmove
= M
.getOrInsertFunction(
545 ClMemoryAccessCallbackPrefix
+ "memmove", IRB
.getInt8PtrTy(),
546 IRB
.getInt8PtrTy(), IRB
.getInt8PtrTy(), IntptrTy
);
547 MemProfMemcpy
= M
.getOrInsertFunction(ClMemoryAccessCallbackPrefix
+ "memcpy",
548 IRB
.getInt8PtrTy(), IRB
.getInt8PtrTy(),
549 IRB
.getInt8PtrTy(), IntptrTy
);
550 MemProfMemset
= M
.getOrInsertFunction(ClMemoryAccessCallbackPrefix
+ "memset",
551 IRB
.getInt8PtrTy(), IRB
.getInt8PtrTy(),
552 IRB
.getInt32Ty(), IntptrTy
);
555 bool MemProfiler::maybeInsertMemProfInitAtFunctionEntry(Function
&F
) {
556 // For each NSObject descendant having a +load method, this method is invoked
557 // by the ObjC runtime before any of the static constructors is called.
558 // Therefore we need to instrument such methods with a call to __memprof_init
559 // at the beginning in order to initialize our runtime before any access to
560 // the shadow memory.
561 // We cannot just ignore these methods, because they may call other
562 // instrumented functions.
563 if (F
.getName().find(" load]") != std::string::npos
) {
564 FunctionCallee MemProfInitFunction
=
565 declareSanitizerInitFunction(*F
.getParent(), MemProfInitName
, {});
566 IRBuilder
<> IRB(&F
.front(), F
.front().begin());
567 IRB
.CreateCall(MemProfInitFunction
, {});
573 bool MemProfiler::insertDynamicShadowAtFunctionEntry(Function
&F
) {
574 IRBuilder
<> IRB(&F
.front().front());
575 Value
*GlobalDynamicAddress
= F
.getParent()->getOrInsertGlobal(
576 MemProfShadowMemoryDynamicAddress
, IntptrTy
);
577 if (F
.getParent()->getPICLevel() == PICLevel::NotPIC
)
578 cast
<GlobalVariable
>(GlobalDynamicAddress
)->setDSOLocal(true);
579 DynamicShadowOffset
= IRB
.CreateLoad(IntptrTy
, GlobalDynamicAddress
);
583 bool MemProfiler::instrumentFunction(Function
&F
) {
584 if (F
.getLinkage() == GlobalValue::AvailableExternallyLinkage
)
586 if (ClDebugFunc
== F
.getName())
588 if (F
.getName().startswith("__memprof_"))
591 bool FunctionModified
= false;
593 // If needed, insert __memprof_init.
594 // This function needs to be called even if the function body is not
596 if (maybeInsertMemProfInitAtFunctionEntry(F
))
597 FunctionModified
= true;
599 LLVM_DEBUG(dbgs() << "MEMPROF instrumenting:\n" << F
<< "\n");
601 initializeCallbacks(*F
.getParent());
603 FunctionModified
|= insertDynamicShadowAtFunctionEntry(F
);
605 SmallVector
<Instruction
*, 16> ToInstrument
;
607 // Fill the set of memory operations to instrument.
609 for (auto &Inst
: BB
) {
610 if (isInterestingMemoryAccess(&Inst
) || isa
<MemIntrinsic
>(Inst
))
611 ToInstrument
.push_back(&Inst
);
615 int NumInstrumented
= 0;
616 for (auto *Inst
: ToInstrument
) {
617 if (ClDebugMin
< 0 || ClDebugMax
< 0 ||
618 (NumInstrumented
>= ClDebugMin
&& NumInstrumented
<= ClDebugMax
)) {
619 Optional
<InterestingMemoryAccess
> Access
=
620 isInterestingMemoryAccess(Inst
);
622 instrumentMop(Inst
, F
.getParent()->getDataLayout(), *Access
);
624 instrumentMemIntrinsic(cast
<MemIntrinsic
>(Inst
));
629 if (NumInstrumented
> 0)
630 FunctionModified
= true;
632 LLVM_DEBUG(dbgs() << "MEMPROF done instrumenting: " << FunctionModified
<< " "
635 return FunctionModified
;