Movatterモバイル変換


[0]ホーム

URL:


LLVM 20.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"
20#include "llvm/Analysis/OptimizationRemarkEmitter.h"
21#include "llvm/CodeGen/MachineFrameInfo.h"
22#include "llvm/CodeGen/MachineFunction.h"
23#include "llvm/CodeGen/MachineFunctionPass.h"
24#include "llvm/CodeGen/MachineOptimizationRemarkEmitter.h"
25#include "llvm/CodeGen/Passes.h"
26#include "llvm/CodeGen/SlotIndexes.h"
27#include "llvm/CodeGen/StackProtector.h"
28#include "llvm/CodeGen/TargetFrameLowering.h"
29#include "llvm/CodeGen/TargetSubtargetInfo.h"
30#include "llvm/IR/DebugInfoMetadata.h"
31#include "llvm/IR/PrintPasses.h"
32#include "llvm/InitializePasses.h"
33#include "llvm/Support/Debug.h"
34#include "llvm/Support/FormatVariadic.h"
35#include "llvm/Support/raw_ostream.h"
36
37using namespacellvm;
38
39#define DEBUG_TYPE "stack-frame-layout"
40
41namespace{
42
43/// StackFrameLayoutAnalysisPass - This is a pass to dump the stack frame of a
44/// MachineFunction.
45///
46structStackFrameLayoutAnalysisPass :publicMachineFunctionPass {
47usingSlotDbgMap =SmallDenseMap<int, SetVector<const DILocalVariable *>>;
48staticcharID;
49
50enum SlotType {
51 Spill,// a Spill slot
52Fixed,// a Fixed slot (e.g. arguments passed on the stack)
53 VariableSized,// a variable sized object
54StackProtector,// Stack Protector slot
55 Variable,// a slot used to store a local data (could be a tmp)
56Invalid// It's an error for a slot to have this type
57 };
58
59structSlotData {
60int Slot;
61int Size;
62intAlign;
63StackOffset Offset;
64 SlotType SlotTy;
65bool Scalable;
66
67 SlotData(constMachineFrameInfo &MFI,constStackOffset Offset,
68constintIdx)
69 : Slot(Idx), Size(MFI.getObjectSize(Idx)),
70Align(MFI.getObjectAlign(Idx).value()), Offset(Offset),
71 SlotTy(Invalid), Scalable(false) {
72 Scalable = MFI.getStackID(Idx) ==TargetStackID::ScalableVector;
73if (MFI.isSpillSlotObjectIndex(Idx))
74 SlotTy = SlotType::Spill;
75elseif (MFI.isFixedObjectIndex(Idx))
76 SlotTy = SlotType::Fixed;
77elseif (MFI.isVariableSizedObjectIndex(Idx))
78 SlotTy = SlotType::VariableSized;
79elseif (MFI.hasStackProtectorIndex() &&
80Idx == MFI.getStackProtectorIndex())
81 SlotTy = SlotType::StackProtector;
82else
83 SlotTy = SlotType::Variable;
84 }
85
86bool isVarSize() const{return SlotTy == SlotType::VariableSized; }
87
88// We use this to sort in reverse order, so that the layout is displayed
89// correctly. Variable sized slots are sorted to the end of the list, as
90// offsets are currently incorrect for these but they reside at the end of
91// the stack frame. The Slot index is used to ensure deterministic order
92// when offsets are equal.
93booloperator<(const SlotData &Rhs) const{
94return std::make_tuple(!isVarSize(),
95 Offset.getFixed() + Offset.getScalable(), Slot) >
96 std::make_tuple(!Rhs.isVarSize(),
97 Rhs.Offset.getFixed() + Rhs.Offset.getScalable(),
98 Rhs.Slot);
99 }
100 };
101
102 StackFrameLayoutAnalysisPass() :MachineFunctionPass(ID) {}
103
104StringRefgetPassName() const override{
105return"Stack Frame Layout Analysis";
106 }
107
108voidgetAnalysisUsage(AnalysisUsage &AU) const override{
109 AU.setPreservesAll();
110MachineFunctionPass::getAnalysisUsage(AU);
111 AU.addRequired<MachineOptimizationRemarkEmitterPass>();
112 }
113
114boolrunOnMachineFunction(MachineFunction &MF) override{
115// TODO: We should implement a similar filter for remarks:
116// -Rpass-func-filter=<regex>
117if (!isFunctionInPrintList(MF.getName()))
118returnfalse;
119
120LLVMContext &Ctx = MF.getFunction().getContext();
121if (!Ctx.getDiagHandlerPtr()->isAnalysisRemarkEnabled(DEBUG_TYPE))
122returnfalse;
123
124MachineOptimizationRemarkAnalysis Rem(DEBUG_TYPE,"StackLayout",
125 MF.getFunction().getSubprogram(),
126 &MF.front());
127 Rem << ("\nFunction: " + MF.getName()).str();
128 emitStackFrameLayoutRemarks(MF, Rem);
129 getAnalysis<MachineOptimizationRemarkEmitterPass>().getORE().emit(Rem);
130returnfalse;
131 }
132
133 std::stringgetTypeString(SlotType Ty) {
134switch (Ty) {
135case SlotType::Spill:
136return"Spill";
137case SlotType::Fixed:
138return"Fixed";
139case SlotType::VariableSized:
140return"VariableSized";
141case SlotType::StackProtector:
142return"Protector";
143case SlotType::Variable:
144return"Variable";
145default:
146llvm_unreachable("bad slot type for stack layout");
147 }
148 }
149
150void emitStackSlotRemark(constMachineFunction &MF,const SlotData &D,
151MachineOptimizationRemarkAnalysis &Rem) {
152// To make it easy to understand the stack layout from the CLI, we want to
153// print each slot like the following:
154//
155// Offset: [SP+8], Type: Spill, Align: 8, Size: 16
156// foo @ /path/to/file.c:25
157// bar @ /path/to/file.c:35
158//
159// Which prints the size, alignment, and offset from the SP at function
160// entry.
161//
162// But we also want the machine readable remarks data to be nicely
163// organized. So we print some additional data as strings for the CLI
164// output, but maintain more structured data for the YAML.
165//
166// For example we store the Offset in YAML as:
167// ...
168// - Offset: -8
169// - ScalableOffset: -16
170// Note: the ScalableOffset entries are added only for slots with non-zero
171// scalable offsets.
172//
173// But we print it to the CLI as:
174// Offset: [SP-8]
175//
176// Or with non-zero scalable offset:
177// Offset: [SP-8-16 x vscale]
178
179// Negative offsets will print a leading `-`, so only add `+`
180 std::string Prefix =
181formatv("\nOffset: [SP{0}", (D.Offset.getFixed() < 0) ?"" :"+").str();
182 Rem << Prefix <<ore::NV("Offset",D.Offset.getFixed());
183
184if (D.Offset.getScalable()) {
185 Rem << ((D.Offset.getScalable() < 0) ?"" :"+")
186 <<ore::NV("ScalableOffset",D.Offset.getScalable()) <<" x vscale";
187 }
188
189 Rem <<"], Type: " <<ore::NV("Type",getTypeString(D.SlotTy))
190 <<", Align: " <<ore::NV("Align",D.Align)
191 <<", Size: " <<ore::NV("Size",ElementCount::get(D.Size,D.Scalable));
192 }
193
194void emitSourceLocRemark(constMachineFunction &MF,constDILocalVariable *N,
195MachineOptimizationRemarkAnalysis &Rem) {
196 std::string Loc =
197formatv("{0} @ {1}:{2}",N->getName(),N->getFilename(),N->getLine())
198 .str();
199 Rem <<"\n " <<ore::NV("DataLoc", Loc);
200 }
201
202StackOffsetgetStackOffset(constMachineFunction &MF,
203constMachineFrameInfo &MFI,
204constTargetFrameLowering *FI,int FrameIdx) {
205if (!FI)
206returnStackOffset::getFixed(MFI.getObjectOffset(FrameIdx));
207
208return FI->getFrameIndexReferenceFromSP(MF, FrameIdx);
209 }
210
211void emitStackFrameLayoutRemarks(MachineFunction &MF,
212MachineOptimizationRemarkAnalysis &Rem) {
213constMachineFrameInfo &MFI = MF.getFrameInfo();
214if (!MFI.hasStackObjects())
215return;
216
217constTargetFrameLowering *FI = MF.getSubtarget().getFrameLowering();
218
219LLVM_DEBUG(dbgs() <<"getStackProtectorIndex =="
220 << MFI.getStackProtectorIndex() <<"\n");
221
222 std::vector<SlotData> SlotInfo;
223
224constunsignedint NumObj = MFI.getNumObjects();
225 SlotInfo.reserve(NumObj);
226// initialize slot info
227for (intIdx = MFI.getObjectIndexBegin(), EndIdx = MFI.getObjectIndexEnd();
228Idx != EndIdx; ++Idx) {
229if (MFI.isDeadObjectIndex(Idx))
230continue;
231 SlotInfo.emplace_back(MFI,getStackOffset(MF, MFI, FI,Idx),Idx);
232 }
233
234// sort the ordering, to match the actual layout in memory
235llvm::sort(SlotInfo);
236
237 SlotDbgMap SlotMap = genSlotDbgMapping(MF);
238
239for (const SlotData &Info : SlotInfo) {
240 emitStackSlotRemark(MF,Info, Rem);
241for (constDILocalVariable *N : SlotMap[Info.Slot])
242 emitSourceLocRemark(MF,N, Rem);
243 }
244 }
245
246// We need to generate a mapping of slots to the values that are stored to
247// them. This information is lost by the time we need to print out the frame,
248// so we reconstruct it here by walking the CFG, and generating the mapping.
249 SlotDbgMap genSlotDbgMapping(MachineFunction &MF) {
250 SlotDbgMap SlotDebugMap;
251
252// add variables to the map
253for (MachineFunction::VariableDbgInfo &DI :
254 MF.getInStackSlotVariableDbgInfo())
255 SlotDebugMap[DI.getStackSlot()].insert(DI.Var);
256
257// Then add all the spills that have debug data
258for (MachineBasicBlock &MBB : MF) {
259for (MachineInstr &MI :MBB) {
260for (MachineMemOperand *MO :MI.memoperands()) {
261if (!MO->isStore())
262continue;
263auto *FI = dyn_cast_or_null<FixedStackPseudoSourceValue>(
264 MO->getPseudoValue());
265if (!FI)
266continue;
267int FrameIdx = FI->getFrameIndex();
268SmallVector<MachineInstr *> Dbg;
269MI.collectDebugValues(Dbg);
270
271for (MachineInstr *MI : Dbg)
272 SlotDebugMap[FrameIdx].insert(MI->getDebugVariable());
273 }
274 }
275 }
276
277return SlotDebugMap;
278 }
279};
280
281char StackFrameLayoutAnalysisPass::ID = 0;
282}// namespace
283
284char &llvm::StackFrameLayoutAnalysisPassID = StackFrameLayoutAnalysisPass::ID;
285INITIALIZE_PASS(StackFrameLayoutAnalysisPass,"stack-frame-layout",
286"Stack Frame Layout",false,false)
287
288namespacellvm {
289/// Returns a newly-created StackFrameLayout pass.
290MachineFunctionPass *createStackFrameLayoutAnalysisPass() {
291returnnew StackFrameLayoutAnalysisPass();
292}
293
294}// namespace llvm
getStackOffset
static StackOffset getStackOffset(const MachineFunction &MF, int64_t ObjectOffset)
Definition:AArch64FrameLowering.cpp:2694
MBB
MachineBasicBlock & MBB
Definition:ARMSLSHardening.cpp:71
D
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
Info
Analysis containing CSE Info
Definition:CSEInfo.cpp:27
Passes.h
Idx
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
Definition:DeadArgumentElimination.cpp:353
DebugInfoMetadata.h
Debug.h
LLVM_DEBUG
#define LLVM_DEBUG(...)
Definition:Debug.h:106
FormatVariadic.h
MI
IRTranslator LLVM IR MI
Definition:IRTranslator.cpp:112
InitializePasses.h
getTypeString
static std::string getTypeString(Type *T)
Definition:LLParser.cpp:71
MachineFrameInfo.h
MachineFunctionPass.h
MachineFunction.h
MachineOptimizationRemarkEmitter.h
===- MachineOptimizationRemarkEmitter.h - Opt Diagnostics -*- C++ -*-—===//
OptimizationRemarkEmitter.h
INITIALIZE_PASS
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
Definition:PassSupport.h:38
PrintPasses.h
SetVector.h
This file implements a set that has insertion order iteration characteristics.
SlotIndexes.h
DEBUG_TYPE
#define DEBUG_TYPE
Definition:StackFrameLayoutAnalysisPass.cpp:39
StackProtector.h
TargetFrameLowering.h
TargetSubtargetInfo.h
llvm::AnalysisUsage
Represent the analysis usage information of a pass.
Definition:PassAnalysisSupport.h:47
llvm::AnalysisUsage::addRequired
AnalysisUsage & addRequired()
Definition:PassAnalysisSupport.h:75
llvm::AnalysisUsage::setPreservesAll
void setPreservesAll()
Set by analyses that do not transform their input at all.
Definition:PassAnalysisSupport.h:130
llvm::DILocalVariable
Local variable.
Definition:DebugInfoMetadata.h:3460
llvm::ElementCount::get
static constexpr ElementCount get(ScalarTy MinVal, bool Scalable)
Definition:TypeSize.h:317
llvm::Function::getSubprogram
DISubprogram * getSubprogram() const
Get the attached subprogram.
Definition:Metadata.cpp:1874
llvm::Function::getContext
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function.
Definition:Function.cpp:369
llvm::LLVMContext
This is an important class for using LLVM in a threaded context.
Definition:LLVMContext.h:67
llvm::LLVMContext::getDiagHandlerPtr
const DiagnosticHandler * getDiagHandlerPtr() const
getDiagHandlerPtr - Returns const raw pointer of DiagnosticHandler set by setDiagnosticHandler.
Definition:LLVMContext.cpp:357
llvm::MachineBasicBlock
Definition:MachineBasicBlock.h:125
llvm::MachineFrameInfo
The MachineFrameInfo class represents an abstract stack frame until prolog/epilog code is inserted.
Definition:MachineFrameInfo.h:106
llvm::MachineFrameInfo::getStackProtectorIndex
int getStackProtectorIndex() const
Return the index for the stack protector object.
Definition:MachineFrameInfo.h:360
llvm::MachineFrameInfo::getObjectAlign
Align getObjectAlign(int ObjectIdx) const
Return the alignment of the specified stack object.
Definition:MachineFrameInfo.h:486
llvm::MachineFrameInfo::isSpillSlotObjectIndex
bool isSpillSlotObjectIndex(int ObjectIdx) const
Returns true if the specified index corresponds to a spill slot.
Definition:MachineFrameInfo.h:737
llvm::MachineFrameInfo::getObjectSize
int64_t getObjectSize(int ObjectIdx) const
Return the size of the specified object.
Definition:MachineFrameInfo.h:472
llvm::MachineFrameInfo::getNumObjects
unsigned getNumObjects() const
Return the number of objects.
Definition:MachineFrameInfo.h:418
llvm::MachineFrameInfo::isVariableSizedObjectIndex
bool isVariableSizedObjectIndex(int ObjectIdx) const
Returns true if the specified index corresponds to a variable sized object.
Definition:MachineFrameInfo.h:772
llvm::MachineFrameInfo::getObjectIndexEnd
int getObjectIndexEnd() const
Return one past the maximum frame object index.
Definition:MachineFrameInfo.h:412
llvm::MachineFrameInfo::hasStackProtectorIndex
bool hasStackProtectorIndex() const
Definition:MachineFrameInfo.h:362
llvm::MachineFrameInfo::hasStackObjects
bool hasStackObjects() const
Return true if there are any stack objects in this function.
Definition:MachineFrameInfo.h:352
llvm::MachineFrameInfo::getStackID
uint8_t getStackID(int ObjectIdx) const
Definition:MachineFrameInfo.h:750
llvm::MachineFrameInfo::getObjectOffset
int64_t getObjectOffset(int ObjectIdx) const
Return the assigned stack offset of the specified object from the incoming stack pointer.
Definition:MachineFrameInfo.h:528
llvm::MachineFrameInfo::isFixedObjectIndex
bool isFixedObjectIndex(int ObjectIdx) const
Returns true if the specified index corresponds to a fixed stack object.
Definition:MachineFrameInfo.h:700
llvm::MachineFrameInfo::getObjectIndexBegin
int getObjectIndexBegin() const
Return the minimum frame object index.
Definition:MachineFrameInfo.h:409
llvm::MachineFrameInfo::isDeadObjectIndex
bool isDeadObjectIndex(int ObjectIdx) const
Returns true if the specified index corresponds to a dead object.
Definition:MachineFrameInfo.h:764
llvm::MachineFunctionPass
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
Definition:MachineFunctionPass.h:30
llvm::MachineFunctionPass::getAnalysisUsage
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
Definition:MachineFunctionPass.cpp:169
llvm::MachineFunctionPass::runOnMachineFunction
virtual bool runOnMachineFunction(MachineFunction &MF)=0
runOnMachineFunction - This method must be overloaded to perform the desired machine code transformat...
llvm::MachineFunction::VariableDbgInfo
Description of the location of a variable whose Address is valid and unchanging during function execu...
Definition:MachineFunction.h:427
llvm::MachineFunction
Definition:MachineFunction.h:267
llvm::MachineFunction::getSubtarget
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
Definition:MachineFunction.h:733
llvm::MachineFunction::getName
StringRef getName() const
getName - Return the name of the corresponding LLVM function.
Definition:MachineFunction.cpp:645
llvm::MachineFunction::getFrameInfo
MachineFrameInfo & getFrameInfo()
getFrameInfo - Return the frame info object for the current function.
Definition:MachineFunction.h:749
llvm::MachineFunction::getInStackSlotVariableDbgInfo
auto getInStackSlotVariableDbgInfo()
Returns the collection of variables for which we have debug info and that have been assigned a stack ...
Definition:MachineFunction.h:1374
llvm::MachineFunction::getFunction
Function & getFunction()
Return the LLVM function that this machine code represents.
Definition:MachineFunction.h:704
llvm::MachineFunction::front
const MachineBasicBlock & front() const
Definition:MachineFunction.h:959
llvm::MachineInstr
Representation of each machine instruction.
Definition:MachineInstr.h:71
llvm::MachineMemOperand
A description of a memory reference used in the backend.
Definition:MachineMemOperand.h:129
llvm::MachineOptimizationRemarkAnalysis
Diagnostic information for optimization analysis remarks.
Definition:MachineOptimizationRemarkEmitter.h:111
llvm::MachineOptimizationRemarkEmitterPass
The analysis pass.
Definition:MachineOptimizationRemarkEmitter.h:239
llvm::Pass::getPassName
virtual StringRef getPassName() const
getPassName - Return a nice clean name for a pass.
Definition:Pass.cpp:81
llvm::SmallDenseMap
Definition:DenseMap.h:883
llvm::SmallVector
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition:SmallVector.h:1196
llvm::StackOffset
StackOffset holds a fixed and a scalable offset in bytes.
Definition:TypeSize.h:33
llvm::StackOffset::getFixed
int64_t getFixed() const
Returns the fixed component of the stack.
Definition:TypeSize.h:49
llvm::StackProtector
Definition:StackProtector.h:93
llvm::StringRef
StringRef - Represent a constant reference to a string, i.e.
Definition:StringRef.h:51
llvm::TargetFrameLowering
Information about stack frame layout on the target.
Definition:TargetFrameLowering.h:45
llvm::TargetFrameLowering::getFrameIndexReferenceFromSP
virtual StackOffset getFrameIndexReferenceFromSP(const MachineFunction &MF, int FI) const
getFrameIndexReferenceFromSP - This method returns the offset from the stack pointer to the slot of t...
Definition:TargetFrameLoweringImpl.cpp:69
llvm::TargetSubtargetInfo::getFrameLowering
virtual const TargetFrameLowering * getFrameLowering() const
Definition:TargetSubtargetInfo.h:98
unsigned
llvm_unreachable
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
Definition:ErrorHandling.h:143
llvm::CallingConv::ID
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Definition:CallingConv.h:24
llvm::TargetStackID::ScalableVector
@ ScalableVector
Definition:TargetFrameLowering.h:32
llvm::ore::NV
DiagnosticInfoOptimizationBase::Argument NV
Definition:OptimizationRemarkEmitter.h:135
llvm
This is an optimization pass for GlobalISel generic memory operations.
Definition:AddressRanges.h:18
llvm::operator<
bool operator<(int64_t V1, const APSInt &V2)
Definition:APSInt.h:361
llvm::FloatStyle::Fixed
@ Fixed
llvm::createStackFrameLayoutAnalysisPass
MachineFunctionPass * createStackFrameLayoutAnalysisPass()
StackFramePrinter pass - This pass prints out the machine function's stack frame to the given stream ...
llvm::formatv
auto formatv(bool Validate, const char *Fmt, Ts &&...Vals)
Definition:FormatVariadic.h:252
llvm::sort
void sort(IteratorTy Start, IteratorTy End)
Definition:STLExtras.h:1664
llvm::dbgs
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition:Debug.cpp:163
llvm::isFunctionInPrintList
bool isFunctionInPrintList(StringRef FunctionName)
Definition:PrintPasses.cpp:160
llvm::StackFrameLayoutAnalysisPassID
char & StackFrameLayoutAnalysisPassID
StackFramePrinter - This pass prints the stack frame layout and variable mappings.
Definition:StackFrameLayoutAnalysisPass.cpp:284
llvm::Invalid
@ Invalid
Definition:PGOCtxProfWriter.h:22
raw_ostream.h
N
#define N
llvm::Align
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition:Alignment.h:39
llvm::Align::value
uint64_t value() const
This is a hole in the type system and should not be abused.
Definition:Alignment.h:85
llvm::DiagnosticHandler::isAnalysisRemarkEnabled
virtual bool isAnalysisRemarkEnabled(StringRef PassName) const
Return true if analysis remarks are enabled, override to provide different implementation.
Definition:DiagnosticHandler.cpp:71

Generated on Fri Jul 18 2025 11:03:18 for LLVM by doxygen 1.9.6
[8]ページ先頭

©2009-2025 Movatter.jp