================
@@ -632,6 +632,461 @@ TEST(DWARFExpression, DW_OP_unknown) {
           "unhandled opcode DW_OP_unknown_ff in DWARFExpression"));
 }
 
+TEST(DWARFExpression, DW_OP_addr) {
+  EXPECT_THAT_EXPECTED(
+      Evaluate({DW_OP_addr, 0x10, 0x20, 0x30, 0x40, DW_OP_stack_value}),
+      ExpectScalar(uint32_t{0x40302010}));
+}
+
+TEST(DWARFExpression, DW_OP_nop) {
+  EXPECT_THAT_EXPECTED(Evaluate({DW_OP_lit5, DW_OP_nop}), ExpectScalar(5));
+}
+
+TEST(DWARFExpression, DW_OP_neg) {
+  // neg interprets the operand as signed.
+  EXPECT_THAT_EXPECTED(Evaluate({DW_OP_lit5, DW_OP_neg}),
+                       ExpectScalar(static_cast<int32_t>(-5)));
+}
+
+TEST(DWARFExpression, DW_OP_abs) {
+  EXPECT_THAT_EXPECTED(
+      Evaluate({DW_OP_const1s, static_cast<uint8_t>(-5), DW_OP_abs}),
+      ExpectScalar(5));
+  EXPECT_THAT_EXPECTED(Evaluate({DW_OP_lit5, DW_OP_abs}), ExpectScalar(5));
+}
+
+TEST(DWARFExpression, DW_OP_div_int_min_by_neg_one) {
+  // INT32_MIN / -1 is C++ UB; the evaluator must not crash.
+  auto result = Evaluate({DW_OP_const4s, 0x00, 0x00, 0x00, 0x80, DW_OP_const1s,
+                          static_cast<uint8_t>(-1), DW_OP_div});
+  if (!result)
+    llvm::consumeError(result.takeError());
+  SUCCEED();
+}
+
+TEST(DWARFExpression, DW_OP_div) {
+  // Signed division: -10 / 3 = -3 (truncation toward zero).
+  EXPECT_THAT_EXPECTED(Evaluate({DW_OP_const1s, static_cast<uint8_t>(-10),
+                                 DW_OP_const1s, 3, DW_OP_div}),
+                       ExpectScalar(static_cast<int32_t>(-3)));
+}
+
+TEST(DWARFExpression, DW_OP_mod) {
+  EXPECT_THAT_EXPECTED(Evaluate({DW_OP_const1s, static_cast<uint8_t>(-7),
+                                 DW_OP_const1s, 3, DW_OP_mod}),
+                       ExpectScalar(static_cast<int32_t>(-1)));
+}
+
+TEST(DWARFExpression, DW_OP_minus) {
+  // Generic arithmetic wraps modulo address-size: 0 - 1 = 0xFFFFFFFF.
+  EXPECT_THAT_EXPECTED(Evaluate({DW_OP_lit0, DW_OP_lit1, DW_OP_minus}),
+                       ExpectScalar(uint32_t{0xFFFFFFFF}));
+}
+
+TEST(DWARFExpression, DW_OP_plus) {
+  EXPECT_THAT_EXPECTED(Evaluate({DW_OP_lit5, DW_OP_lit3, DW_OP_plus}),
+                       ExpectScalar(8));
+}
+
+TEST(DWARFExpression, DW_OP_mul) {
+  EXPECT_THAT_EXPECTED(Evaluate({DW_OP_lit5, DW_OP_lit3, DW_OP_mul}),
+                       ExpectScalar(15));
+}
+
+TEST(DWARFExpression, DW_OP_plus_uconst) {
+  EXPECT_THAT_EXPECTED(Evaluate({DW_OP_const1s, static_cast<uint8_t>(-10),
+                                 DW_OP_plus_uconst, 5}),
+                       ExpectScalar(static_cast<int32_t>(-5)));
+}
+
+TEST(DWARFExpression, DW_OP_and) {
+  EXPECT_THAT_EXPECTED(
+      Evaluate({DW_OP_const1u, 0x0F, DW_OP_const1u, 0x33, DW_OP_and}),
+      ExpectScalar(0x03));
+}
+
+TEST(DWARFExpression, DW_OP_or) {
+  EXPECT_THAT_EXPECTED(
+      Evaluate({DW_OP_const1u, 0x0F, DW_OP_const1u, 0x30, DW_OP_or}),
+      ExpectScalar(0x3F));
+}
+
+TEST(DWARFExpression, DW_OP_xor) {
+  EXPECT_THAT_EXPECTED(
+      Evaluate({DW_OP_const1u, 0x0F, DW_OP_const1u, 0x33, DW_OP_xor}),
+      ExpectScalar(0x3C));
+}
+
+TEST(DWARFExpression, DW_OP_not) {
+  EXPECT_THAT_EXPECTED(Evaluate({DW_OP_lit0, DW_OP_not}),
+                       ExpectScalar(uint32_t{0xFFFFFFFF}));
+}
+
+TEST(DWARFExpression, DW_OP_lt) {
+  EXPECT_THAT_EXPECTED(
+      Evaluate({DW_OP_const1s, static_cast<uint8_t>(-1), DW_OP_lit0, 
DW_OP_lt}),
+      ExpectScalar(1));
+}
+
+TEST(DWARFExpression, DW_OP_gt) {
+  EXPECT_THAT_EXPECTED(
+      Evaluate({DW_OP_lit0, DW_OP_const1s, static_cast<uint8_t>(-1), 
DW_OP_gt}),
+      ExpectScalar(1));
+}
+
+TEST(DWARFExpression, DW_OP_le) {
+  EXPECT_THAT_EXPECTED(
+      Evaluate({DW_OP_const1s, static_cast<uint8_t>(-1), DW_OP_lit0, 
DW_OP_le}),
+      ExpectScalar(1));
+}
+
+TEST(DWARFExpression, DW_OP_ge) {
+  EXPECT_THAT_EXPECTED(
+      Evaluate({DW_OP_lit0, DW_OP_const1s, static_cast<uint8_t>(-1), 
DW_OP_ge}),
+      ExpectScalar(1));
+}
+
+TEST(DWARFExpression, DW_OP_eq) {
+  EXPECT_THAT_EXPECTED(Evaluate({DW_OP_lit5, DW_OP_lit5, DW_OP_eq}),
+                       ExpectScalar(1));
+  EXPECT_THAT_EXPECTED(Evaluate({DW_OP_lit5, DW_OP_lit3, DW_OP_eq}),
+                       ExpectScalar(0));
+}
+
+TEST(DWARFExpression, DW_OP_ne) {
+  EXPECT_THAT_EXPECTED(Evaluate({DW_OP_lit5, DW_OP_lit3, DW_OP_ne}),
+                       ExpectScalar(1));
+  EXPECT_THAT_EXPECTED(Evaluate({DW_OP_lit5, DW_OP_lit5, DW_OP_ne}),
+                       ExpectScalar(0));
+}
+
+TEST(DWARFExpression, DW_OP_swap) {
+  // After swap, top is the value pushed first (lit1).
+  EXPECT_THAT_EXPECTED(Evaluate({DW_OP_lit1, DW_OP_lit2, DW_OP_swap}),
+                       ExpectScalar(1));
+}
+
+TEST(DWARFExpression, DW_OP_rot) {
+  // Stack pre-rot (top last): [1, 2, 3]. Post-rot: [2, 3, 1]. Top = 2.
+  EXPECT_THAT_EXPECTED(
+      Evaluate({DW_OP_lit1, DW_OP_lit2, DW_OP_lit3, DW_OP_rot}),
+      ExpectScalar(2));
+}
+
+TEST(DWARFExpression, DW_OP_over) {
+  EXPECT_THAT_EXPECTED(Evaluate({DW_OP_lit1, DW_OP_lit2, DW_OP_over}),
+                       ExpectScalar(1));
+}
+
+TEST(DWARFExpression, DW_OP_dup) {
+  EXPECT_THAT_EXPECTED(Evaluate({DW_OP_lit5, DW_OP_dup}), ExpectScalar(5));
+  EXPECT_THAT_EXPECTED(Evaluate({DW_OP_dup}), llvm::Failed());
+}
+
+TEST(DWARFExpression, DW_OP_drop) {
+  EXPECT_THAT_EXPECTED(Evaluate({DW_OP_lit3, DW_OP_lit5, DW_OP_drop}),
+                       ExpectScalar(3));
+  EXPECT_THAT_EXPECTED(Evaluate({DW_OP_drop}), llvm::Failed());
+}
+
+TEST(DWARFExpression, DW_OP_skip_backward) {
+  // Layout (offsets):
+  //   0: skip +5  → end_offset=3, target=8
+  //   3: const1u 0x42  ← target of backward branch
+  //   5: skip +3  → end_offset=8, target=11 (== expr.size, exits)
+  //   8: skip -8  → end_offset=11, target=3
+  EXPECT_THAT_EXPECTED(
+      Evaluate({DW_OP_skip, 0x05, 0x00, DW_OP_const1u, 0x42, DW_OP_skip, 0x03,
+                0x00, DW_OP_skip, 0xF8, 0xFF}),
+      ExpectScalar(0x42));
+}
+
+TEST(DWARFExpression, DW_OP_skip_to_end) {
+  // skip 0 from end-of-skip lands at end-of-expression and terminates cleanly.
+  EXPECT_THAT_EXPECTED(Evaluate({DW_OP_lit5, DW_OP_skip, 0x00, 0x00}),
+                       ExpectScalar(5));
+}
+
+TEST(DWARFExpression, DW_OP_bra_false) {
+  // Top is 0 → no branch, fall through to next opcode.
+  EXPECT_THAT_EXPECTED(
+      Evaluate({DW_OP_lit5, DW_OP_lit0, DW_OP_bra, 0x63, 0x00}),
+      ExpectScalar(5));
+}
+
+TEST(DWARFExpression, DW_OP_lit_all) {
+  for (uint8_t n = 0; n <= 31; ++n) {
+    uint8_t opcode = DW_OP_lit0 + n;
+    EXPECT_THAT_EXPECTED(Evaluate({opcode}), ExpectScalar(n))
+        << "DW_OP_lit" << static_cast<int>(n) << " failed";
+  }
----------------
s-barannikov wrote:

Should we have tests for DW_OP_const*? In particular, that s and u versions 
correctly sign- and zero-extend to pointer size.

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

Reply via email to