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/3] [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/3] [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);
+}

>From 5b6302b1408bcee0f9ba7ea7271190d56ab6cb22 Mon Sep 17 00:00:00 2001
From: MrEven132 <[email protected]>
Date: Wed, 16 Sep 2026 16:14:35 +0800
Subject: [PATCH 3/3] [lldb] Simplify the DWARF expression stack representation

Represent the evaluation stack as a vector of StackEntry objects instead of a 
custom stack wrapper. Access values and location-description kinds through the 
same entry, while keeping opcode-specific copy and reorder logic in the 
evaluator.

Take stack entry values by const reference and remove the metadata getter, 
setter, and opcode-specific stack methods. Replace their direct unit tests with 
evaluator-level coverage.
---
 .../include/lldb/Expression/DWARFExpression.h |  87 +----
 lldb/source/Expression/DWARFExpression.cpp    | 337 +++++++++---------
 .../Expression/DWARFExpressionTest.cpp        | 139 +++-----
 3 files changed, 240 insertions(+), 323 deletions(-)

diff --git a/lldb/include/lldb/Expression/DWARFExpression.h 
b/lldb/include/lldb/Expression/DWARFExpression.h
index f8710d555e6a7..90ea94e6582bc 100644
--- a/lldb/include/lldb/Expression/DWARFExpression.h
+++ b/lldb/include/lldb/Expression/DWARFExpression.h
@@ -39,78 +39,25 @@ namespace lldb_private {
 /// location expression or a location list and interprets it.
 class DWARFExpression {
 public:
-  /// 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;
+  enum class LocationDescriptionKind { Empty, Memory, Register, Implicit };
+
+  /// An eagerly materialized value on the DWARF expression stack together
+  /// with the kind of location description that produced it.
+  struct StackEntry {
+    StackEntry(const Value &value, LocationDescriptionKind loc_desc_kind =
+                                       LocationDescriptionKind::Memory)
+        : value(value), loc_desc_kind(loc_desc_kind) {}
+
+    StackEntry(const Scalar &value, LocationDescriptionKind loc_desc_kind =
+                                        LocationDescriptionKind::Memory)
+        : value(value), loc_desc_kind(loc_desc_kind) {}
+
+    Value value;
+    LocationDescriptionKind loc_desc_kind;
   };
 
+  using Stack = std::vector<StackEntry>;
+
   class Delegate {
   public:
     Delegate() = default;
diff --git a/lldb/source/Expression/DWARFExpression.cpp 
b/lldb/source/Expression/DWARFExpression.cpp
index 685fbc847e908..ec86b56ae81a9 100644
--- a/lldb/source/Expression/DWARFExpression.cpp
+++ b/lldb/source/Expression/DWARFExpression.cpp
@@ -53,7 +53,7 @@ using namespace lldb_private::plugin::dwarf;
 using namespace llvm::dwarf;
 
 namespace {
-using LocationDescriptionKind = 
DWARFExpression::Stack::LocationDescriptionKind;
+using LocationDescriptionKind = DWARFExpression::LocationDescriptionKind;
 static constexpr LocationDescriptionKind Empty = 
LocationDescriptionKind::Empty;
 static constexpr LocationDescriptionKind Memory =
     LocationDescriptionKind::Memory;
@@ -971,27 +971,26 @@ 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.
-  LocationDescriptionKind loc_desc_kind =
-      eval_ctx.stack.GetLocationDescriptionKind();
+  LocationDescriptionKind loc_desc_kind = eval_ctx.stack.back().loc_desc_kind;
   if (loc_desc_kind == Register || loc_desc_kind == Implicit) {
     // Reset context to default values.
-    eval_ctx.stack.SetLocationDescriptionKind(Memory);
-    eval_ctx.stack.back().ClearContext();
+    eval_ctx.stack.back().loc_desc_kind = Memory;
+    eval_ctx.stack.back().value.ClearContext();
 
     // Truncate the value on top of the stack to *size* bytes then
     // extend to the size of an address (e.g. generic type).
-    Scalar scalar = eval_ctx.stack.back().GetScalar();
+    Scalar scalar = eval_ctx.stack.back().value.GetScalar();
     scalar.TruncOrExtendTo(size * 8, /*sign=*/false);
     scalar.TruncOrExtendTo(size_addr_bytes * 8,
                            /*sign=*/false);
-    eval_ctx.stack.back().GetScalar() = scalar;
+    eval_ctx.stack.back().value.GetScalar() = scalar;
     return llvm::Error::success();
   }
 
-  Value::ValueType value_type = eval_ctx.stack.back().GetValueType();
+  Value::ValueType value_type = eval_ctx.stack.back().value.GetValueType();
   switch (value_type) {
   case Value::ValueType::HostAddress: {
-    void *src = (void *)eval_ctx.stack.back().GetScalar().ULongLong();
+    void *src = (void *)eval_ctx.stack.back().value.GetScalar().ULongLong();
     intptr_t ptr;
     ::memcpy(&ptr, src, sizeof(void *));
     // I can't decide whether the size operand should apply to the bytes in
@@ -1025,12 +1024,12 @@ static llvm::Error Evaluate_DW_OP_deref(EvalContext 
&eval_ctx,
     default:
       break;
     }
-    eval_ctx.stack.back().GetScalar() = ptr;
-    eval_ctx.stack.back().ClearContext();
+    eval_ctx.stack.back().value.GetScalar() = ptr;
+    eval_ctx.stack.back().value.ClearContext();
   } break;
   case Value::ValueType::FileAddress: {
     auto file_addr =
-        eval_ctx.stack.back().GetScalar().ULongLong(LLDB_INVALID_ADDRESS);
+        
eval_ctx.stack.back().value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS);
     Address so_addr;
     auto maybe_load_addr =
         ResolveLoadAddress(eval_ctx, op_name, file_addr, so_addr,
@@ -1054,19 +1053,19 @@ static llvm::Error Evaluate_DW_OP_deref(EvalContext 
&eval_ctx,
 
       ObjectFile *objfile = eval_ctx.module_sp->GetObjectFile();
 
-      eval_ctx.stack.back().GetScalar() = DerefSizeExtractDataHelper(
+      eval_ctx.stack.back().value.GetScalar() = DerefSizeExtractDataHelper(
           addr_bytes, size, objfile->GetByteOrder(), size);
-      eval_ctx.stack.back().ClearContext();
+      eval_ctx.stack.back().value.ClearContext();
       break;
     }
-    eval_ctx.stack.back().GetScalar() = load_addr;
+    eval_ctx.stack.back().value.GetScalar() = load_addr;
     // Fall through to load address promotion code below.
   }
 
     [[fallthrough]];
   case Value::ValueType::Scalar:
     // Promote Scalar to LoadAddress and fall through.
-    eval_ctx.stack.back().SetValueType(Value::ValueType::LoadAddress);
+    eval_ctx.stack.back().value.SetValueType(Value::ValueType::LoadAddress);
     [[fallthrough]];
   case Value::ValueType::LoadAddress: {
     if (!eval_ctx.exe_ctx)
@@ -1075,7 +1074,7 @@ static llvm::Error Evaluate_DW_OP_deref(EvalContext 
&eval_ctx,
       return llvm::createStringError("no process for %s", op_name);
 
     lldb::addr_t pointer_addr =
-        eval_ctx.stack.back().GetScalar().ULongLong(LLDB_INVALID_ADDRESS);
+        
eval_ctx.stack.back().value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS);
     uint8_t addr_bytes[sizeof(lldb::addr_t)];
     Status error;
 
@@ -1085,9 +1084,9 @@ static llvm::Error Evaluate_DW_OP_deref(EvalContext 
&eval_ctx,
           "failed to dereference pointer from 0x%" PRIx64 " for %s: %s\n",
           pointer_addr, op_name, error.AsCString());
 
-    eval_ctx.stack.back().GetScalar() = DerefSizeExtractDataHelper(
+    eval_ctx.stack.back().value.GetScalar() = DerefSizeExtractDataHelper(
         addr_bytes, sizeof(addr_bytes), eval_ctx.process->GetByteOrder(), 
size);
-    eval_ctx.stack.back().ClearContext();
+    eval_ctx.stack.back().value.ClearContext();
   } break;
 
   case Value::ValueType::Invalid:
@@ -1098,21 +1097,21 @@ static llvm::Error Evaluate_DW_OP_deref(EvalContext 
&eval_ctx,
   // `size` bytes is unnecessary here because the branches above already limit
   // the value to `size` bytes; it is only done for consistency with the
   // Register/Implicit path above.
-  eval_ctx.stack.back().GetScalar().TruncOrExtendTo(size * 8, /*sign=*/false);
-  eval_ctx.stack.back().GetScalar().TruncOrExtendTo(size_addr_bytes * 8,
-                                                    /*sign=*/false);
+  eval_ctx.stack.back().value.GetScalar().TruncOrExtendTo(size * 8,
+                                                          /*sign=*/false);
+  eval_ctx.stack.back().value.GetScalar().TruncOrExtendTo(size_addr_bytes * 8,
+                                                          /*sign=*/false);
   return llvm::Error::success();
 }
 
 static llvm::Error Evaluate_DW_OP_piece(EvalContext &eval_ctx,
                                         uint64_t piece_byte_size) {
   LocationDescriptionKind piece_locdesc =
-      eval_ctx.stack.empty() ? Memory
-                             : eval_ctx.stack.GetLocationDescriptionKind();
+      eval_ctx.stack.empty() ? Memory : eval_ctx.stack.back().loc_desc_kind;
 
   if (piece_byte_size == 0) {
     if (!eval_ctx.stack.empty())
-      eval_ctx.stack.SetLocationDescriptionKind(Memory);
+      eval_ctx.stack.back().loc_desc_kind = Memory;
     return llvm::Error::success();
   }
 
@@ -1134,7 +1133,7 @@ static llvm::Error Evaluate_DW_OP_piece(EvalContext 
&eval_ctx,
   } else {
     Status error;
     // Extract the current piece into "curr_piece"
-    Value curr_piece_source_value(eval_ctx.stack.back());
+    Value curr_piece_source_value(eval_ctx.stack.back().value);
     eval_ctx.stack.pop_back();
     UpdateValueTypeFromLocationDescription(eval_ctx, piece_locdesc,
                                            &curr_piece_source_value);
@@ -1273,7 +1272,7 @@ static llvm::Error Evaluate_DW_OP_convert(EvalContext 
&eval_ctx,
     encoding = bit_size_encoding_or_err->second;
   }
 
-  Scalar &scalar = eval_ctx.stack.back().GetScalar();
+  Scalar &scalar = eval_ctx.stack.back().value.GetScalar();
   if (encoding == llvm::dwarf::DW_ATE_float) {
     const llvm::fltSemantics *semantics;
     switch (bit_size) {
@@ -1341,7 +1340,7 @@ static llvm::Error 
Evaluate_DW_OP_form_tls_address(EvalContext &eval_ctx,
 
   // Lookup the TLS block address for this thread and module.
   const addr_t tls_file_addr =
-      eval_ctx.stack.back().GetScalar().ULongLong(LLDB_INVALID_ADDRESS);
+      eval_ctx.stack.back().value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS);
   const addr_t tls_load_addr =
       thread->GetThreadLocalData(eval_ctx.module_sp, tls_file_addr);
 
@@ -1349,8 +1348,8 @@ static llvm::Error 
Evaluate_DW_OP_form_tls_address(EvalContext &eval_ctx,
     return llvm::createStringError(
         "no TLS data currently exists for this thread");
 
-  eval_ctx.stack.back().GetScalar() = tls_load_addr;
-  eval_ctx.stack.back().SetValueType(Value::ValueType::LoadAddress);
+  eval_ctx.stack.back().value.GetScalar() = tls_load_addr;
+  eval_ctx.stack.back().value.SetValueType(Value::ValueType::LoadAddress);
   return llvm::Error::success();
 }
 
@@ -1367,7 +1366,7 @@ static llvm::Error Evaluate_DW_OP_fbreg(EvalContext 
&eval_ctx,
     return err;
   value += fbreg_offset;
   eval_ctx.stack.push_back(value);
-  eval_ctx.stack.back().SetValueType(Value::ValueType::LoadAddress);
+  eval_ctx.stack.back().value.SetValueType(Value::ValueType::LoadAddress);
   return llvm::Error::success();
 }
 
@@ -1386,7 +1385,7 @@ static llvm::Error 
Evaluate_DW_OP_call_frame_cfa(EvalContext &eval_ctx) {
                                    "opcode");
 
   eval_ctx.stack.push_back(Scalar(cfa));
-  eval_ctx.stack.back().SetValueType(Value::ValueType::LoadAddress);
+  eval_ctx.stack.back().value.SetValueType(Value::ValueType::LoadAddress);
   return llvm::Error::success();
 }
 
@@ -1499,7 +1498,7 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
       for (size_t i = 0; i < count; ++i) {
         StreamString new_value;
         new_value.Printf("[%" PRIu64 "]", static_cast<uint64_t>(i));
-        stack[i].Dump(&new_value);
+        stack[i].value.Dump(&new_value);
         LLDB_LOGF(log, "  %s", new_value.GetData());
       }
       LLDB_LOGF(log, "0x%8.8" PRIx64 ": %s", op_offset,
@@ -1516,7 +1515,7 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
     switch (opcode) {
     case DW_OP_addr:
       stack.push_back(to_generic(op->getRawOperand(0)));
-      stack.back().SetValueType(Value::ValueType::FileAddress);
+      stack.back().value.SetValueType(Value::ValueType::FileAddress);
       break;
 
     case DW_OP_deref: {
@@ -1566,10 +1565,8 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
     case DW_OP_dup:
       if (stack.empty()) {
         return llvm::createStringError("expression stack empty for DW_OP_dup");
-      } else if (!stack.PushCopy(stack.size() - 1)) {
-        return llvm::createStringError(
-            "unable to copy stack entry for DW_OP_dup");
-      }
+      } else
+        stack.push_back(stack.back());
       break;
 
     case DW_OP_drop:
@@ -1580,36 +1577,33 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
       break;
 
     case DW_OP_over:
-      if (!stack.PushCopy(stack.size() - 2))
-        return llvm::createStringError(
-            "unable to copy stack entry for DW_OP_over");
+      stack.push_back(stack[stack.size() - 2]);
       break;
 
     case DW_OP_pick: {
       uint8_t pick_idx = op->getRawOperand(0);
-      if (pick_idx >= stack.size()) {
+      if (pick_idx < stack.size())
+        stack.push_back(stack[stack.size() - 1 - pick_idx]);
+      else {
         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:
-      if (!stack.SwapTopTwo())
-        return llvm::createStringError(
-            "expression stack needs at least 2 items for DW_OP_swap");
+      std::swap(stack[stack.size() - 1], stack[stack.size() - 2]);
       break;
 
-    case DW_OP_rot:
-      if (!stack.RotateTopThree())
-        return llvm::createStringError(
-            "expression stack needs at least 3 items for DW_OP_rot");
-      break;
+    case DW_OP_rot: {
+      size_t last_idx = stack.size() - 1;
+      StackEntry 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_abs:
-      if (!stack.back().GetScalar().AbsoluteValue()) {
+      if (!stack.back().value.GetScalar().AbsoluteValue()) {
         return llvm::createStringError(
             "failed to take the absolute value of the first stack item");
       }
@@ -1617,104 +1611,109 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
 
     case DW_OP_and:
       if (llvm::Error err = CheckScalarOperandsHaveSameType(
-              stack[stack.size() - 2].GetScalar(), stack.back().GetScalar(),
-              opcode, address_size))
+              stack[stack.size() - 2].value.GetScalar(),
+              stack.back().value.GetScalar(), opcode, address_size))
         return err;
-      tmp = stack.back();
+      tmp = stack.back().value;
       stack.pop_back();
-      stack.back().GetScalar() = stack.back().GetScalar() & tmp.GetScalar();
+      stack.back().value.GetScalar() =
+          stack.back().value.GetScalar() & tmp.GetScalar();
       break;
 
     case DW_OP_div: {
       if (llvm::Error err = CheckScalarOperandsHaveSameType(
-              stack[stack.size() - 2].GetScalar(), stack.back().GetScalar(),
-              opcode, address_size))
+              stack[stack.size() - 2].value.GetScalar(),
+              stack.back().value.GetScalar(), opcode, address_size))
         return err;
-      tmp = stack.back();
+      tmp = stack.back().value;
       if (tmp.GetScalar().IsZero())
         return llvm::createStringError("divide by zero");
 
       stack.pop_back();
       Scalar divisor, dividend;
       divisor = tmp.GetScalar();
-      dividend = stack.back().GetScalar();
+      dividend = stack.back().value.GetScalar();
       divisor.MakeSigned();
       dividend.MakeSigned();
-      stack.back() = dividend / divisor;
+      stack.back().value = dividend / divisor;
 
-      if (!stack.back().GetScalar().IsValid())
+      if (!stack.back().value.GetScalar().IsValid())
         return llvm::createStringError("divide failed");
     } break;
 
     case DW_OP_minus:
       if (llvm::Error err = CheckScalarOperandsHaveSameType(
-              stack[stack.size() - 2].GetScalar(), stack.back().GetScalar(),
-              opcode, address_size))
+              stack[stack.size() - 2].value.GetScalar(),
+              stack.back().value.GetScalar(), opcode, address_size))
         return err;
-      tmp = stack.back();
+      tmp = stack.back().value;
       stack.pop_back();
-      stack.back().GetScalar() = stack.back().GetScalar() - tmp.GetScalar();
+      stack.back().value.GetScalar() =
+          stack.back().value.GetScalar() - tmp.GetScalar();
       break;
 
     case DW_OP_mod:
       if (llvm::Error err = CheckScalarOperandsHaveSameType(
-              stack[stack.size() - 2].GetScalar(), stack.back().GetScalar(),
-              opcode, address_size))
+              stack[stack.size() - 2].value.GetScalar(),
+              stack.back().value.GetScalar(), opcode, address_size))
         return err;
-      tmp = stack.back();
+      tmp = stack.back().value;
       stack.pop_back();
       if (IsPotentiallyGenericIntegerOperand(tmp.GetScalar(), address_size) &&
-          IsPotentiallyGenericIntegerOperand(stack.back().GetScalar(),
+          IsPotentiallyGenericIntegerOperand(stack.back().value.GetScalar(),
                                              address_size)) {
         tmp.GetScalar().MakeUnsigned();
-        stack.back().GetScalar().MakeUnsigned();
+        stack.back().value.GetScalar().MakeUnsigned();
       }
-      stack.back().GetScalar() = stack.back().GetScalar() % tmp.GetScalar();
+      stack.back().value.GetScalar() =
+          stack.back().value.GetScalar() % tmp.GetScalar();
       break;
 
     case DW_OP_mul:
       if (llvm::Error err = CheckScalarOperandsHaveSameType(
-              stack[stack.size() - 2].GetScalar(), stack.back().GetScalar(),
-              opcode, address_size))
+              stack[stack.size() - 2].value.GetScalar(),
+              stack.back().value.GetScalar(), opcode, address_size))
         return err;
-      tmp = stack.back();
+      tmp = stack.back().value;
       stack.pop_back();
-      stack.back().GetScalar() = stack.back().GetScalar() * tmp.GetScalar();
+      stack.back().value.GetScalar() =
+          stack.back().value.GetScalar() * tmp.GetScalar();
       break;
 
     case DW_OP_neg:
-      if (!stack.back().GetScalar().UnaryNegate())
+      if (!stack.back().value.GetScalar().UnaryNegate())
         return llvm::createStringError("unary negate failed");
       break;
 
     case DW_OP_not:
-      if (!stack.back().GetScalar().OnesComplement())
+      if (!stack.back().value.GetScalar().OnesComplement())
         return llvm::createStringError("logical NOT failed");
       break;
 
     case DW_OP_or:
       if (llvm::Error err = CheckScalarOperandsHaveSameType(
-              stack[stack.size() - 2].GetScalar(), stack.back().GetScalar(),
-              opcode, address_size))
+              stack[stack.size() - 2].value.GetScalar(),
+              stack.back().value.GetScalar(), opcode, address_size))
         return err;
-      tmp = stack.back();
+      tmp = stack.back().value;
       stack.pop_back();
-      stack.back().GetScalar() = stack.back().GetScalar() | tmp.GetScalar();
+      stack.back().value.GetScalar() =
+          stack.back().value.GetScalar() | tmp.GetScalar();
       break;
 
     case DW_OP_plus:
       if (llvm::Error err = CheckScalarOperandsHaveSameType(
-              stack[stack.size() - 2].GetScalar(), stack.back().GetScalar(),
-              opcode, address_size))
+              stack[stack.size() - 2].value.GetScalar(),
+              stack.back().value.GetScalar(), opcode, address_size))
         return err;
-      tmp = stack.back();
+      tmp = stack.back().value;
       stack.pop_back();
-      stack.back().GetScalar() += tmp.GetScalar();
+      stack.back().value.GetScalar() += tmp.GetScalar();
       break;
 
     case DW_OP_plus_uconst: {
       const uint64_t uconst_value = op->getRawOperand(0);
-      Scalar &operand = stack.back().GetScalar();
+      Scalar &operand = stack.back().value.GetScalar();
       Scalar addend(uconst_value);
       // The addend is interpreted as the same type as the popped operand
       // (DWARF v5, 2.5.1.4). Give it the operand's exact integer type so
@@ -1730,43 +1729,44 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
 
     case DW_OP_shl:
       if (llvm::Error err = CheckScalarOperandsHaveSameType(
-              stack[stack.size() - 2].GetScalar(), stack.back().GetScalar(),
-              opcode, address_size))
+              stack[stack.size() - 2].value.GetScalar(),
+              stack.back().value.GetScalar(), opcode, address_size))
         return err;
-      tmp = stack.back();
+      tmp = stack.back().value;
       stack.pop_back();
-      stack.back().GetScalar() <<= tmp.GetScalar();
+      stack.back().value.GetScalar() <<= tmp.GetScalar();
       break;
 
     case DW_OP_shr:
       if (llvm::Error err = CheckScalarOperandsHaveSameType(
-              stack[stack.size() - 2].GetScalar(), stack.back().GetScalar(),
-              opcode, address_size))
+              stack[stack.size() - 2].value.GetScalar(),
+              stack.back().value.GetScalar(), opcode, address_size))
         return err;
-      tmp = stack.back();
+      tmp = stack.back().value;
       stack.pop_back();
-      if (!stack.back().GetScalar().ShiftRightLogical(tmp.GetScalar()))
+      if (!stack.back().value.GetScalar().ShiftRightLogical(tmp.GetScalar()))
         return llvm::createStringError("DW_OP_shr failed");
       break;
 
     case DW_OP_shra:
       if (llvm::Error err = CheckScalarOperandsHaveSameType(
-              stack[stack.size() - 2].GetScalar(), stack.back().GetScalar(),
-              opcode, address_size))
+              stack[stack.size() - 2].value.GetScalar(),
+              stack.back().value.GetScalar(), opcode, address_size))
         return err;
-      tmp = stack.back();
+      tmp = stack.back().value;
       stack.pop_back();
-      stack.back().GetScalar() >>= tmp.GetScalar();
+      stack.back().value.GetScalar() >>= tmp.GetScalar();
       break;
 
     case DW_OP_xor:
       if (llvm::Error err = CheckScalarOperandsHaveSameType(
-              stack[stack.size() - 2].GetScalar(), stack.back().GetScalar(),
-              opcode, address_size))
+              stack[stack.size() - 2].value.GetScalar(),
+              stack.back().value.GetScalar(), opcode, address_size))
         return err;
-      tmp = stack.back();
+      tmp = stack.back().value;
       stack.pop_back();
-      stack.back().GetScalar() = stack.back().GetScalar() ^ tmp.GetScalar();
+      stack.back().value.GetScalar() =
+          stack.back().value.GetScalar() ^ tmp.GetScalar();
       break;
 
     case DW_OP_skip: {
@@ -1785,7 +1785,7 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
     }
 
     case DW_OP_bra: {
-      tmp = stack.back();
+      tmp = stack.back().value;
       stack.pop_back();
       int16_t bra_offset = static_cast<int16_t>(op->getRawOperand(0));
       Scalar zero(0);
@@ -1806,92 +1806,92 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
 
     case DW_OP_eq:
       if (llvm::Error err = CheckScalarOperandsHaveSameType(
-              stack[stack.size() - 2].GetScalar(), stack.back().GetScalar(),
-              opcode, address_size))
+              stack[stack.size() - 2].value.GetScalar(),
+              stack.back().value.GetScalar(), opcode, address_size))
         return err;
-      tmp = stack.back();
+      tmp = stack.back().value;
       stack.pop_back();
-      stack.back().GetScalar() =
-          to_generic(stack.back().GetScalar() == tmp.GetScalar());
+      stack.back().value.GetScalar() =
+          to_generic(stack.back().value.GetScalar() == tmp.GetScalar());
       break;
 
     case DW_OP_ge:
       if (llvm::Error err = CheckScalarOperandsHaveSameType(
-              stack[stack.size() - 2].GetScalar(), stack.back().GetScalar(),
-              opcode, address_size))
+              stack[stack.size() - 2].value.GetScalar(),
+              stack.back().value.GetScalar(), opcode, address_size))
         return err;
-      tmp = stack.back();
+      tmp = stack.back().value;
       stack.pop_back();
       if (IsPotentiallyGenericIntegerOperand(tmp.GetScalar(), address_size) &&
-          IsPotentiallyGenericIntegerOperand(stack.back().GetScalar(),
+          IsPotentiallyGenericIntegerOperand(stack.back().value.GetScalar(),
                                              address_size)) {
         tmp.GetScalar().MakeSigned();
-        stack.back().GetScalar().MakeSigned();
+        stack.back().value.GetScalar().MakeSigned();
       }
-      stack.back().GetScalar() =
-          to_generic(stack.back().GetScalar() >= tmp.GetScalar());
+      stack.back().value.GetScalar() =
+          to_generic(stack.back().value.GetScalar() >= tmp.GetScalar());
       break;
 
     case DW_OP_gt:
       if (llvm::Error err = CheckScalarOperandsHaveSameType(
-              stack[stack.size() - 2].GetScalar(), stack.back().GetScalar(),
-              opcode, address_size))
+              stack[stack.size() - 2].value.GetScalar(),
+              stack.back().value.GetScalar(), opcode, address_size))
         return err;
-      tmp = stack.back();
+      tmp = stack.back().value;
       stack.pop_back();
       if (IsPotentiallyGenericIntegerOperand(tmp.GetScalar(), address_size) &&
-          IsPotentiallyGenericIntegerOperand(stack.back().GetScalar(),
+          IsPotentiallyGenericIntegerOperand(stack.back().value.GetScalar(),
                                              address_size)) {
         tmp.GetScalar().MakeSigned();
-        stack.back().GetScalar().MakeSigned();
+        stack.back().value.GetScalar().MakeSigned();
       }
-      stack.back().GetScalar() =
-          to_generic(stack.back().GetScalar() > tmp.GetScalar());
+      stack.back().value.GetScalar() =
+          to_generic(stack.back().value.GetScalar() > tmp.GetScalar());
       break;
 
     case DW_OP_le:
       if (llvm::Error err = CheckScalarOperandsHaveSameType(
-              stack[stack.size() - 2].GetScalar(), stack.back().GetScalar(),
-              opcode, address_size))
+              stack[stack.size() - 2].value.GetScalar(),
+              stack.back().value.GetScalar(), opcode, address_size))
         return err;
-      tmp = stack.back();
+      tmp = stack.back().value;
       stack.pop_back();
       if (IsPotentiallyGenericIntegerOperand(tmp.GetScalar(), address_size) &&
-          IsPotentiallyGenericIntegerOperand(stack.back().GetScalar(),
+          IsPotentiallyGenericIntegerOperand(stack.back().value.GetScalar(),
                                              address_size)) {
         tmp.GetScalar().MakeSigned();
-        stack.back().GetScalar().MakeSigned();
+        stack.back().value.GetScalar().MakeSigned();
       }
-      stack.back().GetScalar() =
-          to_generic(stack.back().GetScalar() <= tmp.GetScalar());
+      stack.back().value.GetScalar() =
+          to_generic(stack.back().value.GetScalar() <= tmp.GetScalar());
       break;
 
     case DW_OP_lt:
       if (llvm::Error err = CheckScalarOperandsHaveSameType(
-              stack[stack.size() - 2].GetScalar(), stack.back().GetScalar(),
-              opcode, address_size))
+              stack[stack.size() - 2].value.GetScalar(),
+              stack.back().value.GetScalar(), opcode, address_size))
         return err;
-      tmp = stack.back();
+      tmp = stack.back().value;
       stack.pop_back();
       if (IsPotentiallyGenericIntegerOperand(tmp.GetScalar(), address_size) &&
-          IsPotentiallyGenericIntegerOperand(stack.back().GetScalar(),
+          IsPotentiallyGenericIntegerOperand(stack.back().value.GetScalar(),
                                              address_size)) {
         tmp.GetScalar().MakeSigned();
-        stack.back().GetScalar().MakeSigned();
+        stack.back().value.GetScalar().MakeSigned();
       }
-      stack.back().GetScalar() =
-          to_generic(stack.back().GetScalar() < tmp.GetScalar());
+      stack.back().value.GetScalar() =
+          to_generic(stack.back().value.GetScalar() < tmp.GetScalar());
       break;
 
     case DW_OP_ne:
       if (llvm::Error err = CheckScalarOperandsHaveSameType(
-              stack[stack.size() - 2].GetScalar(), stack.back().GetScalar(),
-              opcode, address_size))
+              stack[stack.size() - 2].value.GetScalar(),
+              stack.back().value.GetScalar(), opcode, address_size))
         return err;
-      tmp = stack.back();
+      tmp = stack.back().value;
       stack.pop_back();
-      stack.back().GetScalar() =
-          to_generic(stack.back().GetScalar() != tmp.GetScalar());
+      stack.back().value.GetScalar() =
+          to_generic(stack.back().value.GetScalar() != tmp.GetScalar());
       break;
 
     case DW_OP_lit0:
@@ -1966,7 +1966,7 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
       if (llvm::Error err = ReadRegisterValueAsScalar(
               eval_ctx.reg_ctx, eval_ctx.reg_kind, reg_num, tmp))
         return err;
-      stack.push_back(tmp, Register);
+      stack.emplace_back(tmp, Register);
     } break;
     case DW_OP_regx: {
       reg_num = op->getRawOperand(0);
@@ -1974,7 +1974,7 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
       if (llvm::Error err = ReadRegisterValueAsScalar(
               eval_ctx.reg_ctx, eval_ctx.reg_kind, reg_num, tmp))
         return err;
-      stack.push_back(tmp, Register);
+      stack.emplace_back(tmp, Register);
     } break;
 
     case DW_OP_breg0:
@@ -2019,7 +2019,7 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
       tmp.GetScalar() += to_generic(breg_offset);
       tmp.ClearContext();
       stack.push_back(tmp);
-      stack.back().SetValueType(Value::ValueType::LoadAddress);
+      stack.back().value.SetValueType(Value::ValueType::LoadAddress);
     } break;
     case DW_OP_bregx: {
       reg_num = op->getRawOperand(0);
@@ -2032,15 +2032,15 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
       tmp.GetScalar() += to_generic(breg_offset);
       tmp.ClearContext();
       stack.push_back(tmp);
-      stack.back().SetValueType(Value::ValueType::LoadAddress);
+      stack.back().value.SetValueType(Value::ValueType::LoadAddress);
     } break;
 
     case DW_OP_fbreg:
       if (llvm::Error err =
               Evaluate_DW_OP_fbreg(eval_ctx, op->getRawOperand(0)))
         return err;
-      stack.back().GetScalar() =
-          to_generic(stack.back().GetScalar().ULongLong());
+      stack.back().value.GetScalar() =
+          to_generic(stack.back().value.GetScalar().ULongLong());
       break;
 
     case DW_OP_nop:
@@ -2060,25 +2060,25 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
             "expression stack needs at least 1 item for DW_OP_bit_piece");
       } else {
         const LocationDescriptionKind piece_locdesc =
-            stack.GetLocationDescriptionKind();
+            stack.back().loc_desc_kind;
         UpdateValueTypeFromLocationDescription(eval_ctx, piece_locdesc,
-                                               &stack.back());
+                                               &stack.back().value);
         // Reset for the next piece.
-        stack.SetLocationDescriptionKind(Memory);
+        stack.back().loc_desc_kind = Memory;
         const uint64_t piece_bit_size = op->getRawOperand(0);
         const uint64_t piece_bit_offset = op->getRawOperand(1);
-        switch (stack.back().GetValueType()) {
+        switch (stack.back().value.GetValueType()) {
         case Value::ValueType::Invalid:
           return llvm::createStringError(
               "unable to extract bit value from invalid value");
         case Value::ValueType::Scalar: {
-          if (!stack.back().GetScalar().ExtractBitfield(piece_bit_size,
-                                                        piece_bit_offset)) {
+          if (!stack.back().value.GetScalar().ExtractBitfield(
+                  piece_bit_size, piece_bit_offset)) {
             return llvm::createStringError(
                 "unable to extract %" PRIu64 " bit value with %" PRIu64
                 " bit offset from a %" PRIu64 " bit scalar value.",
                 piece_bit_size, piece_bit_offset,
-                (uint64_t)(stack.back().GetScalar().GetByteSize() * 8));
+                (uint64_t)(stack.back().value.GetScalar().GetByteSize() * 8));
           }
         } break;
 
@@ -2094,7 +2094,8 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
           // backing bytes, not the address of that backing storage.
           if (piece_locdesc == Implicit && piece_bit_offset == 0 &&
               piece_bit_size % 8 == 0 &&
-              stack.back().GetBuffer().GetByteSize() == piece_bit_size / 8)
+              stack.back().value.GetBuffer().GetByteSize() ==
+                  piece_bit_size / 8)
             break;
           return llvm::createStringError(
               "unable to extract DW_OP_bit_piece(bit_size = %" PRIu64
@@ -2118,7 +2119,7 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
         return error;
 
       Value result(block_data.data(), block_data.size());
-      stack.push_back(result, Implicit);
+      stack.emplace_back(result, Implicit);
       break;
     }
 
@@ -2137,8 +2138,8 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
       break;
 
     case DW_OP_stack_value:
-      stack.SetLocationDescriptionKind(Implicit);
-      stack.back().SetValueType(Value::ValueType::Scalar);
+      stack.back().loc_desc_kind = Implicit;
+      stack.back().value.SetValueType(Value::ValueType::Scalar);
       break;
 
     case DW_OP_convert:
@@ -2150,8 +2151,8 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
     case DW_OP_call_frame_cfa:
       if (llvm::Error err = Evaluate_DW_OP_call_frame_cfa(eval_ctx))
         return err;
-      stack.back().GetScalar() =
-          to_generic(stack.back().GetScalar().ULongLong());
+      stack.back().value.GetScalar() =
+          to_generic(stack.back().value.GetScalar().ULongLong());
       break;
 
     case DW_OP_form_tls_address:
@@ -2169,7 +2170,7 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
       lldb::addr_t value =
           eval_ctx.dwarf_cu->ReadAddressFromDebugAddrSection(index);
       stack.push_back(to_generic(value));
-      stack.back().SetValueType(Value::ValueType::FileAddress);
+      stack.back().value.SetValueType(Value::ValueType::FileAddress);
     } break;
 
     case DW_OP_GNU_const_index: {
@@ -2261,8 +2262,8 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
     return llvm::createStringError("stack empty after evaluation");
   }
 
-  UpdateValueTypeFromLocationDescription(
-      eval_ctx, stack.GetLocationDescriptionKind(), &stack.back());
+  UpdateValueTypeFromLocationDescription(eval_ctx, stack.back().loc_desc_kind,
+                                         &stack.back().value);
 
   if (log && log->GetVerbose()) {
     size_t count = stack.size();
@@ -2271,11 +2272,11 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
     for (size_t i = 0; i < count; ++i) {
       StreamString new_value;
       new_value.Printf("[%" PRIu64 "]", static_cast<uint64_t>(i));
-      stack[i].Dump(&new_value);
+      stack[i].value.Dump(&new_value);
       LLDB_LOGF(log, "  %s", new_value.GetData());
     }
   }
-  return stack.back();
+  return stack.back().value;
 }
 
 bool DWARFExpression::MatchesOperand(
diff --git a/lldb/unittests/Expression/DWARFExpressionTest.cpp 
b/lldb/unittests/Expression/DWARFExpressionTest.cpp
index 7270a0f3c3811..1dfb8d8a41377 100644
--- a/lldb/unittests/Expression/DWARFExpressionTest.cpp
+++ b/lldb/unittests/Expression/DWARFExpressionTest.cpp
@@ -2409,6 +2409,60 @@ TEST_F(DWARFExpressionMockProcessTest, 
DW_OP_drop_location_description) {
                        ExpectLoadAddress(0x0201));
 }
 
+TEST_F(DWARFExpressionMockProcessTest, DW_OP_swap_rot_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());
+  };
+
+  // Swapping a register location with the memory location underneath keeps
+  // each entry's location kind with its value: the new top is a memory
+  // location and is dereferenced as an address.
+  EXPECT_THAT_EXPECTED(
+      Eval({DW_OP_lit4, DW_OP_reg0, DW_OP_swap, DW_OP_deref_size, 2}),
+      ExpectLoadAddress(0x0201));
+
+  // Rotating the top three entries keeps each entry's location kind with its
+  // value: the new top (lit4) is a memory location.
+  EXPECT_THAT_EXPECTED(Eval({DW_OP_lit5, DW_OP_lit4, DW_OP_reg0, DW_OP_rot,
+                             DW_OP_deref_size, 2}),
+                       ExpectLoadAddress(0x0201));
+}
+
+TEST_F(DWARFExpressionMockProcessTest, DW_OP_copy_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());
+  };
+
+  // Copying a register location keeps the copied entry's kind: dereferencing
+  // the new top truncates the register value instead of reading memory.
+  EXPECT_THAT_EXPECTED(Eval({DW_OP_reg0, DW_OP_dup, DW_OP_deref_size, 2}),
+                       ExpectLoadAddress(0x0504));
+
+  EXPECT_THAT_EXPECTED(
+      Eval({DW_OP_reg0, DW_OP_lit4, DW_OP_over, DW_OP_deref_size, 2}),
+      ExpectLoadAddress(0x0504));
+
+  EXPECT_THAT_EXPECTED(
+      Eval({DW_OP_reg0, DW_OP_lit4, DW_OP_pick, 1, DW_OP_deref_size, 2}),
+      ExpectLoadAddress(0x0504));
+}
+
 TEST_F(DWARFExpressionMockProcessTest, deref_implicit_value) {
   TestContext test_ctx;
   MockMemory::Map memory = {
@@ -2452,88 +2506,3 @@ 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