LLVM 19.0.0git
StackFrameLayoutAnalysisPass.cpp
Go to the documentation of this file.
1//===-- StackFrameLayoutAnalysisPass.cpp
2//------------------------------------===//
3//
4// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5// See https://llvm.org/LICENSE.txt for license information.
6// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7//
8//===----------------------------------------------------------------------===//
9//
10// StackFrameLayoutAnalysisPass implementation. Outputs information about the
11// layout of the stack frame, using the remarks interface. On the CLI it prints
12// a textual representation of the stack frame. When possible it prints the
13// values that occupy a stack slot using any available debug information. Since
14// output is remarks based, it is also available in a machine readable file
15// format, such as YAML.
16//
17//===----------------------------------------------------------------------===//
18
19#include "llvm/ADT/SetVector.h"
25#include "llvm/CodeGen/Passes.h"
31#include "llvm/IR/PrintPasses.h"
33#include "llvm/Support/Debug.h"
36
37#include <sstream>
38
39using namespace llvm;
40
41#define DEBUG_TYPE "stack-frame-layout"
42
43namespace {
44
45/// StackFrameLayoutAnalysisPass - This is a pass to dump the stack frame of a
46/// MachineFunction.
47///
48struct StackFrameLayoutAnalysisPass : public MachineFunctionPass {
50 static char ID;
51
52 enum SlotType {
53 Spill, // a Spill slot
54 StackProtector, // Stack Protector slot
55 Variable, // a slot used to store a local data (could be a tmp)
56 Invalid // It's an error for a slot to have this type
57 };
58
59 struct SlotData {
60 int Slot;
61 int Size;
62 int Align;
63 int Offset;
64 SlotType SlotTy;
65
66 SlotData(const MachineFrameInfo &MFI, const int ValOffset, const int Idx)
67 : Slot(Idx), Size(MFI.getObjectSize(Idx)),
69 Offset(MFI.getObjectOffset(Idx) - ValOffset), SlotTy(Invalid) {
71 SlotTy = SlotType::Spill;
72 else if (Idx == MFI.getStackProtectorIndex())
73 SlotTy = SlotType::StackProtector;
74 else
75 SlotTy = SlotType::Variable;
76 }
77
78 // we use this to sort in reverse order, so that the layout is displayed
79 // correctly
80 bool operator<(const SlotData &Rhs) const { return Offset > Rhs.Offset; }
81 };
82
83 StackFrameLayoutAnalysisPass() : MachineFunctionPass(ID) {}
84
85 StringRef getPassName() const override {
86 return "Stack Frame Layout Analysis";
87 }
88
89 void getAnalysisUsage(AnalysisUsage &AU) const override {
90 AU.setPreservesAll();
93 }
94
95 bool runOnMachineFunction(MachineFunction &MF) override {
96 // TODO: We should implement a similar filter for remarks:
97 // -Rpass-func-filter=<regex>
99 return false;
100
101 LLVMContext &Ctx = MF.getFunction().getContext();
103 return false;
104
107 &MF.front());
108 Rem << ("\nFunction: " + MF.getName()).str();
109 emitStackFrameLayoutRemarks(MF, Rem);
110 getAnalysis<MachineOptimizationRemarkEmitterPass>().getORE().emit(Rem);
111 return false;
112 }
113
114 std::string getTypeString(SlotType Ty) {
115 switch (Ty) {
116 case SlotType::Spill:
117 return "Spill";
118 case SlotType::StackProtector:
119 return "Protector";
120 case SlotType::Variable:
121 return "Variable";
122 default:
123 llvm_unreachable("bad slot type for stack layout");
124 }
125 }
126
127 void emitStackSlotRemark(const MachineFunction &MF, const SlotData &D,
129 // To make it easy to understand the stack layout from the CLI, we want to
130 // print each slot like the following:
131 //
132 // Offset: [SP+8], Type: Spill, Align: 8, Size: 16
133 // foo @ /path/to/file.c:25
134 // bar @ /path/to/file.c:35
135 //
136 // Which prints the size, alignment, and offset from the SP at function
137 // entry.
138 //
139 // But we also want the machine readable remarks data to be nicely
140 // organized. So we print some additional data as strings for the CLI
141 // output, but maintain more structured data for the YAML.
142 //
143 // For example we store the Offset in YAML as:
144 // ...
145 // - Offset: -8
146 //
147 // But we print it to the CLI as
148 // Offset: [SP-8]
149
150 // Negative offsets will print a leading `-`, so only add `+`
151 std::string Prefix =
152 formatv("\nOffset: [SP{0}", (D.Offset < 0) ? "" : "+").str();
153 Rem << Prefix << ore::NV("Offset", D.Offset)
154 << "], Type: " << ore::NV("Type", getTypeString(D.SlotTy))
155 << ", Align: " << ore::NV("Align", D.Align)
156 << ", Size: " << ore::NV("Size", D.Size);
157 }
158
159 void emitSourceLocRemark(const MachineFunction &MF, const DILocalVariable *N,
161 std::string Loc =
162 formatv("{0} @ {1}:{2}", N->getName(), N->getFilename(), N->getLine())
163 .str();
164 Rem << "\n " << ore::NV("DataLoc", Loc);
165 }
166
167 void emitStackFrameLayoutRemarks(MachineFunction &MF,
169 const MachineFrameInfo &MFI = MF.getFrameInfo();
170 if (!MFI.hasStackObjects())
171 return;
172
173 // ValOffset is the offset to the local area from the SP at function entry.
174 // To display the true offset from SP, we need to subtract ValOffset from
175 // MFI's ObjectOffset.
177 const int ValOffset = (FI ? FI->getOffsetOfLocalArea() : 0);
178
179 LLVM_DEBUG(dbgs() << "getStackProtectorIndex =="
180 << MFI.getStackProtectorIndex() << "\n");
181
182 std::vector<SlotData> SlotInfo;
183
184 const unsigned int NumObj = MFI.getNumObjects();
185 SlotInfo.reserve(NumObj);
186 // initialize slot info
187 for (int Idx = MFI.getObjectIndexBegin(), EndIdx = MFI.getObjectIndexEnd();
188 Idx != EndIdx; ++Idx) {
189 if (MFI.isDeadObjectIndex(Idx))
190 continue;
191 SlotInfo.emplace_back(MFI, ValOffset, Idx);
192 }
193
194 // sort the ordering, to match the actual layout in memory
195 llvm::sort(SlotInfo);
196
197 SlotDbgMap SlotMap = genSlotDbgMapping(MF);
198
199 for (const SlotData &Info : SlotInfo) {
200 emitStackSlotRemark(MF, Info, Rem);
201 for (const DILocalVariable *N : SlotMap[Info.Slot])
202 emitSourceLocRemark(MF, N, Rem);
203 }
204 }
205
206 // We need to generate a mapping of slots to the values that are stored to
207 // them. This information is lost by the time we need to print out the frame,
208 // so we reconstruct it here by walking the CFG, and generating the mapping.
209 SlotDbgMap genSlotDbgMapping(MachineFunction &MF) {
210 SlotDbgMap SlotDebugMap;
211
212 // add variables to the map
215 SlotDebugMap[DI.getStackSlot()].insert(DI.Var);
216
217 // Then add all the spills that have debug data
218 for (MachineBasicBlock &MBB : MF) {
219 for (MachineInstr &MI : MBB) {
220 for (MachineMemOperand *MO : MI.memoperands()) {
221 if (!MO->isStore())
222 continue;
223 auto *FI = dyn_cast_or_null<FixedStackPseudoSourceValue>(
224 MO->getPseudoValue());
225 if (!FI)
226 continue;
227 int FrameIdx = FI->getFrameIndex();
229 MI.collectDebugValues(Dbg);
230
231 for (MachineInstr *MI : Dbg)
232 SlotDebugMap[FrameIdx].insert(MI->getDebugVariable());
233 }
234 }
235 }
236
237 return SlotDebugMap;
238 }
239};
240
241char StackFrameLayoutAnalysisPass::ID = 0;
242} // namespace
243
244char &llvm::StackFrameLayoutAnalysisPassID = StackFrameLayoutAnalysisPass::ID;
245INITIALIZE_PASS(StackFrameLayoutAnalysisPass, "stack-frame-layout",
246 "Stack Frame Layout", false, false)
247
248namespace llvm {
249/// Returns a newly-created StackFrameLayout pass.
251 return new StackFrameLayoutAnalysisPass();
252}
253
254} // namespace llvm
MachineBasicBlock & MBB
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
Analysis containing CSE Info
Definition: CSEInfo.cpp:27
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
#define LLVM_DEBUG(X)
Definition: Debug.h:101
IRTranslator LLVM IR MI
static std::string getTypeString(Type *T)
Definition: LLParser.cpp:67
===- MachineOptimizationRemarkEmitter.h - Opt Diagnostics -*- C++ -*-—===//
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
Definition: PassSupport.h:38
This file implements a set that has insertion order iteration characteristics.
#define DEBUG_TYPE
Represent the analysis usage information of a pass.
AnalysisUsage & addRequired()
void setPreservesAll()
Set by analyses that do not transform their input at all.
DISubprogram * getSubprogram() const
Get the attached subprogram.
Definition: Metadata.cpp:1831
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function.
Definition: Function.cpp:350
This is an important class for using LLVM in a threaded context.
Definition: LLVMContext.h:67
const DiagnosticHandler * getDiagHandlerPtr() const
getDiagHandlerPtr - Returns const raw pointer of DiagnosticHandler set by setDiagnosticHandler.
The MachineFrameInfo class represents an abstract stack frame until prolog/epilog code is inserted.
int getStackProtectorIndex() const
Return the index for the stack protector object.
Align getObjectAlign(int ObjectIdx) const
Return the alignment of the specified stack object.
bool isSpillSlotObjectIndex(int ObjectIdx) const
Returns true if the specified index corresponds to a spill slot.
int64_t getObjectSize(int ObjectIdx) const
Return the size of the specified object.
unsigned getNumObjects() const
Return the number of objects.
int getObjectIndexEnd() const
Return one past the maximum frame object index.
bool hasStackObjects() const
Return true if there are any stack objects in this function.
int64_t getObjectOffset(int ObjectIdx) const
Return the assigned stack offset of the specified object from the incoming stack pointer.
int getObjectIndexBegin() const
Return the minimum frame object index.
bool isDeadObjectIndex(int ObjectIdx) const
Returns true if the specified index corresponds to a dead object.
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
virtual bool runOnMachineFunction(MachineFunction &MF)=0
runOnMachineFunction - This method must be overloaded to perform the desired machine code transformat...
Description of the location of a variable whose Address is valid and unchanging during function execu...
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
StringRef getName() const
getName - Return the name of the corresponding LLVM function.
MachineFrameInfo & getFrameInfo()
getFrameInfo - Return the frame info object for the current function.
auto getInStackSlotVariableDbgInfo()
Returns the collection of variables for which we have debug info and that have been assigned a stack ...
Function & getFunction()
Return the LLVM function that this machine code represents.
const MachineBasicBlock & front() const
Representation of each machine instruction.
Definition: MachineInstr.h:69
A description of a memory reference used in the backend.
Diagnostic information for optimization analysis remarks.
virtual StringRef getPassName() const
getPassName - Return a nice clean name for a pass.
Definition: Pass.cpp:81
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1209
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:50
Information about stack frame layout on the target.
int getOffsetOfLocalArea() const
getOffsetOfLocalArea - This method returns the offset of the local area from the stack pointer on ent...
virtual const TargetFrameLowering * getFrameLowering() const
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Definition: CallingConv.h:24
DiagnosticInfoOptimizationBase::Argument NV
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
bool operator<(int64_t V1, const APSInt &V2)
Definition: APSInt.h:361
auto formatv(const char *Fmt, Ts &&... Vals) -> formatv_object< decltype(std::make_tuple(detail::build_format_adapter(std::forward< Ts >(Vals))...))>
MachineFunctionPass * createStackFrameLayoutAnalysisPass()
StackFramePrinter pass - This pass prints out the machine function's stack frame to the given stream ...
void sort(IteratorTy Start, IteratorTy End)
Definition: STLExtras.h:1656
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:163
bool isFunctionInPrintList(StringRef FunctionName)
char & StackFrameLayoutAnalysisPassID
StackFramePrinter - This pass prints the stack frame layout and variable mappings.
#define N
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition: Alignment.h:39
uint64_t value() const
This is a hole in the type system and should not be abused.
Definition: Alignment.h:85
virtual bool isAnalysisRemarkEnabled(StringRef PassName) const
Return true if analysis remarks are enabled, override to provide different implementation.