Skip to content

Commit 474db6a

Browse files
[NFC] Separate high-level-dependent portions of DWARFExpression (revised) (#143170)
(Revised version of a previous, unreviewed, PR.) Move all expression verification into its only client: DWARFVerifier. Move all printing code (which was a mix of static and member functions) into a separate class. This is one in a series of refactoring PRs to separate dwarf functionality into lower-level pieces usable without object files and sections at build time. The code is already written this way via various "if (section == nullptr)" and similar conditionals. So the functionality itself is needed and exists, but only as a runtime feature. The goal of these refactors is to remove the build-time dependencies, which will allow the existing functionality to be used from lower-level parts of the compiler. Particularly from lib/MC/.... More information at: https://discourse.llvm.org/t/rfc-debuginfo-dwarf-refactor-into-to-lower-and-higher-level-libraries/86665
1 parent d099d95 commit 474db6a

File tree

15 files changed

+198
-130
lines changed

15 files changed

+198
-130
lines changed

lldb/source/Expression/DWARFExpression.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,8 +80,8 @@ void DWARFExpression::DumpLocation(Stream *s, lldb::DescriptionLevel level,
8080
};
8181
llvm::DIDumpOptions DumpOpts;
8282
DumpOpts.GetNameForDWARFReg = GetRegName;
83-
llvm::DWARFExpression(m_data.GetAsLLVM(), m_data.GetAddressByteSize())
84-
.print(s->AsRawOstream(), DumpOpts, nullptr);
83+
llvm::DWARFExpression E(m_data.GetAsLLVM(), m_data.GetAddressByteSize());
84+
llvm::DWARFExpressionPrinter::print(&E, s->AsRawOstream(), DumpOpts, nullptr);
8585
}
8686

8787
RegisterKind DWARFExpression::GetRegisterKind() const { return m_reg_kind; }

lldb/source/Symbol/UnwindPlan.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -87,8 +87,10 @@ static void DumpDWARFExpr(Stream &s, llvm::ArrayRef<uint8_t> expr, Thread *threa
8787
if (auto order_and_width = GetByteOrderAndAddrSize(thread)) {
8888
llvm::DataExtractor data(expr, order_and_width->first == eByteOrderLittle,
8989
order_and_width->second);
90-
llvm::DWARFExpression(data, order_and_width->second, llvm::dwarf::DWARF32)
91-
.print(s.AsRawOstream(), llvm::DIDumpOptions(), nullptr);
90+
llvm::DWARFExpression E(data, order_and_width->second,
91+
llvm::dwarf::DWARF32);
92+
llvm::DWARFExpressionPrinter::print(&E, s.AsRawOstream(),
93+
llvm::DIDumpOptions(), nullptr);
9294
} else
9395
s.PutCString("dwarf-expr");
9496
}

lldb/unittests/Symbol/PostfixExpressionTest.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -159,8 +159,8 @@ static std::string ParseAndGenerateDWARF(llvm::StringRef expr) {
159159

160160
std::string result;
161161
llvm::raw_string_ostream os(result);
162-
llvm::DWARFExpression(extractor, addr_size, llvm::dwarf::DWARF32)
163-
.print(os, llvm::DIDumpOptions(), nullptr);
162+
llvm::DWARFExpression E(extractor, addr_size, llvm::dwarf::DWARF32);
163+
llvm::DWARFExpressionPrinter::print(&E, os, llvm::DIDumpOptions(), nullptr);
164164
return result;
165165
}
166166

lldb/unittests/SymbolFile/NativePDB/PdbFPOProgramToDWARFExpressionTests.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,8 @@ CheckValidProgramTranslation(llvm::StringRef fpo_program,
3939

4040
std::string result;
4141
llvm::raw_string_ostream os(result);
42-
llvm::DWARFExpression(extractor, /*AddressSize=*/4, llvm::dwarf::DWARF32)
43-
.print(os, llvm::DIDumpOptions(), nullptr);
42+
llvm::DWARFExpression E(extractor, /*AddressSize=*/4, llvm::dwarf::DWARF32);
43+
llvm::DWARFExpressionPrinter::print(&E, os, llvm::DIDumpOptions(), nullptr);
4444

4545
// actual check
4646
ASSERT_EQ(expected_dwarf_expression, result);

llvm/include/llvm/DebugInfo/DWARF/DWARFExpression.h

Lines changed: 65 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,9 @@ class DWARFExpression {
7777

7878
private:
7979
friend class DWARFExpression::iterator;
80+
friend class DWARFExpressionPrinter;
81+
friend class DWARFVerifier;
82+
8083
uint8_t Opcode; ///< The Op Opcode, DW_OP_<something>.
8184
Description Desc;
8285
bool Error = false;
@@ -99,11 +102,6 @@ class DWARFExpression {
99102
}
100103
uint64_t getEndOffset() const { return EndOffset; }
101104
bool isError() const { return Error; }
102-
LLVM_ABI bool print(raw_ostream &OS, DIDumpOptions DumpOpts,
103-
const DWARFExpression *Expr, DWARFUnit *U) const;
104-
105-
/// Verify \p Op. Does not affect the return of \a isError().
106-
LLVM_ABI static bool verify(const Operation &Op, DWARFUnit *U);
107105

108106
private:
109107
LLVM_ABI bool extract(DataExtractor Data, uint8_t AddressSize,
@@ -154,28 +152,12 @@ class DWARFExpression {
154152
iterator begin() const { return iterator(this, 0); }
155153
iterator end() const { return iterator(this, Data.getData().size()); }
156154

157-
LLVM_ABI void print(raw_ostream &OS, DIDumpOptions DumpOpts, DWARFUnit *U,
158-
bool IsEH = false) const;
159-
160-
/// Print the expression in a format intended to be compact and useful to a
161-
/// user, but not perfectly unambiguous, or capable of representing every
162-
/// valid DWARF expression. Returns true if the expression was sucessfully
163-
/// printed.
164-
LLVM_ABI bool printCompact(
165-
raw_ostream &OS,
166-
std::function<StringRef(uint64_t RegNum, bool IsEH)> GetNameForDWARFReg =
167-
nullptr);
168-
169-
LLVM_ABI bool verify(DWARFUnit *U);
170-
171155
LLVM_ABI bool operator==(const DWARFExpression &RHS) const;
172156

173157
StringRef getData() const { return Data.getData(); }
174158

175-
LLVM_ABI static bool prettyPrintRegisterOp(DWARFUnit *U, raw_ostream &OS,
176-
DIDumpOptions DumpOpts,
177-
uint8_t Opcode,
178-
const ArrayRef<uint64_t> Operands);
159+
friend class DWARFExpressionPrinter;
160+
friend class DWARFVerifier;
179161

180162
private:
181163
DataExtractor Data;
@@ -187,5 +169,63 @@ inline bool operator==(const DWARFExpression::iterator &LHS,
187169
const DWARFExpression::iterator &RHS) {
188170
return LHS.Expr == RHS.Expr && LHS.Offset == RHS.Offset;
189171
}
190-
}
191-
#endif
172+
173+
// This functionality is separated from the main data structure so that nothing
174+
// in DWARFExpression.cpp needs build-time dependencies on DWARFUnit or other
175+
// higher-level Dwarf structures. This approach creates better layering and
176+
// allows DWARFExpression to be used from code which can't have dependencies on
177+
// those higher-level structures.
178+
179+
class DWARFUnit;
180+
struct DIDumpOptions;
181+
class raw_ostream;
182+
183+
class DWARFExpressionPrinter {
184+
public:
185+
/// Print a Dwarf expression/
186+
/// \param E to be printed
187+
/// \param OS to this stream
188+
/// \param GetNameForDWARFReg callback to return dwarf register name
189+
static void print(const DWARFExpression *E, raw_ostream &OS,
190+
DIDumpOptions DumpOpts, DWARFUnit *U, bool IsEH = false);
191+
192+
/// Print the expression in a format intended to be compact and useful to a
193+
/// user, but not perfectly unambiguous, or capable of representing every
194+
/// valid DWARF expression. Returns true if the expression was sucessfully
195+
/// printed.
196+
///
197+
/// \param E to be printed
198+
/// \param OS to this stream
199+
/// \param GetNameForDWARFReg callback to return dwarf register name
200+
///
201+
/// \returns true if the expression was successfully printed
202+
static bool printCompact(const DWARFExpression *E, raw_ostream &OS,
203+
std::function<StringRef(uint64_t RegNum, bool IsEH)>
204+
GetNameForDWARFReg = nullptr);
205+
206+
/// Pretty print a register opcode and operands.
207+
/// \param U within the context of this Dwarf unit, if any.
208+
/// \param OS to this stream
209+
/// \param DumpOpts with these options
210+
/// \param Opcode to print
211+
/// \param Operands to the opcode
212+
///
213+
/// returns true if the Op was successfully printed
214+
static bool prettyPrintRegisterOp(DWARFUnit *U, raw_ostream &OS,
215+
DIDumpOptions DumpOpts, uint8_t Opcode,
216+
ArrayRef<uint64_t> Operands);
217+
218+
private:
219+
static bool printOp(const DWARFExpression::Operation *Op, raw_ostream &OS,
220+
DIDumpOptions DumpOpts, const DWARFExpression *Expr,
221+
DWARFUnit *U);
222+
223+
static void prettyPrintBaseTypeRef(DWARFUnit *U, raw_ostream &OS,
224+
DIDumpOptions DumpOpts,
225+
ArrayRef<uint64_t> Operands,
226+
unsigned Operand);
227+
};
228+
229+
} // end namespace llvm
230+
231+
#endif // LLVM_DEBUGINFO_DWARF_DWARFEXPRESSION_H

llvm/include/llvm/DebugInfo/DWARF/DWARFVerifier.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#include "llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h"
1515
#include "llvm/DebugInfo/DWARF/DWARFAddressRange.h"
1616
#include "llvm/DebugInfo/DWARF/DWARFDie.h"
17+
#include "llvm/DebugInfo/DWARF/DWARFExpression.h"
1718
#include "llvm/DebugInfo/DWARF/DWARFUnitIndex.h"
1819
#include "llvm/Support/Compiler.h"
1920
#include <cstdint>
@@ -323,6 +324,23 @@ class DWARFVerifier {
323324
void verifyDebugNames(const DWARFSection &AccelSection,
324325
const DataExtractor &StrData);
325326

327+
/// Verify that the the expression is valid within the context of unit U.
328+
///
329+
/// \param E expression to verify.
330+
/// \param U containing DWARFUnit, if any.
331+
///
332+
/// returns true if E is a valid expression.
333+
bool verifyExpression(const DWARFExpression &E, DWARFUnit *U);
334+
335+
/// Verify that the the expression operation is valid within the context of
336+
/// unit U.
337+
///
338+
/// \param Op operation to verify
339+
/// \param U containing DWARFUnit, if any
340+
///
341+
/// returns true if Op is a valid Dwarf operation
342+
bool verifyExpressionOp(const DWARFExpression::Operation &Op, DWARFUnit *U);
343+
326344
public:
327345
LLVM_ABI
328346
DWARFVerifier(raw_ostream &S, DWARFContext &D,

llvm/lib/DebugInfo/DWARF/DWARFCFIProgram.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -425,7 +425,8 @@ void CFIProgram::printOperand(raw_ostream &OS, DIDumpOptions DumpOpts,
425425
case OT_Expression:
426426
assert(Instr.Expression && "missing DWARFExpression object");
427427
OS << " ";
428-
Instr.Expression->print(OS, DumpOpts, nullptr);
428+
DWARFExpressionPrinter::print(&Instr.Expression.value(), OS, DumpOpts,
429+
nullptr);
429430
break;
430431
}
431432
}

llvm/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#include "llvm/DebugInfo/DIContext.h"
1515
#include "llvm/DebugInfo/DWARF/DWARFCFIProgram.h"
1616
#include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h"
17+
#include "llvm/DebugInfo/DWARF/DWARFExpression.h"
1718
#include "llvm/Support/Compiler.h"
1819
#include "llvm/Support/DataExtractor.h"
1920
#include "llvm/Support/Errc.h"
@@ -110,7 +111,8 @@ void UnwindLocation::dump(raw_ostream &OS, DIDumpOptions DumpOpts) const {
110111
OS << " in addrspace" << *AddrSpace;
111112
break;
112113
case DWARFExpr: {
113-
Expr->print(OS, DumpOpts, nullptr);
114+
if (Expr)
115+
DWARFExpressionPrinter::print(&(*Expr), OS, DumpOpts, nullptr);
114116
break;
115117
}
116118
case Constant:

llvm/lib/DebugInfo/DWARF/DWARFDebugLoc.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,8 @@ static void dumpExpression(raw_ostream &OS, DIDumpOptions DumpOpts,
116116
std::optional<dwarf::DwarfFormat> Format;
117117
if (U)
118118
Format = U->getFormat();
119-
DWARFExpression(Extractor, AddressSize, Format).print(OS, DumpOpts, U);
119+
DWARFExpression E(Extractor, AddressSize, Format);
120+
DWARFExpressionPrinter::print(&E, OS, DumpOpts, U);
120121
}
121122

122123
bool DWARFLocationTable::dumpLocationList(

llvm/lib/DebugInfo/DWARF/DWARFDie.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -98,8 +98,8 @@ static void dumpLocationExpr(raw_ostream &OS, const DWARFFormValue &FormValue,
9898
ArrayRef<uint8_t> Expr = *FormValue.getAsBlock();
9999
DataExtractor Data(StringRef((const char *)Expr.data(), Expr.size()),
100100
Ctx.isLittleEndian(), 0);
101-
DWARFExpression(Data, U->getAddressByteSize(), U->getFormParams().Format)
102-
.print(OS, DumpOpts, U);
101+
DWARFExpression DE(Data, U->getAddressByteSize(), U->getFormParams().Format);
102+
DWARFExpressionPrinter::print(&DE, OS, DumpOpts, U);
103103
}
104104

105105
static DWARFDie resolveReferencedType(DWARFDie D, DWARFFormValue F) {

0 commit comments

Comments
 (0)