LLVM  14.0.0git
EntryExitInstrumenter.cpp
Go to the documentation of this file.
1 //===- EntryExitInstrumenter.cpp - Function Entry/Exit Instrumentation ----===//
2 //
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
6 //
7 //===----------------------------------------------------------------------===//
8 
12 #include "llvm/IR/Dominators.h"
13 #include "llvm/IR/Function.h"
14 #include "llvm/IR/Instructions.h"
15 #include "llvm/IR/Intrinsics.h"
16 #include "llvm/IR/Module.h"
17 #include "llvm/IR/Type.h"
18 #include "llvm/InitializePasses.h"
19 #include "llvm/Pass.h"
20 #include "llvm/Transforms/Utils.h"
21 
22 using namespace llvm;
23 
24 static void insertCall(Function &CurFn, StringRef Func,
25  Instruction *InsertionPt, DebugLoc DL) {
26  Module &M = *InsertionPt->getParent()->getParent()->getParent();
27  LLVMContext &C = InsertionPt->getParent()->getContext();
28 
29  if (Func == "mcount" ||
30  Func == ".mcount" ||
31  Func == "llvm.arm.gnu.eabi.mcount" ||
32  Func == "\01_mcount" ||
33  Func == "\01mcount" ||
34  Func == "__mcount" ||
35  Func == "_mcount" ||
36  Func == "__cyg_profile_func_enter_bare") {
37  FunctionCallee Fn = M.getOrInsertFunction(Func, Type::getVoidTy(C));
38  CallInst *Call = CallInst::Create(Fn, "", InsertionPt);
39  Call->setDebugLoc(DL);
40  return;
41  }
42 
43  if (Func == "__cyg_profile_func_enter" || Func == "__cyg_profile_func_exit") {
44  Type *ArgTypes[] = {Type::getInt8PtrTy(C), Type::getInt8PtrTy(C)};
45 
46  FunctionCallee Fn = M.getOrInsertFunction(
47  Func, FunctionType::get(Type::getVoidTy(C), ArgTypes, false));
48 
49  Instruction *RetAddr = CallInst::Create(
50  Intrinsic::getDeclaration(&M, Intrinsic::returnaddress),
52  InsertionPt);
53  RetAddr->setDebugLoc(DL);
54 
56  RetAddr};
57 
58  CallInst *Call =
59  CallInst::Create(Fn, ArrayRef<Value *>(Args), "", InsertionPt);
60  Call->setDebugLoc(DL);
61  return;
62  }
63 
64  // We only know how to call a fixed set of instrumentation functions, because
65  // they all expect different arguments, etc.
66  report_fatal_error(Twine("Unknown instrumentation function: '") + Func + "'");
67 }
68 
69 static bool runOnFunction(Function &F, bool PostInlining) {
70  StringRef EntryAttr = PostInlining ? "instrument-function-entry-inlined"
71  : "instrument-function-entry";
72 
73  StringRef ExitAttr = PostInlining ? "instrument-function-exit-inlined"
74  : "instrument-function-exit";
75 
76  StringRef EntryFunc = F.getFnAttribute(EntryAttr).getValueAsString();
77  StringRef ExitFunc = F.getFnAttribute(ExitAttr).getValueAsString();
78 
79  bool Changed = false;
80 
81  // If the attribute is specified, insert instrumentation and then "consume"
82  // the attribute so that it's not inserted again if the pass should happen to
83  // run later for some reason.
84 
85  if (!EntryFunc.empty()) {
86  DebugLoc DL;
87  if (auto SP = F.getSubprogram())
88  DL = DILocation::get(SP->getContext(), SP->getScopeLine(), 0, SP);
89 
90  insertCall(F, EntryFunc, &*F.begin()->getFirstInsertionPt(), DL);
91  Changed = true;
92  F.removeAttribute(AttributeList::FunctionIndex, EntryAttr);
93  }
94 
95  if (!ExitFunc.empty()) {
96  for (BasicBlock &BB : F) {
97  Instruction *T = BB.getTerminator();
98  if (!isa<ReturnInst>(T))
99  continue;
100 
101  // If T is preceded by a musttail call, that's the real terminator.
102  if (CallInst *CI = BB.getTerminatingMustTailCall())
103  T = CI;
104 
105  DebugLoc DL;
106  if (DebugLoc TerminatorDL = T->getDebugLoc())
107  DL = TerminatorDL;
108  else if (auto SP = F.getSubprogram())
109  DL = DILocation::get(SP->getContext(), 0, 0, SP);
110 
111  insertCall(F, ExitFunc, T, DL);
112  Changed = true;
113  }
114  F.removeAttribute(AttributeList::FunctionIndex, ExitAttr);
115  }
116 
117  return Changed;
118 }
119 
120 namespace {
121 struct EntryExitInstrumenter : public FunctionPass {
122  static char ID;
123  EntryExitInstrumenter() : FunctionPass(ID) {
125  }
126  void getAnalysisUsage(AnalysisUsage &AU) const override {
129  }
130  bool runOnFunction(Function &F) override { return ::runOnFunction(F, false); }
131 };
133 
134 struct PostInlineEntryExitInstrumenter : public FunctionPass {
135  static char ID;
136  PostInlineEntryExitInstrumenter() : FunctionPass(ID) {
139  }
140  void getAnalysisUsage(AnalysisUsage &AU) const override {
143  }
144  bool runOnFunction(Function &F) override { return ::runOnFunction(F, true); }
145 };
147 }
148 
150  EntryExitInstrumenter, "ee-instrument",
151  "Instrument function entry/exit with calls to e.g. mcount() (pre inlining)",
152  false, false)
155  EntryExitInstrumenter, "ee-instrument",
156  "Instrument function entry/exit with calls to e.g. mcount() (pre inlining)",
158 
160  PostInlineEntryExitInstrumenter, "post-inline-ee-instrument",
161  "Instrument function entry/exit with calls to e.g. mcount() "
162  "(post inlining)",
163  false, false)
166  PostInlineEntryExitInstrumenter, "post-inline-ee-instrument",
167  "Instrument function entry/exit with calls to e.g. mcount() "
168  "(post inlining)",
169  false, false)
170 
172  return new EntryExitInstrumenter();
173 }
174 
176  return new PostInlineEntryExitInstrumenter();
177 }
178 
181  runOnFunction(F, PostInlining);
183  PA.preserveSet<CFGAnalyses>();
184  return PA;
185 }
llvm::PreservedAnalyses
A set of analyses that are preserved following a run of a transformation pass.
Definition: PassManager.h:155
llvm
---------------------— PointerInfo ------------------------------------—
Definition: AllocatorList.h:23
M
We currently emits eax Perhaps this is what we really should generate is Is imull three or four cycles eax eax The current instruction priority is based on pattern complexity The former is more complex because it folds a load so the latter will not be emitted Perhaps we should use AddedComplexity to give LEA32r a higher priority We should always try to match LEA first since the LEA matching code does some estimate to determine whether the match is profitable if we care more about code then imull is better It s two bytes shorter than movl leal On a Pentium M
Definition: README.txt:252
llvm::StringRef::empty
LLVM_NODISCARD bool empty() const
empty - Check if the string is empty.
Definition: StringRef.h:153
llvm::Intrinsic::getDeclaration
Function * getDeclaration(Module *M, ID id, ArrayRef< Type * > Tys=None)
Create or insert an LLVM Function declaration for an intrinsic, and return it.
Definition: Function.cpp:1336
llvm::Type::getInt8PtrTy
static PointerType * getInt8PtrTy(LLVMContext &C, unsigned AS=0)
Definition: Type.cpp:255
llvm::BasicBlock::getParent
const Function * getParent() const
Return the enclosing method, or null if none.
Definition: BasicBlock.h:107
DebugInfoMetadata.h
llvm::Function
Definition: Function.h:61
Pass.h
llvm::ConstantExpr::getBitCast
static Constant * getBitCast(Constant *C, Type *Ty, bool OnlyIfReduced=false)
Definition: Constants.cpp:2221
llvm::FunctionType::get
static FunctionType * get(Type *Result, ArrayRef< Type * > Params, bool isVarArg)
This static method is the primary way of constructing a FunctionType.
Definition: Type.cpp:327
GlobalsModRef.h
to
Should compile to
Definition: README.txt:449
llvm::Type
The instances of the Type class are immutable: once they are created, they are never changed.
Definition: Type.h:45
Module.h
T
#define T
Definition: Mips16ISelLowering.cpp:341
g
should just be implemented with a CLZ instruction Since there are other e g
Definition: README.txt:709
llvm::initializeEntryExitInstrumenterPass
void initializeEntryExitInstrumenterPass(PassRegistry &)
llvm::Type::getInt32Ty
static IntegerType * getInt32Ty(LLVMContext &C)
Definition: Type.cpp:203
llvm::MDNode::get
static MDTuple * get(LLVMContext &Context, ArrayRef< Metadata * > MDs)
Definition: Metadata.h:1198
F
#define F(x, y, z)
Definition: MD5.cpp:56
llvm::BasicBlock
LLVM Basic Block Representation.
Definition: BasicBlock.h:58
INITIALIZE_PASS_BEGIN
INITIALIZE_PASS_BEGIN(EntryExitInstrumenter, "ee-instrument", "Instrument function entry/exit with calls to e.g. mcount() (pre inlining)", false, false) INITIALIZE_PASS_END(EntryExitInstrumenter
llvm::PassRegistry::getPassRegistry
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
Definition: PassRegistry.cpp:31
mcount
ee Instrument function entry exit with calls to e g mcount()(pre inlining)"
Intrinsics.h
C
(vector float) vec_cmpeq(*A, *B) C
Definition: README_ALTIVEC.txt:86
llvm::CallInst::Create
static CallInst * Create(FunctionType *Ty, Value *F, const Twine &NameStr="", Instruction *InsertBefore=nullptr)
Definition: Instructions.h:1518
llvm::AnalysisUsage
Represent the analysis usage information of a pass.
Definition: PassAnalysisSupport.h:47
false
Definition: StackSlotColoring.cpp:142
llvm::Instruction
Definition: Instruction.h:45
llvm::DominatorTreeWrapperPass
Legacy analysis pass which computes a DominatorTree.
Definition: Dominators.h:281
llvm::report_fatal_error
void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
Definition: Error.cpp:140
llvm::ConstantInt::get
static Constant * get(Type *Ty, uint64_t V, bool IsSigned=false)
If Ty is a vector type, return a Constant with a splat of the given value.
Definition: Constants.cpp:899
Utils.h
insertCall
static void insertCall(Function &CurFn, StringRef Func, Instruction *InsertionPt, DebugLoc DL)
Definition: EntryExitInstrumenter.cpp:24
Type.h
INITIALIZE_PASS_END
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
Definition: PassSupport.h:58
llvm::GlobalValue::getParent
Module * getParent()
Get the module that this global value is contained inside of...
Definition: GlobalValue.h:572
instrument
ee instrument
Definition: EntryExitInstrumenter.cpp:155
INITIALIZE_PASS_DEPENDENCY
INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass)
llvm::LLVMContext
This is an important class for using LLVM in a threaded context.
Definition: LLVMContext.h:68
llvm::numbers::e
constexpr double e
Definition: MathExtras.h:57
llvm::Instruction::setDebugLoc
void setDebugLoc(DebugLoc Loc)
Set the debug location information for this instruction.
Definition: Instruction.h:369
inline
into xmm2 addss xmm2 xmm1 xmm3 addss xmm3 movaps xmm0 unpcklps xmm0 ret seems silly when it could just be one addps Expand libm rounding functions inline
Definition: README-SSE.txt:72
llvm::createPostInlineEntryExitInstrumenterPass
FunctionPass * createPostInlineEntryExitInstrumenterPass()
Definition: EntryExitInstrumenter.cpp:175
function
print Print MemDeps of function
Definition: MemDepPrinter.cpp:83
llvm::Module
A Module instance is used to store all the information related to an LLVM module.
Definition: Module.h:67
llvm::ArrayRef
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition: APInt.h:32
llvm::StringRef
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:58
llvm::CFGAnalyses
Represents analyses that only rely on functions' control flow.
Definition: PassManager.h:116
llvm::AnalysisUsage::addPreserved
AnalysisUsage & addPreserved()
Add the specified Pass class to the set of analyses preserved by this pass.
Definition: PassAnalysisSupport.h:98
DL
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
Definition: AArch64SLSHardening.cpp:76
llvm::initializePostInlineEntryExitInstrumenterPass
void initializePostInlineEntryExitInstrumenterPass(PassRegistry &)
llvm::BasicBlock::getContext
LLVMContext & getContext() const
Get the context in which this basic block lives.
Definition: BasicBlock.cpp:32
runOnFunction
static bool runOnFunction(Function &F, bool PostInlining)
Definition: EntryExitInstrumenter.cpp:69
llvm::Twine
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition: Twine.h:83
Function.h
llvm::AttributeList::FunctionIndex
@ FunctionIndex
Definition: Attributes.h:402
llvm::Type::getVoidTy
static Type * getVoidTy(LLVMContext &C)
Definition: Type.cpp:186
Instructions.h
llvm::PreservedAnalyses::preserveSet
void preserveSet()
Mark an analysis set as preserved.
Definition: PassManager.h:191
exit
declare void exit(i32) noreturn nounwind This compiles into
Definition: README.txt:1072
Dominators.h
llvm::Instruction::getParent
const BasicBlock * getParent() const
Definition: Instruction.h:94
llvm::GlobalsAAWrapperPass
Legacy wrapper pass to provide the GlobalsAAResult object.
Definition: GlobalsModRef.h:143
llvm::FunctionCallee
A handy container for a FunctionType+Callee-pointer pair, which can be passed around as a single enti...
Definition: DerivedTypes.h:164
calls
amdgpu Simplify well known AMD library calls
Definition: AMDGPULibCalls.cpp:199
llvm::EntryExitInstrumenterPass::run
PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM)
Definition: EntryExitInstrumenter.cpp:180
llvm::createEntryExitInstrumenterPass
FunctionPass * createEntryExitInstrumenterPass()
Definition: EntryExitInstrumenter.cpp:171
llvm::AnalysisManager
A container for analyses that lazily runs them and caches their results.
Definition: InstructionSimplify.h:44
llvm::FunctionPass
FunctionPass class - This class is used to implement most global optimizations.
Definition: Pass.h:298
llvm::CallInst
This class represents a function call, abstracting a target machine's calling convention.
Definition: Instructions.h:1475
BB
Common register allocation spilling lr str ldr sxth r3 ldr mla r4 can lr mov lr str ldr sxth r3 mla r4 and then merge mul and lr str ldr sxth r3 mla r4 It also increase the likelihood the store may become dead bb27 Successors according to LLVM BB
Definition: README.txt:39
llvm::DebugLoc
A debug info location.
Definition: DebugLoc.h:33
llvm::AMDGPU::HSAMD::Kernel::Key::Args
constexpr char Args[]
Key for Kernel::Metadata::mArgs.
Definition: AMDGPUMetadata.h:389
EntryExitInstrumenter.h
InitializePasses.h
llvm::Value
LLVM Value Representation.
Definition: Value.h:75
entry
print Instructions which execute on loop entry
Definition: MustExecute.cpp:339
llvm::Intrinsic::ID
unsigned ID
Definition: TargetTransformInfo.h:38