[llvm-branch-commits] [llvm] [SPIR-V] Emit extra DebugExpression ops under NonSemantic.Shader.DebugInfo.200 (PR #223461)

via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Mon Sep 14 11:03:31 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->

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

Author: Manuel Carrasco (mgcarrasco)

<details>
<summary>Changes</summary>

Add support for the DWARF operations that .200 requires. 

---

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


8 Files Affected:

- (modified) llvm/lib/Target/SPIRV/CMakeLists.txt (+1) 
- (modified) llvm/lib/Target/SPIRV/SPIRVNonSemanticDebugHandler.cpp (+38-17) 
- (modified) llvm/lib/Target/SPIRV/SPIRVNonSemanticDebugHandler.h (+5-3) 
- (added) llvm/lib/Target/SPIRV/SPIRVNonSemanticDebugInfo200.cpp (+159) 
- (added) llvm/lib/Target/SPIRV/SPIRVNonSemanticDebugInfo200.h (+194) 
- (added) llvm/test/CodeGen/SPIRV/debug-info/debug-declare-expression-unsupported-200.ll (+44) 
- (added) llvm/test/CodeGen/SPIRV/debug-info/debug-expression-extra-ops-200.ll (+42) 
- (added) llvm/test/CodeGen/SPIRV/debug-info/debug-expression-operations-200.ll (+53) 


``````````diff
diff --git a/llvm/lib/Target/SPIRV/CMakeLists.txt b/llvm/lib/Target/SPIRV/CMakeLists.txt
index 32026491fdaedb..ec9b513eaad21a 100644
--- a/llvm/lib/Target/SPIRV/CMakeLists.txt
+++ b/llvm/lib/Target/SPIRV/CMakeLists.txt
@@ -54,6 +54,7 @@ add_llvm_target(SPIRVCodeGen
   SPIRVTypeInst.cpp
   SPIRVUtils.cpp
   SPIRVNonSemanticDebugHandler.cpp
+  SPIRVNonSemanticDebugInfo200.cpp
   SPIRVAuxDataHandler.cpp
   SPIRVCBufferAccess.cpp
   SPIRVPushConstantAccess.cpp
diff --git a/llvm/lib/Target/SPIRV/SPIRVNonSemanticDebugHandler.cpp b/llvm/lib/Target/SPIRV/SPIRVNonSemanticDebugHandler.cpp
index 791387ac0af04a..d1c4fd59cd694b 100644
--- a/llvm/lib/Target/SPIRV/SPIRVNonSemanticDebugHandler.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVNonSemanticDebugHandler.cpp
@@ -9,6 +9,7 @@
 
 #include "SPIRVNonSemanticDebugHandler.h"
 #include "MCTargetDesc/SPIRVMCTargetDesc.h"
+#include "SPIRVNonSemanticDebugInfo200.h"
 #include "SPIRVSubtarget.h"
 #include "SPIRVUtils.h"
 #include "llvm/ADT/SetVector.h"
@@ -871,7 +872,10 @@ std::optional<MCRegister> SPIRVNonSemanticDebugHandler::mapDISignatureTypeToReg(
 
 // NonSemantic.Shader.DebugInfo.100 debug operation encodings
 // (section 4.5, "Debug Operations").
-enum class NonSemanticDebugOp : uint32_t {
+namespace llvm {
+namespace SPIRV {
+namespace NSDI100 {
+enum class DebugOp : uint32_t {
   Deref = 0,
   Plus = 1,
   Minus = 2,
@@ -883,45 +887,62 @@ enum class NonSemanticDebugOp : uint32_t {
   Constu = 8,
   Fragment = 9
 };
+} // namespace NSDI100
+} // namespace SPIRV
+} // namespace llvm
 
-static std::optional<NonSemanticDebugOp>
-mapDwarfOpToNonSemanticOp(uint64_t DwarfOp) {
+static std::optional<SPIRV::NSDI100::DebugOp>
+mapDwarfOpToDebugOp100(uint64_t DwarfOp) {
   switch (DwarfOp) {
   case dwarf::DW_OP_deref:
-    return NonSemanticDebugOp::Deref;
+    return SPIRV::NSDI100::DebugOp::Deref;
   case dwarf::DW_OP_plus:
-    return NonSemanticDebugOp::Plus;
+    return SPIRV::NSDI100::DebugOp::Plus;
   case dwarf::DW_OP_minus:
-    return NonSemanticDebugOp::Minus;
+    return SPIRV::NSDI100::DebugOp::Minus;
   case dwarf::DW_OP_plus_uconst:
-    return NonSemanticDebugOp::PlusUconst;
+    return SPIRV::NSDI100::DebugOp::PlusUconst;
   case dwarf::DW_OP_bit_piece:
-    return NonSemanticDebugOp::BitPiece;
+    return SPIRV::NSDI100::DebugOp::BitPiece;
   case dwarf::DW_OP_swap:
-    return NonSemanticDebugOp::Swap;
+    return SPIRV::NSDI100::DebugOp::Swap;
   case dwarf::DW_OP_xderef:
-    return NonSemanticDebugOp::Xderef;
+    return SPIRV::NSDI100::DebugOp::Xderef;
   case dwarf::DW_OP_stack_value:
-    return NonSemanticDebugOp::StackValue;
+    return SPIRV::NSDI100::DebugOp::StackValue;
   case dwarf::DW_OP_constu:
-    return NonSemanticDebugOp::Constu;
+    return SPIRV::NSDI100::DebugOp::Constu;
   case dwarf::DW_OP_LLVM_fragment:
-    return NonSemanticDebugOp::Fragment;
+    return SPIRV::NSDI100::DebugOp::Fragment;
   default:
     return std::nullopt;
   }
 }
 
+static std::optional<uint32_t> mapDwarfOpToDebugOpEncoding(uint64_t DwarfOp,
+                                                           unsigned NSSet) {
+  if (NSSet == SPIRV::InstructionSet::NonSemantic_Shader_DebugInfo_200) {
+    if (std::optional<SPIRV::NSDI200::DebugOp> Op200 =
+            SPIRV::NSDI200::mapDwarfOpToDebugOp200(DwarfOp))
+      return static_cast<uint32_t>(*Op200);
+  }
+
+  // .200 fallbacks to .100 for those 10 that are in the 100 set.
+  if (std::optional<SPIRV::NSDI100::DebugOp> Op100 =
+          mapDwarfOpToDebugOp100(DwarfOp))
+    return static_cast<uint32_t>(*Op100);
+  return std::nullopt;
+}
+
 std::optional<MCRegister> SPIRVNonSemanticDebugHandler::emitDebugOperation(
     const DIExpression::ExprOperand &Op, MCRegister VoidTypeReg,
     MCRegister I32TypeReg, MCRegister ExtInstSetReg,
     SPIRV::ModuleAnalysisInfo &MAI) {
-  std::optional<NonSemanticDebugOp> NSOp =
-      mapDwarfOpToNonSemanticOp(Op.getOp());
+  std::optional<uint32_t> NSOp = mapDwarfOpToDebugOpEncoding(Op.getOp(), NSSet);
   if (!NSOp)
     return std::nullopt;
 
-  SmallVector<uint32_t, 3> Key{static_cast<uint32_t>(*NSOp)};
+  SmallVector<uint32_t, DebugOperationMaxOperands> Key{*NSOp};
   for (unsigned I = 0, E = Op.getNumArgs(); I != E; ++I) {
     uint64_t Arg = Op.getArg(I);
     if (!isUInt<32>(Arg))
@@ -933,7 +954,7 @@ std::optional<MCRegister> SPIRVNonSemanticDebugHandler::emitDebugOperation(
   if (!Inserted)
     return It->second;
 
-  SmallVector<MCRegister, 3> Operands;
+  SmallVector<MCRegister, DebugOperationMaxOperands> Operands;
   for (uint32_t V : It->first)
     Operands.push_back(emitOpConstantI32(V, I32TypeReg, MAI));
   MCRegister Reg = emitExtInst(SPIRV::NonSemanticExtInst::DebugOperation,
diff --git a/llvm/lib/Target/SPIRV/SPIRVNonSemanticDebugHandler.h b/llvm/lib/Target/SPIRV/SPIRVNonSemanticDebugHandler.h
index 3f7ab14a3bb7aa..94d6750f77d47d 100644
--- a/llvm/lib/Target/SPIRV/SPIRVNonSemanticDebugHandler.h
+++ b/llvm/lib/Target/SPIRV/SPIRVNonSemanticDebugHandler.h
@@ -163,10 +163,12 @@ class SPIRVNonSemanticDebugHandler : public DebugHandlerBase {
   // ids (flags, return type, parameters).
   DenseMap<SmallVector<MCRegister, 8>, MCRegister> DebugTypeFunctionCache;
 
+  static constexpr unsigned DebugOperationMaxOperands = 4;
+
   // Cache of already-emitted DebugOperation instructions, keyed by NonSemantic
-  // opcode followed by the 32-bit operation arguments. Inline size 3 is the
-  // spec maximum (opcode plus at most two operands: BitPiece, Fragment).
-  DenseMap<SmallVector<uint32_t, 3>, MCRegister> DebugOperationCache;
+  // opcode followed by the 32-bit operation arguments.
+  DenseMap<SmallVector<uint32_t, DebugOperationMaxOperands>, MCRegister>
+      DebugOperationCache;
 
   // Cache of already-emitted DebugExpression instructions, keyed by the
   // DebugOperation result ids in operand order. Useful for debug values
diff --git a/llvm/lib/Target/SPIRV/SPIRVNonSemanticDebugInfo200.cpp b/llvm/lib/Target/SPIRV/SPIRVNonSemanticDebugInfo200.cpp
new file mode 100644
index 00000000000000..5e272c39571dc5
--- /dev/null
+++ b/llvm/lib/Target/SPIRV/SPIRVNonSemanticDebugInfo200.cpp
@@ -0,0 +1,159 @@
+//===-- SPIRVNonSemanticDebugInfo200.cpp - NSDI.200 specifics -------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "SPIRVNonSemanticDebugInfo200.h"
+#include "llvm/BinaryFormat/Dwarf.h"
+
+using namespace llvm;
+
+namespace llvm {
+namespace SPIRV {
+namespace NSDI200 {
+
+std::optional<DebugOp> mapDwarfOpToDebugOp200(uint64_t DwarfOp) {
+  if (DwarfOp >= dwarf::DW_OP_lit0 && DwarfOp <= dwarf::DW_OP_lit31)
+    return static_cast<DebugOp>(static_cast<uint32_t>(DebugOp::Lit0) +
+                                (DwarfOp - dwarf::DW_OP_lit0));
+  if (DwarfOp >= dwarf::DW_OP_reg0 && DwarfOp <= dwarf::DW_OP_reg31)
+    return static_cast<DebugOp>(static_cast<uint32_t>(DebugOp::Reg0) +
+                                (DwarfOp - dwarf::DW_OP_reg0));
+  if (DwarfOp >= dwarf::DW_OP_breg0 && DwarfOp <= dwarf::DW_OP_breg31)
+    return static_cast<DebugOp>(static_cast<uint32_t>(DebugOp::Breg0) +
+                                (DwarfOp - dwarf::DW_OP_breg0));
+
+  switch (DwarfOp) {
+  case dwarf::DW_OP_LLVM_convert:
+    return DebugOp::Convert;
+  case dwarf::DW_OP_addr:
+    return DebugOp::Addr;
+  case dwarf::DW_OP_const1u:
+    return DebugOp::Const1u;
+  case dwarf::DW_OP_const1s:
+    return DebugOp::Const1s;
+  case dwarf::DW_OP_const2u:
+    return DebugOp::Const2u;
+  case dwarf::DW_OP_const2s:
+    return DebugOp::Const2s;
+  case dwarf::DW_OP_const4u:
+    return DebugOp::Const4u;
+  case dwarf::DW_OP_const4s:
+    return DebugOp::Const4s;
+  case dwarf::DW_OP_const8u:
+    return DebugOp::Const8u;
+  case dwarf::DW_OP_const8s:
+    return DebugOp::Const8s;
+  case dwarf::DW_OP_consts:
+    return DebugOp::Consts;
+  case dwarf::DW_OP_dup:
+    return DebugOp::Dup;
+  case dwarf::DW_OP_drop:
+    return DebugOp::Drop;
+  case dwarf::DW_OP_over:
+    return DebugOp::Over;
+  case dwarf::DW_OP_pick:
+    return DebugOp::Pick;
+  case dwarf::DW_OP_rot:
+    return DebugOp::Rot;
+  case dwarf::DW_OP_abs:
+    return DebugOp::Abs;
+  case dwarf::DW_OP_and:
+    return DebugOp::And;
+  case dwarf::DW_OP_div:
+    return DebugOp::Div;
+  case dwarf::DW_OP_mod:
+    return DebugOp::Mod;
+  case dwarf::DW_OP_mul:
+    return DebugOp::Mul;
+  case dwarf::DW_OP_neg:
+    return DebugOp::Neg;
+  case dwarf::DW_OP_not:
+    return DebugOp::Not;
+  case dwarf::DW_OP_or:
+    return DebugOp::Or;
+  case dwarf::DW_OP_shl:
+    return DebugOp::Shl;
+  case dwarf::DW_OP_shr:
+    return DebugOp::Shr;
+  case dwarf::DW_OP_shra:
+    return DebugOp::Shra;
+  case dwarf::DW_OP_xor:
+    return DebugOp::Xor;
+  case dwarf::DW_OP_bra:
+    return DebugOp::Bra;
+  case dwarf::DW_OP_eq:
+    return DebugOp::Eq;
+  case dwarf::DW_OP_ge:
+    return DebugOp::Ge;
+  case dwarf::DW_OP_gt:
+    return DebugOp::Gt;
+  case dwarf::DW_OP_le:
+    return DebugOp::Le;
+  case dwarf::DW_OP_lt:
+    return DebugOp::Lt;
+  case dwarf::DW_OP_ne:
+    return DebugOp::Ne;
+  case dwarf::DW_OP_skip:
+    return DebugOp::Skip;
+  case dwarf::DW_OP_regx:
+    return DebugOp::Regx;
+  case dwarf::DW_OP_bregx:
+    return DebugOp::Bregx;
+  case dwarf::DW_OP_piece:
+    return DebugOp::Piece;
+  case dwarf::DW_OP_deref_size:
+    return DebugOp::DerefSize;
+  case dwarf::DW_OP_xderef_size:
+    return DebugOp::XderefSize;
+  case dwarf::DW_OP_nop:
+    return DebugOp::Nop;
+  case dwarf::DW_OP_push_object_address:
+    return DebugOp::PushObjectAddress;
+  case dwarf::DW_OP_call2:
+    return DebugOp::Call2;
+  case dwarf::DW_OP_call4:
+    return DebugOp::Call4;
+  case dwarf::DW_OP_call_ref:
+    return DebugOp::CallRef;
+  case dwarf::DW_OP_form_tls_address:
+    return DebugOp::FormTlsAddress;
+  case dwarf::DW_OP_call_frame_cfa:
+    return DebugOp::CallFrameCfa;
+  case dwarf::DW_OP_implicit_value:
+    return DebugOp::ImplicitValue;
+  case dwarf::DW_OP_implicit_pointer:
+    return DebugOp::ImplicitPointer;
+  case dwarf::DW_OP_addrx:
+    return DebugOp::Addrx;
+  case dwarf::DW_OP_constx:
+    return DebugOp::Constx;
+  case dwarf::DW_OP_entry_value:
+    return DebugOp::EntryValue;
+  case dwarf::DW_OP_const_type:
+    return DebugOp::ConstTypeOp;
+  case dwarf::DW_OP_regval_type:
+    return DebugOp::RegvalType;
+  case dwarf::DW_OP_deref_type:
+    return DebugOp::DerefType;
+  case dwarf::DW_OP_xderef_type:
+    return DebugOp::XderefType;
+  case dwarf::DW_OP_reinterpret:
+    return DebugOp::Reinterpret;
+  case dwarf::DW_OP_LLVM_arg:
+    return DebugOp::LLVMArg;
+  case dwarf::DW_OP_LLVM_implicit_pointer:
+    return DebugOp::ImplicitPointerTag;
+  case dwarf::DW_OP_LLVM_tag_offset:
+    return DebugOp::TagOffset;
+  default:
+    return std::nullopt;
+  }
+}
+
+} // namespace NSDI200
+} // namespace SPIRV
+} // namespace llvm
diff --git a/llvm/lib/Target/SPIRV/SPIRVNonSemanticDebugInfo200.h b/llvm/lib/Target/SPIRV/SPIRVNonSemanticDebugInfo200.h
new file mode 100644
index 00000000000000..05069148cca8b4
--- /dev/null
+++ b/llvm/lib/Target/SPIRV/SPIRVNonSemanticDebugInfo200.h
@@ -0,0 +1,194 @@
+//===-- SPIRVNonSemanticDebugInfo200.h - NSDI.200 ---------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// NonSemantic.Shader.DebugInfo.200-specific lowering.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIB_TARGET_SPIRV_SPIRVNONSEMANTICDEBUGINFO200_H
+#define LLVM_LIB_TARGET_SPIRV_SPIRVNONSEMANTICDEBUGINFO200_H
+
+#include <cstdint>
+#include <optional>
+
+namespace llvm {
+namespace SPIRV {
+namespace NSDI200 {
+
+// Additional DebugOperation encodings for NonSemantic.Shader.DebugInfo.200.
+enum class DebugOp : uint32_t {
+  Convert = 10,
+  Addr = 11,
+  Const1u = 12,
+  Const1s = 13,
+  Const2u = 14,
+  Const2s = 15,
+  Const4u = 16,
+  Const4s = 17,
+  Const8u = 18,
+  Const8s = 19,
+  Consts = 20,
+  Dup = 21,
+  Drop = 22,
+  Over = 23,
+  Pick = 24,
+  Rot = 25,
+  Abs = 26,
+  And = 27,
+  Div = 28,
+  Mod = 29,
+  Mul = 30,
+  Neg = 31,
+  Not = 32,
+  Or = 33,
+  Shl = 34,
+  Shr = 35,
+  Shra = 36,
+  Xor = 37,
+  Bra = 38,
+  Eq = 39,
+  Ge = 40,
+  Gt = 41,
+  Le = 42,
+  Lt = 43,
+  Ne = 44,
+  Skip = 45,
+  Lit0 = 46,
+  Lit1 = 47,
+  Lit2 = 48,
+  Lit3 = 49,
+  Lit4 = 50,
+  Lit5 = 51,
+  Lit6 = 52,
+  Lit7 = 53,
+  Lit8 = 54,
+  Lit9 = 55,
+  Lit10 = 56,
+  Lit11 = 57,
+  Lit12 = 58,
+  Lit13 = 59,
+  Lit14 = 60,
+  Lit15 = 61,
+  Lit16 = 62,
+  Lit17 = 63,
+  Lit18 = 64,
+  Lit19 = 65,
+  Lit20 = 66,
+  Lit21 = 67,
+  Lit22 = 68,
+  Lit23 = 69,
+  Lit24 = 70,
+  Lit25 = 71,
+  Lit26 = 72,
+  Lit27 = 73,
+  Lit28 = 74,
+  Lit29 = 75,
+  Lit30 = 76,
+  Lit31 = 77,
+  Reg0 = 78,
+  Reg1 = 79,
+  Reg2 = 80,
+  Reg3 = 81,
+  Reg4 = 82,
+  Reg5 = 83,
+  Reg6 = 84,
+  Reg7 = 85,
+  Reg8 = 86,
+  Reg9 = 87,
+  Reg10 = 88,
+  Reg11 = 89,
+  Reg12 = 90,
+  Reg13 = 91,
+  Reg14 = 92,
+  Reg15 = 93,
+  Reg16 = 94,
+  Reg17 = 95,
+  Reg18 = 96,
+  Reg19 = 97,
+  Reg20 = 98,
+  Reg21 = 99,
+  Reg22 = 100,
+  Reg23 = 101,
+  Reg24 = 102,
+  Reg25 = 103,
+  Reg26 = 104,
+  Reg27 = 105,
+  Reg28 = 106,
+  Reg29 = 107,
+  Reg30 = 108,
+  Reg31 = 109,
+  Breg0 = 110,
+  Breg1 = 111,
+  Breg2 = 112,
+  Breg3 = 113,
+  Breg4 = 114,
+  Breg5 = 115,
+  Breg6 = 116,
+  Breg7 = 117,
+  Breg8 = 118,
+  Breg9 = 119,
+  Breg10 = 120,
+  Breg11 = 121,
+  Breg12 = 122,
+  Breg13 = 123,
+  Breg14 = 124,
+  Breg15 = 125,
+  Breg16 = 126,
+  Breg17 = 127,
+  Breg18 = 128,
+  Breg19 = 129,
+  Breg20 = 130,
+  Breg21 = 131,
+  Breg22 = 132,
+  Breg23 = 133,
+  Breg24 = 134,
+  Breg25 = 135,
+  Breg26 = 136,
+  Breg27 = 137,
+  Breg28 = 138,
+  Breg29 = 139,
+  Breg30 = 140,
+  Breg31 = 141,
+  Regx = 142,
+  Fbreg = 143,
+  Bregx = 144,
+  Piece = 145,
+  DerefSize = 146,
+  XderefSize = 147,
+  Nop = 148,
+  PushObjectAddress = 149,
+  Call2 = 150,
+  Call4 = 151,
+  CallRef = 152,
+  FormTlsAddress = 153,
+  CallFrameCfa = 154,
+  ImplicitValue = 155,
+  ImplicitPointer = 156,
+  Addrx = 157,
+  Constx = 158,
+  EntryValue = 159,
+  ConstTypeOp = 160,
+  RegvalType = 161,
+  DerefType = 162,
+  XderefType = 163,
+  Reinterpret = 164,
+  LLVMArg = 165,
+  ImplicitPointerTag = 166,
+  TagOffset = 167,
+};
+
+/// Map a DWARF location opcode to a .200-only DebugOperation encoding.
+/// Returns nullopt for the .100 set (encodings 0-9); those are mapped
+/// separately.
+std::optional<DebugOp> mapDwarfOpToDebugOp200(uint64_t DwarfOp);
+
+} // namespace NSDI200
+} // namespace SPIRV
+} // namespace llvm
+
+#endif // LLVM_LIB_TARGET_SPIRV_SPIRVNONSEMANTICDEBUGINFO200_H
diff --git a/llvm/test/CodeGen/SPIRV/debug-info/debug-declare-expression-unsupported-200.ll b/llvm/test/CodeGen/SPIRV/debug-info/debug-declare-expression-unsupported-200.ll
new file mode 100644
index 00000000000000..fcadb1b68a03c9
--- /dev/null
+++ b/llvm/test/CodeGen/SPIRV/debug-info/debug-declare-expression-unsupported-200.ll
@@ -0,0 +1,44 @@
+; RUN: llc --verify-machineinstrs -O0 -mtriple=spirv64-unknown-unknown --spirv-ext=+SPV_KHR_non_semantic_info %s -o - | FileCheck %s --check-prefix=CHECK-100 --implicit-check-not=DebugDeclare --implicit-check-not=DebugExpression --implicit-check-not=DebugOperation
+; RUN: llc --verify-machineinstrs -O0 -mtriple=spirv64-unknown-unknown --spirv-ext=+SPV_KHR_non_semantic_info -spirv-nonsemantic-debug-info-version=200 %s -o - | FileCheck %s --check-prefix=CHECK-200
+; 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 %}
+; RUN: %if spirv-tools %{ llc --verify-machineinstrs --spirv-ext=+SPV_KHR_non_semantic_info -O0 -mtriple=spirv64-unknown-unknown -spirv-nonsemantic-debug-info-version=200 %s -o - -filetype=obj | spirv-val %}
+
+; DW_OP_LLVM_convert has no .100 encoding, so the expression (and declare) are
+; dropped. The same IR is emitted under .200 as DebugOperation opcode 10.
+
+; CHECK-100: OpExtInstImport "NonSemantic.Shader.DebugInfo.100"
+; CHECK-100: OpExtInst {{.*}} DebugLocalVariable
+
+; CHECK-200-DAG: [[EXT:%[0-9]+]] = OpExtInstImport "NonSemantic.Shader.DebugInfo.200"
+; CHECK-200-DAG: [[VOID:%[0-9]+]] = OpTypeVoid
+; CHECK-200-DAG: [[I32T:%[0-9]+]] = OpTypeInt 32 0
+; CHECK-200-DAG: [[C10:%[0-9]+]] = OpConstant [[I32T]] 10{{ *$}}
+; CHECK-200-DAG: [[C32:%[0-9]+]] = OpConstant [[I32T]] 32{{ *$}}
+; CHECK-200-DAG: [[C5:%[0-9]+]] = OpConstant [[I32T]] 5{{ *$}}
+; CHECK-200-DAG: [[CONV:%[0-9]+]] = OpExtInst [[VOID]] [[EXT]] DebugOperation [[C10]] [[C32]] [[C5]]{{ *$}}
+; CHECK-200-DAG: [[EXPR:%[0-9]+]] = OpExtInst [[VOID]] [[EXT]] DebugExpression [[CONV]]{{ *$}}
+; CHECK-200: OpExtInst [[VOID]] [[EXT]] DebugDeclare {{%[0-9]+}} {{%[0-9]+}} [[EXPR]]
+
+target triple = "spirv64-unknown-unknown"
+
+define spir_func void @f() !dbg !5 {
+entry:
+  %x = alloca i32, align 4
+    #dbg_declare(ptr %x, !9, !DIExpression(DW_OP_LLVM_convert, 32, DW_ATE_signed), !10)
+  store i32 1, ptr %x, align 4, !dbg !10
+  ret void, !dbg !10
+}
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!2, !3}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, splitDebugInlining: false, nameTableKind: None)
+!1 = !DIFile(filename: "debug-declare-expression-unsupported-200.c", directory: "/src")
+!2 = !{i32 7, !"Dwarf Version", i32 5}
+!3 = !{i32 2, !"Debug Info Version", i32 3}
+!4 = !DISubroutineType(types: !6)
+!6 = !{null}
+!7 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+!5 = distinct !DISubprogram(name: "f", linkageName: "f", scope: !1, file: !1, line: 1, type: !4, scopeLine: 1, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0)
+!9 = !DILocalVariable(name: "x", scope: !5, file: !1, line: 2, type: !7)
+!10 = !DILocation(line: 3, column: 1, scope: !5)
diff --git a/llvm/test/CodeGen/SPIRV/debug-info/debug-expression-extra-ops-200.ll b/llvm/test/CodeGen/SPIRV/debug-info/debug-expression-extra-ops-200.ll
new file mode 100644
index 00000000000000..fde8c7d4a75932
--- /dev/null
+++ b/llvm/test/CodeGen/SPIRV/debug-info/debug-expression-extra-ops-200.ll
@@ -0,0 +1,42 @@
+; RUN: llc --verify-machineinstrs -O0 -mtriple=spirv64-unknown-unknown --spirv-ext=+SPV_KHR_non_semantic_info -spirv-nonsemantic-debug-info-version=200 %s -o - | FileCheck %s
+; RUN: %if spirv-tools %{ llc --verify-machineinstrs --spirv-ext=+SPV_KHR_non_semantic_info -O0 -mtriple=spirv64-unknown-unknown -spirv-nonsemantic-debug-info-version=200 %s -o - -filetype=obj | spirv-val %}
+
+; Extra debug operations (encoding > Fragment) are only emitted when the
+; NonSemantic.Shader.DebugInfo.200 extension set is selected.
+
+; CHECK-DAG: [[EXT:%[0-9]+]] = OpExtInstImport "NonSemantic.Shader.DebugInfo.200"
+; CHECK-DAG: [[VOID:%[0-9]+]] = OpTypeVoid
+; CHECK-DAG: [[I32T:%[0-9]+]] = OpTypeInt 32 0
+; CHECK-DAG: [[C10:%[0-9]+]] = OpConstant [[I32T]] 10{{ *$}}
+; CHECK-DAG: [[C30:%[0-9]+]] = OpConstant [[I32T]] 30{{ *$}}
+; CHECK-DAG: [[C32:%[0-9]+]] = OpConstant [[I32T]] 32{{ *$}}
+; CHECK-DAG: [[C5:%[0-9]+]] = OpConstant [[I32T]] 5{{ *$}}
+
+; CHECK-DAG: [[CONV:%[0-9]+]] = OpExtInst [[VOID]] [[EXT]] DebugOperation [[C10]] [[C32]] [[C5]]{{ *$}}
+; CHECK-DAG: [[MUL:%[0-9]+]] = OpExtInst [[VOID]] [[EXT]] DebugOperation [[C30]]{{ *$}}
+; CHECK-DAG: [[EXPR:%[0-9]+]] = OpExtInst [[VOID]] [[EXT]] DebugExpression [[CONV]] [[MUL]]{{ *$}}
+; CHECK: OpExtInst [[VOID]] [[EXT]] DebugDeclare {{%[0-9]+}} {{%[0-9]+}} [[EXPR]]
+
+target triple = "spirv64-unknown-unknown"
+
+define spir_func void @f() !dbg !5 {
+entry:
+  %x = alloca i32, align 4
+    #dbg_declare(ptr %x, !9, !DIExpression(DW_OP_LLVM_convert, 32, DW_ATE_signed, DW_OP_mul), !10)
+  store i32 1, ptr %x, align 4, !dbg !10
+  ret void, !dbg !10
+}
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!2, !3}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang", isOptimized: false, run...
[truncated]

``````````

</details>


https://github.com/llvm/llvm-project/pull/223461


More information about the llvm-branch-commits mailing list