[llvm] Emit debug type vector (PR #200056)

Diego Novillo via llvm-commits llvm-commits at lists.llvm.org
Thu Jun 11 12:55:08 PDT 2026


https://github.com/dnovillo updated https://github.com/llvm/llvm-project/pull/200056

>From 6a6ebed8ad5229fd7425e3322394f05dd3df1e2f Mon Sep 17 00:00:00 2001
From: Diego Novillo <dnovillo at nvidia.com>
Date: Wed, 27 May 2026 17:05:28 -0400
Subject: [PATCH 1/2] [SPIRV] Emit DebugTypeVector for NSDI

This emits `DebugTypeVector` for HLSL `float4`-style vectors. It works by collecting those nodes in `collectType()` and emitting `DebugTypeVector` after the `DebugTypeBasic` loop. The collection recurses into `getBaseType()` so the element `DIBasicType` is reachable from a vector-only module.

Added a new test in `test/CodeGen/SPIRV/debug-info/debug-type-vector.ll`.
---
 .../SPIRV/SPIRVNonSemanticDebugHandler.cpp    | 51 ++++++++++++--
 .../SPIRV/SPIRVNonSemanticDebugHandler.h      |  5 +-
 .../SPIRV/debug-info/debug-type-vector.ll     | 66 +++++++++++++++++++
 3 files changed, 114 insertions(+), 8 deletions(-)
 create mode 100644 llvm/test/CodeGen/SPIRV/debug-info/debug-type-vector.ll

diff --git a/llvm/lib/Target/SPIRV/SPIRVNonSemanticDebugHandler.cpp b/llvm/lib/Target/SPIRV/SPIRVNonSemanticDebugHandler.cpp
index de2dc8d17a4ad..0178441ac222f 100644
--- a/llvm/lib/Target/SPIRV/SPIRVNonSemanticDebugHandler.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVNonSemanticDebugHandler.cpp
@@ -27,15 +27,17 @@ using namespace llvm;
 
 namespace {
 
-/// Partition \p Ty into \p BasicTypes, \p PointerTypes, and \p SubroutineTypes
-/// for NSDI emission. Used when iterating DebugInfoFinder.types(); each DI
-/// node is seen once, so no recursion into pointer bases. Other composites and
-/// non-pointer derived kinds are ignored because they are not yet supported.
-/// Only types that are supported (later used) are partitioned.
+/// Partition \p Ty into \p BasicTypes, \p PointerTypes, \p SubroutineTypes,
+/// and \p VectorTypes for NSDI emission. Used when iterating
+/// DebugInfoFinder.types(); each DI node is seen once, so no recursion into
+/// pointer bases. Other composites and non-pointer derived kinds are ignored
+/// because they are not yet supported. Only types that are supported (later
+/// used) are partitioned.
 static void
 partitionTypes(const DIType *Ty, SmallVector<const DIBasicType *> &BasicTypes,
                SmallVector<const DIDerivedType *> &PointerTypes,
-               SmallVector<const DISubroutineType *> &SubroutineTypes) {
+               SmallVector<const DISubroutineType *> &SubroutineTypes,
+               SmallVector<const DICompositeType *> &VectorTypes) {
   if (const auto *BT = dyn_cast<DIBasicType>(Ty)) {
     BasicTypes.push_back(BT);
     return;
@@ -44,6 +46,11 @@ partitionTypes(const DIType *Ty, SmallVector<const DIBasicType *> &BasicTypes,
     SubroutineTypes.push_back(ST);
     return;
   }
+  if (const auto *CT = dyn_cast<DICompositeType>(Ty)) {
+    if (CT->getTag() == dwarf::DW_TAG_array_type && CT->isVector())
+      VectorTypes.push_back(CT);
+    return;
+  }
   const auto *DT = dyn_cast<DIDerivedType>(Ty);
   if (DT && DT->getTag() == dwarf::DW_TAG_pointer_type)
     PointerTypes.push_back(DT);
@@ -173,6 +180,7 @@ void SPIRVNonSemanticDebugHandler::beginModule(Module *M) {
   BasicTypes.clear();
   PointerTypes.clear();
   SubroutineTypes.clear();
+  VectorTypes.clear();
   DebugTypeRegs.clear();
   OpStringContentCache.clear();
   I32ConstantCache.clear();
@@ -218,7 +226,7 @@ void SPIRVNonSemanticDebugHandler::beginModule(Module *M) {
   DebugInfoFinder Finder;
   Finder.processModule(*M);
   llvm::for_each(Finder.types(), [&](DIType *Ty) {
-    partitionTypes(Ty, BasicTypes, PointerTypes, SubroutineTypes);
+    partitionTypes(Ty, BasicTypes, PointerTypes, SubroutineTypes, VectorTypes);
   });
 }
 
@@ -587,6 +595,35 @@ void SPIRVNonSemanticDebugHandler::emitNonSemanticGlobalDebugInfo(
     DebugTypeRegs[BT] = BTReg;
   }
 
+  // Emit DebugTypeVector for each collected vector type. Skip entries that
+  // would produce a module rejected by spirv-val: Base Type must resolve to
+  // a DebugTypeBasic, the subrange count must be a constant, and the Vulkan
+  // flavor of NSDI requires Component Count in [1, 4].
+  for (const DICompositeType *VT : VectorTypes) {
+    const auto *BaseTy = dyn_cast_or_null<DIBasicType>(VT->getBaseType());
+    if (!BaseTy)
+      continue;
+    auto BTIt = DebugTypeRegs.find(BaseTy);
+    if (BTIt == DebugTypeRegs.end())
+      continue;
+
+    DINodeArray Elements = VT->getElements();
+    if (Elements.size() != 1)
+      continue;
+    const auto *SR = cast<DISubrange>(Elements[0]);
+    const auto *CI = dyn_cast_if_present<ConstantInt *>(SR->getCount());
+    if (!CI)
+      continue;
+    uint64_t Count = CI->getZExtValue();
+    if (Count == 0 || Count > 4)
+      continue;
+
+    MCRegister CountReg =
+        emitOpConstantI32(static_cast<uint32_t>(Count), I32TypeReg, MAI);
+    emitExtInst(SPIRV::NonSemanticExtInst::DebugTypeVector, VoidTypeReg,
+                ExtInstSetReg, {BTIt->second, CountReg}, MAI);
+  }
+
   // Emit DebugTypePointer for each referenced pointer type.
   for (const DIDerivedType *PT : PointerTypes) {
     if (auto PtrReg = emitDebugTypePointer(PT, ExtInstSetReg, MAI))
diff --git a/llvm/lib/Target/SPIRV/SPIRVNonSemanticDebugHandler.h b/llvm/lib/Target/SPIRV/SPIRVNonSemanticDebugHandler.h
index b07e3f23a71af..9ca9b28ee8dab 100644
--- a/llvm/lib/Target/SPIRV/SPIRVNonSemanticDebugHandler.h
+++ b/llvm/lib/Target/SPIRV/SPIRVNonSemanticDebugHandler.h
@@ -61,10 +61,13 @@ class SPIRVNonSemanticDebugHandler : public DebugHandlerBase {
   int64_t DwarfVersion = 0;
 
   // DI types partitioned from DebugInfoFinder.types() in beginModule()
-  // (basics, pointers, subroutine types NSDI v1 may emit).
+  // (basics, pointers, vectors, subroutine types NSDI v1 may emit).
   SmallVector<const DIBasicType *> BasicTypes;
   SmallVector<const DIDerivedType *> PointerTypes;
   SmallVector<const DISubroutineType *> SubroutineTypes;
+  // DICompositeType nodes with DW_TAG_array_type and DINode::FlagVector,
+  // partitioned from DebugInfoFinder.types() in beginModule().
+  SmallVector<const DICompositeType *> VectorTypes;
 
   // Filled in emitNonSemanticGlobalDebugInfo(): DI types to their result
   // registers.
diff --git a/llvm/test/CodeGen/SPIRV/debug-info/debug-type-vector.ll b/llvm/test/CodeGen/SPIRV/debug-info/debug-type-vector.ll
new file mode 100644
index 0000000000000..4e9dee89e3fe0
--- /dev/null
+++ b/llvm/test/CodeGen/SPIRV/debug-info/debug-type-vector.ll
@@ -0,0 +1,66 @@
+; RUN: llc --verify-machineinstrs --spirv-ext=+SPV_KHR_non_semantic_info -O0 -mtriple=spirv64-unknown-unknown %s -o - | FileCheck %s --check-prefix=CHECK-SPIRV
+; RUN: %if spirv-tools %{ llc --verify-machineinstrs --spirv-ext=+SPV_KHR_non_semantic_info -O0 -mtriple=spirv64-unknown-unknown %s -o - -filetype=obj | spirv-val %}
+
+; Verify that DICompositeType nodes with tag DW_TAG_array_type and the
+; DIFlagVector flag lower to DebugTypeVector. Three element widths exercise
+; the OpConstant cache: a 4-component float vector and a 3-component float
+; vector share the float DebugTypeBasic but have distinct component-count
+; constants, while a 4-component int vector reuses the OpConstant 4 already
+; emitted for the float4.
+;
+; The OpConstant cache merges values across uses. OpConstant 3 is emitted
+; once and shared between the float DebugTypeBasic's Encoding operand (3 =
+; Float, NSDI 4.5) and the 3-component vector's ComponentCount operand.
+; Likewise OpConstant 4 is shared between the int DebugTypeBasic's Encoding
+; (4 = Signed) and the 4-component vector's ComponentCount.
+
+; CHECK-SPIRV: [[ext_inst_non_semantic:%[0-9]+]] = OpExtInstImport "NonSemantic.Shader.DebugInfo.100"
+; CHECK-SPIRV-DAG: [[type_void:%[0-9]+]] = OpTypeVoid
+; CHECK-SPIRV-DAG: [[type_int32:%[0-9]+]] = OpTypeInt 32 0
+; CHECK-SPIRV-DAG: [[str_float:%[0-9]+]] = OpString "float"
+; CHECK-SPIRV-DAG: [[str_int:%[0-9]+]] = OpString "int"
+; CHECK-SPIRV-DAG: [[size_32bit:%[0-9]+]] = OpConstant [[type_int32]] 32{{$}}
+; CHECK-SPIRV-DAG: [[flag_zero:%[0-9]+]] = OpConstant [[type_int32]] 0{{$}}
+; CHECK-SPIRV-DAG: [[const_3:%[0-9]+]] = OpConstant [[type_int32]] 3{{$}}
+; CHECK-SPIRV-DAG: [[const_4:%[0-9]+]] = OpConstant [[type_int32]] 4{{$}}
+; CHECK-SPIRV-DAG: [[basic_float:%[0-9]+]] = OpExtInst [[type_void]] [[ext_inst_non_semantic]] DebugTypeBasic [[str_float]] [[size_32bit]] [[const_3]] [[flag_zero]]
+; CHECK-SPIRV-DAG: [[basic_int:%[0-9]+]] = OpExtInst [[type_void]] [[ext_inst_non_semantic]] DebugTypeBasic [[str_int]] [[size_32bit]] [[const_4]] [[flag_zero]]
+; CHECK-SPIRV-DAG: OpExtInst [[type_void]] [[ext_inst_non_semantic]] DebugTypeVector [[basic_float]] [[const_4]]
+; CHECK-SPIRV-DAG: OpExtInst [[type_void]] [[ext_inst_non_semantic]] DebugTypeVector [[basic_float]] [[const_3]]
+; CHECK-SPIRV-DAG: OpExtInst [[type_void]] [[ext_inst_non_semantic]] DebugTypeVector [[basic_int]] [[const_4]]
+
+define spir_func void @test() !dbg !6 {
+entry:
+  %f4 = alloca <4 x float>, align 16
+  %f3 = alloca <3 x float>, align 16
+  %i4 = alloca <4 x i32>, align 16
+    #dbg_declare(ptr %f4, !10, !DIExpression(), !14)
+    #dbg_declare(ptr %f3, !15, !DIExpression(), !17)
+    #dbg_declare(ptr %i4, !18, !DIExpression(), !22)
+  ret void
+}
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!2, !3}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_HLSL, file: !1, producer: "clang", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug)
+!1 = !DIFile(filename: "vector.hlsl", directory: "/src")
+!2 = !{i32 7, !"Dwarf Version", i32 5}
+!3 = !{i32 2, !"Debug Info Version", i32 3}
+!6 = distinct !DISubprogram(name: "test", scope: !1, file: !1, line: 1, type: !7, scopeLine: 1, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !9)
+!7 = !DISubroutineType(types: !8)
+!8 = !{null}
+!9 = !{}
+!10 = !DILocalVariable(name: "f4", scope: !6, file: !1, line: 2, type: !11)
+!11 = !DICompositeType(tag: DW_TAG_array_type, baseType: !12, size: 128, flags: DIFlagVector, elements: !13)
+!12 = !DIBasicType(name: "float", size: 32, encoding: DW_ATE_float)
+!13 = !{!DISubrange(count: 4)}
+!14 = !DILocation(line: 2, column: 10, scope: !6)
+!15 = !DILocalVariable(name: "f3", scope: !6, file: !1, line: 3, type: !16)
+!16 = !DICompositeType(tag: DW_TAG_array_type, baseType: !12, size: 96, flags: DIFlagVector, elements: !20)
+!17 = !DILocation(line: 3, column: 10, scope: !6)
+!18 = !DILocalVariable(name: "i4", scope: !6, file: !1, line: 4, type: !19)
+!19 = !DICompositeType(tag: DW_TAG_array_type, baseType: !21, size: 128, flags: DIFlagVector, elements: !13)
+!20 = !{!DISubrange(count: 3)}
+!21 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+!22 = !DILocation(line: 4, column: 8, scope: !6)

>From 1833d5e05f9844041f6c94e1f05830e4043b56f9 Mon Sep 17 00:00:00 2001
From: Diego Novillo <dnovillo at nvidia.com>
Date: Thu, 4 Jun 2026 16:31:56 -0400
Subject: [PATCH 2/2] Address review feedback.

---
 .../SPIRV/SPIRVNonSemanticDebugHandler.cpp    | 57 ++++++++--------
 .../SPIRV/SPIRVNonSemanticDebugHandler.h      | 10 +++
 .../debug-info/debug-type-vector-skipped.ll   | 66 +++++++++++++++++++
 3 files changed, 107 insertions(+), 26 deletions(-)
 create mode 100644 llvm/test/CodeGen/SPIRV/debug-info/debug-type-vector-skipped.ll

diff --git a/llvm/lib/Target/SPIRV/SPIRVNonSemanticDebugHandler.cpp b/llvm/lib/Target/SPIRV/SPIRVNonSemanticDebugHandler.cpp
index 0178441ac222f..9cd82d74bc592 100644
--- a/llvm/lib/Target/SPIRV/SPIRVNonSemanticDebugHandler.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVNonSemanticDebugHandler.cpp
@@ -468,6 +468,34 @@ std::optional<MCRegister> SPIRVNonSemanticDebugHandler::mapDISignatureTypeToReg(
   return std::nullopt;
 }
 
+std::optional<MCRegister> SPIRVNonSemanticDebugHandler::emitDebugTypeVector(
+    const DICompositeType *VT, MCRegister ExtInstSetReg,
+    SPIRV::ModuleAnalysisInfo &MAI) {
+  const auto *BaseTy = dyn_cast_or_null<DIBasicType>(VT->getBaseType());
+  if (!BaseTy)
+    return std::nullopt;
+  auto BTIt = DebugTypeRegs.find(BaseTy);
+  if (BTIt == DebugTypeRegs.end())
+    return std::nullopt;
+
+  // DebugTypeVector models only 1D vectors (multi-subrange types cannot be
+  // encoded).
+  DINodeArray Elements = VT->getElements();
+  if (Elements.size() != 1)
+    return std::nullopt;
+  const auto *SR = cast<DISubrange>(Elements[0]);
+  const auto *CI = dyn_cast_if_present<ConstantInt *>(SR->getCount());
+  if (!CI)
+    return std::nullopt;
+
+  MCRegister VoidTypeReg = getOrEmitOpTypeVoidReg(MAI);
+  MCRegister I32TypeReg = getOrEmitOpTypeInt32Reg(MAI);
+  MCRegister CountReg = emitOpConstantI32(
+      static_cast<uint32_t>(CI->getZExtValue()), I32TypeReg, MAI);
+  return emitExtInst(SPIRV::NonSemanticExtInst::DebugTypeVector, VoidTypeReg,
+                     ExtInstSetReg, {BTIt->second, CountReg}, MAI);
+}
+
 void SPIRVNonSemanticDebugHandler::emitNonSemanticDebugStrings(
     SPIRV::ModuleAnalysisInfo &MAI) {
   if (CompileUnits.empty())
@@ -595,33 +623,10 @@ void SPIRVNonSemanticDebugHandler::emitNonSemanticGlobalDebugInfo(
     DebugTypeRegs[BT] = BTReg;
   }
 
-  // Emit DebugTypeVector for each collected vector type. Skip entries that
-  // would produce a module rejected by spirv-val: Base Type must resolve to
-  // a DebugTypeBasic, the subrange count must be a constant, and the Vulkan
-  // flavor of NSDI requires Component Count in [1, 4].
+  // Emit DebugTypeVector for each collected vector type.
   for (const DICompositeType *VT : VectorTypes) {
-    const auto *BaseTy = dyn_cast_or_null<DIBasicType>(VT->getBaseType());
-    if (!BaseTy)
-      continue;
-    auto BTIt = DebugTypeRegs.find(BaseTy);
-    if (BTIt == DebugTypeRegs.end())
-      continue;
-
-    DINodeArray Elements = VT->getElements();
-    if (Elements.size() != 1)
-      continue;
-    const auto *SR = cast<DISubrange>(Elements[0]);
-    const auto *CI = dyn_cast_if_present<ConstantInt *>(SR->getCount());
-    if (!CI)
-      continue;
-    uint64_t Count = CI->getZExtValue();
-    if (Count == 0 || Count > 4)
-      continue;
-
-    MCRegister CountReg =
-        emitOpConstantI32(static_cast<uint32_t>(Count), I32TypeReg, MAI);
-    emitExtInst(SPIRV::NonSemanticExtInst::DebugTypeVector, VoidTypeReg,
-                ExtInstSetReg, {BTIt->second, CountReg}, MAI);
+    if (auto VecReg = emitDebugTypeVector(VT, ExtInstSetReg, MAI))
+      DebugTypeRegs[VT] = *VecReg;
   }
 
   // Emit DebugTypePointer for each referenced pointer type.
diff --git a/llvm/lib/Target/SPIRV/SPIRVNonSemanticDebugHandler.h b/llvm/lib/Target/SPIRV/SPIRVNonSemanticDebugHandler.h
index 9ca9b28ee8dab..9a9dca36bb984 100644
--- a/llvm/lib/Target/SPIRV/SPIRVNonSemanticDebugHandler.h
+++ b/llvm/lib/Target/SPIRV/SPIRVNonSemanticDebugHandler.h
@@ -219,6 +219,16 @@ class SPIRVNonSemanticDebugHandler : public DebugHandlerBase {
                                          MCRegister ExtInstSetReg,
                                          SPIRV::ModuleAnalysisInfo &MAI);
 
+  /// Emit \c DebugTypeVector for the vector composite type \p VT.
+  ///
+  /// \returns The result id register on success. Returns \c std::nullopt and
+  /// emits nothing if \p VT has no \c DIBasicType base type, if the base type
+  /// has not been emitted yet, if \p VT has more than one \c DISubrange
+  /// element, or if the component count is not a compile-time constant.
+  std::optional<MCRegister> emitDebugTypeVector(const DICompositeType *VT,
+                                                MCRegister ExtInstSetReg,
+                                                SPIRV::ModuleAnalysisInfo &MAI);
+
   /// Map a \c DISubroutineType::getTypeArray() element to an operand register
   /// for
   /// \c DebugTypeFunction. Non-null \p Ty resolves via \c DebugTypeRegs; if the
diff --git a/llvm/test/CodeGen/SPIRV/debug-info/debug-type-vector-skipped.ll b/llvm/test/CodeGen/SPIRV/debug-info/debug-type-vector-skipped.ll
new file mode 100644
index 0000000000000..3a57d31abc772
--- /dev/null
+++ b/llvm/test/CodeGen/SPIRV/debug-info/debug-type-vector-skipped.ll
@@ -0,0 +1,66 @@
+; RUN: llc --verify-machineinstrs --spirv-ext=+SPV_KHR_non_semantic_info -O0 -mtriple=spirv64-unknown-unknown %s -o - | FileCheck %s
+; RUN: %if spirv-tools %{ llc --verify-machineinstrs --spirv-ext=+SPV_KHR_non_semantic_info -O0 -mtriple=spirv64-unknown-unknown %s -o - -filetype=obj | spirv-val %}
+
+; Verify that DICompositeType vector nodes that cannot be lowered to
+; DebugTypeVector are silently skipped. Four conditions trigger the skip:
+;   1. No base type (getBaseType() returns null).
+;   2. Non-DIBasicType base type (struct type as element type).
+;   3. More than one DISubrange element (multi-dimensional array shape).
+;   4. Non-constant subrange count (DILocalVariable used as component count).
+;
+; None of the four vectors below should produce a DebugTypeVector instruction.
+
+; CHECK-NOT: DebugTypeVector
+
+define spir_func void @test() !dbg !6 {
+entry:
+  %v1 = alloca <4 x float>, align 16
+  %v2 = alloca <4 x float>, align 16
+  %v3 = alloca <4 x i32>, align 16
+  %v4 = alloca <4 x i64>, align 32
+    #dbg_declare(ptr %v1, !10, !DIExpression(), !30)
+    #dbg_declare(ptr %v2, !12, !DIExpression(), !30)
+    #dbg_declare(ptr %v3, !15, !DIExpression(), !30)
+    #dbg_declare(ptr %v4, !20, !DIExpression(), !30)
+  ret void
+}
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!2, !3}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_HLSL, file: !1, producer: "clang", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug)
+!1 = !DIFile(filename: "skip.hlsl", directory: "/src")
+!2 = !{i32 7, !"Dwarf Version", i32 5}
+!3 = !{i32 2, !"Debug Info Version", i32 3}
+!4 = !DISubroutineType(types: !5)
+!5 = !{null}
+!6 = distinct !DISubprogram(name: "test", scope: !1, file: !1, line: 1, type: !4, scopeLine: 1, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !9)
+!9 = !{}
+
+; Case 1: vector with no base type -- skipped at dyn_cast_or_null<DIBasicType>.
+!10 = !DILocalVariable(name: "v1", scope: !6, file: !1, line: 2, type: !11)
+!11 = !DICompositeType(tag: DW_TAG_array_type, size: 128, flags: DIFlagVector, elements: !29)
+
+; Case 2: vector with non-DIBasicType base (struct) -- dyn_cast_or_null<DIBasicType>
+; returns null, so skipped at the same check as case 1.
+!12 = !DILocalVariable(name: "v2", scope: !6, file: !1, line: 3, type: !13)
+!13 = !DICompositeType(tag: DW_TAG_array_type, baseType: !14, size: 128, flags: DIFlagVector, elements: !29)
+!14 = !DICompositeType(tag: DW_TAG_structure_type, name: "S", file: !1, size: 32)
+
+; Case 3: vector with multiple subranges -- skipped at Elements.size() != 1.
+!15 = !DILocalVariable(name: "v3", scope: !6, file: !1, line: 4, type: !16)
+!16 = !DICompositeType(tag: DW_TAG_array_type, baseType: !17, size: 128, flags: DIFlagVector, elements: !18)
+!17 = !DIBasicType(name: "uint", size: 32, encoding: DW_ATE_unsigned)
+!18 = !{!DISubrange(count: 4), !DISubrange(count: 4)}
+
+; Case 4: vector with a non-constant subrange count (DILocalVariable) --
+; skipped at dyn_cast_if_present<ConstantInt *>.
+!20 = !DILocalVariable(name: "v4", scope: !6, file: !1, line: 5, type: !21)
+!21 = !DICompositeType(tag: DW_TAG_array_type, baseType: !22, size: 256, flags: DIFlagVector, elements: !27)
+!22 = !DIBasicType(name: "int64", size: 64, encoding: DW_ATE_signed)
+!23 = !DILocalVariable(name: "n", scope: !6, file: !1, line: 1, type: !24)
+!24 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+!27 = !{!DISubrange(count: !23)}
+
+!29 = !{!DISubrange(count: 4)}
+!30 = !DILocation(line: 2, column: 1, scope: !6)



More information about the llvm-commits mailing list