[PATCH 58/79] [DebugInfo] Adjust TypeMember for NonSemantic spec (#2033)
authorDmitry Sidorov <dmitry.sidorov@intel.com>
Fri, 2 Jun 2023 13:23:28 +0000 (15:23 +0200)
committerAndreas Beckmann <anbe@debian.org>
Thu, 14 Mar 2024 19:01:08 +0000 (20:01 +0100)
It no longer has a Scope (parent) parameter. It results in several changes including how to determine DIBuilder to use for debug info generation.

The patch also fixes a bug of incorrect debug info assignment in case of recursion DebugInfo inst generation.

Signed-off-by: Sidorov, Dmitry <dmitry.sidorov@intel.com>
Gbp-Pq: Name 0058-DebugInfo-Adjust-TypeMember-for-NonSemantic-spec-203.patch

lib/SPIRV/LLVMToSPIRVDbgTran.cpp
lib/SPIRV/LLVMToSPIRVDbgTran.h
lib/SPIRV/SPIRVToLLVMDbgTran.cpp
lib/SPIRV/SPIRVToLLVMDbgTran.h
lib/SPIRV/libSPIRV/SPIRV.debug.h
test/DebugInfo/NonSemantic/Shader200/DebugInfoSubrange.ll
test/DebugInfo/NonSemantic/static_member_array.ll [new file with mode: 0644]
test/DebugInfo/OpenCL100/DebugInfoSubrange.ll

index 539ae7da1d6270887a599243a3a5d2fd31698288..821eafdba1688eb39355dbc4a8411f7a89ca1546 100644 (file)
@@ -252,6 +252,17 @@ SPIRVEntry *LLVMToSPIRVDbgTran::transDbgEntry(const MDNode *DIEntry) {
   }
   SPIRVEntry *Res = transDbgEntryImpl(DIEntry);
   assert(Res && "Translation failure");
+  // We might end up having a recursive debug info generation like the
+  // following:
+  // translation of DIDerivedType (member) calls DICompositeType translation
+  // as its parent scope;
+  // translation of DICompositeType calls translation of its members
+  // (DIDerivedType with member tag).
+  // Here we make only the latest of these instructions be cached and hence
+  // reused
+  // FIXME: find a way to not create dead instruction
+  if (MDMap[DIEntry])
+    return MDMap[DIEntry];
   MDMap[DIEntry] = Res;
   return Res;
 }
@@ -959,7 +970,14 @@ LLVMToSPIRVDbgTran::transDbgCompositeType(const DICompositeType *CT) {
 }
 
 SPIRVEntry *LLVMToSPIRVDbgTran::transDbgMemberType(const DIDerivedType *MT) {
-  using namespace SPIRVDebug::Operand::TypeMember;
+  if (isNonSemanticDebugInfo())
+    return transDbgMemberTypeNonSemantic(MT);
+  return transDbgMemberTypeOpenCL(MT);
+}
+
+SPIRVEntry *
+LLVMToSPIRVDbgTran::transDbgMemberTypeOpenCL(const DIDerivedType *MT) {
+  using namespace SPIRVDebug::Operand::TypeMember::OpenCL;
   SPIRVWordVec Ops(MinOperandCount);
 
   Ops[NameIdx] = BM->getString(MT->getName().str())->getId();
@@ -986,6 +1004,34 @@ SPIRVEntry *LLVMToSPIRVDbgTran::transDbgMemberType(const DIDerivedType *MT) {
   return BM->addDebugInfo(SPIRVDebug::TypeMember, getVoidTy(), Ops);
 }
 
+SPIRVEntry *
+LLVMToSPIRVDbgTran::transDbgMemberTypeNonSemantic(const DIDerivedType *MT) {
+  using namespace SPIRVDebug::Operand::TypeMember::NonSemantic;
+  SPIRVWordVec Ops(MinOperandCount);
+
+  Ops[NameIdx] = BM->getString(MT->getName().str())->getId();
+  Ops[TypeIdx] = transDbgEntry(MT->getBaseType())->getId();
+  Ops[SourceIdx] = getSource(MT)->getId();
+  Ops[LineIdx] = MT->getLine();
+  Ops[ColumnIdx] = 0; // This version of DIDerivedType has no column number
+  ConstantInt *Offset = getUInt(M, MT->getOffsetInBits());
+  Ops[OffsetIdx] = SPIRVWriter->transValue(Offset, nullptr)->getId();
+  ConstantInt *Size = getUInt(M, MT->getSizeInBits());
+  Ops[SizeIdx] = SPIRVWriter->transValue(Size, nullptr)->getId();
+  Ops[FlagsIdx] = adjustAccessFlags(MT->getScope(), transDebugFlags(MT));
+  transDbgEntry(MT->getScope())->getId();
+  if (MT->isStaticMember()) {
+    if (llvm::Constant *C = MT->getConstant()) {
+      SPIRVValue *Val = SPIRVWriter->transValue(C, nullptr);
+      assert(isConstantOpCode(Val->getOpCode()) &&
+             "LLVM constant must be translated to SPIRV constant");
+      Ops.push_back(Val->getId());
+    }
+  }
+  transformToConstant(Ops, {LineIdx, ColumnIdx, FlagsIdx});
+  return BM->addDebugInfo(SPIRVDebug::TypeMember, getVoidTy(), Ops);
+}
+
 SPIRVEntry *LLVMToSPIRVDbgTran::transDbgInheritance(const DIDerivedType *DT) {
   using namespace SPIRVDebug::Operand::TypeInheritance;
   SPIRVWordVec Ops(OperandCount);
index 0ca070d636754f5e30dd53326bdc4cbc68111795..21bd6f2f6251a4c9976895c1631d9a40080731ae 100644 (file)
@@ -119,6 +119,8 @@ private:
   SPIRVEntry *transDbgEnumType(const DICompositeType *ET);
   SPIRVEntry *transDbgCompositeType(const DICompositeType *CT);
   SPIRVEntry *transDbgMemberType(const DIDerivedType *MT);
+  SPIRVEntry *transDbgMemberTypeOpenCL(const DIDerivedType *MT);
+  SPIRVEntry *transDbgMemberTypeNonSemantic(const DIDerivedType *MT);
   SPIRVEntry *transDbgInheritance(const DIDerivedType *DT);
   SPIRVEntry *transDbgPtrToMember(const DIDerivedType *DT);
 
index 9dd9c9330d27d268fa910b271b7b19ead00a61f6..42026b6263d8239cf83db809ddacc6523435c67a 100644 (file)
@@ -535,7 +535,16 @@ SPIRVToLLVMDbgTran::transTypeComposite(const SPIRVExtInst *DebugInst) {
   DebugInstCache[DebugInst] = CT;
   SmallVector<llvm::Metadata *, 8> EltTys;
   for (size_t I = FirstMemberIdx; I < Ops.size(); ++I) {
-    EltTys.push_back(transDebugInst(BM->get<SPIRVExtInst>(Ops[I])));
+    auto *MemberInst = BM->get<SPIRVExtInst>(Ops[I]);
+    if (MemberInst->getExtOp() == SPIRVDebug::TypeMember) {
+      auto *SPVMemberInst = BM->get<SPIRVExtInst>(Ops[I]);
+      DINode *MemberMD =
+          transTypeMember(SPVMemberInst, DebugInst, cast<DIScope>(CT));
+      EltTys.push_back(MemberMD);
+      DebugInstCache[SPVMemberInst] = MemberMD;
+    } else {
+      EltTys.emplace_back(transDebugInst(BM->get<SPIRVExtInst>(Ops[I])));
+    }
   }
   DINodeArray Elements = getDIBuilder(DebugInst).getOrCreateArray(EltTys);
   getDIBuilder(DebugInst).replaceArrays(CT, Elements);
@@ -617,8 +626,18 @@ SPIRVToLLVMDbgTran::transTypeString(const SPIRVExtInst *DebugInst) {
                            0 /*AlignInBits*/, Encoding);
 }
 
-DINode *SPIRVToLLVMDbgTran::transTypeMember(const SPIRVExtInst *DebugInst) {
-  using namespace SPIRVDebug::Operand::TypeMember;
+DINode *SPIRVToLLVMDbgTran::transTypeMember(const SPIRVExtInst *DebugInst,
+                                            const SPIRVExtInst *ParentInst,
+                                            DIScope *Scope) {
+  if (isNonSemanticDebugInfo(DebugInst->getExtSetKind()))
+    // In NonSemantic spec TypeMember doesn't have Scope parameter
+    return transTypeMemberNonSemantic(DebugInst, ParentInst, Scope);
+  return transTypeMemberOpenCL(DebugInst);
+}
+
+DINode *
+SPIRVToLLVMDbgTran::transTypeMemberOpenCL(const SPIRVExtInst *DebugInst) {
+  using namespace SPIRVDebug::Operand::TypeMember::OpenCL;
   const SPIRVWordVec &Ops = DebugInst->getArguments();
   assert(Ops.size() >= MinOperandCount && "Invalid number of operands");
 
@@ -660,6 +679,54 @@ DINode *SPIRVToLLVMDbgTran::transTypeMember(const SPIRVExtInst *DebugInst) {
                                                   Flags, BaseType);
 }
 
+DINode *
+SPIRVToLLVMDbgTran::transTypeMemberNonSemantic(const SPIRVExtInst *DebugInst,
+                                               const SPIRVExtInst *ParentInst,
+                                               DIScope *Scope) {
+  if (!Scope)
+    // Will be translated later when processing TypeMember's parent
+    return nullptr;
+  using namespace SPIRVDebug::Operand::TypeMember::NonSemantic;
+  const SPIRVWordVec &Ops = DebugInst->getArguments();
+  assert(Ops.size() >= MinOperandCount && "Invalid number of operands");
+
+  DIFile *File = getFile(Ops[SourceIdx]);
+  SPIRVWord LineNo =
+      getConstantValueOrLiteral(Ops, LineIdx, DebugInst->getExtSetKind());
+  StringRef Name = getString(Ops[NameIdx]);
+  DIType *BaseType =
+      transDebugInst<DIType>(BM->get<SPIRVExtInst>(Ops[TypeIdx]));
+  uint64_t OffsetInBits =
+      BM->get<SPIRVConstant>(Ops[OffsetIdx])->getZExtIntValue();
+  SPIRVWord SPIRVFlags =
+      getConstantValueOrLiteral(Ops, FlagsIdx, DebugInst->getExtSetKind());
+  DINode::DIFlags Flags = DINode::FlagZero;
+  if ((SPIRVDebug::FlagAccess & SPIRVFlags) == SPIRVDebug::FlagIsPublic) {
+    Flags |= DINode::FlagPublic;
+  } else if (SPIRVFlags & SPIRVDebug::FlagIsProtected) {
+    Flags |= DINode::FlagProtected;
+  } else if (SPIRVFlags & SPIRVDebug::FlagIsPrivate) {
+    Flags |= DINode::FlagPrivate;
+  }
+  if (SPIRVFlags & SPIRVDebug::FlagIsStaticMember)
+    Flags |= DINode::FlagStaticMember;
+
+  if (Flags & DINode::FlagStaticMember && Ops.size() > MinOperandCount) {
+    SPIRVValue *ConstVal = BM->get<SPIRVValue>(Ops[ValueIdx]);
+    assert(isConstantOpCode(ConstVal->getOpCode()) &&
+           "Static member must be a constant");
+    llvm::Value *Val = SPIRVReader->transValue(ConstVal, nullptr, nullptr);
+    return getDIBuilder(DebugInst).createStaticMemberType(
+        Scope, Name, File, LineNo, BaseType, Flags, cast<llvm::Constant>(Val));
+  }
+  uint64_t Size = BM->get<SPIRVConstant>(Ops[SizeIdx])->getZExtIntValue();
+  uint64_t Alignment = 0;
+
+  return getDIBuilder(ParentInst)
+      .createMemberType(Scope, Name, File, LineNo, Size, Alignment,
+                        OffsetInBits, Flags, BaseType);
+}
+
 DINode *SPIRVToLLVMDbgTran::transTypeEnum(const SPIRVExtInst *DebugInst) {
   using namespace SPIRVDebug::Operand::TypeEnum;
   const SPIRVWordVec &Ops = DebugInst->getArguments();
index 50d0d1e53b60b7d51d829195ae1ac385d7c7a514..48d7ea6b2fbd70a5ba25e6875bc6f3ae64a75fa3 100644 (file)
@@ -128,7 +128,13 @@ private:
 
   DIStringType *transTypeString(const SPIRVExtInst *DebugInst);
 
-  DINode *transTypeMember(const SPIRVExtInst *DebugInst);
+  DINode *transTypeMember(const SPIRVExtInst *DebugInst,
+                          const SPIRVExtInst *ParentInst = nullptr,
+                          DIScope *Scope = nullptr);
+  DINode *transTypeMemberOpenCL(const SPIRVExtInst *DebugInst);
+  DINode *transTypeMemberNonSemantic(const SPIRVExtInst *DebugInst,
+                                     const SPIRVExtInst *ParentInst,
+                                     DIScope *Scope);
 
   DINode *transTypeEnum(const SPIRVExtInst *DebugInst);
 
index 660d9510d64bd3579e0c162a9363de5a1a265e23..723a0b140c2fbbd8ef195c615fbc96fede6f9f2b 100644 (file)
@@ -465,6 +465,7 @@ enum {
 }
 
 namespace TypeMember {
+namespace OpenCL {
 enum {
   NameIdx         = 0,
   TypeIdx         = 1,
@@ -480,6 +481,22 @@ enum {
 };
 }
 
+namespace NonSemantic {
+enum {
+  NameIdx         = 0,
+  TypeIdx         = 1,
+  SourceIdx       = 2,
+  LineIdx         = 3,
+  ColumnIdx       = 4,
+  OffsetIdx       = 5,
+  SizeIdx         = 6,
+  FlagsIdx        = 7,
+  ValueIdx        = 8,
+  MinOperandCount = 8
+};
+}
+} // namespace TypeMember
+
 namespace TypeInheritance {
 enum {
   ChildIdx     = 0,
@@ -934,7 +951,7 @@ inline bool hasDbgInstParentScopeIdx(const uint32_t Kind,
     ParentScopeIdx = TypeEnum::ParentIdx;
     return true;
   case SPIRVDebug::TypeComposite:
-    ParentScopeIdx = TypeMember::ParentIdx;
+    ParentScopeIdx = TypeMember::OpenCL::ParentIdx;
     return true;
   case SPIRVDebug::TypeInheritance:
     ParentScopeIdx = TypeInheritance::ParentIdx;
index d83e170a611d8c537bd4e9891ce58e6e19b53d37..3bb29f080cc4c5af578784e94d233165897675b6 100644 (file)
@@ -16,8 +16,8 @@
 ; CHECK-SPIRV: [[#DINoneId:]] [[#EISId]] DebugInfoNone
 
 ; CHECK-SPIRV: [[#DebugFuncId:]] [[#EISId]] DebugFunction
+; CHECK-SPIRV: [[#LocalVarId:]] [[#EISId]] DebugLocalVariable [[#LocalVarNameId]] [[#]] [[#]] [[#]] [[#]] [[#DebugFuncId]]
 ; CHECK-SPIRV: [[#DebugTypeTemplate:]] [[#EISId]] DebugTypeTemplate [[#DebugFuncId]]
-; CHECK-SPIRV: [[#LocalVarId:]] [[#EISId]] DebugLocalVariable [[#LocalVarNameId]] [[#]] [[#]] [[#]] [[#]] [[#DebugTypeTemplate]]
 ; CHECK-SPIRV: [[#EISId]] DebugTypeSubrange [[#DINoneId]] [[#Constant1Id]] [[#LocalVarId]]  [[#DINoneId]]
 
 ; CHECK-SPIRV: [[#DIExprId:]] [[#EISId]] DebugExpression
diff --git a/test/DebugInfo/NonSemantic/static_member_array.ll b/test/DebugInfo/NonSemantic/static_member_array.ll
new file mode 100644 (file)
index 0000000..05e0a70
--- /dev/null
@@ -0,0 +1,80 @@
+; RUN: llvm-as < %s -o %t.bc
+; RUN: llvm-spirv %t.bc -o %t.spv -spirv-debug-info-version=nonsemantic-shader-100
+; RUN: llvm-spirv %t.spv --to-text -o - | FileCheck %s --check-prefix=CHECK-SPIRV
+; RUN: llvm-spirv -r %t.spv -o %t.rev.bc
+; RUN: llvm-dis < %t.rev.bc | FileCheck %s --check-prefix=CHECK-LLVM
+
+; RUN: llvm-spirv %t.bc -o %t.spv -spirv-debug-info-version=nonsemantic-shader-200
+; RUN: llvm-spirv %t.spv --to-text -o - | FileCheck %s --check-prefix=CHECK-SPIRV
+; RUN: llvm-spirv -r %t.spv -o %t.rev.bc
+; RUN: llvm-dis < %t.rev.bc | FileCheck %s --check-prefix=CHECK-LLVM
+
+; Generated from:
+;
+; struct A {
+;   static int fully_specified;
+;   static int smem[];
+; };
+;
+; int A::fully_specified;
+; int A::smem[] = { 0, 1, 2, 3 };
+
+; CHECK-SPIRV: ExtInst [[#]] [[#Member1:]] [[#]] DebugTypeMember [[#]] [[#]] [[#]] [[#]] [[#]] [[#]] [[#]] [[#]] {{$}}
+; CHECK-SPIRV: ExtInst [[#]] [[#Member2:]] [[#]] DebugTypeMember [[#]] [[#]] [[#]] [[#]] [[#]] [[#]] [[#]] [[#]] {{$}} 
+; CHECK-SPIRV: ExtInst [[#]] [[#]] [[#]] DebugTypeComposite [[#]] [[#]] [[#]] [[#]] [[#]] [[#]] [[#]] [[#]] [[#]] [[#Member1]] [[#Member2]]
+; CHECK-SPIRV: ExtInst [[#]] [[#]] [[#]] DebugGlobalVariable [[#]] [[#]] [[#]] [[#]] [[#]] [[#]] [[#]] [[#]] [[#]] [[#Member1]]
+; CHECK-SPIRV: ExtInst [[#]] [[#]] [[#]] DebugGlobalVariable [[#]] [[#]] [[#]] [[#]] [[#]] [[#]] [[#]] [[#]] [[#]] [[#Member2]]
+
+; CHECK-LLVM: ![[#GVExpr1:]] = !DIGlobalVariableExpression(var: ![[#GV1:]], expr: !DIExpression())
+; CHECK-LLVM: ![[#GV1]] = distinct !DIGlobalVariable(name: "fully_specified", linkageName: "_ZN1A15fully_specifiedE", scope: ![[#CU:]], file: ![[#File:]], line: 7, type: ![[#GVTy1:]], isLocal: false, isDefinition: true, declaration: ![[#Decl1:]])
+; CHECK-LLVM: ![[#CU]] = distinct !DICompileUnit(language: DW_LANG_C_plus_plus{{.*}}, file: ![[#File:]], {{.*}}, globals: ![[#GVs:]]
+; CHECK-LLVM: ![[#File]] = !DIFile(filename: "static_member_array.cpp", directory: "/Volumes/Data/radar/28706946")
+; CHECK-LLVM: ![[#GVs]] = !{![[#GVExpr1]], ![[#GVExpr2:]]}
+; CHECK-LLVM: ![[#GVExpr2]] = !DIGlobalVariableExpression(var: ![[#GV2:]], expr: !DIExpression())
+; CHECK-LLVM: ![[#GV2]] = distinct !DIGlobalVariable(name: "smem", linkageName: "_ZN1A4smemE", scope: ![[#CU]], file: ![[#File]], line: 8, type: ![[#GVTy2:]], isLocal: false, isDefinition: true, declaration: ![[#Decl2:]])
+; CHECK-LLVM: ![[#GVTy2]] = !DICompositeType(tag: DW_TAG_array_type, baseType: !8, size: 128, elements: ![[#Elements1:]])
+; CHECK-LLVM: ![[#GVTy1]] = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+; CHECK-LLVM: ![[#Elements1]] = !{![[#Subrange:]]}
+; CHECK-LLVM: ![[#Subrange]] = !DISubrange(count: 4
+; CHECK-LLVM: ![[#MemTy1:]] = !DIDerivedType(tag: DW_TAG_member, name: "smem", scope: ![[#StructTy:]], file: ![[#File]], line: 4, baseType: ![[#ArrTy:]], flags: DIFlagPublic | DIFlagStaticMember)
+; CHECK-LLVM: ![[#StructTy]] = !DICompositeType(tag: DW_TAG_structure_type, name: "A", file: ![[#File]], line: 1, size: 8, elements: ![[#Elements2:]], identifier: "_ZTS1A")
+; CHECK-LLVM: ![[#Elements2]] = !{![[#MemTy2:]], ![[#MemTy1]]}
+; CHECK-LLVM: ![[#MemTy2:]] = !DIDerivedType(tag: DW_TAG_member, name: "fully_specified", scope: ![[#StructTy]], file: ![[#File]], line: 3, baseType: ![[#GVTy1]], flags: DIFlagPublic | DIFlagStaticMember)
+; CHECK-LLVM: ![[#ArrTy]] = !DICompositeType(tag: DW_TAG_array_type, baseType: !8, elements: ![[#]])
+
+
+source_filename = "static_member_array.cpp"
+target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "spir64-unknown-unknown"
+
+@_ZN1A15fully_specifiedE = global i32 0, align 4, !dbg !0
+@_ZN1A4smemE = global [4 x i32] [i32 0, i32 1, i32 2, i32 3], align 16, !dbg !6
+
+!llvm.dbg.cu = !{!2}
+!llvm.module.flags = !{!19, !20, !21}
+!llvm.ident = !{!22}
+
+!0 = distinct !DIGlobalVariableExpression(var: !1, expr: !DIExpression())
+!1 = !DIGlobalVariable(name: "fully_specified", linkageName: "_ZN1A15fully_specifiedE", scope: !2, file: !3, line: 7, type: !9, isLocal: false, isDefinition: true, declaration: !15)
+!2 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !3, producer: "clang version 4.0.0 (trunk 286129) (llvm/trunk 286128)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !4, globals: !5)
+!3 = !DIFile(filename: "static_member_array.cpp", directory: "/Volumes/Data/radar/28706946")
+!4 = !{}
+!5 = !{!0, !6}
+!6 = distinct !DIGlobalVariableExpression(var: !7, expr: !DIExpression())
+!7 = !DIGlobalVariable(name: "smem", linkageName: "_ZN1A4smemE", scope: !2, file: !3, line: 8, type: !8, isLocal: false, isDefinition: true, declaration: !12)
+!8 = !DICompositeType(tag: DW_TAG_array_type, baseType: !9, size: 128, elements: !10)
+!9 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+!10 = !{!11}
+!11 = !DISubrange(count: 4)
+!12 = !DIDerivedType(tag: DW_TAG_member, name: "smem", scope: !13, file: !3, line: 4, baseType: !16, flags: DIFlagStaticMember)
+!13 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "A", file: !3, line: 1, size: 8, elements: !14, identifier: "_ZTS1A")
+!14 = !{!15, !12}
+!15 = !DIDerivedType(tag: DW_TAG_member, name: "fully_specified", scope: !13, file: !3, line: 3, baseType: !9, flags: DIFlagStaticMember)
+!16 = !DICompositeType(tag: DW_TAG_array_type, baseType: !9, elements: !17)
+!17 = !{!18}
+!18 = !DISubrange(count: -1)
+!19 = !{i32 2, !"Dwarf Version", i32 4}
+!20 = !{i32 2, !"Debug Info Version", i32 3}
+!21 = !{i32 1, !"PIC Level", i32 2}
+!22 = !{!"clang version 4.0.0 (trunk 286129) (llvm/trunk 286128)"}
+
index fcc11485f32722b3e196b2c37a8d209184b66125..da43ec5c05fdc568718db663195d69681382d464 100644 (file)
@@ -14,8 +14,8 @@
 ; CHECK-SPIRV: Constant [[#TypeInt64Id]] [[#NegativeCount:]] 4294967295 4294967295
 
 ; CHECK-SPIRV: [[#DbgFuncId:]] [[#]] DebugFunction [[#FuncNameId]]
+; CHECK-SPIRV: [[#]] [[#DbgLocVarId:]] [[#]] DebugLocalVariable [[#VarNameId]] [[#]] [[#]] [[#]] [[#]] [[#DbgFuncId]]
 ; CHECK-SPIRV: [[#DbgTemplateId:]] [[#]] DebugTypeTemplate [[#DbgFuncId]]
-; CHECK-SPIRV: [[#]] [[#DbgLocVarId:]] [[#]] DebugLocalVariable [[#VarNameId]] [[#]] [[#]] [[#]] [[#]] [[#DbgTemplateId]]
 ; CHECK-SPIRV: DebugTypeArray [[#]] [[#DbgLocVarId]] [[#LowerBoundId]]
 
 ; CHECK-SPIRV: [[#DbgExprId:]] [[#]] DebugExpression