Skip to content

Commit b9d1642

Browse files
authored
[NFC] Remove UnwindTable dependency on CIE, and FDE (#142520)
This PR is in the direction of separating Unwind table from FDE, and CIE that depends on llvm/Object. To separate, first the runtime dependencies have to be removed, which this commit does that. This is similar to [1](#140096), [2](#139175), and [3](#139326).
1 parent 290fc1e commit b9d1642

File tree

3 files changed

+106
-92
lines changed

3 files changed

+106
-92
lines changed

llvm/include/llvm/DebugInfo/DWARF/DWARFDebugFrame.h

Lines changed: 48 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -311,9 +311,6 @@ class UnwindRow {
311311

312312
LLVM_ABI raw_ostream &operator<<(raw_ostream &OS, const UnwindRow &Row);
313313

314-
class CIE;
315-
class FDE;
316-
317314
/// A class that contains all UnwindRow objects for an FDE or a single unwind
318315
/// row for a CIE. To unwind an address the rows, which are sorted by start
319316
/// address, can be searched to find the UnwindRow with the lowest starting
@@ -325,6 +322,8 @@ class UnwindTable {
325322
using iterator = RowContainer::iterator;
326323
using const_iterator = RowContainer::const_iterator;
327324

325+
UnwindTable(RowContainer &&Rows) : Rows(std::move(Rows)) {}
326+
328327
size_t size() const { return Rows.size(); }
329328
iterator begin() { return Rows.begin(); }
330329
const_iterator begin() const { return Rows.begin(); }
@@ -339,7 +338,7 @@ class UnwindTable {
339338
///
340339
/// \param OS the stream to use for output.
341340
///
342-
/// \param MRI register information that helps emit register names insteead
341+
/// \param MRI register information that helps emit register names instead
343342
/// of raw register numbers.
344343
///
345344
/// \param IsEH true if the DWARF Call Frame Information is from .eh_frame
@@ -352,53 +351,57 @@ class UnwindTable {
352351
LLVM_ABI void dump(raw_ostream &OS, DIDumpOptions DumpOpts,
353352
unsigned IndentLevel = 0) const;
354353

355-
/// Create an UnwindTable from a Common Information Entry (CIE).
356-
///
357-
/// \param Cie The Common Information Entry to extract the table from. The
358-
/// CFIProgram is retrieved from the \a Cie object and used to create the
359-
/// UnwindTable.
360-
///
361-
/// \returns An error if the DWARF Call Frame Information opcodes have state
362-
/// machine errors, or a valid UnwindTable otherwise.
363-
LLVM_ABI static Expected<UnwindTable> create(const CIE *Cie);
364-
365-
/// Create an UnwindTable from a Frame Descriptor Entry (FDE).
366-
///
367-
/// \param Fde The Frame Descriptor Entry to extract the table from. The
368-
/// CFIProgram is retrieved from the \a Fde object and used to create the
369-
/// UnwindTable.
370-
///
371-
/// \returns An error if the DWARF Call Frame Information opcodes have state
372-
/// machine errors, or a valid UnwindTable otherwise.
373-
LLVM_ABI static Expected<UnwindTable> create(const FDE *Fde);
374-
375354
private:
376355
RowContainer Rows;
377-
/// The end address when data is extracted from a FDE. This value will be
378-
/// invalid when a UnwindTable is extracted from a CIE.
379-
std::optional<uint64_t> EndAddress;
380-
381-
/// Parse the information in the CFIProgram and update the CurrRow object
382-
/// that the state machine describes.
383-
///
384-
/// This is an internal implementation that emulates the state machine
385-
/// described in the DWARF Call Frame Information opcodes and will push
386-
/// CurrRow onto the Rows container when needed.
387-
///
388-
/// \param CFIP the CFI program that contains the opcodes from a CIE or FDE.
389-
///
390-
/// \param CurrRow the current row to modify while parsing the state machine.
391-
///
392-
/// \param InitialLocs If non-NULL, we are parsing a FDE and this contains
393-
/// the initial register locations from the CIE. If NULL, then a CIE's
394-
/// opcodes are being parsed and this is not needed. This is used for the
395-
/// DW_CFA_restore and DW_CFA_restore_extended opcodes.
396-
Error parseRows(const CFIProgram &CFIP, UnwindRow &CurrRow,
397-
const RegisterLocations *InitialLocs);
398356
};
399357

358+
/// Parse the information in the CFIProgram and update the CurrRow object
359+
/// that the state machine describes.
360+
///
361+
/// This function emulates the state machine described in the DWARF Call Frame
362+
/// Information opcodes and will push CurrRow onto a RowContainer when needed.
363+
///
364+
/// \param CFIP the CFI program that contains the opcodes from a CIE or FDE.
365+
///
366+
/// \param CurrRow the current row to modify while parsing the state machine.
367+
///
368+
/// \param InitialLocs If non-NULL, we are parsing a FDE and this contains
369+
/// the initial register locations from the CIE. If NULL, then a CIE's
370+
/// opcodes are being parsed and this is not needed. This is used for the
371+
/// DW_CFA_restore and DW_CFA_restore_extended opcodes.
372+
///
373+
/// \returns An error if the DWARF Call Frame Information opcodes have state
374+
/// machine errors, or the accumulated rows otherwise.
375+
LLVM_ABI Expected<UnwindTable::RowContainer>
376+
parseRows(const CFIProgram &CFIP, UnwindRow &CurrRow,
377+
const RegisterLocations *InitialLocs);
378+
400379
LLVM_ABI raw_ostream &operator<<(raw_ostream &OS, const UnwindTable &Rows);
401380

381+
class CIE;
382+
383+
/// Create an UnwindTable from a Common Information Entry (CIE).
384+
///
385+
/// \param Cie The Common Information Entry to extract the table from. The
386+
/// CFIProgram is retrieved from the \a Cie object and used to create the
387+
/// UnwindTable.
388+
///
389+
/// \returns An error if the DWARF Call Frame Information opcodes have state
390+
/// machine errors, or a valid UnwindTable otherwise.
391+
LLVM_ABI Expected<UnwindTable> createUnwindTable(const CIE *Cie);
392+
393+
class FDE;
394+
395+
/// Create an UnwindTable from a Frame Descriptor Entry (FDE).
396+
///
397+
/// \param Fde The Frame Descriptor Entry to extract the table from. The
398+
/// CFIProgram is retrieved from the \a Fde object and used to create the
399+
/// UnwindTable.
400+
///
401+
/// \returns An error if the DWARF Call Frame Information opcodes have state
402+
/// machine errors, or a valid UnwindTable otherwise.
403+
LLVM_ABI Expected<UnwindTable> createUnwindTable(const FDE *Fde);
404+
402405
/// An entry in either debug_frame or eh_frame. This entry can be a CIE or an
403406
/// FDE.
404407
class FrameEntry {

llvm/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp

Lines changed: 30 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include "llvm/Support/Compiler.h"
2020
#include "llvm/Support/DataExtractor.h"
2121
#include "llvm/Support/Errc.h"
22+
#include "llvm/Support/Error.h"
2223
#include "llvm/Support/ErrorHandling.h"
2324
#include "llvm/Support/Format.h"
2425
#include "llvm/Support/raw_ostream.h"
@@ -204,7 +205,7 @@ raw_ostream &llvm::dwarf::operator<<(raw_ostream &OS, const UnwindTable &Rows) {
204205
return OS;
205206
}
206207

207-
Expected<UnwindTable> UnwindTable::create(const FDE *Fde) {
208+
Expected<UnwindTable> llvm::dwarf::createUnwindTable(const FDE *Fde) {
208209
const CIE *Cie = Fde->getLinkedCIE();
209210
if (Cie == nullptr)
210211
return createStringError(errc::invalid_argument,
@@ -213,46 +214,56 @@ Expected<UnwindTable> UnwindTable::create(const FDE *Fde) {
213214

214215
// Rows will be empty if there are no CFI instructions.
215216
if (Cie->cfis().empty() && Fde->cfis().empty())
216-
return UnwindTable();
217+
return UnwindTable({});
217218

218-
UnwindTable UT;
219+
UnwindTable::RowContainer CieRows;
219220
UnwindRow Row;
220221
Row.setAddress(Fde->getInitialLocation());
221-
UT.EndAddress = Fde->getInitialLocation() + Fde->getAddressRange();
222-
if (Error CieError = UT.parseRows(Cie->cfis(), Row, nullptr))
222+
if (Error CieError = parseRows(Cie->cfis(), Row, nullptr).moveInto(CieRows))
223223
return std::move(CieError);
224224
// We need to save the initial locations of registers from the CIE parsing
225225
// in case we run into DW_CFA_restore or DW_CFA_restore_extended opcodes.
226+
UnwindTable::RowContainer FdeRows;
226227
const RegisterLocations InitialLocs = Row.getRegisterLocations();
227-
if (Error FdeError = UT.parseRows(Fde->cfis(), Row, &InitialLocs))
228+
if (Error FdeError =
229+
parseRows(Fde->cfis(), Row, &InitialLocs).moveInto(FdeRows))
228230
return std::move(FdeError);
231+
232+
UnwindTable::RowContainer AllRows;
233+
AllRows.insert(AllRows.end(), CieRows.begin(), CieRows.end());
234+
AllRows.insert(AllRows.end(), FdeRows.begin(), FdeRows.end());
235+
229236
// May be all the CFI instructions were DW_CFA_nop amd Row becomes empty.
230237
// Do not add that to the unwind table.
231238
if (Row.getRegisterLocations().hasLocations() ||
232239
Row.getCFAValue().getLocation() != UnwindLocation::Unspecified)
233-
UT.Rows.push_back(Row);
234-
return UT;
240+
AllRows.push_back(Row);
241+
return UnwindTable(std::move(AllRows));
235242
}
236243

237-
Expected<UnwindTable> UnwindTable::create(const CIE *Cie) {
244+
Expected<UnwindTable> llvm::dwarf::createUnwindTable(const CIE *Cie) {
238245
// Rows will be empty if there are no CFI instructions.
239246
if (Cie->cfis().empty())
240-
return UnwindTable();
247+
return UnwindTable({});
241248

242-
UnwindTable UT;
249+
UnwindTable::RowContainer Rows;
243250
UnwindRow Row;
244-
if (Error CieError = UT.parseRows(Cie->cfis(), Row, nullptr))
251+
if (Error CieError = parseRows(Cie->cfis(), Row, nullptr).moveInto(Rows))
245252
return std::move(CieError);
246253
// May be all the CFI instructions were DW_CFA_nop amd Row becomes empty.
247254
// Do not add that to the unwind table.
248255
if (Row.getRegisterLocations().hasLocations() ||
249256
Row.getCFAValue().getLocation() != UnwindLocation::Unspecified)
250-
UT.Rows.push_back(Row);
251-
return UT;
257+
Rows.push_back(Row);
258+
return UnwindTable(std::move(Rows));
252259
}
253260

254-
Error UnwindTable::parseRows(const CFIProgram &CFIP, UnwindRow &Row,
255-
const RegisterLocations *InitialLocs) {
261+
Expected<UnwindTable::RowContainer>
262+
llvm::dwarf::parseRows(const CFIProgram &CFIP, UnwindRow &Row,
263+
const RegisterLocations *InitialLocs) {
264+
// All the unwinding rows parsed during processing of the CFI program.
265+
UnwindTable::RowContainer Rows;
266+
256267
// State consists of CFA value and register locations.
257268
std::vector<std::pair<UnwindLocation, RegisterLocations>> States;
258269
for (const CFIProgram::Instruction &Inst : CFIP) {
@@ -554,7 +565,7 @@ Error UnwindTable::parseRows(const CFIProgram &CFIP, UnwindRow &Row,
554565
break;
555566
}
556567
}
557-
return Error::success();
568+
return Rows;
558569
}
559570

560571
// Returns the CIE identifier to be used by the requested format.
@@ -607,7 +618,7 @@ void CIE::dump(raw_ostream &OS, DIDumpOptions DumpOpts) const {
607618
/*InitialLocation=*/{});
608619
OS << "\n";
609620

610-
if (Expected<UnwindTable> RowsOrErr = UnwindTable::create(this))
621+
if (Expected<UnwindTable> RowsOrErr = createUnwindTable(this))
611622
RowsOrErr->dump(OS, DumpOpts, 1);
612623
else {
613624
DumpOpts.RecoverableErrorHandler(joinErrors(
@@ -635,7 +646,7 @@ void FDE::dump(raw_ostream &OS, DIDumpOptions DumpOpts) const {
635646
printCFIProgram(CFIs, OS, DumpOpts, /*IndentLevel=*/1, InitialLocation);
636647
OS << "\n";
637648

638-
if (Expected<UnwindTable> RowsOrErr = UnwindTable::create(this))
649+
if (Expected<UnwindTable> RowsOrErr = createUnwindTable(this))
639650
RowsOrErr->dump(OS, DumpOpts, 1);
640651
else {
641652
DumpOpts.RecoverableErrorHandler(joinErrors(

0 commit comments

Comments
 (0)