LLVM 24.0.0git
SPIRVNonSemanticDebugHandler.h
Go to the documentation of this file.
1//===-- SPIRVNonSemanticDebugHandler.h - NSDI AsmPrinter handler -*- C++
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// This file declares SPIRVNonSemanticDebugHandler, a DebugHandlerBase subclass
11// that emits NonSemantic.Shader.DebugInfo.100 instructions in the SPIR-V
12// AsmPrinter. It replaces SPIRVEmitNonSemanticDI, which was a
13// MachineFunctionPass, with a handler that controls instruction placement
14// directly instead of routing through SPIRVModuleAnalysis.
15//
16//===----------------------------------------------------------------------===//
17
18#ifndef LLVM_LIB_TARGET_SPIRV_SPIRVNONSEMANTICDEBUGHANDLER_H
19#define LLVM_LIB_TARGET_SPIRV_SPIRVNONSEMANTICDEBUGHANDLER_H
20
22#include "SPIRVModuleAnalysis.h"
23#include "llvm/ADT/DenseMap.h"
24#include "llvm/ADT/DenseSet.h"
25#include "llvm/ADT/SetVector.h"
28#include "llvm/ADT/StringMap.h"
31#include "llvm/MC/MCInst.h"
32#include "llvm/MC/MCRegister.h"
33#include <optional>
34
35namespace llvm {
36
37class GlobalVariable;
39class SPIRVSubtarget;
40
41/// AsmPrinter handler that emits NonSemantic.Shader.DebugInfo.100 (NSDI)
42/// instructions for the SPIR-V backend. Registered with SPIRVAsmPrinter when
43/// the module contains debug info (llvm.dbg.cu).
44///
45/// Call sequence:
46/// - beginModule() collects compile-unit metadata.
47/// - prepareModuleOutput() adds the extension and ext-inst set to MAI.
48/// - emitNonSemanticDebugStrings() emits NSDI OpStrings in section 7.
49/// - emitNonSemanticGlobalDebugInfo() emits module-scope NSDI and sets
50/// GlobalNSDIEnabled.
51/// - beginFunctionImpl() prepares per-function DebugFunctionDefinition state
52/// and runs analyzeDebugRecords() over the whole function.
53/// - endInstruction() emits DebugFunctionDefinition after the last function-
54/// level OpVariable; SPIRVAsmPrinter calls notifyEntryLabelEmitted() after
55/// the synthesized entry OpLabel when there are no OpVariables.
56/// - beginInstruction() emits the DebugScope and DebugLine for the instruction
57/// being printed, and the DebugDeclare and DebugValue anchored on it.
58/// - endFunctionImpl() resets per-function state.
60 static constexpr unsigned NSSet = static_cast<unsigned>(
61 SPIRV::InstructionSet::NonSemantic_Shader_DebugInfo_100);
62
63 struct CompileUnitInfo {
64 const DICompileUnit *TheCU = nullptr;
65 SmallString<128> FilePath;
66 unsigned SpirvSourceLanguage = 0; // NonSemantic.Shader.DebugInfo.100 source
67 // language code (section 4.3)
68 };
70 int64_t DwarfVersion = 0;
71
72 // DI types partitioned from DebugInfoFinder.types() in beginModule()
73 // (basics, pointers, vectors, subroutine types NSDI v1 may emit).
77 // DICompositeType nodes with DW_TAG_array_type and DINode::FlagVector,
78 // partitioned from DebugInfoFinder.types() in beginModule().
80 // DICompositeType nodes with DW_TAG_array_type that are not vectors,
81 // partitioned in beginModule().
83 // DICompositeType nodes with DW_TAG_structure_type, DW_TAG_class_type, or
84 // DW_TAG_union_type, partitioned in beginModule() for DebugTypeComposite.
86 // DIDerivedType nodes with DW_TAG_typedef, partitioned in beginModule() for
87 // DebugTypedef emission.
89
90 // NonSemantic debug instruction result id per emitted scope.
92
93 // DISubprogram nodes that are declarations only (!isDefinition()), collected
94 // in beginModule() for DebugFunctionDeclaration emission.
95 SmallVector<const DISubprogram *> SubprogramDeclarations;
96
97 // DISubprogram nodes that are definitions, collected in beginModule() for
98 // DebugFunction emission.
99 SmallVector<const DISubprogram *> SubprogramDefinitions;
100
101 // Distinct DILocations from instruction !dbg attachments and debug program
102 // records (#dbg_declare, #dbg_value, #dbg_assign, #dbg_label).
103 SetVector<const DILocation *> UniqueDebugLocations;
104
105 struct GlobalVariableDebugInfo {
106 const DIExpression *Expr = nullptr;
107 const GlobalVariable *LLVMGV = nullptr;
108 };
110 GlobalVariableDebugInfoMap;
111
112 // Distinct DILocalVariable nodes collected in beginModule() from dbg records
113 // and from DISubprogram retained nodes.
115
116 // DebugLocalVariable result id per variable that module-scope emission
117 // actually emitted. DebugDeclare needs it for its Local Variable operand; a
118 // variable missing here (skipped type or scope) gets no declare.
120
121 // DebugExpression result id per DIExpression that could be lowered. An
122 // expression missing here uses operations with no NonSemantic counterpart,
123 // so declares referencing it are skipped rather than described wrongly.
125
126 // Distinct DILexicalBlock and DINamespace scopes, parent-before-child
127 // order, collected in beginModule() for DebugLexicalBlock emission.
128 SetVector<const DIScope *> LexicalBlocks;
129
130 // DebugInlinedAt result id per DILocation used as an inlined-at chain link.
132
133 // Path \c OpString result id per \c DIScope (CU, \c DIFile, declaration
134 // \c DISubprogram, …). Filled during \c emitNonSemanticDebugStrings() using
135 // \c getDebugFullPath + \c emitOpStringIfNew; section 10 uses it for
136 // \c DebugSource without recomputing path text.
137 DenseMap<const DIScope *, MCRegister> ScopeToPathOpStringReg;
138
139 // DebugSource result id keyed by path \c OpString id (\c MCRegister::id()),
140 // deduplicating when the same file string is reused.
141 DenseMap<unsigned, MCRegister> DebugSourceRegByFileStr;
142
143 // Maps OpString contents to result id. Populated only by emitOpStringIfNew()
144 // during section 7; section 10 uses getCachedOpStringReg() (lookup only).
145 StringMap<MCRegister> OpStringContentCache;
146
147#ifndef NDEBUG // Only declare the variable for debugging purposes.
148 // True after emitNonSemanticDebugStrings() emitted the NSDI OpStrings for
149 // this module. SPIRVAsmPrinter calls that before
150 // emitNonSemanticGlobalDebugInfo().
151 bool NonSemanticOpStringsSectionEmitted = false;
152#endif
153
154 MCRegister CachedEmptyStringReg;
155
156 MCRegister CachedDebugInfoNoneReg;
157
158 MCRegister CachedOpTypeVoidReg;
159
160 MCRegister CachedOpTypeInt32Reg;
161
162 // Result id per SPIR-V scalar type this handler needed, keyed by opcode and
163 // width. MB_TypeConstVars holds only what module analysis collected, so a
164 // type emitted here has to be remembered separately to stay unique.
166
167 // Result id per scalar constant, keyed by its type's id and its bits. Keying
168 // on the type lets two DIBasicTypes describing it share a constant.
170
171 // Result id per collected constant, keyed by its type and bits. Filled
172 // during module-scope emission, since an OpConstant has to precede every
173 // function body that names it.
175 ConstantValueRegs;
176
177 // Cache of already-emitted DebugTypeFunction instructions, keyed by operand
178 // ids (flags, return type, parameters).
179 DenseMap<SmallVector<MCRegister, 8>, MCRegister> DebugTypeFunctionCache;
180
181 // Cache of already-emitted DebugOperation instructions, keyed by NonSemantic
182 // opcode followed by the 32-bit operation arguments. Inline size 3 is the
183 // spec maximum (opcode plus at most two operands: BitPiece, Fragment).
184 DenseMap<SmallVector<uint32_t, 3>, MCRegister> DebugOperationCache;
185
186 // Cache of already-emitted DebugExpression instructions, keyed by the
187 // DebugOperation result ids in operand order. Useful for debug values
188 // and global-variable init expressions.
189 DenseMap<SmallVector<MCRegister>, MCRegister> DebugExpressionCache;
190
191 // True once emitNonSemanticGlobalDebugInfo() has run. Both
192 // SPIRVAsmPrinter::emitFunctionHeader() and emitEndOfAsmFile() may call
193 // outputModuleSections(), each guarded by ModuleSectionsEmitted, so only
194 // one fires. This flag provides a secondary guard in case the call sites
195 // change.
196 bool GlobalDIEmitted = false;
197
198 // True when emitNonSemanticGlobalDebugInfo() completed module-scope NSDI
199 // emission for this module.
200 bool GlobalNSDIEnabled = false;
201
202 SPIRV::ModuleAnalysisInfo *CurrentMAI = nullptr;
203
204 const MachineFunction *CurrentMF = nullptr;
205
206 const MachineInstr *LastFunctionOpVariable = nullptr;
207
208 bool DebugFunctionDefinitionEmitted = false;
209
210 // Instruction that opened the DebugLine / DebugScope region currently in
211 // effect, or nullptr when no region is open. The two are tracked separately
212 // because a DebugScope region usually spans several DebugLine regions, and
213 // either one can skip emission on a cache miss.
214 const MachineInstr *LastLineMI = nullptr;
215 const MachineInstr *LastScopeMI = nullptr;
216
217 // Result ids in MB_TypeConstVars, which precedes every function body. Filled
218 // once per module in prepareModuleOutput().
219 DenseSet<MCRegister> ModuleScopeIds;
220
221 /// A DebugDeclare or DebugValue waiting for its anchor to be printed.
222 struct DebugRecord {
223 const MachineInstr *MI; ///< The DBG_VALUE this came from.
224 SPIRV::NonSemanticExtInst::NonSemanticExtInst Opcode;
225 MCRegister LocationReg; ///< The Variable or Value operand.
226 };
227
228 // Records to emit before their anchor is printed, built once per function by
229 // analyzeDebugRecords() and only read afterwards.
231
232public:
234
235 /// Collect compile-unit metadata from the module. Called by
236 /// AsmPrinter::doInitialization() via the handler list. No emission.
237 void beginModule(Module *M) override;
238
239 /// Emit OpString instructions for all NSDI file paths and basic type names
240 /// into the debug section (section 7 of the SPIR-V module layout). Must be
241 /// called from SPIRVAsmPrinter::outputDebugSourceAndStrings(), after
242 /// prepareModuleOutput() has registered the ext inst set. Registers are
243 /// stored in \c OpStringContentCache and \c ScopeToPathOpStringReg;
244 /// \c emitNonSemanticGlobalDebugInfo() resolves them via
245 /// \c getCachedOpStringReg() and path maps.
247
248 /// Add SPV_KHR_non_semantic_info extension and
249 /// NonSemantic.Shader.DebugInfo.100 ext inst set entry to MAI. Must be called
250 /// before outputGlobalRequirements() and outputOpExtInstImports() in
251 /// SPIRVAsmPrinter::outputModuleSections().
252 void prepareModuleOutput(const SPIRVSubtarget &ST,
254
255 /// Emit module-scope NSDI instructions (DebugSource, DebugCompilationUnit,
256 /// DebugTypeBasic, DebugTypePointer, DebugTypeFunction,
257 /// DebugFunctionDeclaration, DebugFunction). Called by
258 /// SPIRVAsmPrinter::outputModuleSections() at section 10 in place of
259 /// outputModuleSection(MB_NonSemanticGlobalDI). Requires
260 /// emitNonSemanticDebugStrings() to have run first when NSDI strings apply.
261 /// Sets \c GlobalNSDIEnabled when module-scope NSDI emission completes.
263
264 /// Called after the synthesized entry \c OpLabel has been emitted.
266
267protected:
268 // All module-level output is driven by emitNonSemanticGlobalDebugInfo(),
269 // called explicitly from SPIRVAsmPrinter::outputModuleSections(). Nothing
270 // needs to happen in the AsmPrinterHandler::endModule() callback.
271 void endModule() override {}
272
273 // DebugHandlerBase stores MMI as a pointer copy from Asm->MMI at construction
274 // time (DebugHandlerBase.cpp: `MMI(Asm->MMI)`). The handler is constructed
275 // before AsmPrinter::doInitialization() runs, so Asm->MMI is null at that
276 // point and MMI remains null for this handler's entire lifetime. Do not call
277 // the base-class beginInstruction/endInstruction — they dereference MMI to
278 // create temp symbols for label tracking and would crash.
279 // Future local NSDI that needs MCContext must use
280 // Asm->OutStreamer->getContext() rather than MMI->getContext().
281 void beginInstruction(const MachineInstr *MI) override;
282 void endInstruction() override;
283
284 // Override beginFunctionImpl(), not beginFunction():
285 // DebugHandlerBase::beginFunction() populates LScopes and DbgValues needed
286 // for future DebugLine emission.
287 void beginFunctionImpl(const MachineFunction *MF) override;
288 void endFunctionImpl(const MachineFunction *MF) override;
289
290private:
291 void emitDebugFunctionDefinition(MCRegister DebugFunctionReg,
292 MCRegister OpFunctionReg,
294
295 void resetPerFunctionDebugState();
296
297 /// Resolve the instruction that a per-instruction DebugLine/DebugScope
298 /// update should attach to: \p MI adjusted forward past a merge
299 /// instruction to its terminator, or \c std::nullopt if \p MI is not a
300 /// valid attachment point (skip-emission, or one of the structural opcodes
301 /// that can never carry DebugLine/DebugScope: OpFunction,
302 /// OpFunctionParameter, OpFunctionEnd, OpLabel, OpPhi).
303 std::optional<const MachineInstr *>
304 resolveDebugLocTarget(const MachineInstr *MI);
305
306 /// Open the DebugScope region \p MI belongs to, closing the previous one.
307 ///
308 /// \returns False when \p MI's scope has no \c DebugScope, or its chain no
309 /// \c DebugInlinedAt, leaving the open region someone else's.
310 bool emitDebugScopeForInstruction(const MachineInstr *MI);
311 void emitDebugLineForInstruction(const MachineInstr *MI);
312 void preparePerFunctionDebug(const MachineFunction *MF);
313 void tryEmitDebugFunctionDefinition(SPIRV::ModuleAnalysisInfo &MAI);
314
315 void emitMCInst(MCInst &Inst);
316 MCRegister emitOpString(StringRef S, SPIRV::ModuleAnalysisInfo &MAI);
317
318 /// Section 7 only: emit OpString and cache it if not already present. Must
319 /// not be called after NonSemanticOpStringsSectionEmitted is set. Returns
320 /// the path (or string) \c OpString result id.
321 MCRegister emitOpStringIfNew(StringRef S, SPIRV::ModuleAnalysisInfo &MAI);
322
323 /// Section 10 only: lookup OpString id from cache; asserts if missing or if
324 /// section 7 did not complete.
325 MCRegister getCachedOpStringReg(StringRef S);
326
327 /// Section 7 only: emit the path \c OpString for \p Scope and cache it under
328 /// \p Scope. Returns the \c OpString result id. A \p Scope already seen
329 /// returns the cached id without rebuilding the path. A null \p Scope maps to
330 /// the empty path and is cached like any other, though section 10 reads it
331 /// through \c getCachedScopePathOpStringReg, which handles null separately.
332 MCRegister emitAndCacheScopePathOpStringReg(const DIScope *Scope,
334
335 /// Section 10 only: lookup path \c OpString id for \p Scope from
336 /// \c ScopeToPathOpStringReg; asserts if missing or invalid. When
337 /// \p UseEmptyPathIfNullScope is true and \p Scope is null, returns
338 /// \c CachedEmptyStringReg instead.
340 getCachedScopePathOpStringReg(const DIScope *Scope,
341 bool UseEmptyPathIfNullScope = false);
342 MCRegister emitOpConstantI32(uint32_t Value, MCRegister I32TypeReg,
344 MCRegister emitExtInst(SPIRV::NonSemanticExtInst::NonSemanticExtInst Opcode,
345 MCRegister VoidTypeReg, MCRegister ExtInstSetReg,
348
349 /// Return a cached DebugTypeFunction id when \p Ops matches a prior emission,
350 /// otherwise emit and cache a new instruction.
351 MCRegister getOrEmitDebugTypeFunction(ArrayRef<MCRegister> Ops,
352 MCRegister VoidTypeReg,
353 MCRegister ExtInstSetReg,
355
356 /// Return OpTypeVoid id for this module (lazy lookup / emit, then cache).
357 MCRegister getOrEmitOpTypeVoidReg(SPIRV::ModuleAnalysisInfo &MAI);
358
359 /// Return OpTypeInt 32 0 id for this module (lazy lookup / emit, then cache).
360 MCRegister getOrEmitOpTypeInt32Reg(SPIRV::ModuleAnalysisInfo &MAI);
361
362 /// Find OpTypeVoid in the already-emitted TypeConstVars section, or emit one
363 /// if the module does not contain it (e.g. no void-returning functions).
364 MCRegister findOrEmitOpTypeVoid(SPIRV::ModuleAnalysisInfo &MAI);
365
366 /// Find OpTypeInt 32 0 in the already-emitted TypeConstVars section, or emit
367 /// one if the module does not contain it.
368 MCRegister findOrEmitOpTypeInt32(SPIRV::ModuleAnalysisInfo &MAI);
369
370 /// Emit \c DebugTypePointer for pointer metadata \p PT.
371 ///
372 /// \returns The result id register on success. Returns \c std::nullopt and
373 /// emits nothing if \p PT has no DWARF address space (needed to pick the
374 /// SPIR-V storage class), or if \p PT has a non-null base DI type that is not
375 /// yet in \c DebugScopeRegs (the pointee was not emitted as a debug type).
376 ///
377 /// Base Type operand: the register from \c DebugScopeRegs for \p PT's base
378 /// type when it is set and mapped; \c DebugInfoNone when there is no base
379 /// type (e.g. \c void * in IR), consistent with SPIRV-LLVM-Translator.
380 std::optional<MCRegister>
381 emitDebugTypePointer(const DIDerivedType *PT, MCRegister ExtInstSetReg,
383
384 /// Emit one DebugTypeFunction for ST when every DI operand maps to a debug
385 /// type id; otherwise emit nothing and return std::nullopt.
386 std::optional<MCRegister>
387 emitDebugTypeFunctionForSubroutineType(const DISubroutineType *ST,
388 MCRegister ExtInstSetReg,
390
391 /// Emit \c DebugFunctionDeclaration for a \c DISubprogram that is not a
392 /// definition (\p SP must satisfy \c !isDefinition()).
393 ///
394 /// \returns The result id register on success. Returns \c std::nullopt and
395 /// emits nothing if \p SP is null, is a definition, has no \c
396 /// DISubroutineType type, the signature type was not emitted in \c
397 /// DebugScopeRegs, no path
398 /// \c OpString was recorded for \p SP in section 7, or
399 /// \c resolveScope returns no id for the \c Parent operand.
400 std::optional<MCRegister>
401 emitDebugFunctionDeclaration(const DISubprogram *SP, MCRegister VoidTypeReg,
402 MCRegister I32TypeReg, MCRegister ExtInstSetReg,
404
405 /// Emit \c DebugFunction for a defining \c DISubprogram (\p SP must satisfy
406 /// \c isDefinition()).
407 std::optional<MCRegister> emitDebugFunction(const DISubprogram *SP,
408 MCRegister VoidTypeReg,
409 MCRegister I32TypeReg,
410 MCRegister ExtInstSetReg,
412
413 /// Emit \c DebugLocalVariable for the source local variable \p LV:
414 /// Name, Type, Source, Line, Column, Parent, Flags, and an optional Arg
415 /// Number. Line, Column, Flags, and Arg Number are emitted as \c OpConstant
416 /// ids as required for non-semantic debug info. Column is always 0:
417 /// \c DILocalVariable has no column field.
418 ///
419 /// Arg Number is appended when \p LV is a parameter.
420 ///
421 /// \returns The result id register on success. Returns \c std::nullopt and
422 /// emits nothing if \p LV's scope is not an emitted local scope,
423 /// if a non-null type was not emitted in \c DebugScopeRegs, or if
424 /// \c resolveScope returns no id for the Parent operand.
425 std::optional<MCRegister>
426 emitDebugLocalVariable(const DILocalVariable *LV, MCRegister VoidTypeReg,
427 MCRegister I32TypeReg, MCRegister ExtInstSetReg,
429
430 /// Emit \c DebugGlobalVariable for the source global variable \p GV.
431 ///
432 /// (\c SPIRVDebug::Operand::GlobalVariable): Name, Type, Source, Line,
433 /// Column, Parent, Linkage Name, Variable, Flags, and an optional Static
434 /// Member Declaration. Line, Column, and Flags are emitted as \c OpConstant
435 /// ids as required for non-semantic debug info.
436 ///
437 /// \c DebugInfoNone is used for two operands when LLVM has no value to
438 /// supply:
439 /// \c Type when \p GV is a declaration with no DI type (e.g. \c extern void;
440 /// valid IR, \c isDefinition: false); \c Variable when no \c
441 /// llvm::GlobalVariable in this module carries \p GV in its \c !dbg metadata.
442 ///
443 /// \returns The result id register on success. Returns \c std::nullopt and
444 /// emits nothing if a non-null \p GV type was not emitted in \c
445 /// DebugScopeRegs, or \p GV has a static data member declaration that was not
446 /// emitted in \c DebugScopeRegs.
447 std::optional<MCRegister> emitDebugGlobalVariable(
448 const DIGlobalVariable *GV, const GlobalVariableDebugInfo &Info,
449 MCRegister VoidTypeReg, MCRegister I32TypeReg, MCRegister ExtInstSetReg,
451
452 /// Collect the \c DIExpression of every debug value in the module
453 /// (\c DBG_VALUE, \c DBG_VALUE_LIST, \c DBG_INSTR_REF), in MIR order.
454 ///
455 /// Reads MIR rather than IR because only MIR shows which debug values
456 /// survived codegen and in what form, and because an expression synthesized
457 /// during lowering never appears in the IR at all. Must be called from
458 /// module-scope emission, which is where the resulting \c DebugExpression
459 /// instructions have to be emitted; every \c MachineFunction is still
460 /// reachable at that point through \c MachineModuleInfo.
461 ///
462 /// Deliberately independent of what the consumers can currently emit, so
463 /// that adding an instruction that needs an expression (\c DebugValue) needs
464 /// no change here. The cost is a \c DebugExpression that nothing references
465 /// yet, for a debug value no instruction is emitted for.
466 void collectDebugExpressions(SetVector<const DIExpression *> &Out) const;
467
468 /// Emit one \c DebugOperation for \p Op, reusing a cached result id when the
469 /// same opcode and arguments were already emitted.
470 ///
471 /// \returns The result id register on success. Returns \c std::nullopt and
472 /// emits nothing if \p Op has no NonSemantic counterpart, or carries an
473 /// argument too large for the 32-bit \c OpConstant operands this set
474 /// requires.
475 std::optional<MCRegister>
476 emitDebugOperation(const DIExpression::ExprOperand &Op,
477 MCRegister VoidTypeReg, MCRegister I32TypeReg,
478 MCRegister ExtInstSetReg, SPIRV::ModuleAnalysisInfo &MAI);
479
480 /// Emit one \c DebugOperation per element of \p Expr followed by the
481 /// \c DebugExpression that lists them. Reuses a cached \c DebugExpression
482 /// when that sequence of \c DebugOperation ids was already emitted. An
483 /// empty \p Expr yields a \c DebugExpression with no operands, which is
484 /// what a plain \c !DIExpression() means.
485 ///
486 /// Must be called from module-scope emission only: \c DebugExpression and
487 /// \c DebugOperation are not in the spec's list of instructions allowed
488 /// inside a function, and forward references were removed in Rev 2.
489 ///
490 /// \returns The result id register on success. Returns \c std::nullopt and
491 /// does not emit the \c DebugExpression if any element has no NonSemantic
492 /// counterpart, or carries an argument too large for the 32-bit \c OpConstant
493 /// operands this set requires.
494 std::optional<MCRegister> emitDebugExpression(const DIExpression *Expr,
495 MCRegister VoidTypeReg,
496 MCRegister I32TypeReg,
497 MCRegister ExtInstSetReg,
499
500 /// Fill \c Records from the debug records in \p MF.
501 ///
502 /// Where a record may legally sit is a property of the whole function, and
503 /// emission is unbuffered, so it is settled here rather than while printing.
504 void analyzeDebugRecords(const MachineFunction &MF);
505
506 /// Place the single record \p MI. \p LastEmitted is the nearest preceding
507 /// instruction in this block that reaches the output, or null when there is
508 /// none.
509 ///
510 /// Places nothing when this backend cannot name the record: an unavailable
511 /// location, a declare whose storage is not an \c OpVariable, a constant
512 /// with no module-scope id, a physical register, a variadic value, an
513 /// instruction reference, or a definition that does not dominate \p MI.
514 void resolveDebugRecord(const MachineInstr &MI,
515 const MachineInstr *LastEmitted,
516 const MachineDominatorTree &DomTree);
517
518 /// Store \p MI on \p Anchor, to emit before \p Anchor is printed.
519 void placeRecord(SPIRV::NonSemanticExtInst::NonSemanticExtInst Opcode,
520 const MachineInstr &MI, MCRegister LocationReg,
521 const MachineInstr *Anchor);
522
523 void emitAnalyzedRecords(const MachineInstr *Anchor);
524
525 /// The \c OpConstant id for the constant \p MI assigns, or \c std::nullopt
526 /// when \p MI assigns no constant this backend emitted.
527 std::optional<MCRegister> getConstantValueReg(const MachineInstr &MI) const;
528
529 /// Result id of the constant \p Opcode of type \p TypeReg holding
530 /// \p Value in \c MB_TypeConstVars, or an invalid register when the module
531 /// does not already define it.
532 MCRegister findModuleConstant(unsigned Opcode, MCRegister TypeReg,
533 uint64_t Value, bool IsBool, bool IsWide,
535
536 /// Result id of the SPIR-V type for \p BT, reusing one from
537 /// \c MB_TypeConstVars when the module already defines it. Invalid when
538 /// declaring it would require a capability the module does not have, since
539 /// debug info must not change what the module requires.
540 MCRegister findOrEmitScalarType(const DIBasicType *BT,
542
543 /// Result id of the constant \p Value, with \p BT giving both the SPIR-V
544 /// type and the opcode. Invalid when the type may not be created.
545 MCRegister findOrEmitScalarConstant(const DIBasicType *BT, uint64_t Value,
547
548 /// Result id of the constant \p Value of type \p TypeReg, reusing one from
549 /// \c MB_TypeConstVars or from an earlier call when either already has it.
550 MCRegister findOrEmitConstant(unsigned Opcode, MCRegister TypeReg,
551 uint64_t Value, unsigned Width,
553
554 /// Emit \p Opcode naming \p MI's variable, \p LocationReg and \p MI's
555 /// expression, after \p MI's own \c DebugScope and \c DebugLine. Emits
556 /// nothing when \p MI's variable has no \c DebugLocalVariable, its
557 /// expression no \c DebugExpression, or its scope no id.
558 void emitDebugBinding(SPIRV::NonSemanticExtInst::NonSemanticExtInst Opcode,
559 const MachineInstr *MI, MCRegister LocationReg);
560
561 /// Emit \c DebugTypeVector for the vector composite type \p VT.
562 ///
563 /// \returns The result id register on success. Returns \c std::nullopt and
564 /// emits nothing if \p VT has no \c DIBasicType base type, if the base type
565 /// has not been emitted yet, if \p VT has more than one \c DISubrange
566 /// element, or if the component count is not a compile-time constant.
567 std::optional<MCRegister> emitDebugTypeVector(const DICompositeType *VT,
568 MCRegister ExtInstSetReg,
570
571 /// Emit \c DebugTypeArray for the array composite type \p AT.
572 ///
573 /// Emits the element (base) type id followed by one Component Count per
574 /// \c DISubrange, in DWARF subrange order. A count that is not a
575 /// compile-time constant is emitted as 0, matching \c OpTypeRuntimeArray. A
576 /// matrix arrives here as a multi-subrange array and is emitted with one
577 /// count per dimension.
578 ///
579 /// \returns The result id register on success. Returns \c std::nullopt and
580 /// emits nothing if \p AT's element type has not been emitted into
581 /// \c DebugScopeRegs.
582 std::optional<MCRegister> emitDebugTypeArray(const DICompositeType *AT,
583 MCRegister ExtInstSetReg,
585
586 /// Emit \c DebugTypeMember for the data member \p M (a \c DIDerivedType with
587 /// \c DW_TAG_member). Operands: Name, Type, Source, Line, Column, Offset,
588 /// Size, Flags. NonSemantic \c DebugTypeMember carries no Parent operand: the
589 /// enclosing \c DebugTypeComposite references its members, not the reverse.
590 ///
591 /// \returns The result id register on success. Returns \c std::nullopt and
592 /// emits nothing if \p M's type has not been emitted into \c DebugScopeRegs.
593 std::optional<MCRegister> emitDebugTypeMember(const DIDerivedType *M,
594 MCRegister VoidTypeReg,
595 MCRegister I32TypeReg,
596 MCRegister ExtInstSetReg,
598
599 /// Emit \c DebugTypeComposite for the struct, class, or union \p CT, listing
600 /// the already-emitted \p MemberRegs in its Members operand. A forward
601 /// declaration emits \c DebugInfoNone for Size and no members.
602 ///
603 /// \returns The result id register on success. Returns \c std::nullopt and
604 /// emits nothing if the Parent scope cannot be resolved.
605 std::optional<MCRegister> emitDebugTypeComposite(
606 const DICompositeType *CT, ArrayRef<MCRegister> MemberRegs,
607 MCRegister VoidTypeReg, MCRegister I32TypeReg, MCRegister ExtInstSetReg,
609
610 /// Emit \c DebugTypedef for the typedef derived type \p TD (a \c
611 /// DIDerivedType with \c DW_TAG_typedef). Operands: Name, Base Type, Source,
612 /// Line, Column, Parent. Parent is the enclosing type when \c TD->getScope()
613 /// is an emitted \c DIType, otherwise the first module \c
614 /// DebugCompilationUnit.
615 ///
616 /// \returns The result id register on success. Returns \c std::nullopt and
617 /// emits nothing if \p TD's base type has not been emitted into \c
618 /// DebugScopeRegs.
619 std::optional<MCRegister> emitDebugTypedef(const DIDerivedType *TD,
620 MCRegister VoidTypeReg,
621 MCRegister I32TypeReg,
622 MCRegister ExtInstSetReg,
624
625 /// Map a \c DISubroutineType::getTypeArray() element to an operand register
626 /// for
627 /// \c DebugTypeFunction. Non-null \p Ty resolves via \c DebugScopeRegs; if
628 /// the type was never emitted, returns \c std::nullopt.
629 ///
630 /// LLVM encodes a void return as a null first element (and may use null in
631 /// later slots). NonSemantic \c DebugTypeFunction
632 /// requires a concrete return-type operand, so when \p ReturnType is true and
633 /// \p Ty is null, this returns \p VoidTypeReg (\c OpTypeVoid). When
634 /// \p ReturnType is false and \p Ty is null, this returns
635 /// \c CachedDebugInfoNoneReg (\c DebugInfoNone).
636 std::optional<MCRegister> mapDISignatureTypeToReg(const DIType *Ty,
637 MCRegister VoidTypeReg,
638 bool ReturnType);
639
640 /// Map a DWARF source language code to a NonSemantic.Shader.DebugInfo.100
641 /// source language code.
642 static unsigned toNSDISrcLang(unsigned DwarfSrcLang);
643
644 /// Build a full path from debug \p Scope for OpString / DebugSource, matching
645 /// SPIRV-LLVM-Translator \c getFullPath (OCLUtil.h): \c DIScope::getFilename,
646 /// \c getDirectory, and \c sys::path::Style::native. Works for any \c DIScope
647 /// that carries file path fields (e.g. \c DIFile, \c DISubprogram,
648 /// \c DICompileUnit). Returns an empty path when \p Scope is null.
649 SmallString<128> getDebugFullPath(const DIScope *Scope) const;
650
651 /// Return an existing \c DebugSource id for file path \c OpString \p
652 /// FileStrReg or emit \c DebugSource and cache it (keyed by \p FileStrReg
653 /// id).
654 MCRegister getOrEmitDebugSourceForFileStrReg(MCRegister FileStrReg,
655 MCRegister VoidTypeReg,
656 MCRegister ExtInstSetReg,
658
659 /// Map \p Scope to the NonSemantic debug id used as a \c Parent operand.
660 ///
661 /// Checks \c DebugScopeRegs in order by scope kind. When \p Scope is null, a
662 /// \c DIFile, or another scope without a dedicated debug instruction, falls
663 /// back to \p FallbackCU or the first module \c DebugCompilationUnit
664 /// recorded in \c DebugScopeRegs.
665 ///
666 /// \returns \c std::nullopt when \p Scope names an emitted scope that has
667 /// not been recorded yet, or when no fallback compile unit is available.
668 std::optional<MCRegister>
669 resolveScope(const DIScope *Scope,
670 const DICompileUnit *FallbackCU = nullptr) const;
671
672 /// Emit \c DebugLexicalBlock for \p S, which must be a \c DILexicalBlock or
673 /// a \c DINamespace. A \c DILexicalBlock supplies Line/Column
674 /// from \c getLine()/getColumn(); a \c DINamespace has neither, so both are
675 /// emitted as 0, and its Name is appended as an extra \c OpString operand.
676 ///
677 /// \returns The result id register on success. Returns \c std::nullopt and
678 /// emits nothing if \c resolveScope returns no id for \c S->getScope().
679 std::optional<MCRegister>
680 emitDebugLexicalBlock(const DIScope *S, MCRegister VoidTypeReg,
681 MCRegister I32TypeReg, MCRegister ExtInstSetReg,
683
684 /// Return a cached \c DebugInlinedAt id for \p IA, or emit one (recursing
685 /// into \c IA->getInlinedAt() first for the optional Inlined operand, so
686 /// outer frames are always emitted before the inner frame that references
687 /// them). Must run after \c DebugScopeRegs is populated, since the Scope
688 /// operand is resolved through \c resolveScope. \c DebugInlinedAt is not in
689 /// the spec's in-block instruction list, so this is only ever called from
690 /// module-scope emission (\c emitNonSemanticGlobalDebugInfo), never from
691 /// per-instruction emission.
692 ///
693 /// \returns An invalid (default-constructed) \c MCRegister, and emits
694 /// nothing, if \p IA's Scope does not resolve.
695 MCRegister getOrEmitDebugInlinedAt(const DILocation *IA,
696 MCRegister VoidTypeReg,
697 MCRegister I32TypeReg,
698 MCRegister ExtInstSetReg,
700};
701
702} // namespace llvm
703
704#endif // LLVM_LIB_TARGET_SPIRV_SPIRVNONSEMANTICDEBUGHANDLER_H
This file defines the StringMap class.
unsigned uint64_t
BitTracker BT
This file defines the DenseMap class.
This file defines the DenseSet and SmallDenseSet classes.
IRTranslator LLVM IR MI
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
static NVPTX::Scope resolveScope(NVPTX::Scope S, const NVPTXSubtarget *T)
SI Fold Operands
This file implements a set that has insertion order iteration characteristics.
This file defines the SmallString class.
This file defines the SmallVector class.
Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:40
This class is intended to be used as a driving class for all asm writers.
Definition AsmPrinter.h:91
Basic type, like 'int' or 'float'.
A lightweight wrapper around an expression operand.
DWARF expression.
Base class for scope-like contexts.
Subprogram description. Uses SubclassData1.
Type array for a subprogram.
Base class for types.
Implements a dense probed hash-table based set.
Definition DenseSet.h:281
Instances of this class represent a single low-level machine instruction.
Definition MCInst.h:188
Wrapper class representing physical registers. Should be passed by value.
Definition MCRegister.h:41
DominatorTree Class - Concrete subclass of DominatorTreeBase that is used to compute a normal dominat...
Representation of each machine instruction.
This class implements a map that also provides access to all stored values in a deterministic order.
Definition MapVector.h:38
A Module instance is used to store all the information related to an LLVM module.
Definition Module.h:68
void beginInstruction(const MachineInstr *MI) override
Process beginning of an instruction.
void endModule() override
Emit all sections that should come after the content.
void emitNonSemanticDebugStrings(SPIRV::ModuleAnalysisInfo &MAI)
Emit OpString instructions for all NSDI file paths and basic type names into the debug section (secti...
void beginModule(Module *M) override
Collect compile-unit metadata from the module.
void endFunctionImpl(const MachineFunction *MF) override
void beginFunctionImpl(const MachineFunction *MF) override
void emitNonSemanticGlobalDebugInfo(SPIRV::ModuleAnalysisInfo &MAI)
Emit module-scope NSDI instructions (DebugSource, DebugCompilationUnit, DebugTypeBasic,...
void prepareModuleOutput(const SPIRVSubtarget &ST, SPIRV::ModuleAnalysisInfo &MAI)
Add SPV_KHR_non_semantic_info extension and NonSemantic.Shader.DebugInfo.100 ext inst set entry to MA...
void endInstruction() override
Process end of an instruction.
void notifyEntryLabelEmitted(const MachineFunction &MF)
Called after the synthesized entry OpLabel has been emitted.
A vector that has set insertion semantics.
Definition SetVector.h:57
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
Definition SmallString.h:26
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
StringMap - This is an unconventional map that is specialized for handling keys that are "strings",...
Definition StringMap.h:129
Represent a constant reference to a string, i.e.
Definition StringRef.h:56
LLVM Value Representation.
Definition Value.h:75
This is an optimization pass for GlobalISel generic memory operations.
DWARFExpression::Operation Op