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