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

Jonas Devlieghere via llvm-commits llvm-commits at lists.llvm.org
Fri Jun 7 08:19:59 PDT 2024


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

>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/4] [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/4] [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/4] [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;

>From a4049409c25a7496e4721e0d7647e86d9b2747ff Mon Sep 17 00:00:00 2001
From: Jonas Devlieghere <jonas at devlieghere.com>
Date: Thu, 6 Jun 2024 15:09:11 -0700
Subject: [PATCH 4/4] Address Adrian's feedback

---
 llvm/include/llvm/BinaryFormat/Dwarf.def | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/llvm/include/llvm/BinaryFormat/Dwarf.def b/llvm/include/llvm/BinaryFormat/Dwarf.def
index 69694d90d69a9..d55947fc5103a 100644
--- a/llvm/include/llvm/BinaryFormat/Dwarf.def
+++ b/llvm/include/llvm/BinaryFormat/Dwarf.def
@@ -728,14 +728,14 @@ 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(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, -1, 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)
@@ -841,12 +841,12 @@ 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, 0, 3, DWARF)
-HANDLE_DW_OP(0x98, call2, 1, 1, 3, DWARF)
-HANDLE_DW_OP(0x99, call4, 1, 1, 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, 1, 3, DWARF)
+HANDLE_DW_OP(0x9d, bit_piece, 2, 0, 3, DWARF)
 // New in DWARF v4:
 HANDLE_DW_OP(0x9e, implicit_value, 2, 0, 4, DWARF)
 HANDLE_DW_OP(0x9f, stack_value, 0, 1, 4, DWARF)



More information about the llvm-commits mailing list