Skip to content

Commit 5dad14d

Browse files
LU-JOHNsys-ce-bb
authored andcommitted
Support translation of DebugBuildIdentifier/DebugStoragePath instruction (#1977)
LLVM compileUnit dwoId is translated to/from DebugBuildIdentifier. LLVM compileUnit splitDebugFilename is translated to/from DebugStoragePath. Specification: https://github.com/KhronosGroup/SPIRV-Registry/blob/main/nonsemantic/NonSemantic.Shader.DebugInfo.100.asciidoc#DebugBuildIdentifier https://github.com/KhronosGroup/SPIRV-Registry/blob/main/nonsemantic/NonSemantic.Shader.DebugInfo.100.asciidoc#DebugStoragePath Original commit: KhronosGroup/SPIRV-LLVM-Translator@7ebb389
1 parent 02f5545 commit 5dad14d

File tree

7 files changed

+169
-2
lines changed

7 files changed

+169
-2
lines changed

llvm-spirv/lib/SPIRV/LLVMToSPIRVDbgTran.cpp

+50
Original file line numberDiff line numberDiff line change
@@ -546,6 +546,9 @@ SPIRVEntry *LLVMToSPIRVDbgTran::transDbgCompileUnit(const DICompileUnit *CU) {
546546
Ops[SPIRVDebugInfoVersionIdx] = SPIRVDebug::DebugInfoVersion;
547547
Ops[DWARFVersionIdx] = M->getDwarfVersion();
548548
Ops[SourceIdx] = getSource(CU)->getId();
549+
550+
generateBuildIdentifierAndStoragePath(CU);
551+
549552
auto DwarfLang =
550553
static_cast<llvm::dwarf::SourceLanguage>(CU->getSourceLanguage());
551554
Ops[LanguageIdx] =
@@ -1405,6 +1408,53 @@ SPIRVExtInst *LLVMToSPIRVDbgTran::getSource(const T *DIEntry) {
14051408
return Source;
14061409
}
14071410

1411+
void LLVMToSPIRVDbgTran::generateBuildIdentifierAndStoragePath(
1412+
const DICompileUnit *DIEntry) {
1413+
// get information from LLVM IR
1414+
auto BuildIdentifier = DIEntry->getDWOId();
1415+
const std::string BuildIdentifierString = std::to_string(BuildIdentifier);
1416+
const std::string StoragePath = DIEntry->getSplitDebugFilename().str();
1417+
1418+
using namespace SPIRVDebug::Operand;
1419+
1420+
if (BuildIdentifierInsn || StoragePathInsn) {
1421+
#ifndef NDEBUG
1422+
assert(BuildIdentifierInsn && StoragePathInsn &&
1423+
"BuildIdentifier and StoragePath instructions must both be created");
1424+
1425+
auto PreviousBuildIdentifierString =
1426+
BM->get<SPIRVString>(
1427+
BuildIdentifierInsn
1428+
->getArguments()[BuildIdentifier::IdentifierIdx])
1429+
->getStr();
1430+
assert(PreviousBuildIdentifierString == BuildIdentifierString &&
1431+
"New BuildIdentifier should match previous BuildIdentifier");
1432+
auto PreviousStoragePath =
1433+
BM->get<SPIRVString>(
1434+
StoragePathInsn->getArguments()[StoragePath::PathIdx])
1435+
->getStr();
1436+
assert(PreviousStoragePath == StoragePath &&
1437+
"New StoragePath should match previous StoragePath");
1438+
#endif
1439+
return;
1440+
}
1441+
1442+
// generate BuildIdentifier inst
1443+
SPIRVWordVec BuildIdentifierOps(BuildIdentifier::OperandCount);
1444+
BuildIdentifierOps[BuildIdentifier::IdentifierIdx] =
1445+
BM->getString(BuildIdentifierString)->getId();
1446+
BuildIdentifierOps[BuildIdentifier::FlagsIdx] =
1447+
BM->getLiteralAsConstant(1)->getId(); // Placeholder value for now
1448+
BuildIdentifierInsn = static_cast<SPIRVExtInst *>(BM->addDebugInfo(
1449+
SPIRVDebug::BuildIdentifier, getVoidTy(), BuildIdentifierOps));
1450+
1451+
// generate StoragePath inst
1452+
SPIRVWordVec StoragePathOps(StoragePath::OperandCount);
1453+
StoragePathOps[StoragePath::PathIdx] = BM->getString(StoragePath)->getId();
1454+
StoragePathInsn = static_cast<SPIRVExtInst *>(
1455+
BM->addDebugInfo(SPIRVDebug::StoragePath, getVoidTy(), StoragePathOps));
1456+
}
1457+
14081458
SPIRVEntry *LLVMToSPIRVDbgTran::transDbgFileType(const DIFile *F) {
14091459
return BM->getString(getFullPath(F));
14101460
}

llvm-spirv/lib/SPIRV/LLVMToSPIRVDbgTran.h

+7
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,10 @@ class LLVMToSPIRVDbgTran {
146146
template <class T> SPIRVExtInst *getSource(const T *DIEntry);
147147
SPIRVEntry *transDbgFileType(const DIFile *F);
148148

149+
// Generate instructions recording identifier and file where debug information
150+
// was split to
151+
void generateBuildIdentifierAndStoragePath(const DICompileUnit *DIEntry);
152+
149153
// Local Variables
150154
SPIRVEntry *transDbgLocalVariable(const DILocalVariable *Var);
151155

@@ -170,6 +174,9 @@ class LLVMToSPIRVDbgTran {
170174
std::unordered_map<const DICompileUnit *, SPIRVExtInst *> SPIRVCUMap;
171175
std::vector<const DbgVariableIntrinsic *> DbgDeclareIntrinsics;
172176
std::vector<const DbgVariableIntrinsic *> DbgValueIntrinsics;
177+
178+
inline static SPIRVExtInst *BuildIdentifierInsn{nullptr};
179+
inline static SPIRVExtInst *StoragePathInsn{nullptr};
173180
}; // class LLVMToSPIRVDbgTran
174181

175182
} // namespace SPIRV

llvm-spirv/lib/SPIRV/SPIRVToLLVMDbgTran.cpp

+53-2
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,18 @@ SPIRVToLLVMDbgTran::transCompilationUnit(const SPIRVExtInst *DebugInst,
217217
// TODO: Remove this workaround once we switch to NonSemantic.Shader.* debug
218218
// info by default
219219
auto Producer = findModuleProducer();
220+
assert(BuilderMap.size() != 0 && "No debug compile units");
221+
if (BuilderMap.size()==1)
222+
// Only initialize once
223+
setBuildIdentifierAndStoragePath();
224+
225+
if (!StoragePath.empty()) {
226+
return BuilderMap[DebugInst->getId()]->createCompileUnit(
227+
SourceLang, getFile(Ops[SourceIdx]), Producer, false, "", 0,
228+
StoragePath, DICompileUnit::DebugEmissionKind::FullDebug,
229+
BuildIdentifier);
230+
}
231+
220232
return BuilderMap[DebugInst->getId()]->createCompileUnit(
221233
SourceLang, getFile(Ops[SourceIdx]), Producer, false, Flags, 0);
222234
}
@@ -398,8 +410,8 @@ SPIRVToLLVMDbgTran::transTypeArrayDynamic(const SPIRVExtInst *DebugInst) {
398410
getDIBuilder(DebugInst).getOrCreateArray(Subscripts);
399411
size_t Size = getDerivedSizeInBits(BaseTy) * TotalCount;
400412

401-
auto TransOperand = [&](SPIRVWord Idx) -> PointerUnion<DIExpression *,
402-
DIVariable *> {
413+
auto TransOperand =
414+
[&](SPIRVWord Idx) -> PointerUnion<DIExpression *, DIVariable *> {
403415
if (!getDbgInst<SPIRVDebug::DebugInfoNone>(Ops[Idx])) {
404416
if (const auto *GV = getDbgInst<SPIRVDebug::GlobalVariable>(Ops[Idx]))
405417
return transDebugInst<DIGlobalVariable>(GV);
@@ -1344,6 +1356,8 @@ MDNode *SPIRVToLLVMDbgTran::transDebugInstImpl(const SPIRVExtInst *DebugInst) {
13441356
case SPIRVDebug::Operation: // To be translated with transExpression
13451357
case SPIRVDebug::Source: // To be used by other instructions
13461358
case SPIRVDebug::SourceContinued:
1359+
case SPIRVDebug::BuildIdentifier: // To be used by transCompilationUnit
1360+
case SPIRVDebug::StoragePath: // To be used by transCompilationUnit
13471361
return nullptr;
13481362

13491363
case SPIRVDebug::Expression:
@@ -1512,6 +1526,43 @@ DIFile *SPIRVToLLVMDbgTran::getFile(const SPIRVId SourceId) {
15121526
getStringSourceContinued(StrIdx, Source));
15131527
}
15141528

1529+
void SPIRVToLLVMDbgTran::setBuildIdentifierAndStoragePath() {
1530+
#ifndef NDEBUG
1531+
bool FoundBuildIdentifier{false};
1532+
bool FoundStoragePath{false};
1533+
#endif
1534+
1535+
for (SPIRVExtInst *EI : BM->getDebugInstVec()) {
1536+
if (EI->getExtOp() == SPIRVDebug::BuildIdentifier) {
1537+
using namespace SPIRVDebug::Operand::BuildIdentifier;
1538+
SPIRVWordVec BuildIdentifierArgs = EI->getArguments();
1539+
assert(BuildIdentifierArgs.size() == OperandCount &&
1540+
"Invalid number of operands");
1541+
assert(!FoundBuildIdentifier &&
1542+
"More than one BuildIdentifier instruction not allowed");
1543+
BuildIdentifier = strtoull(
1544+
getString(BuildIdentifierArgs[IdentifierIdx]).c_str(), NULL, 10);
1545+
#ifndef NDEBUG
1546+
FoundBuildIdentifier = true;
1547+
#endif
1548+
} else if (EI->getExtOp() == SPIRVDebug::StoragePath) {
1549+
using namespace SPIRVDebug::Operand::StoragePath;
1550+
SPIRVWordVec StoragePathArgs = EI->getArguments();
1551+
assert(StoragePathArgs.size() == OperandCount &&
1552+
"Invalid number of operands");
1553+
assert(!FoundStoragePath &&
1554+
"More than one StoragePath instruction not allowed");
1555+
StoragePath = getString(StoragePathArgs[PathIdx]);
1556+
#ifndef NDEBUG
1557+
FoundStoragePath = true;
1558+
#endif
1559+
}
1560+
}
1561+
assert(((FoundBuildIdentifier && FoundStoragePath) ||
1562+
(!FoundBuildIdentifier && !FoundStoragePath)) &&
1563+
"BuildIdentifier and StoragePath must both be set or both unset");
1564+
}
1565+
15151566
DIBuilder &SPIRVToLLVMDbgTran::getDIBuilder(const SPIRVExtInst *DebugInst) {
15161567
assert(BuilderMap.size() != 0 && "No debug compile units");
15171568
if (BuilderMap.size() == 1)

llvm-spirv/lib/SPIRV/SPIRVToLLVMDbgTran.h

+7
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ class SPIRVToLLVMDbgTran {
8989

9090
private:
9191
DIFile *getFile(const SPIRVId SourceId);
92+
9293
DIFile *
9394
getDIFile(const std::string &FileName,
9495
std::optional<DIFile::ChecksumInfo<StringRef>> CS = std::nullopt,
@@ -203,6 +204,12 @@ class SPIRVToLLVMDbgTran {
203204
const SPIRVExtInstSetKind);
204205
std::string findModuleProducer();
205206
std::optional<DIFile::ChecksumInfo<StringRef>> ParseChecksum(StringRef Text);
207+
208+
// BuildIdentifier and StoragePath must both be set or both unset.
209+
// If StoragePath is empty both variables are unset and not valid.
210+
uint64_t BuildIdentifier{0};
211+
std::string StoragePath{};
212+
void setBuildIdentifierAndStoragePath();
206213
};
207214
} // namespace SPIRV
208215

llvm-spirv/lib/SPIRV/libSPIRV/SPIRV.debug.h

+17
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,8 @@ enum Instruction {
5757
InstCount = 37,
5858
FunctionDefinition = 101,
5959
SourceContinued = 102,
60+
BuildIdentifier = 105,
61+
StoragePath = 106,
6062
EntryPoint = 107,
6163
Module = 200,
6264
TypeSubrange = 201,
@@ -321,6 +323,21 @@ enum {
321323
};
322324
}
323325

326+
namespace BuildIdentifier {
327+
enum {
328+
IdentifierIdx = 0,
329+
FlagsIdx = 1,
330+
OperandCount = 2
331+
};
332+
}
333+
334+
namespace StoragePath {
335+
enum {
336+
PathIdx = 0,
337+
OperandCount = 1
338+
};
339+
}
340+
324341
namespace TypeBasic {
325342
enum {
326343
NameIdx = 0,

llvm-spirv/lib/SPIRV/libSPIRV/SPIRVExtInst.h

+2
Original file line numberDiff line numberDiff line change
@@ -264,6 +264,8 @@ template <> inline void SPIRVMap<SPIRVDebugExtOpKind, std::string>::init() {
264264
add(SPIRVDebug::FunctionDefinition, "DebugFunctionDefinition");
265265
add(SPIRVDebug::SourceContinued, "DebugSourceContinued");
266266
add(SPIRVDebug::EntryPoint, "DebugEntryPoint");
267+
add(SPIRVDebug::BuildIdentifier, "DebugBuildIdentifier");
268+
add(SPIRVDebug::StoragePath, "DebugStoragePath");
267269
}
268270
SPIRV_DEF_NAMEMAP(SPIRVDebugExtOpKind, SPIRVDebugExtOpMap)
269271

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
; Test checks that dwoId and splitDebugFilename is preserved from LLVM IR to spirv
2+
; and spirv to LLVM IR translation.
3+
4+
; RUN: llvm-as %s -o %t.bc
5+
; RUN: llvm-spirv %t.bc -spirv-text -o - | FileCheck %s --check-prefix CHECK-SPIRV
6+
; RUN: llvm-spirv %t.bc -o %t.spv
7+
; RUN: llvm-spirv -r -emit-opaque-pointers %t.spv -o %t.rev.bc
8+
; RUN: llvm-dis %t.rev.bc -o %t.rev.ll
9+
; RUN: FileCheck %s --input-file %t.rev.ll --check-prefix CHECK-LLVM
10+
11+
; CHECK-SPIRV: String [[#stringA_id:]] "11111"
12+
; CHECK-SPIRV: String [[#stringA_sf:]] "debugA_info.dwo"
13+
; CHECK-SPIRV: [[#buildID_A:]] [[#]] DebugBuildIdentifier [[#stringA_id]]
14+
; CHECK-SPIRV: [[#storageID_A:]] [[#]] DebugStoragePath [[#stringA_sf]]
15+
16+
; CHECK-LLVM: !DICompileUnit
17+
; CHECK-LLVM-SAME: splitDebugFilename: "debugA_info.dwo"
18+
; CHECK-LLVM-SAME: dwoId: 11111
19+
; CHECK-LLVM: !DICompileUnit
20+
; CHECK-LLVM-SAME: splitDebugFilename: "debugA_info.dwo"
21+
; CHECK-LLVM-SAME: dwoId: 11111
22+
23+
!llvm.dbg.cu = !{!7, !0}
24+
!llvm.module.flags = !{!3, !4}
25+
26+
!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "Clang", isOptimized: false, runtimeVersion: 2, splitDebugFilename: "debugA_info.dwo", emissionKind: FullDebug, enums: !2, retainedTypes: !2, globals: !2, imports: !2, dwoId: 11111)
27+
!1 = !DIFile(filename: "<stdin>", directory: "/")
28+
!2 = !{}
29+
!3 = !{i32 2, !"Dwarf Version", i32 4}
30+
!4 = !{i32 2, !"Debug Info Version", i32 3}
31+
!5 = !{!6}
32+
!6 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
33+
!7 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "Clang", isOptimized: false, runtimeVersion: 2, splitDebugFilename: "debugA_info.dwo", dwoId: 11111, emissionKind: FullDebug, retainedTypes: !5)

0 commit comments

Comments
 (0)