diff options
Diffstat (limited to 'llvm/lib/CodeGen/AsmPrinter/DIE.cpp')
-rw-r--r-- | llvm/lib/CodeGen/AsmPrinter/DIE.cpp | 817 |
1 files changed, 817 insertions, 0 deletions
diff --git a/llvm/lib/CodeGen/AsmPrinter/DIE.cpp b/llvm/lib/CodeGen/AsmPrinter/DIE.cpp new file mode 100644 index 000000000000..f4134da48caa --- /dev/null +++ b/llvm/lib/CodeGen/AsmPrinter/DIE.cpp @@ -0,0 +1,817 @@ +//===--- lib/CodeGen/DIE.cpp - DWARF Info Entries -------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// Data structures for DWARF info entries. +// +//===----------------------------------------------------------------------===// + +#include "llvm/CodeGen/DIE.h" +#include "DwarfCompileUnit.h" +#include "DwarfDebug.h" +#include "DwarfUnit.h" +#include "llvm/ADT/Twine.h" +#include "llvm/CodeGen/AsmPrinter.h" +#include "llvm/Config/llvm-config.h" +#include "llvm/IR/DataLayout.h" +#include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCStreamer.h" +#include "llvm/MC/MCSymbol.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/Format.h" +#include "llvm/Support/FormattedStream.h" +#include "llvm/Support/LEB128.h" +#include "llvm/Support/MD5.h" +#include "llvm/Support/raw_ostream.h" +using namespace llvm; + +#define DEBUG_TYPE "dwarfdebug" + +//===----------------------------------------------------------------------===// +// DIEAbbrevData Implementation +//===----------------------------------------------------------------------===// + +/// Profile - Used to gather unique data for the abbreviation folding set. +/// +void DIEAbbrevData::Profile(FoldingSetNodeID &ID) const { + // Explicitly cast to an integer type for which FoldingSetNodeID has + // overloads. Otherwise MSVC 2010 thinks this call is ambiguous. + ID.AddInteger(unsigned(Attribute)); + ID.AddInteger(unsigned(Form)); + if (Form == dwarf::DW_FORM_implicit_const) + ID.AddInteger(Value); +} + +//===----------------------------------------------------------------------===// +// DIEAbbrev Implementation +//===----------------------------------------------------------------------===// + +/// Profile - Used to gather unique data for the abbreviation folding set. +/// +void DIEAbbrev::Profile(FoldingSetNodeID &ID) const { + ID.AddInteger(unsigned(Tag)); + ID.AddInteger(unsigned(Children)); + + // For each attribute description. + for (unsigned i = 0, N = Data.size(); i < N; ++i) + Data[i].Profile(ID); +} + +/// Emit - Print the abbreviation using the specified asm printer. +/// +void DIEAbbrev::Emit(const AsmPrinter *AP) const { + // Emit its Dwarf tag type. + AP->EmitULEB128(Tag, dwarf::TagString(Tag).data()); + + // Emit whether it has children DIEs. + AP->EmitULEB128((unsigned)Children, dwarf::ChildrenString(Children).data()); + + // For each attribute description. + for (unsigned i = 0, N = Data.size(); i < N; ++i) { + const DIEAbbrevData &AttrData = Data[i]; + + // Emit attribute type. + AP->EmitULEB128(AttrData.getAttribute(), + dwarf::AttributeString(AttrData.getAttribute()).data()); + + // Emit form type. +#ifndef NDEBUG + // Could be an assertion, but this way we can see the failing form code + // easily, which helps track down where it came from. + if (!dwarf::isValidFormForVersion(AttrData.getForm(), + AP->getDwarfVersion())) { + LLVM_DEBUG(dbgs() << "Invalid form " << format("0x%x", AttrData.getForm()) + << " for DWARF version " << AP->getDwarfVersion() + << "\n"); + llvm_unreachable("Invalid form for specified DWARF version"); + } +#endif + AP->EmitULEB128(AttrData.getForm(), + dwarf::FormEncodingString(AttrData.getForm()).data()); + + // Emit value for DW_FORM_implicit_const. + if (AttrData.getForm() == dwarf::DW_FORM_implicit_const) + AP->EmitSLEB128(AttrData.getValue()); + } + + // Mark end of abbreviation. + AP->EmitULEB128(0, "EOM(1)"); + AP->EmitULEB128(0, "EOM(2)"); +} + +LLVM_DUMP_METHOD +void DIEAbbrev::print(raw_ostream &O) const { + O << "Abbreviation @" + << format("0x%lx", (long)(intptr_t)this) + << " " + << dwarf::TagString(Tag) + << " " + << dwarf::ChildrenString(Children) + << '\n'; + + for (unsigned i = 0, N = Data.size(); i < N; ++i) { + O << " " + << dwarf::AttributeString(Data[i].getAttribute()) + << " " + << dwarf::FormEncodingString(Data[i].getForm()); + + if (Data[i].getForm() == dwarf::DW_FORM_implicit_const) + O << " " << Data[i].getValue(); + + O << '\n'; + } +} + +#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) +LLVM_DUMP_METHOD void DIEAbbrev::dump() const { + print(dbgs()); +} +#endif + +//===----------------------------------------------------------------------===// +// DIEAbbrevSet Implementation +//===----------------------------------------------------------------------===// + +DIEAbbrevSet::~DIEAbbrevSet() { + for (DIEAbbrev *Abbrev : Abbreviations) + Abbrev->~DIEAbbrev(); +} + +DIEAbbrev &DIEAbbrevSet::uniqueAbbreviation(DIE &Die) { + + FoldingSetNodeID ID; + DIEAbbrev Abbrev = Die.generateAbbrev(); + Abbrev.Profile(ID); + + void *InsertPos; + if (DIEAbbrev *Existing = + AbbreviationsSet.FindNodeOrInsertPos(ID, InsertPos)) { + Die.setAbbrevNumber(Existing->getNumber()); + return *Existing; + } + + // Move the abbreviation to the heap and assign a number. + DIEAbbrev *New = new (Alloc) DIEAbbrev(std::move(Abbrev)); + Abbreviations.push_back(New); + New->setNumber(Abbreviations.size()); + Die.setAbbrevNumber(Abbreviations.size()); + + // Store it for lookup. + AbbreviationsSet.InsertNode(New, InsertPos); + return *New; +} + +void DIEAbbrevSet::Emit(const AsmPrinter *AP, MCSection *Section) const { + if (!Abbreviations.empty()) { + // Start the debug abbrev section. + AP->OutStreamer->SwitchSection(Section); + AP->emitDwarfAbbrevs(Abbreviations); + } +} + +//===----------------------------------------------------------------------===// +// DIE Implementation +//===----------------------------------------------------------------------===// + +DIE *DIE::getParent() const { + return Owner.dyn_cast<DIE*>(); +} + +DIEAbbrev DIE::generateAbbrev() const { + DIEAbbrev Abbrev(Tag, hasChildren()); + for (const DIEValue &V : values()) + if (V.getForm() == dwarf::DW_FORM_implicit_const) + Abbrev.AddImplicitConstAttribute(V.getAttribute(), + V.getDIEInteger().getValue()); + else + Abbrev.AddAttribute(V.getAttribute(), V.getForm()); + return Abbrev; +} + +unsigned DIE::getDebugSectionOffset() const { + const DIEUnit *Unit = getUnit(); + assert(Unit && "DIE must be owned by a DIEUnit to get its absolute offset"); + return Unit->getDebugSectionOffset() + getOffset(); +} + +const DIE *DIE::getUnitDie() const { + const DIE *p = this; + while (p) { + if (p->getTag() == dwarf::DW_TAG_compile_unit || + p->getTag() == dwarf::DW_TAG_type_unit) + return p; + p = p->getParent(); + } + return nullptr; +} + +DIEUnit *DIE::getUnit() const { + const DIE *UnitDie = getUnitDie(); + if (UnitDie) + return UnitDie->Owner.dyn_cast<DIEUnit*>(); + return nullptr; +} + +DIEValue DIE::findAttribute(dwarf::Attribute Attribute) const { + // Iterate through all the attributes until we find the one we're + // looking for, if we can't find it return NULL. + for (const auto &V : values()) + if (V.getAttribute() == Attribute) + return V; + return DIEValue(); +} + +LLVM_DUMP_METHOD +static void printValues(raw_ostream &O, const DIEValueList &Values, + StringRef Type, unsigned Size, unsigned IndentCount) { + O << Type << ": Size: " << Size << "\n"; + + unsigned I = 0; + const std::string Indent(IndentCount, ' '); + for (const auto &V : Values.values()) { + O << Indent; + O << "Blk[" << I++ << "]"; + O << " " << dwarf::FormEncodingString(V.getForm()) << " "; + V.print(O); + O << "\n"; + } +} + +LLVM_DUMP_METHOD +void DIE::print(raw_ostream &O, unsigned IndentCount) const { + const std::string Indent(IndentCount, ' '); + O << Indent << "Die: " << format("0x%lx", (long)(intptr_t) this) + << ", Offset: " << Offset << ", Size: " << Size << "\n"; + + O << Indent << dwarf::TagString(getTag()) << " " + << dwarf::ChildrenString(hasChildren()) << "\n"; + + IndentCount += 2; + for (const auto &V : values()) { + O << Indent; + O << dwarf::AttributeString(V.getAttribute()); + O << " " << dwarf::FormEncodingString(V.getForm()) << " "; + V.print(O); + O << "\n"; + } + IndentCount -= 2; + + for (const auto &Child : children()) + Child.print(O, IndentCount + 4); + + O << "\n"; +} + +#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) +LLVM_DUMP_METHOD void DIE::dump() const { + print(dbgs()); +} +#endif + +unsigned DIE::computeOffsetsAndAbbrevs(const AsmPrinter *AP, + DIEAbbrevSet &AbbrevSet, + unsigned CUOffset) { + // Unique the abbreviation and fill in the abbreviation number so this DIE + // can be emitted. + const DIEAbbrev &Abbrev = AbbrevSet.uniqueAbbreviation(*this); + + // Set compile/type unit relative offset of this DIE. + setOffset(CUOffset); + + // Add the byte size of the abbreviation code. + CUOffset += getULEB128Size(getAbbrevNumber()); + + // Add the byte size of all the DIE attribute values. + for (const auto &V : values()) + CUOffset += V.SizeOf(AP); + + // Let the children compute their offsets and abbreviation numbers. + if (hasChildren()) { + (void)Abbrev; + assert(Abbrev.hasChildren() && "Children flag not set"); + + for (auto &Child : children()) + CUOffset = Child.computeOffsetsAndAbbrevs(AP, AbbrevSet, CUOffset); + + // Each child chain is terminated with a zero byte, adjust the offset. + CUOffset += sizeof(int8_t); + } + + // Compute the byte size of this DIE and all of its children correctly. This + // is needed so that top level DIE can help the compile unit set its length + // correctly. + setSize(CUOffset - getOffset()); + return CUOffset; +} + +//===----------------------------------------------------------------------===// +// DIEUnit Implementation +//===----------------------------------------------------------------------===// +DIEUnit::DIEUnit(uint16_t V, uint8_t A, dwarf::Tag UnitTag) + : Die(UnitTag), Section(nullptr), Offset(0), Length(0), Version(V), + AddrSize(A) +{ + Die.Owner = this; + assert((UnitTag == dwarf::DW_TAG_compile_unit || + UnitTag == dwarf::DW_TAG_type_unit || + UnitTag == dwarf::DW_TAG_partial_unit) && "expected a unit TAG"); +} + +void DIEValue::EmitValue(const AsmPrinter *AP) const { + switch (Ty) { + case isNone: + llvm_unreachable("Expected valid DIEValue"); +#define HANDLE_DIEVALUE(T) \ + case is##T: \ + getDIE##T().EmitValue(AP, Form); \ + break; +#include "llvm/CodeGen/DIEValue.def" + } +} + +unsigned DIEValue::SizeOf(const AsmPrinter *AP) const { + switch (Ty) { + case isNone: + llvm_unreachable("Expected valid DIEValue"); +#define HANDLE_DIEVALUE(T) \ + case is##T: \ + return getDIE##T().SizeOf(AP, Form); +#include "llvm/CodeGen/DIEValue.def" + } + llvm_unreachable("Unknown DIE kind"); +} + +LLVM_DUMP_METHOD +void DIEValue::print(raw_ostream &O) const { + switch (Ty) { + case isNone: + llvm_unreachable("Expected valid DIEValue"); +#define HANDLE_DIEVALUE(T) \ + case is##T: \ + getDIE##T().print(O); \ + break; +#include "llvm/CodeGen/DIEValue.def" + } +} + +#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) +LLVM_DUMP_METHOD void DIEValue::dump() const { + print(dbgs()); +} +#endif + +//===----------------------------------------------------------------------===// +// DIEInteger Implementation +//===----------------------------------------------------------------------===// + +/// EmitValue - Emit integer of appropriate size. +/// +void DIEInteger::EmitValue(const AsmPrinter *Asm, dwarf::Form Form) const { + switch (Form) { + case dwarf::DW_FORM_implicit_const: + case dwarf::DW_FORM_flag_present: + // Emit something to keep the lines and comments in sync. + // FIXME: Is there a better way to do this? + Asm->OutStreamer->AddBlankLine(); + return; + case dwarf::DW_FORM_flag: + case dwarf::DW_FORM_ref1: + case dwarf::DW_FORM_data1: + case dwarf::DW_FORM_strx1: + case dwarf::DW_FORM_addrx1: + case dwarf::DW_FORM_ref2: + case dwarf::DW_FORM_data2: + case dwarf::DW_FORM_strx2: + case dwarf::DW_FORM_addrx2: + case dwarf::DW_FORM_strx3: + case dwarf::DW_FORM_strp: + case dwarf::DW_FORM_ref4: + case dwarf::DW_FORM_data4: + case dwarf::DW_FORM_ref_sup4: + case dwarf::DW_FORM_strx4: + case dwarf::DW_FORM_addrx4: + case dwarf::DW_FORM_ref8: + case dwarf::DW_FORM_ref_sig8: + case dwarf::DW_FORM_data8: + case dwarf::DW_FORM_ref_sup8: + case dwarf::DW_FORM_GNU_ref_alt: + case dwarf::DW_FORM_GNU_strp_alt: + case dwarf::DW_FORM_line_strp: + case dwarf::DW_FORM_sec_offset: + case dwarf::DW_FORM_strp_sup: + case dwarf::DW_FORM_addr: + case dwarf::DW_FORM_ref_addr: + Asm->OutStreamer->EmitIntValue(Integer, SizeOf(Asm, Form)); + return; + case dwarf::DW_FORM_GNU_str_index: + case dwarf::DW_FORM_GNU_addr_index: + case dwarf::DW_FORM_ref_udata: + case dwarf::DW_FORM_strx: + case dwarf::DW_FORM_addrx: + case dwarf::DW_FORM_rnglistx: + case dwarf::DW_FORM_udata: + Asm->EmitULEB128(Integer); + return; + case dwarf::DW_FORM_sdata: + Asm->EmitSLEB128(Integer); + return; + default: llvm_unreachable("DIE Value form not supported yet"); + } +} + +/// SizeOf - Determine size of integer value in bytes. +/// +unsigned DIEInteger::SizeOf(const AsmPrinter *AP, dwarf::Form Form) const { + dwarf::FormParams Params = {0, 0, dwarf::DWARF32}; + if (AP) + Params = {AP->getDwarfVersion(), uint8_t(AP->getPointerSize()), + AP->OutStreamer->getContext().getDwarfFormat()}; + + if (Optional<uint8_t> FixedSize = dwarf::getFixedFormByteSize(Form, Params)) + return *FixedSize; + + switch (Form) { + case dwarf::DW_FORM_GNU_str_index: + case dwarf::DW_FORM_GNU_addr_index: + case dwarf::DW_FORM_ref_udata: + case dwarf::DW_FORM_strx: + case dwarf::DW_FORM_addrx: + case dwarf::DW_FORM_rnglistx: + case dwarf::DW_FORM_udata: + return getULEB128Size(Integer); + case dwarf::DW_FORM_sdata: + return getSLEB128Size(Integer); + default: llvm_unreachable("DIE Value form not supported yet"); + } +} + +LLVM_DUMP_METHOD +void DIEInteger::print(raw_ostream &O) const { + O << "Int: " << (int64_t)Integer << " 0x"; + O.write_hex(Integer); +} + +//===----------------------------------------------------------------------===// +// DIEExpr Implementation +//===----------------------------------------------------------------------===// + +/// EmitValue - Emit expression value. +/// +void DIEExpr::EmitValue(const AsmPrinter *AP, dwarf::Form Form) const { + AP->EmitDebugValue(Expr, SizeOf(AP, Form)); +} + +/// SizeOf - Determine size of expression value in bytes. +/// +unsigned DIEExpr::SizeOf(const AsmPrinter *AP, dwarf::Form Form) const { + if (Form == dwarf::DW_FORM_data4) return 4; + if (Form == dwarf::DW_FORM_sec_offset) return 4; + if (Form == dwarf::DW_FORM_strp) return 4; + return AP->getPointerSize(); +} + +LLVM_DUMP_METHOD +void DIEExpr::print(raw_ostream &O) const { O << "Expr: " << *Expr; } + +//===----------------------------------------------------------------------===// +// DIELabel Implementation +//===----------------------------------------------------------------------===// + +/// EmitValue - Emit label value. +/// +void DIELabel::EmitValue(const AsmPrinter *AP, dwarf::Form Form) const { + AP->EmitLabelReference(Label, SizeOf(AP, Form), + Form == dwarf::DW_FORM_strp || + Form == dwarf::DW_FORM_sec_offset || + Form == dwarf::DW_FORM_ref_addr || + Form == dwarf::DW_FORM_data4); +} + +/// SizeOf - Determine size of label value in bytes. +/// +unsigned DIELabel::SizeOf(const AsmPrinter *AP, dwarf::Form Form) const { + if (Form == dwarf::DW_FORM_data4) return 4; + if (Form == dwarf::DW_FORM_sec_offset) return 4; + if (Form == dwarf::DW_FORM_strp) return 4; + return AP->MAI->getCodePointerSize(); +} + +LLVM_DUMP_METHOD +void DIELabel::print(raw_ostream &O) const { O << "Lbl: " << Label->getName(); } + +//===----------------------------------------------------------------------===// +// DIEBaseTypeRef Implementation +//===----------------------------------------------------------------------===// + +void DIEBaseTypeRef::EmitValue(const AsmPrinter *AP, dwarf::Form Form) const { + uint64_t Offset = CU->ExprRefedBaseTypes[Index].Die->getOffset(); + assert(Offset < (1ULL << (ULEB128PadSize * 7)) && "Offset wont fit"); + AP->EmitULEB128(Offset, nullptr, ULEB128PadSize); +} + +unsigned DIEBaseTypeRef::SizeOf(const AsmPrinter *AP, dwarf::Form Form) const { + return ULEB128PadSize; +} + +LLVM_DUMP_METHOD +void DIEBaseTypeRef::print(raw_ostream &O) const { O << "BaseTypeRef: " << Index; } + +//===----------------------------------------------------------------------===// +// DIEDelta Implementation +//===----------------------------------------------------------------------===// + +/// EmitValue - Emit delta value. +/// +void DIEDelta::EmitValue(const AsmPrinter *AP, dwarf::Form Form) const { + AP->EmitLabelDifference(LabelHi, LabelLo, SizeOf(AP, Form)); +} + +/// SizeOf - Determine size of delta value in bytes. +/// +unsigned DIEDelta::SizeOf(const AsmPrinter *AP, dwarf::Form Form) const { + if (Form == dwarf::DW_FORM_data4) return 4; + if (Form == dwarf::DW_FORM_sec_offset) return 4; + if (Form == dwarf::DW_FORM_strp) return 4; + return AP->MAI->getCodePointerSize(); +} + +LLVM_DUMP_METHOD +void DIEDelta::print(raw_ostream &O) const { + O << "Del: " << LabelHi->getName() << "-" << LabelLo->getName(); +} + +//===----------------------------------------------------------------------===// +// DIEString Implementation +//===----------------------------------------------------------------------===// + +/// EmitValue - Emit string value. +/// +void DIEString::EmitValue(const AsmPrinter *AP, dwarf::Form Form) const { + // Index of string in symbol table. + switch (Form) { + case dwarf::DW_FORM_GNU_str_index: + case dwarf::DW_FORM_strx: + case dwarf::DW_FORM_strx1: + case dwarf::DW_FORM_strx2: + case dwarf::DW_FORM_strx3: + case dwarf::DW_FORM_strx4: + DIEInteger(S.getIndex()).EmitValue(AP, Form); + return; + case dwarf::DW_FORM_strp: + if (AP->MAI->doesDwarfUseRelocationsAcrossSections()) + DIELabel(S.getSymbol()).EmitValue(AP, Form); + else + DIEInteger(S.getOffset()).EmitValue(AP, Form); + return; + default: + llvm_unreachable("Expected valid string form"); + } +} + +/// SizeOf - Determine size of delta value in bytes. +/// +unsigned DIEString::SizeOf(const AsmPrinter *AP, dwarf::Form Form) const { + // Index of string in symbol table. + switch (Form) { + case dwarf::DW_FORM_GNU_str_index: + case dwarf::DW_FORM_strx: + case dwarf::DW_FORM_strx1: + case dwarf::DW_FORM_strx2: + case dwarf::DW_FORM_strx3: + case dwarf::DW_FORM_strx4: + return DIEInteger(S.getIndex()).SizeOf(AP, Form); + case dwarf::DW_FORM_strp: + if (AP->MAI->doesDwarfUseRelocationsAcrossSections()) + return DIELabel(S.getSymbol()).SizeOf(AP, Form); + return DIEInteger(S.getOffset()).SizeOf(AP, Form); + default: + llvm_unreachable("Expected valid string form"); + } +} + +LLVM_DUMP_METHOD +void DIEString::print(raw_ostream &O) const { + O << "String: " << S.getString(); +} + +//===----------------------------------------------------------------------===// +// DIEInlineString Implementation +//===----------------------------------------------------------------------===// +void DIEInlineString::EmitValue(const AsmPrinter *AP, dwarf::Form Form) const { + if (Form == dwarf::DW_FORM_string) { + AP->OutStreamer->EmitBytes(S); + AP->emitInt8(0); + return; + } + llvm_unreachable("Expected valid string form"); +} + +unsigned DIEInlineString::SizeOf(const AsmPrinter *AP, dwarf::Form Form) const { + // Emit string bytes + NULL byte. + return S.size() + 1; +} + +LLVM_DUMP_METHOD +void DIEInlineString::print(raw_ostream &O) const { + O << "InlineString: " << S; +} + +//===----------------------------------------------------------------------===// +// DIEEntry Implementation +//===----------------------------------------------------------------------===// + +/// EmitValue - Emit debug information entry offset. +/// +void DIEEntry::EmitValue(const AsmPrinter *AP, dwarf::Form Form) const { + + switch (Form) { + case dwarf::DW_FORM_ref1: + case dwarf::DW_FORM_ref2: + case dwarf::DW_FORM_ref4: + case dwarf::DW_FORM_ref8: + AP->OutStreamer->EmitIntValue(Entry->getOffset(), SizeOf(AP, Form)); + return; + + case dwarf::DW_FORM_ref_udata: + AP->EmitULEB128(Entry->getOffset()); + return; + + case dwarf::DW_FORM_ref_addr: { + // Get the absolute offset for this DIE within the debug info/types section. + unsigned Addr = Entry->getDebugSectionOffset(); + if (const MCSymbol *SectionSym = + Entry->getUnit()->getCrossSectionRelativeBaseAddress()) { + AP->EmitLabelPlusOffset(SectionSym, Addr, SizeOf(AP, Form), true); + return; + } + + AP->OutStreamer->EmitIntValue(Addr, SizeOf(AP, Form)); + return; + } + default: + llvm_unreachable("Improper form for DIE reference"); + } +} + +unsigned DIEEntry::SizeOf(const AsmPrinter *AP, dwarf::Form Form) const { + switch (Form) { + case dwarf::DW_FORM_ref1: + return 1; + case dwarf::DW_FORM_ref2: + return 2; + case dwarf::DW_FORM_ref4: + return 4; + case dwarf::DW_FORM_ref8: + return 8; + case dwarf::DW_FORM_ref_udata: + return getULEB128Size(Entry->getOffset()); + case dwarf::DW_FORM_ref_addr: + if (AP->getDwarfVersion() == 2) + return AP->MAI->getCodePointerSize(); + switch (AP->OutStreamer->getContext().getDwarfFormat()) { + case dwarf::DWARF32: + return 4; + case dwarf::DWARF64: + return 8; + } + llvm_unreachable("Invalid DWARF format"); + + default: + llvm_unreachable("Improper form for DIE reference"); + } +} + +LLVM_DUMP_METHOD +void DIEEntry::print(raw_ostream &O) const { + O << format("Die: 0x%lx", (long)(intptr_t)&Entry); +} + +//===----------------------------------------------------------------------===// +// DIELoc Implementation +//===----------------------------------------------------------------------===// + +/// ComputeSize - calculate the size of the location expression. +/// +unsigned DIELoc::ComputeSize(const AsmPrinter *AP) const { + if (!Size) { + for (const auto &V : values()) + Size += V.SizeOf(AP); + } + + return Size; +} + +/// EmitValue - Emit location data. +/// +void DIELoc::EmitValue(const AsmPrinter *Asm, dwarf::Form Form) const { + switch (Form) { + default: llvm_unreachable("Improper form for block"); + case dwarf::DW_FORM_block1: Asm->emitInt8(Size); break; + case dwarf::DW_FORM_block2: Asm->emitInt16(Size); break; + case dwarf::DW_FORM_block4: Asm->emitInt32(Size); break; + case dwarf::DW_FORM_block: + case dwarf::DW_FORM_exprloc: + Asm->EmitULEB128(Size); break; + } + + for (const auto &V : values()) + V.EmitValue(Asm); +} + +/// SizeOf - Determine size of location data in bytes. +/// +unsigned DIELoc::SizeOf(const AsmPrinter *AP, dwarf::Form Form) const { + switch (Form) { + case dwarf::DW_FORM_block1: return Size + sizeof(int8_t); + case dwarf::DW_FORM_block2: return Size + sizeof(int16_t); + case dwarf::DW_FORM_block4: return Size + sizeof(int32_t); + case dwarf::DW_FORM_block: + case dwarf::DW_FORM_exprloc: + return Size + getULEB128Size(Size); + default: llvm_unreachable("Improper form for block"); + } +} + +LLVM_DUMP_METHOD +void DIELoc::print(raw_ostream &O) const { + printValues(O, *this, "ExprLoc", Size, 5); +} + +//===----------------------------------------------------------------------===// +// DIEBlock Implementation +//===----------------------------------------------------------------------===// + +/// ComputeSize - calculate the size of the block. +/// +unsigned DIEBlock::ComputeSize(const AsmPrinter *AP) const { + if (!Size) { + for (const auto &V : values()) + Size += V.SizeOf(AP); + } + + return Size; +} + +/// EmitValue - Emit block data. +/// +void DIEBlock::EmitValue(const AsmPrinter *Asm, dwarf::Form Form) const { + switch (Form) { + default: llvm_unreachable("Improper form for block"); + case dwarf::DW_FORM_block1: Asm->emitInt8(Size); break; + case dwarf::DW_FORM_block2: Asm->emitInt16(Size); break; + case dwarf::DW_FORM_block4: Asm->emitInt32(Size); break; + case dwarf::DW_FORM_block: Asm->EmitULEB128(Size); break; + case dwarf::DW_FORM_string: break; + case dwarf::DW_FORM_data16: break; + } + + for (const auto &V : values()) + V.EmitValue(Asm); +} + +/// SizeOf - Determine size of block data in bytes. +/// +unsigned DIEBlock::SizeOf(const AsmPrinter *AP, dwarf::Form Form) const { + switch (Form) { + case dwarf::DW_FORM_block1: return Size + sizeof(int8_t); + case dwarf::DW_FORM_block2: return Size + sizeof(int16_t); + case dwarf::DW_FORM_block4: return Size + sizeof(int32_t); + case dwarf::DW_FORM_block: return Size + getULEB128Size(Size); + case dwarf::DW_FORM_data16: return 16; + default: llvm_unreachable("Improper form for block"); + } +} + +LLVM_DUMP_METHOD +void DIEBlock::print(raw_ostream &O) const { + printValues(O, *this, "Blk", Size, 5); +} + +//===----------------------------------------------------------------------===// +// DIELocList Implementation +//===----------------------------------------------------------------------===// + +unsigned DIELocList::SizeOf(const AsmPrinter *AP, dwarf::Form Form) const { + if (Form == dwarf::DW_FORM_data4) + return 4; + if (Form == dwarf::DW_FORM_sec_offset) + return 4; + return AP->MAI->getCodePointerSize(); +} + +/// EmitValue - Emit label value. +/// +void DIELocList::EmitValue(const AsmPrinter *AP, dwarf::Form Form) const { + DwarfDebug *DD = AP->getDwarfDebug(); + MCSymbol *Label = DD->getDebugLocs().getList(Index).Label; + AP->emitDwarfSymbolReference(Label, /*ForceOffset*/ DD->useSplitDwarf()); +} + +LLVM_DUMP_METHOD +void DIELocList::print(raw_ostream &O) const { O << "LocList: " << Index; } |