[llvm] [NFC] Extract Printing portions of DWARFCFIProgram to new files (PR #143762)
via llvm-commits
llvm-commits at lists.llvm.org
Thu Jun 12 16:33:55 PDT 2025
https://github.com/Sterling-Augustine updated https://github.com/llvm/llvm-project/pull/143762
>From 6dc4a10c53d950cb3e8fe451aac3d4c8b00e8246 Mon Sep 17 00:00:00 2001
From: Sterling Augustine <saugustine at google.com>
Date: Wed, 11 Jun 2025 11:05:27 -0700
Subject: [PATCH 1/4] [NFC] Extract Printing portions of DWARFCFIProgram to a
new file
CFIPrograms' most common uses are within debug frames, but it is not
their only use. For example, some assembly writers encode them by hand
into .cfi_escape directives. This PR extracts printing code for them
into its own files, which avoids the need for the main class to
depend on DWARFUnit, sections, and similar.
One in a series of NFC DebugInfo/DWARF refactoring changes to layer it
more cleanly, so that binary CFI parsing can be used from low-level
code, (such as byte strings created via .cfi_escape) without circular
dependencies. The final goal is to make a more limited dwarf library
usable from lower-level code.
---
.../llvm/DebugInfo/DWARF/DWARFCFIPrinter.h | 40 ++++++
.../llvm/DebugInfo/DWARF/DWARFCFIProgram.h | 13 +-
llvm/lib/DebugInfo/DWARF/CMakeLists.txt | 1 +
llvm/lib/DebugInfo/DWARF/DWARFCFIPrinter.cpp | 121 ++++++++++++++++++
llvm/lib/DebugInfo/DWARF/DWARFCFIProgram.cpp | 94 --------------
llvm/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp | 6 +-
llvm/tools/llvm-readobj/DwarfCFIEHPrinter.h | 5 +-
7 files changed, 173 insertions(+), 107 deletions(-)
create mode 100644 llvm/include/llvm/DebugInfo/DWARF/DWARFCFIPrinter.h
create mode 100644 llvm/lib/DebugInfo/DWARF/DWARFCFIPrinter.cpp
diff --git a/llvm/include/llvm/DebugInfo/DWARF/DWARFCFIPrinter.h b/llvm/include/llvm/DebugInfo/DWARF/DWARFCFIPrinter.h
new file mode 100644
index 0000000000000..d51e9a8977c02
--- /dev/null
+++ b/llvm/include/llvm/DebugInfo/DWARF/DWARFCFIPrinter.h
@@ -0,0 +1,40 @@
+//===- DWARFCFIPrinter.h ----------------------------------------*- 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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_DWARF_DWARFCFIPRINTER_H
+#define LLVM_DEBUGINFO_DWARF_DWARFCFIPRINTER_H
+
+#include "llvm/DebugInfo/DWARF/DWARFCFIProgram.h"
+
+namespace llvm {
+
+struct DIDumpOptions;
+
+namespace dwarf {
+
+// This class is separate from CFIProgram to decouple CFIPrograms from the
+// enclosing DWARF dies and type units, which allows using them in lower-level
+// places without build dependencies.
+
+class CFIPrinter {
+public:
+ static void print(const CFIProgram &P, raw_ostream &OS, DIDumpOptions DumpOpts,
+ unsigned IndentLevel, std::optional<uint64_t> Address);
+
+ static void printOperand(raw_ostream &OS, DIDumpOptions DumpOpts,
+ const CFIProgram &P,
+ const CFIProgram::Instruction &Instr,
+ unsigned OperandIdx, uint64_t Operand,
+ std::optional<uint64_t> &Address);
+};
+
+} // end namespace dwarf
+
+} // end namespace llvm
+
+#endif // LLVM_DEBUGINFO_DWARF_DWARFCFIPRINTER_H
diff --git a/llvm/include/llvm/DebugInfo/DWARF/DWARFCFIProgram.h b/llvm/include/llvm/DebugInfo/DWARF/DWARFCFIProgram.h
index 24a0f389470db..b3511a76c543c 100644
--- a/llvm/include/llvm/DebugInfo/DWARF/DWARFCFIProgram.h
+++ b/llvm/include/llvm/DebugInfo/DWARF/DWARFCFIProgram.h
@@ -24,6 +24,9 @@
namespace llvm {
namespace dwarf {
+
+class CFIPrinter;
+
/// Represent a sequence of Call Frame Information instructions that, when read
/// in order, construct a table mapping PC to frame state. This can also be
/// referred to as "CFI rules" in DWARF literature to avoid confusion with
@@ -34,6 +37,7 @@ class CFIProgram {
public:
static constexpr size_t MaxOperands = 3;
typedef SmallVector<uint64_t, MaxOperands> Operands;
+ friend CFIPrinter;
/// An instruction consists of a DWARF CFI opcode and an optional sequence of
/// operands. If it refers to an expression, then this expression has its own
@@ -80,10 +84,6 @@ class CFIProgram {
LLVM_ABI Error parse(DWARFDataExtractor Data, uint64_t *Offset,
uint64_t EndOffset);
- LLVM_ABI void dump(raw_ostream &OS, DIDumpOptions DumpOpts,
- unsigned IndentLevel,
- std::optional<uint64_t> InitialLocation) const;
-
void addInstruction(const Instruction &I) { Instructions.push_back(I); }
/// Get a DWARF CFI call frame string for the given DW_CFA opcode.
@@ -147,11 +147,6 @@ class CFIProgram {
/// Retrieve the array describing the types of operands according to the enum
/// above. This is indexed by opcode.
static ArrayRef<OperandType[MaxOperands]> getOperandTypes();
-
- /// Print \p Opcode's operand number \p OperandIdx which has value \p Operand.
- void printOperand(raw_ostream &OS, DIDumpOptions DumpOpts,
- const Instruction &Instr, unsigned OperandIdx,
- uint64_t Operand, std::optional<uint64_t> &Address) const;
};
} // end namespace dwarf
diff --git a/llvm/lib/DebugInfo/DWARF/CMakeLists.txt b/llvm/lib/DebugInfo/DWARF/CMakeLists.txt
index cc9734f9f22be..86e74110b15ea 100644
--- a/llvm/lib/DebugInfo/DWARF/CMakeLists.txt
+++ b/llvm/lib/DebugInfo/DWARF/CMakeLists.txt
@@ -2,6 +2,7 @@ add_llvm_component_library(LLVMDebugInfoDWARF
DWARFAbbreviationDeclaration.cpp
DWARFAddressRange.cpp
DWARFAcceleratorTable.cpp
+ DWARFCFIPrinter.cpp
DWARFCFIProgram.cpp
DWARFCompileUnit.cpp
DWARFContext.cpp
diff --git a/llvm/lib/DebugInfo/DWARF/DWARFCFIPrinter.cpp b/llvm/lib/DebugInfo/DWARF/DWARFCFIPrinter.cpp
new file mode 100644
index 0000000000000..44261f8ad3139
--- /dev/null
+++ b/llvm/lib/DebugInfo/DWARF/DWARFCFIPrinter.cpp
@@ -0,0 +1,121 @@
+//===- DWARFCFIPrinter.cpp - Print the cfi-portions of .debug_frame -------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/DWARF/DWARFCFIPrinter.h"
+#include "llvm/DebugInfo/DIContext.h"
+#include "llvm/DebugInfo/DWARF/DWARFCFIProgram.h"
+#include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h"
+#include "llvm/Support/Compiler.h"
+#include "llvm/Support/DataExtractor.h"
+#include "llvm/Support/Errc.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/Format.h"
+#include "llvm/Support/raw_ostream.h"
+#include <cassert>
+#include <cinttypes>
+#include <cstdint>
+#include <optional>
+
+using namespace llvm;
+using namespace dwarf;
+
+
+void CFIPrinter::print(const CFIProgram &P, raw_ostream &OS,
+ DIDumpOptions DumpOpts, unsigned IndentLevel,
+ std::optional<uint64_t> Address) {
+ for (const auto &Instr : P) {
+ uint8_t Opcode = Instr.Opcode;
+ OS.indent(2 * IndentLevel);
+ OS << P.callFrameString(Opcode) << ":";
+ for (size_t i = 0; i < Instr.Ops.size(); ++i)
+ printOperand(OS, DumpOpts, P, Instr, i, Instr.Ops[i], Address);
+ OS << '\n';
+ }
+}
+
+static void printRegister(raw_ostream &OS, DIDumpOptions DumpOpts,
+ unsigned RegNum) {
+ if (DumpOpts.GetNameForDWARFReg) {
+ auto RegName = DumpOpts.GetNameForDWARFReg(RegNum, DumpOpts.IsEH);
+ if (!RegName.empty()) {
+ OS << RegName;
+ return;
+ }
+ }
+ OS << "reg" << RegNum;
+}
+
+/// Print \p Opcode's operand number \p OperandIdx which has value \p Operand.
+void CFIPrinter::printOperand(raw_ostream &OS, DIDumpOptions DumpOpts,
+ const CFIProgram &P,
+ const CFIProgram::Instruction &Instr,
+ unsigned OperandIdx, uint64_t Operand,
+ std::optional<uint64_t> &Address) {
+ assert(OperandIdx < CFIProgram::MaxOperands);
+ uint8_t Opcode = Instr.Opcode;
+ CFIProgram::OperandType Type = P.getOperandTypes()[Opcode][OperandIdx];
+
+ switch (Type) {
+ case CFIProgram::OT_Unset: {
+ OS << " Unsupported " << (OperandIdx ? "second" : "first") << " operand to";
+ auto OpcodeName = P.callFrameString(Opcode);
+ if (!OpcodeName.empty())
+ OS << " " << OpcodeName;
+ else
+ OS << format(" Opcode %x", Opcode);
+ break;
+ }
+ case CFIProgram::OT_None:
+ break;
+ case CFIProgram::OT_Address:
+ OS << format(" %" PRIx64, Operand);
+ Address = Operand;
+ break;
+ case CFIProgram::OT_Offset:
+ // The offsets are all encoded in a unsigned form, but in practice
+ // consumers use them signed. It's most certainly legacy due to
+ // the lack of signed variants in the first Dwarf standards.
+ OS << format(" %+" PRId64, int64_t(Operand));
+ break;
+ case CFIProgram::OT_FactoredCodeOffset: // Always Unsigned
+ if (P.CodeAlignmentFactor)
+ OS << format(" %" PRId64, Operand * P.CodeAlignmentFactor);
+ else
+ OS << format(" %" PRId64 "*code_alignment_factor", Operand);
+ if (Address && P.CodeAlignmentFactor) {
+ *Address += Operand * P.CodeAlignmentFactor;
+ OS << format(" to 0x%" PRIx64, *Address);
+ }
+ break;
+ case CFIProgram::OT_SignedFactDataOffset:
+ if (P.DataAlignmentFactor)
+ OS << format(" %" PRId64, int64_t(Operand) * P.DataAlignmentFactor);
+ else
+ OS << format(" %" PRId64 "*data_alignment_factor", int64_t(Operand));
+ break;
+ case CFIProgram::OT_UnsignedFactDataOffset:
+ if (P.DataAlignmentFactor)
+ OS << format(" %" PRId64, Operand * P.DataAlignmentFactor);
+ else
+ OS << format(" %" PRId64 "*data_alignment_factor", Operand);
+ break;
+ case CFIProgram::OT_Register:
+ OS << ' ';
+ printRegister(OS, DumpOpts, Operand);
+ break;
+ case CFIProgram::OT_AddressSpace:
+ OS << format(" in addrspace%" PRId64, Operand);
+ break;
+ case CFIProgram::OT_Expression:
+ assert(Instr.Expression && "missing DWARFExpression object");
+ OS << " ";
+ DWARFExpressionPrinter::print(&Instr.Expression.value(), OS, DumpOpts,
+ nullptr);
+ break;
+ }
+}
diff --git a/llvm/lib/DebugInfo/DWARF/DWARFCFIProgram.cpp b/llvm/lib/DebugInfo/DWARF/DWARFCFIProgram.cpp
index 8d25599627c4a..365b26b98a1e3 100644
--- a/llvm/lib/DebugInfo/DWARF/DWARFCFIProgram.cpp
+++ b/llvm/lib/DebugInfo/DWARF/DWARFCFIProgram.cpp
@@ -23,18 +23,6 @@
using namespace llvm;
using namespace dwarf;
-static void printRegister(raw_ostream &OS, DIDumpOptions DumpOpts,
- unsigned RegNum) {
- if (DumpOpts.GetNameForDWARFReg) {
- auto RegName = DumpOpts.GetNameForDWARFReg(RegNum, DumpOpts.IsEH);
- if (!RegName.empty()) {
- OS << RegName;
- return;
- }
- }
- OS << "reg" << RegNum;
-}
-
// See DWARF standard v3, section 7.23
const uint8_t DWARF_CFI_PRIMARY_OPCODE_MASK = 0xc0;
const uint8_t DWARF_CFI_PRIMARY_OPERAND_MASK = 0x3f;
@@ -361,85 +349,3 @@ CFIProgram::getOperandTypes() {
return ArrayRef<OperandType[MaxOperands]>(&OpTypes[0], DW_CFA_restore + 1);
}
-
-/// Print \p Opcode's operand number \p OperandIdx which has value \p Operand.
-void CFIProgram::printOperand(raw_ostream &OS, DIDumpOptions DumpOpts,
- const Instruction &Instr, unsigned OperandIdx,
- uint64_t Operand,
- std::optional<uint64_t> &Address) const {
- assert(OperandIdx < MaxOperands);
- uint8_t Opcode = Instr.Opcode;
- OperandType Type = getOperandTypes()[Opcode][OperandIdx];
-
- switch (Type) {
- case OT_Unset: {
- OS << " Unsupported " << (OperandIdx ? "second" : "first") << " operand to";
- auto OpcodeName = callFrameString(Opcode);
- if (!OpcodeName.empty())
- OS << " " << OpcodeName;
- else
- OS << format(" Opcode %x", Opcode);
- break;
- }
- case OT_None:
- break;
- case OT_Address:
- OS << format(" %" PRIx64, Operand);
- Address = Operand;
- break;
- case OT_Offset:
- // The offsets are all encoded in a unsigned form, but in practice
- // consumers use them signed. It's most certainly legacy due to
- // the lack of signed variants in the first Dwarf standards.
- OS << format(" %+" PRId64, int64_t(Operand));
- break;
- case OT_FactoredCodeOffset: // Always Unsigned
- if (CodeAlignmentFactor)
- OS << format(" %" PRId64, Operand * CodeAlignmentFactor);
- else
- OS << format(" %" PRId64 "*code_alignment_factor", Operand);
- if (Address && CodeAlignmentFactor) {
- *Address += Operand * CodeAlignmentFactor;
- OS << format(" to 0x%" PRIx64, *Address);
- }
- break;
- case OT_SignedFactDataOffset:
- if (DataAlignmentFactor)
- OS << format(" %" PRId64, int64_t(Operand) * DataAlignmentFactor);
- else
- OS << format(" %" PRId64 "*data_alignment_factor", int64_t(Operand));
- break;
- case OT_UnsignedFactDataOffset:
- if (DataAlignmentFactor)
- OS << format(" %" PRId64, Operand * DataAlignmentFactor);
- else
- OS << format(" %" PRId64 "*data_alignment_factor", Operand);
- break;
- case OT_Register:
- OS << ' ';
- printRegister(OS, DumpOpts, Operand);
- break;
- case OT_AddressSpace:
- OS << format(" in addrspace%" PRId64, Operand);
- break;
- case OT_Expression:
- assert(Instr.Expression && "missing DWARFExpression object");
- OS << " ";
- DWARFExpressionPrinter::print(&Instr.Expression.value(), OS, DumpOpts,
- nullptr);
- break;
- }
-}
-
-void CFIProgram::dump(raw_ostream &OS, DIDumpOptions DumpOpts,
- unsigned IndentLevel,
- std::optional<uint64_t> Address) const {
- for (const auto &Instr : Instructions) {
- uint8_t Opcode = Instr.Opcode;
- OS.indent(2 * IndentLevel);
- OS << callFrameString(Opcode) << ":";
- for (unsigned i = 0; i < Instr.Ops.size(); ++i)
- printOperand(OS, DumpOpts, Instr, i, Instr.Ops[i], Address);
- OS << '\n';
- }
-}
diff --git a/llvm/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp b/llvm/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp
index c46b14b4446f7..4cad90dc1544b 100644
--- a/llvm/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp
+++ b/llvm/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp
@@ -12,6 +12,7 @@
#include "llvm/ADT/StringRef.h"
#include "llvm/BinaryFormat/Dwarf.h"
#include "llvm/DebugInfo/DIContext.h"
+#include "llvm/DebugInfo/DWARF/DWARFCFIPrinter.h"
#include "llvm/DebugInfo/DWARF/DWARFCFIProgram.h"
#include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h"
#include "llvm/DebugInfo/DWARF/DWARFExpression.h"
@@ -602,7 +603,8 @@ void CIE::dump(raw_ostream &OS, DIDumpOptions DumpOpts) const {
OS << "\n";
}
OS << "\n";
- CFIs.dump(OS, DumpOpts, /*IndentLevel=*/1, /*InitialLocation=*/{});
+ CFIPrinter::print(CFIs, OS, DumpOpts, /*IndentLevel=*/1,
+ /*InitialLocation=*/{});
OS << "\n";
if (Expected<UnwindTable> RowsOrErr = UnwindTable::create(this))
@@ -630,7 +632,7 @@ void FDE::dump(raw_ostream &OS, DIDumpOptions DumpOpts) const {
OS << " Format: " << FormatString(IsDWARF64) << "\n";
if (LSDAAddress)
OS << format(" LSDA Address: %016" PRIx64 "\n", *LSDAAddress);
- CFIs.dump(OS, DumpOpts, /*IndentLevel=*/1, InitialLocation);
+ CFIPrinter::print(CFIs, OS, DumpOpts, /*IndentLevel=*/1, InitialLocation);
OS << "\n";
if (Expected<UnwindTable> RowsOrErr = UnwindTable::create(this))
diff --git a/llvm/tools/llvm-readobj/DwarfCFIEHPrinter.h b/llvm/tools/llvm-readobj/DwarfCFIEHPrinter.h
index 94a44e3afccb4..3a063509d0d73 100644
--- a/llvm/tools/llvm-readobj/DwarfCFIEHPrinter.h
+++ b/llvm/tools/llvm-readobj/DwarfCFIEHPrinter.h
@@ -12,6 +12,7 @@
#include "llvm-readobj.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/BinaryFormat/Dwarf.h"
+#include "llvm/DebugInfo/DWARF/DWARFCFIPrinter.h"
#include "llvm/DebugInfo/DWARF/DWARFContext.h"
#include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h"
#include "llvm/DebugInfo/DWARF/DWARFDebugFrame.h"
@@ -228,8 +229,8 @@ void PrinterContext<ELFT>::printEHFrame(const Elf_Shdr *EHFrameShdr) const {
W.indent();
auto DumpOpts = DIDumpOptions();
DumpOpts.IsEH = true;
- Entry.cfis().dump(W.getOStream(), DumpOpts, W.getIndentLevel(),
- InitialLocation);
+ dwarf::CFIPrinter::print(Entry.cfis(), W.getOStream(), DumpOpts,
+ W.getIndentLevel(), InitialLocation);
W.unindent();
W.unindent();
W.getOStream() << "\n";
>From 7b5d5e24100c8b47fbd562a7473bbf8e008c6291 Mon Sep 17 00:00:00 2001
From: Sterling Augustine <saugustine at google.com>
Date: Wed, 11 Jun 2025 11:17:28 -0700
Subject: [PATCH 2/4] Fix formatting.
---
llvm/include/llvm/DebugInfo/DWARF/DWARFCFIPrinter.h | 5 +++--
llvm/lib/DebugInfo/DWARF/DWARFCFIPrinter.cpp | 1 -
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/llvm/include/llvm/DebugInfo/DWARF/DWARFCFIPrinter.h b/llvm/include/llvm/DebugInfo/DWARF/DWARFCFIPrinter.h
index d51e9a8977c02..a7d5d09aff106 100644
--- a/llvm/include/llvm/DebugInfo/DWARF/DWARFCFIPrinter.h
+++ b/llvm/include/llvm/DebugInfo/DWARF/DWARFCFIPrinter.h
@@ -23,8 +23,9 @@ namespace dwarf {
class CFIPrinter {
public:
- static void print(const CFIProgram &P, raw_ostream &OS, DIDumpOptions DumpOpts,
- unsigned IndentLevel, std::optional<uint64_t> Address);
+ static void print(const CFIProgram &P, raw_ostream &OS,
+ DIDumpOptions DumpOpts, unsigned IndentLevel,
+ std::optional<uint64_t> Address);
static void printOperand(raw_ostream &OS, DIDumpOptions DumpOpts,
const CFIProgram &P,
diff --git a/llvm/lib/DebugInfo/DWARF/DWARFCFIPrinter.cpp b/llvm/lib/DebugInfo/DWARF/DWARFCFIPrinter.cpp
index 44261f8ad3139..989f917295f69 100644
--- a/llvm/lib/DebugInfo/DWARF/DWARFCFIPrinter.cpp
+++ b/llvm/lib/DebugInfo/DWARF/DWARFCFIPrinter.cpp
@@ -24,7 +24,6 @@
using namespace llvm;
using namespace dwarf;
-
void CFIPrinter::print(const CFIProgram &P, raw_ostream &OS,
DIDumpOptions DumpOpts, unsigned IndentLevel,
std::optional<uint64_t> Address) {
>From 4dc530993f29fe431bd8fe7f46c12438ef61958c Mon Sep 17 00:00:00 2001
From: Sterling Augustine <saugustine at google.com>
Date: Thu, 12 Jun 2025 08:47:59 -0700
Subject: [PATCH 3/4] Address comments
---
.../llvm/DebugInfo/DWARF/DWARFCFIPrinter.h | 4 +-
.../llvm/DebugInfo/DWARF/DWARFCFIProgram.h | 53 +++++++++----------
llvm/lib/DebugInfo/DWARF/DWARFCFIPrinter.cpp | 22 ++++----
3 files changed, 39 insertions(+), 40 deletions(-)
diff --git a/llvm/include/llvm/DebugInfo/DWARF/DWARFCFIPrinter.h b/llvm/include/llvm/DebugInfo/DWARF/DWARFCFIPrinter.h
index a7d5d09aff106..55a7e38670faa 100644
--- a/llvm/include/llvm/DebugInfo/DWARF/DWARFCFIPrinter.h
+++ b/llvm/include/llvm/DebugInfo/DWARF/DWARFCFIPrinter.h
@@ -24,10 +24,10 @@ namespace dwarf {
class CFIPrinter {
public:
static void print(const CFIProgram &P, raw_ostream &OS,
- DIDumpOptions DumpOpts, unsigned IndentLevel,
+ DIDumpOptions &DumpOpts, unsigned IndentLevel,
std::optional<uint64_t> Address);
- static void printOperand(raw_ostream &OS, DIDumpOptions DumpOpts,
+ static void printOperand(raw_ostream &OS, DIDumpOptions &DumpOpts,
const CFIProgram &P,
const CFIProgram::Instruction &Instr,
unsigned OperandIdx, uint64_t Operand,
diff --git a/llvm/include/llvm/DebugInfo/DWARF/DWARFCFIProgram.h b/llvm/include/llvm/DebugInfo/DWARF/DWARFCFIProgram.h
index b3511a76c543c..b194d22b00923 100644
--- a/llvm/include/llvm/DebugInfo/DWARF/DWARFCFIProgram.h
+++ b/llvm/include/llvm/DebugInfo/DWARF/DWARFCFIProgram.h
@@ -37,7 +37,6 @@ class CFIProgram {
public:
static constexpr size_t MaxOperands = 3;
typedef SmallVector<uint64_t, MaxOperands> Operands;
- friend CFIPrinter;
/// An instruction consists of a DWARF CFI opcode and an optional sequence of
/// operands. If it refers to an expression, then this expression has its own
@@ -89,6 +88,32 @@ class CFIProgram {
/// Get a DWARF CFI call frame string for the given DW_CFA opcode.
LLVM_ABI StringRef callFrameString(unsigned Opcode) const;
+ /// Types of operands to CFI instructions
+ /// In DWARF, this type is implicitly tied to a CFI instruction opcode and
+ /// thus this type doesn't need to be explicitly written to the file (this is
+ /// not a DWARF encoding). The relationship of instrs to operand types can
+ /// be obtained from getOperandTypes() and is only used to simplify
+ /// instruction printing and error messages.
+ enum OperandType {
+ OT_Unset,
+ OT_None,
+ OT_Address,
+ OT_Offset,
+ OT_FactoredCodeOffset,
+ OT_SignedFactDataOffset,
+ OT_UnsignedFactDataOffset,
+ OT_Register,
+ OT_AddressSpace,
+ OT_Expression
+ };
+
+ /// Get the OperandType as a "const char *".
+ static const char *operandTypeString(OperandType OT);
+
+ /// Retrieve the array describing the types of operands according to the enum
+ /// above. This is indexed by opcode.
+ static ArrayRef<OperandType[MaxOperands]> getOperandTypes();
+
private:
std::vector<Instruction> Instructions;
const uint64_t CodeAlignmentFactor;
@@ -121,32 +146,6 @@ class CFIProgram {
Instructions.back().Ops.push_back(Operand2);
Instructions.back().Ops.push_back(Operand3);
}
-
- /// Types of operands to CFI instructions
- /// In DWARF, this type is implicitly tied to a CFI instruction opcode and
- /// thus this type doesn't need to be explicitly written to the file (this is
- /// not a DWARF encoding). The relationship of instrs to operand types can
- /// be obtained from getOperandTypes() and is only used to simplify
- /// instruction printing.
- enum OperandType {
- OT_Unset,
- OT_None,
- OT_Address,
- OT_Offset,
- OT_FactoredCodeOffset,
- OT_SignedFactDataOffset,
- OT_UnsignedFactDataOffset,
- OT_Register,
- OT_AddressSpace,
- OT_Expression
- };
-
- /// Get the OperandType as a "const char *".
- static const char *operandTypeString(OperandType OT);
-
- /// Retrieve the array describing the types of operands according to the enum
- /// above. This is indexed by opcode.
- static ArrayRef<OperandType[MaxOperands]> getOperandTypes();
};
} // end namespace dwarf
diff --git a/llvm/lib/DebugInfo/DWARF/DWARFCFIPrinter.cpp b/llvm/lib/DebugInfo/DWARF/DWARFCFIPrinter.cpp
index 989f917295f69..97155b24dd983 100644
--- a/llvm/lib/DebugInfo/DWARF/DWARFCFIPrinter.cpp
+++ b/llvm/lib/DebugInfo/DWARF/DWARFCFIPrinter.cpp
@@ -25,7 +25,7 @@ using namespace llvm;
using namespace dwarf;
void CFIPrinter::print(const CFIProgram &P, raw_ostream &OS,
- DIDumpOptions DumpOpts, unsigned IndentLevel,
+ DIDumpOptions &DumpOpts, unsigned IndentLevel,
std::optional<uint64_t> Address) {
for (const auto &Instr : P) {
uint8_t Opcode = Instr.Opcode;
@@ -37,7 +37,7 @@ void CFIPrinter::print(const CFIProgram &P, raw_ostream &OS,
}
}
-static void printRegister(raw_ostream &OS, DIDumpOptions DumpOpts,
+static void printRegister(raw_ostream &OS, DIDumpOptions &DumpOpts,
unsigned RegNum) {
if (DumpOpts.GetNameForDWARFReg) {
auto RegName = DumpOpts.GetNameForDWARFReg(RegNum, DumpOpts.IsEH);
@@ -50,7 +50,7 @@ static void printRegister(raw_ostream &OS, DIDumpOptions DumpOpts,
}
/// Print \p Opcode's operand number \p OperandIdx which has value \p Operand.
-void CFIPrinter::printOperand(raw_ostream &OS, DIDumpOptions DumpOpts,
+void CFIPrinter::printOperand(raw_ostream &OS, DIDumpOptions &DumpOpts,
const CFIProgram &P,
const CFIProgram::Instruction &Instr,
unsigned OperandIdx, uint64_t Operand,
@@ -82,24 +82,24 @@ void CFIPrinter::printOperand(raw_ostream &OS, DIDumpOptions DumpOpts,
OS << format(" %+" PRId64, int64_t(Operand));
break;
case CFIProgram::OT_FactoredCodeOffset: // Always Unsigned
- if (P.CodeAlignmentFactor)
- OS << format(" %" PRId64, Operand * P.CodeAlignmentFactor);
+ if (P.codeAlign())
+ OS << format(" %" PRId64, Operand * P.codeAlign());
else
OS << format(" %" PRId64 "*code_alignment_factor", Operand);
- if (Address && P.CodeAlignmentFactor) {
- *Address += Operand * P.CodeAlignmentFactor;
+ if (Address && P.codeAlign()) {
+ *Address += Operand * P.codeAlign();
OS << format(" to 0x%" PRIx64, *Address);
}
break;
case CFIProgram::OT_SignedFactDataOffset:
- if (P.DataAlignmentFactor)
- OS << format(" %" PRId64, int64_t(Operand) * P.DataAlignmentFactor);
+ if (P.dataAlign())
+ OS << format(" %" PRId64, int64_t(Operand) * P.dataAlign());
else
OS << format(" %" PRId64 "*data_alignment_factor", int64_t(Operand));
break;
case CFIProgram::OT_UnsignedFactDataOffset:
- if (P.DataAlignmentFactor)
- OS << format(" %" PRId64, Operand * P.DataAlignmentFactor);
+ if (P.dataAlign())
+ OS << format(" %" PRId64, Operand * P.dataAlign());
else
OS << format(" %" PRId64 "*data_alignment_factor", Operand);
break;
>From f083691938d906873da566e2294cde74f390355f Mon Sep 17 00:00:00 2001
From: Sterling Augustine <saugustine at google.com>
Date: Thu, 12 Jun 2025 16:32:15 -0700
Subject: [PATCH 4/4] Address comments
---
.../llvm/DebugInfo/DWARF/DWARFCFIPrinter.h | 19 ++-------
.../llvm/DebugInfo/DWARF/DWARFCFIProgram.h | 2 -
llvm/lib/DebugInfo/DWARF/DWARFCFIPrinter.cpp | 39 ++++++++++---------
llvm/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp | 6 +--
llvm/tools/llvm-readobj/DwarfCFIEHPrinter.h | 4 +-
5 files changed, 28 insertions(+), 42 deletions(-)
diff --git a/llvm/include/llvm/DebugInfo/DWARF/DWARFCFIPrinter.h b/llvm/include/llvm/DebugInfo/DWARF/DWARFCFIPrinter.h
index 55a7e38670faa..32e8247ac4c22 100644
--- a/llvm/include/llvm/DebugInfo/DWARF/DWARFCFIPrinter.h
+++ b/llvm/include/llvm/DebugInfo/DWARF/DWARFCFIPrinter.h
@@ -17,22 +17,9 @@ struct DIDumpOptions;
namespace dwarf {
-// This class is separate from CFIProgram to decouple CFIPrograms from the
-// enclosing DWARF dies and type units, which allows using them in lower-level
-// places without build dependencies.
-
-class CFIPrinter {
-public:
- static void print(const CFIProgram &P, raw_ostream &OS,
- DIDumpOptions &DumpOpts, unsigned IndentLevel,
- std::optional<uint64_t> Address);
-
- static void printOperand(raw_ostream &OS, DIDumpOptions &DumpOpts,
- const CFIProgram &P,
- const CFIProgram::Instruction &Instr,
- unsigned OperandIdx, uint64_t Operand,
- std::optional<uint64_t> &Address);
-};
+void printCFIProgram(const CFIProgram &P, raw_ostream &OS,
+ const DIDumpOptions &DumpOpts, unsigned IndentLevel,
+ std::optional<uint64_t> Address);
} // end namespace dwarf
diff --git a/llvm/include/llvm/DebugInfo/DWARF/DWARFCFIProgram.h b/llvm/include/llvm/DebugInfo/DWARF/DWARFCFIProgram.h
index b194d22b00923..ad7358c28f16b 100644
--- a/llvm/include/llvm/DebugInfo/DWARF/DWARFCFIProgram.h
+++ b/llvm/include/llvm/DebugInfo/DWARF/DWARFCFIProgram.h
@@ -25,8 +25,6 @@ namespace llvm {
namespace dwarf {
-class CFIPrinter;
-
/// Represent a sequence of Call Frame Information instructions that, when read
/// in order, construct a table mapping PC to frame state. This can also be
/// referred to as "CFI rules" in DWARF literature to avoid confusion with
diff --git a/llvm/lib/DebugInfo/DWARF/DWARFCFIPrinter.cpp b/llvm/lib/DebugInfo/DWARF/DWARFCFIPrinter.cpp
index 97155b24dd983..e52f671e4fa1c 100644
--- a/llvm/lib/DebugInfo/DWARF/DWARFCFIPrinter.cpp
+++ b/llvm/lib/DebugInfo/DWARF/DWARFCFIPrinter.cpp
@@ -24,20 +24,7 @@
using namespace llvm;
using namespace dwarf;
-void CFIPrinter::print(const CFIProgram &P, raw_ostream &OS,
- DIDumpOptions &DumpOpts, unsigned IndentLevel,
- std::optional<uint64_t> Address) {
- for (const auto &Instr : P) {
- uint8_t Opcode = Instr.Opcode;
- OS.indent(2 * IndentLevel);
- OS << P.callFrameString(Opcode) << ":";
- for (size_t i = 0; i < Instr.Ops.size(); ++i)
- printOperand(OS, DumpOpts, P, Instr, i, Instr.Ops[i], Address);
- OS << '\n';
- }
-}
-
-static void printRegister(raw_ostream &OS, DIDumpOptions &DumpOpts,
+static void printRegister(raw_ostream &OS, const DIDumpOptions &DumpOpts,
unsigned RegNum) {
if (DumpOpts.GetNameForDWARFReg) {
auto RegName = DumpOpts.GetNameForDWARFReg(RegNum, DumpOpts.IsEH);
@@ -50,11 +37,11 @@ static void printRegister(raw_ostream &OS, DIDumpOptions &DumpOpts,
}
/// Print \p Opcode's operand number \p OperandIdx which has value \p Operand.
-void CFIPrinter::printOperand(raw_ostream &OS, DIDumpOptions &DumpOpts,
- const CFIProgram &P,
- const CFIProgram::Instruction &Instr,
- unsigned OperandIdx, uint64_t Operand,
- std::optional<uint64_t> &Address) {
+static void printOperand(raw_ostream &OS, const DIDumpOptions &DumpOpts,
+ const CFIProgram &P,
+ const CFIProgram::Instruction &Instr,
+ unsigned OperandIdx, uint64_t Operand,
+ std::optional<uint64_t> &Address) {
assert(OperandIdx < CFIProgram::MaxOperands);
uint8_t Opcode = Instr.Opcode;
CFIProgram::OperandType Type = P.getOperandTypes()[Opcode][OperandIdx];
@@ -118,3 +105,17 @@ void CFIPrinter::printOperand(raw_ostream &OS, DIDumpOptions &DumpOpts,
break;
}
}
+
+void llvm::dwarf::printCFIProgram(const CFIProgram &P, raw_ostream &OS,
+ const DIDumpOptions &DumpOpts,
+ unsigned IndentLevel,
+ std::optional<uint64_t> Address) {
+ for (const auto &Instr : P) {
+ uint8_t Opcode = Instr.Opcode;
+ OS.indent(2 * IndentLevel);
+ OS << P.callFrameString(Opcode) << ":";
+ for (size_t i = 0; i < Instr.Ops.size(); ++i)
+ printOperand(OS, DumpOpts, P, Instr, i, Instr.Ops[i], Address);
+ OS << '\n';
+ }
+}
diff --git a/llvm/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp b/llvm/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp
index 4cad90dc1544b..9dff925073dbe 100644
--- a/llvm/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp
+++ b/llvm/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp
@@ -603,8 +603,8 @@ void CIE::dump(raw_ostream &OS, DIDumpOptions DumpOpts) const {
OS << "\n";
}
OS << "\n";
- CFIPrinter::print(CFIs, OS, DumpOpts, /*IndentLevel=*/1,
- /*InitialLocation=*/{});
+ printCFIProgram(CFIs, OS, DumpOpts, /*IndentLevel=*/1,
+ /*InitialLocation=*/{});
OS << "\n";
if (Expected<UnwindTable> RowsOrErr = UnwindTable::create(this))
@@ -632,7 +632,7 @@ void FDE::dump(raw_ostream &OS, DIDumpOptions DumpOpts) const {
OS << " Format: " << FormatString(IsDWARF64) << "\n";
if (LSDAAddress)
OS << format(" LSDA Address: %016" PRIx64 "\n", *LSDAAddress);
- CFIPrinter::print(CFIs, OS, DumpOpts, /*IndentLevel=*/1, InitialLocation);
+ printCFIProgram(CFIs, OS, DumpOpts, /*IndentLevel=*/1, InitialLocation);
OS << "\n";
if (Expected<UnwindTable> RowsOrErr = UnwindTable::create(this))
diff --git a/llvm/tools/llvm-readobj/DwarfCFIEHPrinter.h b/llvm/tools/llvm-readobj/DwarfCFIEHPrinter.h
index 3a063509d0d73..85c4165de4aa9 100644
--- a/llvm/tools/llvm-readobj/DwarfCFIEHPrinter.h
+++ b/llvm/tools/llvm-readobj/DwarfCFIEHPrinter.h
@@ -229,8 +229,8 @@ void PrinterContext<ELFT>::printEHFrame(const Elf_Shdr *EHFrameShdr) const {
W.indent();
auto DumpOpts = DIDumpOptions();
DumpOpts.IsEH = true;
- dwarf::CFIPrinter::print(Entry.cfis(), W.getOStream(), DumpOpts,
- W.getIndentLevel(), InitialLocation);
+ printCFIProgram(Entry.cfis(), W.getOStream(), DumpOpts, W.getIndentLevel(),
+ InitialLocation);
W.unindent();
W.unindent();
W.getOStream() << "\n";
More information about the llvm-commits
mailing list