[llvm] 96d01a3 - [lldb] Encode operands and arity in Dwarf.def and use them in LLDB. (#94679)

via llvm-commits llvm-commits at lists.llvm.org
Fri Jun 7 13:48:22 PDT 2024


Author: Jonas Devlieghere
Date: 2024-06-07T13:48:17-07:00
New Revision: 96d01a350ce9875a8f893ecdc1d470caf7ed5bcd

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

LOG: [lldb] Encode operands and arity in Dwarf.def and use them in LLDB. (#94679)

This PR extends Dwarf.def to include the number of operands and the arity (the
number of entries on the DWARF stack).

  - The arity is used in LLDB's DWARF expression evaluator.
  - The number of operands is unused, but is present in the table to avoid
    confusing the arity with the operands. Keeping the latter up to date should
    be straightforward as it maps directly to a table present in the DWARF
    standard.

Added: 
    

Modified: 
    lldb/source/Expression/DWARFExpression.cpp
    llvm/include/llvm/BinaryFormat/Dwarf.def
    llvm/include/llvm/BinaryFormat/Dwarf.h
    llvm/include/llvm/ObjectYAML/DWARFYAML.h
    llvm/lib/BinaryFormat/Dwarf.cpp

Removed: 
    


################################################################################
diff  --git a/lldb/source/Expression/DWARFExpression.cpp b/lldb/source/Expression/DWARFExpression.cpp
index 05767a8d02ff2..444e44b392891 100644
--- a/lldb/source/Expression/DWARFExpression.cpp
+++ b/lldb/source/Expression/DWARFExpression.cpp
@@ -888,6 +888,14 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
                 DW_OP_value_to_name(op));
     }
 
+    if (std::optional<unsigned> arity =
+            llvm::dwarf::OperationArity(static_cast<LocationAtom>(op))) {
+      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());
+    }
+
     switch (op) {
     // 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.
@@ -1253,11 +1261,7 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
     // DESCRIPTION: Duplicates the entry currently second in the stack at
     // the top of the stack.
     case DW_OP_over:
-      if (stack.size() < 2) {
-        return llvm::createStringError(
-            "expression stack needs at least 2 items for DW_OP_over");
-      } else
-        stack.push_back(stack[stack.size() - 2]);
+      stack.push_back(stack[stack.size() - 2]);
       break;
 
     // OPCODE: DW_OP_pick
@@ -1280,14 +1284,9 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
     // of the stack becomes the second stack entry, and the second entry
     // becomes the top of the stack
     case DW_OP_swap:
-      if (stack.size() < 2) {
-        return llvm::createStringError(
-            "expression stack needs at least 2 items for DW_OP_swap");
-      } else {
-        tmp = stack.back();
-        stack.back() = stack[stack.size() - 2];
-        stack[stack.size() - 2] = tmp;
-      }
+      tmp = stack.back();
+      stack.back() = stack[stack.size() - 2];
+      stack[stack.size() - 2] = tmp;
       break;
 
     // OPCODE: DW_OP_rot
@@ -1296,18 +1295,13 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
     // the top of the stack becomes the third stack entry, the second entry
     // becomes the top of the stack, and the third entry becomes the second
     // entry.
-    case DW_OP_rot:
-      if (stack.size() < 3) {
-        return llvm::createStringError(
-            "expression stack needs at least 3 items for DW_OP_rot");
-      } else {
-        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: {
+      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;
 
     // OPCODE: DW_OP_abs
     // OPERANDS: none
@@ -1315,10 +1309,7 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
     // value and pushes its absolute value. If the absolute value can not be
     // represented, the result is undefined.
     case DW_OP_abs:
-      if (stack.empty()) {
-        return llvm::createStringError(
-            "expression stack needs at least 1 item for DW_OP_abs");
-      } else if (!stack.back().ResolveValue(exe_ctx).AbsoluteValue()) {
+      if (!stack.back().ResolveValue(exe_ctx).AbsoluteValue()) {
         return llvm::createStringError(
             "failed to take the absolute value of the first stack item");
       }
@@ -1329,15 +1320,10 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
     // DESCRIPTION: pops the top two stack values, performs a bitwise and
     // operation on the two, and pushes the result.
     case DW_OP_and:
-      if (stack.size() < 2) {
-        return llvm::createStringError(
-            "expression stack needs at least 2 items for DW_OP_and");
-      } else {
-        tmp = stack.back();
-        stack.pop_back();
-        stack.back().ResolveValue(exe_ctx) =
-            stack.back().ResolveValue(exe_ctx) & tmp.ResolveValue(exe_ctx);
-      }
+      tmp = stack.back();
+      stack.pop_back();
+      stack.back().ResolveValue(exe_ctx) =
+          stack.back().ResolveValue(exe_ctx) & tmp.ResolveValue(exe_ctx);
       break;
 
     // OPCODE: DW_OP_div
@@ -1345,42 +1331,32 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
     // DESCRIPTION: pops the top two stack values, divides the former second
     // entry by the former top of the stack using signed division, and pushes
     // the result.
-    case DW_OP_div:
-      if (stack.size() < 2) {
-        return llvm::createStringError(
-            "expression stack needs at least 2 items for DW_OP_div");
-      } else {
-        tmp = stack.back();
-        if (tmp.ResolveValue(exe_ctx).IsZero())
-          return llvm::createStringError("divide by zero");
-
-        stack.pop_back();
-        Scalar divisor, dividend;
-        divisor = tmp.ResolveValue(exe_ctx);
-        dividend = stack.back().ResolveValue(exe_ctx);
-        divisor.MakeSigned();
-        dividend.MakeSigned();
-        stack.back() = dividend / divisor;
-
-        if (!stack.back().ResolveValue(exe_ctx).IsValid())
-          return llvm::createStringError("divide failed");
-      }
-      break;
+    case DW_OP_div: {
+      tmp = stack.back();
+      if (tmp.ResolveValue(exe_ctx).IsZero())
+        return llvm::createStringError("divide by zero");
+
+      stack.pop_back();
+      Scalar divisor, dividend;
+      divisor = tmp.ResolveValue(exe_ctx);
+      dividend = stack.back().ResolveValue(exe_ctx);
+      divisor.MakeSigned();
+      dividend.MakeSigned();
+      stack.back() = dividend / divisor;
+
+      if (!stack.back().ResolveValue(exe_ctx).IsValid())
+        return llvm::createStringError("divide failed");
+    } break;
 
     // OPCODE: DW_OP_minus
     // OPERANDS: none
     // DESCRIPTION: pops the top two stack values, subtracts the former top
     // of the stack from the former second entry, and pushes the result.
     case DW_OP_minus:
-      if (stack.size() < 2) {
-        return llvm::createStringError(
-            "expression stack needs at least 2 items for DW_OP_minus");
-      } else {
-        tmp = stack.back();
-        stack.pop_back();
-        stack.back().ResolveValue(exe_ctx) =
-            stack.back().ResolveValue(exe_ctx) - tmp.ResolveValue(exe_ctx);
-      }
+      tmp = stack.back();
+      stack.pop_back();
+      stack.back().ResolveValue(exe_ctx) =
+          stack.back().ResolveValue(exe_ctx) - tmp.ResolveValue(exe_ctx);
       break;
 
     // OPCODE: DW_OP_mod
@@ -1389,15 +1365,10 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
     // the calculation: former second stack entry modulo the former top of the
     // stack.
     case DW_OP_mod:
-      if (stack.size() < 2) {
-        return llvm::createStringError(
-            "expression stack needs at least 2 items for DW_OP_mod");
-      } else {
-        tmp = stack.back();
-        stack.pop_back();
-        stack.back().ResolveValue(exe_ctx) =
-            stack.back().ResolveValue(exe_ctx) % tmp.ResolveValue(exe_ctx);
-      }
+      tmp = stack.back();
+      stack.pop_back();
+      stack.back().ResolveValue(exe_ctx) =
+          stack.back().ResolveValue(exe_ctx) % tmp.ResolveValue(exe_ctx);
       break;
 
     // OPCODE: DW_OP_mul
@@ -1405,28 +1376,18 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
     // DESCRIPTION: pops the top two stack entries, multiplies them
     // together, and pushes the result.
     case DW_OP_mul:
-      if (stack.size() < 2) {
-        return llvm::createStringError(
-            "expression stack needs at least 2 items for DW_OP_mul");
-      } else {
-        tmp = stack.back();
-        stack.pop_back();
-        stack.back().ResolveValue(exe_ctx) =
-            stack.back().ResolveValue(exe_ctx) * tmp.ResolveValue(exe_ctx);
-      }
+      tmp = stack.back();
+      stack.pop_back();
+      stack.back().ResolveValue(exe_ctx) =
+          stack.back().ResolveValue(exe_ctx) * tmp.ResolveValue(exe_ctx);
       break;
 
     // OPCODE: DW_OP_neg
     // OPERANDS: none
     // DESCRIPTION: pops the top stack entry, and pushes its negation.
     case DW_OP_neg:
-      if (stack.empty()) {
-        return llvm::createStringError(
-            "expression stack needs at least 1 item for DW_OP_neg");
-      } else {
-        if (!stack.back().ResolveValue(exe_ctx).UnaryNegate())
-          return llvm::createStringError("unary negate failed");
-      }
+      if (!stack.back().ResolveValue(exe_ctx).UnaryNegate())
+        return llvm::createStringError("unary negate failed");
       break;
 
     // OPCODE: DW_OP_not
@@ -1434,14 +1395,8 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
     // DESCRIPTION: pops the top stack entry, and pushes its bitwise
     // complement
     case DW_OP_not:
-      if (stack.empty()) {
-        return llvm::createStringError(
-            "expression stack needs at least 1 item for DW_OP_not");
-      } else {
-        if (!stack.back().ResolveValue(exe_ctx).OnesComplement()) {
-          return llvm::createStringError("logical NOT failed");
-        }
-      }
+      if (!stack.back().ResolveValue(exe_ctx).OnesComplement())
+        return llvm::createStringError("logical NOT failed");
       break;
 
     // OPCODE: DW_OP_or
@@ -1449,15 +1404,10 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
     // DESCRIPTION: pops the top two stack entries, performs a bitwise or
     // operation on the two, and pushes the result.
     case DW_OP_or:
-      if (stack.size() < 2) {
-        return llvm::createStringError(
-            "expression stack needs at least 2 items for DW_OP_or");
-      } else {
-        tmp = stack.back();
-        stack.pop_back();
-        stack.back().ResolveValue(exe_ctx) =
-            stack.back().ResolveValue(exe_ctx) | tmp.ResolveValue(exe_ctx);
-      }
+      tmp = stack.back();
+      stack.pop_back();
+      stack.back().ResolveValue(exe_ctx) =
+          stack.back().ResolveValue(exe_ctx) | tmp.ResolveValue(exe_ctx);
       break;
 
     // OPCODE: DW_OP_plus
@@ -1465,32 +1415,22 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
     // DESCRIPTION: pops the top two stack entries, adds them together, and
     // pushes the result.
     case DW_OP_plus:
-      if (stack.size() < 2) {
-        return llvm::createStringError(
-            "expression stack needs at least 2 items for DW_OP_plus");
-      } else {
-        tmp = stack.back();
-        stack.pop_back();
-        stack.back().GetScalar() += tmp.GetScalar();
-      }
+      tmp = stack.back();
+      stack.pop_back();
+      stack.back().GetScalar() += tmp.GetScalar();
       break;
 
     // OPCODE: DW_OP_plus_uconst
     // OPERANDS: none
     // DESCRIPTION: pops the top stack entry, adds it to the unsigned LEB128
     // constant operand and pushes the result.
-    case DW_OP_plus_uconst:
-      if (stack.empty()) {
-        return llvm::createStringError(
-            "expression stack needs at least 1 item for DW_OP_plus_uconst");
-      } else {
-        const uint64_t uconst_value = opcodes.GetULEB128(&offset);
-        // Implicit conversion from a UINT to a Scalar...
-        stack.back().GetScalar() += uconst_value;
-        if (!stack.back().GetScalar().IsValid())
-          return llvm::createStringError("DW_OP_plus_uconst failed");
-      }
-      break;
+    case DW_OP_plus_uconst: {
+      const uint64_t uconst_value = opcodes.GetULEB128(&offset);
+      // Implicit conversion from a UINT to a Scalar...
+      stack.back().GetScalar() += uconst_value;
+      if (!stack.back().GetScalar().IsValid())
+        return llvm::createStringError("DW_OP_plus_uconst failed");
+    } break;
 
     // OPCODE: DW_OP_shl
     // OPERANDS: none
@@ -1498,14 +1438,9 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
     // second entry left by the number of bits specified by the former top of
     // the stack, and pushes the result.
     case DW_OP_shl:
-      if (stack.size() < 2) {
-        return llvm::createStringError(
-            "expression stack needs at least 2 items for DW_OP_shl");
-      } else {
-        tmp = stack.back();
-        stack.pop_back();
-        stack.back().ResolveValue(exe_ctx) <<= tmp.ResolveValue(exe_ctx);
-      }
+      tmp = stack.back();
+      stack.pop_back();
+      stack.back().ResolveValue(exe_ctx) <<= tmp.ResolveValue(exe_ctx);
       break;
 
     // OPCODE: DW_OP_shr
@@ -1514,17 +1449,11 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
     // entry right logically (filling with zero bits) by the number of bits
     // specified by the former top of the stack, and pushes the result.
     case DW_OP_shr:
-      if (stack.size() < 2) {
-        return llvm::createStringError(
-            "expression stack needs at least 2 items for DW_OP_shr");
-      } else {
-        tmp = stack.back();
-        stack.pop_back();
-        if (!stack.back().ResolveValue(exe_ctx).ShiftRightLogical(
-                tmp.ResolveValue(exe_ctx))) {
-          return llvm::createStringError("DW_OP_shr failed");
-        }
-      }
+      tmp = stack.back();
+      stack.pop_back();
+      if (!stack.back().ResolveValue(exe_ctx).ShiftRightLogical(
+              tmp.ResolveValue(exe_ctx)))
+        return llvm::createStringError("DW_OP_shr failed");
       break;
 
     // OPCODE: DW_OP_shra
@@ -1534,14 +1463,9 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
     // sign for the result) by the number of bits specified by the former top
     // of the stack, and pushes the result.
     case DW_OP_shra:
-      if (stack.size() < 2) {
-        return llvm::createStringError(
-            "expression stack needs at least 2 items for DW_OP_shra");
-      } else {
-        tmp = stack.back();
-        stack.pop_back();
-        stack.back().ResolveValue(exe_ctx) >>= tmp.ResolveValue(exe_ctx);
-      }
+      tmp = stack.back();
+      stack.pop_back();
+      stack.back().ResolveValue(exe_ctx) >>= tmp.ResolveValue(exe_ctx);
       break;
 
     // OPCODE: DW_OP_xor
@@ -1549,15 +1473,10 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
     // DESCRIPTION: pops the top two stack entries, performs the bitwise
     // exclusive-or operation on the two, and pushes the result.
     case DW_OP_xor:
-      if (stack.size() < 2) {
-        return llvm::createStringError(
-            "expression stack needs at least 2 items for DW_OP_xor");
-      } else {
-        tmp = stack.back();
-        stack.pop_back();
-        stack.back().ResolveValue(exe_ctx) =
-            stack.back().ResolveValue(exe_ctx) ^ tmp.ResolveValue(exe_ctx);
-      }
+      tmp = stack.back();
+      stack.pop_back();
+      stack.back().ResolveValue(exe_ctx) =
+          stack.back().ResolveValue(exe_ctx) ^ tmp.ResolveValue(exe_ctx);
       break;
 
     // OPCODE: DW_OP_skip
@@ -1588,30 +1507,25 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
     // value popped is not the constant 0, the 2-byte constant operand is the
     // number of bytes of the DWARF expression to skip forward or backward from
     // the current operation, beginning after the 2-byte constant.
-    case DW_OP_bra:
-      if (stack.empty()) {
-        return llvm::createStringError(
-            "expression stack needs at least 1 item for DW_OP_bra");
-      } else {
-        tmp = stack.back();
-        stack.pop_back();
-        int16_t bra_offset = (int16_t)opcodes.GetU16(&offset);
-        Scalar zero(0);
-        if (tmp.ResolveValue(exe_ctx) != zero) {
-          lldb::offset_t new_offset = offset + 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::createStringError(llvm::formatv(
-                "Invalid opcode offset in DW_OP_bra: {0}+({1}) > {2}", offset,
-                bra_offset, opcodes.GetByteSize()));
-          }
+    case DW_OP_bra: {
+      tmp = stack.back();
+      stack.pop_back();
+      int16_t bra_offset = (int16_t)opcodes.GetU16(&offset);
+      Scalar zero(0);
+      if (tmp.ResolveValue(exe_ctx) != zero) {
+        lldb::offset_t new_offset = offset + 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::createStringError(llvm::formatv(
+              "Invalid opcode offset in DW_OP_bra: {0}+({1}) > {2}", offset,
+              bra_offset, opcodes.GetByteSize()));
         }
       }
-      break;
+    } break;
 
     // OPCODE: DW_OP_eq
     // OPERANDS: none
@@ -1621,15 +1535,10 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
     // of the operation is true or the constant value 0 if the result of the
     // operation is false.
     case DW_OP_eq:
-      if (stack.size() < 2) {
-        return llvm::createStringError(
-            "expression stack needs at least 2 items for DW_OP_eq");
-      } else {
-        tmp = stack.back();
-        stack.pop_back();
-        stack.back().ResolveValue(exe_ctx) =
-            stack.back().ResolveValue(exe_ctx) == tmp.ResolveValue(exe_ctx);
-      }
+      tmp = stack.back();
+      stack.pop_back();
+      stack.back().ResolveValue(exe_ctx) =
+          stack.back().ResolveValue(exe_ctx) == tmp.ResolveValue(exe_ctx);
       break;
 
     // OPCODE: DW_OP_ge
@@ -1640,15 +1549,10 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
     // of the operation is true or the constant value 0 if the result of the
     // operation is false.
     case DW_OP_ge:
-      if (stack.size() < 2) {
-        return llvm::createStringError(
-            "expression stack needs at least 2 items for DW_OP_ge");
-      } else {
-        tmp = stack.back();
-        stack.pop_back();
-        stack.back().ResolveValue(exe_ctx) =
-            stack.back().ResolveValue(exe_ctx) >= tmp.ResolveValue(exe_ctx);
-      }
+      tmp = stack.back();
+      stack.pop_back();
+      stack.back().ResolveValue(exe_ctx) =
+          stack.back().ResolveValue(exe_ctx) >= tmp.ResolveValue(exe_ctx);
       break;
 
     // OPCODE: DW_OP_gt
@@ -1659,15 +1563,10 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
     // of the operation is true or the constant value 0 if the result of the
     // operation is false.
     case DW_OP_gt:
-      if (stack.size() < 2) {
-        return llvm::createStringError(
-            "expression stack needs at least 2 items for DW_OP_gt");
-      } else {
-        tmp = stack.back();
-        stack.pop_back();
-        stack.back().ResolveValue(exe_ctx) =
-            stack.back().ResolveValue(exe_ctx) > tmp.ResolveValue(exe_ctx);
-      }
+      tmp = stack.back();
+      stack.pop_back();
+      stack.back().ResolveValue(exe_ctx) =
+          stack.back().ResolveValue(exe_ctx) > tmp.ResolveValue(exe_ctx);
       break;
 
     // OPCODE: DW_OP_le
@@ -1678,15 +1577,10 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
     // of the operation is true or the constant value 0 if the result of the
     // operation is false.
     case DW_OP_le:
-      if (stack.size() < 2) {
-        return llvm::createStringError(
-            "expression stack needs at least 2 items for DW_OP_le");
-      } else {
-        tmp = stack.back();
-        stack.pop_back();
-        stack.back().ResolveValue(exe_ctx) =
-            stack.back().ResolveValue(exe_ctx) <= tmp.ResolveValue(exe_ctx);
-      }
+      tmp = stack.back();
+      stack.pop_back();
+      stack.back().ResolveValue(exe_ctx) =
+          stack.back().ResolveValue(exe_ctx) <= tmp.ResolveValue(exe_ctx);
       break;
 
     // OPCODE: DW_OP_lt
@@ -1697,15 +1591,10 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
     // of the operation is true or the constant value 0 if the result of the
     // operation is false.
     case DW_OP_lt:
-      if (stack.size() < 2) {
-        return llvm::createStringError(
-            "expression stack needs at least 2 items for DW_OP_lt");
-      } else {
-        tmp = stack.back();
-        stack.pop_back();
-        stack.back().ResolveValue(exe_ctx) =
-            stack.back().ResolveValue(exe_ctx) < tmp.ResolveValue(exe_ctx);
-      }
+      tmp = stack.back();
+      stack.pop_back();
+      stack.back().ResolveValue(exe_ctx) =
+          stack.back().ResolveValue(exe_ctx) < tmp.ResolveValue(exe_ctx);
       break;
 
     // OPCODE: DW_OP_ne
@@ -1716,15 +1605,10 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
     // of the operation is true or the constant value 0 if the result of the
     // operation is false.
     case DW_OP_ne:
-      if (stack.size() < 2) {
-        return llvm::createStringError(
-            "expression stack needs at least 2 items for DW_OP_ne");
-      } else {
-        tmp = stack.back();
-        stack.pop_back();
-        stack.back().ResolveValue(exe_ctx) =
-            stack.back().ResolveValue(exe_ctx) != tmp.ResolveValue(exe_ctx);
-      }
+      tmp = stack.back();
+      stack.pop_back();
+      stack.back().ResolveValue(exe_ctx) =
+          stack.back().ResolveValue(exe_ctx) != tmp.ResolveValue(exe_ctx);
       break;
 
     // OPCODE: DW_OP_litn
@@ -2189,9 +2073,6 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
     // value to be used.  This is the actual object value and not the location.
     case DW_OP_stack_value:
       dwarf4_location_description_kind = Implicit;
-      if (stack.empty())
-        return llvm::createStringError(
-            "expression stack needs at least 1 item for DW_OP_stack_value");
       stack.back().SetValueType(Value::ValueType::Scalar);
       break;
 
@@ -2203,10 +2084,6 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
     // DESCRIPTION: Pop the top stack element, convert it to a
     // 
diff erent type, and push the result.
     case DW_OP_convert: {
-      if (stack.size() < 1) {
-        return llvm::createStringError(
-            "expression stack needs at least 1 item for DW_OP_convert");
-      }
       const uint64_t die_offset = opcodes.GetULEB128(&offset);
       uint64_t bit_size;
       bool sign;

diff  --git a/llvm/include/llvm/BinaryFormat/Dwarf.def b/llvm/include/llvm/BinaryFormat/Dwarf.def
index adcf24eb83b03..d55947fc5103a 100644
--- a/llvm/include/llvm/BinaryFormat/Dwarf.def
+++ b/llvm/include/llvm/BinaryFormat/Dwarf.def
@@ -51,7 +51,7 @@
 #endif
 
 #ifndef HANDLE_DW_OP
-#define HANDLE_DW_OP(ID, NAME, VERSION, VENDOR)
+#define HANDLE_DW_OP(ID, NAME, OPERANDS, ARITY, VERSION, VENDOR)
 #endif
 
 #ifndef HANDLE_DW_OP_LLVM_USEROP
@@ -694,197 +694,197 @@ HANDLE_DW_FORM(0x1f21, GNU_strp_alt, 0, GNU)
 HANDLE_DW_FORM(0x2001, LLVM_addrx_offset, 0, LLVM)
 
 // DWARF Expression operators.
-HANDLE_DW_OP(0x03, addr, 2, DWARF)
-HANDLE_DW_OP(0x06, deref, 2, DWARF)
-HANDLE_DW_OP(0x08, const1u, 2, DWARF)
-HANDLE_DW_OP(0x09, const1s, 2, DWARF)
-HANDLE_DW_OP(0x0a, const2u, 2, DWARF)
-HANDLE_DW_OP(0x0b, const2s, 2, DWARF)
-HANDLE_DW_OP(0x0c, const4u, 2, DWARF)
-HANDLE_DW_OP(0x0d, const4s, 2, DWARF)
-HANDLE_DW_OP(0x0e, const8u, 2, DWARF)
-HANDLE_DW_OP(0x0f, const8s, 2, DWARF)
-HANDLE_DW_OP(0x10, constu, 2, DWARF)
-HANDLE_DW_OP(0x11, consts, 2, DWARF)
-HANDLE_DW_OP(0x12, dup, 2, DWARF)
-HANDLE_DW_OP(0x13, drop, 2, DWARF)
-HANDLE_DW_OP(0x14, over, 2, DWARF)
-HANDLE_DW_OP(0x15, pick, 2, DWARF)
-HANDLE_DW_OP(0x16, swap, 2, DWARF)
-HANDLE_DW_OP(0x17, rot, 2, DWARF)
-HANDLE_DW_OP(0x18, xderef, 2, DWARF)
-HANDLE_DW_OP(0x19, abs, 2, DWARF)
-HANDLE_DW_OP(0x1a, and, 2, DWARF)
-HANDLE_DW_OP(0x1b, div, 2, DWARF)
-HANDLE_DW_OP(0x1c, minus, 2, DWARF)
-HANDLE_DW_OP(0x1d, mod, 2, DWARF)
-HANDLE_DW_OP(0x1e, mul, 2, DWARF)
-HANDLE_DW_OP(0x1f, neg, 2, DWARF)
-HANDLE_DW_OP(0x20, not, 2, DWARF)
-HANDLE_DW_OP(0x21, or, 2, DWARF)
-HANDLE_DW_OP(0x22, plus, 2, DWARF)
-HANDLE_DW_OP(0x23, plus_uconst, 2, DWARF)
-HANDLE_DW_OP(0x24, shl, 2, DWARF)
-HANDLE_DW_OP(0x25, shr, 2, DWARF)
-HANDLE_DW_OP(0x26, shra, 2, DWARF)
-HANDLE_DW_OP(0x27, xor, 2, DWARF)
-HANDLE_DW_OP(0x28, bra, 2, DWARF)
-HANDLE_DW_OP(0x29, eq, 2, DWARF)
-HANDLE_DW_OP(0x2a, ge, 2, DWARF)
-HANDLE_DW_OP(0x2b, gt, 2, DWARF)
-HANDLE_DW_OP(0x2c, le, 2, DWARF)
-HANDLE_DW_OP(0x2d, lt, 2, DWARF)
-HANDLE_DW_OP(0x2e, ne, 2, DWARF)
-HANDLE_DW_OP(0x2f, skip, 2, DWARF)
-HANDLE_DW_OP(0x30, lit0, 2, DWARF)
-HANDLE_DW_OP(0x31, lit1, 2, DWARF)
-HANDLE_DW_OP(0x32, lit2, 2, DWARF)
-HANDLE_DW_OP(0x33, lit3, 2, DWARF)
-HANDLE_DW_OP(0x34, lit4, 2, DWARF)
-HANDLE_DW_OP(0x35, lit5, 2, DWARF)
-HANDLE_DW_OP(0x36, lit6, 2, DWARF)
-HANDLE_DW_OP(0x37, lit7, 2, DWARF)
-HANDLE_DW_OP(0x38, lit8, 2, DWARF)
-HANDLE_DW_OP(0x39, lit9, 2, DWARF)
-HANDLE_DW_OP(0x3a, lit10, 2, DWARF)
-HANDLE_DW_OP(0x3b, lit11, 2, DWARF)
-HANDLE_DW_OP(0x3c, lit12, 2, DWARF)
-HANDLE_DW_OP(0x3d, lit13, 2, DWARF)
-HANDLE_DW_OP(0x3e, lit14, 2, DWARF)
-HANDLE_DW_OP(0x3f, lit15, 2, DWARF)
-HANDLE_DW_OP(0x40, lit16, 2, DWARF)
-HANDLE_DW_OP(0x41, lit17, 2, DWARF)
-HANDLE_DW_OP(0x42, lit18, 2, DWARF)
-HANDLE_DW_OP(0x43, lit19, 2, DWARF)
-HANDLE_DW_OP(0x44, lit20, 2, DWARF)
-HANDLE_DW_OP(0x45, lit21, 2, DWARF)
-HANDLE_DW_OP(0x46, lit22, 2, DWARF)
-HANDLE_DW_OP(0x47, lit23, 2, DWARF)
-HANDLE_DW_OP(0x48, lit24, 2, DWARF)
-HANDLE_DW_OP(0x49, lit25, 2, DWARF)
-HANDLE_DW_OP(0x4a, lit26, 2, DWARF)
-HANDLE_DW_OP(0x4b, lit27, 2, DWARF)
-HANDLE_DW_OP(0x4c, lit28, 2, DWARF)
-HANDLE_DW_OP(0x4d, lit29, 2, DWARF)
-HANDLE_DW_OP(0x4e, lit30, 2, DWARF)
-HANDLE_DW_OP(0x4f, lit31, 2, DWARF)
-HANDLE_DW_OP(0x50, reg0, 2, DWARF)
-HANDLE_DW_OP(0x51, reg1, 2, DWARF)
-HANDLE_DW_OP(0x52, reg2, 2, DWARF)
-HANDLE_DW_OP(0x53, reg3, 2, DWARF)
-HANDLE_DW_OP(0x54, reg4, 2, DWARF)
-HANDLE_DW_OP(0x55, reg5, 2, DWARF)
-HANDLE_DW_OP(0x56, reg6, 2, DWARF)
-HANDLE_DW_OP(0x57, reg7, 2, DWARF)
-HANDLE_DW_OP(0x58, reg8, 2, DWARF)
-HANDLE_DW_OP(0x59, reg9, 2, DWARF)
-HANDLE_DW_OP(0x5a, reg10, 2, DWARF)
-HANDLE_DW_OP(0x5b, reg11, 2, DWARF)
-HANDLE_DW_OP(0x5c, reg12, 2, DWARF)
-HANDLE_DW_OP(0x5d, reg13, 2, DWARF)
-HANDLE_DW_OP(0x5e, reg14, 2, DWARF)
-HANDLE_DW_OP(0x5f, reg15, 2, DWARF)
-HANDLE_DW_OP(0x60, reg16, 2, DWARF)
-HANDLE_DW_OP(0x61, reg17, 2, DWARF)
-HANDLE_DW_OP(0x62, reg18, 2, DWARF)
-HANDLE_DW_OP(0x63, reg19, 2, DWARF)
-HANDLE_DW_OP(0x64, reg20, 2, DWARF)
-HANDLE_DW_OP(0x65, reg21, 2, DWARF)
-HANDLE_DW_OP(0x66, reg22, 2, DWARF)
-HANDLE_DW_OP(0x67, reg23, 2, DWARF)
-HANDLE_DW_OP(0x68, reg24, 2, DWARF)
-HANDLE_DW_OP(0x69, reg25, 2, DWARF)
-HANDLE_DW_OP(0x6a, reg26, 2, DWARF)
-HANDLE_DW_OP(0x6b, reg27, 2, DWARF)
-HANDLE_DW_OP(0x6c, reg28, 2, DWARF)
-HANDLE_DW_OP(0x6d, reg29, 2, DWARF)
-HANDLE_DW_OP(0x6e, reg30, 2, DWARF)
-HANDLE_DW_OP(0x6f, reg31, 2, DWARF)
-HANDLE_DW_OP(0x70, breg0, 2, DWARF)
-HANDLE_DW_OP(0x71, breg1, 2, DWARF)
-HANDLE_DW_OP(0x72, breg2, 2, DWARF)
-HANDLE_DW_OP(0x73, breg3, 2, DWARF)
-HANDLE_DW_OP(0x74, breg4, 2, DWARF)
-HANDLE_DW_OP(0x75, breg5, 2, DWARF)
-HANDLE_DW_OP(0x76, breg6, 2, DWARF)
-HANDLE_DW_OP(0x77, breg7, 2, DWARF)
-HANDLE_DW_OP(0x78, breg8, 2, DWARF)
-HANDLE_DW_OP(0x79, breg9, 2, DWARF)
-HANDLE_DW_OP(0x7a, breg10, 2, DWARF)
-HANDLE_DW_OP(0x7b, breg11, 2, DWARF)
-HANDLE_DW_OP(0x7c, breg12, 2, DWARF)
-HANDLE_DW_OP(0x7d, breg13, 2, DWARF)
-HANDLE_DW_OP(0x7e, breg14, 2, DWARF)
-HANDLE_DW_OP(0x7f, breg15, 2, DWARF)
-HANDLE_DW_OP(0x80, breg16, 2, DWARF)
-HANDLE_DW_OP(0x81, breg17, 2, DWARF)
-HANDLE_DW_OP(0x82, breg18, 2, DWARF)
-HANDLE_DW_OP(0x83, breg19, 2, DWARF)
-HANDLE_DW_OP(0x84, breg20, 2, DWARF)
-HANDLE_DW_OP(0x85, breg21, 2, DWARF)
-HANDLE_DW_OP(0x86, breg22, 2, DWARF)
-HANDLE_DW_OP(0x87, breg23, 2, DWARF)
-HANDLE_DW_OP(0x88, breg24, 2, DWARF)
-HANDLE_DW_OP(0x89, breg25, 2, DWARF)
-HANDLE_DW_OP(0x8a, breg26, 2, DWARF)
-HANDLE_DW_OP(0x8b, breg27, 2, DWARF)
-HANDLE_DW_OP(0x8c, breg28, 2, DWARF)
-HANDLE_DW_OP(0x8d, breg29, 2, DWARF)
-HANDLE_DW_OP(0x8e, breg30, 2, DWARF)
-HANDLE_DW_OP(0x8f, breg31, 2, DWARF)
-HANDLE_DW_OP(0x90, regx, 2, DWARF)
-HANDLE_DW_OP(0x91, fbreg, 2, DWARF)
-HANDLE_DW_OP(0x92, bregx, 2, DWARF)
-HANDLE_DW_OP(0x93, piece, 2, DWARF)
-HANDLE_DW_OP(0x94, deref_size, 2, DWARF)
-HANDLE_DW_OP(0x95, xderef_size, 2, DWARF)
-HANDLE_DW_OP(0x96, nop, 2, DWARF)
+HANDLE_DW_OP(0x03, addr, 1, 0, 2, DWARF)
+HANDLE_DW_OP(0x06, deref, 0, 1, 2, DWARF)
+HANDLE_DW_OP(0x08, const1u, 1, 0, 2, DWARF)
+HANDLE_DW_OP(0x09, const1s, 1, 0, 2, DWARF)
+HANDLE_DW_OP(0x0a, const2u, 1, 0, 2, DWARF)
+HANDLE_DW_OP(0x0b, const2s, 1, 0, 2, DWARF)
+HANDLE_DW_OP(0x0c, const4u, 1, 0, 2, DWARF)
+HANDLE_DW_OP(0x0d, const4s, 1, 0, 2, DWARF)
+HANDLE_DW_OP(0x0e, const8u, 1, 0, 2, DWARF)
+HANDLE_DW_OP(0x0f, const8s, 1, 0, 2, DWARF)
+HANDLE_DW_OP(0x10, constu, 1, 0, 2, DWARF)
+HANDLE_DW_OP(0x11, consts, 1, 0, 2, DWARF)
+HANDLE_DW_OP(0x12, dup, 0, 1, 2, DWARF)
+HANDLE_DW_OP(0x13, drop, 0, 1, 2, DWARF)
+HANDLE_DW_OP(0x14, over, 0, 1, 2, DWARF)
+HANDLE_DW_OP(0x15, pick, 1, -1, 2, DWARF)
+HANDLE_DW_OP(0x16, swap, 0, 2, 2, DWARF)
+HANDLE_DW_OP(0x17, rot, 0, 3, 2, DWARF)
+HANDLE_DW_OP(0x18, xderef, 0, 2, 2, DWARF)
+HANDLE_DW_OP(0x19, abs, 0, 1, 2, DWARF)
+HANDLE_DW_OP(0x1a, and, 0, 2, 2, DWARF)
+HANDLE_DW_OP(0x1b, div, 0, 2, 2, DWARF)
+HANDLE_DW_OP(0x1c, minus, 0, 2, 2, DWARF)
+HANDLE_DW_OP(0x1d, mod, 0, 2, 2, DWARF)
+HANDLE_DW_OP(0x1e, mul, 0, 2, 2, DWARF)
+HANDLE_DW_OP(0x1f, neg, 0, 1, 2, DWARF)
+HANDLE_DW_OP(0x20, not, 0, 1, 2, DWARF)
+HANDLE_DW_OP(0x21, or, 0, 2, 2, DWARF)
+HANDLE_DW_OP(0x22, plus, 0, 2, 2, DWARF)
+HANDLE_DW_OP(0x23, plus_uconst, 1, 1, 2, DWARF)
+HANDLE_DW_OP(0x24, shl, 0, 2, 2, DWARF)
+HANDLE_DW_OP(0x25, shr, 0, 2, 2, DWARF)
+HANDLE_DW_OP(0x26, shra, 0, 2, 2, DWARF)
+HANDLE_DW_OP(0x27, xor, 0, 2, 2, DWARF)
+HANDLE_DW_OP(0x28, bra, 1, 0, 2, DWARF)
+HANDLE_DW_OP(0x29, eq, 0, 2, 2, DWARF)
+HANDLE_DW_OP(0x2a, ge, 0, 2, 2, DWARF)
+HANDLE_DW_OP(0x2b, gt, 0, 2, 2, DWARF)
+HANDLE_DW_OP(0x2c, le, 0, 2, 2, DWARF)
+HANDLE_DW_OP(0x2d, lt, 0, 2, 2, DWARF)
+HANDLE_DW_OP(0x2e, ne, 0, 2, 2, DWARF)
+HANDLE_DW_OP(0x2f, skip, 1, 0, 2, DWARF)
+HANDLE_DW_OP(0x30, lit0, 0, 0, 2, DWARF)
+HANDLE_DW_OP(0x31, lit1, 0, 0, 2, DWARF)
+HANDLE_DW_OP(0x32, lit2, 0, 0, 2, DWARF)
+HANDLE_DW_OP(0x33, lit3, 0, 0, 2, DWARF)
+HANDLE_DW_OP(0x34, lit4, 0, 0, 2, DWARF)
+HANDLE_DW_OP(0x35, lit5, 0, 0, 2, DWARF)
+HANDLE_DW_OP(0x36, lit6, 0, 0, 2, DWARF)
+HANDLE_DW_OP(0x37, lit7, 0, 0, 2, DWARF)
+HANDLE_DW_OP(0x38, lit8, 0, 0, 2, DWARF)
+HANDLE_DW_OP(0x39, lit9, 0, 0, 2, DWARF)
+HANDLE_DW_OP(0x3a, lit10, 0, 0, 2, DWARF)
+HANDLE_DW_OP(0x3b, lit11, 0, 0, 2, DWARF)
+HANDLE_DW_OP(0x3c, lit12, 0, 0, 2, DWARF)
+HANDLE_DW_OP(0x3d, lit13, 0, 0, 2, DWARF)
+HANDLE_DW_OP(0x3e, lit14, 0, 0, 2, DWARF)
+HANDLE_DW_OP(0x3f, lit15, 0, 0, 2, DWARF)
+HANDLE_DW_OP(0x40, lit16, 0, 0, 2, DWARF)
+HANDLE_DW_OP(0x41, lit17, 0, 0, 2, DWARF)
+HANDLE_DW_OP(0x42, lit18, 0, 0, 2, DWARF)
+HANDLE_DW_OP(0x43, lit19, 0, 0, 2, DWARF)
+HANDLE_DW_OP(0x44, lit20, 0, 0, 2, DWARF)
+HANDLE_DW_OP(0x45, lit21, 0, 0, 2, DWARF)
+HANDLE_DW_OP(0x46, lit22, 0, 0, 2, DWARF)
+HANDLE_DW_OP(0x47, lit23, 0, 0, 2, DWARF)
+HANDLE_DW_OP(0x48, lit24, 0, 0, 2, DWARF)
+HANDLE_DW_OP(0x49, lit25, 0, 0, 2, DWARF)
+HANDLE_DW_OP(0x4a, lit26, 0, 0, 2, DWARF)
+HANDLE_DW_OP(0x4b, lit27, 0, 0, 2, DWARF)
+HANDLE_DW_OP(0x4c, lit28, 0, 0, 2, DWARF)
+HANDLE_DW_OP(0x4d, lit29, 0, 0, 2, DWARF)
+HANDLE_DW_OP(0x4e, lit30, 0, 0, 2, DWARF)
+HANDLE_DW_OP(0x4f, lit31, 0, 0, 2, DWARF)
+HANDLE_DW_OP(0x50, reg0, 0, 0, 2, DWARF)
+HANDLE_DW_OP(0x51, reg1, 0, 0, 2, DWARF)
+HANDLE_DW_OP(0x52, reg2, 0, 0, 2, DWARF)
+HANDLE_DW_OP(0x53, reg3, 0, 0, 2, DWARF)
+HANDLE_DW_OP(0x54, reg4, 0, 0, 2, DWARF)
+HANDLE_DW_OP(0x55, reg5, 0, 0, 2, DWARF)
+HANDLE_DW_OP(0x56, reg6, 0, 0, 2, DWARF)
+HANDLE_DW_OP(0x57, reg7, 0, 0, 2, DWARF)
+HANDLE_DW_OP(0x58, reg8, 0, 0, 2, DWARF)
+HANDLE_DW_OP(0x59, reg9, 0, 0, 2, DWARF)
+HANDLE_DW_OP(0x5a, reg10, 0, 0, 2, DWARF)
+HANDLE_DW_OP(0x5b, reg11, 0, 0, 2, DWARF)
+HANDLE_DW_OP(0x5c, reg12, 0, 0, 2, DWARF)
+HANDLE_DW_OP(0x5d, reg13, 0, 0, 2, DWARF)
+HANDLE_DW_OP(0x5e, reg14, 0, 0, 2, DWARF)
+HANDLE_DW_OP(0x5f, reg15, 0, 0, 2, DWARF)
+HANDLE_DW_OP(0x60, reg16, 0, 0, 2, DWARF)
+HANDLE_DW_OP(0x61, reg17, 0, 0, 2, DWARF)
+HANDLE_DW_OP(0x62, reg18, 0, 0, 2, DWARF)
+HANDLE_DW_OP(0x63, reg19, 0, 0, 2, DWARF)
+HANDLE_DW_OP(0x64, reg20, 0, 0, 2, DWARF)
+HANDLE_DW_OP(0x65, reg21, 0, 0, 2, DWARF)
+HANDLE_DW_OP(0x66, reg22, 0, 0, 2, DWARF)
+HANDLE_DW_OP(0x67, reg23, 0, 0, 2, DWARF)
+HANDLE_DW_OP(0x68, reg24, 0, 0, 2, DWARF)
+HANDLE_DW_OP(0x69, reg25, 0, 0, 2, DWARF)
+HANDLE_DW_OP(0x6a, reg26, 0, 0, 2, DWARF)
+HANDLE_DW_OP(0x6b, reg27, 0, 0, 2, DWARF)
+HANDLE_DW_OP(0x6c, reg28, 0, 0, 2, DWARF)
+HANDLE_DW_OP(0x6d, reg29, 0, 0, 2, DWARF)
+HANDLE_DW_OP(0x6e, reg30, 0, 0, 2, DWARF)
+HANDLE_DW_OP(0x6f, reg31, 0, 0, 2, DWARF)
+HANDLE_DW_OP(0x70, breg0, 1, 0, 2, DWARF)
+HANDLE_DW_OP(0x71, breg1, 1, 0, 2, DWARF)
+HANDLE_DW_OP(0x72, breg2, 1, 0, 2, DWARF)
+HANDLE_DW_OP(0x73, breg3, 1, 0, 2, DWARF)
+HANDLE_DW_OP(0x74, breg4, 1, 0, 2, DWARF)
+HANDLE_DW_OP(0x75, breg5, 1, 0, 2, DWARF)
+HANDLE_DW_OP(0x76, breg6, 1, 0, 2, DWARF)
+HANDLE_DW_OP(0x77, breg7, 1, 0, 2, DWARF)
+HANDLE_DW_OP(0x78, breg8, 1, 0, 2, DWARF)
+HANDLE_DW_OP(0x79, breg9, 1, 0, 2, DWARF)
+HANDLE_DW_OP(0x7a, breg10, 1, 0, 2, DWARF)
+HANDLE_DW_OP(0x7b, breg11, 1, 0, 2, DWARF)
+HANDLE_DW_OP(0x7c, breg12, 1, 0, 2, DWARF)
+HANDLE_DW_OP(0x7d, breg13, 1, 0, 2, DWARF)
+HANDLE_DW_OP(0x7e, breg14, 1, 0, 2, DWARF)
+HANDLE_DW_OP(0x7f, breg15, 1, 0, 2, DWARF)
+HANDLE_DW_OP(0x80, breg16, 1, 0, 2, DWARF)
+HANDLE_DW_OP(0x81, breg17, 1, 0, 2, DWARF)
+HANDLE_DW_OP(0x82, breg18, 1, 0, 2, DWARF)
+HANDLE_DW_OP(0x83, breg19, 1, 0, 2, DWARF)
+HANDLE_DW_OP(0x84, breg20, 1, 0, 2, DWARF)
+HANDLE_DW_OP(0x85, breg21, 1, 0, 2, DWARF)
+HANDLE_DW_OP(0x86, breg22, 1, 0, 2, DWARF)
+HANDLE_DW_OP(0x87, breg23, 1, 0, 2, DWARF)
+HANDLE_DW_OP(0x88, breg24, 1, 0, 2, DWARF)
+HANDLE_DW_OP(0x89, breg25, 1, 0, 2, DWARF)
+HANDLE_DW_OP(0x8a, breg26, 1, 0, 2, DWARF)
+HANDLE_DW_OP(0x8b, breg27, 1, 0, 2, DWARF)
+HANDLE_DW_OP(0x8c, breg28, 1, 0, 2, DWARF)
+HANDLE_DW_OP(0x8d, breg29, 1, 0, 2, DWARF)
+HANDLE_DW_OP(0x8e, breg30, 1, 0, 2, DWARF)
+HANDLE_DW_OP(0x8f, breg31, 1, 0, 2, DWARF)
+HANDLE_DW_OP(0x90, regx, 1, 0, 2, DWARF)
+HANDLE_DW_OP(0x91, fbreg, 1, 0, 2, DWARF)
+HANDLE_DW_OP(0x92, bregx, 2, 0, 2, DWARF)
+HANDLE_DW_OP(0x93, piece, 1, 0, 2, DWARF)
+HANDLE_DW_OP(0x94, deref_size, 1, 1, 2, DWARF)
+HANDLE_DW_OP(0x95, xderef_size, 1, 1, 2, DWARF)
+HANDLE_DW_OP(0x96, nop, 0, 0, 2, DWARF)
 // New in DWARF v3:
-HANDLE_DW_OP(0x97, push_object_address, 3, DWARF)
-HANDLE_DW_OP(0x98, call2, 3, DWARF)
-HANDLE_DW_OP(0x99, call4, 3, DWARF)
-HANDLE_DW_OP(0x9a, call_ref, 3, DWARF)
-HANDLE_DW_OP(0x9b, form_tls_address, 3, DWARF)
-HANDLE_DW_OP(0x9c, call_frame_cfa, 3, DWARF)
-HANDLE_DW_OP(0x9d, bit_piece, 3, DWARF)
+HANDLE_DW_OP(0x97, push_object_address, 0, 0, 3, DWARF)
+HANDLE_DW_OP(0x98, call2, 1, 0, 3, DWARF)
+HANDLE_DW_OP(0x99, call4, 1, 0, 3, DWARF)
+HANDLE_DW_OP(0x9a, call_ref, 1, 1, 3, DWARF)
+HANDLE_DW_OP(0x9b, form_tls_address, 0, 1, 3, DWARF)
+HANDLE_DW_OP(0x9c, call_frame_cfa, 0, 0, 3, DWARF)
+HANDLE_DW_OP(0x9d, bit_piece, 2, 0, 3, DWARF)
 // New in DWARF v4:
-HANDLE_DW_OP(0x9e, implicit_value, 4, DWARF)
-HANDLE_DW_OP(0x9f, stack_value, 4, DWARF)
+HANDLE_DW_OP(0x9e, implicit_value, 2, 0, 4, DWARF)
+HANDLE_DW_OP(0x9f, stack_value, 0, 1, 4, DWARF)
 // New in DWARF v5:
-HANDLE_DW_OP(0xa0, implicit_pointer, 5, DWARF)
-HANDLE_DW_OP(0xa1, addrx, 5, DWARF)
-HANDLE_DW_OP(0xa2, constx, 5, DWARF)
-HANDLE_DW_OP(0xa3, entry_value, 5, DWARF)
-HANDLE_DW_OP(0xa4, const_type, 5, DWARF)
-HANDLE_DW_OP(0xa5, regval_type, 5, DWARF)
-HANDLE_DW_OP(0xa6, deref_type, 5, DWARF)
-HANDLE_DW_OP(0xa7, xderef_type, 5, DWARF)
-HANDLE_DW_OP(0xa8, convert, 5, DWARF)
-HANDLE_DW_OP(0xa9, reinterpret, 5, DWARF)
+HANDLE_DW_OP(0xa0, implicit_pointer, 2, 0, 5, DWARF)
+HANDLE_DW_OP(0xa1, addrx, 1, 0, 5, DWARF)
+HANDLE_DW_OP(0xa2, constx, 1, 0, 5, DWARF)
+HANDLE_DW_OP(0xa3, entry_value, 2, 0, 5, DWARF)
+HANDLE_DW_OP(0xa4, const_type, 3, 0, 5, DWARF)
+HANDLE_DW_OP(0xa5, regval_type, 2, 0, 5, DWARF)
+HANDLE_DW_OP(0xa6, deref_type, 2, 1, 5, DWARF)
+HANDLE_DW_OP(0xa7, xderef_type, 2, 2, 5, DWARF)
+HANDLE_DW_OP(0xa8, convert, 2, 1, 5, DWARF)
+HANDLE_DW_OP(0xa9, reinterpret, 1, 1, 5, DWARF)
 // Vendor extensions:
 // Extensions for GNU-style thread-local storage.
-HANDLE_DW_OP(0xe0, GNU_push_tls_address, 0, GNU)
+HANDLE_DW_OP(0xe0, GNU_push_tls_address, 0, 0, 0, GNU)
 // Conflicting:
-// HANDLE_DW_OP(0xe0, HP_unknown, 0, HP)
-HANDLE_DW_OP(0xe1, HP_is_value, 0, HP)
-HANDLE_DW_OP(0xe2, HP_fltconst4, 0, HP)
-HANDLE_DW_OP(0xe3, HP_fltconst8, 0, HP)
-HANDLE_DW_OP(0xe4, HP_mod_range, 0, HP)
-HANDLE_DW_OP(0xe5, HP_unmod_range, 0, HP)
-HANDLE_DW_OP(0xe6, HP_tls, 0, HP)
-HANDLE_DW_OP(0xe8, INTEL_bit_piece, 0, INTEL)
+// HANDLE_DW_OP(0xe0, HP_unknown, -1, -1, 0, HP)
+HANDLE_DW_OP(0xe1, HP_is_value, -1, -1, 0, HP)
+HANDLE_DW_OP(0xe2, HP_fltconst4, -1, -1, 0, HP)
+HANDLE_DW_OP(0xe3, HP_fltconst8, -1, -1, 0, HP)
+HANDLE_DW_OP(0xe4, HP_mod_range, -1, -1, 0, HP)
+HANDLE_DW_OP(0xe5, HP_unmod_range, -1, -1, 0, HP)
+HANDLE_DW_OP(0xe6, HP_tls, -1, -1, 0, HP)
+HANDLE_DW_OP(0xe8, INTEL_bit_piece, -1, -1, 0, INTEL)
 
 // Extensions for WebAssembly.
-HANDLE_DW_OP(0xed, WASM_location, 0, WASM)
-HANDLE_DW_OP(0xee, WASM_location_int, 0, WASM)
+HANDLE_DW_OP(0xed, WASM_location, -1, -1, 0, WASM)
+HANDLE_DW_OP(0xee, WASM_location_int, -1, -1, 0, WASM)
 // Historic and not implemented in LLVM.
-HANDLE_DW_OP(0xf0, APPLE_uninit, 0, APPLE)
+HANDLE_DW_OP(0xf0, APPLE_uninit, -1, -1, 0, APPLE)
 // The GNU entry value extension.
-HANDLE_DW_OP(0xf3, GNU_entry_value, 0, GNU)
-HANDLE_DW_OP(0xf8, PGI_omp_thread_num, 0, PGI)
+HANDLE_DW_OP(0xf3, GNU_entry_value, 2, 0, 0, GNU)
+HANDLE_DW_OP(0xf8, PGI_omp_thread_num, -1, -1, 0, PGI)
 // Extensions for Fission proposal.
-HANDLE_DW_OP(0xfb, GNU_addr_index, 0, GNU)
-HANDLE_DW_OP(0xfc, GNU_const_index, 0, GNU)
+HANDLE_DW_OP(0xfb, GNU_addr_index, 1, 0, 0, GNU)
+HANDLE_DW_OP(0xfc, GNU_const_index, 1, 0, 0, GNU)
 
 // DW_OP_LLVM_user has two operands:
 //   (1) An unsigned LEB128 "LLVM Vendor Extension Opcode".
@@ -893,7 +893,7 @@ HANDLE_DW_OP(0xfc, GNU_const_index, 0, GNU)
 // DW_OP_LLVM_user acts as an extension multiplexer, opening up the encoding
 // space to accommodate an infinite number of extensions. This better reflects
 // the de-facto permanent allocation of extensions.
-HANDLE_DW_OP(0xe9, LLVM_user, 0, LLVM)
+HANDLE_DW_OP(0xe9, LLVM_user, -1, -1, 0, LLVM)
 // "LLVM Vendor Extension" operations under the DW_OP_LLVM_user encoding
 // scheme. This list is authoritative and exhaustive. Once an operation is
 // registered here it cannot be removed nor have its encoding changed. The

diff  --git a/llvm/include/llvm/BinaryFormat/Dwarf.h b/llvm/include/llvm/BinaryFormat/Dwarf.h
index 607f3eb9d4c22..4657ad30eb1be 100644
--- a/llvm/include/llvm/BinaryFormat/Dwarf.h
+++ b/llvm/include/llvm/BinaryFormat/Dwarf.h
@@ -134,7 +134,8 @@ enum Form : uint16_t {
 };
 
 enum LocationAtom {
-#define HANDLE_DW_OP(ID, NAME, VERSION, VENDOR) DW_OP_##NAME = ID,
+#define HANDLE_DW_OP(ID, NAME, OPERANDS, ARITY, VERSION, VENDOR)               \
+  DW_OP_##NAME = ID,
 #include "llvm/BinaryFormat/Dwarf.def"
   DW_OP_lo_user = 0xe0,
   DW_OP_hi_user = 0xff,
@@ -1049,6 +1050,14 @@ unsigned AttributeEncodingVendor(TypeKind E);
 unsigned LanguageVendor(SourceLanguage L);
 /// @}
 
+/// The number of operands for the given LocationAtom.
+std::optional<unsigned> OperationOperands(LocationAtom O);
+
+/// The arity of the given LocationAtom. This is the number of elements on the
+/// stack this operation operates on. Returns -1 if the arity is variable (e.g.
+/// depending on the argument) or unknown.
+std::optional<unsigned> OperationArity(LocationAtom O);
+
 std::optional<unsigned> LanguageLowerBound(SourceLanguage L);
 
 /// The size of a reference determined by the DWARF 32/64-bit format.

diff  --git a/llvm/include/llvm/ObjectYAML/DWARFYAML.h b/llvm/include/llvm/ObjectYAML/DWARFYAML.h
index 0b3bea786d31c..7b65e325ef05d 100644
--- a/llvm/include/llvm/ObjectYAML/DWARFYAML.h
+++ b/llvm/include/llvm/ObjectYAML/DWARFYAML.h
@@ -522,7 +522,7 @@ template <> struct ScalarEnumerationTraits<dwarf::LoclistEntries> {
   }
 };
 
-#define HANDLE_DW_OP(id, name, version, vendor)                                \
+#define HANDLE_DW_OP(id, name, operands, arity, version, vendor)               \
   io.enumCase(value, "DW_OP_" #name, dwarf::DW_OP_##name);
 
 template <> struct ScalarEnumerationTraits<dwarf::LocationAtom> {

diff  --git a/llvm/lib/BinaryFormat/Dwarf.cpp b/llvm/lib/BinaryFormat/Dwarf.cpp
index 0bf4f201dbe10..0cd5dfbd023e4 100644
--- a/llvm/lib/BinaryFormat/Dwarf.cpp
+++ b/llvm/lib/BinaryFormat/Dwarf.cpp
@@ -139,7 +139,7 @@ StringRef llvm::dwarf::OperationEncodingString(unsigned Encoding) {
   switch (Encoding) {
   default:
     return StringRef();
-#define HANDLE_DW_OP(ID, NAME, VERSION, VENDOR)                                \
+#define HANDLE_DW_OP(ID, NAME, OPERANDS, ARITY, VERSION, VENDOR)               \
   case DW_OP_##NAME:                                                           \
     return "DW_OP_" #NAME;
 #include "llvm/BinaryFormat/Dwarf.def"
@@ -164,7 +164,7 @@ StringRef llvm::dwarf::OperationEncodingString(unsigned Encoding) {
 
 unsigned llvm::dwarf::getOperationEncoding(StringRef OperationEncodingString) {
   return StringSwitch<unsigned>(OperationEncodingString)
-#define HANDLE_DW_OP(ID, NAME, VERSION, VENDOR)                                \
+#define HANDLE_DW_OP(ID, NAME, OPERANDS, ARITY, VERSION, VENDOR)               \
   .Case("DW_OP_" #NAME, DW_OP_##NAME)
 #include "llvm/BinaryFormat/Dwarf.def"
       .Case("DW_OP_LLVM_convert", DW_OP_LLVM_convert)
@@ -216,18 +216,44 @@ unsigned llvm::dwarf::OperationVersion(dwarf::LocationAtom Op) {
   switch (Op) {
   default:
     return 0;
-#define HANDLE_DW_OP(ID, NAME, VERSION, VENDOR)                                \
+#define HANDLE_DW_OP(ID, NAME, OPERANDS, ARITY, VERSION, VENDOR)               \
   case DW_OP_##NAME:                                                           \
     return VERSION;
 #include "llvm/BinaryFormat/Dwarf.def"
   }
 }
 
+std::optional<unsigned> llvm::dwarf::OperationOperands(dwarf::LocationAtom Op) {
+  switch (Op) {
+  default:
+    return std::nullopt;
+#define HANDLE_DW_OP(ID, NAME, OPERANDS, ARITY, VERSION, VENDOR)               \
+  case DW_OP_##NAME:                                                           \
+    if (OPERANDS == -1)                                                        \
+      return std::nullopt;                                                     \
+    return OPERANDS;
+#include "llvm/BinaryFormat/Dwarf.def"
+  }
+}
+
+std::optional<unsigned> llvm::dwarf::OperationArity(dwarf::LocationAtom Op) {
+  switch (Op) {
+  default:
+    return std::nullopt;
+#define HANDLE_DW_OP(ID, NAME, OPERANDS, ARITY, VERSION, VENDOR)               \
+  case DW_OP_##NAME:                                                           \
+    if (ARITY == -1)                                                           \
+      return std::nullopt;                                                     \
+    return ARITY;
+#include "llvm/BinaryFormat/Dwarf.def"
+  }
+}
+
 unsigned llvm::dwarf::OperationVendor(dwarf::LocationAtom Op) {
   switch (Op) {
   default:
     return 0;
-#define HANDLE_DW_OP(ID, NAME, VERSION, VENDOR)                                \
+#define HANDLE_DW_OP(ID, NAME, OPERANDS, ARITY, VERSION, VENDOR)               \
   case DW_OP_##NAME:                                                           \
     return DWARF_VENDOR_##VENDOR;
 #include "llvm/BinaryFormat/Dwarf.def"


        


More information about the llvm-commits mailing list