Skip to content

Commit 7e0f2c0

Browse files
vmaksimosvenvh
andauthored
[SPIR-V] Reland Encode debug info producer in SPIR-V (#4082)
Fix OpModuleProcessed memory leak Original commit: KhronosGroup/SPIRV-LLVM-Translator@8f59b42 Co-authored-by: Sven van Haastregt <[email protected]>
1 parent 03155e7 commit 7e0f2c0

File tree

10 files changed

+134
-4
lines changed

10 files changed

+134
-4
lines changed

llvm-spirv/lib/SPIRV/LLVMToSPIRVDbgTran.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -497,6 +497,7 @@ LLVMToSPIRVDbgTran::transDbgCompilationUnit(const DICompileUnit *CU) {
497497
Ops[DWARFVersionIdx] = M->getDwarfVersion();
498498
Ops[SourceIdx] = getSource(CU)->getId();
499499
Ops[LanguageIdx] = CU->getSourceLanguage();
500+
BM->addModuleProcessed(SPIRVDebug::ProducerPrefix + CU->getProducer().str());
500501
// Cache CU in a member.
501502
SPIRVCU = static_cast<SPIRVExtInst *>(
502503
BM->addDebugInfo(SPIRVDebug::CompilationUnit, getVoidTy(), Ops));

llvm-spirv/lib/SPIRV/SPIRVToLLVMDbgTran.cpp

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -127,8 +127,9 @@ SPIRVToLLVMDbgTran::transCompileUnit(const SPIRVExtInst *DebugInst) {
127127
assert(Ops.size() == OperandCount && "Invalid number of operands");
128128
M->addModuleFlag(llvm::Module::Max, "Dwarf Version", Ops[DWARFVersionIdx]);
129129
unsigned SourceLang = Ops[LanguageIdx];
130-
CU = Builder.createCompileUnit(SourceLang, getFile(Ops[SourceIdx]), "spirv", false,
131-
"", 0);
130+
auto Producer = findModuleProducer();
131+
CU = Builder.createCompileUnit(SourceLang, getFile(Ops[SourceIdx]), Producer,
132+
false, "", 0);
132133
return CU;
133134
}
134135

@@ -1051,6 +1052,16 @@ SPIRVToLLVMDbgTran::SplitFileName::SplitFileName(const string &FileName) {
10511052
}
10521053
}
10531054

1055+
std::string SPIRVToLLVMDbgTran::findModuleProducer() {
1056+
for (const auto &I : BM->getModuleProcessedVec()) {
1057+
if (I->getProcessStr().find(SPIRVDebug::ProducerPrefix) !=
1058+
std::string::npos) {
1059+
return I->getProcessStr().substr(SPIRVDebug::ProducerPrefix.size());
1060+
}
1061+
}
1062+
return "spirv";
1063+
}
1064+
10541065
Optional<DIFile::ChecksumInfo<StringRef>>
10551066
SPIRVToLLVMDbgTran::ParseChecksum(StringRef Text) {
10561067
// Example of "Text" variable:

llvm-spirv/lib/SPIRV/SPIRVToLLVMDbgTran.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,7 @@ class SPIRVToLLVMDbgTran {
175175
return nullptr;
176176
}
177177
const std::string &getString(const SPIRVId Id);
178+
std::string findModuleProducer();
178179
Optional<DIFile::ChecksumInfo<StringRef>> ParseChecksum(StringRef Text);
179180
};
180181
} // namespace SPIRV

llvm-spirv/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
static const std::string ChecksumKindPrefx = {"//__CSK_"};
1011

1112
// clang-format off

llvm-spirv/lib/SPIRV/libSPIRV/SPIRVEntry.cpp

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

745+
void SPIRVModuleProcessed::validate() const {
746+
assert(WordCount == FixedWC + getSizeInWords(ProcessStr) &&
747+
"Incorrect word count in OpModuleProcessed");
748+
}
749+
750+
void SPIRVModuleProcessed::encode(spv_ostream &O) const {
751+
getEncoder(O) << ProcessStr;
752+
}
753+
754+
void SPIRVModuleProcessed::decode(std::istream &I) {
755+
getDecoder(I) >> ProcessStr;
756+
Module->addModuleProcessed(ProcessStr);
757+
}
758+
759+
std::string SPIRVModuleProcessed::getProcessStr() { return ProcessStr; }
760+
745761
} // namespace SPIRV

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

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

965+
class SPIRVModuleProcessed : public SPIRVEntryNoId<OpModuleProcessed> {
966+
public:
967+
SPIRVModuleProcessed(SPIRVModule *M, const std::string &Process)
968+
: SPIRVEntryNoId(M, FixedWC + getSizeInWords(Process)),
969+
ProcessStr(Process) {
970+
updateModuleVersion();
971+
}
972+
SPIRVModuleProcessed() { updateModuleVersion(); }
973+
_SPIRV_DCL_ENCDEC
974+
void validate() const override;
975+
SPIRVWord getRequiredSPIRVVersion() const override {
976+
return static_cast<SPIRVWord>(VersionNumber::SPIRV_1_1);
977+
}
978+
979+
std::string getProcessStr();
980+
981+
private:
982+
std::string ProcessStr;
983+
static const SPIRVWord FixedWC = 1;
984+
};
985+
965986
// ToDo: The following typedef's are place holders for SPIRV entity classes
966987
// to be implemented.
967988
// Each time a new class is implemented, remove the corresponding typedef.

llvm-spirv/lib/SPIRV/libSPIRV/SPIRVModule.cpp

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -305,6 +305,8 @@ class SPIRVModuleImpl : public SPIRVModule {
305305
SPIRVInstruction * = nullptr) override;
306306
SPIRVEntry *addDebugInfo(SPIRVWord, SPIRVType *TheType,
307307
const std::vector<SPIRVWord> &) override;
308+
SPIRVEntry *addModuleProcessed(const std::string &) override;
309+
std::vector<SPIRVModuleProcessed *> getModuleProcessedVec() override;
308310
SPIRVInstruction *addBinaryInst(Op, SPIRVType *, SPIRVValue *, SPIRVValue *,
309311
SPIRVBasicBlock *) override;
310312
SPIRVInstruction *addCallInst(SPIRVFunction *, const std::vector<SPIRVWord> &,
@@ -526,6 +528,7 @@ class SPIRVModuleImpl : public SPIRVModule {
526528
std::map<unsigned, SPIRVTypeInt *> IntTypeMap;
527529
std::map<unsigned, SPIRVConstant *> LiteralMap;
528530
std::vector<SPIRVExtInst *> DebugInstVec;
531+
std::vector<SPIRVModuleProcessed *> ModuleProcessedVec;
529532
SPIRVAliasInstMDVec AliasInstMDVec;
530533
SPIRVAliasInstMDMap AliasInstMDMap;
531534

@@ -541,6 +544,9 @@ SPIRVModuleImpl::~SPIRVModuleImpl() {
541544

542545
for (auto C : CapMap)
543546
delete C.second;
547+
548+
for (auto *M : ModuleProcessedVec)
549+
delete M;
544550
}
545551

546552
const std::shared_ptr<const SPIRVLine> &
@@ -1279,6 +1285,15 @@ SPIRVEntry *SPIRVModuleImpl::addDebugInfo(SPIRVWord InstId, SPIRVType *TheType,
12791285
ExtInstSetIds[getDebugInfoEIS()], InstId, Args));
12801286
}
12811287

1288+
SPIRVEntry *SPIRVModuleImpl::addModuleProcessed(const std::string &Process) {
1289+
ModuleProcessedVec.push_back(new SPIRVModuleProcessed(this, Process));
1290+
return ModuleProcessedVec.back();
1291+
}
1292+
1293+
std::vector<SPIRVModuleProcessed *> SPIRVModuleImpl::getModuleProcessedVec() {
1294+
return ModuleProcessedVec;
1295+
}
1296+
12821297
SPIRVInstruction *
12831298
SPIRVModuleImpl::addCallInst(SPIRVFunction *TheFunction,
12841299
const std::vector<SPIRVWord> &TheArguments,
@@ -1840,8 +1855,8 @@ spv_ostream &operator<<(spv_ostream &O, SPIRVModule &M) {
18401855
TopologicalSort TS(MI.TypeVec, MI.ConstVec, MI.VariableVec,
18411856
MI.ForwardPointerVec);
18421857

1843-
O << MI.MemberNameVec << MI.DecGroupVec << MI.DecorateSet << MI.GroupDecVec
1844-
<< MI.ForwardPointerVec << TS;
1858+
O << MI.MemberNameVec << MI.ModuleProcessedVec << MI.DecGroupVec
1859+
<< MI.DecorateSet << MI.GroupDecVec << MI.ForwardPointerVec << TS;
18451860

18461861
if (M.isAllowedToUseExtension(ExtensionID::SPV_INTEL_inline_assembly)) {
18471862
O << SPIRVNL() << MI.AsmTargetVec << MI.AsmVec;

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -306,6 +306,7 @@ class SPIRVModule {
306306
SPIRVInstruction * = nullptr) = 0;
307307
virtual SPIRVEntry *addDebugInfo(SPIRVWord, SPIRVType *,
308308
const std::vector<SPIRVWord> &) = 0;
309+
virtual SPIRVEntry *addModuleProcessed(const std::string &) = 0;
309310
virtual void addCapability(SPIRVCapabilityKind) = 0;
310311
template <typename T> void addCapabilities(const T &Caps) {
311312
for (auto I : Caps)
@@ -487,6 +488,8 @@ class SPIRVModule {
487488
return TranslationOpts.isGenArgNameMDEnabled();
488489
}
489490

491+
virtual std::vector<SPIRVModuleProcessed *> getModuleProcessedVec() = 0;
492+
490493
bool getSpecializationConstant(SPIRVWord SpecId, uint64_t &ConstValue) {
491494
return TranslationOpts.getSpecializationConstant(SpecId, ConstValue);
492495
}

llvm-spirv/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(DecorateId, 332)
298299
_SPIRV_OP(GroupNonUniformElect, 333)
299300
_SPIRV_OP(GroupNonUniformAll, 334)
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)