LLVM 19.0.0git
DebugHandlerBase.cpp
Go to the documentation of this file.
1//===-- llvm/lib/CodeGen/AsmPrinter/DebugHandlerBase.cpp -------*- C++ -*--===//
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//
9// Common functionality for different debug information format backends.
10// LLVM currently supports DWARF and CodeView.
11//
12//===----------------------------------------------------------------------===//
13
20#include "llvm/IR/DebugInfo.h"
21#include "llvm/MC/MCStreamer.h"
23
24using namespace llvm;
25
26#define DEBUG_TYPE "dwarfdebug"
27
28/// If true, we drop variable location ranges which exist entirely outside the
29/// variable's lexical scope instruction ranges.
30static cl::opt<bool> TrimVarLocs("trim-var-locs", cl::Hidden, cl::init(true));
31
32std::optional<DbgVariableLocation>
35 DbgVariableLocation Location;
36 // Variables calculated from multiple locations can't be represented here.
37 if (Instruction.getNumDebugOperands() != 1)
38 return std::nullopt;
39 if (!Instruction.getDebugOperand(0).isReg())
40 return std::nullopt;
41 Location.Register = Instruction.getDebugOperand(0).getReg();
42 Location.FragmentInfo.reset();
43 // We only handle expressions generated by DIExpression::appendOffset,
44 // which doesn't require a full stack machine.
45 int64_t Offset = 0;
46 const DIExpression *DIExpr = Instruction.getDebugExpression();
47 auto Op = DIExpr->expr_op_begin();
48 // We can handle a DBG_VALUE_LIST iff it has exactly one location operand that
49 // appears exactly once at the start of the expression.
50 if (Instruction.isDebugValueList()) {
51 if (Instruction.getNumDebugOperands() == 1 &&
52 Op->getOp() == dwarf::DW_OP_LLVM_arg)
53 ++Op;
54 else
55 return std::nullopt;
56 }
57 while (Op != DIExpr->expr_op_end()) {
58 switch (Op->getOp()) {
59 case dwarf::DW_OP_constu: {
60 int Value = Op->getArg(0);
61 ++Op;
62 if (Op != DIExpr->expr_op_end()) {
63 switch (Op->getOp()) {
64 case dwarf::DW_OP_minus:
65 Offset -= Value;
66 break;
67 case dwarf::DW_OP_plus:
68 Offset += Value;
69 break;
70 default:
71 continue;
72 }
73 }
74 } break;
75 case dwarf::DW_OP_plus_uconst:
76 Offset += Op->getArg(0);
77 break;
79 Location.FragmentInfo = {Op->getArg(1), Op->getArg(0)};
80 break;
81 case dwarf::DW_OP_deref:
82 Location.LoadChain.push_back(Offset);
83 Offset = 0;
84 break;
85 default:
86 return std::nullopt;
87 }
88 ++Op;
89 }
90
91 // Do one final implicit DW_OP_deref if this was an indirect DBG_VALUE
92 // instruction.
93 // FIXME: Replace these with DIExpression.
94 if (Instruction.isIndirectDebugValue())
95 Location.LoadChain.push_back(Offset);
96
97 return Location;
98}
99
101
103 if (M->debug_compile_units().empty())
104 Asm = nullptr;
105}
106
107// Each LexicalScope has first instruction and last instruction to mark
108// beginning and end of a scope respectively. Create an inverse map that list
109// scopes starts (and ends) with an instruction. One instruction may start (or
110// end) multiple scopes. Ignore scopes that are not reachable.
114 while (!WorkList.empty()) {
115 LexicalScope *S = WorkList.pop_back_val();
116
117 const SmallVectorImpl<LexicalScope *> &Children = S->getChildren();
118 if (!Children.empty())
119 WorkList.append(Children.begin(), Children.end());
120
121 if (S->isAbstractScope())
122 continue;
123
124 for (const InsnRange &R : S->getRanges()) {
125 assert(R.first && "InsnRange does not have first instruction!");
126 assert(R.second && "InsnRange does not have second instruction!");
127 requestLabelBeforeInsn(R.first);
128 requestLabelAfterInsn(R.second);
129 }
130 }
131}
132
133// Return Label preceding the instruction.
135 MCSymbol *Label = LabelsBeforeInsn.lookup(MI);
136 assert(Label && "Didn't insert label before instruction");
137 return Label;
138}
139
140// Return Label immediately following the instruction.
142 return LabelsAfterInsn.lookup(MI);
143}
144
145/// If this type is derived from a base type then return base type size.
147 assert(Ty);
148 const DIDerivedType *DDTy = dyn_cast<DIDerivedType>(Ty);
149 if (!DDTy)
150 return Ty->getSizeInBits();
151
152 unsigned Tag = DDTy->getTag();
153
154 if (Tag != dwarf::DW_TAG_member && Tag != dwarf::DW_TAG_typedef &&
155 Tag != dwarf::DW_TAG_const_type && Tag != dwarf::DW_TAG_volatile_type &&
156 Tag != dwarf::DW_TAG_restrict_type && Tag != dwarf::DW_TAG_atomic_type &&
157 Tag != dwarf::DW_TAG_immutable_type)
158 return DDTy->getSizeInBits();
159
160 DIType *BaseType = DDTy->getBaseType();
161
162 if (!BaseType)
163 return 0;
164
165 // If this is a derived type, go ahead and get the base type, unless it's a
166 // reference then it's just the size of the field. Pointer types have no need
167 // of this since they're a different type of qualification on the type.
168 if (BaseType->getTag() == dwarf::DW_TAG_reference_type ||
169 BaseType->getTag() == dwarf::DW_TAG_rvalue_reference_type)
170 return Ty->getSizeInBits();
171
173}
174
176 if (isa<DIStringType>(Ty)) {
177 // Some transformations (e.g. instcombine) may decide to turn a Fortran
178 // character object into an integer, and later ones (e.g. SROA) may
179 // further inject a constant integer in a llvm.dbg.value call to track
180 // the object's value. Here we trust the transformations are doing the
181 // right thing, and treat the constant as unsigned to preserve that value
182 // (i.e. avoid sign extension).
183 return true;
184 }
185
186 if (auto *CTy = dyn_cast<DICompositeType>(Ty)) {
187 if (CTy->getTag() == dwarf::DW_TAG_enumeration_type) {
188 if (!(Ty = CTy->getBaseType()))
189 // FIXME: Enums without a fixed underlying type have unknown signedness
190 // here, leading to incorrectly emitted constants.
191 return false;
192 } else
193 // (Pieces of) aggregate types that get hacked apart by SROA may be
194 // represented by a constant. Encode them as unsigned bytes.
195 return true;
196 }
197
198 if (auto *DTy = dyn_cast<DIDerivedType>(Ty)) {
199 dwarf::Tag T = (dwarf::Tag)Ty->getTag();
200 // Encode pointer constants as unsigned bytes. This is used at least for
201 // null pointer constant emission.
202 // FIXME: reference and rvalue_reference /probably/ shouldn't be allowed
203 // here, but accept them for now due to a bug in SROA producing bogus
204 // dbg.values.
205 if (T == dwarf::DW_TAG_pointer_type ||
206 T == dwarf::DW_TAG_ptr_to_member_type ||
207 T == dwarf::DW_TAG_reference_type ||
208 T == dwarf::DW_TAG_rvalue_reference_type)
209 return true;
210 assert(T == dwarf::DW_TAG_typedef || T == dwarf::DW_TAG_const_type ||
211 T == dwarf::DW_TAG_volatile_type ||
212 T == dwarf::DW_TAG_restrict_type || T == dwarf::DW_TAG_atomic_type ||
213 T == dwarf::DW_TAG_immutable_type);
214 assert(DTy->getBaseType() && "Expected valid base type");
215 return isUnsignedDIType(DTy->getBaseType());
216 }
217
218 auto *BTy = cast<DIBasicType>(Ty);
219 unsigned Encoding = BTy->getEncoding();
220 assert((Encoding == dwarf::DW_ATE_unsigned ||
221 Encoding == dwarf::DW_ATE_unsigned_char ||
222 Encoding == dwarf::DW_ATE_signed ||
223 Encoding == dwarf::DW_ATE_signed_char ||
224 Encoding == dwarf::DW_ATE_float || Encoding == dwarf::DW_ATE_UTF ||
225 Encoding == dwarf::DW_ATE_boolean ||
226 Encoding == dwarf::DW_ATE_complex_float ||
227 Encoding == dwarf::DW_ATE_signed_fixed ||
228 Encoding == dwarf::DW_ATE_unsigned_fixed ||
229 (Ty->getTag() == dwarf::DW_TAG_unspecified_type &&
230 Ty->getName() == "decltype(nullptr)")) &&
231 "Unsupported encoding");
232 return Encoding == dwarf::DW_ATE_unsigned ||
233 Encoding == dwarf::DW_ATE_unsigned_char ||
234 Encoding == dwarf::DW_ATE_UTF || Encoding == dwarf::DW_ATE_boolean ||
235 Encoding == llvm::dwarf::DW_ATE_unsigned_fixed ||
236 Ty->getTag() == dwarf::DW_TAG_unspecified_type;
237}
238
239static bool hasDebugInfo(const MachineModuleInfo *MMI,
240 const MachineFunction *MF) {
241 if (!MMI->hasDebugInfo())
242 return false;
243 auto *SP = MF->getFunction().getSubprogram();
244 if (!SP)
245 return false;
246 assert(SP->getUnit());
247 auto EK = SP->getUnit()->getEmissionKind();
248 if (EK == DICompileUnit::NoDebug)
249 return false;
250 return true;
251}
252
254 PrevInstBB = nullptr;
255
256 if (!Asm || !hasDebugInfo(MMI, MF)) {
258 return;
259 }
260
261 // Grab the lexical scopes for the function, if we don't have any of those
262 // then we're not going to be able to do anything.
263 LScopes.initialize(*MF);
264 if (LScopes.empty()) {
266 return;
267 }
268
269 // Make sure that each lexical scope will have a begin/end label.
271
272 // Calculate history for local variables.
273 assert(DbgValues.empty() && "DbgValues map wasn't cleaned!");
274 assert(DbgLabels.empty() && "DbgLabels map wasn't cleaned!");
277 InstOrdering.initialize(*MF);
278 if (TrimVarLocs)
279 DbgValues.trimLocationRanges(*MF, LScopes, InstOrdering);
281
282 // Request labels for the full history.
283 for (const auto &I : DbgValues) {
284 const auto &Entries = I.second;
285 if (Entries.empty())
286 continue;
287
288 auto IsDescribedByReg = [](const MachineInstr *MI) {
289 return any_of(MI->debug_operands(),
290 [](auto &MO) { return MO.isReg() && MO.getReg(); });
291 };
292
293 // The first mention of a function argument gets the CurrentFnBegin label,
294 // so arguments are visible when breaking at function entry.
295 //
296 // We do not change the label for values that are described by registers,
297 // as that could place them above their defining instructions. We should
298 // ideally not change the labels for constant debug values either, since
299 // doing that violates the ranges that are calculated in the history map.
300 // However, we currently do not emit debug values for constant arguments
301 // directly at the start of the function, so this code is still useful.
302 const DILocalVariable *DIVar =
303 Entries.front().getInstr()->getDebugVariable();
304 if (DIVar->isParameter() &&
305 getDISubprogram(DIVar->getScope())->describes(&MF->getFunction())) {
306 if (!IsDescribedByReg(Entries.front().getInstr()))
307 LabelsBeforeInsn[Entries.front().getInstr()] = Asm->getFunctionBegin();
308 if (Entries.front().getInstr()->getDebugExpression()->isFragment()) {
309 // Mark all non-overlapping initial fragments.
310 for (const auto *I = Entries.begin(); I != Entries.end(); ++I) {
311 if (!I->isDbgValue())
312 continue;
313 const DIExpression *Fragment = I->getInstr()->getDebugExpression();
314 if (std::any_of(Entries.begin(), I,
315 [&](DbgValueHistoryMap::Entry Pred) {
316 return Pred.isDbgValue() &&
317 Fragment->fragmentsOverlap(
318 Pred.getInstr()->getDebugExpression());
319 }))
320 break;
321 // The code that generates location lists for DWARF assumes that the
322 // entries' start labels are monotonically increasing, and since we
323 // don't change the label for fragments that are described by
324 // registers, we must bail out when encountering such a fragment.
325 if (IsDescribedByReg(I->getInstr()))
326 break;
327 LabelsBeforeInsn[I->getInstr()] = Asm->getFunctionBegin();
328 }
329 }
330 }
331
332 for (const auto &Entry : Entries) {
333 if (Entry.isDbgValue())
334 requestLabelBeforeInsn(Entry.getInstr());
335 else
336 requestLabelAfterInsn(Entry.getInstr());
337 }
338 }
339
340 // Ensure there is a symbol before DBG_LABEL.
341 for (const auto &I : DbgLabels) {
342 const MachineInstr *MI = I.second;
344 }
345
349}
350
352 if (!Asm || !MMI->hasDebugInfo())
353 return;
354
355 assert(CurMI == nullptr);
356 CurMI = MI;
357
358 // Insert labels where requested.
360 LabelsBeforeInsn.find(MI);
361
362 // No label needed.
363 if (I == LabelsBeforeInsn.end())
364 return;
365
366 // Label already assigned.
367 if (I->second)
368 return;
369
370 if (!PrevLabel) {
372 Asm->OutStreamer->emitLabel(PrevLabel);
373 }
374 I->second = PrevLabel;
375}
376
378 if (!Asm || !MMI->hasDebugInfo())
379 return;
380
381 assert(CurMI != nullptr);
382 // Don't create a new label after DBG_VALUE and other instructions that don't
383 // generate code.
384 if (!CurMI->isMetaInstruction()) {
385 PrevLabel = nullptr;
387 }
388
391
392 // No label needed or label already assigned.
393 if (I == LabelsAfterInsn.end() || I->second) {
394 CurMI = nullptr;
395 return;
396 }
397
398 // We need a label after this instruction. With basic block sections, just
399 // use the end symbol of the section if this is the last instruction of the
400 // section. This reduces the need for an additional label and also helps
401 // merging ranges.
402 if (CurMI->getParent()->isEndSection() && CurMI->getNextNode() == nullptr) {
404 } else if (!PrevLabel) {
406 Asm->OutStreamer->emitLabel(PrevLabel);
407 }
408 I->second = PrevLabel;
409 CurMI = nullptr;
410}
411
413 if (Asm && hasDebugInfo(MMI, MF))
414 endFunctionImpl(MF);
417 LabelsBeforeInsn.clear();
418 LabelsAfterInsn.clear();
419 InstOrdering.clear();
420}
421
423 EpilogBeginBlock = nullptr;
424 if (!MBB.isEntryBlock())
426}
427
429 PrevLabel = nullptr;
430}
MachineBasicBlock & MBB
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static cl::opt< bool > TrimVarLocs("trim-var-locs", cl::Hidden, cl::init(true))
If true, we drop variable location ranges which exist entirely outside the variable's lexical scope i...
static bool hasDebugInfo(const MachineModuleInfo *MMI, const MachineFunction *MF)
#define LLVM_DEBUG(X)
Definition: Debug.h:101
IRTranslator LLVM IR MI
#define I(x, y, z)
Definition: MD5.cpp:58
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This class is intended to be used as a driving class for all asm writers.
Definition: AsmPrinter.h:84
MCSymbol * getFunctionBegin() const
Definition: AsmPrinter.h:274
MachineFunction * MF
The current machine function.
Definition: AsmPrinter.h:102
std::unique_ptr< MCStreamer > OutStreamer
This is the MCStreamer object for the file we are generating.
Definition: AsmPrinter.h:99
DWARF expression.
expr_op_iterator expr_op_begin() const
Visit the elements via ExprOperand wrappers.
expr_op_iterator expr_op_end() const
DILocalScope * getScope() const
Get the local scope for this variable.
dwarf::Tag getTag() const
Base class for types.
StringRef getName() const
uint64_t getSizeInBits() const
This class represents an Operation in the Expression.
Specifies a change in a variable's debug value history.
void trimLocationRanges(const MachineFunction &MF, LexicalScopes &LScopes, const InstructionOrdering &Ordering)
Drop location ranges which exist entirely outside each variable's scope.
LLVM_DUMP_METHOD void dump(StringRef FuncName) const
static bool isUnsignedDIType(const DIType *Ty)
Return true if type encoding is unsigned.
const MachineInstr * CurMI
If nonnull, stores the current machine instruction we're processing.
AsmPrinter * Asm
Target of debug info emission.
virtual void endFunctionImpl(const MachineFunction *MF)=0
MCSymbol * getLabelBeforeInsn(const MachineInstr *MI)
Return Label preceding the instruction.
MachineModuleInfo * MMI
Collected machine module information.
void endBasicBlockSection(const MachineBasicBlock &MBB) override
Process the end of a basic-block-section within a function.
void identifyScopeMarkers()
Indentify instructions that are marking the beginning of or ending of a scope.
virtual void skippedNonDebugFunction()
void endFunction(const MachineFunction *MF) override
Gather post-function debug information.
DebugLoc PrevInstLoc
Previous instruction's location information.
void beginFunction(const MachineFunction *MF) override
Gather pre-function debug information.
void endInstruction() override
Process end of an instruction.
MCSymbol * getLabelAfterInsn(const MachineInstr *MI)
Return Label immediately following the instruction.
DebugHandlerBase(AsmPrinter *A)
void beginInstruction(const MachineInstr *MI) override
Process beginning of an instruction.
const MachineBasicBlock * PrevInstBB
virtual void beginFunctionImpl(const MachineFunction *MF)=0
void requestLabelAfterInsn(const MachineInstr *MI)
Ensure that a label will be emitted after MI.
void beginBasicBlockSection(const MachineBasicBlock &MBB) override
Process the beginning of a new basic-block-section within a function.
DbgValueHistoryMap DbgValues
History of DBG_VALUE and clobber instructions for each user variable.
DbgLabelInstrMap DbgLabels
Mapping of inlined labels and DBG_LABEL machine instruction.
DenseMap< const MachineInstr *, MCSymbol * > LabelsBeforeInsn
Maps instruction with label emitted before instruction.
void beginModule(Module *M) override
DenseMap< const MachineInstr *, MCSymbol * > LabelsAfterInsn
Maps instruction with label emitted after instruction.
void requestLabelBeforeInsn(const MachineInstr *MI)
Ensure that a label will be emitted before MI.
const MachineBasicBlock * EpilogBeginBlock
This block includes epilogue instructions.
static uint64_t getBaseTypeSize(const DIType *Ty)
If this type is derived from a base type then return base type size.
A debug info location.
Definition: DebugLoc.h:33
DISubprogram * getSubprogram() const
Get the attached subprogram.
Definition: Metadata.cpp:1828
void initialize(const MachineFunction &MF)
LexicalScope - This class is used to track scope information.
Definition: LexicalScopes.h:44
SmallVectorImpl< LexicalScope * > & getChildren()
Definition: LexicalScopes.h:65
SmallVectorImpl< InsnRange > & getRanges()
Definition: LexicalScopes.h:66
bool isAbstractScope() const
Definition: LexicalScopes.h:64
void initialize(const MachineFunction &)
initialize - Scan machine function and constuct lexical scope nest, resets the instance if necessary.
bool empty()
empty - Return true if there is any lexical scope information available.
LexicalScope * getCurrentFunctionScope() const
getCurrentFunctionScope - Return lexical scope for the current function.
MCSymbol * createTempSymbol()
Create a temporary symbol with a unique name.
Definition: MCContext.cpp:321
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
Definition: MCSymbol.h:40
MCSymbol * getSymbol() const
Return the MCSymbol for this basic block.
MCSymbol * getEndSymbol() const
Returns the MCSymbol marking the end of this basic block.
bool isEntryBlock() const
Returns true if this is the entry block of the function.
bool isEndSection() const
Returns true if this block ends any section.
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.
Function & getFunction()
Return the LLVM function that this machine code represents.
Representation of each machine instruction.
Definition: MachineInstr.h:69
const MachineBasicBlock * getParent() const
Definition: MachineInstr.h:327
bool isMetaInstruction(QueryType Type=IgnoreBundle) const
Return true if this instruction doesn't produce any output in the form of executable instructions.
Definition: MachineInstr.h:902
This class contains meta information specific to a module.
const MCContext & getContext() const
bool hasDebugInfo() const
Returns true if valid debug info is present.
A Module instance is used to store all the information related to an LLVM module.
Definition: Module.h:65
bool empty() const
Definition: SmallVector.h:94
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
Definition: SmallVector.h:586
void append(ItTy in_start, ItTy in_end)
Add the specified range to the end of the SmallVector.
Definition: SmallVector.h:696
void push_back(const T &Elt)
Definition: SmallVector.h:426
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1209
virtual const TargetRegisterInfo * getRegisterInfo() const
getRegisterInfo - If register information is available, return it.
LLVM Value Representation.
Definition: Value.h:74
NodeTy * getNextNode()
Get the next node, or nullptr for the list tail.
Definition: ilist_node.h:316
initializer< Ty > init(const Ty &Val)
Definition: CommandLine.h:450
@ DW_OP_LLVM_fragment
Only used in LLVM metadata.
Definition: Dwarf.h:141
@ DW_OP_LLVM_arg
Only used in LLVM metadata.
Definition: Dwarf.h:146
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
@ Offset
Definition: DWP.cpp:456
void calculateDbgEntityHistory(const MachineFunction *MF, const TargetRegisterInfo *TRI, DbgValueHistoryMap &DbgValues, DbgLabelInstrMap &DbgLabels)
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
Definition: STLExtras.h:1738
DWARFExpression::Operation Op
std::pair< const MachineInstr *, const MachineInstr * > InsnRange
InsnRange - This is used to track range of instructions with identical lexical scope.
Definition: LexicalScopes.h:39
DISubprogram * getDISubprogram(const MDNode *Scope)
Find subprogram that is enclosing this scope.
Definition: DebugInfo.cpp:149
Represents the location at which a variable is stored.
static std::optional< DbgVariableLocation > extractFromMachineInstruction(const MachineInstr &Instruction)
Extract a VariableLocation from a MachineInstr.