[llvm] [WIP][NFC] Start to hide details of DIExpression (PR #161716)
via llvm-commits
llvm-commits at lists.llvm.org
Thu Oct 2 11:22:42 PDT 2025
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-llvm-selectiondag
Author: Scott Linder (slinder1)
<details>
<summary>Changes</summary>
This is a WIP review to facilitate discussing https://discourse.llvm.org/t/rfc-for-diexpression-editing/88459
The first commit is just some refactoring to prepare for the change. The core of the proposal is in commit [Add DebugInfoExprs](https://github.com/llvm/llvm-project/commit/4175db72b48d5c0f40d469880c3aa86c4dea9c2d), and is followed by multiple commits adding example use.
The original commit message for the squashed version was:
Add a DIOp::Op type that fits in 2 qwords to replace the use of
uint64_ts in the interface.
Pull out nearly every DIExpression method which has a relationship to
the actual expression representation into either DIExprRef (an immutable
reference without ownership, similar to an ArrayRef) or DIExprBuf (a
mutable "builder" type).
TODO: A lot of docs, some remaining methods from DIExpression, and many
of the uses in the codebase
Rather than a std::variant this uses a bespoke X-macro based approach
I tried a few approaches which still had std::variant at the core, but
they all have drawbacks.
I also considered reviving the "IntrusiveVariant" generic type from
https://reviews.llvm.org/D98477 but ultimately I just went with the
approach @<!-- -->epilk suggested, basing the core implementation of visit on the
macros that are already useful for defining the alternative types
themselves.
I did not match the std::variant API particularly faithfully, but
if you squint it does map somewhat closely:
* Rather than free functions, everything is a member. A member visit is
already part of newer standards, although I have currently only
implemented a sort of "helper" over it that I called visitOverload,
which just removes the need to nest another call to e.g.
llvm::makeVisitor. Adding a standards-faithful visit member isn't
quite possible without future language features, but as the type is
canonically used by-value it seems fine to just add one (TODO). Adding
a N-ary free-function visit is probably not needed for this type.
* Rather than has_alternative, a regretably verbose identifier that I
assume was chosen to avoid collisions, we just have `has`.
* The getIf member is changed to be value-based and returns an optional.
Misc notes:
* DIExprBuf is double-buffered, added one example of using this
in FastISel to amortize allocations over many expression updates.
Unsure on this one, need to also consider how large the SmallVectors
themselves are and whether this is an acceptable tradeoff to e.g. the
size of what will hold the buf.
* DIExprBuf eagerly copies the expression into buffer on
construction/assignment, could also lazily work from the original
expression for the first operation.
---
Patch is 123.65 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/161716.diff
22 Files Affected:
- (modified) llvm/include/llvm/CodeGen/FastISel.h (+3)
- (added) llvm/include/llvm/IR/DIOps.def (+407)
- (added) llvm/include/llvm/IR/DebugInfoCommon.h (+124)
- (added) llvm/include/llvm/IR/DebugInfoExprs.h (+375)
- (modified) llvm/include/llvm/IR/DebugInfoMetadata.h (+11-91)
- (modified) llvm/include/llvm/Transforms/Utils/Local.h (+3-2)
- (modified) llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp (+4-5)
- (modified) llvm/lib/CodeGen/AsmPrinter/DwarfExpression.cpp (+2-2)
- (modified) llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp (+1-2)
- (modified) llvm/lib/CodeGen/MachineInstr.cpp (+6-7)
- (modified) llvm/lib/CodeGen/SelectionDAG/FastISel.cpp (+5)
- (modified) llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp (+11-6)
- (modified) llvm/lib/IR/AsmWriter.cpp (+2-3)
- (modified) llvm/lib/IR/CMakeLists.txt (+2)
- (modified) llvm/lib/IR/DIExpressionOptimizer.cpp (+8-11)
- (added) llvm/lib/IR/DebugInfoCommon.cpp (+57)
- (added) llvm/lib/IR/DebugInfoExprs.cpp (+879)
- (modified) llvm/lib/IR/DebugInfoMetadata.cpp (+104-45)
- (modified) llvm/lib/Transforms/Coroutines/CoroFrame.cpp (+15-11)
- (modified) llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp (+4-8)
- (modified) llvm/lib/Transforms/Scalar/SROA.cpp (+19-14)
- (modified) llvm/lib/Transforms/Utils/Local.cpp (+116-101)
``````````diff
diff --git a/llvm/include/llvm/CodeGen/FastISel.h b/llvm/include/llvm/CodeGen/FastISel.h
index b9d6694a935f6..17f959990c1f4 100644
--- a/llvm/include/llvm/CodeGen/FastISel.h
+++ b/llvm/include/llvm/CodeGen/FastISel.h
@@ -23,6 +23,8 @@
#include "llvm/CodeGenTypes/MachineValueType.h"
#include "llvm/IR/Attributes.h"
#include "llvm/IR/CallingConv.h"
+#include "llvm/IR/DebugInfoExprs.h"
+#include "llvm/IR/DebugInfoMetadata.h"
#include "llvm/IR/DebugLoc.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/InstrTypes.h"
@@ -213,6 +215,7 @@ class FastISel {
const TargetRegisterInfo &TRI;
const TargetLibraryInfo *LibInfo;
bool SkipTargetIndependentISel;
+ DIExprBuf DIBuf;
/// The position of the last instruction for materializing constants
/// for use in the current block. It resets to EmitStartPt when it makes sense
diff --git a/llvm/include/llvm/IR/DIOps.def b/llvm/include/llvm/IR/DIOps.def
new file mode 100644
index 0000000000000..ca0614e20502d
--- /dev/null
+++ b/llvm/include/llvm/IR/DIOps.def
@@ -0,0 +1,407 @@
+//===- llvm/IR/DIOps.def - DIExpression Op definitions ----------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Macros for running through all typed DIExpression operations.
+//
+//===----------------------------------------------------------------------===//
+
+#if !(defined HANDLE_OP || defined HANDLE_OP0 || defined HANDLE_OP1 || \
+ defined HANDLE_OP2)
+#error "Missing macro definition of HANDLE_OP*"
+#endif
+
+#if defined HANDLE_OP && \
+ (defined HANDLE_OP0 || defined HANDLE_OP1 || defined HANDLE_OP2)
+#error "HANDLE_OP cannot be defined together with HANDLE_OP{0,1,2}"
+#endif
+
+// TODO: Update docs to reflect ENCODING param
+
+/// If defined, HANDLE_OP is invoked for each DIExpr operation.
+///
+/// It is invoked with one argument, which is the identifier for the name of
+/// the operation.
+///
+/// If defined, none of HANDLE_OP{0,1,2} may be defined.
+#ifndef HANDLE_OP
+#define HANDLE_OP(NAME, ENCODING)
+#endif
+
+/// If defined, HANDLE_OP0 is invoked once for each DIExpr operation which has
+/// exactly zero arguments.
+///
+/// It is invoked with one argument, which is the identifier for the name of
+/// the operation.
+#ifndef HANDLE_OP0
+#define HANDLE_OP0(NAME, ENCODING) HANDLE_OP(NAME, ENCODING)
+#endif
+
+/// If defined, HANDLE_OP1 is invoked once for each DIExpr operation which has
+/// exactly one argument.
+///
+/// It is invoked with three arguments:
+///
+/// 1. The identifier for the name of the operation.
+/// (2, 3). The type and identifier of the first argument to the operation.
+#ifndef HANDLE_OP1
+#define HANDLE_OP1(NAME, ENCODING, ...) HANDLE_OP(NAME, ENCODING)
+#endif
+
+/// If defined, HANDLE_OP2 is invoked once for each DIExpr operation which has
+/// exactly two arguments.
+///
+/// It is invoked with five arguments:
+///
+/// 1. The identifier for the name of the operation.
+/// (2, 3). The type and identifier of the first argument to the operation.
+/// (4, 5). The type and identifier of the second argument to the operation.
+#ifndef HANDLE_OP2
+#define HANDLE_OP2(NAME, ENCODING, ...) HANDLE_OP(NAME, ENCODING)
+#endif
+
+/// If defined, SEPARATOR is invoked between each invocation of the HANDLE_OP*
+/// macros.
+#ifndef SEPARATOR
+#define SEPARATOR
+#endif
+
+HANDLE_OP1(Addr, ::llvm::dwarf::DW_OP_addr, uint64_t, Value)
+SEPARATOR
+HANDLE_OP0(Deref, ::llvm::dwarf::DW_OP_deref)
+SEPARATOR
+HANDLE_OP1(Const1U, ::llvm::dwarf::DW_OP_const1u, uint8_t, Value)
+SEPARATOR
+HANDLE_OP1(Const1S, ::llvm::dwarf::DW_OP_const1s, int8_t, Value)
+SEPARATOR
+HANDLE_OP1(Const2U, ::llvm::dwarf::DW_OP_const2u, uint16_t, Value)
+SEPARATOR
+HANDLE_OP1(Const2S, ::llvm::dwarf::DW_OP_const2s, int16_t, Value)
+SEPARATOR
+HANDLE_OP1(Const4U, ::llvm::dwarf::DW_OP_const4u, uint32_t, Value)
+SEPARATOR
+HANDLE_OP1(Const4S, ::llvm::dwarf::DW_OP_const4s, int32_t, Value)
+SEPARATOR
+HANDLE_OP1(Const8U, ::llvm::dwarf::DW_OP_const8u, uint64_t, Value)
+SEPARATOR
+HANDLE_OP1(Const8S, ::llvm::dwarf::DW_OP_const8s, int64_t, Value)
+SEPARATOR
+HANDLE_OP1(ConstU, ::llvm::dwarf::DW_OP_constu, uint64_t, Value)
+SEPARATOR
+HANDLE_OP1(ConstS, ::llvm::dwarf::DW_OP_consts, int64_t, Value)
+SEPARATOR
+HANDLE_OP0(Dup, ::llvm::dwarf::DW_OP_dup)
+SEPARATOR
+HANDLE_OP0(Drop, ::llvm::dwarf::DW_OP_drop)
+SEPARATOR
+HANDLE_OP0(Over, ::llvm::dwarf::DW_OP_over)
+SEPARATOR
+HANDLE_OP1(Pick, ::llvm::dwarf::DW_OP_pick, uint64_t, Index)
+SEPARATOR
+HANDLE_OP0(Swap, ::llvm::dwarf::DW_OP_swap)
+SEPARATOR
+HANDLE_OP0(Rot, ::llvm::dwarf::DW_OP_rot)
+SEPARATOR
+HANDLE_OP0(XDeref, ::llvm::dwarf::DW_OP_xderef)
+SEPARATOR
+HANDLE_OP0(Abs, ::llvm::dwarf::DW_OP_abs)
+SEPARATOR
+HANDLE_OP0(And, ::llvm::dwarf::DW_OP_and)
+SEPARATOR
+HANDLE_OP0(Div, ::llvm::dwarf::DW_OP_div)
+SEPARATOR
+HANDLE_OP0(Minus, ::llvm::dwarf::DW_OP_minus)
+SEPARATOR
+HANDLE_OP0(Mod, ::llvm::dwarf::DW_OP_mod)
+SEPARATOR
+HANDLE_OP0(Mul, ::llvm::dwarf::DW_OP_mul)
+SEPARATOR
+HANDLE_OP0(Neg, ::llvm::dwarf::DW_OP_neg)
+SEPARATOR
+HANDLE_OP0(Not, ::llvm::dwarf::DW_OP_not)
+SEPARATOR
+HANDLE_OP0(Or, ::llvm::dwarf::DW_OP_or)
+SEPARATOR
+HANDLE_OP0(Plus, ::llvm::dwarf::DW_OP_plus)
+SEPARATOR
+HANDLE_OP1(PlusUConst, ::llvm::dwarf::DW_OP_plus_uconst, uint64_t, Value)
+SEPARATOR
+HANDLE_OP0(Shl, ::llvm::dwarf::DW_OP_shl)
+SEPARATOR
+HANDLE_OP0(Shr, ::llvm::dwarf::DW_OP_shr)
+SEPARATOR
+HANDLE_OP0(Shra, ::llvm::dwarf::DW_OP_shra)
+SEPARATOR
+HANDLE_OP0(Xor, ::llvm::dwarf::DW_OP_xor)
+SEPARATOR
+HANDLE_OP0(Bra, ::llvm::dwarf::DW_OP_bra)
+SEPARATOR
+HANDLE_OP0(Eq, ::llvm::dwarf::DW_OP_eq)
+SEPARATOR
+HANDLE_OP0(Ge, ::llvm::dwarf::DW_OP_ge)
+SEPARATOR
+HANDLE_OP0(Gt, ::llvm::dwarf::DW_OP_gt)
+SEPARATOR
+HANDLE_OP0(Le, ::llvm::dwarf::DW_OP_le)
+SEPARATOR
+HANDLE_OP0(Lt, ::llvm::dwarf::DW_OP_lt)
+SEPARATOR
+HANDLE_OP0(Ne, ::llvm::dwarf::DW_OP_ne)
+SEPARATOR
+HANDLE_OP1(Skip, ::llvm::dwarf::DW_OP_skip, uint16_t, Bytes)
+SEPARATOR
+HANDLE_OP0(Lit0, ::llvm::dwarf::DW_OP_lit0)
+SEPARATOR
+HANDLE_OP0(Lit1, ::llvm::dwarf::DW_OP_lit1)
+SEPARATOR
+HANDLE_OP0(Lit2, ::llvm::dwarf::DW_OP_lit2)
+SEPARATOR
+HANDLE_OP0(Lit3, ::llvm::dwarf::DW_OP_lit3)
+SEPARATOR
+HANDLE_OP0(Lit4, ::llvm::dwarf::DW_OP_lit4)
+SEPARATOR
+HANDLE_OP0(Lit5, ::llvm::dwarf::DW_OP_lit5)
+SEPARATOR
+HANDLE_OP0(Lit6, ::llvm::dwarf::DW_OP_lit6)
+SEPARATOR
+HANDLE_OP0(Lit7, ::llvm::dwarf::DW_OP_lit7)
+SEPARATOR
+HANDLE_OP0(Lit8, ::llvm::dwarf::DW_OP_lit8)
+SEPARATOR
+HANDLE_OP0(Lit9, ::llvm::dwarf::DW_OP_lit9)
+SEPARATOR
+HANDLE_OP0(Lit10, ::llvm::dwarf::DW_OP_lit10)
+SEPARATOR
+HANDLE_OP0(Lit11, ::llvm::dwarf::DW_OP_lit11)
+SEPARATOR
+HANDLE_OP0(Lit12, ::llvm::dwarf::DW_OP_lit12)
+SEPARATOR
+HANDLE_OP0(Lit13, ::llvm::dwarf::DW_OP_lit13)
+SEPARATOR
+HANDLE_OP0(Lit14, ::llvm::dwarf::DW_OP_lit14)
+SEPARATOR
+HANDLE_OP0(Lit15, ::llvm::dwarf::DW_OP_lit15)
+SEPARATOR
+HANDLE_OP0(Lit16, ::llvm::dwarf::DW_OP_lit16)
+SEPARATOR
+HANDLE_OP0(Lit17, ::llvm::dwarf::DW_OP_lit17)
+SEPARATOR
+HANDLE_OP0(Lit18, ::llvm::dwarf::DW_OP_lit18)
+SEPARATOR
+HANDLE_OP0(Lit19, ::llvm::dwarf::DW_OP_lit19)
+SEPARATOR
+HANDLE_OP0(Lit20, ::llvm::dwarf::DW_OP_lit20)
+SEPARATOR
+HANDLE_OP0(Lit21, ::llvm::dwarf::DW_OP_lit21)
+SEPARATOR
+HANDLE_OP0(Lit22, ::llvm::dwarf::DW_OP_lit22)
+SEPARATOR
+HANDLE_OP0(Lit23, ::llvm::dwarf::DW_OP_lit23)
+SEPARATOR
+HANDLE_OP0(Lit24, ::llvm::dwarf::DW_OP_lit24)
+SEPARATOR
+HANDLE_OP0(Lit25, ::llvm::dwarf::DW_OP_lit25)
+SEPARATOR
+HANDLE_OP0(Lit26, ::llvm::dwarf::DW_OP_lit26)
+SEPARATOR
+HANDLE_OP0(Lit27, ::llvm::dwarf::DW_OP_lit27)
+SEPARATOR
+HANDLE_OP0(Lit28, ::llvm::dwarf::DW_OP_lit28)
+SEPARATOR
+HANDLE_OP0(Lit29, ::llvm::dwarf::DW_OP_lit29)
+SEPARATOR
+HANDLE_OP0(Lit30, ::llvm::dwarf::DW_OP_lit30)
+SEPARATOR
+HANDLE_OP0(Lit31, ::llvm::dwarf::DW_OP_lit31)
+SEPARATOR
+HANDLE_OP0(Reg0, ::llvm::dwarf::DW_OP_reg0)
+SEPARATOR
+HANDLE_OP0(Reg1, ::llvm::dwarf::DW_OP_reg1)
+SEPARATOR
+HANDLE_OP0(Reg2, ::llvm::dwarf::DW_OP_reg2)
+SEPARATOR
+HANDLE_OP0(Reg3, ::llvm::dwarf::DW_OP_reg3)
+SEPARATOR
+HANDLE_OP0(Reg4, ::llvm::dwarf::DW_OP_reg4)
+SEPARATOR
+HANDLE_OP0(Reg5, ::llvm::dwarf::DW_OP_reg5)
+SEPARATOR
+HANDLE_OP0(Reg6, ::llvm::dwarf::DW_OP_reg6)
+SEPARATOR
+HANDLE_OP0(Reg7, ::llvm::dwarf::DW_OP_reg7)
+SEPARATOR
+HANDLE_OP0(Reg8, ::llvm::dwarf::DW_OP_reg8)
+SEPARATOR
+HANDLE_OP0(Reg9, ::llvm::dwarf::DW_OP_reg9)
+SEPARATOR
+HANDLE_OP0(Reg10, ::llvm::dwarf::DW_OP_reg10)
+SEPARATOR
+HANDLE_OP0(Reg11, ::llvm::dwarf::DW_OP_reg11)
+SEPARATOR
+HANDLE_OP0(Reg12, ::llvm::dwarf::DW_OP_reg12)
+SEPARATOR
+HANDLE_OP0(Reg13, ::llvm::dwarf::DW_OP_reg13)
+SEPARATOR
+HANDLE_OP0(Reg14, ::llvm::dwarf::DW_OP_reg14)
+SEPARATOR
+HANDLE_OP0(Reg15, ::llvm::dwarf::DW_OP_reg15)
+SEPARATOR
+HANDLE_OP0(Reg16, ::llvm::dwarf::DW_OP_reg16)
+SEPARATOR
+HANDLE_OP0(Reg17, ::llvm::dwarf::DW_OP_reg17)
+SEPARATOR
+HANDLE_OP0(Reg18, ::llvm::dwarf::DW_OP_reg18)
+SEPARATOR
+HANDLE_OP0(Reg19, ::llvm::dwarf::DW_OP_reg19)
+SEPARATOR
+HANDLE_OP0(Reg20, ::llvm::dwarf::DW_OP_reg20)
+SEPARATOR
+HANDLE_OP0(Reg21, ::llvm::dwarf::DW_OP_reg21)
+SEPARATOR
+HANDLE_OP0(Reg22, ::llvm::dwarf::DW_OP_reg22)
+SEPARATOR
+HANDLE_OP0(Reg23, ::llvm::dwarf::DW_OP_reg23)
+SEPARATOR
+HANDLE_OP0(Reg24, ::llvm::dwarf::DW_OP_reg24)
+SEPARATOR
+HANDLE_OP0(Reg25, ::llvm::dwarf::DW_OP_reg25)
+SEPARATOR
+HANDLE_OP0(Reg26, ::llvm::dwarf::DW_OP_reg26)
+SEPARATOR
+HANDLE_OP0(Reg27, ::llvm::dwarf::DW_OP_reg27)
+SEPARATOR
+HANDLE_OP0(Reg28, ::llvm::dwarf::DW_OP_reg28)
+SEPARATOR
+HANDLE_OP0(Reg29, ::llvm::dwarf::DW_OP_reg29)
+SEPARATOR
+HANDLE_OP0(Reg30, ::llvm::dwarf::DW_OP_reg30)
+SEPARATOR
+HANDLE_OP0(Reg31, ::llvm::dwarf::DW_OP_reg31)
+SEPARATOR
+HANDLE_OP1(BReg0, ::llvm::dwarf::DW_OP_breg0, uint64_t, Offset)
+SEPARATOR
+HANDLE_OP1(BReg1, ::llvm::dwarf::DW_OP_breg1, uint64_t, Offset)
+SEPARATOR
+HANDLE_OP1(BReg2, ::llvm::dwarf::DW_OP_breg2, uint64_t, Offset)
+SEPARATOR
+HANDLE_OP1(BReg3, ::llvm::dwarf::DW_OP_breg3, uint64_t, Offset)
+SEPARATOR
+HANDLE_OP1(BReg4, ::llvm::dwarf::DW_OP_breg4, uint64_t, Offset)
+SEPARATOR
+HANDLE_OP1(BReg5, ::llvm::dwarf::DW_OP_breg5, uint64_t, Offset)
+SEPARATOR
+HANDLE_OP1(BReg6, ::llvm::dwarf::DW_OP_breg6, uint64_t, Offset)
+SEPARATOR
+HANDLE_OP1(BReg7, ::llvm::dwarf::DW_OP_breg7, uint64_t, Offset)
+SEPARATOR
+HANDLE_OP1(BReg8, ::llvm::dwarf::DW_OP_breg8, uint64_t, Offset)
+SEPARATOR
+HANDLE_OP1(BReg9, ::llvm::dwarf::DW_OP_breg9, uint64_t, Offset)
+SEPARATOR
+HANDLE_OP1(BReg10, ::llvm::dwarf::DW_OP_breg10, uint64_t, Offset)
+SEPARATOR
+HANDLE_OP1(BReg11, ::llvm::dwarf::DW_OP_breg11, uint64_t, Offset)
+SEPARATOR
+HANDLE_OP1(BReg12, ::llvm::dwarf::DW_OP_breg12, uint64_t, Offset)
+SEPARATOR
+HANDLE_OP1(BReg13, ::llvm::dwarf::DW_OP_breg13, uint64_t, Offset)
+SEPARATOR
+HANDLE_OP1(BReg14, ::llvm::dwarf::DW_OP_breg14, uint64_t, Offset)
+SEPARATOR
+HANDLE_OP1(BReg15, ::llvm::dwarf::DW_OP_breg15, uint64_t, Offset)
+SEPARATOR
+HANDLE_OP1(BReg16, ::llvm::dwarf::DW_OP_breg16, uint64_t, Offset)
+SEPARATOR
+HANDLE_OP1(BReg17, ::llvm::dwarf::DW_OP_breg17, uint64_t, Offset)
+SEPARATOR
+HANDLE_OP1(BReg18, ::llvm::dwarf::DW_OP_breg18, uint64_t, Offset)
+SEPARATOR
+HANDLE_OP1(BReg19, ::llvm::dwarf::DW_OP_breg19, uint64_t, Offset)
+SEPARATOR
+HANDLE_OP1(BReg20, ::llvm::dwarf::DW_OP_breg20, uint64_t, Offset)
+SEPARATOR
+HANDLE_OP1(BReg21, ::llvm::dwarf::DW_OP_breg21, uint64_t, Offset)
+SEPARATOR
+HANDLE_OP1(BReg22, ::llvm::dwarf::DW_OP_breg22, uint64_t, Offset)
+SEPARATOR
+HANDLE_OP1(BReg23, ::llvm::dwarf::DW_OP_breg23, uint64_t, Offset)
+SEPARATOR
+HANDLE_OP1(BReg24, ::llvm::dwarf::DW_OP_breg24, uint64_t, Offset)
+SEPARATOR
+HANDLE_OP1(BReg25, ::llvm::dwarf::DW_OP_breg25, uint64_t, Offset)
+SEPARATOR
+HANDLE_OP1(BReg26, ::llvm::dwarf::DW_OP_breg26, uint64_t, Offset)
+SEPARATOR
+HANDLE_OP1(BReg27, ::llvm::dwarf::DW_OP_breg27, uint64_t, Offset)
+SEPARATOR
+HANDLE_OP1(BReg28, ::llvm::dwarf::DW_OP_breg28, uint64_t, Offset)
+SEPARATOR
+HANDLE_OP1(BReg29, ::llvm::dwarf::DW_OP_breg29, uint64_t, Offset)
+SEPARATOR
+HANDLE_OP1(BReg30, ::llvm::dwarf::DW_OP_breg30, uint64_t, Offset)
+SEPARATOR
+HANDLE_OP1(BReg31, ::llvm::dwarf::DW_OP_breg31, uint64_t, Offset)
+SEPARATOR
+HANDLE_OP1(RegX, ::llvm::dwarf::DW_OP_regx, uint32_t, Register)
+SEPARATOR
+HANDLE_OP1(FBReg, ::llvm::dwarf::DW_OP_fbreg, uint64_t, Offset)
+SEPARATOR
+HANDLE_OP2(BRegX, ::llvm::dwarf::DW_OP_bregx, uint32_t, Register, uint32_t, Offset)
+SEPARATOR
+HANDLE_OP1(Piece, ::llvm::dwarf::DW_OP_piece, uint64_t, SizeInBytes)
+SEPARATOR
+HANDLE_OP1(DerefSize, ::llvm::dwarf::DW_OP_deref_size, uint8_t, SizeInBytes)
+SEPARATOR
+HANDLE_OP1(XDerefSize, ::llvm::dwarf::DW_OP_xderef_size, uint8_t, SizeInBytes)
+SEPARATOR
+HANDLE_OP0(Nop, ::llvm::dwarf::DW_OP_nop)
+SEPARATOR
+HANDLE_OP0(PushObjectAddress, ::llvm::dwarf::DW_OP_push_object_address)
+SEPARATOR
+HANDLE_OP1(Call2, ::llvm::dwarf::DW_OP_call2, uint16_t, DIEOffset)
+SEPARATOR
+HANDLE_OP1(Call4, ::llvm::dwarf::DW_OP_call4, uint32_t, DIEOffset)
+SEPARATOR
+HANDLE_OP1(CallRef, ::llvm::dwarf::DW_OP_call_ref, uint64_t, DIEOffset)
+SEPARATOR
+HANDLE_OP0(FormTLSAddress, ::llvm::dwarf::DW_OP_form_tls_address)
+SEPARATOR
+HANDLE_OP0(CallFrameCFA, ::llvm::dwarf::DW_OP_call_frame_cfa)
+SEPARATOR
+HANDLE_OP2(BitPiece, ::llvm::dwarf::DW_OP_bit_piece, uint32_t, SizeInBits, uint32_t, OffsetInBits)
+SEPARATOR
+HANDLE_OP0(StackValue, ::llvm::dwarf::DW_OP_stack_value)
+SEPARATOR
+HANDLE_OP1(AddrX, ::llvm::dwarf::DW_OP_addrx, uint64_t, Index)
+SEPARATOR
+HANDLE_OP1(ConstX, ::llvm::dwarf::DW_OP_constx, uint64_t, Index)
+SEPARATOR
+HANDLE_OP1(Convert, ::llvm::dwarf::DW_OP_convert, uint64_t, DIEOffset)
+SEPARATOR
+HANDLE_OP1(Reinterpret, ::llvm::dwarf::DW_OP_reinterpret, uint64_t, DIEOffset)
+SEPARATOR
+HANDLE_OP2(LLVMFragment, ::llvm::dwarf::DW_OP_LLVM_fragment, uint32_t, OffsetInBits, uint32_t, SizeInBits)
+SEPARATOR
+HANDLE_OP2(LLVMConvert, ::llvm::dwarf::DW_OP_LLVM_convert, uint32_t, SizeInBits, uint8_t, Encoding)
+SEPARATOR
+HANDLE_OP1(LLVMTagOffset, ::llvm::dwarf::DW_OP_LLVM_tag_offset, uint64_t, Tag)
+SEPARATOR
+HANDLE_OP1(LLVMEntryValue, ::llvm::dwarf::DW_OP_LLVM_entry_value, uint64_t, Ops)
+SEPARATOR
+HANDLE_OP0(LLVMImplicitPointer, ::llvm::dwarf::DW_OP_LLVM_implicit_pointer)
+SEPARATOR
+HANDLE_OP1(LLVMArg, ::llvm::dwarf::DW_OP_LLVM_arg, uint64_t, Index)
+SEPARATOR
+HANDLE_OP2(LLVMExtractBitsSExt, ::llvm::dwarf::DW_OP_LLVM_extract_bits_sext, uint32_t, OffsetInBits, uint32_t, SizeInBits)
+SEPARATOR
+HANDLE_OP2(LLVMExtractBitsZExt, ::llvm::dwarf::DW_OP_LLVM_extract_bits_zext, uint32_t, OffsetInBits, uint32_t, SizeInBits)
+
+#undef SEPARATOR
+#undef HANDLE_OP2
+#undef HANDLE_OP1
+#undef HANDLE_OP0
+#undef HANDLE_OP
diff --git a/llvm/include/llvm/IR/DebugInfoCommon.h b/llvm/include/llvm/IR/DebugInfoCommon.h
new file mode 100644
index 0000000000000..ed0ce32b0ac8b
--- /dev/null
+++ b/llvm/include/llvm/IR/DebugInfoCommon.h
@@ -0,0 +1,124 @@
+//===- DebugInfoCommon.h - Shared Debug Info Types --------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines small types common to multiple DebugInfo translation units
+// while transitioning to DebugInfoExprs.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_IR_DEBUGINFOCOMMON_H
+#define LLVM_IR_DEBUGINFOCOMMON_H
+
+#include <llvm/ADT/ArrayRef.h>
+#include <llvm/ADT/SmallVector.h>
+#include <llvm/Support/Compiler.h>
+
+#include <cstdint>
+
+namespace llvm {
+
+enum class SignedOrUnsignedConstant { SignedConstant, UnsignedConstant };
+
+/// A lightweight wrapper around an expression operand.
+class ExprOperand {
+ const uint64_t *Op = nullptr;
+
+public:
+ ExprOperand() = default;
+ explicit ExprOperand(const uint64_t *Op) : Op(Op) {}
+
+ const uint64_t *get() const { return Op; }
+
+ /// Get the operand code.
+ uint64_t getOp() const { return *Op; }
+
+ /// Get an argument to the operand.
+ ///
+ /// Never returns the operand itself.
+ uint64_t getArg(unsigned I) const { return Op[I + 1]; }
+
+ unsigned getNumArgs() const { return getSize() - 1; }
+
+ /// Return the size of the operand.
+ ///
+ /// Return the number of elements in the operand (1 + args).
+ LLVM_ABI unsigned getSize() const;
+
+ /// Append the elements of this operand to \p V.
+ void appendToVector(SmallVectorImpl<uint64_t> &V) const {
+ V.append(get(), get() + getSize());
+ }
+};
+
+/// An iterator for expression operands.
+class expr_op_iterator { // NOLINT(readability-identifier-naming)
+ ExprOperand Op;
+
+public:
+ using iterator_category = std::input_iterator_tag;
+ using value_type = ExprOperand;
+ using difference_type = std::ptrdiff_t;
+ using pointer = value_type *;
+ using reference = value_type &;
+
+ using element_iterator = ArrayRef<uint64_t>::iterator;
+
+ expr_op_iterator() = default;
+ explicit expr_op_iterator(element_iterator I) : Op(I) {}
+
+ element_iterator getBase() const { return Op.get(); }
+ const ExprOperand &operator*() const { return Op; }
+ const ExprOperand *operator->() const { return &Op; }
+
+ expr_op_iterator &operator++() {
+ increment();
+ return *this;
+ }
+ expr_op_iterator operator++(int) {
+ expr_op_iterator T(*this);
+ increment();
+ return T;
+ }
+
+ /// Get the next iterator.
+ ///
+ /// \a std::next() doesn't work because this is technically an
+ /// input_iterator, but it's a perfectly valid operation. This is an
+ /// accessor to provide the same functionality.
+ expr_op_iterator getNext() const { return ++expr_op_iterator(*this); }
+
+ bool operator==(const expr_op_iterator &X) const {
+ return getBase() == X.getBase();
+ }
+ bool operator!=(const expr_op_iterator &X) const {
+ return getBase() != X.getBase();
+ }
+
+private:
+ void increment() { Op = ExprOperand(getBase() + Op.getSize()); }
+};
+
+// NOLINTNEXTLINE(readability-identifier-naming)
+static inline expr_op_iterator expr_op_begin(ArrayRef<uint64_t> Elements) {
+ return expr_op_iterator(Elements.begin());
+}
+// NOLINTNEXTLINE(readability-identifier-naming)
+static inline expr_op_iterator expr_op_end(ArrayRef<uint64_t> Elements) {
+ return expr_op_iterator(Elements.end());
+}
+// NOLINTNEXTLINE(readability-identifier-naming)
+static inline iterator_range<expr_op_iterator>
+expr_ops(ArrayRef<uint64_t> Elements) {
+ return {expr_op_begin(Elements), expr_op_end(Elements)};
+}
+
+void appendOffsetImpl(SmallVectorImpl<uint64_t> &Ops, int64_t Offset);
+
+} // end namespace llvm
+
+#endif // LLVM_IR_DEBUGINFOCOMMON_H
diff --git a/llvm/include/llvm/IR/DebugInfoExprs.h b/llvm/include/llvm/IR/DebugInfoExprs.h
new file mode 100644
index 0000000000000..61aff9f65648d
--- /dev/null
+++ b/llvm/include/llvm/IR/DebugInfoExprs.h
@@ -0,0 +1,375 @@
+//===- DebugInfoExprs.h - Debug Info Expression Manipulation ----*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines types for working with DIExpression in a type-safe way.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_IR_DEBUGINFOEXPRS_H
+#define LLVM_IR_DEBUGINFOEXPRS_H
+
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/BinaryFormat/Dwarf.h"
+#include "llvm/IR/DbgVariableFragmentInfo.h"
+#include "llvm/IR/DebugInfoCommon.h"
+#include <cassert>
+#include <climits>
+#include <cstdint>
+#include <optional>
+
+namespace llvm {
+
+class ConstantInt;
+class DIExpression;
+class DIVariable;
+class LLVMContext;
+
+namespace impl {
+class DIExpr;
+} // namespace impl
+class DIExprRef;
+class DIExprBuf;
+
+namespace DIOp {
+
+namespace impl {
+enum class TagT : uint8_t {
+ LLVMEscape = 0,
+#define HANDLE_OP(NAME, ENCODING) NAME
+#define SEPARATOR ,
+#include "llvm/IR/DIOps.def"
+};
+struct CommonInitialSequence {
+ TagT Tag;
+ con...
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/161716
More information about the llvm-commits
mailing list