From 5cd325159e0be34195f23125d9efa4ea97f19062 Mon Sep 17 00:00:00 2001 From: "Sidorov, Dmitry" Date: Tue, 23 Jan 2024 07:00:11 -0800 Subject: [PATCH] [DebugInfo] Fix instruction enumeration for template parameter These two opcodes were mistakenly swapped when they were originally added, at least according to the DebugInfo, OpenCL.DebugInfo.100, and NonSemantic.Shader.DebugInfo.100 extended instruction sets. This might break existing third-party SPIR-V translators if they are accommodating this bug, mistakenly or otherwise. Original author: Fraser Cormack --- lib/SPIRV/SPIRVToLLVMDbgTran.cpp | 21 ++++++-- lib/SPIRV/SPIRVToLLVMDbgTran.h | 1 + lib/SPIRV/libSPIRV/SPIRV.debug.h | 4 +- ...ctInstructionEnumerationSPIRVtoLLVM.spvasm | 49 +++++++++++++++++++ 4 files changed, 70 insertions(+), 5 deletions(-) create mode 100644 test/DebugInfo/IncorrectInstructionEnumerationSPIRVtoLLVM.spvasm diff --git a/lib/SPIRV/SPIRVToLLVMDbgTran.cpp b/lib/SPIRV/SPIRVToLLVMDbgTran.cpp index 03461fb2d6..b013ced387 100644 --- a/lib/SPIRV/SPIRVToLLVMDbgTran.cpp +++ b/lib/SPIRV/SPIRVToLLVMDbgTran.cpp @@ -1267,6 +1267,23 @@ SPIRVToLLVMDbgTran::transTypeTemplateParameter(const SPIRVExtInst *DebugInst) { false); } +// Workaround for the incorrect enum used for OpTypeTemplateTemplateParameter +// and OpTypeTemplateParameterPack instructions previously. The W/A added +// to enforce compatibility with previously generated SPIR-V modules. +DINode *SPIRVToLLVMDbgTran::transTypeTemplateParameterInst( + const SPIRVExtInst *DebugInst) { + constexpr SPIRVWord IndexToCheck = + SPIRVDebug::Operand::TypeTemplateTemplateParameter::TemplateNameIdx; + const SPIRVWordVec &Ops = DebugInst->getArguments(); + // We can't distinguish these 2 instructions by number of SPIR-V words which + // would be better. But we know, that the second parameter of + // OpTypeTemplateTemplateParameter is 'Template Name', which for + // OpTypeTemplateParameterPack it is 'Source'. + if (BM->get(Ops[IndexToCheck])->getOpCode() == OpString) + return transTypeTemplateTemplateParameter(DebugInst); + return transTypeTemplateParameterPack(DebugInst); +} + DINode *SPIRVToLLVMDbgTran::transTypeTemplateTemplateParameter( const SPIRVExtInst *DebugInst) { using namespace SPIRVDebug::Operand::TypeTemplateTemplateParameter; @@ -1493,10 +1510,8 @@ MDNode *SPIRVToLLVMDbgTran::transDebugInstImpl(const SPIRVExtInst *DebugInst) { return transTypeTemplateParameter(DebugInst); case SPIRVDebug::TypeTemplateTemplateParameter: - return transTypeTemplateTemplateParameter(DebugInst); - case SPIRVDebug::TypeTemplateParameterPack: - return transTypeTemplateParameterPack(DebugInst); + return transTypeTemplateParameterInst(DebugInst); case SPIRVDebug::TypeTemplate: return transTypeTemplate(DebugInst); diff --git a/lib/SPIRV/SPIRVToLLVMDbgTran.h b/lib/SPIRV/SPIRVToLLVMDbgTran.h index 996917b90f..2ad26e1268 100644 --- a/lib/SPIRV/SPIRVToLLVMDbgTran.h +++ b/lib/SPIRV/SPIRVToLLVMDbgTran.h @@ -145,6 +145,7 @@ class SPIRVToLLVMDbgTran { DINode *transTypeTemplateParameter(const SPIRVExtInst *DebugInst); DINode *transTypeTemplateTemplateParameter(const SPIRVExtInst *DebugInst); DINode *transTypeTemplateParameterPack(const SPIRVExtInst *DebugInst); + DINode *transTypeTemplateParameterInst(const SPIRVExtInst *DebugInst); MDNode *transTypeTemplate(const SPIRVExtInst *DebugInst); diff --git a/lib/SPIRV/libSPIRV/SPIRV.debug.h b/lib/SPIRV/libSPIRV/SPIRV.debug.h index dbca2dbe75..3fefca48cf 100644 --- a/lib/SPIRV/libSPIRV/SPIRV.debug.h +++ b/lib/SPIRV/libSPIRV/SPIRV.debug.h @@ -34,8 +34,8 @@ enum Instruction { TypePtrToMember = 13, TypeTemplate = 14, TypeTemplateParameter = 15, - TypeTemplateParameterPack = 16, - TypeTemplateTemplateParameter = 17, + TypeTemplateTemplateParameter = 16, + TypeTemplateParameterPack = 17, GlobalVariable = 18, FunctionDeclaration = 19, Function = 20, diff --git a/test/DebugInfo/IncorrectInstructionEnumerationSPIRVtoLLVM.spvasm b/test/DebugInfo/IncorrectInstructionEnumerationSPIRVtoLLVM.spvasm new file mode 100644 index 0000000000..7b7aa1d791 --- /dev/null +++ b/test/DebugInfo/IncorrectInstructionEnumerationSPIRVtoLLVM.spvasm @@ -0,0 +1,49 @@ +; This test checks that the decoding of DebugTypeTemplateParameterPack and +; DebugTypeTemplateTemplateParameter is correct. + +; REQUIRES: spirv-as + +; RUN: spirv-as --target-env spv1.3 %s -o %t.spv +; RUN: llvm-spirv -r %t.spv -o - | llvm-dis | FileCheck %s + +; SPIR-V +; Version: 1.1 +; Generator: Khronos LLVM/SPIR-V Translator; 14 +; Bound: 16 +; Schema: 0 + OpCapability Addresses + OpCapability Kernel + %1 = OpExtInstImport "OpenCL.std" + %2 = OpExtInstImport "OpenCL.DebugInfo.100" + OpMemoryModel Physical64 OpenCL + OpEntryPoint Kernel %5 "func" + %8 = OpString "/tmp/test.cpp" + %9 = OpString "//__CSK_MD5:18aa9ce738eaafc7b7b7181c19092815" + %12 = OpString "func" + %14 = OpString "" + %15 = OpString "T" + %16 = OpString "U" + %17 = OpString "Foo" + OpSource OpenCL_CPP 100000 + OpName %entry "entry" + %void = OpTypeVoid + %4 = OpTypeFunction %void + %10 = OpExtInst %void %2 DebugSource %8 %9 + %11 = OpExtInst %void %2 DebugCompilationUnit 65536 5 %10 OpenCL_CPP + %13 = OpExtInst %void %2 DebugInfoNone + %20 = OpExtInst %void %2 DebugFunction %12 %13 %10 1 0 %11 %14 FlagIsDefinition|FlagPrototyped|FlagIsOptimized 2 %5 %13 + %18 = OpExtInst %void %2 DebugTypeTemplateParameterPack %15 %10 0 0 %13 %13 + %19 = OpExtInst %void %2 DebugTypeTemplateTemplateParameter %16 %17 %10 0 0 + %21 = OpExtInst %void %2 DebugTypeTemplate %20 %18 %19 + %5 = OpFunction %void None %4 + %entry = OpLabel + OpReturn + OpFunctionEnd + +; CHECK: = distinct !DISubprogram(name: "func", +; CHECK-SAME: templateParams: [[TPARAMS:![0-9]+]]{{[,)]}} + +; CHECK-DAG: [[TPARAMS]] = !{[[PACKPARAM:![0-9]+]], [[TTPARAM:![0-9]+]]} +; CHECK-DAG: [[PACKPARAM]] = !DITemplateValueParameter(tag: DW_TAG_GNU_template_parameter_pack, name: "T", value: [[PACK:![0-9]+]]) +; CHECK-DAG: [[PACK]] = !{null, null} +; CHECK-DAG: [[TTPARAM]] = !DITemplateValueParameter(tag: DW_TAG_GNU_template_template_param, name: "U", value: !"Foo")