Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[SPIR-V] Emit DebugTypeBasic for NonSemantic DI #106980

Merged
merged 6 commits into from
Sep 17, 2024

Conversation

bwlodarcz
Copy link
Contributor

The commit introduces support for fundamental DI instruction. Metadata handlers required for this instruction is stored inside debug records (https://llvm.org/docs/SourceLevelDebugging.html) parts of the module which rises the necessity of it's traversal.

@llvmbot
Copy link
Collaborator

llvmbot commented Sep 2, 2024

@llvm/pr-subscribers-backend-spir-v

Author: None (bwlodarcz)

Changes

The commit introduces support for fundamental DI instruction. Metadata handlers required for this instruction is stored inside debug records (https://llvm.org/docs/SourceLevelDebugging.html) parts of the module which rises the necessity of it's traversal.


Patch is 25.05 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/106980.diff

3 Files Affected:

  • (modified) llvm/lib/Target/SPIRV/SPIRVEmitNonSemanticDI.cpp (+106-33)
  • (modified) llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp (+2-1)
  • (added) llvm/test/CodeGen/SPIRV/debug-info/basic-debug-type.ll (+232)
diff --git a/llvm/lib/Target/SPIRV/SPIRVEmitNonSemanticDI.cpp b/llvm/lib/Target/SPIRV/SPIRVEmitNonSemanticDI.cpp
index b37c7c1a6ee044..b33e81df2c8f1f 100644
--- a/llvm/lib/Target/SPIRV/SPIRVEmitNonSemanticDI.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVEmitNonSemanticDI.cpp
@@ -4,7 +4,9 @@
 #include "SPIRVGlobalRegistry.h"
 #include "SPIRVRegisterInfo.h"
 #include "SPIRVTargetMachine.h"
+#include "llvm/ADT/SmallSet.h"
 #include "llvm/ADT/SmallString.h"
+#include "llvm/BinaryFormat/Dwarf.h"
 #include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"
 #include "llvm/CodeGen/MachineBasicBlock.h"
 #include "llvm/CodeGen/MachineFunction.h"
@@ -13,7 +15,10 @@
 #include "llvm/CodeGen/MachineInstrBuilder.h"
 #include "llvm/CodeGen/MachineModuleInfo.h"
 #include "llvm/CodeGen/MachineOperand.h"
+#include "llvm/CodeGen/MachineRegisterInfo.h"
+#include "llvm/CodeGen/Register.h"
 #include "llvm/IR/DebugInfoMetadata.h"
+#include "llvm/IR/DebugProgramInstruction.h"
 #include "llvm/IR/Metadata.h"
 #include "llvm/PassRegistry.h"
 #include "llvm/Support/Casting.h"
@@ -71,7 +76,7 @@ bool SPIRVEmitNonSemanticDI::emitGlobalDI(MachineFunction &MF) {
   unsigned SourceLanguage = 0;
   int64_t DwarfVersion = 0;
   int64_t DebugInfoVersion = 0;
-
+  SmallSet<DIBasicType *, 12> BasicTypes;
   // Searching through the Module metadata to find nescessary
   // information like DwarfVersion or SourceLanguage
   {
@@ -104,6 +109,24 @@ bool SPIRVEmitNonSemanticDI::emitGlobalDI(MachineFunction &MF) {
                 cast<ConstantAsMetadata>(Op->getOperand(2))->getValue())
                 ->getSExtValue();
     }
+
+    // This traversal is the only supported way to access
+    // instruction related DI metadata like DIBasicType
+    for (auto &F : *M) {
+      for (auto &BB : F) {
+        for (auto &I : BB) {
+          for (DbgRecord &DR : I.getDbgRecordRange()) {
+            if (auto *DVR = dyn_cast<DbgVariableRecord>(&DR)) {
+              DILocalVariable *LocalVariable = DVR->getVariable();
+              if (auto *BasicType =
+                      dyn_cast<DIBasicType>(LocalVariable->getType())) {
+                BasicTypes.insert(BasicType);
+              }
+            }
+          }
+        }
+      }
+    }
   }
   // NonSemantic.Shader.DebugInfo.100 global DI instruction emitting
   {
@@ -120,29 +143,45 @@ bool SPIRVEmitNonSemanticDI::emitGlobalDI(MachineFunction &MF) {
     // and before first terminator
     MachineIRBuilder MIRBuilder(MBB, MBB.getFirstTerminator());
 
+    const auto EmitOpString = [&](StringRef SR) {
+      const Register StrReg = MRI.createVirtualRegister(&SPIRV::IDRegClass);
+      MRI.setType(StrReg, LLT::scalar(32));
+      MachineInstrBuilder MIB = MIRBuilder.buildInstr(SPIRV::OpString);
+      MIB.addDef(StrReg);
+      addStringImm(SR, MIB);
+      return StrReg;
+    };
+
     // Emit OpString with FilePath which is required by DebugSource
-    const Register StrReg = MRI.createVirtualRegister(&SPIRV::IDRegClass);
-    MRI.setType(StrReg, LLT::scalar(32));
-    MachineInstrBuilder MIB = MIRBuilder.buildInstr(SPIRV::OpString);
-    MIB.addDef(StrReg);
-    addStringImm(FilePath, MIB);
+    const Register FilePathStrReg = EmitOpString(FilePath);
 
     const SPIRVType *VoidTy =
         GR->getOrCreateSPIRVType(Type::getVoidTy(*Context), MIRBuilder);
 
+    const auto EmitDIInstruction =
+        [&](SPIRV::NonSemanticExtInst::NonSemanticExtInst Inst,
+            std::initializer_list<Register> Registers) {
+          const Register InstReg =
+              MRI.createVirtualRegister(&SPIRV::IDRegClass);
+          MRI.setType(InstReg, LLT::scalar(32));
+          MachineInstrBuilder MIB =
+              MIRBuilder.buildInstr(SPIRV::OpExtInst)
+                  .addDef(InstReg)
+                  .addUse(GR->getSPIRVTypeID(VoidTy))
+                  .addImm(static_cast<int64_t>(
+                      SPIRV::InstructionSet::NonSemantic_Shader_DebugInfo_100))
+                  .addImm(Inst);
+          for (auto Reg : Registers) {
+            MIB.addUse(Reg);
+          }
+          MIB.constrainAllUses(*TII, *TRI, *RBI);
+          GR->assignSPIRVTypeToVReg(VoidTy, InstReg, MF);
+          return InstReg;
+        };
+
     // Emit DebugSource which is required by DebugCompilationUnit
-    const Register DebugSourceResIdReg =
-        MRI.createVirtualRegister(&SPIRV::IDRegClass);
-    MRI.setType(DebugSourceResIdReg, LLT::scalar(32));
-    MIB = MIRBuilder.buildInstr(SPIRV::OpExtInst)
-              .addDef(DebugSourceResIdReg)
-              .addUse(GR->getSPIRVTypeID(VoidTy))
-              .addImm(static_cast<int64_t>(
-                  SPIRV::InstructionSet::NonSemantic_Shader_DebugInfo_100))
-              .addImm(SPIRV::NonSemanticExtInst::DebugSource)
-              .addUse(StrReg);
-    MIB.constrainAllUses(*TII, *TRI, *RBI);
-    GR->assignSPIRVTypeToVReg(VoidTy, DebugSourceResIdReg, MF);
+    const Register DebugSourceResIdReg = EmitDIInstruction(
+        SPIRV::NonSemanticExtInst::DebugSource, {FilePathStrReg});
 
     const SPIRVType *I32Ty =
         GR->getOrCreateSPIRVType(Type::getInt32Ty(*Context), MIRBuilder);
@@ -156,22 +195,56 @@ bool SPIRVEmitNonSemanticDI::emitGlobalDI(MachineFunction &MF) {
     const Register SourceLanguageReg =
         GR->buildConstantInt(SourceLanguage, MIRBuilder, I32Ty, false);
 
-    // Emit DebugCompilationUnit
+    [[maybe_unused]]
     const Register DebugCompUnitResIdReg =
-        MRI.createVirtualRegister(&SPIRV::IDRegClass);
-    MRI.setType(DebugCompUnitResIdReg, LLT::scalar(32));
-    MIB = MIRBuilder.buildInstr(SPIRV::OpExtInst)
-              .addDef(DebugCompUnitResIdReg)
-              .addUse(GR->getSPIRVTypeID(VoidTy))
-              .addImm(static_cast<int64_t>(
-                  SPIRV::InstructionSet::NonSemantic_Shader_DebugInfo_100))
-              .addImm(SPIRV::NonSemanticExtInst::DebugCompilationUnit)
-              .addUse(DebugInfoVersionReg)
-              .addUse(DwarfVersionReg)
-              .addUse(DebugSourceResIdReg)
-              .addUse(SourceLanguageReg);
-    MIB.constrainAllUses(*TII, *TRI, *RBI);
-    GR->assignSPIRVTypeToVReg(VoidTy, DebugCompUnitResIdReg, MF);
+        EmitDIInstruction(SPIRV::NonSemanticExtInst::DebugCompilationUnit,
+                          {DebugInfoVersionReg, DwarfVersionReg,
+                           DebugSourceResIdReg, SourceLanguageReg});
+
+    // Emit DebugInfoNone. This instruction is a wildcard accepted
+    // by standard to put into instruction arguments as Not Available/Null 
+    const Register DebugInfoNoneReg =
+        EmitDIInstruction(SPIRV::NonSemanticExtInst::DebugInfoNone, {});
+
+    for (auto *BasicType : BasicTypes) {
+      const Register BasicTypeStrReg = EmitOpString(BasicType->getName());
+
+      const Register ConstIntBitwidthReg = GR->buildConstantInt(
+          BasicType->getSizeInBits(), MIRBuilder, I32Ty, false);
+
+      uint64_t AttributeEncoding = 0;
+      switch (BasicType->getEncoding()) {
+      case dwarf::DW_ATE_signed:
+        AttributeEncoding = 4;
+        break;
+      case dwarf::DW_ATE_unsigned:
+        AttributeEncoding = 6;
+        break;
+      case dwarf::DW_ATE_unsigned_char:
+        AttributeEncoding = 7;
+        break;
+      case dwarf::DW_ATE_signed_char:
+        AttributeEncoding = 5;
+        break;
+      case dwarf::DW_ATE_float:
+        AttributeEncoding = 3;
+        break;
+      case dwarf::DW_ATE_boolean:
+        AttributeEncoding = 2;
+        break;
+      case dwarf::DW_ATE_address:
+        AttributeEncoding = 1;
+      }
+
+      const Register AttributeEncodingReg =
+          GR->buildConstantInt(AttributeEncoding, MIRBuilder, I32Ty, false);
+
+      [[maybe_unused]]
+      const Register BasicTypeReg =
+          EmitDIInstruction(SPIRV::NonSemanticExtInst::DebugTypeBasic,
+                            {BasicTypeStrReg, ConstIntBitwidthReg,
+                             AttributeEncodingReg, DebugInfoNoneReg});
+    }
   }
   return true;
 }
diff --git a/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp b/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp
index a2fcfc636e3684..bd35b815a72f4f 100644
--- a/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp
@@ -432,7 +432,8 @@ void SPIRVModuleAnalysis::processOtherInstrs(const Module &M) {
           MachineOperand Ins = MI.getOperand(3);
           namespace NS = SPIRV::NonSemanticExtInst;
           static constexpr int64_t GlobalNonSemanticDITy[] = {
-              NS::DebugSource, NS::DebugCompilationUnit};
+              NS::DebugSource, NS::DebugCompilationUnit, NS::DebugInfoNone,
+              NS::DebugTypeBasic};
           bool IsGlobalDI = false;
           for (unsigned Idx = 0; Idx < std::size(GlobalNonSemanticDITy); ++Idx)
             IsGlobalDI |= Ins.getImm() == GlobalNonSemanticDITy[Idx];
diff --git a/llvm/test/CodeGen/SPIRV/debug-info/basic-debug-type.ll b/llvm/test/CodeGen/SPIRV/debug-info/basic-debug-type.ll
new file mode 100644
index 00000000000000..87598ff3b1b984
--- /dev/null
+++ b/llvm/test/CodeGen/SPIRV/debug-info/basic-debug-type.ll
@@ -0,0 +1,232 @@
+; RUN: llc --verify-machineinstrs --spv-emit-nonsemantic-debug-info --spirv-ext=+SPV_KHR_non_semantic_info --print-after=spirv-nonsemantic-debug-info -O0 -mtriple=spirv64-unknown-unknown %s -o - 2>&1 | FileCheck %s --check-prefix=CHECK-MIR
+; RUN: llc --verify-machineinstrs --spv-emit-nonsemantic-debug-info --spirv-ext=+SPV_KHR_non_semantic_info -O0 -mtriple=spirv64-unknown-unknown %s -o - | FileCheck %s --check-prefix=CHECK-SPIRV
+; RUN: llc --verify-machineinstrs -O0 -mtriple=spirv64-unknown-unknown --spirv-ext=+SPV_KHR_non_semantic_info %s -o - | FileCheck %s --check-prefix=CHECK-OPTION
+; RUN: %if spirv-tools %{ llc --spirv-ext=+SPV_KHR_non_semantic_info -O0 -mtriple=spirv64-unknown-unknown %s -o - -filetype=obj | spirv-val %}
+
+; CHECK-MIR: [[type_void:%[0-9]+\:type]] = OpTypeVoid
+; CHECK-MIR: [[type_i32:%[0-9]+\:type]] = OpTypeInt 32, 0
+; CHECK-MIR: [[encoding_signedchar:%[0-9]+\:iid\(s32\)]] = OpConstantI [[type_i32]], 5
+; CHECK-MIR: [[encoding_float:%[0-9]+\:iid\(s32\)]] = OpConstantI [[type_i32]], 3
+; CHECK-MIR: [[debug_info_none:%[0-9]+\:id\(s32\)]] = OpExtInst [[type_void]], 3, 0
+; CHECK-MIR: [[str_bool:%[0-9]+\:id\(s32\)]] = OpString 1819242338, 0
+; CHECK-MIR: [[size_8bits:%[0-9]+\:iid\(s32\)]] = OpConstantI [[type_i32]], 8
+; CHECK-MIR: [[encoding_boolean:%[0-9]+\:iid\(s32\)]] = OpConstantI [[type_i32]], 2
+; CHECK-MIR: OpExtInst [[type_void]], 3, 2, [[str_bool]], [[size_8bits]], [[encoding_boolean]], [[debug_info_none]]
+; CHECK-MIR: [[str_int:%[0-9]+\:id\(s32\)]] = OpString 7630441
+; CHECK-MIR: [[size_32bits:%[0-9]+\:iid\(s32\)]] = OpConstantI [[type_i32]], 32
+; CHECK-MIR: [[encoding_signed:%[0-9]+\:iid\(s32\)]] = OpConstantI [[type_i32]], 4
+; CHECK-MIR: OpExtInst [[type_void]], 3, 2, [[str_int]], [[size_32bits]], [[encoding_signed]], [[debug_info_none]]
+; CHECK-MIR: [[str_short:%[0-9]+\:id\(s32\)]] = OpString 1919903859, 116
+; CHECK-MIR: [[size_16bits:%[0-9]+\:iid\(s32\)]] = OpConstantI [[type_i32]], 16
+; CHECK-MIR: OpExtInst [[type_void]], 3, 2, [[str_short]], [[size_16bits]], [[encoding_signed]], [[debug_info_none]]
+; CHECK-MIR: [[str_char:%[0-9]+\:id\(s32\)]] = OpString 1918986339, 0
+; CHECK-MIR: OpExtInst [[type_void]], 3, 2, [[str_char]], [[size_8bits]], [[encoding_signedchar]], [[debug_info_none]]
+; CHECK-MIR: [[str_long:%[0-9]+\:id\(s32\)]] = OpString 1735290732, 0
+; CHECK-MIR: [[size_64bits:%[0-9]+\:iid\(s32\)]] = OpConstantI [[type_i32]], 64
+; CHECK-MIR: OpExtInst [[type_void]], 3, 2, [[str_long]], [[size_64bits]], [[encoding_signed]], [[debug_info_none]]
+; CHECK-MIR: [[str_uint:%[0-9]+\:id\(s32\)]] = OpString 1769172597, 1684368999, 1953392928, 0
+; CHECK-MIR: [[encoding_unsigned:%[0-9]+\:iid\(s32\)]] = OpConstantI [[type_i32]], 6
+; CHECK-MIR: OpExtInst [[type_void]], 3, 2, [[str_uint]], [[size_32bits]], [[encoding_unsigned]], [[debug_info_none]]
+; CHECK-MIR: [[str_ushort:%[0-9]+\:id\(s32\)]] = OpString 1769172597, 1684368999, 1869116192, 29810
+; CHECK-MIR: OpExtInst [[type_void]], 3, 2, [[str_ushort]], [[size_16bits]], [[encoding_unsigned]], [[debug_info_none]]
+; CHECK-MIR: [[str_uchar:%[0-9]+\:id\(s32\)]] = OpString 1769172597, 1684368999, 1634231072, 114
+; CHECK-MIR: [[encoding_unsignedchar:%[0-9]+\:iid\(s32\)]] = OpConstantI [[type_i32]], 7
+; CHECK-MIR: OpExtInst [[type_void]], 3, 2, [[str_uchar]], [[size_8bits]], [[encoding_unsignedchar]], [[debug_info_none]]
+; CHECK-MIR: [[str_ulong:%[0-9]+\:id\(s32\)]] = OpString 1769172597, 1684368999, 1852795936, 103
+; CHECK-MIR: OpExtInst [[type_void]], 3, 2, [[str_ulong]], [[size_64bits]], [[encoding_unsigned]], [[debug_info_none]]
+; CHECK-MIR: [[str_float:%[0-9]+\:id\(s32\)]] = OpString 1634692198, 116
+; CHECK-MIR: OpExtInst [[type_void]], 3, 2, [[str_float]], [[size_32bits]], [[encoding_float]], [[debug_info_none]]
+; CHECK-MIR: [[str_double:%[0-9]+\:id\(s32\)]] = OpString 1651863396, 25964
+; CHECK-MIR: OpExtInst [[type_void]], 3, 2, [[str_double]], [[size_64bits]], [[encoding_float]], [[debug_info_none]]
+
+; CHECK-SPIRV: [[ext_inst_non_semantic:%[0-9]+]] = OpExtInstImport "NonSemantic.Shader.DebugInfo.100"
+; CHECK-SPIRV: [[str_bool:%[0-9]+]] = OpString "bool"
+; CHECK-SPIRV: [[str_int:%[0-9]+]] = OpString "int"
+; CHECK-SPIRV: [[str_short:%[0-9]+]] = OpString "short"
+; CHECK-SPIRV: [[str_char:%[0-9]+]] = OpString "char"
+; CHECK-SPIRV: [[str_long:%[0-9]+]] = OpString "long"
+; CHECK-SPIRV: [[str_uint:%[0-9]+]] = OpString "unsigned int"
+; CHECK-SPIRV: [[str_ushort:%[0-9]+]] = OpString "unsigned short"
+; CHECK-SPIRV: [[str_uchar:%[0-9]+]] = OpString "unsigned char"
+; CHECK-SPIRV: [[str_ulong:%[0-9]+]] = OpString "unsigned long"
+; CHECK-SPIRV: [[str_float:%[0-9]+]] = OpString "float"
+; CHECK-SPIRV: [[str_double:%[0-9]+]] = OpString "double"
+; CHECK-SPIRV: [[type_void:%[0-9]+]] = OpTypeVoid
+; CHECK-SPIRV: [[type_float64:%[0-9]+]] = OpTypeFloat 64
+; CHECK-SPIRV: [[type_float32:%[0-9]+]] = OpTypeFloat 32
+; CHECK-SPIRV: [[type_int64:%[0-9]+]] = OpTypeInt 64 0
+; CHECK-SPIRV: [[type_int8:%[0-9]+]] = OpTypeInt 8 0
+; CHECK-SPIRV: [[type_int16:%[0-9]+]] = OpTypeInt 16 0
+; CHECK-SPIRV: [[type_int32:%[0-9]+]] = OpTypeInt 32 0
+; CHECK-SPIRV: [[encoding_signedchar:%[0-9]+]] = OpConstant [[type_int32]] 5
+; CHECK-SPIRV: [[encoding_float:%[0-9]+]] = OpConstant [[type_int32]] 3
+; CHECK-SPIRV: [[size_8bit:%[0-9]+]] = OpConstant [[type_int32]] 8
+; CHECK-SPIRV: [[encoding_boolean:%[0-9]+]] = OpConstant [[type_int32]] 2
+; CHECK-SPIRV: [[size_32bit:%[0-9]+]] = OpConstant [[type_int32]] 32
+; CHECK-SPIRV: [[encoding_signed:%[0-9]+]] = OpConstant [[type_int32]] 4
+; CHECK-SPIRV: [[size_16bit:%[0-9]+]] = OpConstant [[type_int32]] 16
+; CHECK-SPIRV: [[size_64bit:%[0-9]+]] = OpConstant [[type_int32]] 64
+; CHECK-SPIRV: [[encoding_unsigned:%[0-9]+]] = OpConstant [[type_int32]] 6
+; CHECK-SPIRV: [[encoding_unsignedchar:%[0-9]+]] = OpConstant [[type_int32]] 7
+; CHECK-SPIRV: [[debug_info_none:%[0-9]+]] = OpExtInst [[type_void]] [[ext_inst_non_semantic]] DebugInfoNone
+; CHECK-SPIRV: OpExtInst [[type_void]] [[ext_inst_non_semantic]] DebugTypeBasic [[str_bool]] [[size_8bit]] [[encoding_boolean]] [[debug_info_none]]
+; CHECK-SPIRV: OpExtInst [[type_void]] [[ext_inst_non_semantic]] DebugTypeBasic [[str_int]] [[size_32bit]] [[encoding_signed]] [[debug_info_none]]
+; CHECK-SPIRV: OpExtInst [[type_void]] [[ext_inst_non_semantic]] DebugTypeBasic [[str_short]] [[size_16bit]] [[encoding_signed]] [[debug_info_none]]
+; CHECK-SPIRV: OpExtInst [[type_void]] [[ext_inst_non_semantic]] DebugTypeBasic [[str_char]] [[size_8bit]] [[encoding_signedchar]] [[debug_info_none]]
+; CHECK-SPIRV: OpExtInst [[type_void]] [[ext_inst_non_semantic]] DebugTypeBasic [[str_long]] [[size_64bit]] [[encoding_signed]] [[debug_info_none]]
+; CHECK-SPIRV: OpExtInst [[type_void]] [[ext_inst_non_semantic]] DebugTypeBasic [[str_uint]] [[size_32bit]] [[encoding_unsigned]] [[debug_info_none]]
+; CHECK-SPIRV: OpExtInst [[type_void]] [[ext_inst_non_semantic]] DebugTypeBasic [[str_ushort]] [[size_16bit]] [[encoding_unsigned]] [[debug_info_none]]
+; CHECK-SPIRV: OpExtInst [[type_void]] [[ext_inst_non_semantic]] DebugTypeBasic [[str_uchar]] [[size_8bit]] [[encoding_unsignedchar]] [[debug_info_none]]
+; CHECK-SPIRV: OpExtInst [[type_void]] [[ext_inst_non_semantic]] DebugTypeBasic [[str_ulong]] [[size_64bit]] [[encoding_unsigned]] [[debug_info_none]]
+; CHECK-SPIRV: OpExtInst [[type_void]] [[ext_inst_non_semantic]] DebugTypeBasic [[str_float]] [[size_32bit]] [[encoding_float]] [[debug_info_none]]
+; CHECK-SPIRV: OpExtInst [[type_void]] [[ext_inst_non_semantic]] DebugTypeBasic [[str_double]] [[size_64bit]] [[encoding_float]] [[debug_info_none]]
+
+; CHECK-OPTION-NOT: DebugTypeBasic
+
+define spir_func void  @test1() !dbg !9 {
+entry:
+  %b0 = alloca i8, align 1
+  %a0 = alloca i32, align 4
+  %s0 = alloca i16, align 2
+  %c0 = alloca i8, align 1
+  %l0 = alloca i64, align 8
+  %ua0 = alloca i32, align 4
+  %us0 = alloca i16, align 2
+  %uc0 = alloca i8, align 1
+  %ul0 = alloca i64, align 8
+  %f0 = alloca float, align 4
+  %d0 = alloca double, align 8
+    #dbg_declare(ptr %b0, !14, !DIExpression(DW_OP_constu, 0, DW_OP_swap, DW_OP_xderef), !16)
+  store i8 0, ptr %b0, align 1, !dbg !16
+    #dbg_declare(ptr %a0, !17, !DIExpression(DW_OP_constu, 0, DW_OP_swap, DW_OP_xderef), !18)
+  store i32 1, ptr %a0, align 4, !dbg !18
+    #dbg_declare(ptr %s0, !19, !DIExpression(DW_OP_constu, 0, DW_OP_swap, DW_OP_xderef), !21)
+  store i16 2, ptr %s0, align 2, !dbg !21
+    #dbg_declare(ptr %c0, !22, !DIExpression(DW_OP_constu, 0, DW_OP_swap, DW_OP_xderef), !24)
+  store i8 3, ptr %c0, align 1, !dbg !24
+    #dbg_declare(ptr %l0, !25, !DIExpression(DW_OP_constu, 0, DW_OP_swap, DW_OP_xderef), !27)
+  store i64 4, ptr %l0, align 8, !dbg !27
+    #dbg_declare(ptr %ua0, !28, !DIExpression(DW_OP_constu, 0, DW_OP_swap, DW_OP_xderef), !30)
+  store i32 1, ptr %ua0, align 4, !dbg !30
+    #dbg_declare(ptr %us0, !31, !DIExpression(DW_OP_constu, 0, DW_OP_swap, DW_OP_xderef), !33)
+  store i16 2, ptr %us0, align 2, !dbg !33
+    #dbg_declare(ptr %uc0, !34, !DIExpression(DW_OP_constu, 0, DW_OP_swap, DW_OP_xderef), !36)
+  store i8 3, ptr %uc0, align 1, !dbg !36
+    #dbg_declare(ptr %ul0, !37, !DIExpression(DW_OP_constu, 0, DW_OP_swap, DW_OP_xderef), !39)
+  store i64 4, ptr %ul0, align 8, !dbg !39
+    #dbg_declare(ptr %f0, !40, !DIExpression(DW_OP_constu, 0, DW_OP_swap, DW_OP_xderef), !42)
+  store float 1.000000e+00, ptr %f0, align 4, !dbg !42
+    #dbg_declare(ptr %d0, !43, !DIExpression(DW_OP_constu, 0, DW_OP_swap, DW_OP_xderef), !45)
+  store double 2.000000e+00, ptr %d0, align 8, !dbg !45
+  ret void
+}
+
+define spir_func void @test2() !dbg !47 {
+entry:
+  %b1 = alloca i8, align 1
+  %a1 = alloca i32, align 4
+  %s1 = alloca i16, align 2
+  %c1 = alloca i8, align 1
+  %l1 = alloca i64, align 8
+  %ua1 = alloca i32, align 4
+  %us1 = alloca i16, align 2
+  %uc1 = alloca i8, align 1
+  %ul1 = alloca i64, align 8
+  %f1 = alloca float, align 4
+  %d1 = alloca double, align 8
+    #dbg_declare(ptr %b1, !48, !DIExpression(DW_OP_constu, 0, DW_OP_swap, DW_OP_xderef), !49)
+  store i8 0, ptr %b1, align 1, !dbg !49
+    #dbg_declare(ptr %a1, !50, !DIExpression(DW_OP_constu, 0, DW_OP_swap, DW_OP_xderef), !51)
+  store i32 1, ptr %a1, align 4, !dbg !51
+    #dbg_declare(ptr %s1, !52, !DIExpression(DW_OP_constu, 0, DW_OP_swap, DW_OP_xderef), !53)
+  store i16 2, ptr %s1, align 2, !dbg !53
+    #dbg_declare(ptr %c1, !54, !DIExpression(DW_OP_constu, 0, DW_OP_swap, DW_OP_xderef), !55)
+  store i8 3, ptr %c1, align 1, !dbg !55
+    #dbg_declare(ptr %l1, !56, !DIExpression(DW_OP_constu, 0, DW_OP_swap, DW_OP_xderef), !57)
+  store i64 4, ptr %l1, align 8, !dbg !57
+    #dbg_declare(ptr %ua1, !58, !DIExpression(DW_OP_constu, 0, DW_OP_swap, DW_OP_xderef), !59)
+  store i32 1, ptr %ua1, align 4, !dbg !59
+    #dbg_declare(ptr %us1, !60, !DIExpression(DW_OP_constu, 0, DW_OP_swap, DW_OP_xderef), !61)
+  store i16 2, ptr %us1, align 2, !dbg !61
+    #dbg_declare(ptr %uc1, !62, !DIExpression(DW_OP_constu, 0, DW_OP_swap, DW_OP_xderef), !63)
+  store i8 3, ptr %uc1, align 1, !dbg !63
+    #dbg_declare(ptr %ul1, !64, !DIExpression(DW_OP_constu, 0, DW_OP_swap, DW_OP_xderef), !65)
+  store i64 4, ptr %ul1, align 8, !dbg !65
+    #dbg_declare(ptr %f1, !66, !DIExpression(DW_OP_constu, 0, DW_OP_swap, DW_OP_xderef), !67)
+  store float ...
[truncated]

@bwlodarcz
Copy link
Contributor Author

@michalpaszkowski @Keenuts @VyacheslavLevytskyy Please review. Thanks.

Copy link

github-actions bot commented Sep 2, 2024

✅ With the latest revision this PR passed the C/C++ code formatter.

@bwlodarcz bwlodarcz force-pushed the spirv_debug_basic_type branch 2 times, most recently from d943ea3 to d240f5a Compare September 2, 2024 14:08
@bwlodarcz
Copy link
Contributor Author

bwlodarcz commented Sep 2, 2024

Failed Tests (1):
LLVM :: CodeGen/SPIRV/hlsl-intrinsics/round.ll

Seems unrelated. I'm unable to reproduce the failed test on the current trunk locally.

Edit: It seems that it can be related to bug fixable by #107007. Anyway I can't reproduce the failing test.

The commit introduces support for fundamental DI instruction.
Metadata handlers required for this instruction is stored inside
debug records (https://llvm.org/docs/SourceLevelDebugging.html) parts
of the module which rises the necessity of it's traversal.
Copy link
Contributor

@MrSidims MrSidims left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, I'm a bit too late for the party. This PR is LGTM, but I have several questions for the code around.
1st is related to https://github.com/llvm/llvm-project/pull/106980/files#diff-4b1404a35b0d0bc5726da0a1774bf36112350066a39a6d66690fd96186a438e1R106 - it seem too me, that currently only one CU is supported, is it correct? The SPIR-V specification (and LLVM and dwarf themselves) doesn't push a restriction to have a single CU in the module. In LLVM IR it would be looking like !llvm.dbg.cu = !{![[#CU1:]], ![[#CU2:]]} that can be generated by either clang if certain pragmas changing compilation options is added to the code or when 2 (or more) LLVM IR modules are linked via llvm-link (a common scenario for OpenMP Fortran applications, when C++ modules are linked with Fortran - there it's crucial to have both compilation unites preserved in debug information).
2nd: https://github.com/llvm/llvm-project/pull/106980/files#diff-4b1404a35b0d0bc5726da0a1774bf36112350066a39a6d66690fd96186a438e1R117 - if DWARF information doesn't exist in the module, we shouldn't guess the version but either put zero constant (current translator's behavior) or better DebugInfoNone (but expect translator to not parse such SPIR-V - probably this should be fixed there, didn't check it yet) .

@michalpaszkowski michalpaszkowski merged commit f99bb02 into llvm:main Sep 17, 2024
9 checks passed
tmsri pushed a commit to tmsri/llvm-project that referenced this pull request Sep 19, 2024
The commit introduces support for fundamental DI instruction. Metadata
handlers required for this instruction is stored inside debug records
(https://llvm.org/docs/SourceLevelDebugging.html) parts of the module
which rises the necessity of it's traversal.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants