Skip to content

Commit aabcaf8

Browse files
authored
[DebugInfo] Support translation of DebugSourceContinued (#1993)
Max length of SPIRV instruction is 65535 words by specification. DebugSourceContinued helps to overcome the limitation and specify full source code text by continuing the string from the previous DebugSource(Continued)instruction. Spec: https://github.com/KhronosGroup/SPIRV-Registry/blob/main/nonsemantic/NonSemantic.Shader.DebugInfo.100.asciidoc#DebugSourceContinued
1 parent d9afed4 commit aabcaf8

File tree

10 files changed

+180
-23
lines changed

10 files changed

+180
-23
lines changed

lib/SPIRV/LLVMToSPIRVDbgTran.cpp

Lines changed: 34 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1343,17 +1343,44 @@ SPIRVExtInst *LLVMToSPIRVDbgTran::getSource(const T *DIEntry) {
13431343
return It->second;
13441344

13451345
using namespace SPIRVDebug::Operand::Source;
1346-
SPIRVWordVec Ops(OperandCount);
1346+
SPIRVWordVec Ops(MinOperandCount);
13471347
Ops[FileIdx] = BM->getString(FileName)->getId();
13481348
DIFile *F = DIEntry ? DIEntry->getFile() : nullptr;
1349-
if (F && F->getRawChecksum()) {
1349+
1350+
if (F && F->getRawChecksum() && !isNonSemanticDebugInfo()) {
13501351
auto CheckSum = F->getChecksum().value();
1351-
Ops[TextIdx] = BM->getString("//__" + CheckSum.getKindAsString().str() +
1352-
":" + CheckSum.Value.str())
1353-
->getId();
1354-
} else {
1355-
Ops[TextIdx] = getDebugInfoNone()->getId();
1352+
Ops.push_back(BM->getString("//__" + CheckSum.getKindAsString().str() +
1353+
":" + CheckSum.Value.str())
1354+
->getId());
13561355
}
1356+
1357+
if (F && F->getRawSource() && isNonSemanticDebugInfo()) {
1358+
std::string Str = F->getSource().value().str();
1359+
constexpr size_t MaxNumWords =
1360+
MaxWordCount - 2 /*Fixed WC for SPIRVString*/;
1361+
constexpr size_t MaxStrSize = MaxNumWords * 4 - 1;
1362+
const size_t NumWords = getSizeInWords(Str);
1363+
1364+
Ops.push_back(BM->getString(Str.substr(0, MaxStrSize))->getId());
1365+
SPIRVExtInst *Source = static_cast<SPIRVExtInst *>(
1366+
BM->addDebugInfo(SPIRVDebug::Source, getVoidTy(), Ops));
1367+
FileMap[FileName] = Source;
1368+
Str.erase(0, MaxStrSize);
1369+
1370+
// No need to generate source continued instructions
1371+
if (NumWords < MaxNumWords)
1372+
return Source;
1373+
1374+
uint64_t NumOfContinuedInstructions =
1375+
NumWords / MaxNumWords - 1 + (NumWords % MaxNumWords ? 1 : 0);
1376+
for (uint64_t J = 0; J < NumOfContinuedInstructions; J++) {
1377+
SPIRVWord Op = BM->getString(Str.substr(0, MaxStrSize))->getId();
1378+
BM->addDebugInfo(SPIRVDebug::SourceContinued, getVoidTy(), {Op});
1379+
Str.erase(0, MaxStrSize);
1380+
}
1381+
return Source;
1382+
}
1383+
13571384
SPIRVExtInst *Source = static_cast<SPIRVExtInst *>(
13581385
BM->addDebugInfo(SPIRVDebug::Source, getVoidTy(), Ops));
13591386
FileMap[FileName] = Source;

lib/SPIRV/SPIRVToLLVMDbgTran.cpp

Lines changed: 34 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -75,16 +75,17 @@ void SPIRVToLLVMDbgTran::addDbgInfoVersion() {
7575
DEBUG_METADATA_VERSION);
7676
}
7777

78-
DIFile *SPIRVToLLVMDbgTran::getDIFile(
79-
const std::string &FileName,
80-
std::optional<DIFile::ChecksumInfo<StringRef>> CS) {
78+
DIFile *
79+
SPIRVToLLVMDbgTran::getDIFile(const std::string &FileName,
80+
std::optional<DIFile::ChecksumInfo<StringRef>> CS,
81+
std::optional<StringRef> Source) {
8182
return getOrInsert(FileMap, FileName, [=]() {
8283
SplitFileName Split(FileName);
8384
// Use the first builder from the map to crete DIFile since it's
8485
// relations with other debug metadata is not going through DICompileUnit
8586
if (!Split.BaseName.empty())
8687
return BuilderMap.begin()->second->createFile(Split.BaseName, Split.Path,
87-
CS);
88+
CS, Source);
8889
return static_cast<DIFile *>(nullptr);
8990
});
9091
}
@@ -134,6 +135,19 @@ const std::string &SPIRVToLLVMDbgTran::getString(const SPIRVId Id) {
134135
return String->getStr();
135136
}
136137

138+
const std::string
139+
SPIRVToLLVMDbgTran::getStringContinued(const SPIRVId Id,
140+
SPIRVExtInst *DebugInst) {
141+
std::string Str = BM->get<SPIRVString>(Id)->getStr();
142+
using namespace SPIRVDebug::Operand::SourceContinued;
143+
for (auto *I : DebugInst->getContinuedInstructions()) {
144+
std::string TmpStr =
145+
BM->get<SPIRVString>(I->getArguments()[TextIdx])->getStr();
146+
Str.append(TmpStr);
147+
}
148+
return Str;
149+
}
150+
137151
void SPIRVToLLVMDbgTran::transDbgInfo(const SPIRVValue *SV, Value *V) {
138152
// A constant sampler does not have a corresponding SPIRVInstruction.
139153
if (SV->getOpCode() == OpConstantSampler)
@@ -1327,6 +1341,7 @@ MDNode *SPIRVToLLVMDbgTran::transDebugInstImpl(const SPIRVExtInst *DebugInst) {
13271341

13281342
case SPIRVDebug::Operation: // To be translated with transExpression
13291343
case SPIRVDebug::Source: // To be used by other instructions
1344+
case SPIRVDebug::SourceContinued:
13301345
return nullptr;
13311346

13321347
case SPIRVDebug::Expression:
@@ -1458,12 +1473,21 @@ DIFile *SPIRVToLLVMDbgTran::getFile(const SPIRVId SourceId) {
14581473
assert(Source->getExtOp() == SPIRVDebug::Source &&
14591474
"DebugSource instruction is expected");
14601475
SPIRVWordVec SourceArgs = Source->getArguments();
1461-
assert(SourceArgs.size() == OperandCount && "Invalid number of operands");
1462-
std::string ChecksumStr =
1463-
getDbgInst<SPIRVDebug::DebugInfoNone>(SourceArgs[TextIdx])
1464-
? ""
1465-
: getString(SourceArgs[TextIdx]);
1466-
return getDIFile(getString(SourceArgs[FileIdx]), ParseChecksum(ChecksumStr));
1476+
assert(SourceArgs.size() >= MinOperandCount && "Invalid number of operands");
1477+
if (SourceArgs.size() == MinOperandCount)
1478+
return getDIFile(getString(SourceArgs[FileIdx]));
1479+
1480+
if (!isNonSemanticDebugInfo(Source->getExtSetKind())) {
1481+
std::string ChecksumStr =
1482+
getDbgInst<SPIRVDebug::DebugInfoNone>(SourceArgs[TextIdx])
1483+
? ""
1484+
: getString(SourceArgs[TextIdx]);
1485+
return getDIFile(getString(SourceArgs[FileIdx]),
1486+
ParseChecksum(ChecksumStr));
1487+
}
1488+
1489+
return getDIFile(getString(SourceArgs[FileIdx]), std::nullopt,
1490+
getStringContinued(SourceArgs[TextIdx], Source));
14671491
}
14681492

14691493
DIBuilder &SPIRVToLLVMDbgTran::getDIBuilder(const SPIRVExtInst *DebugInst) {

lib/SPIRV/SPIRVToLLVMDbgTran.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,8 @@ class SPIRVToLLVMDbgTran {
9191
DIFile *getFile(const SPIRVId SourceId);
9292
DIFile *
9393
getDIFile(const std::string &FileName,
94-
std::optional<DIFile::ChecksumInfo<StringRef>> CS = std::nullopt);
94+
std::optional<DIFile::ChecksumInfo<StringRef>> CS = std::nullopt,
95+
std::optional<StringRef> Source = std::nullopt);
9596
DIFile *getDIFile(const SPIRVEntry *E);
9697
unsigned getLineNo(const SPIRVEntry *E);
9798

@@ -195,6 +196,8 @@ class SPIRVToLLVMDbgTran {
195196
return nullptr;
196197
}
197198
const std::string &getString(const SPIRVId Id);
199+
const std::string getStringContinued(const SPIRVId Id,
200+
SPIRVExtInst *DebugInst);
198201
SPIRVWord getConstantValueOrLiteral(const std::vector<SPIRVWord> &,
199202
const SPIRVWord,
200203
const SPIRVExtInstSetKind);

lib/SPIRV/libSPIRV/SPIRV.debug.h

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ enum Instruction {
5555
ModuleINTEL = 36,
5656
InstCount = 37,
5757
FunctionDefinition = 101,
58+
SourceContinued = 102,
5859
EntryPoint = 107,
5960
Module = 200,
6061
TypeSubrange = 201,
@@ -302,9 +303,9 @@ enum {
302303

303304
namespace Source {
304305
enum {
305-
FileIdx = 0,
306-
TextIdx = 1,
307-
OperandCount = 2
306+
FileIdx = 0,
307+
TextIdx = 1,
308+
MinOperandCount = 1
308309
};
309310
}
310311

@@ -573,6 +574,13 @@ enum {
573574
};
574575
}
575576

577+
namespace SourceContinued {
578+
enum {
579+
TextIdx = 0,
580+
OperandCount = 1
581+
};
582+
}
583+
576584
namespace EntryPoint {
577585
enum {
578586
EntryPointIdx = 0,

lib/SPIRV/libSPIRV/SPIRVExtInst.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -262,6 +262,7 @@ template <> inline void SPIRVMap<SPIRVDebugExtOpKind, std::string>::init() {
262262
add(SPIRVDebug::Expression, "DebugExpression");
263263
add(SPIRVDebug::Operation, "DebugOperation");
264264
add(SPIRVDebug::FunctionDefinition, "DebugFunctionDefinition");
265+
add(SPIRVDebug::SourceContinued, "DebugSourceContinued");
265266
add(SPIRVDebug::EntryPoint, "DebugEntryPoint");
266267
}
267268
SPIRV_DEF_NAMEMAP(SPIRVDebugExtOpKind, SPIRVDebugExtOpMap)

lib/SPIRV/libSPIRV/SPIRVInstruction.h

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1758,6 +1758,14 @@ class SPIRVExtInst : public SPIRVFunctionCallGeneric<OpExtInst, 5> {
17581758

17591759
SPIRVExtInstSetKind getExtSetKind() const { return ExtSetKind; }
17601760

1761+
void addContinuedInstruction(SPIRVExtInst *Inst) {
1762+
ContinuedInstructions.push_back(Inst);
1763+
}
1764+
1765+
std::vector<SPIRVExtInst *> getContinuedInstructions() {
1766+
return ContinuedInstructions;
1767+
}
1768+
17611769
void setExtSetKindById() {
17621770
assert(Module && "Invalid module");
17631771
ExtSetKind = Module->getBuiltinSet(ExtSetId);
@@ -1809,7 +1817,17 @@ class SPIRVExtInst : public SPIRVFunctionCallGeneric<OpExtInst, 5> {
18091817
assert(0 && "not supported");
18101818
getDecoder(I) >> ExtOp;
18111819
}
1812-
getDecoder(I) >> Args;
1820+
SPIRVDecoder Decoder = getDecoder(I);
1821+
Decoder >> Args;
1822+
1823+
if (ExtSetKind == SPIRVEIS_NonSemantic_Shader_DebugInfo_100 ||
1824+
ExtSetKind == SPIRVEIS_NonSemantic_Shader_DebugInfo_200) {
1825+
if (getExtOp() == SPIRVDebug::Instruction::Source) {
1826+
for (SPIRVEntry *E : Decoder.getSourceContinuedInstructions()) {
1827+
addContinuedInstruction(static_cast<SPIRVExtInst *>(E));
1828+
}
1829+
}
1830+
}
18131831
}
18141832
void validate() const override {
18151833
SPIRVFunctionCallGeneric::validate();
@@ -1865,6 +1883,7 @@ class SPIRVExtInst : public SPIRVFunctionCallGeneric<OpExtInst, 5> {
18651883
SPIRVDebugExtOpKind ExtOpDebug;
18661884
NonSemanticAuxDataOpKind ExtOpNonSemanticAuxData;
18671885
};
1886+
std::vector<SPIRVExtInst *> ContinuedInstructions;
18681887
};
18691888

18701889
class SPIRVCompositeConstruct : public SPIRVInstruction {

lib/SPIRV/libSPIRV/SPIRVStream.cpp

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
#include "SPIRVStream.h"
4040
#include "SPIRVDebug.h"
4141
#include "SPIRVFunction.h"
42+
#include "SPIRVInstruction.h"
4243
#include "SPIRVNameMapEnum.h"
4344
#include "SPIRVOpCode.h"
4445

@@ -332,4 +333,25 @@ SPIRVDecoder::getContinuedInstructions(const spv::Op ContinuedOpCode) {
332333
return ContinuedInst;
333334
}
334335

336+
std::vector<SPIRVEntry *> SPIRVDecoder::getSourceContinuedInstructions() {
337+
std::vector<SPIRVEntry *> ContinuedInst;
338+
std::streampos Pos = IS.tellg(); // remember position
339+
getWordCountAndOpCode();
340+
while (OpCode == OpExtInst) {
341+
SPIRVEntry *Entry = getEntry();
342+
assert(Entry && "Failed to decode entry! Invalid instruction!");
343+
SPIRVExtInst *Inst = static_cast<SPIRVExtInst *>(Entry);
344+
if (Inst->getExtOp() != SPIRVDebug::Instruction::SourceContinued) {
345+
IS.seekg(Pos); // restore position
346+
return ContinuedInst;
347+
}
348+
M.add(Entry);
349+
ContinuedInst.push_back(Entry);
350+
Pos = IS.tellg();
351+
getWordCountAndOpCode();
352+
}
353+
IS.seekg(Pos); // restore position
354+
return ContinuedInst;
355+
}
356+
335357
} // namespace SPIRV

lib/SPIRV/libSPIRV/SPIRVStream.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ class SPIRVDecoder {
7878
void ignoreInstruction();
7979
std::vector<SPIRVEntry *>
8080
getContinuedInstructions(const spv::Op ContinuedOpCode);
81+
std::vector<SPIRVEntry *> getSourceContinuedInstructions();
8182

8283
std::istream &IS;
8384
SPIRVModule &M;

test/DebugInfo/NonSemantic/DebugSourceContinued.ll

Lines changed: 52 additions & 0 deletions
Large diffs are not rendered by default.

test/DebugInfo/NonSemantic/Shader200/FortranArray.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@
77
; RUN: llvm-dis %t.rev.bc -o - | FileCheck %s --check-prefix=CHECK-LLVM
88

99

10-
; CHECK-SPIRV: [[#None:]] [[#]] DebugInfoNone
1110
; CHECK-SPIRV: [[#CompUnit:]] [[#]] DebugCompilationUnit
11+
; CHECK-SPIRV: [[#None:]] [[#]] DebugInfoNone
1212
; CHECK-SPIRV: [[#EntryFunc:]] [[#]] DebugFunction
1313
; CHECK-SPIRV: [[#BaseTy:]] [[#]] DebugTypeBasic
1414
; CHECK-SPIRV: [[#Subrange:]] [[#]] DebugTypeSubrange

0 commit comments

Comments
 (0)