Skip to content

Commit 601e4a5

Browse files
authored
[SPIRV] Encode debug info producer in SPIR-V (#924)
* [SPIRV] Encode debug info producer in SPIR-V This is a workaround to keep debug info producer information throughout the translation. We need it because the debug info specification doesn't provide means to carry this information.
1 parent e219ce0 commit 601e4a5

File tree

10 files changed

+130
-3
lines changed

10 files changed

+130
-3
lines changed

lib/SPIRV/LLVMToSPIRVDbgTran.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -478,6 +478,7 @@ LLVMToSPIRVDbgTran::transDbgCompilationUnit(const DICompileUnit *CU) {
478478
Ops[DWARFVersionIdx] = M->getDwarfVersion();
479479
Ops[SourceIdx] = getSource(CU)->getId();
480480
Ops[LanguageIdx] = CU->getSourceLanguage();
481+
BM->addModuleProcessed(SPIRVDebug::ProducerPrefix + CU->getProducer().str());
481482
// Cache CU in a member.
482483
SPIRVCU = static_cast<SPIRVExtInst *>(
483484
BM->addDebugInfo(SPIRVDebug::CompilationUnit, getVoidTy(), Ops));

lib/SPIRV/SPIRVToLLVMDbgTran.cpp

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,8 @@ SPIRVToLLVMDbgTran::transCompileUnit(const SPIRVExtInst *DebugInst) {
119119
SPIRVId FileId = Source->getArguments()[SPIRVDebug::Operand::Source::FileIdx];
120120
std::string File = getString(FileId);
121121
unsigned SourceLang = Ops[LanguageIdx];
122-
CU = Builder.createCompileUnit(SourceLang, getDIFile(File), "spirv", false,
122+
auto Producer = findModuleProducer();
123+
CU = Builder.createCompileUnit(SourceLang, getDIFile(File), Producer, false,
123124
"", 0);
124125
return CU;
125126
}
@@ -1000,4 +1001,14 @@ SPIRVToLLVMDbgTran::SplitFileName::SplitFileName(const string &FileName) {
10001001
}
10011002
}
10021003

1004+
std::string SPIRVToLLVMDbgTran::findModuleProducer() {
1005+
for (const auto &I : BM->getModuleProcessedVec()) {
1006+
if (I->getProcessStr().find(SPIRVDebug::ProducerPrefix) !=
1007+
std::string::npos) {
1008+
return I->getProcessStr().substr(SPIRVDebug::ProducerPrefix.size());
1009+
}
1010+
}
1011+
return "spirv";
1012+
}
1013+
10031014
} // namespace SPIRV

lib/SPIRV/SPIRVToLLVMDbgTran.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,7 @@ class SPIRVToLLVMDbgTran {
172172
return nullptr;
173173
}
174174
const std::string &getString(const SPIRVId Id);
175+
std::string findModuleProducer();
175176
};
176177
} // namespace SPIRV
177178

lib/SPIRV/libSPIRV/SPIRV.debug.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
namespace SPIRVDebug {
77

88
const unsigned int DebugInfoVersion = 0x00010000;
9+
static const std::string ProducerPrefix = {"Debug info producer: "};
910

1011
// clang-format off
1112

lib/SPIRV/libSPIRV/SPIRVEntry.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -679,4 +679,20 @@ SPIRVType *SPIRVTypeStructContinuedINTEL::getMemberType(size_t I) const {
679679
return static_cast<SPIRVType *>(SPIRVEntry::getEntry(Elements[I]));
680680
}
681681

682+
void SPIRVModuleProcessed::validate() const {
683+
assert(WordCount == FixedWC + getSizeInWords(ProcessStr) &&
684+
"Incorrect word count in OpModuleProcessed");
685+
}
686+
687+
void SPIRVModuleProcessed::encode(spv_ostream &O) const {
688+
getEncoder(O) << ProcessStr;
689+
}
690+
691+
void SPIRVModuleProcessed::decode(std::istream &I) {
692+
getDecoder(I) >> ProcessStr;
693+
Module->addModuleProcessed(ProcessStr);
694+
}
695+
696+
std::string SPIRVModuleProcessed::getProcessStr() { return ProcessStr; }
697+
682698
} // namespace SPIRV

lib/SPIRV/libSPIRV/SPIRVEntry.h

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -950,6 +950,27 @@ template <> struct InstToContinued<OpSpecConstantComposite> {
950950
constexpr static spv::Op OpCode = OpSpecConstantCompositeContinuedINTEL;
951951
};
952952

953+
class SPIRVModuleProcessed : public SPIRVEntryNoId<OpModuleProcessed> {
954+
public:
955+
SPIRVModuleProcessed(SPIRVModule *M, const std::string &Process)
956+
: SPIRVEntryNoId(M, FixedWC + getSizeInWords(Process)),
957+
ProcessStr(Process) {
958+
updateModuleVersion();
959+
}
960+
SPIRVModuleProcessed() { updateModuleVersion(); }
961+
_SPIRV_DCL_ENCDEC
962+
void validate() const override;
963+
SPIRVWord getRequiredSPIRVVersion() const override {
964+
return static_cast<SPIRVWord>(VersionNumber::SPIRV_1_1);
965+
}
966+
967+
std::string getProcessStr();
968+
969+
private:
970+
std::string ProcessStr;
971+
static const SPIRVWord FixedWC = 1;
972+
};
973+
953974
// ToDo: The following typedef's are place holders for SPIRV entity classes
954975
// to be implemented.
955976
// Each time a new class is implemented, remove the corresponding typedef.

lib/SPIRV/libSPIRV/SPIRVModule.cpp

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -304,6 +304,8 @@ class SPIRVModuleImpl : public SPIRVModule {
304304
SPIRVInstruction * = nullptr) override;
305305
SPIRVEntry *addDebugInfo(SPIRVWord, SPIRVType *TheType,
306306
const std::vector<SPIRVWord> &) override;
307+
SPIRVEntry *addModuleProcessed(const std::string &) override;
308+
std::vector<SPIRVModuleProcessed *> getModuleProcessedVec() override;
307309
SPIRVInstruction *addBinaryInst(Op, SPIRVType *, SPIRVValue *, SPIRVValue *,
308310
SPIRVBasicBlock *) override;
309311
SPIRVInstruction *addCallInst(SPIRVFunction *, const std::vector<SPIRVWord> &,
@@ -514,6 +516,7 @@ class SPIRVModuleImpl : public SPIRVModule {
514516
std::map<unsigned, SPIRVTypeInt *> IntTypeMap;
515517
std::map<unsigned, SPIRVConstant *> LiteralMap;
516518
std::vector<SPIRVExtInst *> DebugInstVec;
519+
std::vector<SPIRVModuleProcessed *> ModuleProcessedVec;
517520

518521
void layoutEntry(SPIRVEntry *Entry);
519522
};
@@ -1283,6 +1286,15 @@ SPIRVEntry *SPIRVModuleImpl::addDebugInfo(SPIRVWord InstId, SPIRVType *TheType,
12831286
ExtInstSetIds[getDebugInfoEIS()], InstId, Args));
12841287
}
12851288

1289+
SPIRVEntry *SPIRVModuleImpl::addModuleProcessed(const std::string &Process) {
1290+
ModuleProcessedVec.push_back(new SPIRVModuleProcessed(this, Process));
1291+
return ModuleProcessedVec.back();
1292+
}
1293+
1294+
std::vector<SPIRVModuleProcessed *> SPIRVModuleImpl::getModuleProcessedVec() {
1295+
return ModuleProcessedVec;
1296+
}
1297+
12861298
SPIRVInstruction *
12871299
SPIRVModuleImpl::addCallInst(SPIRVFunction *TheFunction,
12881300
const std::vector<SPIRVWord> &TheArguments,
@@ -1759,8 +1771,8 @@ spv_ostream &operator<<(spv_ostream &O, SPIRVModule &M) {
17591771
M.getEntry(I)->encodeName(O);
17601772
}
17611773

1762-
O << MI.MemberNameVec << MI.DecGroupVec << MI.DecorateSet << MI.GroupDecVec
1763-
<< MI.ForwardPointerVec
1774+
O << MI.MemberNameVec << MI.ModuleProcessedVec << MI.DecGroupVec
1775+
<< MI.DecorateSet << MI.GroupDecVec << MI.ForwardPointerVec
17641776
<< TopologicalSort(MI.TypeVec, MI.ConstVec, MI.VariableVec,
17651777
MI.ForwardPointerVec);
17661778

lib/SPIRV/libSPIRV/SPIRVModule.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -303,6 +303,7 @@ class SPIRVModule {
303303
SPIRVInstruction * = nullptr) = 0;
304304
virtual SPIRVEntry *addDebugInfo(SPIRVWord, SPIRVType *,
305305
const std::vector<SPIRVWord> &) = 0;
306+
virtual SPIRVEntry *addModuleProcessed(const std::string &) = 0;
306307
virtual void addCapability(SPIRVCapabilityKind) = 0;
307308
template <typename T> void addCapabilities(const T &Caps) {
308309
for (auto I : Caps)
@@ -478,6 +479,8 @@ class SPIRVModule {
478479
return TranslationOpts.isGenArgNameMDEnabled();
479480
}
480481

482+
virtual std::vector<SPIRVModuleProcessed *> getModuleProcessedVec() = 0;
483+
481484
bool getSpecializationConstant(SPIRVWord SpecId, uint64_t &ConstValue) {
482485
return TranslationOpts.getSpecializationConstant(SpecId, ConstValue);
483486
}

lib/SPIRV/libSPIRV/SPIRVOpCodeEnum.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -294,6 +294,7 @@ _SPIRV_OP(AtomicFlagClear, 319)
294294
_SPIRV_OP(TypePipeStorage, 322)
295295
_SPIRV_OP(ConstantPipeStorage, 323)
296296
_SPIRV_OP(CreatePipeFromPipeStorage, 324)
297+
_SPIRV_OP(ModuleProcessed, 330)
297298
_SPIRV_OP(GroupNonUniformElect, 333)
298299
_SPIRV_OP(GroupNonUniformAll, 334)
299300
_SPIRV_OP(GroupNonUniformAny, 335)

test/DebugInfo/DebugInfoProducer.ll

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
; Test checks debug info of producer is preserved from LLVM IR to spirv
2+
; and spirv to LLVM IR translation.
3+
4+
; Original .cpp source:
5+
;
6+
; int main() {
7+
; return 0;
8+
; }
9+
10+
; Command line:
11+
; ./clang -cc1 -debug-info-kind=standalone -v s.cpp -S -emit-llvm -triple spir
12+
13+
; RUN: llvm-as %s -o %t.bc
14+
; RUN: llvm-spirv %t.bc -spirv-text -o - | FileCheck %s --check-prefix CHECK-SPIRV
15+
; RUN: llvm-spirv %t.bc -o %t.spv
16+
; RUN: llvm-spirv -r %t.spv -o %t.rev.bc
17+
; RUN: llvm-dis %t.rev.bc -o %t.rev.ll
18+
; RUN: FileCheck %s --input-file %t.rev.ll --check-prefix CHECK-LLVM
19+
20+
; ModuleID = 's.bc'
21+
source_filename = "s.cpp"
22+
target datalayout = "e-p:32:32-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-n8:16:32:64"
23+
target triple = "spir"
24+
25+
; Function Attrs: noinline norecurse nounwind optnone
26+
define i32 @main() #0 !dbg !8 {
27+
entry:
28+
%retval = alloca i32, align 4
29+
store i32 0, i32* %retval, align 4
30+
ret i32 0, !dbg !13
31+
}
32+
33+
attributes #0 = { noinline norecurse nounwind optnone "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "frame-pointer"="none" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }
34+
35+
!llvm.dbg.cu = !{!0}
36+
!llvm.module.flags = !{!3, !4, !5, !6}
37+
!opencl.used.extensions = !{!2}
38+
!opencl.used.optional.core.features = !{!2}
39+
!opencl.compiler.options = !{!2}
40+
!llvm.ident = !{!7}
41+
42+
; CHECK-LLVM: !DICompileUnit
43+
; CHECK-LLVM-SAME: producer: "clang version 13.0.0 (https://github.com/llvm/llvm-project.git 16a50c9e642fd085e5ceb68c403b71b5b2e0607c)"
44+
; CHECK-LLVM-NOT: producer: "spirv"
45+
; CHECK-SPIRV: ModuleProcessed "Debug info producer: clang version 13.0.0 (https://github.com/llvm/llvm-project.git 16a50c9e642fd085e5ceb68c403b71b5b2e0607c)"
46+
47+
!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !1, producer: "clang version 13.0.0 (https://github.com/llvm/llvm-project.git 16a50c9e642fd085e5ceb68c403b71b5b2e0607c)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, nameTableKind: None)
48+
!1 = !DIFile(filename: "<stdin>", directory: "oneAPI")
49+
!2 = !{}
50+
!3 = !{i32 2, !"Debug Info Version", i32 3}
51+
!4 = !{i32 1, !"wchar_size", i32 4}
52+
!5 = !{i32 1, !"ThinLTO", i32 0}
53+
!6 = !{i32 1, !"EnableSplitLTOUnit", i32 1}
54+
!7 = !{!"clang version 13.0.0 (https://github.com/llvm/llvm-project.git 16a50c9e642fd085e5ceb68c403b71b5b2e0607c)"}
55+
!8 = distinct !DISubprogram(name: "main", scope: !9, file: !9, line: 1, type: !10, scopeLine: 1, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !2)
56+
!9 = !DIFile(filename: "s.cpp", directory: "C:\\")
57+
!10 = !DISubroutineType(types: !11)
58+
!11 = !{!12}
59+
!12 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
60+
!13 = !DILocation(line: 2, column: 2, scope: !8)

0 commit comments

Comments
 (0)