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

Jonas Devlieghere via lldb-commits lldb-commits at lists.llvm.org
Thu Jun 6 13:39:34 PDT 2024


https://github.com/JDevlieghere created https://github.com/llvm/llvm-project/pull/94679

This PR extends Dwarf.def to include the number of operands and the arity (the number of entries on the DWARF stack) and use it from the LLDB DWARF expression evaluator.

>From 63fd7a008900fea3bb609ac018f8401f04f07703 Mon Sep 17 00:00:00 2001
From: Jonas Devlieghere <jonas at devlieghere.com>
Date: Thu, 6 Jun 2024 10:14:34 -0700
Subject: [PATCH 1/3] [lldb] Encode number of operands for DWARF operations

Add the number of operands to Dwarf.h as documented in Table 7.6 in the
DWARF 5 standard.
---
 llvm/include/llvm/BinaryFormat/Dwarf.def | 364 +++++++++++------------
 llvm/include/llvm/BinaryFormat/Dwarf.h   |   5 +-
 llvm/include/llvm/ObjectYAML/DWARFYAML.h |   2 +-
 llvm/lib/BinaryFormat/Dwarf.cpp          |  21 +-
 4 files changed, 204 insertions(+), 188 deletions(-)

diff --git a/llvm/include/llvm/BinaryFormat/Dwarf.def b/llvm/include/llvm/BinaryFormat/Dwarf.def
index adcf24eb83b03..bbc3bbcf02b5c 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, 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, 2, DWARF)
+HANDLE_DW_OP(0x06, deref, 0, 2, DWARF)
+HANDLE_DW_OP(0x08, const1u, 1, 2, DWARF)
+HANDLE_DW_OP(0x09, const1s, 1, 2, DWARF)
+HANDLE_DW_OP(0x0a, const2u, 1, 2, DWARF)
+HANDLE_DW_OP(0x0b, const2s, 1, 2, DWARF)
+HANDLE_DW_OP(0x0c, const4u, 1, 2, DWARF)
+HANDLE_DW_OP(0x0d, const4s, 1, 2, DWARF)
+HANDLE_DW_OP(0x0e, const8u, 1, 2, DWARF)
+HANDLE_DW_OP(0x0f, const8s, 1, 2, DWARF)
+HANDLE_DW_OP(0x10, constu, 1, 2, DWARF)
+HANDLE_DW_OP(0x11, consts, 1, 2, DWARF)
+HANDLE_DW_OP(0x12, dup, 0, 2, DWARF)
+HANDLE_DW_OP(0x13, drop, 0, 2, DWARF)
+HANDLE_DW_OP(0x14, over, 0, 2, DWARF)
+HANDLE_DW_OP(0x15, pick, 1, 2, DWARF)
+HANDLE_DW_OP(0x16, swap, 0, 2, DWARF)
+HANDLE_DW_OP(0x17, rot, 0 ,2, DWARF)
+HANDLE_DW_OP(0x18, xderef, 0, 2, DWARF)
+HANDLE_DW_OP(0x19, abs, 0, 2, DWARF)
+HANDLE_DW_OP(0x1a, and, 0, 2, DWARF)
+HANDLE_DW_OP(0x1b, div, 0, 2, DWARF)
+HANDLE_DW_OP(0x1c, minus, 0, 2, DWARF)
+HANDLE_DW_OP(0x1d, mod, 0, 2, DWARF)
+HANDLE_DW_OP(0x1e, mul, 0, 2, DWARF)
+HANDLE_DW_OP(0x1f, neg, 0, 2, DWARF)
+HANDLE_DW_OP(0x20, not, 0, 2, DWARF)
+HANDLE_DW_OP(0x21, or, 0, 2, DWARF)
+HANDLE_DW_OP(0x22, plus, 0, 2, DWARF)
+HANDLE_DW_OP(0x23, plus_uconst, 1, 2, DWARF)
+HANDLE_DW_OP(0x24, shl, 0, 2, DWARF)
+HANDLE_DW_OP(0x25, shr, 0, 2, DWARF)
+HANDLE_DW_OP(0x26, shra, 0, 2, DWARF)
+HANDLE_DW_OP(0x27, xor, 0, 2, DWARF)
+HANDLE_DW_OP(0x28, bra, 1, 2, DWARF)
+HANDLE_DW_OP(0x29, eq, 0, 2, DWARF)
+HANDLE_DW_OP(0x2a, ge, 0, 2, DWARF)
+HANDLE_DW_OP(0x2b, gt, 0, 2, DWARF)
+HANDLE_DW_OP(0x2c, le, 0, 2, DWARF)
+HANDLE_DW_OP(0x2d, lt, 0, 2, DWARF)
+HANDLE_DW_OP(0x2e, ne, 0, 2, DWARF)
+HANDLE_DW_OP(0x2f, skip, 1, 2, DWARF)
+HANDLE_DW_OP(0x30, lit0, 0, 2, DWARF)
+HANDLE_DW_OP(0x31, lit1, 0, 2, DWARF)
+HANDLE_DW_OP(0x32, lit2, 0, 2, DWARF)
+HANDLE_DW_OP(0x33, lit3, 0, 2, DWARF)
+HANDLE_DW_OP(0x34, lit4, 0, 2, DWARF)
+HANDLE_DW_OP(0x35, lit5, 0, 2, DWARF)
+HANDLE_DW_OP(0x36, lit6, 0, 2, DWARF)
+HANDLE_DW_OP(0x37, lit7, 0, 2, DWARF)
+HANDLE_DW_OP(0x38, lit8, 0, 2, DWARF)
+HANDLE_DW_OP(0x39, lit9, 0, 2, DWARF)
+HANDLE_DW_OP(0x3a, lit10, 0, 2, DWARF)
+HANDLE_DW_OP(0x3b, lit11, 0, 2, DWARF)
+HANDLE_DW_OP(0x3c, lit12, 0, 2, DWARF)
+HANDLE_DW_OP(0x3d, lit13, 0, 2, DWARF)
+HANDLE_DW_OP(0x3e, lit14, 0, 2, DWARF)
+HANDLE_DW_OP(0x3f, lit15, 0, 2, DWARF)
+HANDLE_DW_OP(0x40, lit16, 0, 2, DWARF)
+HANDLE_DW_OP(0x41, lit17, 0, 2, DWARF)
+HANDLE_DW_OP(0x42, lit18, 0, 2, DWARF)
+HANDLE_DW_OP(0x43, lit19, 0, 2, DWARF)
+HANDLE_DW_OP(0x44, lit20, 0, 2, DWARF)
+HANDLE_DW_OP(0x45, lit21, 0, 2, DWARF)
+HANDLE_DW_OP(0x46, lit22, 0, 2, DWARF)
+HANDLE_DW_OP(0x47, lit23, 0, 2, DWARF)
+HANDLE_DW_OP(0x48, lit24, 0, 2, DWARF)
+HANDLE_DW_OP(0x49, lit25, 0, 2, DWARF)
+HANDLE_DW_OP(0x4a, lit26, 0, 2, DWARF)
+HANDLE_DW_OP(0x4b, lit27, 0, 2, DWARF)
+HANDLE_DW_OP(0x4c, lit28, 0, 2, DWARF)
+HANDLE_DW_OP(0x4d, lit29, 0, 2, DWARF)
+HANDLE_DW_OP(0x4e, lit30, 0, 2, DWARF)
+HANDLE_DW_OP(0x4f, lit31, 0, 2, DWARF)
+HANDLE_DW_OP(0x50, reg0, 0, 2, DWARF)
+HANDLE_DW_OP(0x51, reg1, 0, 2, DWARF)
+HANDLE_DW_OP(0x52, reg2, 0, 2, DWARF)
+HANDLE_DW_OP(0x53, reg3, 0, 2, DWARF)
+HANDLE_DW_OP(0x54, reg4, 0, 2, DWARF)
+HANDLE_DW_OP(0x55, reg5, 0, 2, DWARF)
+HANDLE_DW_OP(0x56, reg6, 0, 2, DWARF)
+HANDLE_DW_OP(0x57, reg7, 0, 2, DWARF)
+HANDLE_DW_OP(0x58, reg8, 0, 2, DWARF)
+HANDLE_DW_OP(0x59, reg9, 0, 2, DWARF)
+HANDLE_DW_OP(0x5a, reg10, 0, 2, DWARF)
+HANDLE_DW_OP(0x5b, reg11, 0, 2, DWARF)
+HANDLE_DW_OP(0x5c, reg12, 0, 2, DWARF)
+HANDLE_DW_OP(0x5d, reg13, 0, 2, DWARF)
+HANDLE_DW_OP(0x5e, reg14, 0, 2, DWARF)
+HANDLE_DW_OP(0x5f, reg15, 0, 2, DWARF)
+HANDLE_DW_OP(0x60, reg16, 0, 2, DWARF)
+HANDLE_DW_OP(0x61, reg17, 0, 2, DWARF)
+HANDLE_DW_OP(0x62, reg18, 0, 2, DWARF)
+HANDLE_DW_OP(0x63, reg19, 0, 2, DWARF)
+HANDLE_DW_OP(0x64, reg20, 0, 2, DWARF)
+HANDLE_DW_OP(0x65, reg21, 0, 2, DWARF)
+HANDLE_DW_OP(0x66, reg22, 0, 2, DWARF)
+HANDLE_DW_OP(0x67, reg23, 0, 2, DWARF)
+HANDLE_DW_OP(0x68, reg24, 0, 2, DWARF)
+HANDLE_DW_OP(0x69, reg25, 0, 2, DWARF)
+HANDLE_DW_OP(0x6a, reg26, 0, 2, DWARF)
+HANDLE_DW_OP(0x6b, reg27, 0, 2, DWARF)
+HANDLE_DW_OP(0x6c, reg28, 0, 2, DWARF)
+HANDLE_DW_OP(0x6d, reg29, 0, 2, DWARF)
+HANDLE_DW_OP(0x6e, reg30, 0, 2, DWARF)
+HANDLE_DW_OP(0x6f, reg31, 0, 2, DWARF)
+HANDLE_DW_OP(0x70, breg0, 1, 2, DWARF)
+HANDLE_DW_OP(0x71, breg1, 1, 2, DWARF)
+HANDLE_DW_OP(0x72, breg2, 1, 2, DWARF)
+HANDLE_DW_OP(0x73, breg3, 1, 2, DWARF)
+HANDLE_DW_OP(0x74, breg4, 1, 2, DWARF)
+HANDLE_DW_OP(0x75, breg5, 1, 2, DWARF)
+HANDLE_DW_OP(0x76, breg6, 1, 2, DWARF)
+HANDLE_DW_OP(0x77, breg7, 1, 2, DWARF)
+HANDLE_DW_OP(0x78, breg8, 1, 2, DWARF)
+HANDLE_DW_OP(0x79, breg9, 1, 2, DWARF)
+HANDLE_DW_OP(0x7a, breg10, 1, 2, DWARF)
+HANDLE_DW_OP(0x7b, breg11, 1, 2, DWARF)
+HANDLE_DW_OP(0x7c, breg12, 1, 2, DWARF)
+HANDLE_DW_OP(0x7d, breg13, 1, 2, DWARF)
+HANDLE_DW_OP(0x7e, breg14, 1, 2, DWARF)
+HANDLE_DW_OP(0x7f, breg15, 1, 2, DWARF)
+HANDLE_DW_OP(0x80, breg16, 1, 2, DWARF)
+HANDLE_DW_OP(0x81, breg17, 1, 2, DWARF)
+HANDLE_DW_OP(0x82, breg18, 1, 2, DWARF)
+HANDLE_DW_OP(0x83, breg19, 1, 2, DWARF)
+HANDLE_DW_OP(0x84, breg20, 1, 2, DWARF)
+HANDLE_DW_OP(0x85, breg21, 1, 2, DWARF)
+HANDLE_DW_OP(0x86, breg22, 1, 2, DWARF)
+HANDLE_DW_OP(0x87, breg23, 1, 2, DWARF)
+HANDLE_DW_OP(0x88, breg24, 1, 2, DWARF)
+HANDLE_DW_OP(0x89, breg25, 1, 2, DWARF)
+HANDLE_DW_OP(0x8a, breg26, 1, 2, DWARF)
+HANDLE_DW_OP(0x8b, breg27, 1, 2, DWARF)
+HANDLE_DW_OP(0x8c, breg28, 1, 2, DWARF)
+HANDLE_DW_OP(0x8d, breg29, 1, 2, DWARF)
+HANDLE_DW_OP(0x8e, breg30, 1, 2, DWARF)
+HANDLE_DW_OP(0x8f, breg31, 1, 2, DWARF)
+HANDLE_DW_OP(0x90, regx, 1, 2, DWARF)
+HANDLE_DW_OP(0x91, fbreg, 1, 2, DWARF)
+HANDLE_DW_OP(0x92, bregx, 2, 2, DWARF)
+HANDLE_DW_OP(0x93, piece, 1, 2, DWARF)
+HANDLE_DW_OP(0x94, deref_size, 1, 2, DWARF)
+HANDLE_DW_OP(0x95, xderef_size, 1, 2, DWARF)
+HANDLE_DW_OP(0x96, nop, 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, 3, DWARF)
+HANDLE_DW_OP(0x98, call2, 1, 3, DWARF)
+HANDLE_DW_OP(0x99, call4, 1, 3, DWARF)
+HANDLE_DW_OP(0x9a, call_ref, 1, 3, DWARF)
+HANDLE_DW_OP(0x9b, form_tls_address, 0, 3, DWARF)
+HANDLE_DW_OP(0x9c, call_frame_cfa, 0, 3, DWARF)
+HANDLE_DW_OP(0x9d, bit_piece, 2, 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, 4, DWARF)
+HANDLE_DW_OP(0x9f, stack_value, 0, 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, 5, DWARF)
+HANDLE_DW_OP(0xa1, addrx, 1, 5, DWARF)
+HANDLE_DW_OP(0xa2, constx, 1, 5, DWARF)
+HANDLE_DW_OP(0xa3, entry_value, 2, 5, DWARF)
+HANDLE_DW_OP(0xa4, const_type, 3, 5, DWARF)
+HANDLE_DW_OP(0xa5, regval_type, 2, 5, DWARF)
+HANDLE_DW_OP(0xa6, deref_type, 2, 5, DWARF)
+HANDLE_DW_OP(0xa7, xderef_type, 2, 5, DWARF)
+HANDLE_DW_OP(0xa8, convert, 2, 5, DWARF)
+HANDLE_DW_OP(0xa9, reinterpret, 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, 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, 0, HP)
+HANDLE_DW_OP(0xe1, HP_is_value, -1, 0, HP)
+HANDLE_DW_OP(0xe2, HP_fltconst4, -1, 0, HP)
+HANDLE_DW_OP(0xe3, HP_fltconst8, -1, 0, HP)
+HANDLE_DW_OP(0xe4, HP_mod_range, -1, 0, HP)
+HANDLE_DW_OP(0xe5, HP_unmod_range, -1, 0, HP)
+HANDLE_DW_OP(0xe6, HP_tls, -1, 0, HP)
+HANDLE_DW_OP(0xe8, INTEL_bit_piece, -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, 0, WASM)
+HANDLE_DW_OP(0xee, WASM_location_int, -1, 0, WASM)
 // Historic and not implemented in LLVM.
-HANDLE_DW_OP(0xf0, APPLE_uninit, 0, APPLE)
+HANDLE_DW_OP(0xf0, APPLE_uninit, -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, GNU)
+HANDLE_DW_OP(0xf8, PGI_omp_thread_num, -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, GNU)
+HANDLE_DW_OP(0xfc, GNU_const_index, 1, 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, 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 74c4d6ff3a716..214db2a300637 100644
--- a/llvm/include/llvm/BinaryFormat/Dwarf.h
+++ b/llvm/include/llvm/BinaryFormat/Dwarf.h
@@ -134,7 +134,7 @@ 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, VERSION, VENDOR) DW_OP_##NAME = ID,
 #include "llvm/BinaryFormat/Dwarf.def"
   DW_OP_lo_user = 0xe0,
   DW_OP_hi_user = 0xff,
@@ -1047,6 +1047,9 @@ unsigned AttributeEncodingVendor(TypeKind E);
 unsigned LanguageVendor(SourceLanguage L);
 /// @}
 
+/// The number of operands for the given LocationAtom.
+std::optional<unsigned> OperationOperands(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..caa88d856c575 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, 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 7324266172684..314966d9d2350 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, VERSION, VENDOR)                      \
   case DW_OP_##NAME:                                                           \
     return "DW_OP_" #NAME;
 #include "llvm/BinaryFormat/Dwarf.def"
@@ -160,7 +160,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, VERSION, VENDOR)                      \
   .Case("DW_OP_" #NAME, DW_OP_##NAME)
 #include "llvm/BinaryFormat/Dwarf.def"
       .Case("DW_OP_LLVM_convert", DW_OP_LLVM_convert)
@@ -210,18 +210,31 @@ 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, 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, VERSION, VENDOR)                      \
+  case DW_OP_##NAME:                                                           \
+    if (OPERANDS == -1)                                                        \
+      return std::nullopt;                                                     \
+    return OPERANDS;
+#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, VERSION, VENDOR)                      \
   case DW_OP_##NAME:                                                           \
     return DWARF_VENDOR_##VENDOR;
 #include "llvm/BinaryFormat/Dwarf.def"

>From 92a3abaa9b644d72298b7705b8f9fcbe0bbf7480 Mon Sep 17 00:00:00 2001
From: Jonas Devlieghere <jonas at devlieghere.com>
Date: Thu, 6 Jun 2024 11:41:25 -0700
Subject: [PATCH 2/3] [lldb] Encode arity for DWARF operations in Dwarf.def

---
 llvm/include/llvm/BinaryFormat/Dwarf.def | 364 +++++++++++------------
 llvm/include/llvm/BinaryFormat/Dwarf.h   |   8 +-
 llvm/include/llvm/ObjectYAML/DWARFYAML.h |   2 +-
 llvm/lib/BinaryFormat/Dwarf.cpp          |  23 +-
 4 files changed, 208 insertions(+), 189 deletions(-)

diff --git a/llvm/include/llvm/BinaryFormat/Dwarf.def b/llvm/include/llvm/BinaryFormat/Dwarf.def
index bbc3bbcf02b5c..69694d90d69a9 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, OPERANDS, 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, 1, 2, DWARF)
-HANDLE_DW_OP(0x06, deref, 0, 2, DWARF)
-HANDLE_DW_OP(0x08, const1u, 1, 2, DWARF)
-HANDLE_DW_OP(0x09, const1s, 1, 2, DWARF)
-HANDLE_DW_OP(0x0a, const2u, 1, 2, DWARF)
-HANDLE_DW_OP(0x0b, const2s, 1, 2, DWARF)
-HANDLE_DW_OP(0x0c, const4u, 1, 2, DWARF)
-HANDLE_DW_OP(0x0d, const4s, 1, 2, DWARF)
-HANDLE_DW_OP(0x0e, const8u, 1, 2, DWARF)
-HANDLE_DW_OP(0x0f, const8s, 1, 2, DWARF)
-HANDLE_DW_OP(0x10, constu, 1, 2, DWARF)
-HANDLE_DW_OP(0x11, consts, 1, 2, DWARF)
-HANDLE_DW_OP(0x12, dup, 0, 2, DWARF)
-HANDLE_DW_OP(0x13, drop, 0, 2, DWARF)
-HANDLE_DW_OP(0x14, over, 0, 2, DWARF)
-HANDLE_DW_OP(0x15, pick, 1, 2, DWARF)
-HANDLE_DW_OP(0x16, swap, 0, 2, DWARF)
-HANDLE_DW_OP(0x17, rot, 0 ,2, DWARF)
-HANDLE_DW_OP(0x18, xderef, 0, 2, DWARF)
-HANDLE_DW_OP(0x19, abs, 0, 2, DWARF)
-HANDLE_DW_OP(0x1a, and, 0, 2, DWARF)
-HANDLE_DW_OP(0x1b, div, 0, 2, DWARF)
-HANDLE_DW_OP(0x1c, minus, 0, 2, DWARF)
-HANDLE_DW_OP(0x1d, mod, 0, 2, DWARF)
-HANDLE_DW_OP(0x1e, mul, 0, 2, DWARF)
-HANDLE_DW_OP(0x1f, neg, 0, 2, DWARF)
-HANDLE_DW_OP(0x20, not, 0, 2, DWARF)
-HANDLE_DW_OP(0x21, or, 0, 2, DWARF)
-HANDLE_DW_OP(0x22, plus, 0, 2, DWARF)
-HANDLE_DW_OP(0x23, plus_uconst, 1, 2, DWARF)
-HANDLE_DW_OP(0x24, shl, 0, 2, DWARF)
-HANDLE_DW_OP(0x25, shr, 0, 2, DWARF)
-HANDLE_DW_OP(0x26, shra, 0, 2, DWARF)
-HANDLE_DW_OP(0x27, xor, 0, 2, DWARF)
-HANDLE_DW_OP(0x28, bra, 1, 2, DWARF)
-HANDLE_DW_OP(0x29, eq, 0, 2, DWARF)
-HANDLE_DW_OP(0x2a, ge, 0, 2, DWARF)
-HANDLE_DW_OP(0x2b, gt, 0, 2, DWARF)
-HANDLE_DW_OP(0x2c, le, 0, 2, DWARF)
-HANDLE_DW_OP(0x2d, lt, 0, 2, DWARF)
-HANDLE_DW_OP(0x2e, ne, 0, 2, DWARF)
-HANDLE_DW_OP(0x2f, skip, 1, 2, DWARF)
-HANDLE_DW_OP(0x30, lit0, 0, 2, DWARF)
-HANDLE_DW_OP(0x31, lit1, 0, 2, DWARF)
-HANDLE_DW_OP(0x32, lit2, 0, 2, DWARF)
-HANDLE_DW_OP(0x33, lit3, 0, 2, DWARF)
-HANDLE_DW_OP(0x34, lit4, 0, 2, DWARF)
-HANDLE_DW_OP(0x35, lit5, 0, 2, DWARF)
-HANDLE_DW_OP(0x36, lit6, 0, 2, DWARF)
-HANDLE_DW_OP(0x37, lit7, 0, 2, DWARF)
-HANDLE_DW_OP(0x38, lit8, 0, 2, DWARF)
-HANDLE_DW_OP(0x39, lit9, 0, 2, DWARF)
-HANDLE_DW_OP(0x3a, lit10, 0, 2, DWARF)
-HANDLE_DW_OP(0x3b, lit11, 0, 2, DWARF)
-HANDLE_DW_OP(0x3c, lit12, 0, 2, DWARF)
-HANDLE_DW_OP(0x3d, lit13, 0, 2, DWARF)
-HANDLE_DW_OP(0x3e, lit14, 0, 2, DWARF)
-HANDLE_DW_OP(0x3f, lit15, 0, 2, DWARF)
-HANDLE_DW_OP(0x40, lit16, 0, 2, DWARF)
-HANDLE_DW_OP(0x41, lit17, 0, 2, DWARF)
-HANDLE_DW_OP(0x42, lit18, 0, 2, DWARF)
-HANDLE_DW_OP(0x43, lit19, 0, 2, DWARF)
-HANDLE_DW_OP(0x44, lit20, 0, 2, DWARF)
-HANDLE_DW_OP(0x45, lit21, 0, 2, DWARF)
-HANDLE_DW_OP(0x46, lit22, 0, 2, DWARF)
-HANDLE_DW_OP(0x47, lit23, 0, 2, DWARF)
-HANDLE_DW_OP(0x48, lit24, 0, 2, DWARF)
-HANDLE_DW_OP(0x49, lit25, 0, 2, DWARF)
-HANDLE_DW_OP(0x4a, lit26, 0, 2, DWARF)
-HANDLE_DW_OP(0x4b, lit27, 0, 2, DWARF)
-HANDLE_DW_OP(0x4c, lit28, 0, 2, DWARF)
-HANDLE_DW_OP(0x4d, lit29, 0, 2, DWARF)
-HANDLE_DW_OP(0x4e, lit30, 0, 2, DWARF)
-HANDLE_DW_OP(0x4f, lit31, 0, 2, DWARF)
-HANDLE_DW_OP(0x50, reg0, 0, 2, DWARF)
-HANDLE_DW_OP(0x51, reg1, 0, 2, DWARF)
-HANDLE_DW_OP(0x52, reg2, 0, 2, DWARF)
-HANDLE_DW_OP(0x53, reg3, 0, 2, DWARF)
-HANDLE_DW_OP(0x54, reg4, 0, 2, DWARF)
-HANDLE_DW_OP(0x55, reg5, 0, 2, DWARF)
-HANDLE_DW_OP(0x56, reg6, 0, 2, DWARF)
-HANDLE_DW_OP(0x57, reg7, 0, 2, DWARF)
-HANDLE_DW_OP(0x58, reg8, 0, 2, DWARF)
-HANDLE_DW_OP(0x59, reg9, 0, 2, DWARF)
-HANDLE_DW_OP(0x5a, reg10, 0, 2, DWARF)
-HANDLE_DW_OP(0x5b, reg11, 0, 2, DWARF)
-HANDLE_DW_OP(0x5c, reg12, 0, 2, DWARF)
-HANDLE_DW_OP(0x5d, reg13, 0, 2, DWARF)
-HANDLE_DW_OP(0x5e, reg14, 0, 2, DWARF)
-HANDLE_DW_OP(0x5f, reg15, 0, 2, DWARF)
-HANDLE_DW_OP(0x60, reg16, 0, 2, DWARF)
-HANDLE_DW_OP(0x61, reg17, 0, 2, DWARF)
-HANDLE_DW_OP(0x62, reg18, 0, 2, DWARF)
-HANDLE_DW_OP(0x63, reg19, 0, 2, DWARF)
-HANDLE_DW_OP(0x64, reg20, 0, 2, DWARF)
-HANDLE_DW_OP(0x65, reg21, 0, 2, DWARF)
-HANDLE_DW_OP(0x66, reg22, 0, 2, DWARF)
-HANDLE_DW_OP(0x67, reg23, 0, 2, DWARF)
-HANDLE_DW_OP(0x68, reg24, 0, 2, DWARF)
-HANDLE_DW_OP(0x69, reg25, 0, 2, DWARF)
-HANDLE_DW_OP(0x6a, reg26, 0, 2, DWARF)
-HANDLE_DW_OP(0x6b, reg27, 0, 2, DWARF)
-HANDLE_DW_OP(0x6c, reg28, 0, 2, DWARF)
-HANDLE_DW_OP(0x6d, reg29, 0, 2, DWARF)
-HANDLE_DW_OP(0x6e, reg30, 0, 2, DWARF)
-HANDLE_DW_OP(0x6f, reg31, 0, 2, DWARF)
-HANDLE_DW_OP(0x70, breg0, 1, 2, DWARF)
-HANDLE_DW_OP(0x71, breg1, 1, 2, DWARF)
-HANDLE_DW_OP(0x72, breg2, 1, 2, DWARF)
-HANDLE_DW_OP(0x73, breg3, 1, 2, DWARF)
-HANDLE_DW_OP(0x74, breg4, 1, 2, DWARF)
-HANDLE_DW_OP(0x75, breg5, 1, 2, DWARF)
-HANDLE_DW_OP(0x76, breg6, 1, 2, DWARF)
-HANDLE_DW_OP(0x77, breg7, 1, 2, DWARF)
-HANDLE_DW_OP(0x78, breg8, 1, 2, DWARF)
-HANDLE_DW_OP(0x79, breg9, 1, 2, DWARF)
-HANDLE_DW_OP(0x7a, breg10, 1, 2, DWARF)
-HANDLE_DW_OP(0x7b, breg11, 1, 2, DWARF)
-HANDLE_DW_OP(0x7c, breg12, 1, 2, DWARF)
-HANDLE_DW_OP(0x7d, breg13, 1, 2, DWARF)
-HANDLE_DW_OP(0x7e, breg14, 1, 2, DWARF)
-HANDLE_DW_OP(0x7f, breg15, 1, 2, DWARF)
-HANDLE_DW_OP(0x80, breg16, 1, 2, DWARF)
-HANDLE_DW_OP(0x81, breg17, 1, 2, DWARF)
-HANDLE_DW_OP(0x82, breg18, 1, 2, DWARF)
-HANDLE_DW_OP(0x83, breg19, 1, 2, DWARF)
-HANDLE_DW_OP(0x84, breg20, 1, 2, DWARF)
-HANDLE_DW_OP(0x85, breg21, 1, 2, DWARF)
-HANDLE_DW_OP(0x86, breg22, 1, 2, DWARF)
-HANDLE_DW_OP(0x87, breg23, 1, 2, DWARF)
-HANDLE_DW_OP(0x88, breg24, 1, 2, DWARF)
-HANDLE_DW_OP(0x89, breg25, 1, 2, DWARF)
-HANDLE_DW_OP(0x8a, breg26, 1, 2, DWARF)
-HANDLE_DW_OP(0x8b, breg27, 1, 2, DWARF)
-HANDLE_DW_OP(0x8c, breg28, 1, 2, DWARF)
-HANDLE_DW_OP(0x8d, breg29, 1, 2, DWARF)
-HANDLE_DW_OP(0x8e, breg30, 1, 2, DWARF)
-HANDLE_DW_OP(0x8f, breg31, 1, 2, DWARF)
-HANDLE_DW_OP(0x90, regx, 1, 2, DWARF)
-HANDLE_DW_OP(0x91, fbreg, 1, 2, DWARF)
-HANDLE_DW_OP(0x92, bregx, 2, 2, DWARF)
-HANDLE_DW_OP(0x93, piece, 1, 2, DWARF)
-HANDLE_DW_OP(0x94, deref_size, 1, 2, DWARF)
-HANDLE_DW_OP(0x95, xderef_size, 1, 2, DWARF)
-HANDLE_DW_OP(0x96, nop, 0, 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, 1, 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, -1, 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, 0, 3, DWARF)
-HANDLE_DW_OP(0x98, call2, 1, 3, DWARF)
-HANDLE_DW_OP(0x99, call4, 1, 3, DWARF)
-HANDLE_DW_OP(0x9a, call_ref, 1, 3, DWARF)
-HANDLE_DW_OP(0x9b, form_tls_address, 0, 3, DWARF)
-HANDLE_DW_OP(0x9c, call_frame_cfa, 0, 3, DWARF)
-HANDLE_DW_OP(0x9d, bit_piece, 2, 3, DWARF)
+HANDLE_DW_OP(0x97, push_object_address, 0, 0, 3, DWARF)
+HANDLE_DW_OP(0x98, call2, 1, 1, 3, DWARF)
+HANDLE_DW_OP(0x99, call4, 1, 1, 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, 1, 3, DWARF)
 // New in DWARF v4:
-HANDLE_DW_OP(0x9e, implicit_value, 2, 4, DWARF)
-HANDLE_DW_OP(0x9f, stack_value, 0, 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, 2, 5, DWARF)
-HANDLE_DW_OP(0xa1, addrx, 1, 5, DWARF)
-HANDLE_DW_OP(0xa2, constx, 1, 5, DWARF)
-HANDLE_DW_OP(0xa3, entry_value, 2, 5, DWARF)
-HANDLE_DW_OP(0xa4, const_type, 3, 5, DWARF)
-HANDLE_DW_OP(0xa5, regval_type, 2, 5, DWARF)
-HANDLE_DW_OP(0xa6, deref_type, 2, 5, DWARF)
-HANDLE_DW_OP(0xa7, xderef_type, 2, 5, DWARF)
-HANDLE_DW_OP(0xa8, convert, 2, 5, DWARF)
-HANDLE_DW_OP(0xa9, reinterpret, 1, 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, 0, GNU)
+HANDLE_DW_OP(0xe0, GNU_push_tls_address, 0, 0, 0, GNU)
 // Conflicting:
-// HANDLE_DW_OP(0xe0, HP_unknown, -1, 0, HP)
-HANDLE_DW_OP(0xe1, HP_is_value, -1, 0, HP)
-HANDLE_DW_OP(0xe2, HP_fltconst4, -1, 0, HP)
-HANDLE_DW_OP(0xe3, HP_fltconst8, -1, 0, HP)
-HANDLE_DW_OP(0xe4, HP_mod_range, -1, 0, HP)
-HANDLE_DW_OP(0xe5, HP_unmod_range, -1, 0, HP)
-HANDLE_DW_OP(0xe6, HP_tls, -1, 0, HP)
-HANDLE_DW_OP(0xe8, INTEL_bit_piece, -1, 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, -1, 0, WASM)
-HANDLE_DW_OP(0xee, WASM_location_int, -1, 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, -1, 0, APPLE)
+HANDLE_DW_OP(0xf0, APPLE_uninit, -1, -1, 0, APPLE)
 // The GNU entry value extension.
-HANDLE_DW_OP(0xf3, GNU_entry_value, 2, 0, GNU)
-HANDLE_DW_OP(0xf8, PGI_omp_thread_num, -1, 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, 1, 0, GNU)
-HANDLE_DW_OP(0xfc, GNU_const_index, 1, 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, 1, 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, -1, 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 214db2a300637..2a331fc119bbe 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, OPERANDS, 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,
@@ -1050,6 +1051,11 @@ 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 caa88d856c575..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, operands, 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 314966d9d2350..78454540b3076 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, OPERANDS, 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"
@@ -160,7 +160,7 @@ StringRef llvm::dwarf::OperationEncodingString(unsigned Encoding) {
 
 unsigned llvm::dwarf::getOperationEncoding(StringRef OperationEncodingString) {
   return StringSwitch<unsigned>(OperationEncodingString)
-#define HANDLE_DW_OP(ID, NAME, OPERANDS, 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)
@@ -210,7 +210,7 @@ unsigned llvm::dwarf::OperationVersion(dwarf::LocationAtom Op) {
   switch (Op) {
   default:
     return 0;
-#define HANDLE_DW_OP(ID, NAME, OPERANDS, VERSION, VENDOR)                      \
+#define HANDLE_DW_OP(ID, NAME, OPERANDS, ARITY, VERSION, VENDOR)               \
   case DW_OP_##NAME:                                                           \
     return VERSION;
 #include "llvm/BinaryFormat/Dwarf.def"
@@ -221,7 +221,7 @@ std::optional<unsigned> llvm::dwarf::OperationOperands(dwarf::LocationAtom Op) {
   switch (Op) {
   default:
     return std::nullopt;
-#define HANDLE_DW_OP(ID, NAME, OPERANDS, VERSION, VENDOR)                      \
+#define HANDLE_DW_OP(ID, NAME, OPERANDS, ARITY, VERSION, VENDOR)               \
   case DW_OP_##NAME:                                                           \
     if (OPERANDS == -1)                                                        \
       return std::nullopt;                                                     \
@@ -230,11 +230,24 @@ std::optional<unsigned> llvm::dwarf::OperationOperands(dwarf::LocationAtom Op) {
   }
 }
 
+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, OPERANDS, 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"

>From c40774996ddca3c5d555e85151c0689b56ef0eb8 Mon Sep 17 00:00:00 2001
From: Jonas Devlieghere <jonas at devlieghere.com>
Date: Thu, 6 Jun 2024 13:36:09 -0700
Subject: [PATCH 3/3] [lldb] Use arity from Dwarf.def in DWARF expression
 evaluation

---
 lldb/source/Expression/DWARFExpression.cpp | 375 +++++++--------------
 1 file changed, 126 insertions(+), 249 deletions(-)

diff --git a/lldb/source/Expression/DWARFExpression.cpp b/lldb/source/Expression/DWARFExpression.cpp
index 4681dbafb6f9c..b10c3d4ac5ad9 100644
--- a/lldb/source/Expression/DWARFExpression.cpp
+++ b/lldb/source/Expression/DWARFExpression.cpp
@@ -912,6 +912,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.
@@ -1280,11 +1288,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
@@ -1307,14 +1311,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
@@ -1323,18 +1322,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
@@ -1342,10 +1336,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");
       }
@@ -1356,15 +1347,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
@@ -1372,42 +1358,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
@@ -1416,15 +1392,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
@@ -1432,28 +1403,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
@@ -1461,14 +1422,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
@@ -1476,15 +1431,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
@@ -1492,32 +1442,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
@@ -1525,14 +1465,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
@@ -1541,17 +1476,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
@@ -1561,14 +1490,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
@@ -1576,15 +1500,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
@@ -1615,30 +1534,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
@@ -1648,15 +1562,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
@@ -1667,15 +1576,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
@@ -1686,15 +1590,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
@@ -1705,15 +1604,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
@@ -1724,15 +1618,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
@@ -1743,15 +1632,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
@@ -2221,9 +2105,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;
 
@@ -2235,10 +2116,6 @@ 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: {
-      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;



More information about the lldb-commits mailing list