Author: MrEven132
Date: 2026-08-25T14:09:16+08:00
New Revision: cbc5a226cbf8d1d37d1ba8e55ce6973e8ef739cd

URL: 
https://github.com/llvm/llvm-project/commit/cbc5a226cbf8d1d37d1ba8e55ce6973e8ef739cd
DIFF: 
https://github.com/llvm/llvm-project/commit/cbc5a226cbf8d1d37d1ba8e55ce6973e8ef739cd.diff

LOG: [lldb] Compare generic DWARF relational operands as signed values (#218335)

DWARF v5 requires relational comparisons whose operands have the generic
type
to be performed as signed operations. LLDB currently dispatches
`DW_OP_lt`,
`DW_OP_le`, `DW_OP_gt`, and `DW_OP_ge` directly to `Scalar` comparisons,
whose
C-like integer promotion makes an equal-width unsigned operand win. As a
result, the generic comparison of an all-one address-sized value with
zero can
be evaluated as `UINT64_MAX < 0` instead of `-1 < 0`.

Reuse the evaluator's existing approximation for potentially generic
integer
operands and mark temporary operand copies signed before evaluating the
four
ordering operations. This keeps the change local to DWARF expression
semantics, without changing general `Scalar` comparisons or `DW_OP_eq`
and
`DW_OP_ne`.

The expression stack does not yet preserve genericness explicitly, so
this
uses the same address-width approximation as the existing operand-type
check.
Precisely distinguishing generic values from explicit address-sized base
types
requires the larger typed-stack work already noted in the source.

Add a unit test using the issue's operands and cover all four affected
ordering
opcodes. The focused test, all `DWARFExpression` tests, and the complete
`ExpressionTests` binary pass locally. Component-level `check-lldb-unit`
also
passes.

Fixes #202878

Added: 
    

Modified: 
    lldb/source/Expression/DWARFExpression.cpp
    lldb/unittests/Expression/DWARFExpressionTest.cpp

Removed: 
    


################################################################################
diff  --git a/lldb/source/Expression/DWARFExpression.cpp 
b/lldb/source/Expression/DWARFExpression.cpp
index 40c69c65853a8..453c361c1d6f9 100644
--- a/lldb/source/Expression/DWARFExpression.cpp
+++ b/lldb/source/Expression/DWARFExpression.cpp
@@ -1380,6 +1380,15 @@ static llvm::Error CheckScalarOperandsHaveSameType(const 
Scalar &lhs,
   return llvm::Error::success();
 }
 
+// Scalar does not preserve DWARF's generic type identifier. Since generic
+// values are address-sized integers, use the scalar kind and width as an
+// approximation.
+static bool IsPotentiallyGenericIntegerOperand(const Scalar &operand,
+                                               size_t address_size) {
+  return address_size != 0 && operand.GetType() == Scalar::e_int &&
+         operand.GetByteSize() == address_size;
+}
+
 llvm::Expected<Value> DWARFExpression::Evaluate(
     ExecutionContext *exe_ctx, RegisterContext *reg_ctx,
     lldb::ModuleSP module_sp, const DataExtractor &opcodes,
@@ -1745,6 +1754,12 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
         return err;
       tmp = stack.back();
       stack.pop_back();
+      if (IsPotentiallyGenericIntegerOperand(tmp.GetScalar(), address_size) &&
+          IsPotentiallyGenericIntegerOperand(stack.back().GetScalar(),
+                                             address_size)) {
+        tmp.GetScalar().MakeSigned();
+        stack.back().GetScalar().MakeSigned();
+      }
       stack.back().GetScalar() =
           to_generic(stack.back().GetScalar() >= tmp.GetScalar());
       break;
@@ -1756,6 +1771,12 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
         return err;
       tmp = stack.back();
       stack.pop_back();
+      if (IsPotentiallyGenericIntegerOperand(tmp.GetScalar(), address_size) &&
+          IsPotentiallyGenericIntegerOperand(stack.back().GetScalar(),
+                                             address_size)) {
+        tmp.GetScalar().MakeSigned();
+        stack.back().GetScalar().MakeSigned();
+      }
       stack.back().GetScalar() =
           to_generic(stack.back().GetScalar() > tmp.GetScalar());
       break;
@@ -1767,6 +1788,12 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
         return err;
       tmp = stack.back();
       stack.pop_back();
+      if (IsPotentiallyGenericIntegerOperand(tmp.GetScalar(), address_size) &&
+          IsPotentiallyGenericIntegerOperand(stack.back().GetScalar(),
+                                             address_size)) {
+        tmp.GetScalar().MakeSigned();
+        stack.back().GetScalar().MakeSigned();
+      }
       stack.back().GetScalar() =
           to_generic(stack.back().GetScalar() <= tmp.GetScalar());
       break;
@@ -1778,6 +1805,12 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
         return err;
       tmp = stack.back();
       stack.pop_back();
+      if (IsPotentiallyGenericIntegerOperand(tmp.GetScalar(), address_size) &&
+          IsPotentiallyGenericIntegerOperand(stack.back().GetScalar(),
+                                             address_size)) {
+        tmp.GetScalar().MakeSigned();
+        stack.back().GetScalar().MakeSigned();
+      }
       stack.back().GetScalar() =
           to_generic(stack.back().GetScalar() < tmp.GetScalar());
       break;

diff  --git a/lldb/unittests/Expression/DWARFExpressionTest.cpp 
b/lldb/unittests/Expression/DWARFExpressionTest.cpp
index b59bddff0cd1e..a09aadf88039c 100644
--- a/lldb/unittests/Expression/DWARFExpressionTest.cpp
+++ b/lldb/unittests/Expression/DWARFExpressionTest.cpp
@@ -766,6 +766,45 @@ TEST(DWARFExpression, RelationalOpsProduceGenericResult) {
   }
 }
 
+TEST(DWARFExpression, GenericRelationalOpsUseSignedComparison) {
+  struct TestCase {
+    uint8_t opcode;
+    uint8_t expected;
+  };
+  constexpr TestCase test_cases[] = {
+      {DW_OP_lt, 1}, {DW_OP_le, 1}, {DW_OP_gt, 0}, {DW_OP_ge, 0}};
+
+  for (const TestCase &test : test_cases) {
+    // Generic relational operands are compared as signed values, so the
+    // unsigned encoding of all-one bits below represents -1 for comparison.
+    const std::vector<uint8_t> expr = {
+        DW_OP_const8u,
+        0xff,
+        0xff,
+        0xff,
+        0xff,
+        0xff,
+        0xff,
+        0xff,
+        0xff,
+        DW_OP_consts,
+        0x00,
+        test.opcode,
+        DW_OP_stack_value,
+    };
+    DataExtractor extractor(expr.data(), expr.size(), lldb::eByteOrderLittle,
+                            /*addr_size=*/8);
+
+    EXPECT_THAT_EXPECTED(
+        DWARFExpression::Evaluate(
+            /*exe_ctx=*/nullptr, /*reg_ctx=*/nullptr, /*module_sp=*/{},
+            extractor, /*unit=*/nullptr, lldb::eRegisterKindLLDB,
+            /*initial_value_ptr=*/nullptr, /*object_address_ptr=*/nullptr),
+        ExpectScalar(64, test.expected, false))
+        << "opcode 0x" << llvm::utohexstr(test.opcode);
+  }
+}
+
 TEST(DWARFExpression, DW_OP_stack_value) {
   EXPECT_THAT_EXPECTED(Evaluate({DW_OP_stack_value}), llvm::Failed());
 }


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

Reply via email to