Skip to content

[lldb][NFC] Explicitly list unsupported DWARF expression opcodes#210363

Open
firmiana402 wants to merge 1 commit into
llvm:mainfrom
firmiana402:nfc-lldb-clarify-dwarf-expression-opcodes
Open

[lldb][NFC] Explicitly list unsupported DWARF expression opcodes#210363
firmiana402 wants to merge 1 commit into
llvm:mainfrom
firmiana402:nfc-lldb-clarify-dwarf-expression-opcodes

Conversation

@firmiana402

Copy link
Copy Markdown
Contributor

This PR addresses #202251.

Several opcodes recognized by LLDB's DWARF expression decoding logic currently have no explicit case in DWARFExpression::Evaluate. They therefore reach the generic default path, which makes it unclear whether their evaluator status is intentional or an omission.

Explicitly list the affected opcodes and group them with the existing DW_OP_xderef, DW_OP_xderef_size, DW_OP_call2, and DW_OP_call4 cases. All twelve known but unsupported opcodes now share an unimplemented opcode return, while default remains responsible for unknown and vendor-handled opcodes. No opcode evaluation semantics change.

The affected opcodes are DW_OP_call_ref, DW_OP_constx, DW_OP_const_type, DW_OP_regval_type, DW_OP_deref_type, DW_OP_xderef_type, DW_OP_reinterpret, and DW_OP_GNU_implicit_pointer.

Tests

The existing per-opcode status-locking tests in DWARFExpressionTest.cpp cover all affected cases and are updated to check the unified diagnostic.

@firmiana402
firmiana402 marked this pull request as ready for review July 17, 2026 16:41
@llvmorg-github-actions

Copy link
Copy Markdown

@llvm/pr-subscribers-lldb

Author: firmiana (firmiana402)

Changes

This PR addresses #202251.

Several opcodes recognized by LLDB's DWARF expression decoding logic currently have no explicit case in DWARFExpression::Evaluate. They therefore reach the generic default path, which makes it unclear whether their evaluator status is intentional or an omission.

Explicitly list the affected opcodes and group them with the existing DW_OP_xderef, DW_OP_xderef_size, DW_OP_call2, and DW_OP_call4 cases. All twelve known but unsupported opcodes now share an unimplemented opcode return, while default remains responsible for unknown and vendor-handled opcodes. No opcode evaluation semantics change.

The affected opcodes are DW_OP_call_ref, DW_OP_constx, DW_OP_const_type, DW_OP_regval_type, DW_OP_deref_type, DW_OP_xderef_type, DW_OP_reinterpret, and DW_OP_GNU_implicit_pointer.

Tests

The existing per-opcode status-locking tests in DWARFExpressionTest.cpp cover all affected cases and are updated to check the unified diagnostic.


Full diff: https://github.com/llvm/llvm-project/pull/210363.diff

2 Files Affected:

  • (modified) lldb/source/Expression/DWARFExpression.cpp (+16-10)
  • (modified) lldb/unittests/Expression/DWARFExpressionTest.cpp (+20-26)
diff --git a/lldb/source/Expression/DWARFExpression.cpp b/lldb/source/Expression/DWARFExpression.cpp
index 299dbe97d6176..2dbf61a14eac4 100644
--- a/lldb/source/Expression/DWARFExpression.cpp
+++ b/lldb/source/Expression/DWARFExpression.cpp
@@ -1457,11 +1457,6 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
         return err;
     } break;
 
-    case DW_OP_xderef_size:
-      return llvm::createStringError("unimplemented opcode: DW_OP_xderef_size");
-    case DW_OP_xderef:
-      return llvm::createStringError("unimplemented opcode: DW_OP_xderef");
-
     case DW_OP_const1u:
       stack.push_back(to_generic(op->getRawOperand(0)));
       break;
@@ -2015,11 +2010,6 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
       }
       break;
 
-    case DW_OP_call2:
-      return llvm::createStringError("unimplemented opcode DW_OP_call2");
-    case DW_OP_call4:
-      return llvm::createStringError("unimplemented opcode DW_OP_call4");
-
     case DW_OP_stack_value:
       eval_ctx.loc_desc_kind = Implicit;
       stack.back().SetValueType(Value::ValueType::Scalar);
@@ -2092,6 +2082,22 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
       continue;
     }
 
+    // These opcodes are decoded but not evaluated here.
+    case DW_OP_xderef:
+    case DW_OP_xderef_size:
+    case DW_OP_call2:
+    case DW_OP_call4:
+    case DW_OP_call_ref:
+    case DW_OP_constx:
+    case DW_OP_const_type:
+    case DW_OP_regval_type:
+    case DW_OP_deref_type:
+    case DW_OP_xderef_type:
+    case DW_OP_reinterpret:
+    case DW_OP_GNU_implicit_pointer:
+      return llvm::createStringError("unimplemented opcode %s",
+                                     DW_OP_value_to_name(opcode));
+
     default:
       if (eval_ctx.dwarf_cu) {
         const uint64_t operands_offset = op_offset + 1;
diff --git a/lldb/unittests/Expression/DWARFExpressionTest.cpp b/lldb/unittests/Expression/DWARFExpressionTest.cpp
index 6df4553757de4..e8bca7208c8d5 100644
--- a/lldb/unittests/Expression/DWARFExpressionTest.cpp
+++ b/lldb/unittests/Expression/DWARFExpressionTest.cpp
@@ -1176,13 +1176,13 @@ TEST(DWARFExpression, DW_OP_deref_size_too_large) {
 TEST(DWARFExpression, DW_OP_xderef_unimplemented) {
   EXPECT_THAT_EXPECTED(
       Evaluate({DW_OP_lit0, DW_OP_lit0, DW_OP_xderef}),
-      llvm::FailedWithMessage("unimplemented opcode: DW_OP_xderef"));
+      llvm::FailedWithMessage("unimplemented opcode DW_OP_xderef"));
 }
 
 TEST(DWARFExpression, DW_OP_xderef_size_unimplemented) {
   EXPECT_THAT_EXPECTED(
       Evaluate({DW_OP_lit0, DW_OP_lit0, DW_OP_xderef_size, 4}),
-      llvm::FailedWithMessage("unimplemented opcode: DW_OP_xderef_size"));
+      llvm::FailedWithMessage("unimplemented opcode DW_OP_xderef_size"));
 }
 
 TEST(DWARFExpression, DW_OP_call2_unimplemented) {
@@ -1197,12 +1197,11 @@ TEST(DWARFExpression, DW_OP_call4_unimplemented) {
       llvm::FailedWithMessage("unimplemented opcode DW_OP_call4"));
 }
 
-TEST(DWARFExpression, DW_OP_call_ref_unhandled) {
+TEST(DWARFExpression, DW_OP_call_ref_unimplemented) {
   // call_ref has stack arity 1 in LLVM's table, so push a value first.
   EXPECT_THAT_EXPECTED(
       Evaluate({DW_OP_lit0, DW_OP_call_ref, 0x00, 0x00, 0x00, 0x00}),
-      llvm::FailedWithMessage(
-          "unhandled opcode DW_OP_call_ref in DWARFExpression"));
+      llvm::FailedWithMessage("unimplemented opcode DW_OP_call_ref"));
 }
 
 TEST(DWARFExpression, DW_OP_implicit_pointer_unimplemented) {
@@ -1211,53 +1210,48 @@ TEST(DWARFExpression, DW_OP_implicit_pointer_unimplemented) {
       llvm::Failed());
 }
 
-TEST(DWARFExpression, DW_OP_GNU_implicit_pointer_unhandled) {
+TEST(DWARFExpression, DW_OP_GNU_implicit_pointer_unimplemented) {
   EXPECT_THAT_EXPECTED(
       Evaluate({DW_OP_GNU_implicit_pointer, 0x00, 0x00, 0x00, 0x00, 0x00}),
       llvm::FailedWithMessage(
-          "unhandled opcode DW_OP_GNU_implicit_pointer in DWARFExpression"));
+          "unimplemented opcode DW_OP_GNU_implicit_pointer"));
 }
 
-TEST(DWARFExpression, DW_OP_const_type_unhandled) {
+TEST(DWARFExpression, DW_OP_const_type_unimplemented) {
   // const_type: ULEB128 type DIE offset, 1-byte size, N-byte value block.
   EXPECT_THAT_EXPECTED(
       Evaluate({DW_OP_const_type, 0x00, 0x04, 0x01, 0x00, 0x00, 0x00}),
-      llvm::FailedWithMessage(
-          "unhandled opcode DW_OP_const_type in DWARFExpression"));
+      llvm::FailedWithMessage("unimplemented opcode DW_OP_const_type"));
 }
 
-TEST(DWARFExpression, DW_OP_regval_type_unhandled) {
+TEST(DWARFExpression, DW_OP_regval_type_unimplemented) {
   EXPECT_THAT_EXPECTED(
       Evaluate({DW_OP_regval_type, 0x00, 0x00}),
-      llvm::FailedWithMessage(
-          "unhandled opcode DW_OP_regval_type in DWARFExpression"));
+      llvm::FailedWithMessage("unimplemented opcode DW_OP_regval_type"));
 }
 
-TEST(DWARFExpression, DW_OP_deref_type_unhandled) {
+TEST(DWARFExpression, DW_OP_deref_type_unimplemented) {
   EXPECT_THAT_EXPECTED(
       Evaluate({DW_OP_lit0, DW_OP_deref_type, 0x04, 0x00}),
-      llvm::FailedWithMessage(
-          "unhandled opcode DW_OP_deref_type in DWARFExpression"));
+      llvm::FailedWithMessage("unimplemented opcode DW_OP_deref_type"));
 }
 
-TEST(DWARFExpression, DW_OP_xderef_type_unhandled) {
+TEST(DWARFExpression, DW_OP_xderef_type_unimplemented) {
   EXPECT_THAT_EXPECTED(
       Evaluate({DW_OP_lit0, DW_OP_lit0, DW_OP_xderef_type, 0x04, 0x00}),
-      llvm::FailedWithMessage(
-          "unhandled opcode DW_OP_xderef_type in DWARFExpression"));
+      llvm::FailedWithMessage("unimplemented opcode DW_OP_xderef_type"));
 }
 
-TEST(DWARFExpression, DW_OP_constx_unhandled) {
-  EXPECT_THAT_EXPECTED(Evaluate({DW_OP_constx, 0x00}),
-                       llvm::FailedWithMessage(
-                           "unhandled opcode DW_OP_constx in DWARFExpression"));
+TEST(DWARFExpression, DW_OP_constx_unimplemented) {
+  EXPECT_THAT_EXPECTED(
+      Evaluate({DW_OP_constx, 0x00}),
+      llvm::FailedWithMessage("unimplemented opcode DW_OP_constx"));
 }
 
-TEST(DWARFExpression, DW_OP_reinterpret_unhandled) {
+TEST(DWARFExpression, DW_OP_reinterpret_unimplemented) {
   EXPECT_THAT_EXPECTED(
       Evaluate({DW_OP_lit0, DW_OP_reinterpret, 0x00}),
-      llvm::FailedWithMessage(
-          "unhandled opcode DW_OP_reinterpret in DWARFExpression"));
+      llvm::FailedWithMessage("unimplemented opcode DW_OP_reinterpret"));
 }
 
 // Register-based tests need a register context. MockRegisterContext returns the

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant