diff --git a/llvm-spirv/lib/SPIRV/LLVMToSPIRVDbgTran.cpp b/llvm-spirv/lib/SPIRV/LLVMToSPIRVDbgTran.cpp index e24b4d3ea192d..34221732b9e20 100644 --- a/llvm-spirv/lib/SPIRV/LLVMToSPIRVDbgTran.cpp +++ b/llvm-spirv/lib/SPIRV/LLVMToSPIRVDbgTran.cpp @@ -497,6 +497,7 @@ LLVMToSPIRVDbgTran::transDbgCompilationUnit(const DICompileUnit *CU) { Ops[DWARFVersionIdx] = M->getDwarfVersion(); Ops[SourceIdx] = getSource(CU)->getId(); Ops[LanguageIdx] = CU->getSourceLanguage(); + BM->addModuleProcessed(SPIRVDebug::ProducerPrefix + CU->getProducer().str()); // Cache CU in a member. SPIRVCU = static_cast( BM->addDebugInfo(SPIRVDebug::CompilationUnit, getVoidTy(), Ops)); diff --git a/llvm-spirv/lib/SPIRV/SPIRVToLLVMDbgTran.cpp b/llvm-spirv/lib/SPIRV/SPIRVToLLVMDbgTran.cpp index 3da6fd52f2abf..f53cb21a82cac 100644 --- a/llvm-spirv/lib/SPIRV/SPIRVToLLVMDbgTran.cpp +++ b/llvm-spirv/lib/SPIRV/SPIRVToLLVMDbgTran.cpp @@ -127,8 +127,9 @@ SPIRVToLLVMDbgTran::transCompileUnit(const SPIRVExtInst *DebugInst) { assert(Ops.size() == OperandCount && "Invalid number of operands"); M->addModuleFlag(llvm::Module::Max, "Dwarf Version", Ops[DWARFVersionIdx]); unsigned SourceLang = Ops[LanguageIdx]; - CU = Builder.createCompileUnit(SourceLang, getFile(Ops[SourceIdx]), "spirv", false, - "", 0); + auto Producer = findModuleProducer(); + CU = Builder.createCompileUnit(SourceLang, getFile(Ops[SourceIdx]), Producer, + false, "", 0); return CU; } @@ -1051,6 +1052,16 @@ SPIRVToLLVMDbgTran::SplitFileName::SplitFileName(const string &FileName) { } } +std::string SPIRVToLLVMDbgTran::findModuleProducer() { + for (const auto &I : BM->getModuleProcessedVec()) { + if (I->getProcessStr().find(SPIRVDebug::ProducerPrefix) != + std::string::npos) { + return I->getProcessStr().substr(SPIRVDebug::ProducerPrefix.size()); + } + } + return "spirv"; +} + Optional> SPIRVToLLVMDbgTran::ParseChecksum(StringRef Text) { // Example of "Text" variable: diff --git a/llvm-spirv/lib/SPIRV/SPIRVToLLVMDbgTran.h b/llvm-spirv/lib/SPIRV/SPIRVToLLVMDbgTran.h index d28997a61a31a..a95c99cb37d34 100644 --- a/llvm-spirv/lib/SPIRV/SPIRVToLLVMDbgTran.h +++ b/llvm-spirv/lib/SPIRV/SPIRVToLLVMDbgTran.h @@ -175,6 +175,7 @@ class SPIRVToLLVMDbgTran { return nullptr; } const std::string &getString(const SPIRVId Id); + std::string findModuleProducer(); Optional> ParseChecksum(StringRef Text); }; } // namespace SPIRV diff --git a/llvm-spirv/lib/SPIRV/libSPIRV/SPIRV.debug.h b/llvm-spirv/lib/SPIRV/libSPIRV/SPIRV.debug.h index b8f293f7224c2..f09d8cddf922b 100644 --- a/llvm-spirv/lib/SPIRV/libSPIRV/SPIRV.debug.h +++ b/llvm-spirv/lib/SPIRV/libSPIRV/SPIRV.debug.h @@ -6,6 +6,7 @@ namespace SPIRVDebug { const unsigned int DebugInfoVersion = 0x00010000; +static const std::string ProducerPrefix = {"Debug info producer: "}; static const std::string ChecksumKindPrefx = {"//__CSK_"}; // clang-format off diff --git a/llvm-spirv/lib/SPIRV/libSPIRV/SPIRVEntry.cpp b/llvm-spirv/lib/SPIRV/libSPIRV/SPIRVEntry.cpp index 82f48ca346522..2de4153099e5b 100644 --- a/llvm-spirv/lib/SPIRV/libSPIRV/SPIRVEntry.cpp +++ b/llvm-spirv/lib/SPIRV/libSPIRV/SPIRVEntry.cpp @@ -742,4 +742,20 @@ SPIRVType *SPIRVTypeStructContinuedINTEL::getMemberType(size_t I) const { return static_cast(SPIRVEntry::getEntry(Elements[I])); } +void SPIRVModuleProcessed::validate() const { + assert(WordCount == FixedWC + getSizeInWords(ProcessStr) && + "Incorrect word count in OpModuleProcessed"); +} + +void SPIRVModuleProcessed::encode(spv_ostream &O) const { + getEncoder(O) << ProcessStr; +} + +void SPIRVModuleProcessed::decode(std::istream &I) { + getDecoder(I) >> ProcessStr; + Module->addModuleProcessed(ProcessStr); +} + +std::string SPIRVModuleProcessed::getProcessStr() { return ProcessStr; } + } // namespace SPIRV diff --git a/llvm-spirv/lib/SPIRV/libSPIRV/SPIRVEntry.h b/llvm-spirv/lib/SPIRV/libSPIRV/SPIRVEntry.h index 9b75f407111ba..f03e777cfe110 100644 --- a/llvm-spirv/lib/SPIRV/libSPIRV/SPIRVEntry.h +++ b/llvm-spirv/lib/SPIRV/libSPIRV/SPIRVEntry.h @@ -962,6 +962,27 @@ template <> struct InstToContinued { constexpr static spv::Op OpCode = OpSpecConstantCompositeContinuedINTEL; }; +class SPIRVModuleProcessed : public SPIRVEntryNoId { +public: + SPIRVModuleProcessed(SPIRVModule *M, const std::string &Process) + : SPIRVEntryNoId(M, FixedWC + getSizeInWords(Process)), + ProcessStr(Process) { + updateModuleVersion(); + } + SPIRVModuleProcessed() { updateModuleVersion(); } + _SPIRV_DCL_ENCDEC + void validate() const override; + SPIRVWord getRequiredSPIRVVersion() const override { + return static_cast(VersionNumber::SPIRV_1_1); + } + + std::string getProcessStr(); + +private: + std::string ProcessStr; + static const SPIRVWord FixedWC = 1; +}; + // ToDo: The following typedef's are place holders for SPIRV entity classes // to be implemented. // Each time a new class is implemented, remove the corresponding typedef. diff --git a/llvm-spirv/lib/SPIRV/libSPIRV/SPIRVModule.cpp b/llvm-spirv/lib/SPIRV/libSPIRV/SPIRVModule.cpp index 27c08b27188eb..e72047a4b8ae7 100644 --- a/llvm-spirv/lib/SPIRV/libSPIRV/SPIRVModule.cpp +++ b/llvm-spirv/lib/SPIRV/libSPIRV/SPIRVModule.cpp @@ -305,6 +305,8 @@ class SPIRVModuleImpl : public SPIRVModule { SPIRVInstruction * = nullptr) override; SPIRVEntry *addDebugInfo(SPIRVWord, SPIRVType *TheType, const std::vector &) override; + SPIRVEntry *addModuleProcessed(const std::string &) override; + std::vector getModuleProcessedVec() override; SPIRVInstruction *addBinaryInst(Op, SPIRVType *, SPIRVValue *, SPIRVValue *, SPIRVBasicBlock *) override; SPIRVInstruction *addCallInst(SPIRVFunction *, const std::vector &, @@ -526,6 +528,7 @@ class SPIRVModuleImpl : public SPIRVModule { std::map IntTypeMap; std::map LiteralMap; std::vector DebugInstVec; + std::vector ModuleProcessedVec; SPIRVAliasInstMDVec AliasInstMDVec; SPIRVAliasInstMDMap AliasInstMDMap; @@ -541,6 +544,9 @@ SPIRVModuleImpl::~SPIRVModuleImpl() { for (auto C : CapMap) delete C.second; + + for (auto *M : ModuleProcessedVec) + delete M; } const std::shared_ptr & @@ -1279,6 +1285,15 @@ SPIRVEntry *SPIRVModuleImpl::addDebugInfo(SPIRVWord InstId, SPIRVType *TheType, ExtInstSetIds[getDebugInfoEIS()], InstId, Args)); } +SPIRVEntry *SPIRVModuleImpl::addModuleProcessed(const std::string &Process) { + ModuleProcessedVec.push_back(new SPIRVModuleProcessed(this, Process)); + return ModuleProcessedVec.back(); +} + +std::vector SPIRVModuleImpl::getModuleProcessedVec() { + return ModuleProcessedVec; +} + SPIRVInstruction * SPIRVModuleImpl::addCallInst(SPIRVFunction *TheFunction, const std::vector &TheArguments, @@ -1840,8 +1855,8 @@ spv_ostream &operator<<(spv_ostream &O, SPIRVModule &M) { TopologicalSort TS(MI.TypeVec, MI.ConstVec, MI.VariableVec, MI.ForwardPointerVec); - O << MI.MemberNameVec << MI.DecGroupVec << MI.DecorateSet << MI.GroupDecVec - << MI.ForwardPointerVec << TS; + O << MI.MemberNameVec << MI.ModuleProcessedVec << MI.DecGroupVec + << MI.DecorateSet << MI.GroupDecVec << MI.ForwardPointerVec << TS; if (M.isAllowedToUseExtension(ExtensionID::SPV_INTEL_inline_assembly)) { O << SPIRVNL() << MI.AsmTargetVec << MI.AsmVec; diff --git a/llvm-spirv/lib/SPIRV/libSPIRV/SPIRVModule.h b/llvm-spirv/lib/SPIRV/libSPIRV/SPIRVModule.h index a35e45fc1a231..21e25159531b8 100644 --- a/llvm-spirv/lib/SPIRV/libSPIRV/SPIRVModule.h +++ b/llvm-spirv/lib/SPIRV/libSPIRV/SPIRVModule.h @@ -306,6 +306,7 @@ class SPIRVModule { SPIRVInstruction * = nullptr) = 0; virtual SPIRVEntry *addDebugInfo(SPIRVWord, SPIRVType *, const std::vector &) = 0; + virtual SPIRVEntry *addModuleProcessed(const std::string &) = 0; virtual void addCapability(SPIRVCapabilityKind) = 0; template void addCapabilities(const T &Caps) { for (auto I : Caps) @@ -487,6 +488,8 @@ class SPIRVModule { return TranslationOpts.isGenArgNameMDEnabled(); } + virtual std::vector getModuleProcessedVec() = 0; + bool getSpecializationConstant(SPIRVWord SpecId, uint64_t &ConstValue) { return TranslationOpts.getSpecializationConstant(SpecId, ConstValue); } diff --git a/llvm-spirv/lib/SPIRV/libSPIRV/SPIRVOpCodeEnum.h b/llvm-spirv/lib/SPIRV/libSPIRV/SPIRVOpCodeEnum.h index 18f7c3bc679b1..df0242f177a75 100644 --- a/llvm-spirv/lib/SPIRV/libSPIRV/SPIRVOpCodeEnum.h +++ b/llvm-spirv/lib/SPIRV/libSPIRV/SPIRVOpCodeEnum.h @@ -294,6 +294,7 @@ _SPIRV_OP(AtomicFlagClear, 319) _SPIRV_OP(TypePipeStorage, 322) _SPIRV_OP(ConstantPipeStorage, 323) _SPIRV_OP(CreatePipeFromPipeStorage, 324) +_SPIRV_OP(ModuleProcessed, 330) _SPIRV_OP(DecorateId, 332) _SPIRV_OP(GroupNonUniformElect, 333) _SPIRV_OP(GroupNonUniformAll, 334) diff --git a/llvm-spirv/test/DebugInfo/DebugInfoProducer.ll b/llvm-spirv/test/DebugInfo/DebugInfoProducer.ll new file mode 100644 index 0000000000000..fa5536fa33870 --- /dev/null +++ b/llvm-spirv/test/DebugInfo/DebugInfoProducer.ll @@ -0,0 +1,60 @@ +; Test checks debug info of producer is preserved from LLVM IR to spirv +; and spirv to LLVM IR translation. + +; Original .cpp source: +; +; int main() { +; return 0; +; } + +; Command line: +; ./clang -cc1 -debug-info-kind=standalone -v s.cpp -S -emit-llvm -triple spir + +; RUN: llvm-as %s -o %t.bc +; RUN: llvm-spirv %t.bc -spirv-text -o - | FileCheck %s --check-prefix CHECK-SPIRV +; RUN: llvm-spirv %t.bc -o %t.spv +; RUN: llvm-spirv -r %t.spv -o %t.rev.bc +; RUN: llvm-dis %t.rev.bc -o %t.rev.ll +; RUN: FileCheck %s --input-file %t.rev.ll --check-prefix CHECK-LLVM + +; ModuleID = 's.bc' +source_filename = "s.cpp" +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" +target triple = "spir" + +; Function Attrs: noinline norecurse nounwind optnone +define i32 @main() #0 !dbg !8 { +entry: + %retval = alloca i32, align 4 + store i32 0, i32* %retval, align 4 + ret i32 0, !dbg !13 +} + +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" } + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!3, !4, !5, !6} +!opencl.used.extensions = !{!2} +!opencl.used.optional.core.features = !{!2} +!opencl.compiler.options = !{!2} +!llvm.ident = !{!7} + +; CHECK-LLVM: !DICompileUnit +; CHECK-LLVM-SAME: producer: "clang version 13.0.0 (https://github.com/llvm/llvm-project.git 16a50c9e642fd085e5ceb68c403b71b5b2e0607c)" +; CHECK-LLVM-NOT: producer: "spirv" +; CHECK-SPIRV: ModuleProcessed "Debug info producer: clang version 13.0.0 (https://github.com/llvm/llvm-project.git 16a50c9e642fd085e5ceb68c403b71b5b2e0607c)" + +!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) +!1 = !DIFile(filename: "", directory: "oneAPI") +!2 = !{} +!3 = !{i32 2, !"Debug Info Version", i32 3} +!4 = !{i32 1, !"wchar_size", i32 4} +!5 = !{i32 1, !"ThinLTO", i32 0} +!6 = !{i32 1, !"EnableSplitLTOUnit", i32 1} +!7 = !{!"clang version 13.0.0 (https://github.com/llvm/llvm-project.git 16a50c9e642fd085e5ceb68c403b71b5b2e0607c)"} +!8 = distinct !DISubprogram(name: "main", scope: !9, file: !9, line: 1, type: !10, scopeLine: 1, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !2) +!9 = !DIFile(filename: "s.cpp", directory: "C:\\") +!10 = !DISubroutineType(types: !11) +!11 = !{!12} +!12 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!13 = !DILocation(line: 2, column: 2, scope: !8)