Skip to content

Commit 7d05067

Browse files
[NFC] Separate high-level-dependent portions of DWARFExpression
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. Dwarf expressions are used in many contexts without Dwarf units and other higher-level Dwarf concepts. The code currently includes conditionals which fall back to defaults if some high-level construct is not available. For example, prettyPrintBaseTypeRef checks U for null. These checks mean that a Dwarf expressions can be used without high-level *run* time* dependencies on Dwarf unit. But as coded they cannot be used without high level *build* time dependencies on Dwarf unit. 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.
1 parent 5936c02 commit 7d05067

File tree

10 files changed

+187
-119
lines changed

10 files changed

+187
-119
lines changed

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

Lines changed: 65 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,9 @@ class DWARFExpression {
7676

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

107105
private:
108106
bool extract(DataExtractor Data, uint8_t AddressSize, uint64_t Offset,
@@ -152,26 +150,12 @@ class DWARFExpression {
152150
iterator begin() const { return iterator(this, 0); }
153151
iterator end() const { return iterator(this, Data.getData().size()); }
154152

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

170155
StringRef getData() const { return Data.getData(); }
171156

172-
static bool prettyPrintRegisterOp(DWARFUnit *U, raw_ostream &OS,
173-
DIDumpOptions DumpOpts, uint8_t Opcode,
174-
const ArrayRef<uint64_t> Operands);
157+
friend class DWARFExpressionPrinter;
158+
friend class DWARFVerifier;
175159

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

323+
/// Verify that the the expression is valid within the context of unit U.
324+
///
325+
/// \param E expression to verify.
326+
/// \param U containing DWARFUnit, if any.
327+
///
328+
/// returns true if E is a valid expression.
329+
bool verifyExpression(const DWARFExpression &E, DWARFUnit *U);
330+
331+
/// Verify that the the expression operation is valid within the context of
332+
/// unit U.
333+
///
334+
/// \param Op operation to verify
335+
/// \param U containing DWARFUnit, if any
336+
///
337+
/// returns true if Op is a valid Dwarf operation
338+
bool verifyExpressionOp(const DWARFExpression::Operation &Op, DWARFUnit *U);
339+
322340
public:
323341
DWARFVerifier(raw_ostream &S, DWARFContext &D,
324342
DIDumpOptions DumpOpts = DIDumpOptions::getForSingleDIE());

llvm/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include "llvm/BinaryFormat/Dwarf.h"
1414
#include "llvm/DebugInfo/DIContext.h"
1515
#include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h"
16+
#include "llvm/DebugInfo/DWARF/DWARFExpression.h"
1617
#include "llvm/Support/Compiler.h"
1718
#include "llvm/Support/DataExtractor.h"
1819
#include "llvm/Support/Errc.h"
@@ -109,7 +110,8 @@ void UnwindLocation::dump(raw_ostream &OS, DIDumpOptions DumpOpts) const {
109110
OS << " in addrspace" << *AddrSpace;
110111
break;
111112
case DWARFExpr: {
112-
Expr->print(OS, DumpOpts, nullptr);
113+
if (Expr)
114+
DWARFExpressionPrinter::print(&(*Expr), OS, DumpOpts, nullptr);
113115
break;
114116
}
115117
case Constant:
@@ -943,7 +945,7 @@ void CFIProgram::printOperand(raw_ostream &OS, DIDumpOptions DumpOpts,
943945
case OT_Expression:
944946
assert(Instr.Expression && "missing DWARFExpression object");
945947
OS << " ";
946-
Instr.Expression->print(OS, DumpOpts, nullptr);
948+
DWARFExpressionPrinter::print(&(*Instr.Expression), OS, DumpOpts, nullptr);
947949
break;
948950
}
949951
}

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)