https://github.com/MrEven132 updated 
https://github.com/llvm/llvm-project/pull/219372

>From a160b8f8bfc144f35c12616c77513714eda24c26 Mon Sep 17 00:00:00 2001
From: MrEven132 <[email protected]>
Date: Fri, 28 Aug 2026 13:04:45 +0800
Subject: [PATCH 1/2] [lldb] Track location descriptions per DWARF stack entry

---
 lldb/source/Expression/DWARFExpression.cpp    | 136 ++++++++++++------
 .../Expression/DWARFExpressionTest.cpp        |  25 ++++
 2 files changed, 121 insertions(+), 40 deletions(-)

diff --git a/lldb/source/Expression/DWARFExpression.cpp 
b/lldb/source/Expression/DWARFExpression.cpp
index d22634d63e875..268637c109f3b 100644
--- a/lldb/source/Expression/DWARFExpression.cpp
+++ b/lldb/source/Expression/DWARFExpression.cpp
@@ -64,6 +64,71 @@ enum LocationDescriptionKind {
   /* Composite*/
 };
 
+/// Keeps the location description kind associated with each eagerly
+/// materialized value on the DWARF expression stack.
+class EvaluationStack {
+public:
+  bool empty() const { return m_values.empty(); }
+  size_t size() const { return m_values.size(); }
+
+  Value &back() { return m_values.back(); }
+  const Value &back() const { return m_values.back(); }
+
+  Value &operator[](size_t index) { return m_values[index]; }
+  const Value &operator[](size_t index) const { return m_values[index]; }
+
+  void push_back(Value value, LocationDescriptionKind loc_desc_kind = Memory) {
+    m_values.push_back(std::move(value));
+    m_loc_desc_kinds.push_back(loc_desc_kind);
+  }
+
+  void PushCopy(size_t index) {
+    push_back(m_values[index], m_loc_desc_kinds[index]);
+  }
+
+  void pop_back() {
+    m_values.pop_back();
+    m_loc_desc_kinds.pop_back();
+  }
+
+  LocationDescriptionKind GetLocationDescriptionKind() const {
+    return m_loc_desc_kinds.back();
+  }
+
+  void SetLocationDescriptionKind(LocationDescriptionKind loc_desc_kind) {
+    m_loc_desc_kinds.back() = loc_desc_kind;
+  }
+
+  void SwapTopTwo() {
+    const size_t last = size() - 1;
+    std::swap(m_values[last], m_values[last - 1]);
+    std::swap(m_loc_desc_kinds[last], m_loc_desc_kinds[last - 1]);
+  }
+
+  void RotateTopThree() {
+    const size_t last = size() - 1;
+    Value old_top = m_values[last];
+    m_values[last] = m_values[last - 1];
+    m_values[last - 1] = m_values[last - 2];
+    m_values[last - 2] = std::move(old_top);
+
+    LocationDescriptionKind old_top_kind = m_loc_desc_kinds[last];
+    m_loc_desc_kinds[last] = m_loc_desc_kinds[last - 1];
+    m_loc_desc_kinds[last - 1] = m_loc_desc_kinds[last - 2];
+    m_loc_desc_kinds[last - 2] = old_top_kind;
+  }
+
+  DWARFExpression::Stack &Values() { return m_values; }
+
+  void SyncLocationDescriptionKinds() {
+    m_loc_desc_kinds.resize(m_values.size(), Memory);
+  }
+
+private:
+  DWARFExpression::Stack m_values;
+  std::vector<LocationDescriptionKind> m_loc_desc_kinds;
+};
+
 /// Aggregates the inputs, derived pointers, and mutable evaluation state for
 /// a single DWARF expression evaluation. Passed by reference to every helper
 /// so they don't need to re-thread these individually.
@@ -81,10 +146,9 @@ struct EvalContext {
 
   /// Mutable evaluation state.
   /// @{
-  std::vector<Value> stack;
+  EvaluationStack stack;
   Value pieces;
   uint64_t op_piece_offset = 0;
-  LocationDescriptionKind loc_desc_kind = Memory;
   /// @}
 
   EvalContext(ExecutionContext *exe_ctx, RegisterContext *reg_ctx,
@@ -974,10 +1038,11 @@ static llvm::Error Evaluate_DW_OP_deref(EvalContext 
&eval_ctx,
   // Deref a register or implicit location and truncate the value to `size`
   // bytes. See the corresponding comment in DW_OP_deref for more details on
   // why we deref these locations this way.
-  if (eval_ctx.loc_desc_kind == Register ||
-      eval_ctx.loc_desc_kind == Implicit) {
+  LocationDescriptionKind loc_desc_kind =
+      eval_ctx.stack.GetLocationDescriptionKind();
+  if (loc_desc_kind == Register || loc_desc_kind == Implicit) {
     // Reset context to default values.
-    eval_ctx.loc_desc_kind = Memory;
+    eval_ctx.stack.SetLocationDescriptionKind(Memory);
     eval_ctx.stack.back().ClearContext();
 
     // Truncate the value on top of the stack to *size* bytes then
@@ -1108,12 +1173,15 @@ static llvm::Error Evaluate_DW_OP_deref(EvalContext 
&eval_ctx,
 
 static llvm::Error Evaluate_DW_OP_piece(EvalContext &eval_ctx,
                                         uint64_t piece_byte_size) {
-  LocationDescriptionKind piece_locdesc = eval_ctx.loc_desc_kind;
-  // Reset for the next piece.
-  eval_ctx.loc_desc_kind = Memory;
+  LocationDescriptionKind piece_locdesc =
+      eval_ctx.stack.empty() ? Memory
+                             : eval_ctx.stack.GetLocationDescriptionKind();
 
-  if (piece_byte_size == 0)
+  if (piece_byte_size == 0) {
+    if (!eval_ctx.stack.empty())
+      eval_ctx.stack.SetLocationDescriptionKind(Memory);
     return llvm::Error::success();
+  }
 
   Value curr_piece;
 
@@ -1455,7 +1523,7 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
   EvalContext eval_ctx(exe_ctx, reg_ctx, std::move(module_sp), dwarf_cu,
                        reg_kind, initial_value_ptr, object_address_ptr);
 
-  Stack &stack = eval_ctx.stack;
+  EvaluationStack &stack = eval_ctx.stack;
 
   if (initial_value_ptr)
     stack.push_back(*initial_value_ptr);
@@ -1557,7 +1625,7 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
       if (stack.empty()) {
         return llvm::createStringError("expression stack empty for DW_OP_dup");
       } else
-        stack.push_back(stack.back());
+        stack.PushCopy(stack.size() - 1);
       break;
 
     case DW_OP_drop:
@@ -1568,13 +1636,13 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
       break;
 
     case DW_OP_over:
-      stack.push_back(stack[stack.size() - 2]);
+      stack.PushCopy(stack.size() - 2);
       break;
 
     case DW_OP_pick: {
       uint8_t pick_idx = op->getRawOperand(0);
       if (pick_idx < stack.size())
-        stack.push_back(stack[stack.size() - 1 - pick_idx]);
+        stack.PushCopy(stack.size() - 1 - pick_idx);
       else {
         return llvm::createStringError(
             "Index %u out of range for DW_OP_pick.\n", pick_idx);
@@ -1582,18 +1650,12 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
     } break;
 
     case DW_OP_swap:
-      tmp = stack.back();
-      stack.back() = stack[stack.size() - 2];
-      stack[stack.size() - 2] = tmp;
+      stack.SwapTopTwo();
       break;
 
-    case DW_OP_rot: {
-      size_t last_idx = stack.size() - 1;
-      Value old_top = stack[last_idx];
-      stack[last_idx] = stack[last_idx - 1];
-      stack[last_idx - 1] = stack[last_idx - 2];
-      stack[last_idx - 2] = old_top;
-    } break;
+    case DW_OP_rot:
+      stack.RotateTopThree();
+      break;
 
     case DW_OP_abs:
       if (!stack.back().GetScalar().AbsoluteValue()) {
@@ -1948,22 +2010,20 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
     case DW_OP_reg29:
     case DW_OP_reg30:
     case DW_OP_reg31: {
-      eval_ctx.loc_desc_kind = Register;
       reg_num = opcode - DW_OP_reg0;
 
       if (llvm::Error err = ReadRegisterValueAsScalar(
               eval_ctx.reg_ctx, eval_ctx.reg_kind, reg_num, tmp))
         return err;
-      stack.push_back(tmp);
+      stack.push_back(tmp, Register);
     } break;
     case DW_OP_regx: {
-      eval_ctx.loc_desc_kind = Register;
       reg_num = op->getRawOperand(0);
       Status read_err;
       if (llvm::Error err = ReadRegisterValueAsScalar(
               eval_ctx.reg_ctx, eval_ctx.reg_kind, reg_num, tmp))
         return err;
-      stack.push_back(tmp);
+      stack.push_back(tmp, Register);
     } break;
 
     case DW_OP_breg0:
@@ -2045,15 +2105,13 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
       if (stack.size() < 1) {
         UpdateValueTypeFromLocationDescription(eval_ctx,
                                                LocationDescriptionKind::Empty);
-        // Reset for the next piece.
-        eval_ctx.loc_desc_kind = Memory;
         return llvm::createStringError(
             "expression stack needs at least 1 item for DW_OP_bit_piece");
       } else {
-        UpdateValueTypeFromLocationDescription(eval_ctx, 
eval_ctx.loc_desc_kind,
-                                               &stack.back());
+        UpdateValueTypeFromLocationDescription(
+            eval_ctx, stack.GetLocationDescriptionKind(), &stack.back());
         // Reset for the next piece.
-        eval_ctx.loc_desc_kind = Memory;
+        stack.SetLocationDescriptionKind(Memory);
         const uint64_t piece_bit_size = op->getRawOperand(0);
         const uint64_t piece_bit_offset = op->getRawOperand(1);
         switch (stack.back().GetValueType()) {
@@ -2083,8 +2141,6 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
       break;
 
     case DW_OP_implicit_value: {
-      eval_ctx.loc_desc_kind = Implicit;
-
       // The second operand is a sequence of bytes of the length specified by
       // the first operand. LLVM represents it as an offset to that sequence.
       const uint64_t block_size = op->getRawOperand(0);
@@ -2098,12 +2154,11 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
         return error;
 
       Value result(block_data.data(), block_data.size());
-      stack.push_back(result);
+      stack.push_back(result, Implicit);
       break;
     }
 
     case DW_OP_implicit_pointer: {
-      eval_ctx.loc_desc_kind = Implicit;
       return llvm::createStringError("could not evaluate %s",
                                      DW_OP_value_to_name(opcode));
     }
@@ -2118,7 +2173,7 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
       break;
 
     case DW_OP_stack_value:
-      eval_ctx.loc_desc_kind = Implicit;
+      stack.SetLocationDescriptionKind(Implicit);
       stack.back().SetValueType(Value::ValueType::Scalar);
       break;
 
@@ -2213,7 +2268,8 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
         uint64_t offset = operands_offset; // Updated by the callee.
         if (eval_ctx.dwarf_cu->ParseVendorDWARFOpcode(
                 opcode, expr_data, offset, eval_ctx.reg_ctx, eval_ctx.reg_kind,
-                stack)) {
+                stack.Values())) {
+          stack.SyncLocationDescriptionKinds();
           // This is a little tricky. If LLVM knows about this vendor-specific
           // operation, `getEndOffset()` points past its last operand. If LLVM
           // knows nothing about this operation, `getEndOffset()` points to its
@@ -2242,8 +2298,8 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
     return llvm::createStringError("stack empty after evaluation");
   }
 
-  UpdateValueTypeFromLocationDescription(eval_ctx, eval_ctx.loc_desc_kind,
-                                         &stack.back());
+  UpdateValueTypeFromLocationDescription(
+      eval_ctx, stack.GetLocationDescriptionKind(), &stack.back());
 
   if (log && log->GetVerbose()) {
     size_t count = stack.size();
diff --git a/lldb/unittests/Expression/DWARFExpressionTest.cpp 
b/lldb/unittests/Expression/DWARFExpressionTest.cpp
index aa8e17a88cc34..29c9163c1f3f8 100644
--- a/lldb/unittests/Expression/DWARFExpressionTest.cpp
+++ b/lldb/unittests/Expression/DWARFExpressionTest.cpp
@@ -2373,6 +2373,31 @@ TEST_F(DWARFExpressionMockProcessTest, deref_register) {
       ExpectLoadAddress(0x08070605, Value::ContextType::Invalid));
 }
 
+TEST_F(DWARFExpressionMockProcessTest, DW_OP_drop_location_description) {
+  TestContext test_ctx;
+  MockMemory::Map memory = {{{0x4, 2}, {0x1, 0x2}}};
+  ASSERT_TRUE(CreateTestContext(&test_ctx, "i386-pc-linux",
+                                RegisterValue(uint32_t{0x504}), memory));
+
+  MockDwarfDelegate delegate = MockDwarfDelegate::Dwarf5();
+  auto Eval = [&](llvm::ArrayRef<uint8_t> expr_data) {
+    ExecutionContext exe_ctx(test_ctx.process_sp);
+    return Evaluate(expr_data, {}, &delegate, &exe_ctx,
+                    test_ctx.reg_ctx_sp.get());
+  };
+
+  // Dropping a register location restores the memory location underneath it.
+  EXPECT_THAT_EXPECTED(
+      Eval({DW_OP_lit4, DW_OP_reg0, DW_OP_drop, DW_OP_deref_size, 2}),
+      ExpectLoadAddress(0x0201));
+
+  // Dropping the only implicit location clears its location state before the
+  // following memory location is pushed.
+  EXPECT_THAT_EXPECTED(Eval({DW_OP_implicit_value, 1, 0, DW_OP_drop, 
DW_OP_lit4,
+                             DW_OP_deref_size, 2}),
+                       ExpectLoadAddress(0x0201));
+}
+
 TEST_F(DWARFExpressionMockProcessTest, deref_implicit_value) {
   TestContext test_ctx;
   MockMemory::Map memory = {

>From 24ed31711716ff8c2ac1e99e6520ba82d0c21a8c Mon Sep 17 00:00:00 2001
From: MrEven132 <[email protected]>
Date: Tue, 1 Sep 2026 13:26:30 +0800
Subject: [PATCH 2/2] [lldb] Track location descriptions per DWARF stack entry

---
 .../include/lldb/Expression/DWARFExpression.h |  76 +++++++++++-
 lldb/source/Expression/DWARFExpression.cpp    | 115 +++++-------------
 .../Plugins/SymbolFile/DWARF/DWARFUnit.cpp    |   2 +-
 .../Plugins/SymbolFile/DWARF/DWARFUnit.h      |  11 +-
 .../SymbolFile/DWARF/SymbolFileDWARF.h        |   2 +-
 .../SymbolFile/DWARF/SymbolFileDWARFDwo.cpp   |   2 +-
 .../SymbolFile/DWARF/SymbolFileDWARFDwo.h     |   2 +-
 .../SymbolFile/DWARF/SymbolFileWasm.cpp       |  10 +-
 .../Plugins/SymbolFile/DWARF/SymbolFileWasm.h |   2 +-
 .../Expression/DWARFExpressionTest.cpp        |  95 ++++++++++++++-
 10 files changed, 207 insertions(+), 110 deletions(-)

diff --git a/lldb/include/lldb/Expression/DWARFExpression.h 
b/lldb/include/lldb/Expression/DWARFExpression.h
index 1f9994815499a..f8710d555e6a7 100644
--- a/lldb/include/lldb/Expression/DWARFExpression.h
+++ b/lldb/include/lldb/Expression/DWARFExpression.h
@@ -11,6 +11,7 @@
 
 #include "lldb/Core/Address.h"
 #include "lldb/Core/Disassembler.h"
+#include "lldb/Core/Value.h"
 #include "lldb/Core/dwarf.h"
 #include "lldb/Utility/DataExtractor.h"
 #include "lldb/Utility/Scalar.h"
@@ -18,7 +19,10 @@
 #include "lldb/lldb-private.h"
 #include "llvm/DebugInfo/DWARF/DWARFLocationExpression.h"
 #include "llvm/Support/Error.h"
+#include <cstddef>
 #include <functional>
+#include <utility>
+#include <vector>
 
 namespace lldb_private {
 
@@ -35,7 +39,77 @@ namespace lldb_private {
 /// location expression or a location list and interprets it.
 class DWARFExpression {
 public:
-  using Stack = std::vector<Value>;
+  /// The stack used while evaluating a DWARF expression. Each eagerly
+  /// materialized value retains the kind of location description that
+  /// produced it.
+  class Stack {
+  public:
+    enum class LocationDescriptionKind { Empty, Memory, Register, Implicit };
+
+    bool empty() const { return m_entries.empty(); }
+    size_t size() const { return m_entries.size(); }
+
+    Value &back() { return m_entries.back().value; }
+    const Value &back() const { return m_entries.back().value; }
+
+    Value &operator[](size_t index) { return m_entries[index].value; }
+    const Value &operator[](size_t index) const {
+      return m_entries[index].value;
+    }
+
+    void push_back(Value value, LocationDescriptionKind loc_desc_kind =
+                                    LocationDescriptionKind::Memory) {
+      m_entries.push_back({std::move(value), loc_desc_kind});
+    }
+
+    /// Push a copy of the entry at \p index, or return false if it is invalid.
+    [[nodiscard]] bool PushCopy(size_t index) {
+      if (index >= size())
+        return false;
+      Entry entry = m_entries[index];
+      m_entries.push_back(std::move(entry));
+      return true;
+    }
+
+    void pop_back() { m_entries.pop_back(); }
+
+    LocationDescriptionKind GetLocationDescriptionKind() const {
+      return m_entries.back().loc_desc_kind;
+    }
+
+    void SetLocationDescriptionKind(LocationDescriptionKind loc_desc_kind) {
+      m_entries.back().loc_desc_kind = loc_desc_kind;
+    }
+
+    /// Swap the top two entries, or return false if fewer than two exist.
+    [[nodiscard]] bool SwapTopTwo() {
+      if (size() < 2)
+        return false;
+      const size_t last = size() - 1;
+      std::swap(m_entries[last], m_entries[last - 1]);
+      return true;
+    }
+
+    /// Rotate the top three entries, or return false if fewer than three 
exist.
+    [[nodiscard]] bool RotateTopThree() {
+      if (size() < 3)
+        return false;
+      const size_t last = size() - 1;
+      Entry old_top = m_entries[last];
+      m_entries[last] = m_entries[last - 1];
+      m_entries[last - 1] = m_entries[last - 2];
+      m_entries[last - 2] = std::move(old_top);
+      return true;
+    }
+
+  private:
+    struct Entry {
+      Value value;
+      LocationDescriptionKind loc_desc_kind;
+    };
+
+    std::vector<Entry> m_entries;
+  };
 
   class Delegate {
   public:
diff --git a/lldb/source/Expression/DWARFExpression.cpp 
b/lldb/source/Expression/DWARFExpression.cpp
index 268637c109f3b..3ef1673f641b6 100644
--- a/lldb/source/Expression/DWARFExpression.cpp
+++ b/lldb/source/Expression/DWARFExpression.cpp
@@ -53,81 +53,14 @@ using namespace lldb_private::plugin::dwarf;
 using namespace llvm::dwarf;
 
 namespace {
-/// The location description kinds described by the DWARF v5
-/// specification.  Composite locations are handled out-of-band and
-/// thus aren't part of the enum.
-enum LocationDescriptionKind {
-  Empty,
-  Memory,
-  Register,
-  Implicit
-  /* Composite*/
-};
-
-/// Keeps the location description kind associated with each eagerly
-/// materialized value on the DWARF expression stack.
-class EvaluationStack {
-public:
-  bool empty() const { return m_values.empty(); }
-  size_t size() const { return m_values.size(); }
-
-  Value &back() { return m_values.back(); }
-  const Value &back() const { return m_values.back(); }
-
-  Value &operator[](size_t index) { return m_values[index]; }
-  const Value &operator[](size_t index) const { return m_values[index]; }
-
-  void push_back(Value value, LocationDescriptionKind loc_desc_kind = Memory) {
-    m_values.push_back(std::move(value));
-    m_loc_desc_kinds.push_back(loc_desc_kind);
-  }
-
-  void PushCopy(size_t index) {
-    push_back(m_values[index], m_loc_desc_kinds[index]);
-  }
-
-  void pop_back() {
-    m_values.pop_back();
-    m_loc_desc_kinds.pop_back();
-  }
-
-  LocationDescriptionKind GetLocationDescriptionKind() const {
-    return m_loc_desc_kinds.back();
-  }
-
-  void SetLocationDescriptionKind(LocationDescriptionKind loc_desc_kind) {
-    m_loc_desc_kinds.back() = loc_desc_kind;
-  }
-
-  void SwapTopTwo() {
-    const size_t last = size() - 1;
-    std::swap(m_values[last], m_values[last - 1]);
-    std::swap(m_loc_desc_kinds[last], m_loc_desc_kinds[last - 1]);
-  }
-
-  void RotateTopThree() {
-    const size_t last = size() - 1;
-    Value old_top = m_values[last];
-    m_values[last] = m_values[last - 1];
-    m_values[last - 1] = m_values[last - 2];
-    m_values[last - 2] = std::move(old_top);
-
-    LocationDescriptionKind old_top_kind = m_loc_desc_kinds[last];
-    m_loc_desc_kinds[last] = m_loc_desc_kinds[last - 1];
-    m_loc_desc_kinds[last - 1] = m_loc_desc_kinds[last - 2];
-    m_loc_desc_kinds[last - 2] = old_top_kind;
-  }
-
-  DWARFExpression::Stack &Values() { return m_values; }
-
-  void SyncLocationDescriptionKinds() {
-    m_loc_desc_kinds.resize(m_values.size(), Memory);
-  }
-
-private:
-  DWARFExpression::Stack m_values;
-  std::vector<LocationDescriptionKind> m_loc_desc_kinds;
-};
+using LocationDescriptionKind = 
DWARFExpression::Stack::LocationDescriptionKind;
+static constexpr LocationDescriptionKind Empty = 
LocationDescriptionKind::Empty;
+static constexpr LocationDescriptionKind Memory =
+    LocationDescriptionKind::Memory;
+static constexpr LocationDescriptionKind Register =
+    LocationDescriptionKind::Register;
+static constexpr LocationDescriptionKind Implicit =
+    LocationDescriptionKind::Implicit;
 
 /// Aggregates the inputs, derived pointers, and mutable evaluation state for
 /// a single DWARF expression evaluation. Passed by reference to every helper
@@ -146,7 +79,7 @@ struct EvalContext {
 
   /// Mutable evaluation state.
   /// @{
-  EvaluationStack stack;
+  DWARFExpression::Stack stack;
   Value pieces;
   uint64_t op_piece_offset = 0;
   /// @}
@@ -1523,7 +1456,7 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
   EvalContext eval_ctx(exe_ctx, reg_ctx, std::move(module_sp), dwarf_cu,
                        reg_kind, initial_value_ptr, object_address_ptr);
 
-  EvaluationStack &stack = eval_ctx.stack;
+  Stack &stack = eval_ctx.stack;
 
   if (initial_value_ptr)
     stack.push_back(*initial_value_ptr);
@@ -1624,8 +1557,10 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
     case DW_OP_dup:
       if (stack.empty()) {
         return llvm::createStringError("expression stack empty for DW_OP_dup");
-      } else
-        stack.PushCopy(stack.size() - 1);
+      } else if (!stack.PushCopy(stack.size() - 1)) {
+        return llvm::createStringError(
+            "unable to copy stack entry for DW_OP_dup");
+      }
       break;
 
     case DW_OP_drop:
@@ -1636,25 +1571,32 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
       break;
 
     case DW_OP_over:
-      stack.PushCopy(stack.size() - 2);
+      if (!stack.PushCopy(stack.size() - 2))
+        return llvm::createStringError(
+            "unable to copy stack entry for DW_OP_over");
       break;
 
     case DW_OP_pick: {
       uint8_t pick_idx = op->getRawOperand(0);
-      if (pick_idx < stack.size())
-        stack.PushCopy(stack.size() - 1 - pick_idx);
-      else {
+      if (pick_idx >= stack.size()) {
         return llvm::createStringError(
             "Index %u out of range for DW_OP_pick.\n", pick_idx);
       }
+      if (!stack.PushCopy(stack.size() - 1 - pick_idx))
+        return llvm::createStringError(
+            "unable to copy stack entry for DW_OP_pick");
     } break;
 
     case DW_OP_swap:
-      stack.SwapTopTwo();
+      if (!stack.SwapTopTwo())
+        return llvm::createStringError(
+            "expression stack needs at least 2 items for DW_OP_swap");
       break;
 
     case DW_OP_rot:
-      stack.RotateTopThree();
+      if (!stack.RotateTopThree())
+        return llvm::createStringError(
+            "expression stack needs at least 3 items for DW_OP_rot");
       break;
 
     case DW_OP_abs:
@@ -2268,8 +2210,7 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
         uint64_t offset = operands_offset; // Updated by the callee.
         if (eval_ctx.dwarf_cu->ParseVendorDWARFOpcode(
                 opcode, expr_data, offset, eval_ctx.reg_ctx, eval_ctx.reg_kind,
-                stack.Values())) {
-          stack.SyncLocationDescriptionKinds();
+                stack)) {
           // This is a little tricky. If LLVM knows about this vendor-specific
           // operation, `getEndOffset()` points past its last operand. If LLVM
           // knows nothing about this operation, `getEndOffset()` points to its
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp 
b/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp
index bb89ebd52f766..a966e4883af6a 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp
@@ -759,7 +759,7 @@ bool DWARFUnit::ParseVendorDWARFOpcode(uint8_t op,
                                        lldb::offset_t &offset,
                                        RegisterContext *reg_ctx,
                                        lldb::RegisterKind reg_kind,
-                                       std::vector<Value> &stack) const {
+                                       DWARFExpression::Stack &stack) const {
   return GetSymbolFileDWARF().ParseVendorDWARFOpcode(op, opcodes, offset,
                                                      reg_ctx, reg_kind, stack);
 }
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h 
b/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h
index bac64ea467238..0949f69d9b886 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h
@@ -164,12 +164,11 @@ class DWARFUnit : public DWARFExpression::Delegate, 
public UserID {
                                           const lldb::offset_t data_offset,
                                           const uint8_t op) const override;
 
-  virtual bool ParseVendorDWARFOpcode(uint8_t op,
-                                      const llvm::DataExtractor &opcodes,
-                                      lldb::offset_t &offset,
-                                      RegisterContext *reg_ctx,
-                                      lldb::RegisterKind reg_kind,
-                                      std::vector<Value> &stack) const 
override;
+  virtual bool
+  ParseVendorDWARFOpcode(uint8_t op, const llvm::DataExtractor &opcodes,
+                         lldb::offset_t &offset, RegisterContext *reg_ctx,
+                         lldb::RegisterKind reg_kind,
+                         DWARFExpression::Stack &stack) const override;
 
   bool ParseDWARFLocationList(const DataExtractor &data,
                               DWARFExpressionList &loc_list) const;
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h 
b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
index 9879fc4fe922c..dd2528d4918cf 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
@@ -339,7 +339,7 @@ class SymbolFileDWARF : public SymbolFileCommon {
                                       lldb::offset_t &offset,
                                       RegisterContext *reg_ctx,
                                       lldb::RegisterKind reg_kind,
-                                      std::vector<Value> &stack) const {
+                                      DWARFExpression::Stack &stack) const {
     return false;
   }
 
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.cpp 
b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.cpp
index 0ac035a32a3f4..b4483a80abc31 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.cpp
@@ -99,7 +99,7 @@ uint64_t SymbolFileDWARFDwo::GetDebugInfoSize(bool 
load_all_debug_info) {
 bool SymbolFileDWARFDwo::ParseVendorDWARFOpcode(
     uint8_t op, const llvm::DataExtractor &opcodes, lldb::offset_t &offset,
     RegisterContext *reg_ctx, lldb::RegisterKind reg_kind,
-    std::vector<Value> &stack) const {
+    DWARFExpression::Stack &stack) const {
   return GetBaseSymbolFile().ParseVendorDWARFOpcode(op, opcodes, offset,
                                                     reg_ctx, reg_kind, stack);
 }
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h 
b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h
index 42fb0e8a943c7..b177187884f5d 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h
@@ -54,7 +54,7 @@ class SymbolFileDWARFDwo : public SymbolFileDWARF {
   bool ParseVendorDWARFOpcode(uint8_t op, const llvm::DataExtractor &opcodes,
                               lldb::offset_t &offset, RegisterContext *reg_ctx,
                               lldb::RegisterKind reg_kind,
-                              std::vector<Value> &stack) const override;
+                              DWARFExpression::Stack &stack) const override;
 
   void FindGlobalVariables(ConstString name,
                            const CompilerDeclContext &parent_decl_ctx,
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileWasm.cpp 
b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileWasm.cpp
index de660d58682cc..8d26e944b640c 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileWasm.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileWasm.cpp
@@ -188,12 +188,10 @@ SymbolFileWasm::GetVendorDWARFOpcodeSize(const 
DataExtractor &data,
   return offset - data_offset;
 }
 
-bool SymbolFileWasm::ParseVendorDWARFOpcode(uint8_t op,
-                                            const llvm::DataExtractor &opcodes,
-                                            lldb::offset_t &offset,
-                                            RegisterContext *reg_ctx,
-                                            lldb::RegisterKind reg_kind,
-                                            std::vector<Value> &stack) const {
+bool SymbolFileWasm::ParseVendorDWARFOpcode(
+    uint8_t op, const llvm::DataExtractor &opcodes, lldb::offset_t &offset,
+    RegisterContext *reg_ctx, lldb::RegisterKind reg_kind,
+    DWARFExpression::Stack &stack) const {
   if (op != llvm::dwarf::DW_OP_WASM_location)
     return false;
 
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileWasm.h 
b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileWasm.h
index 0d7f0c3b59373..87a1e1d9961d3 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileWasm.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileWasm.h
@@ -31,7 +31,7 @@ class SymbolFileWasm : public SymbolFileDWARF {
   bool ParseVendorDWARFOpcode(uint8_t op, const llvm::DataExtractor &opcodes,
                               lldb::offset_t &offset, RegisterContext *reg_ctx,
                               lldb::RegisterKind reg_kind,
-                              std::vector<Value> &stack) const override;
+                              DWARFExpression::Stack &stack) const override;
 };
 } // namespace dwarf
 } // namespace lldb_private::plugin
diff --git a/lldb/unittests/Expression/DWARFExpressionTest.cpp 
b/lldb/unittests/Expression/DWARFExpressionTest.cpp
index 29c9163c1f3f8..cf8c21e9b89f5 100644
--- a/lldb/unittests/Expression/DWARFExpressionTest.cpp
+++ b/lldb/unittests/Expression/DWARFExpressionTest.cpp
@@ -1897,11 +1897,11 @@ class CustomSymbolFileDWARF : public SymbolFileDWARF {
     return offset - data_offset;
   }
 
-  virtual bool ParseVendorDWARFOpcode(
-      uint8_t op, const llvm::DataExtractor &opcodes, lldb::offset_t &offset,
-
-      RegisterContext *reg_ctx, lldb::RegisterKind reg_kind,
-      std::vector<lldb_private::Value> &stack) const override {
+  virtual bool
+  ParseVendorDWARFOpcode(uint8_t op, const llvm::DataExtractor &opcodes,
+                         lldb::offset_t &offset, RegisterContext *reg_ctx,
+                         lldb::RegisterKind reg_kind,
+                         DWARFExpression::Stack &stack) const override {
     if (op != DW_OP_WASM_location) {
       return false;
     }
@@ -2441,3 +2441,88 @@ TEST_F(DWARFExpressionMockProcessTest, 
deref_implicit_value) {
   EXPECT_THAT_EXPECTED(Eval({DW_OP_lit4, DW_OP_deref_size, 1}),
                        ExpectLoadAddress(0x01));
 }
+
+using DWARFStack = DWARFExpression::Stack;
+using LocationDescriptionKind = DWARFStack::LocationDescriptionKind;
+
+static Value MakeStackValue(uint64_t value) { return Value(Scalar(value)); }
+
+static void ExpectStackTop(const DWARFStack &stack, uint64_t value,
+                           LocationDescriptionKind loc_desc_kind) {
+  EXPECT_EQ(stack.back().GetScalar().ULongLong(), value);
+  EXPECT_EQ(stack.GetLocationDescriptionKind(), loc_desc_kind);
+}
+
+TEST(DWARFExpressionStackTest, PushPopAndSetLocationDescriptionKind) {
+  DWARFStack stack;
+  EXPECT_TRUE(stack.empty());
+
+  stack.push_back(MakeStackValue(1));
+  EXPECT_EQ(stack.size(), 1u);
+  ExpectStackTop(stack, 1, LocationDescriptionKind::Memory);
+
+  stack.SetLocationDescriptionKind(LocationDescriptionKind::Implicit);
+  ExpectStackTop(stack, 1, LocationDescriptionKind::Implicit);
+
+  stack.push_back(MakeStackValue(2), LocationDescriptionKind::Register);
+  EXPECT_EQ(stack.size(), 2u);
+  ExpectStackTop(stack, 2, LocationDescriptionKind::Register);
+  EXPECT_EQ(stack[0].GetScalar().ULongLong(), 1u);
+
+  stack.pop_back();
+  EXPECT_EQ(stack.size(), 1u);
+  ExpectStackTop(stack, 1, LocationDescriptionKind::Implicit);
+}
+
+TEST(DWARFExpressionStackTest, PushCopy) {
+  DWARFStack stack;
+  EXPECT_FALSE(stack.PushCopy(0));
+
+  stack.push_back(MakeStackValue(7), LocationDescriptionKind::Register);
+  EXPECT_TRUE(stack.PushCopy(0));
+  EXPECT_EQ(stack.size(), 2u);
+  ExpectStackTop(stack, 7, LocationDescriptionKind::Register);
+
+  stack.back().GetScalar() = Scalar(8);
+  stack.pop_back();
+  ExpectStackTop(stack, 7, LocationDescriptionKind::Register);
+
+  EXPECT_FALSE(stack.PushCopy(1));
+  EXPECT_EQ(stack.size(), 1u);
+}
+
+TEST(DWARFExpressionStackTest, SwapTopTwo) {
+  DWARFStack stack;
+  EXPECT_FALSE(stack.SwapTopTwo());
+
+  stack.push_back(MakeStackValue(1));
+  EXPECT_FALSE(stack.SwapTopTwo());
+  ExpectStackTop(stack, 1, LocationDescriptionKind::Memory);
+
+  stack.push_back(MakeStackValue(2), LocationDescriptionKind::Register);
+  EXPECT_TRUE(stack.SwapTopTwo());
+  ExpectStackTop(stack, 1, LocationDescriptionKind::Memory);
+
+  stack.pop_back();
+  ExpectStackTop(stack, 2, LocationDescriptionKind::Register);
+}
+
+TEST(DWARFExpressionStackTest, RotateTopThree) {
+  DWARFStack stack;
+  EXPECT_FALSE(stack.RotateTopThree());
+
+  stack.push_back(MakeStackValue(1));
+  EXPECT_FALSE(stack.RotateTopThree());
+
+  stack.push_back(MakeStackValue(2), LocationDescriptionKind::Register);
+  EXPECT_FALSE(stack.RotateTopThree());
+
+  stack.push_back(MakeStackValue(3), LocationDescriptionKind::Implicit);
+  EXPECT_TRUE(stack.RotateTopThree());
+
+  ExpectStackTop(stack, 2, LocationDescriptionKind::Register);
+  stack.pop_back();
+  ExpectStackTop(stack, 1, LocationDescriptionKind::Memory);
+  stack.pop_back();
+  ExpectStackTop(stack, 3, LocationDescriptionKind::Implicit);
+}

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

Reply via email to