Remove the dependency between lib/DebugInfoDWARF and MC.

This patch had to be reverted because on gcc 7.5.0 we see an error converting from std::unique_ptr<MCRegisterInfo> to Expected<std::unique_ptr<MCRegisterInfo>> as the return type for the function createRegInfo. This has now been fixed.
This commit is contained in:
Shubham Sandeep Rastogi 2022-10-06 12:15:07 -07:00
parent e66ff2a284
commit d96ade00c3
22 changed files with 231 additions and 211 deletions

View File

@ -69,9 +69,21 @@ void DWARFExpression::UpdateValue(uint64_t const_value,
void DWARFExpression::DumpLocation(Stream *s, lldb::DescriptionLevel level, void DWARFExpression::DumpLocation(Stream *s, lldb::DescriptionLevel level,
ABI *abi) const { ABI *abi) const {
std::function<llvm::StringRef(uint64_t DwarfRegNum, bool IsEH)> GetRegName;
if (abi) {
auto RegInfo = abi->GetMCRegisterInfo();
GetRegName = [RegInfo](uint64_t DwarfRegNum, bool IsEH) -> llvm::StringRef {
if (llvm::Optional<unsigned> LLVMRegNum =
RegInfo.getLLVMRegNum(DwarfRegNum, IsEH))
if (const char *RegName = RegInfo.getName(*LLVMRegNum))
return llvm::StringRef(RegName);
return {};
};
}
auto DumpOpts = llvm::DIDumpOptions();
DumpOpts.GetNameForDWARFReg = GetRegName;
llvm::DWARFExpression(m_data.GetAsLLVM(), m_data.GetAddressByteSize()) llvm::DWARFExpression(m_data.GetAsLLVM(), m_data.GetAddressByteSize())
.print(s->AsRawOstream(), llvm::DIDumpOptions(), .print(s->AsRawOstream(), DumpOpts, nullptr);
abi ? &abi->GetMCRegisterInfo() : nullptr, nullptr);
} }
RegisterKind DWARFExpression::GetRegisterKind() const { return m_reg_kind; } RegisterKind DWARFExpression::GetRegisterKind() const { return m_reg_kind; }

View File

@ -84,7 +84,7 @@ static void DumpDWARFExpr(Stream &s, llvm::ArrayRef<uint8_t> expr, Thread *threa
llvm::DataExtractor data(expr, order_and_width->first == eByteOrderLittle, llvm::DataExtractor data(expr, order_and_width->first == eByteOrderLittle,
order_and_width->second); order_and_width->second);
llvm::DWARFExpression(data, order_and_width->second, llvm::dwarf::DWARF32) llvm::DWARFExpression(data, order_and_width->second, llvm::dwarf::DWARF32)
.print(s.AsRawOstream(), llvm::DIDumpOptions(), nullptr, nullptr); .print(s.AsRawOstream(), llvm::DIDumpOptions(), nullptr);
} else } else
s.PutCString("dwarf-expr"); s.PutCString("dwarf-expr");
} }

View File

@ -159,7 +159,7 @@ static std::string ParseAndGenerateDWARF(llvm::StringRef expr) {
std::string result; std::string result;
llvm::raw_string_ostream os(result); llvm::raw_string_ostream os(result);
llvm::DWARFExpression(extractor, addr_size, llvm::dwarf::DWARF32) llvm::DWARFExpression(extractor, addr_size, llvm::dwarf::DWARF32)
.print(os, llvm::DIDumpOptions(), nullptr, nullptr); .print(os, llvm::DIDumpOptions(), nullptr);
return std::move(os.str()); return std::move(os.str());
} }

View File

@ -40,7 +40,7 @@ CheckValidProgramTranslation(llvm::StringRef fpo_program,
std::string result; std::string result;
llvm::raw_string_ostream os(result); llvm::raw_string_ostream os(result);
llvm::DWARFExpression(extractor, /*AddressSize=*/4, llvm::dwarf::DWARF32) llvm::DWARFExpression(extractor, /*AddressSize=*/4, llvm::dwarf::DWARF32)
.print(os, llvm::DIDumpOptions(), nullptr, nullptr); .print(os, llvm::DIDumpOptions(), nullptr);
// actual check // actual check
ASSERT_EQ(expected_dwarf_expression, os.str()); ASSERT_EQ(expected_dwarf_expression, os.str());

View File

@ -198,6 +198,9 @@ struct DIDumpOptions {
bool SummarizeTypes = false; bool SummarizeTypes = false;
bool Verbose = false; bool Verbose = false;
bool DisplayRawContents = false; bool DisplayRawContents = false;
bool IsEH = false;
std::function<llvm::StringRef(uint64_t DwarfRegNum, bool IsEH)>
GetNameForDWARFReg;
/// Return default option set for printing a single DIE without children. /// Return default option set for printing a single DIE without children.
static DIDumpOptions getForSingleDIE() { static DIDumpOptions getForSingleDIE() {

View File

@ -27,7 +27,6 @@
namespace llvm { namespace llvm {
class MCRegisterInfo;
class MemoryBuffer; class MemoryBuffer;
class AppleAcceleratorTable; class AppleAcceleratorTable;
class DWARFCompileUnit; class DWARFCompileUnit;
@ -81,9 +80,6 @@ class DWARFContext : public DIContext {
std::weak_ptr<DWOFile> DWP; std::weak_ptr<DWOFile> DWP;
bool CheckedForDWP = false; bool CheckedForDWP = false;
std::string DWPName; std::string DWPName;
std::unique_ptr<MCRegisterInfo> RegInfo;
std::function<void(Error)> RecoverableErrorHandler = std::function<void(Error)> RecoverableErrorHandler =
WithColor::defaultErrorHandler; WithColor::defaultErrorHandler;
std::function<void(Error)> WarningHandler = WithColor::defaultWarningHandler; std::function<void(Error)> WarningHandler = WithColor::defaultWarningHandler;
@ -408,8 +404,6 @@ public:
std::shared_ptr<DWARFContext> getDWOContext(StringRef AbsolutePath); std::shared_ptr<DWARFContext> getDWOContext(StringRef AbsolutePath);
const MCRegisterInfo *getRegisterInfo() const { return RegInfo.get(); }
function_ref<void(Error)> getRecoverableErrorHandler() { function_ref<void(Error)> getRecoverableErrorHandler() {
return RecoverableErrorHandler; return RecoverableErrorHandler;
} }
@ -435,11 +429,6 @@ public:
std::function<void(Error)> WarningHandler = std::function<void(Error)> WarningHandler =
WithColor::defaultWarningHandler); WithColor::defaultWarningHandler);
/// Loads register info for the architecture of the provided object file.
/// Improves readability of dumped DWARF expressions. Requires the caller to
/// have initialized the relevant target descriptions.
Error loadRegisterInfo(const object::ObjectFile &Obj);
/// Get address size from CUs. /// Get address size from CUs.
/// TODO: refactor compile_units() to make this const. /// TODO: refactor compile_units() to make this const.
uint8_t getCUAddrSize(); uint8_t getCUAddrSize();

View File

@ -162,7 +162,7 @@ public:
/// instead of from .debug_frame. This is needed for register number /// instead of from .debug_frame. This is needed for register number
/// conversion because some register numbers differ between the two sections /// conversion because some register numbers differ between the two sections
/// for certain architectures like x86. /// for certain architectures like x86.
void dump(raw_ostream &OS, const MCRegisterInfo *MRI, bool IsEH) const; void dump(raw_ostream &OS, DIDumpOptions DumpOpts) const;
bool operator==(const UnwindLocation &RHS) const; bool operator==(const UnwindLocation &RHS) const;
}; };
@ -220,7 +220,7 @@ public:
/// instead of from .debug_frame. This is needed for register number /// instead of from .debug_frame. This is needed for register number
/// conversion because some register numbers differ between the two sections /// conversion because some register numbers differ between the two sections
/// for certain architectures like x86. /// for certain architectures like x86.
void dump(raw_ostream &OS, const MCRegisterInfo *MRI, bool IsEH) const; void dump(raw_ostream &OS, DIDumpOptions DumpOpts) const;
/// Returns true if we have any register locations in this object. /// Returns true if we have any register locations in this object.
bool hasLocations() const { return !Locations.empty(); } bool hasLocations() const { return !Locations.empty(); }
@ -301,7 +301,7 @@ public:
/// ///
/// \param IndentLevel specify the indent level as an integer. The UnwindRow /// \param IndentLevel specify the indent level as an integer. The UnwindRow
/// will be output to the stream preceded by 2 * IndentLevel number of spaces. /// will be output to the stream preceded by 2 * IndentLevel number of spaces.
void dump(raw_ostream &OS, const MCRegisterInfo *MRI, bool IsEH, void dump(raw_ostream &OS, DIDumpOptions DumpOpts,
unsigned IndentLevel = 0) const; unsigned IndentLevel = 0) const;
}; };
@ -346,7 +346,7 @@ public:
/// ///
/// \param IndentLevel specify the indent level as an integer. The UnwindRow /// \param IndentLevel specify the indent level as an integer. The UnwindRow
/// will be output to the stream preceded by 2 * IndentLevel number of spaces. /// will be output to the stream preceded by 2 * IndentLevel number of spaces.
void dump(raw_ostream &OS, const MCRegisterInfo *MRI, bool IsEH, void dump(raw_ostream &OS, DIDumpOptions DumpOpts,
unsigned IndentLevel = 0) const; unsigned IndentLevel = 0) const;
/// Create an UnwindTable from a Common Information Entry (CIE). /// Create an UnwindTable from a Common Information Entry (CIE).
@ -452,8 +452,8 @@ public:
/// where a problem occurred in case an error is returned. /// where a problem occurred in case an error is returned.
Error parse(DWARFDataExtractor Data, uint64_t *Offset, uint64_t EndOffset); Error parse(DWARFDataExtractor Data, uint64_t *Offset, uint64_t EndOffset);
void dump(raw_ostream &OS, DIDumpOptions DumpOpts, const MCRegisterInfo *MRI, void dump(raw_ostream &OS, DIDumpOptions DumpOpts,
bool IsEH, unsigned IndentLevel = 1) const; unsigned IndentLevel = 1) const;
void addInstruction(const Instruction &I) { Instructions.push_back(I); } void addInstruction(const Instruction &I) { Instructions.push_back(I); }
@ -521,7 +521,6 @@ private:
/// Print \p Opcode's operand number \p OperandIdx which has value \p Operand. /// Print \p Opcode's operand number \p OperandIdx which has value \p Operand.
void printOperand(raw_ostream &OS, DIDumpOptions DumpOpts, void printOperand(raw_ostream &OS, DIDumpOptions DumpOpts,
const MCRegisterInfo *MRI, bool IsEH,
const Instruction &Instr, unsigned OperandIdx, const Instruction &Instr, unsigned OperandIdx,
uint64_t Operand) const; uint64_t Operand) const;
}; };
@ -546,8 +545,7 @@ public:
CFIProgram &cfis() { return CFIs; } CFIProgram &cfis() { return CFIs; }
/// Dump the instructions in this CFI fragment /// Dump the instructions in this CFI fragment
virtual void dump(raw_ostream &OS, DIDumpOptions DumpOpts, virtual void dump(raw_ostream &OS, DIDumpOptions DumpOpts) const = 0;
const MCRegisterInfo *MRI, bool IsEH) const = 0;
protected: protected:
const FrameKind Kind; const FrameKind Kind;
@ -601,8 +599,7 @@ public:
uint32_t getLSDAPointerEncoding() const { return LSDAPointerEncoding; } uint32_t getLSDAPointerEncoding() const { return LSDAPointerEncoding; }
void dump(raw_ostream &OS, DIDumpOptions DumpOpts, const MCRegisterInfo *MRI, void dump(raw_ostream &OS, DIDumpOptions DumpOpts) const override;
bool IsEH) const override;
private: private:
/// The following fields are defined in section 6.4.1 of the DWARF standard v4 /// The following fields are defined in section 6.4.1 of the DWARF standard v4
@ -642,8 +639,7 @@ public:
uint64_t getAddressRange() const { return AddressRange; } uint64_t getAddressRange() const { return AddressRange; }
Optional<uint64_t> getLSDAAddress() const { return LSDAAddress; } Optional<uint64_t> getLSDAAddress() const { return LSDAAddress; }
void dump(raw_ostream &OS, DIDumpOptions DumpOpts, const MCRegisterInfo *MRI, void dump(raw_ostream &OS, DIDumpOptions DumpOpts) const override;
bool IsEH) const override;
static bool classof(const FrameEntry *FE) { return FE->getKind() == FK_FDE; } static bool classof(const FrameEntry *FE) { return FE->getKind() == FK_FDE; }
@ -685,7 +681,7 @@ public:
~DWARFDebugFrame(); ~DWARFDebugFrame();
/// Dump the section data into the given stream. /// Dump the section data into the given stream.
void dump(raw_ostream &OS, DIDumpOptions DumpOpts, const MCRegisterInfo *MRI, void dump(raw_ostream &OS, DIDumpOptions DumpOpts,
Optional<uint64_t> Offset) const; Optional<uint64_t> Offset) const;
/// Parse the section from raw data. \p Data is assumed to contain the whole /// Parse the section from raw data. \p Data is assumed to contain the whole

View File

@ -67,9 +67,8 @@ public:
/// updated to point past the end of the current list). /// updated to point past the end of the current list).
bool dumpLocationList(uint64_t *Offset, raw_ostream &OS, bool dumpLocationList(uint64_t *Offset, raw_ostream &OS,
Optional<object::SectionedAddress> BaseAddr, Optional<object::SectionedAddress> BaseAddr,
const MCRegisterInfo *MRI, const DWARFObject &Obj, const DWARFObject &Obj, DWARFUnit *U,
DWARFUnit *U, DIDumpOptions DumpOpts, DIDumpOptions DumpOpts, unsigned Indent) const;
unsigned Indent) const;
Error visitAbsoluteLocationList( Error visitAbsoluteLocationList(
uint64_t Offset, Optional<object::SectionedAddress> BaseAddr, uint64_t Offset, Optional<object::SectionedAddress> BaseAddr,
@ -109,8 +108,7 @@ public:
: DWARFLocationTable(std::move(Data)) {} : DWARFLocationTable(std::move(Data)) {}
/// Print the location lists found within the debug_loc section. /// Print the location lists found within the debug_loc section.
void dump(raw_ostream &OS, const MCRegisterInfo *RegInfo, void dump(raw_ostream &OS, const DWARFObject &Obj, DIDumpOptions DumpOpts,
const DWARFObject &Obj, DIDumpOptions DumpOpts,
Optional<uint64_t> Offset) const; Optional<uint64_t> Offset) const;
Error visitLocationList( Error visitLocationList(
@ -134,8 +132,7 @@ public:
/// Dump all location lists within the given range. /// Dump all location lists within the given range.
void dumpRange(uint64_t StartOffset, uint64_t Size, raw_ostream &OS, void dumpRange(uint64_t StartOffset, uint64_t Size, raw_ostream &OS,
const MCRegisterInfo *MRI, const DWARFObject &Obj, const DWARFObject &Obj, DIDumpOptions DumpOpts);
DIDumpOptions DumpOpts);
protected: protected:
void dumpRawEntry(const DWARFLocationEntry &Entry, raw_ostream &OS, void dumpRawEntry(const DWARFLocationEntry &Entry, raw_ostream &OS,

View File

@ -94,8 +94,7 @@ public:
uint64_t getEndOffset() const { return EndOffset; } uint64_t getEndOffset() const { return EndOffset; }
bool isError() const { return Error; } bool isError() const { return Error; }
bool print(raw_ostream &OS, DIDumpOptions DumpOpts, bool print(raw_ostream &OS, DIDumpOptions DumpOpts,
const DWARFExpression *Expr, const MCRegisterInfo *RegInfo, const DWARFExpression *Expr, DWARFUnit *U) const;
DWARFUnit *U, bool isEH) const;
/// Verify \p Op. Does not affect the return of \a isError(). /// Verify \p Op. Does not affect the return of \a isError().
static bool verify(const Operation &Op, DWARFUnit *U); static bool verify(const Operation &Op, DWARFUnit *U);
@ -148,15 +147,15 @@ public:
iterator begin() const { return iterator(this, 0); } iterator begin() const { return iterator(this, 0); }
iterator end() const { return iterator(this, Data.getData().size()); } iterator end() const { return iterator(this, Data.getData().size()); }
void print(raw_ostream &OS, DIDumpOptions DumpOpts, void print(raw_ostream &OS, DIDumpOptions DumpOpts, DWARFUnit *U) const;
const MCRegisterInfo *RegInfo, DWARFUnit *U,
bool IsEH = false) const;
/// Print the expression in a format intended to be compact and useful to a /// Print the expression in a format intended to be compact and useful to a
/// user, but not perfectly unambiguous, or capable of representing every /// user, but not perfectly unambiguous, or capable of representing every
/// valid DWARF expression. Returns true if the expression was sucessfully /// valid DWARF expression. Returns true if the expression was sucessfully
/// printed. /// printed.
bool printCompact(raw_ostream &OS, const MCRegisterInfo &RegInfo); bool printCompact(raw_ostream &OS,
std::function<StringRef(uint64_t RegNum, bool IsEH)>
GetNameForDWARFReg = nullptr);
bool verify(DWARFUnit *U); bool verify(DWARFUnit *U);

View File

@ -36,6 +36,5 @@ add_llvm_component_library(LLVMDebugInfoDWARF
LINK_COMPONENTS LINK_COMPONENTS
BinaryFormat BinaryFormat
Object Object
MC
Support Support
) )

View File

@ -38,7 +38,6 @@
#include "llvm/DebugInfo/DWARF/DWARFTypeUnit.h" #include "llvm/DebugInfo/DWARF/DWARFTypeUnit.h"
#include "llvm/DebugInfo/DWARF/DWARFUnitIndex.h" #include "llvm/DebugInfo/DWARF/DWARFUnitIndex.h"
#include "llvm/DebugInfo/DWARF/DWARFVerifier.h" #include "llvm/DebugInfo/DWARF/DWARFVerifier.h"
#include "llvm/MC/MCRegisterInfo.h"
#include "llvm/MC/TargetRegistry.h" #include "llvm/MC/TargetRegistry.h"
#include "llvm/Object/Decompressor.h" #include "llvm/Object/Decompressor.h"
#include "llvm/Object/MachO.h" #include "llvm/Object/MachO.h"
@ -309,9 +308,7 @@ DWARFContext::parseMacroOrMacinfo(MacroSecType SectionType) {
} }
static void dumpLoclistsSection(raw_ostream &OS, DIDumpOptions DumpOpts, static void dumpLoclistsSection(raw_ostream &OS, DIDumpOptions DumpOpts,
DWARFDataExtractor Data, DWARFDataExtractor Data, const DWARFObject &Obj,
const MCRegisterInfo *MRI,
const DWARFObject &Obj,
Optional<uint64_t> DumpOffset) { Optional<uint64_t> DumpOffset) {
uint64_t Offset = 0; uint64_t Offset = 0;
@ -330,13 +327,13 @@ static void dumpLoclistsSection(raw_ostream &OS, DIDumpOptions DumpOpts,
if (DumpOffset) { if (DumpOffset) {
if (DumpOffset >= Offset && DumpOffset < EndOffset) { if (DumpOffset >= Offset && DumpOffset < EndOffset) {
Offset = *DumpOffset; Offset = *DumpOffset;
Loc.dumpLocationList(&Offset, OS, /*BaseAddr=*/None, MRI, Obj, nullptr, Loc.dumpLocationList(&Offset, OS, /*BaseAddr=*/None, Obj, nullptr,
DumpOpts, /*Indent=*/0); DumpOpts, /*Indent=*/0);
OS << "\n"; OS << "\n";
return; return;
} }
} else { } else {
Loc.dumpRange(Offset, EndOffset - Offset, OS, MRI, Obj, DumpOpts); Loc.dumpRange(Offset, EndOffset - Offset, OS, Obj, DumpOpts);
} }
Offset = EndOffset; Offset = EndOffset;
} }
@ -424,21 +421,21 @@ void DWARFContext::dump(
if (const auto *Off = shouldDump(Explicit, ".debug_loc", DIDT_ID_DebugLoc, if (const auto *Off = shouldDump(Explicit, ".debug_loc", DIDT_ID_DebugLoc,
DObj->getLocSection().Data)) { DObj->getLocSection().Data)) {
getDebugLoc()->dump(OS, getRegisterInfo(), *DObj, LLDumpOpts, *Off); getDebugLoc()->dump(OS, *DObj, LLDumpOpts, *Off);
} }
if (const auto *Off = if (const auto *Off =
shouldDump(Explicit, ".debug_loclists", DIDT_ID_DebugLoclists, shouldDump(Explicit, ".debug_loclists", DIDT_ID_DebugLoclists,
DObj->getLoclistsSection().Data)) { DObj->getLoclistsSection().Data)) {
DWARFDataExtractor Data(*DObj, DObj->getLoclistsSection(), isLittleEndian(), DWARFDataExtractor Data(*DObj, DObj->getLoclistsSection(), isLittleEndian(),
0); 0);
dumpLoclistsSection(OS, LLDumpOpts, Data, getRegisterInfo(), *DObj, *Off); dumpLoclistsSection(OS, LLDumpOpts, Data, *DObj, *Off);
} }
if (const auto *Off = if (const auto *Off =
shouldDump(ExplicitDWO, ".debug_loclists.dwo", DIDT_ID_DebugLoclists, shouldDump(ExplicitDWO, ".debug_loclists.dwo", DIDT_ID_DebugLoclists,
DObj->getLoclistsDWOSection().Data)) { DObj->getLoclistsDWOSection().Data)) {
DWARFDataExtractor Data(*DObj, DObj->getLoclistsDWOSection(), DWARFDataExtractor Data(*DObj, DObj->getLoclistsDWOSection(),
isLittleEndian(), 0); isLittleEndian(), 0);
dumpLoclistsSection(OS, LLDumpOpts, Data, getRegisterInfo(), *DObj, *Off); dumpLoclistsSection(OS, LLDumpOpts, Data, *DObj, *Off);
} }
if (const auto *Off = if (const auto *Off =
@ -450,12 +447,11 @@ void DWARFContext::dump(
if (*Off) { if (*Off) {
uint64_t Offset = **Off; uint64_t Offset = **Off;
Loc.dumpLocationList(&Offset, OS, Loc.dumpLocationList(&Offset, OS,
/*BaseAddr=*/None, getRegisterInfo(), *DObj, nullptr, /*BaseAddr=*/None, *DObj, nullptr, LLDumpOpts,
LLDumpOpts, /*Indent=*/0); /*Indent=*/0);
OS << "\n"; OS << "\n";
} else { } else {
Loc.dumpRange(0, Data.getData().size(), OS, getRegisterInfo(), *DObj, Loc.dumpRange(0, Data.getData().size(), OS, *DObj, LLDumpOpts);
LLDumpOpts);
} }
} }
@ -463,7 +459,7 @@ void DWARFContext::dump(
shouldDump(Explicit, ".debug_frame", DIDT_ID_DebugFrame, shouldDump(Explicit, ".debug_frame", DIDT_ID_DebugFrame,
DObj->getFrameSection().Data)) { DObj->getFrameSection().Data)) {
if (Expected<const DWARFDebugFrame *> DF = getDebugFrame()) if (Expected<const DWARFDebugFrame *> DF = getDebugFrame())
(*DF)->dump(OS, DumpOpts, getRegisterInfo(), *Off); (*DF)->dump(OS, DumpOpts, *Off);
else else
RecoverableErrorHandler(DF.takeError()); RecoverableErrorHandler(DF.takeError());
} }
@ -472,7 +468,7 @@ void DWARFContext::dump(
shouldDump(Explicit, ".eh_frame", DIDT_ID_DebugFrame, shouldDump(Explicit, ".eh_frame", DIDT_ID_DebugFrame,
DObj->getEHFrameSection().Data)) { DObj->getEHFrameSection().Data)) {
if (Expected<const DWARFDebugFrame *> DF = getEHFrame()) if (Expected<const DWARFDebugFrame *> DF = getEHFrame())
(*DF)->dump(OS, DumpOpts, getRegisterInfo(), *Off); (*DF)->dump(OS, DumpOpts, *Off);
else else
RecoverableErrorHandler(DF.takeError()); RecoverableErrorHandler(DF.takeError());
} }
@ -2019,23 +2015,6 @@ DWARFContext::create(const StringMap<std::unique_ptr<MemoryBuffer>> &Sections,
std::move(DObj), "", RecoverableErrorHandler, WarningHandler); std::move(DObj), "", RecoverableErrorHandler, WarningHandler);
} }
Error DWARFContext::loadRegisterInfo(const object::ObjectFile &Obj) {
// Detect the architecture from the object file. We usually don't need OS
// info to lookup a target and create register info.
Triple TT;
TT.setArch(Triple::ArchType(Obj.getArch()));
TT.setVendor(Triple::UnknownVendor);
TT.setOS(Triple::UnknownOS);
std::string TargetLookupError;
const Target *TheTarget =
TargetRegistry::lookupTarget(TT.str(), TargetLookupError);
if (!TargetLookupError.empty())
return createStringError(errc::invalid_argument,
TargetLookupError.c_str());
RegInfo.reset(TheTarget->createMCRegInfo(TT.str()));
return Error::success();
}
uint8_t DWARFContext::getCUAddrSize() { uint8_t DWARFContext::getCUAddrSize() {
// In theory, different compile units may have different address byte // In theory, different compile units may have different address byte
// sizes, but for simplicity we just use the address byte size of the // sizes, but for simplicity we just use the address byte size of the

View File

@ -14,7 +14,6 @@
#include "llvm/BinaryFormat/Dwarf.h" #include "llvm/BinaryFormat/Dwarf.h"
#include "llvm/DebugInfo/DIContext.h" #include "llvm/DebugInfo/DIContext.h"
#include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h" #include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h"
#include "llvm/MC/MCRegisterInfo.h"
#include "llvm/Support/Compiler.h" #include "llvm/Support/Compiler.h"
#include "llvm/Support/DataExtractor.h" #include "llvm/Support/DataExtractor.h"
#include "llvm/Support/Errc.h" #include "llvm/Support/Errc.h"
@ -29,16 +28,15 @@
using namespace llvm; using namespace llvm;
using namespace dwarf; using namespace dwarf;
static void printRegister(raw_ostream &OS, const MCRegisterInfo *MRI, bool IsEH, static void printRegister(raw_ostream &OS, DIDumpOptions DumpOpts,
unsigned RegNum) { unsigned RegNum) {
if (MRI) { if (DumpOpts.GetNameForDWARFReg) {
if (Optional<unsigned> LLVMRegNum = MRI->getLLVMRegNum(RegNum, IsEH)) { auto RegName = DumpOpts.GetNameForDWARFReg(RegNum, DumpOpts.IsEH);
if (const char *RegName = MRI->getName(*LLVMRegNum)) { if (!RegName.empty()) {
OS << RegName; OS << RegName;
return; return;
} }
} }
}
OS << "reg" << RegNum; OS << "reg" << RegNum;
} }
@ -80,8 +78,7 @@ UnwindLocation UnwindLocation::createAtDWARFExpression(DWARFExpression Expr) {
return {Expr, true}; return {Expr, true};
} }
void UnwindLocation::dump(raw_ostream &OS, const MCRegisterInfo *MRI, void UnwindLocation::dump(raw_ostream &OS, DIDumpOptions DumpOpts) const {
bool IsEH) const {
if (Dereference) if (Dereference)
OS << '['; OS << '[';
switch (Kind) { switch (Kind) {
@ -103,7 +100,7 @@ void UnwindLocation::dump(raw_ostream &OS, const MCRegisterInfo *MRI,
OS << Offset; OS << Offset;
break; break;
case RegPlusOffset: case RegPlusOffset:
printRegister(OS, MRI, IsEH, RegNum); printRegister(OS, DumpOpts, RegNum);
if (Offset == 0 && !AddrSpace) if (Offset == 0 && !AddrSpace)
break; break;
if (Offset >= 0) if (Offset >= 0)
@ -112,9 +109,10 @@ void UnwindLocation::dump(raw_ostream &OS, const MCRegisterInfo *MRI,
if (AddrSpace) if (AddrSpace)
OS << " in addrspace" << *AddrSpace; OS << " in addrspace" << *AddrSpace;
break; break;
case DWARFExpr: case DWARFExpr: {
Expr->print(OS, DIDumpOptions(), MRI, nullptr, IsEH); Expr->print(OS, DumpOpts, nullptr);
break; break;
}
case Constant: case Constant:
OS << Offset; OS << Offset;
break; break;
@ -125,7 +123,8 @@ void UnwindLocation::dump(raw_ostream &OS, const MCRegisterInfo *MRI,
raw_ostream &llvm::dwarf::operator<<(raw_ostream &OS, raw_ostream &llvm::dwarf::operator<<(raw_ostream &OS,
const UnwindLocation &UL) { const UnwindLocation &UL) {
UL.dump(OS, nullptr, false); auto DumpOpts = DIDumpOptions();
UL.dump(OS, DumpOpts);
return OS; return OS;
} }
@ -150,53 +149,55 @@ bool UnwindLocation::operator==(const UnwindLocation &RHS) const {
return false; return false;
} }
void RegisterLocations::dump(raw_ostream &OS, const MCRegisterInfo *MRI, void RegisterLocations::dump(raw_ostream &OS, DIDumpOptions DumpOpts) const {
bool IsEH) const {
bool First = true; bool First = true;
for (const auto &RegLocPair : Locations) { for (const auto &RegLocPair : Locations) {
if (First) if (First)
First = false; First = false;
else else
OS << ", "; OS << ", ";
printRegister(OS, MRI, IsEH, RegLocPair.first); printRegister(OS, DumpOpts, RegLocPair.first);
OS << '='; OS << '=';
RegLocPair.second.dump(OS, MRI, IsEH); RegLocPair.second.dump(OS, DumpOpts);
} }
} }
raw_ostream &llvm::dwarf::operator<<(raw_ostream &OS, raw_ostream &llvm::dwarf::operator<<(raw_ostream &OS,
const RegisterLocations &RL) { const RegisterLocations &RL) {
RL.dump(OS, nullptr, false); auto DumpOpts = DIDumpOptions();
RL.dump(OS, DumpOpts);
return OS; return OS;
} }
void UnwindRow::dump(raw_ostream &OS, const MCRegisterInfo *MRI, bool IsEH, void UnwindRow::dump(raw_ostream &OS, DIDumpOptions DumpOpts,
unsigned IndentLevel) const { unsigned IndentLevel) const {
OS.indent(2 * IndentLevel); OS.indent(2 * IndentLevel);
if (hasAddress()) if (hasAddress())
OS << format("0x%" PRIx64 ": ", *Address); OS << format("0x%" PRIx64 ": ", *Address);
OS << "CFA="; OS << "CFA=";
CFAValue.dump(OS, MRI, IsEH); CFAValue.dump(OS, DumpOpts);
if (RegLocs.hasLocations()) { if (RegLocs.hasLocations()) {
OS << ": "; OS << ": ";
RegLocs.dump(OS, MRI, IsEH); RegLocs.dump(OS, DumpOpts);
} }
OS << "\n"; OS << "\n";
} }
raw_ostream &llvm::dwarf::operator<<(raw_ostream &OS, const UnwindRow &Row) { raw_ostream &llvm::dwarf::operator<<(raw_ostream &OS, const UnwindRow &Row) {
Row.dump(OS, nullptr, false, 0); auto DumpOpts = DIDumpOptions();
Row.dump(OS, DumpOpts, 0);
return OS; return OS;
} }
void UnwindTable::dump(raw_ostream &OS, const MCRegisterInfo *MRI, bool IsEH, void UnwindTable::dump(raw_ostream &OS, DIDumpOptions DumpOpts,
unsigned IndentLevel) const { unsigned IndentLevel) const {
for (const UnwindRow &Row : Rows) for (const UnwindRow &Row : Rows)
Row.dump(OS, MRI, IsEH, IndentLevel); Row.dump(OS, DumpOpts, IndentLevel);
} }
raw_ostream &llvm::dwarf::operator<<(raw_ostream &OS, const UnwindTable &Rows) { raw_ostream &llvm::dwarf::operator<<(raw_ostream &OS, const UnwindTable &Rows) {
Rows.dump(OS, nullptr, false, 0); auto DumpOpts = DIDumpOptions();
Rows.dump(OS, DumpOpts, 0);
return OS; return OS;
} }
@ -853,7 +854,6 @@ CFIProgram::getOperandTypes() {
/// Print \p Opcode's operand number \p OperandIdx which has value \p Operand. /// Print \p Opcode's operand number \p OperandIdx which has value \p Operand.
void CFIProgram::printOperand(raw_ostream &OS, DIDumpOptions DumpOpts, void CFIProgram::printOperand(raw_ostream &OS, DIDumpOptions DumpOpts,
const MCRegisterInfo *MRI, bool IsEH,
const Instruction &Instr, unsigned OperandIdx, const Instruction &Instr, unsigned OperandIdx,
uint64_t Operand) const { uint64_t Operand) const {
assert(OperandIdx < MaxOperands); assert(OperandIdx < MaxOperands);
@ -901,7 +901,7 @@ void CFIProgram::printOperand(raw_ostream &OS, DIDumpOptions DumpOpts,
break; break;
case OT_Register: case OT_Register:
OS << ' '; OS << ' ';
printRegister(OS, MRI, IsEH, Operand); printRegister(OS, DumpOpts, Operand);
break; break;
case OT_AddressSpace: case OT_AddressSpace:
OS << format(" in addrspace%" PRId64, Operand); OS << format(" in addrspace%" PRId64, Operand);
@ -909,20 +909,19 @@ void CFIProgram::printOperand(raw_ostream &OS, DIDumpOptions DumpOpts,
case OT_Expression: case OT_Expression:
assert(Instr.Expression && "missing DWARFExpression object"); assert(Instr.Expression && "missing DWARFExpression object");
OS << " "; OS << " ";
Instr.Expression->print(OS, DumpOpts, MRI, nullptr, IsEH); Instr.Expression->print(OS, DumpOpts, nullptr);
break; break;
} }
} }
void CFIProgram::dump(raw_ostream &OS, DIDumpOptions DumpOpts, void CFIProgram::dump(raw_ostream &OS, DIDumpOptions DumpOpts,
const MCRegisterInfo *MRI, bool IsEH,
unsigned IndentLevel) const { unsigned IndentLevel) const {
for (const auto &Instr : Instructions) { for (const auto &Instr : Instructions) {
uint8_t Opcode = Instr.Opcode; uint8_t Opcode = Instr.Opcode;
OS.indent(2 * IndentLevel); OS.indent(2 * IndentLevel);
OS << callFrameString(Opcode) << ":"; OS << callFrameString(Opcode) << ":";
for (unsigned i = 0; i < Instr.Ops.size(); ++i) for (unsigned i = 0; i < Instr.Ops.size(); ++i)
printOperand(OS, DumpOpts, MRI, IsEH, Instr, i, Instr.Ops[i]); printOperand(OS, DumpOpts, Instr, i, Instr.Ops[i]);
OS << '\n'; OS << '\n';
} }
} }
@ -939,21 +938,20 @@ constexpr uint64_t getCIEId(bool IsDWARF64, bool IsEH) {
return DW_CIE_ID; return DW_CIE_ID;
} }
void CIE::dump(raw_ostream &OS, DIDumpOptions DumpOpts, void CIE::dump(raw_ostream &OS, DIDumpOptions DumpOpts) const {
const MCRegisterInfo *MRI, bool IsEH) const {
// A CIE with a zero length is a terminator entry in the .eh_frame section. // A CIE with a zero length is a terminator entry in the .eh_frame section.
if (IsEH && Length == 0) { if (DumpOpts.IsEH && Length == 0) {
OS << format("%08" PRIx64, Offset) << " ZERO terminator\n"; OS << format("%08" PRIx64, Offset) << " ZERO terminator\n";
return; return;
} }
OS << format("%08" PRIx64, Offset) OS << format("%08" PRIx64, Offset)
<< format(" %0*" PRIx64, IsDWARF64 ? 16 : 8, Length) << format(" %0*" PRIx64, IsDWARF64 ? 16 : 8, Length)
<< format(" %0*" PRIx64, IsDWARF64 && !IsEH ? 16 : 8, << format(" %0*" PRIx64, IsDWARF64 && !DumpOpts.IsEH ? 16 : 8,
getCIEId(IsDWARF64, IsEH)) getCIEId(IsDWARF64, DumpOpts.IsEH))
<< " CIE\n" << " CIE\n"
<< " Format: " << FormatString(IsDWARF64) << "\n"; << " Format: " << FormatString(IsDWARF64) << "\n";
if (IsEH && Version != 1) if (DumpOpts.IsEH && Version != 1)
OS << "WARNING: unsupported CIE version\n"; OS << "WARNING: unsupported CIE version\n";
OS << format(" Version: %d\n", Version) OS << format(" Version: %d\n", Version)
<< " Augmentation: \"" << Augmentation << "\"\n"; << " Augmentation: \"" << Augmentation << "\"\n";
@ -974,11 +972,11 @@ void CIE::dump(raw_ostream &OS, DIDumpOptions DumpOpts,
OS << "\n"; OS << "\n";
} }
OS << "\n"; OS << "\n";
CFIs.dump(OS, DumpOpts, MRI, IsEH); CFIs.dump(OS, DumpOpts);
OS << "\n"; OS << "\n";
if (Expected<UnwindTable> RowsOrErr = UnwindTable::create(this)) if (Expected<UnwindTable> RowsOrErr = UnwindTable::create(this))
RowsOrErr->dump(OS, MRI, IsEH, 1); RowsOrErr->dump(OS, DumpOpts, 1);
else { else {
DumpOpts.RecoverableErrorHandler(joinErrors( DumpOpts.RecoverableErrorHandler(joinErrors(
createStringError(errc::invalid_argument, createStringError(errc::invalid_argument,
@ -988,11 +986,10 @@ void CIE::dump(raw_ostream &OS, DIDumpOptions DumpOpts,
OS << "\n"; OS << "\n";
} }
void FDE::dump(raw_ostream &OS, DIDumpOptions DumpOpts, void FDE::dump(raw_ostream &OS, DIDumpOptions DumpOpts) const {
const MCRegisterInfo *MRI, bool IsEH) const {
OS << format("%08" PRIx64, Offset) OS << format("%08" PRIx64, Offset)
<< format(" %0*" PRIx64, IsDWARF64 ? 16 : 8, Length) << format(" %0*" PRIx64, IsDWARF64 ? 16 : 8, Length)
<< format(" %0*" PRIx64, IsDWARF64 && !IsEH ? 16 : 8, CIEPointer) << format(" %0*" PRIx64, IsDWARF64 && !DumpOpts.IsEH ? 16 : 8, CIEPointer)
<< " FDE cie="; << " FDE cie=";
if (LinkedCIE) if (LinkedCIE)
OS << format("%08" PRIx64, LinkedCIE->getOffset()); OS << format("%08" PRIx64, LinkedCIE->getOffset());
@ -1003,11 +1000,11 @@ void FDE::dump(raw_ostream &OS, DIDumpOptions DumpOpts,
OS << " Format: " << FormatString(IsDWARF64) << "\n"; OS << " Format: " << FormatString(IsDWARF64) << "\n";
if (LSDAAddress) if (LSDAAddress)
OS << format(" LSDA Address: %016" PRIx64 "\n", *LSDAAddress); OS << format(" LSDA Address: %016" PRIx64 "\n", *LSDAAddress);
CFIs.dump(OS, DumpOpts, MRI, IsEH); CFIs.dump(OS, DumpOpts);
OS << "\n"; OS << "\n";
if (Expected<UnwindTable> RowsOrErr = UnwindTable::create(this)) if (Expected<UnwindTable> RowsOrErr = UnwindTable::create(this))
RowsOrErr->dump(OS, MRI, IsEH, 1); RowsOrErr->dump(OS, DumpOpts, 1);
else { else {
DumpOpts.RecoverableErrorHandler(joinErrors( DumpOpts.RecoverableErrorHandler(joinErrors(
createStringError(errc::invalid_argument, createStringError(errc::invalid_argument,
@ -1242,15 +1239,15 @@ FrameEntry *DWARFDebugFrame::getEntryAtOffset(uint64_t Offset) const {
} }
void DWARFDebugFrame::dump(raw_ostream &OS, DIDumpOptions DumpOpts, void DWARFDebugFrame::dump(raw_ostream &OS, DIDumpOptions DumpOpts,
const MCRegisterInfo *MRI,
Optional<uint64_t> Offset) const { Optional<uint64_t> Offset) const {
DumpOpts.IsEH = IsEH;
if (Offset) { if (Offset) {
if (auto *Entry = getEntryAtOffset(*Offset)) if (auto *Entry = getEntryAtOffset(*Offset))
Entry->dump(OS, DumpOpts, MRI, IsEH); Entry->dump(OS, DumpOpts);
return; return;
} }
OS << "\n"; OS << "\n";
for (const auto &Entry : Entries) for (const auto &Entry : Entries)
Entry->dump(OS, DumpOpts, MRI, IsEH); Entry->dump(OS, DumpOpts);
} }

View File

@ -110,19 +110,17 @@ DWARFLocationInterpreter::Interpret(const DWARFLocationEntry &E) {
static void dumpExpression(raw_ostream &OS, DIDumpOptions DumpOpts, static void dumpExpression(raw_ostream &OS, DIDumpOptions DumpOpts,
ArrayRef<uint8_t> Data, bool IsLittleEndian, ArrayRef<uint8_t> Data, bool IsLittleEndian,
unsigned AddressSize, const MCRegisterInfo *MRI, unsigned AddressSize, DWARFUnit *U) {
DWARFUnit *U) {
DWARFDataExtractor Extractor(Data, IsLittleEndian, AddressSize); DWARFDataExtractor Extractor(Data, IsLittleEndian, AddressSize);
// Note. We do not pass any format to DWARFExpression, even if the // Note. We do not pass any format to DWARFExpression, even if the
// corresponding unit is known. For now, there is only one operation, // corresponding unit is known. For now, there is only one operation,
// DW_OP_call_ref, which depends on the format; it is rarely used, and // DW_OP_call_ref, which depends on the format; it is rarely used, and
// is unexpected in location tables. // is unexpected in location tables.
DWARFExpression(Extractor, AddressSize).print(OS, DumpOpts, MRI, U); DWARFExpression(Extractor, AddressSize).print(OS, DumpOpts, U);
} }
bool DWARFLocationTable::dumpLocationList(uint64_t *Offset, raw_ostream &OS, bool DWARFLocationTable::dumpLocationList(uint64_t *Offset, raw_ostream &OS,
Optional<SectionedAddress> BaseAddr, Optional<SectionedAddress> BaseAddr,
const MCRegisterInfo *MRI,
const DWARFObject &Obj, DWARFUnit *U, const DWARFObject &Obj, DWARFUnit *U,
DIDumpOptions DumpOpts, DIDumpOptions DumpOpts,
unsigned Indent) const { unsigned Indent) const {
@ -158,7 +156,7 @@ bool DWARFLocationTable::dumpLocationList(uint64_t *Offset, raw_ostream &OS,
E.Kind != dwarf::DW_LLE_end_of_list) { E.Kind != dwarf::DW_LLE_end_of_list) {
OS << ": "; OS << ": ";
dumpExpression(OS, DumpOpts, E.Loc, Data.isLittleEndian(), dumpExpression(OS, DumpOpts, E.Loc, Data.isLittleEndian(),
Data.getAddressSize(), MRI, U); Data.getAddressSize(), U);
} }
return true; return true;
}); });
@ -184,13 +182,13 @@ Error DWARFLocationTable::visitAbsoluteLocationList(
}); });
} }
void DWARFDebugLoc::dump(raw_ostream &OS, const MCRegisterInfo *MRI, void DWARFDebugLoc::dump(raw_ostream &OS, const DWARFObject &Obj,
const DWARFObject &Obj, DIDumpOptions DumpOpts, DIDumpOptions DumpOpts,
Optional<uint64_t> DumpOffset) const { Optional<uint64_t> DumpOffset) const {
auto BaseAddr = None; auto BaseAddr = None;
unsigned Indent = 12; unsigned Indent = 12;
if (DumpOffset) { if (DumpOffset) {
dumpLocationList(&*DumpOffset, OS, BaseAddr, MRI, Obj, nullptr, DumpOpts, dumpLocationList(&*DumpOffset, OS, BaseAddr, Obj, nullptr, DumpOpts,
Indent); Indent);
} else { } else {
uint64_t Offset = 0; uint64_t Offset = 0;
@ -200,7 +198,7 @@ void DWARFDebugLoc::dump(raw_ostream &OS, const MCRegisterInfo *MRI,
OS << Separator; OS << Separator;
Separator = "\n"; Separator = "\n";
CanContinue = dumpLocationList(&Offset, OS, BaseAddr, MRI, Obj, nullptr, CanContinue = dumpLocationList(&Offset, OS, BaseAddr, Obj, nullptr,
DumpOpts, Indent); DumpOpts, Indent);
OS << '\n'; OS << '\n';
} }
@ -387,8 +385,7 @@ void DWARFDebugLoclists::dumpRawEntry(const DWARFLocationEntry &Entry,
} }
void DWARFDebugLoclists::dumpRange(uint64_t StartOffset, uint64_t Size, void DWARFDebugLoclists::dumpRange(uint64_t StartOffset, uint64_t Size,
raw_ostream &OS, const MCRegisterInfo *MRI, raw_ostream &OS, const DWARFObject &Obj,
const DWARFObject &Obj,
DIDumpOptions DumpOpts) { DIDumpOptions DumpOpts) {
if (!Data.isValidOffsetForDataOfSize(StartOffset, Size)) { if (!Data.isValidOffsetForDataOfSize(StartOffset, Size)) {
OS << "Invalid dump range\n"; OS << "Invalid dump range\n";
@ -401,8 +398,8 @@ void DWARFDebugLoclists::dumpRange(uint64_t StartOffset, uint64_t Size,
OS << Separator; OS << Separator;
Separator = "\n"; Separator = "\n";
CanContinue = dumpLocationList(&Offset, OS, /*BaseAddr=*/None, MRI, Obj, CanContinue = dumpLocationList(&Offset, OS, /*BaseAddr=*/None, Obj, nullptr,
nullptr, DumpOpts, /*Indent=*/12); DumpOpts, /*Indent=*/12);
OS << '\n'; OS << '\n';
} }
} }

View File

@ -76,7 +76,6 @@ static void dumpLocationList(raw_ostream &OS, const DWARFFormValue &FormValue,
assert(FormValue.isFormClass(DWARFFormValue::FC_SectionOffset) && assert(FormValue.isFormClass(DWARFFormValue::FC_SectionOffset) &&
"bad FORM for location list"); "bad FORM for location list");
DWARFContext &Ctx = U->getContext(); DWARFContext &Ctx = U->getContext();
const MCRegisterInfo *MRI = Ctx.getRegisterInfo();
uint64_t Offset = *FormValue.getAsSectionOffset(); uint64_t Offset = *FormValue.getAsSectionOffset();
if (FormValue.getForm() == DW_FORM_loclistx) { if (FormValue.getForm() == DW_FORM_loclistx) {
@ -87,9 +86,8 @@ static void dumpLocationList(raw_ostream &OS, const DWARFFormValue &FormValue,
else else
return; return;
} }
U->getLocationTable().dumpLocationList(&Offset, OS, U->getBaseAddress(), MRI, U->getLocationTable().dumpLocationList(
Ctx.getDWARFObj(), U, DumpOpts, &Offset, OS, U->getBaseAddress(), Ctx.getDWARFObj(), U, DumpOpts, Indent);
Indent);
} }
static void dumpLocationExpr(raw_ostream &OS, const DWARFFormValue &FormValue, static void dumpLocationExpr(raw_ostream &OS, const DWARFFormValue &FormValue,
@ -99,12 +97,11 @@ static void dumpLocationExpr(raw_ostream &OS, const DWARFFormValue &FormValue,
FormValue.isFormClass(DWARFFormValue::FC_Exprloc)) && FormValue.isFormClass(DWARFFormValue::FC_Exprloc)) &&
"bad FORM for location expression"); "bad FORM for location expression");
DWARFContext &Ctx = U->getContext(); DWARFContext &Ctx = U->getContext();
const MCRegisterInfo *MRI = Ctx.getRegisterInfo();
ArrayRef<uint8_t> Expr = *FormValue.getAsBlock(); ArrayRef<uint8_t> Expr = *FormValue.getAsBlock();
DataExtractor Data(StringRef((const char *)Expr.data(), Expr.size()), DataExtractor Data(StringRef((const char *)Expr.data(), Expr.size()),
Ctx.isLittleEndian(), 0); Ctx.isLittleEndian(), 0);
DWARFExpression(Data, U->getAddressByteSize(), U->getFormParams().Format) DWARFExpression(Data, U->getAddressByteSize(), U->getFormParams().Format)
.print(OS, DumpOpts, MRI, U); .print(OS, DumpOpts, U);
} }
static DWARFDie resolveReferencedType(DWARFDie D, DWARFFormValue F) { static DWARFDie resolveReferencedType(DWARFDie D, DWARFFormValue F) {

View File

@ -8,7 +8,6 @@
#include "llvm/DebugInfo/DWARF/DWARFExpression.h" #include "llvm/DebugInfo/DWARF/DWARFExpression.h"
#include "llvm/DebugInfo/DWARF/DWARFUnit.h" #include "llvm/DebugInfo/DWARF/DWARFUnit.h"
#include "llvm/MC/MCRegisterInfo.h"
#include "llvm/Support/Format.h" #include "llvm/Support/Format.h"
#include <cassert> #include <cassert>
#include <cstdint> #include <cstdint>
@ -227,9 +226,8 @@ static void prettyPrintBaseTypeRef(DWARFUnit *U, raw_ostream &OS,
static bool prettyPrintRegisterOp(DWARFUnit *U, raw_ostream &OS, static bool prettyPrintRegisterOp(DWARFUnit *U, raw_ostream &OS,
DIDumpOptions DumpOpts, uint8_t Opcode, DIDumpOptions DumpOpts, uint8_t Opcode,
const uint64_t Operands[2], const uint64_t Operands[2]) {
const MCRegisterInfo *MRI, bool isEH) { if (!DumpOpts.GetNameForDWARFReg)
if (!MRI)
return false; return false;
uint64_t DwarfRegNum; uint64_t DwarfRegNum;
@ -243,27 +241,25 @@ static bool prettyPrintRegisterOp(DWARFUnit *U, raw_ostream &OS,
else else
DwarfRegNum = Opcode - DW_OP_reg0; DwarfRegNum = Opcode - DW_OP_reg0;
if (Optional<unsigned> LLVMRegNum = MRI->getLLVMRegNum(DwarfRegNum, isEH)) { auto RegName = DumpOpts.GetNameForDWARFReg(DwarfRegNum, DumpOpts.IsEH);
if (const char *RegName = MRI->getName(*LLVMRegNum)) { if (!RegName.empty()) {
if ((Opcode >= DW_OP_breg0 && Opcode <= DW_OP_breg31) || if ((Opcode >= DW_OP_breg0 && Opcode <= DW_OP_breg31) ||
Opcode == DW_OP_bregx) Opcode == DW_OP_bregx)
OS << format(" %s%+" PRId64, RegName, Operands[OpNum]); OS << ' ' << RegName << format("%+" PRId64, Operands[OpNum]);
else else
OS << ' ' << RegName; OS << ' ' << RegName.data();
if (Opcode == DW_OP_regval_type) if (Opcode == DW_OP_regval_type)
prettyPrintBaseTypeRef(U, OS, DumpOpts, Operands, 1); prettyPrintBaseTypeRef(U, OS, DumpOpts, Operands, 1);
return true; return true;
} }
}
return false; return false;
} }
bool DWARFExpression::Operation::print(raw_ostream &OS, DIDumpOptions DumpOpts, bool DWARFExpression::Operation::print(raw_ostream &OS, DIDumpOptions DumpOpts,
const DWARFExpression *Expr, const DWARFExpression *Expr,
const MCRegisterInfo *RegInfo, DWARFUnit *U) const {
DWARFUnit *U, bool isEH) const {
if (Error) { if (Error) {
OS << "<decoding error>"; OS << "<decoding error>";
return false; return false;
@ -277,7 +273,7 @@ bool DWARFExpression::Operation::print(raw_ostream &OS, DIDumpOptions DumpOpts,
(Opcode >= DW_OP_reg0 && Opcode <= DW_OP_reg31) || (Opcode >= DW_OP_reg0 && Opcode <= DW_OP_reg31) ||
Opcode == DW_OP_bregx || Opcode == DW_OP_regx || Opcode == DW_OP_bregx || Opcode == DW_OP_regx ||
Opcode == DW_OP_regval_type) Opcode == DW_OP_regval_type)
if (prettyPrintRegisterOp(U, OS, DumpOpts, Opcode, Operands, RegInfo, isEH)) if (prettyPrintRegisterOp(U, OS, DumpOpts, Opcode, Operands))
return true; return true;
for (unsigned Operand = 0; Operand < 2; ++Operand) { for (unsigned Operand = 0; Operand < 2; ++Operand) {
@ -323,15 +319,14 @@ bool DWARFExpression::Operation::print(raw_ostream &OS, DIDumpOptions DumpOpts,
} }
void DWARFExpression::print(raw_ostream &OS, DIDumpOptions DumpOpts, void DWARFExpression::print(raw_ostream &OS, DIDumpOptions DumpOpts,
const MCRegisterInfo *RegInfo, DWARFUnit *U, DWARFUnit *U) const {
bool IsEH) const {
uint32_t EntryValExprSize = 0; uint32_t EntryValExprSize = 0;
uint64_t EntryValStartOffset = 0; uint64_t EntryValStartOffset = 0;
if (Data.getData().empty()) if (Data.getData().empty())
OS << "<empty>"; OS << "<empty>";
for (auto &Op : *this) { for (auto &Op : *this) {
if (!Op.print(OS, DumpOpts, this, RegInfo, U, IsEH)) { if (!Op.print(OS, DumpOpts, this, U)) {
uint64_t FailOffset = Op.getEndOffset(); uint64_t FailOffset = Op.getEndOffset();
while (FailOffset < Data.getData().size()) while (FailOffset < Data.getData().size())
OS << format(" %02x", Data.getU8(&FailOffset)); OS << format(" %02x", Data.getU8(&FailOffset));
@ -402,9 +397,11 @@ struct PrintedExpr {
PrintedExpr(ExprKind K = Address) : Kind(K) {} PrintedExpr(ExprKind K = Address) : Kind(K) {}
}; };
static bool printCompactDWARFExpr(raw_ostream &OS, DWARFExpression::iterator I, static bool printCompactDWARFExpr(
raw_ostream &OS, DWARFExpression::iterator I,
const DWARFExpression::iterator E, const DWARFExpression::iterator E,
const MCRegisterInfo &MRI) { std::function<StringRef(uint64_t RegNum, bool IsEH)> GetNameForDWARFReg =
nullptr) {
SmallVector<PrintedExpr, 4> Stack; SmallVector<PrintedExpr, 4> Stack;
while (I != E) { while (I != E) {
@ -415,25 +412,21 @@ static bool printCompactDWARFExpr(raw_ostream &OS, DWARFExpression::iterator I,
// DW_OP_regx: A register, with the register num given as an operand. // DW_OP_regx: A register, with the register num given as an operand.
// Printed as the plain register name. // Printed as the plain register name.
uint64_t DwarfRegNum = Op.getRawOperand(0); uint64_t DwarfRegNum = Op.getRawOperand(0);
Optional<unsigned> LLVMRegNum = MRI.getLLVMRegNum(DwarfRegNum, false); auto RegName = GetNameForDWARFReg(DwarfRegNum, false);
if (!LLVMRegNum) { if (RegName.empty())
OS << "<unknown register " << DwarfRegNum << ">";
return false; return false;
}
raw_svector_ostream S(Stack.emplace_back(PrintedExpr::Value).String); raw_svector_ostream S(Stack.emplace_back(PrintedExpr::Value).String);
S << MRI.getName(*LLVMRegNum); S << RegName;
break; break;
} }
case dwarf::DW_OP_bregx: { case dwarf::DW_OP_bregx: {
int DwarfRegNum = Op.getRawOperand(0); int DwarfRegNum = Op.getRawOperand(0);
int64_t Offset = Op.getRawOperand(1); int64_t Offset = Op.getRawOperand(1);
Optional<unsigned> LLVMRegNum = MRI.getLLVMRegNum(DwarfRegNum, false); auto RegName = GetNameForDWARFReg(DwarfRegNum, false);
if (!LLVMRegNum) { if (RegName.empty())
OS << "<unknown register " << DwarfRegNum << ">";
return false; return false;
}
raw_svector_ostream S(Stack.emplace_back().String); raw_svector_ostream S(Stack.emplace_back().String);
S << MRI.getName(*LLVMRegNum); S << RegName;
if (Offset) if (Offset)
S << format("%+" PRId64, Offset); S << format("%+" PRId64, Offset);
break; break;
@ -447,7 +440,7 @@ static bool printCompactDWARFExpr(raw_ostream &OS, DWARFExpression::iterator I,
++I; ++I;
raw_svector_ostream S(Stack.emplace_back().String); raw_svector_ostream S(Stack.emplace_back().String);
S << "entry("; S << "entry(";
printCompactDWARFExpr(S, I, SubExprEnd, MRI); printCompactDWARFExpr(S, I, SubExprEnd, GetNameForDWARFReg);
S << ")"; S << ")";
I = SubExprEnd; I = SubExprEnd;
continue; continue;
@ -464,24 +457,20 @@ static bool printCompactDWARFExpr(raw_ostream &OS, DWARFExpression::iterator I,
// DW_OP_reg<N>: A register, with the register num implied by the // DW_OP_reg<N>: A register, with the register num implied by the
// opcode. Printed as the plain register name. // opcode. Printed as the plain register name.
uint64_t DwarfRegNum = Opcode - dwarf::DW_OP_reg0; uint64_t DwarfRegNum = Opcode - dwarf::DW_OP_reg0;
Optional<unsigned> LLVMRegNum = MRI.getLLVMRegNum(DwarfRegNum, false); auto RegName = GetNameForDWARFReg(DwarfRegNum, false);
if (!LLVMRegNum) { if (RegName.empty())
OS << "<unknown register " << DwarfRegNum << ">";
return false; return false;
}
raw_svector_ostream S(Stack.emplace_back(PrintedExpr::Value).String); raw_svector_ostream S(Stack.emplace_back(PrintedExpr::Value).String);
S << MRI.getName(*LLVMRegNum); S << RegName;
} else if (Opcode >= dwarf::DW_OP_breg0 && } else if (Opcode >= dwarf::DW_OP_breg0 &&
Opcode <= dwarf::DW_OP_breg31) { Opcode <= dwarf::DW_OP_breg31) {
int DwarfRegNum = Opcode - dwarf::DW_OP_breg0; int DwarfRegNum = Opcode - dwarf::DW_OP_breg0;
int64_t Offset = Op.getRawOperand(0); int64_t Offset = Op.getRawOperand(0);
Optional<unsigned> LLVMRegNum = MRI.getLLVMRegNum(DwarfRegNum, false); auto RegName = GetNameForDWARFReg(DwarfRegNum, false);
if (!LLVMRegNum) { if (RegName.empty())
OS << "<unknown register " << DwarfRegNum << ">";
return false; return false;
}
raw_svector_ostream S(Stack.emplace_back().String); raw_svector_ostream S(Stack.emplace_back().String);
S << MRI.getName(*LLVMRegNum); S << RegName;
if (Offset) if (Offset)
S << format("%+" PRId64, Offset); S << format("%+" PRId64, Offset);
} else { } else {
@ -506,8 +495,10 @@ static bool printCompactDWARFExpr(raw_ostream &OS, DWARFExpression::iterator I,
return true; return true;
} }
bool DWARFExpression::printCompact(raw_ostream &OS, const MCRegisterInfo &MRI) { bool DWARFExpression::printCompact(
return printCompactDWARFExpr(OS, begin(), end(), MRI); raw_ostream &OS,
std::function<StringRef(uint64_t RegNum, bool IsEH)> GetNameForDWARFReg) {
return printCompactDWARFExpr(OS, begin(), end(), GetNameForDWARFReg);
} }
bool DWARFExpression::operator==(const DWARFExpression &RHS) const { bool DWARFExpression::operator==(const DWARFExpression &RHS) const {

View File

@ -18,6 +18,8 @@
#include "llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h" #include "llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h"
#include "llvm/DebugInfo/DWARF/DWARFCompileUnit.h" #include "llvm/DebugInfo/DWARF/DWARFCompileUnit.h"
#include "llvm/DebugInfo/DWARF/DWARFContext.h" #include "llvm/DebugInfo/DWARF/DWARFContext.h"
#include "llvm/MC/MCRegisterInfo.h"
#include "llvm/MC/TargetRegistry.h"
#include "llvm/Object/Archive.h" #include "llvm/Object/Archive.h"
#include "llvm/Object/MachOUniversal.h" #include "llvm/Object/MachOUniversal.h"
#include "llvm/Object/ObjectFile.h" #include "llvm/Object/ObjectFile.h"
@ -341,9 +343,11 @@ using HandlerFn = std::function<bool(ObjectFile &, DWARFContext &DICtx,
const Twine &, raw_ostream &)>; const Twine &, raw_ostream &)>;
/// Print only DIEs that have a certain name. /// Print only DIEs that have a certain name.
static bool filterByName(const StringSet<> &Names, DWARFDie Die, static bool filterByName(
StringRef NameRef, raw_ostream &OS) { const StringSet<> &Names, DWARFDie Die, StringRef NameRef, raw_ostream &OS,
std::function<StringRef(uint64_t RegNum, bool IsEH)> GetNameForDWARFReg) {
DIDumpOptions DumpOpts = getDumpOpts(Die.getDwarfUnit()->getContext()); DIDumpOptions DumpOpts = getDumpOpts(Die.getDwarfUnit()->getContext());
DumpOpts.GetNameForDWARFReg = GetNameForDWARFReg;
std::string Name = std::string Name =
(IgnoreCase && !UseRegex) ? NameRef.lower() : NameRef.str(); (IgnoreCase && !UseRegex) ? NameRef.lower() : NameRef.str();
if (UseRegex) { if (UseRegex) {
@ -369,17 +373,18 @@ static bool filterByName(const StringSet<> &Names, DWARFDie Die,
} }
/// Print only DIEs that have a certain name. /// Print only DIEs that have a certain name.
static void filterByName(const StringSet<> &Names, static void filterByName(
DWARFContext::unit_iterator_range CUs, const StringSet<> &Names, DWARFContext::unit_iterator_range CUs,
raw_ostream &OS) { raw_ostream &OS,
std::function<StringRef(uint64_t RegNum, bool IsEH)> GetNameForDWARFReg) {
for (const auto &CU : CUs) for (const auto &CU : CUs)
for (const auto &Entry : CU->dies()) { for (const auto &Entry : CU->dies()) {
DWARFDie Die = {CU.get(), &Entry}; DWARFDie Die = {CU.get(), &Entry};
if (const char *Name = Die.getName(DINameKind::ShortName)) if (const char *Name = Die.getName(DINameKind::ShortName))
if (filterByName(Names, Die, Name, OS)) if (filterByName(Names, Die, Name, OS, GetNameForDWARFReg))
continue; continue;
if (const char *Name = Die.getName(DINameKind::LinkageName)) if (const char *Name = Die.getName(DINameKind::LinkageName))
filterByName(Names, Die, Name, OS); filterByName(Names, Die, Name, OS, GetNameForDWARFReg);
} }
} }
@ -423,8 +428,9 @@ static void getDies(DWARFContext &DICtx, const DWARFDebugNames &Accel,
} }
/// Print only DIEs that have a certain name. /// Print only DIEs that have a certain name.
static void filterByAccelName(ArrayRef<std::string> Names, DWARFContext &DICtx, static void filterByAccelName(
raw_ostream &OS) { ArrayRef<std::string> Names, DWARFContext &DICtx, raw_ostream &OS,
std::function<StringRef(uint64_t RegNum, bool IsEH)> GetNameForDWARFReg) {
SmallVector<DWARFDie, 4> Dies; SmallVector<DWARFDie, 4> Dies;
for (const auto &Name : Names) { for (const auto &Name : Names) {
getDies(DICtx, DICtx.getAppleNames(), Name, Dies); getDies(DICtx, DICtx.getAppleNames(), Name, Dies);
@ -436,6 +442,7 @@ static void filterByAccelName(ArrayRef<std::string> Names, DWARFContext &DICtx,
Dies.erase(std::unique(Dies.begin(), Dies.end()), Dies.end()); Dies.erase(std::unique(Dies.begin(), Dies.end()), Dies.end());
DIDumpOptions DumpOpts = getDumpOpts(DICtx); DIDumpOptions DumpOpts = getDumpOpts(DICtx);
DumpOpts.GetNameForDWARFReg = GetNameForDWARFReg;
for (DWARFDie Die : Dies) for (DWARFDie Die : Dies)
Die.dump(OS, 0, DumpOpts); Die.dump(OS, 0, DumpOpts);
} }
@ -552,10 +559,41 @@ static bool collectObjectSources(ObjectFile &Obj, DWARFContext &DICtx,
return Result; return Result;
} }
static std::unique_ptr<MCRegisterInfo>
createRegInfo(const object::ObjectFile &Obj) {
std::unique_ptr<MCRegisterInfo> MCRegInfo;
Triple TT;
TT.setArch(Triple::ArchType(Obj.getArch()));
TT.setVendor(Triple::UnknownVendor);
TT.setOS(Triple::UnknownOS);
std::string TargetLookupError;
const Target *TheTarget =
TargetRegistry::lookupTarget(TT.str(), TargetLookupError);
if (!TargetLookupError.empty())
return nullptr;
MCRegInfo.reset(TheTarget->createMCRegInfo(TT.str()));
return MCRegInfo;
}
static bool dumpObjectFile(ObjectFile &Obj, DWARFContext &DICtx, static bool dumpObjectFile(ObjectFile &Obj, DWARFContext &DICtx,
const Twine &Filename, raw_ostream &OS) { const Twine &Filename, raw_ostream &OS) {
logAllUnhandledErrors(DICtx.loadRegisterInfo(Obj), errs(),
Filename.str() + ": "); auto MCRegInfo = createRegInfo(Obj);
if (!MCRegInfo)
logAllUnhandledErrors(createStringError(inconvertibleErrorCode(),
"Error in creating MCRegInfo"),
errs(), Filename.str() + ": ");
auto GetRegName = [&MCRegInfo](uint64_t DwarfRegNum, bool IsEH) -> StringRef {
if (!MCRegInfo)
return {};
if (llvm::Optional<unsigned> LLVMRegNum =
MCRegInfo->getLLVMRegNum(DwarfRegNum, IsEH))
if (const char *RegName = MCRegInfo->getName(*LLVMRegNum))
return StringRef(RegName);
return {};
};
// The UUID dump already contains all the same information. // The UUID dump already contains all the same information.
if (!(DumpType & DIDT_UUID) || DumpType == DIDT_All) if (!(DumpType & DIDT_UUID) || DumpType == DIDT_All)
OS << Filename << ":\tfile format " << Obj.getFileFormatName() << '\n'; OS << Filename << ":\tfile format " << Obj.getFileFormatName() << '\n';
@ -570,19 +608,21 @@ static bool dumpObjectFile(ObjectFile &Obj, DWARFContext &DICtx,
for (auto name : Name) for (auto name : Name)
Names.insert((IgnoreCase && !UseRegex) ? StringRef(name).lower() : name); Names.insert((IgnoreCase && !UseRegex) ? StringRef(name).lower() : name);
filterByName(Names, DICtx.normal_units(), OS); filterByName(Names, DICtx.normal_units(), OS, GetRegName);
filterByName(Names, DICtx.dwo_units(), OS); filterByName(Names, DICtx.dwo_units(), OS, GetRegName);
return true; return true;
} }
// Handle the --find option and lower it to --debug-info=<offset>. // Handle the --find option and lower it to --debug-info=<offset>.
if (!Find.empty()) { if (!Find.empty()) {
filterByAccelName(Find, DICtx, OS); filterByAccelName(Find, DICtx, OS, GetRegName);
return true; return true;
} }
// Dump the complete DWARF structure. // Dump the complete DWARF structure.
DICtx.dump(OS, getDumpOpts(DICtx), DumpOffsets); auto DumpOpts = getDumpOpts(DICtx);
DumpOpts.GetNameForDWARFReg = GetRegName;
DICtx.dump(OS, DumpOpts, DumpOffsets);
return true; return true;
} }

View File

@ -285,7 +285,6 @@ static llvm::Error handleObjectFile(ObjectFile &Obj,
if (!DICtx) if (!DICtx)
return createStringError(std::errc::invalid_argument, return createStringError(std::errc::invalid_argument,
"unable to create DWARF context"); "unable to create DWARF context");
logAllUnhandledErrors(DICtx->loadRegisterInfo(Obj), OS, "DwarfTransformer: ");
// Make a DWARF transformer object and populate the ranges of the code // Make a DWARF transformer object and populate the ranges of the code
// so we don't end up adding invalid functions to GSYM data. // so we don't end up adding invalid functions to GSYM data.

View File

@ -42,7 +42,16 @@ void LiveVariable::print(raw_ostream &OS, const MCRegisterInfo &MRI) const {
DataExtractor Data({LocExpr.Expr.data(), LocExpr.Expr.size()}, DataExtractor Data({LocExpr.Expr.data(), LocExpr.Expr.size()},
Unit->getContext().isLittleEndian(), 0); Unit->getContext().isLittleEndian(), 0);
DWARFExpression Expression(Data, Unit->getAddressByteSize()); DWARFExpression Expression(Data, Unit->getAddressByteSize());
Expression.printCompact(OS, MRI);
auto GetRegName = [&MRI, &OS](uint64_t DwarfRegNum, bool IsEH) -> StringRef {
if (Optional<unsigned> LLVMRegNum = MRI.getLLVMRegNum(DwarfRegNum, IsEH))
if (const char *RegName = MRI.getName(*LLVMRegNum))
return StringRef(RegName);
OS << "<unknown register " << DwarfRegNum << ">";
return {};
};
Expression.printCompact(OS, GetRegName);
} }
void LiveVariablePrinter::addVariable(DWARFDie FuncDie, DWARFDie VarDie) { void LiveVariablePrinter::addVariable(DWARFDie FuncDie, DWARFDie VarDie) {

View File

@ -13,6 +13,7 @@
#include "llvm/ADT/StringSet.h" #include "llvm/ADT/StringSet.h"
#include "llvm/DebugInfo/DWARF/DWARFContext.h" #include "llvm/DebugInfo/DWARF/DWARFContext.h"
#include "llvm/DebugInfo/Symbolize/Symbolize.h" #include "llvm/DebugInfo/Symbolize/Symbolize.h"
#include "llvm/MC/MCRegisterInfo.h"
#include "llvm/MC/MCSubtargetInfo.h" #include "llvm/MC/MCSubtargetInfo.h"
#include "llvm/Support/FormattedStream.h" #include "llvm/Support/FormattedStream.h"
#include <unordered_map> #include <unordered_map>

View File

@ -226,8 +226,9 @@ void PrinterContext<ELFT>::printEHFrame(const Elf_Shdr *EHFrameShdr) const {
W.getOStream() << "\n"; W.getOStream() << "\n";
W.startLine() << "Program:\n"; W.startLine() << "Program:\n";
W.indent(); W.indent();
Entry.cfis().dump(W.getOStream(), DIDumpOptions(), nullptr, auto DumpOpts = DIDumpOptions();
W.getIndentLevel()); DumpOpts.IsEH = true;
Entry.cfis().dump(W.getOStream(), DumpOpts, W.getIndentLevel());
W.unindent(); W.unindent();
W.unindent(); W.unindent();
W.getOStream() << "\n"; W.getOStream() << "\n";

View File

@ -41,7 +41,9 @@ void expectDumpResult(const dwarf::CIE &TestCIE, bool IsEH,
StringRef ExpectedFirstLine) { StringRef ExpectedFirstLine) {
std::string Output; std::string Output;
raw_string_ostream OS(Output); raw_string_ostream OS(Output);
TestCIE.dump(OS, DIDumpOptions(), /*MRI=*/nullptr, IsEH); auto DumpOpts = DIDumpOptions();
DumpOpts.IsEH = IsEH;
TestCIE.dump(OS, DumpOpts);
OS.flush(); OS.flush();
StringRef FirstLine = StringRef(Output).split('\n').first; StringRef FirstLine = StringRef(Output).split('\n').first;
EXPECT_EQ(FirstLine, ExpectedFirstLine); EXPECT_EQ(FirstLine, ExpectedFirstLine);
@ -51,7 +53,9 @@ void expectDumpResult(const dwarf::FDE &TestFDE, bool IsEH,
StringRef ExpectedFirstLine) { StringRef ExpectedFirstLine) {
std::string Output; std::string Output;
raw_string_ostream OS(Output); raw_string_ostream OS(Output);
TestFDE.dump(OS, DIDumpOptions(), /*MRI=*/nullptr, IsEH); auto DumpOpts = DIDumpOptions();
DumpOpts.IsEH = IsEH;
TestFDE.dump(OS, DumpOpts);
OS.flush(); OS.flush();
StringRef FirstLine = StringRef(Output).split('\n').first; StringRef FirstLine = StringRef(Output).split('\n').first;
EXPECT_EQ(FirstLine, ExpectedFirstLine); EXPECT_EQ(FirstLine, ExpectedFirstLine);

View File

@ -60,7 +60,17 @@ void DWARFExpressionCompactPrinterTest::TestExprPrinter(
raw_string_ostream OS(Result); raw_string_ostream OS(Result);
DataExtractor DE(ExprData, true, 8); DataExtractor DE(ExprData, true, 8);
DWARFExpression Expr(DE, 8); DWARFExpression Expr(DE, 8);
Expr.printCompact(OS, *MRI);
auto GetRegName = [&](uint64_t DwarfRegNum, bool IsEH) -> StringRef {
if (llvm::Optional<unsigned> LLVMRegNum =
this->MRI->getLLVMRegNum(DwarfRegNum, IsEH))
if (const char *RegName = this->MRI->getName(*LLVMRegNum))
return llvm::StringRef(RegName);
OS << "<unknown register " << DwarfRegNum << ">";
return {};
};
Expr.printCompact(OS, GetRegName);
EXPECT_EQ(OS.str(), Expected); EXPECT_EQ(OS.str(), Expected);
} }