[lldb] [llvm] [lldb] Use llvm::DWARFExpression::iterator in DWARFExpression::Evaluate (PR #190556)

Sergei Barannikov via llvm-commits llvm-commits at lists.llvm.org
Sun Apr 5 15:36:32 PDT 2026


https://github.com/s-barannikov created https://github.com/llvm/llvm-project/pull/190556

None

>From 1264d5d769982608e177442990f8573d623fa668 Mon Sep 17 00:00:00 2001
From: Sergei Barannikov <barannikov88 at gmail.com>
Date: Mon, 6 Apr 2026 01:27:36 +0300
Subject: [PATCH 1/3] Rename op -> opcode to disambiguate with op - operation

---
 lldb/source/Expression/DWARFExpression.cpp | 28 +++++++++++-----------
 1 file changed, 14 insertions(+), 14 deletions(-)

diff --git a/lldb/source/Expression/DWARFExpression.cpp b/lldb/source/Expression/DWARFExpression.cpp
index 1e12b868191ab..80a959966264b 100644
--- a/lldb/source/Expression/DWARFExpression.cpp
+++ b/lldb/source/Expression/DWARFExpression.cpp
@@ -1077,7 +1077,8 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
 
   while (opcodes.ValidOffset(offset)) {
     const lldb::offset_t op_offset = offset;
-    const uint8_t op = opcodes.GetU8(&offset);
+    const LocationAtom opcode =
+        static_cast<LocationAtom>(opcodes.GetU8(&offset));
 
     if (log && log->GetVerbose()) {
       size_t count = stack.size();
@@ -1090,18 +1091,17 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
         LLDB_LOGF(log, "  %s", new_value.GetData());
       }
       LLDB_LOGF(log, "0x%8.8" PRIx64 ": %s", op_offset,
-                DW_OP_value_to_name(op));
+                DW_OP_value_to_name(opcode));
     }
 
-    if (std::optional<unsigned> arity =
-            llvm::dwarf::OperationArity(static_cast<LocationAtom>(op))) {
+    if (std::optional<unsigned> arity = OperationArity(opcode)) {
       if (stack.size() < *arity)
         return llvm::createStringError(
             "%s needs at least %d stack entries (stack has %d entries)",
-            DW_OP_value_to_name(op), *arity, stack.size());
+            DW_OP_value_to_name(opcode), *arity, stack.size());
     }
 
-    switch (op) {
+    switch (opcode) {
     // The DW_OP_addr operation has a single operand that encodes a machine
     // address and whose size is the size of an address on the target machine.
     case DW_OP_addr:
@@ -1662,7 +1662,7 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
     case DW_OP_lit29:
     case DW_OP_lit30:
     case DW_OP_lit31:
-      stack.push_back(to_generic(op - DW_OP_lit0));
+      stack.push_back(to_generic(opcode - DW_OP_lit0));
       break;
 
     // OPCODE: DW_OP_regN
@@ -1701,7 +1701,7 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
     case DW_OP_reg30:
     case DW_OP_reg31: {
       dwarf4_location_description_kind = Register;
-      reg_num = op - DW_OP_reg0;
+      reg_num = opcode - DW_OP_reg0;
 
       if (llvm::Error err =
               ReadRegisterValueAsScalar(reg_ctx, reg_kind, reg_num, tmp))
@@ -1759,7 +1759,7 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
     case DW_OP_breg29:
     case DW_OP_breg30:
     case DW_OP_breg31: {
-      reg_num = op - DW_OP_breg0;
+      reg_num = opcode - DW_OP_breg0;
       if (llvm::Error err =
               ReadRegisterValueAsScalar(reg_ctx, reg_kind, reg_num, tmp))
         return err;
@@ -2016,7 +2016,7 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
       if (!data) {
         LLDB_LOG(log, "Evaluate_DW_OP_implicit_value: could not be read data");
         return llvm::createStringError("could not evaluate %s",
-                                       DW_OP_value_to_name(op));
+                                       DW_OP_value_to_name(opcode));
       }
 
       Value result(data, len);
@@ -2027,7 +2027,7 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
     case DW_OP_implicit_pointer: {
       dwarf4_location_description_kind = Implicit;
       return llvm::createStringError("could not evaluate %s",
-                                     DW_OP_value_to_name(op));
+                                     DW_OP_value_to_name(opcode));
     }
 
     // OPCODE: DW_OP_push_object_address
@@ -2168,7 +2168,7 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
     case DW_OP_form_tls_address:
     case DW_OP_GNU_push_tls_address: {
       if (stack.size() < 1) {
-        if (op == DW_OP_form_tls_address)
+        if (opcode == DW_OP_form_tls_address)
           return llvm::createStringError(
               "DW_OP_form_tls_address needs an argument");
         else
@@ -2250,13 +2250,13 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
 
     default:
       if (dwarf_cu) {
-        if (dwarf_cu->ParseVendorDWARFOpcode(op, opcodes, offset, reg_ctx,
+        if (dwarf_cu->ParseVendorDWARFOpcode(opcode, opcodes, offset, reg_ctx,
                                              reg_kind, stack)) {
           break;
         }
       }
       return llvm::createStringErrorV("unhandled opcode {0} in DWARFExpression",
-                                      LocationAtom(op));
+                                      opcode);
     }
   }
 

>From 7cbf1bab7597331db59d7937d345e2407220165e Mon Sep 17 00:00:00 2001
From: Sergei Barannikov <barannikov88 at gmail.com>
Date: Mon, 6 Apr 2026 01:30:59 +0300
Subject: [PATCH 2/3] Pass llvm version to vendor-specific parsers

---
 lldb/include/lldb/Expression/DWARFExpression.h       |  2 +-
 lldb/source/Expression/DWARFExpression.cpp           |  3 ++-
 lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp   |  3 ++-
 lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h     |  3 ++-
 .../Plugins/SymbolFile/DWARF/SymbolFileDWARF.h       |  3 ++-
 .../Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.cpp  |  2 +-
 .../Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h    |  2 +-
 .../Plugins/SymbolFile/DWARF/SymbolFileWasm.cpp      | 12 ++++++------
 .../source/Plugins/SymbolFile/DWARF/SymbolFileWasm.h |  2 +-
 lldb/unittests/Expression/DWARFExpressionTest.cpp    |  9 ++++-----
 10 files changed, 22 insertions(+), 19 deletions(-)

diff --git a/lldb/include/lldb/Expression/DWARFExpression.h b/lldb/include/lldb/Expression/DWARFExpression.h
index 1f8464cf5cf85..b1895690985a7 100644
--- a/lldb/include/lldb/Expression/DWARFExpression.h
+++ b/lldb/include/lldb/Expression/DWARFExpression.h
@@ -53,7 +53,7 @@ class DWARFExpression {
                              const lldb::offset_t data_offset,
                              const uint8_t op) const = 0;
     virtual bool
-    ParseVendorDWARFOpcode(uint8_t op, const DataExtractor &opcodes,
+    ParseVendorDWARFOpcode(uint8_t op, const llvm::DataExtractor &opcodes,
                            lldb::offset_t &offset, RegisterContext *reg_ctx,
                            lldb::RegisterKind reg_kind, Stack &stack) const = 0;
 
diff --git a/lldb/source/Expression/DWARFExpression.cpp b/lldb/source/Expression/DWARFExpression.cpp
index 80a959966264b..6d6689d616d64 100644
--- a/lldb/source/Expression/DWARFExpression.cpp
+++ b/lldb/source/Expression/DWARFExpression.cpp
@@ -1026,6 +1026,7 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
     const DWARFExpression::Delegate *dwarf_cu,
     const lldb::RegisterKind reg_kind, const Value *initial_value_ptr,
     const Value *object_address_ptr) {
+  llvm::DataExtractor expr_data = opcodes.GetAsLLVM();
 
   if (opcodes.GetByteSize() == 0)
     return llvm::createStringError(
@@ -2250,7 +2251,7 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
 
     default:
       if (dwarf_cu) {
-        if (dwarf_cu->ParseVendorDWARFOpcode(opcode, opcodes, offset, reg_ctx,
+        if (dwarf_cu->ParseVendorDWARFOpcode(opcode, expr_data, offset, reg_ctx,
                                              reg_kind, stack)) {
           break;
         }
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp
index 429cc7a4a611a..dbdab47528961 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp
@@ -754,7 +754,8 @@ DWARFUnit::GetVendorDWARFOpcodeSize(const DataExtractor &data,
   return GetSymbolFileDWARF().GetVendorDWARFOpcodeSize(data, data_offset, op);
 }
 
-bool DWARFUnit::ParseVendorDWARFOpcode(uint8_t op, const DataExtractor &opcodes,
+bool DWARFUnit::ParseVendorDWARFOpcode(uint8_t op,
+                                       const llvm::DataExtractor &opcodes,
                                        lldb::offset_t &offset,
                                        RegisterContext *reg_ctx,
                                        lldb::RegisterKind reg_kind,
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h b/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h
index b5199a891e3bd..6fde9af57fa8b 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h
@@ -164,7 +164,8 @@ 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 DataExtractor &opcodes,
+  virtual bool ParseVendorDWARFOpcode(uint8_t op,
+                                      const llvm::DataExtractor &opcodes,
                                       lldb::offset_t &offset,
                                       RegisterContext *reg_ctx,
                                       lldb::RegisterKind reg_kind,
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
index a60527b8eda33..09dc8da9b7260 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
@@ -330,7 +330,8 @@ class SymbolFileDWARF : public SymbolFileCommon {
     return LLDB_INVALID_OFFSET;
   }
 
-  virtual bool ParseVendorDWARFOpcode(uint8_t op, const DataExtractor &opcodes,
+  virtual bool ParseVendorDWARFOpcode(uint8_t op,
+                                      const llvm::DataExtractor &opcodes,
                                       lldb::offset_t &offset,
                                       RegisterContext *reg_ctx,
                                       lldb::RegisterKind reg_kind,
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.cpp
index 60d87c3fc2559..0ac035a32a3f4 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.cpp
@@ -97,7 +97,7 @@ uint64_t SymbolFileDWARFDwo::GetDebugInfoSize(bool load_all_debug_info) {
 }
 
 bool SymbolFileDWARFDwo::ParseVendorDWARFOpcode(
-    uint8_t op, const DataExtractor &opcodes, lldb::offset_t &offset,
+    uint8_t op, const llvm::DataExtractor &opcodes, lldb::offset_t &offset,
     RegisterContext *reg_ctx, lldb::RegisterKind reg_kind,
     std::vector<Value> &stack) const {
   return GetBaseSymbolFile().ParseVendorDWARFOpcode(op, opcodes, offset,
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h
index d906e09fe81ab..42fb0e8a943c7 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h
@@ -51,7 +51,7 @@ class SymbolFileDWARFDwo : public SymbolFileDWARF {
 
   uint64_t GetDebugInfoSize(bool load_all_debug_info = false) override;
 
-  bool ParseVendorDWARFOpcode(uint8_t op, const DataExtractor &opcodes,
+  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;
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileWasm.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileWasm.cpp
index e25a89cfe26b2..451cbebed837f 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileWasm.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileWasm.cpp
@@ -47,7 +47,7 @@ SymbolFileWasm::GetVendorDWARFOpcodeSize(const DataExtractor &data,
 }
 
 bool SymbolFileWasm::ParseVendorDWARFOpcode(uint8_t op,
-                                            const DataExtractor &opcodes,
+                                            const llvm::DataExtractor &opcodes,
                                             lldb::offset_t &offset,
                                             RegisterContext *reg_ctx,
                                             lldb::RegisterKind reg_kind,
@@ -63,22 +63,22 @@ bool SymbolFileWasm::ParseVendorDWARFOpcode(uint8_t op,
   /// |0                    | Local                 |
   /// |1 or 3               | Global                |
   /// |2                    | Operand Stack         |
-  const uint8_t wasm_op = opcodes.GetU8(&offset);
+  const uint8_t wasm_op = opcodes.getU8(&offset);
   switch (wasm_op) {
   case 0: // LOCAL
-    index = opcodes.GetULEB128(&offset);
+    index = opcodes.getULEB128(&offset);
     tag = eWasmTagLocal;
     break;
   case 1: // GLOBAL_FIXED
-    index = opcodes.GetULEB128(&offset);
+    index = opcodes.getULEB128(&offset);
     tag = eWasmTagGlobal;
     break;
   case 2: // OPERAND_STACK
-    index = opcodes.GetULEB128(&offset);
+    index = opcodes.getULEB128(&offset);
     tag = eWasmTagOperandStack;
     break;
   case 3: // GLOBAL_RELOC
-    index = opcodes.GetU32(&offset);
+    index = opcodes.getU32(&offset);
     tag = eWasmTagGlobal;
     break;
   default:
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileWasm.h b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileWasm.h
index 0e0b742f53f18..fdf0e75f80161 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileWasm.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileWasm.h
@@ -23,7 +23,7 @@ class SymbolFileWasm : public SymbolFileDWARF {
                                           const lldb::offset_t data_offset,
                                           const uint8_t op) const override;
 
-  bool ParseVendorDWARFOpcode(uint8_t op, const DataExtractor &opcodes,
+  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;
diff --git a/lldb/unittests/Expression/DWARFExpressionTest.cpp b/lldb/unittests/Expression/DWARFExpressionTest.cpp
index d8e23eb8cb4ab..77d6ddd21dc44 100644
--- a/lldb/unittests/Expression/DWARFExpressionTest.cpp
+++ b/lldb/unittests/Expression/DWARFExpressionTest.cpp
@@ -74,7 +74,7 @@ class MockDwarfDelegate : public DWARFExpression::Delegate {
     return LLDB_INVALID_OFFSET;
   }
 
-  bool ParseVendorDWARFOpcode(uint8_t op, const DataExtractor &opcodes,
+  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 {
@@ -802,8 +802,7 @@ class CustomSymbolFileDWARF : public SymbolFileDWARF {
   }
 
   virtual bool ParseVendorDWARFOpcode(
-      uint8_t op, const lldb_private::DataExtractor &opcodes,
-      lldb::offset_t &offset,
+      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 {
@@ -814,12 +813,12 @@ class CustomSymbolFileDWARF : public SymbolFileDWARF {
     // DW_OP_WASM_location WASM_GLOBAL:0x03 index:u32
     // Called with "arguments" 0x03 and  0x04
     // Location type:
-    if (opcodes.GetU8(&offset) != /* global */ 0x03) {
+    if (opcodes.getU8(&offset) != /* global */ 0x03) {
       return false;
     }
 
     // Index:
-    if (opcodes.GetU32(&offset) != 0x04) {
+    if (opcodes.getU32(&offset) != 0x04) {
       return false;
     }
 

>From 7d4f16339a75035947cbc885b2722776d7d963ab Mon Sep 17 00:00:00 2001
From: Sergei Barannikov <barannikov88 at gmail.com>
Date: Mon, 6 Apr 2026 00:43:11 +0300
Subject: [PATCH 3/3] [lldb] Use llvm::DWARFExpression::iterator in
 DWARFExpression::Evaluate

---
 lldb/source/Expression/CMakeLists.txt         |   1 +
 lldb/source/Expression/DWARFExpression.cpp    | 166 ++++++++++--------
 .../DWARF/LowLevel/DWARFExpression.h          |   2 +
 3 files changed, 96 insertions(+), 73 deletions(-)

diff --git a/lldb/source/Expression/CMakeLists.txt b/lldb/source/Expression/CMakeLists.txt
index 515289cd0f091..d40bf184eb02e 100644
--- a/lldb/source/Expression/CMakeLists.txt
+++ b/lldb/source/Expression/CMakeLists.txt
@@ -25,6 +25,7 @@ add_lldb_library(lldbExpression NO_PLUGIN_DEPENDENCIES
   LINK_COMPONENTS
     Core
     DebugInfoDWARF
+    DebugInfoDWARFLowLevel
     ExecutionEngine
     Support
   LINK_LIBS
diff --git a/lldb/source/Expression/DWARFExpression.cpp b/lldb/source/Expression/DWARFExpression.cpp
index 6d6689d616d64..a3f6ccc304da5 100644
--- a/lldb/source/Expression/DWARFExpression.cpp
+++ b/lldb/source/Expression/DWARFExpression.cpp
@@ -593,8 +593,7 @@ bool DWARFExpression::LinkThreadLocalStorage(
 static llvm::Error Evaluate_DW_OP_entry_value(DWARFExpression::Stack &stack,
                                               ExecutionContext *exe_ctx,
                                               RegisterContext *reg_ctx,
-                                              const DataExtractor &opcodes,
-                                              lldb::offset_t &opcode_offset,
+                                              llvm::ArrayRef<uint8_t> subexpr,
                                               Log *log) {
   // DW_OP_entry_value(sub-expr) describes the location a variable had upon
   // function entry: this variable location is presumed to be optimized out at
@@ -729,11 +728,6 @@ static llvm::Error Evaluate_DW_OP_entry_value(DWARFExpression::Stack &stack,
   // 3. Attempt to locate the DW_OP_entry_value expression in the set of
   //    available call site parameters. If found, evaluate the corresponding
   //    parameter in the context of the parent frame.
-  const uint32_t subexpr_len = opcodes.GetULEB128(&opcode_offset);
-  const void *subexpr_data = opcodes.GetData(&opcode_offset, subexpr_len);
-  if (!subexpr_data)
-    return llvm::createStringError("subexpr could not be read");
-
   const CallSiteParameter *matched_param = nullptr;
   for (const CallSiteParameter &param : call_edge->GetCallSiteParameters()) {
     DataExtractor param_subexpr_extractor;
@@ -741,7 +735,7 @@ static llvm::Error Evaluate_DW_OP_entry_value(DWARFExpression::Stack &stack,
       continue;
     lldb::offset_t param_subexpr_offset = 0;
     const void *param_subexpr_data =
-        param_subexpr_extractor.GetData(&param_subexpr_offset, subexpr_len);
+        param_subexpr_extractor.GetData(&param_subexpr_offset, subexpr.size());
     if (!param_subexpr_data ||
         param_subexpr_extractor.BytesLeft(param_subexpr_offset) != 0)
       continue;
@@ -753,7 +747,7 @@ static llvm::Error Evaluate_DW_OP_entry_value(DWARFExpression::Stack &stack,
     // Note that an equality check is sufficient: the contents of the
     // DW_OP_entry_value subexpression are only used to identify the right call
     // site parameter in the parent, and do not require any special handling.
-    if (memcmp(subexpr_data, param_subexpr_data, subexpr_len) == 0) {
+    if (memcmp(subexpr.data(), param_subexpr_data, subexpr.size()) == 0) {
       matched_param = ¶m;
       break;
     }
@@ -1026,9 +1020,11 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
     const DWARFExpression::Delegate *dwarf_cu,
     const lldb::RegisterKind reg_kind, const Value *initial_value_ptr,
     const Value *object_address_ptr) {
+  uint32_t address_size = opcodes.GetAddressByteSize();
   llvm::DataExtractor expr_data = opcodes.GetAsLLVM();
+  llvm::DWARFExpression expr(expr_data, address_size);
 
-  if (opcodes.GetByteSize() == 0)
+  if (expr_data.size() == 0)
     return llvm::createStringError(
         "no location, value may have been optimized out");
 
@@ -1049,7 +1045,6 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
   if (initial_value_ptr)
     stack.push_back(*initial_value_ptr);
 
-  lldb::offset_t offset = 0;
   Value tmp;
   uint32_t reg_num;
 
@@ -1066,9 +1061,9 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
     // TODO: Avoid implicit trunc?
     // See https://github.com/llvm/llvm-project/issues/112510.
     bool is_signed = std::is_signed<decltype(v)>::value;
-    return Scalar(llvm::APSInt(llvm::APInt(8 * opcodes.GetAddressByteSize(), v,
-                                           is_signed, /*implicitTrunc=*/true),
-                               !is_signed));
+    return Scalar(llvm::APSInt(
+        llvm::APInt(8 * address_size, v, is_signed, /*implicitTrunc=*/true),
+        !is_signed));
   };
 
   // The default kind is a memory location. This is updated by any
@@ -1076,10 +1071,10 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
   // by composition operations like DW_OP_piece.
   LocationDescriptionKind dwarf4_location_description_kind = Memory;
 
-  while (opcodes.ValidOffset(offset)) {
-    const lldb::offset_t op_offset = offset;
-    const LocationAtom opcode =
-        static_cast<LocationAtom>(opcodes.GetU8(&offset));
+  llvm::DWARFExpression::iterator op = expr.begin(), op_end = expr.end();
+  while (op != op_end) {
+    const uint64_t op_offset = op.getOffset();
+    const LocationAtom opcode = static_cast<LocationAtom>(op->getCode());
 
     if (log && log->GetVerbose()) {
       size_t count = stack.size();
@@ -1106,7 +1101,7 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
     // The DW_OP_addr operation has a single operand that encodes a machine
     // address and whose size is the size of an address on the target machine.
     case DW_OP_addr:
-      stack.push_back(Scalar(opcodes.GetAddress(&offset)));
+      stack.push_back(Scalar(op->getRawOperand(0)));
       if (target &&
           target->GetArchitecture().GetCore() == ArchSpec::eCore_wasm32) {
         // wasm file sections aren't mapped into memory, therefore addresses can
@@ -1161,7 +1156,7 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
     // retrieved from the dereferenced address is the size of an address on the
     // target machine.
     case DW_OP_deref: {
-      size_t size = opcodes.GetAddressByteSize();
+      size_t size = address_size;
       if (llvm::Error err = Evaluate_DW_OP_deref_size(
               stack, exe_ctx, module_sp, process, target, size, size,
               dwarf4_location_description_kind))
@@ -1181,10 +1176,10 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
     // the size of an address on the target machine before being pushed on the
     // expression stack.
     case DW_OP_deref_size: {
-      size_t size = opcodes.GetU8(&offset);
+      size_t size = op->getRawOperand(0);
       if (llvm::Error err = Evaluate_DW_OP_deref_size(
-              stack, exe_ctx, module_sp, process, target, size,
-              opcodes.GetAddressByteSize(), dwarf4_location_description_kind))
+              stack, exe_ctx, module_sp, process, target, size, address_size,
+              dwarf4_location_description_kind))
         return err;
     } break;
 
@@ -1232,36 +1227,36 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
     // DW_OP_constu     unsigned LEB128 integer constant
     // DW_OP_consts     signed LEB128 integer constant
     case DW_OP_const1u:
-      stack.push_back(to_generic(opcodes.GetU8(&offset)));
+      stack.push_back(to_generic(op->getRawOperand(0)));
       break;
     case DW_OP_const1s:
-      stack.push_back(to_generic((int8_t)opcodes.GetU8(&offset)));
+      stack.push_back(to_generic((int8_t)op->getRawOperand(0)));
       break;
     case DW_OP_const2u:
-      stack.push_back(to_generic(opcodes.GetU16(&offset)));
+      stack.push_back(to_generic(op->getRawOperand(0)));
       break;
     case DW_OP_const2s:
-      stack.push_back(to_generic((int16_t)opcodes.GetU16(&offset)));
+      stack.push_back(to_generic((int16_t)op->getRawOperand(0)));
       break;
     case DW_OP_const4u:
-      stack.push_back(to_generic(opcodes.GetU32(&offset)));
+      stack.push_back(to_generic(op->getRawOperand(0)));
       break;
     case DW_OP_const4s:
-      stack.push_back(to_generic((int32_t)opcodes.GetU32(&offset)));
+      stack.push_back(to_generic((int32_t)op->getRawOperand(0)));
       break;
     case DW_OP_const8u:
-      stack.push_back(to_generic(opcodes.GetU64(&offset)));
+      stack.push_back(to_generic(op->getRawOperand(0)));
       break;
     case DW_OP_const8s:
-      stack.push_back(to_generic((int64_t)opcodes.GetU64(&offset)));
+      stack.push_back(to_generic((int64_t)op->getRawOperand(0)));
       break;
     // These should also use to_generic, but we can't do that due to a
     // producer-side bug in llvm. See llvm.org/pr48087.
     case DW_OP_constu:
-      stack.push_back(Scalar(opcodes.GetULEB128(&offset)));
+      stack.push_back(Scalar(op->getRawOperand(0)));
       break;
     case DW_OP_consts:
-      stack.push_back(Scalar(opcodes.GetSLEB128(&offset)));
+      stack.push_back(Scalar(op->getRawOperand(0)));
       break;
 
     // OPCODE: DW_OP_dup
@@ -1297,7 +1292,7 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
     // DESCRIPTION: The stack entry with the specified index (0 through 255,
     // inclusive) is pushed on the stack
     case DW_OP_pick: {
-      uint8_t pick_idx = opcodes.GetU8(&offset);
+      uint8_t pick_idx = op->getRawOperand(0);
       if (pick_idx < stack.size())
         stack.push_back(stack[stack.size() - 1 - pick_idx]);
       else {
@@ -1448,7 +1443,7 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
     // DESCRIPTION: pops the top stack entry, adds it to the unsigned LEB128
     // constant operand and pushes the result.
     case DW_OP_plus_uconst: {
-      const uint64_t uconst_value = opcodes.GetULEB128(&offset);
+      const uint64_t uconst_value = op->getRawOperand(0);
       // Implicit conversion from a UINT to a Scalar...
       stack.back().GetScalar() += uconst_value;
       if (!stack.back().GetScalar().IsValid())
@@ -1507,18 +1502,18 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
     // the DWARF expression to skip forward or backward from the current
     // operation, beginning after the 2-byte constant.
     case DW_OP_skip: {
-      int16_t skip_offset = (int16_t)opcodes.GetU16(&offset);
-      lldb::offset_t new_offset = offset + skip_offset;
+      int16_t skip_offset = (int16_t)op->getRawOperand(0);
+      lldb::offset_t new_offset = op->getEndOffset() + skip_offset;
       // New offset can point at the end of the data, in this case we should
       // terminate the DWARF expression evaluation (will happen in the loop
       // condition).
-      if (new_offset <= opcodes.GetByteSize())
-        offset = new_offset;
-      else {
-        return llvm::createStringErrorV(
-            "Invalid opcode offset in DW_OP_skip: {0}+({1}) > {2}", offset,
-            skip_offset, opcodes.GetByteSize());
+      if (new_offset <= expr_data.size()) {
+        op = op.skipBytes(skip_offset);
+        continue;
       }
+      return llvm::createStringErrorV(
+          "Invalid opcode offset in DW_OP_skip: {0}+({1}) > {2}",
+          op->getEndOffset(), skip_offset, expr_data.size());
     } break;
 
     // OPCODE: DW_OP_bra
@@ -1531,20 +1526,20 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
     case DW_OP_bra: {
       tmp = stack.back();
       stack.pop_back();
-      int16_t bra_offset = (int16_t)opcodes.GetU16(&offset);
+      int16_t bra_offset = (int16_t)op->getRawOperand(0);
       Scalar zero(0);
       if (tmp.GetScalar() != zero) {
-        lldb::offset_t new_offset = offset + bra_offset;
+        lldb::offset_t new_offset = op->getEndOffset() + bra_offset;
         // New offset can point at the end of the data, in this case we should
         // terminate the DWARF expression evaluation (will happen in the loop
         // condition).
-        if (new_offset <= opcodes.GetByteSize())
-          offset = new_offset;
-        else {
-          return llvm::createStringErrorV(
-              "Invalid opcode offset in DW_OP_bra: {0}+({1}) > {2}", offset,
-              bra_offset, opcodes.GetByteSize());
+        if (new_offset <= expr_data.size()) {
+          op = op.skipBytes(bra_offset);
+          continue;
         }
+        return llvm::createStringErrorV(
+            "Invalid opcode offset in DW_OP_bra: {0}+({1}) > {2}",
+            op->getEndOffset(), bra_offset, expr_data.size());
       }
     } break;
 
@@ -1715,7 +1710,7 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
     // DESCRIPTION: Push the value in register on the top of the stack.
     case DW_OP_regx: {
       dwarf4_location_description_kind = Register;
-      reg_num = opcodes.GetULEB128(&offset);
+      reg_num = op->getRawOperand(0);
       Status read_err;
       if (llvm::Error err =
               ReadRegisterValueAsScalar(reg_ctx, reg_kind, reg_num, tmp))
@@ -1765,7 +1760,7 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
               ReadRegisterValueAsScalar(reg_ctx, reg_kind, reg_num, tmp))
         return err;
 
-      int64_t breg_offset = opcodes.GetSLEB128(&offset);
+      int64_t breg_offset = op->getRawOperand(0);
       tmp.GetScalar() += (uint64_t)breg_offset;
       tmp.ClearContext();
       stack.push_back(tmp);
@@ -1778,12 +1773,12 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
     // DESCRIPTION: Value is in memory at the address specified by register
     // N plus an offset.
     case DW_OP_bregx: {
-      reg_num = opcodes.GetULEB128(&offset);
+      reg_num = op->getRawOperand(0);
       if (llvm::Error err =
               ReadRegisterValueAsScalar(reg_ctx, reg_kind, reg_num, tmp))
         return err;
 
-      int64_t breg_offset = opcodes.GetSLEB128(&offset);
+      int64_t breg_offset = op->getRawOperand(0);
       tmp.GetScalar() += (uint64_t)breg_offset;
       tmp.ClearContext();
       stack.push_back(tmp);
@@ -1796,7 +1791,7 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
           Scalar value;
           if (llvm::Error err = frame->GetFrameBaseValue(value))
             return err;
-          int64_t fbreg_offset = opcodes.GetSLEB128(&offset);
+          int64_t fbreg_offset = op->getRawOperand(0);
           value += fbreg_offset;
           stack.push_back(value);
           stack.back().SetValueType(Value::ValueType::LoadAddress);
@@ -1836,7 +1831,7 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
       // Reset for the next piece.
       dwarf4_location_description_kind = Memory;
 
-      const uint64_t piece_byte_size = opcodes.GetULEB128(&offset);
+      const uint64_t piece_byte_size = op->getRawOperand(0);
 
       if (piece_byte_size > 0) {
         Value curr_piece;
@@ -1973,8 +1968,8 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
             log, dwarf_cu, dwarf4_location_description_kind, &stack.back());
         // Reset for the next piece.
         dwarf4_location_description_kind = Memory;
-        const uint64_t piece_bit_size = opcodes.GetULEB128(&offset);
-        const uint64_t piece_bit_offset = opcodes.GetULEB128(&offset);
+        const uint64_t piece_bit_size = op->getRawOperand(0);
+        const uint64_t piece_bit_offset = op->getRawOperand(1);
         switch (stack.back().GetValueType()) {
         case Value::ValueType::Invalid:
           return llvm::createStringError(
@@ -2011,16 +2006,17 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
     case DW_OP_implicit_value: {
       dwarf4_location_description_kind = Implicit;
 
-      const uint32_t len = opcodes.GetULEB128(&offset);
-      const void *data = opcodes.GetData(&offset, len);
+      const uint64_t block_size = op->getRawOperand(0);
+      uint64_t block_offset = op->getRawOperand(1);
 
-      if (!data) {
-        LLDB_LOG(log, "Evaluate_DW_OP_implicit_value: could not be read data");
-        return llvm::createStringError("could not evaluate %s",
-                                       DW_OP_value_to_name(opcode));
-      }
+      llvm::Error error = llvm::Error::success();
+      llvm::StringRef block_data =
+          expr_data.getBytes(&block_offset, block_size, &error);
 
-      Value result(data, len);
+      if (error)
+        return error;
+
+      Value result(block_data.data(), block_data.size());
       stack.push_back(result);
       break;
     }
@@ -2108,7 +2104,7 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
     // DESCRIPTION: Pop the top stack element, convert it to a
     // different type, and push the result.
     case DW_OP_convert: {
-      const uint64_t relative_die_offset = opcodes.GetULEB128(&offset);
+      const uint64_t relative_die_offset = op->getRawOperand(0);
       uint64_t bit_size;
       bool sign;
       if (relative_die_offset == 0) {
@@ -2209,7 +2205,7 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
       if (!dwarf_cu)
         return llvm::createStringError("DW_OP_GNU_addr_index found without a "
                                        "compile unit being specified");
-      uint64_t index = opcodes.GetULEB128(&offset);
+      uint64_t index = op->getRawOperand(0);
       lldb::addr_t value = dwarf_cu->ReadAddressFromDebugAddrSection(index);
       stack.push_back(Scalar(value));
       if (target &&
@@ -2234,31 +2230,55 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
         return llvm::createStringError("DW_OP_GNU_const_index found without a "
                                        "compile unit being specified");
       }
-      uint64_t index = opcodes.GetULEB128(&offset);
+      uint64_t index = op->getRawOperand(0);
       lldb::addr_t value = dwarf_cu->ReadAddressFromDebugAddrSection(index);
       stack.push_back(Scalar(value));
     } break;
 
     case DW_OP_GNU_entry_value:
     case DW_OP_entry_value: {
+      const uint64_t block_size = op->getRawOperand(0);
+      uint64_t block_offset = op->getEndOffset();
+
+      llvm::Error error = llvm::Error::success();
+      llvm::ArrayRef<uint8_t> block_data = llvm::arrayRefFromStringRef(
+          expr_data.getBytes(&block_offset, block_size, &error));
+
+      if (error)
+        return error;
+
       if (llvm::Error err = Evaluate_DW_OP_entry_value(stack, exe_ctx, reg_ctx,
-                                                       opcodes, offset, log))
+                                                       block_data, log))
         return llvm::createStringError(
             "could not evaluate DW_OP_entry_value: %s",
             llvm::toString(std::move(err)).c_str());
-      break;
+
+      op = op.skipBytes(block_size);
+      continue;
     }
 
     default:
       if (dwarf_cu) {
+        const uint64_t operands_offset = op_offset + 1;
+        uint64_t offset = operands_offset; // Updated by the callee.
         if (dwarf_cu->ParseVendorDWARFOpcode(opcode, expr_data, offset, reg_ctx,
                                              reg_kind, stack)) {
-          break;
+          // 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
+          // opcode. In both cases `offset` will point to the next operation,
+          // but we can't use it directly because the only available mutating
+          // method of `iterator` (not counting `operator++`) is `skipBytes()`.
+          // So we calculate the offset and pass it to `skipBytes()`.
+          uint64_t offset_to_next_op = offset - op->getEndOffset();
+          op = op.skipBytes(offset_to_next_op);
+          continue;
         }
       }
       return llvm::createStringErrorV("unhandled opcode {0} in DWARFExpression",
                                       opcode);
     }
+    ++op;
   }
 
   if (stack.empty()) {
diff --git a/llvm/include/llvm/DebugInfo/DWARF/LowLevel/DWARFExpression.h b/llvm/include/llvm/DebugInfo/DWARF/LowLevel/DWARFExpression.h
index 458a3a4e49e8b..132c3b49daf63 100644
--- a/llvm/include/llvm/DebugInfo/DWARF/LowLevel/DWARFExpression.h
+++ b/llvm/include/llvm/DebugInfo/DWARF/LowLevel/DWARFExpression.h
@@ -124,6 +124,8 @@ class DWARFExpression {
     }
 
   public:
+    uint64_t getOffset() const { return Offset; }
+
     iterator &operator++() {
       Offset = Op.isError() ? Expr->Data.getData().size() : Op.EndOffset;
       Op.Error =



More information about the llvm-commits mailing list