https://github.com/enferex created 
https://github.com/llvm/llvm-project/pull/216314

DW_OP_NVIDIA_mux (0xeb) takes a 1-byte unsigned selector, giving NVIDIA an 
extension space behind a single opcode in the crowded 
DW_OP_lo_user..DW_OP_hi_user range. The selector is opaque to LLVM; no NVIDIA 
operation semantics are defined here.

Assissted-by: LLM

>From b30ca547804cfc30b0d15484aa18a65f340e0f2f Mon Sep 17 00:00:00 2001
From: Matt Davis <[email protected]>
Date: Thu, 13 Aug 2026 18:36:19 +0000
Subject: [PATCH] [DWARF] Add DW_OP_NVIDIA_mux vendor extension

DW_OP_NVIDIA_mux (0xeb) takes a 1-byte unsigned selector, giving NVIDIA
an extension space behind a single opcode in the crowded
DW_OP_lo_user..DW_OP_hi_user range. The selector is opaque to LLVM; no
NVIDIA operation semantics are defined here.

Assissted-by: LLM
---
 lldb/source/Expression/DWARFExpression.cpp    |  1 +
 llvm/include/llvm/BinaryFormat/Dwarf.def      |  7 ++++
 llvm/include/llvm/BinaryFormat/Dwarf.h        |  1 +
 .../DWARF/LowLevel/DWARFExpression.cpp        |  2 +
 llvm/unittests/BinaryFormat/DwarfTest.cpp     | 11 ++++++
 .../DWARFExpressionCompactPrinterTest.cpp     | 39 +++++++++++++++++++
 6 files changed, 61 insertions(+)

diff --git a/lldb/source/Expression/DWARFExpression.cpp 
b/lldb/source/Expression/DWARFExpression.cpp
index 2dbf61a14eac4..8b5944f206675 100644
--- a/lldb/source/Expression/DWARFExpression.cpp
+++ b/lldb/source/Expression/DWARFExpression.cpp
@@ -214,6 +214,7 @@ GetOpcodeDataSize(const DataExtractor &data, const 
lldb::offset_t data_offset,
   case DW_OP_HP_unmod_range:
   case DW_OP_HP_tls:
   case DW_OP_INTEL_bit_piece:
+  case DW_OP_NVIDIA_mux:
   case DW_OP_WASM_location:
   case DW_OP_WASM_location_int:
   case DW_OP_APPLE_uninit:
diff --git a/llvm/include/llvm/BinaryFormat/Dwarf.def 
b/llvm/include/llvm/BinaryFormat/Dwarf.def
index 32195aae562c3..885216bdc2de9 100644
--- a/llvm/include/llvm/BinaryFormat/Dwarf.def
+++ b/llvm/include/llvm/BinaryFormat/Dwarf.def
@@ -920,6 +920,13 @@ HANDLE_DW_OP(0xe5, HP_unmod_range, -1, -1, 0, HP)
 HANDLE_DW_OP(0xe6, HP_tls, -1, -1, 0, HP)
 HANDLE_DW_OP(0xe8, INTEL_bit_piece, -1, -1, 0, INTEL)
 
+// Extension for NVIDIA. DW_OP_NVIDIA_mux acts as an extension multiplexer: its
+// single 1-byte unsigned operand selects an NVIDIA-specific operation. This
+// keeps the cost of the whole NVIDIA extension family at one encoding in the
+// scarce DW_OP_lo_user..DW_OP_hi_user range. The selector value is opaque to
+// LLVM; no NVIDIA operation semantics are defined here.
+HANDLE_DW_OP(0xeb, NVIDIA_mux, 1, -1, 0, NVIDIA)
+
 // Extensions for WebAssembly.
 HANDLE_DW_OP(0xed, WASM_location, -1, -1, 0, WASM)
 HANDLE_DW_OP(0xee, WASM_location_int, -1, -1, 0, WASM)
diff --git a/llvm/include/llvm/BinaryFormat/Dwarf.h 
b/llvm/include/llvm/BinaryFormat/Dwarf.h
index 46124019206f2..ee7031b239479 100644
--- a/llvm/include/llvm/BinaryFormat/Dwarf.h
+++ b/llvm/include/llvm/BinaryFormat/Dwarf.h
@@ -83,6 +83,7 @@ enum LLVMConstants : uint32_t {
   DWARF_VENDOR_HP,
   DWARF_VENDOR_IBM,
   DWARF_VENDOR_INTEL,
+  DWARF_VENDOR_NVIDIA,
   DWARF_VENDOR_PGI,
   DWARF_VENDOR_SUN,
   DWARF_VENDOR_UPC,
diff --git a/llvm/lib/DebugInfo/DWARF/LowLevel/DWARFExpression.cpp 
b/llvm/lib/DebugInfo/DWARF/LowLevel/DWARFExpression.cpp
index 61bd6fcb65bfa..654fb459feb37 100644
--- a/llvm/lib/DebugInfo/DWARF/LowLevel/DWARFExpression.cpp
+++ b/llvm/lib/DebugInfo/DWARF/LowLevel/DWARFExpression.cpp
@@ -103,6 +103,8 @@ static std::vector<Desc> getOpDescriptions() {
   Descriptions[DW_OP_GNU_entry_value] = Desc(Op::Dwarf4, Op::SizeLEB);
   Descriptions[DW_OP_GNU_implicit_pointer] =
       Desc(Op::Dwarf4, Op::SizeRefAddr, Op::SignedSizeLEB);
+  // The operand is an opaque 8-bit selector for an NVIDIA-specific operation.
+  Descriptions[DW_OP_NVIDIA_mux] = Desc(Op::Dwarf5, Op::Size1);
   // This Description acts as a marker that getSubOpDesc must be called
   // to fetch the final Description for the operation. Each such final
   // Description must share the same first SizeSubOpLEB operand.
diff --git a/llvm/unittests/BinaryFormat/DwarfTest.cpp 
b/llvm/unittests/BinaryFormat/DwarfTest.cpp
index c9522226c6031..0366bd7b7610e 100644
--- a/llvm/unittests/BinaryFormat/DwarfTest.cpp
+++ b/llvm/unittests/BinaryFormat/DwarfTest.cpp
@@ -48,6 +48,9 @@ TEST(DwarfTest, getOperationEncoding) {
   EXPECT_EQ(DW_OP_deref, getOperationEncoding("DW_OP_deref"));
   EXPECT_EQ(DW_OP_bit_piece, getOperationEncoding("DW_OP_bit_piece"));
 
+  // A vendor extension.
+  EXPECT_EQ(DW_OP_NVIDIA_mux, getOperationEncoding("DW_OP_NVIDIA_mux"));
+
   // Invalid ops.
   EXPECT_EQ(0u, getOperationEncoding("DW_OP_otherthings"));
   EXPECT_EQ(0u, getOperationEncoding("other"));
@@ -57,6 +60,14 @@ TEST(DwarfTest, getOperationEncoding) {
   EXPECT_EQ(0u, getOperationEncoding("DW_OP_hi_user"));
 }
 
+TEST(DwarfTest, OperationEncodingString) {
+  // A vendor extension.
+  EXPECT_EQ("DW_OP_NVIDIA_mux", OperationEncodingString(DW_OP_NVIDIA_mux));
+
+  // Unassigned encodings in the vendor range shouldn't be stringified.
+  EXPECT_EQ(StringRef(), OperationEncodingString(DW_OP_hi_user));
+}
+
 TEST(DwarfTest, LanguageStringOnInvalid) {
   // This is invalid, so it shouldn't be stringified.
   EXPECT_EQ(StringRef(), LanguageString(0));
diff --git 
a/llvm/unittests/DebugInfo/DWARF/DWARFExpressionCompactPrinterTest.cpp 
b/llvm/unittests/DebugInfo/DWARF/DWARFExpressionCompactPrinterTest.cpp
index e328f0ffa8809..a853a22360c95 100644
--- a/llvm/unittests/DebugInfo/DWARF/DWARFExpressionCompactPrinterTest.cpp
+++ b/llvm/unittests/DebugInfo/DWARF/DWARFExpressionCompactPrinterTest.cpp
@@ -208,6 +208,45 @@ TEST_F(DWARFExpressionCompactPrinterTest, 
Test_OP_LLVM_user_unknown_subop) {
                          "DW_OP_LLVM_form_aspace_address (2)>");
 }
 
+// DW_OP_NVIDIA_mux carries an opaque 8-bit selector, so the compact printer
+// cannot know its stack effect and must bail out naming the opcode.
+TEST_F(DWARFExpressionCompactPrinterTest, Test_OP_NVIDIA_mux) {
+  TestExprPrinterFailure({DW_OP_NVIDIA_mux, 0xa5},
+                         "<unknown op DW_OP_NVIDIA_mux (235)>");
+}
+
+// The selector is a fixed 1-byte operand, so the full printer must consume
+// exactly one byte and print its value.
+TEST(NVIDIAMux, Full_DW_OP_NVIDIA_mux) {
+  const uint8_t Enc[] = {DW_OP_NVIDIA_mux, 0xa5};
+
+  std::string Result;
+  raw_string_ostream OS(Result);
+  DataExtractor DE(Enc, true);
+  DWARFExpression Expr(DE, 8);
+
+  DIDumpOptions DumpOpts;
+  printDwarfExpression(&Expr, OS, DumpOpts, nullptr);
+
+  EXPECT_EQ(OS.str(), "DW_OP_NVIDIA_mux 0xa5");
+}
+
+// A trailing operation must still decode, proving the selector advanced the
+// offset by exactly one byte.
+TEST(NVIDIAMux, Full_DW_OP_NVIDIA_mux_TrailingOp) {
+  const uint8_t Enc[] = {DW_OP_NVIDIA_mux, 0xa5, DW_OP_stack_value};
+
+  std::string Result;
+  raw_string_ostream OS(Result);
+  DataExtractor DE(Enc, true);
+  DWARFExpression Expr(DE, 8);
+
+  DIDumpOptions DumpOpts;
+  printDwarfExpression(&Expr, OS, DumpOpts, nullptr);
+
+  EXPECT_EQ(OS.str(), "DW_OP_NVIDIA_mux 0xa5, DW_OP_stack_value");
+}
+
 // NVPTX packs virtual register names into DWARF register numbers, so compact
 // printing without a callback must recover the name and return true.
 TEST(NVPTXPackedRegister, Compact_DW_OP_regx_NoMRI) {

_______________________________________________
lldb-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to