diff --git a/llvm/include/llvm/CodeGen/AsmPrinter.h b/llvm/include/llvm/CodeGen/AsmPrinter.h --- a/llvm/include/llvm/CodeGen/AsmPrinter.h +++ b/llvm/include/llvm/CodeGen/AsmPrinter.h @@ -580,7 +580,7 @@ /// Emit something like ".long Label+Offset" where the size in bytes of the /// directive is specified by Size and Label specifies the label. This /// implicitly uses .set if it is available. - void emitLabelPlusOffset(const MCSymbol *Label, uint64_t Offset, + void emitLabelPlusOffset(const MCSymbol *Label, int64_t Offset, unsigned Size, bool IsSectionRelative = false) const; /// Emit something like ".long Label" where the size in bytes of the directive diff --git a/llvm/include/llvm/CodeGen/DIE.h b/llvm/include/llvm/CodeGen/DIE.h --- a/llvm/include/llvm/CodeGen/DIE.h +++ b/llvm/include/llvm/CodeGen/DIE.h @@ -267,6 +267,22 @@ }; //===--------------------------------------------------------------------===// +/// A simple label plus offset DIE. +/// +class DIELabelPlusOffset { + const MCSymbol *Label; + int64_t Offset; + +public: + DIELabelPlusOffset(const MCSymbol *L, int64_t O) : Label(L), Offset(O) {} + + void emitValue(const AsmPrinter *AP, dwarf::Form Form) const; + unsigned SizeOf(const AsmPrinter *AP, dwarf::Form Form) const; + + void print(raw_ostream &O) const; +}; + +//===--------------------------------------------------------------------===// /// A container for string pool string values. /// /// This class is used with the DW_FORM_strp and DW_FORM_GNU_str_index forms. @@ -370,7 +386,8 @@ /// should be stored by reference instead of by value. using ValTy = AlignedCharArrayUnion; + DIELoc *, DIELocList, DIEBaseTypeRef *, + DIELabelPlusOffset *>; static_assert(sizeof(ValTy) <= sizeof(uint64_t) || sizeof(ValTy) <= sizeof(void *), diff --git a/llvm/include/llvm/CodeGen/DIEValue.def b/llvm/include/llvm/CodeGen/DIEValue.def --- a/llvm/include/llvm/CodeGen/DIEValue.def +++ b/llvm/include/llvm/CodeGen/DIEValue.def @@ -41,6 +41,7 @@ HANDLE_DIEVALUE_LARGE(Loc) HANDLE_DIEVALUE_SMALL(LocList) HANDLE_DIEVALUE_LARGE(InlineString) +HANDLE_DIEVALUE_LARGE(LabelPlusOffset) #undef HANDLE_DIEVALUE #undef HANDLE_DIEVALUE_SMALL diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp --- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -2319,7 +2319,7 @@ /// EmitLabelPlusOffset - Emit something like ".long Label+Offset" /// where the size in bytes of the directive is specified by Size and Label /// specifies the label. This implicitly uses .set if it is available. -void AsmPrinter::emitLabelPlusOffset(const MCSymbol *Label, uint64_t Offset, +void AsmPrinter::emitLabelPlusOffset(const MCSymbol *Label, int64_t Offset, unsigned Size, bool IsSectionRelative) const { if (MAI->needsDwarfSectionOffsetDirective() && IsSectionRelative) { diff --git a/llvm/lib/CodeGen/AsmPrinter/DIE.cpp b/llvm/lib/CodeGen/AsmPrinter/DIE.cpp --- a/llvm/lib/CodeGen/AsmPrinter/DIE.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/DIE.cpp @@ -565,6 +565,36 @@ } //===----------------------------------------------------------------------===// +// DIELabelPlusOffset Implementation +//===----------------------------------------------------------------------===// + +/// EmitValue - Emit lable plus offset value. +/// +void DIELabelPlusOffset::emitValue(const AsmPrinter *AP, dwarf::Form Form) const { + AP->emitLabelPlusOffset(Label, Offset, SizeOf(AP, Form)); +} + +/// SizeOf - Determine size of delta value in bytes. +/// +unsigned DIELabelPlusOffset::SizeOf(const AsmPrinter *AP, dwarf::Form Form) const { + switch (Form) { + case dwarf::DW_FORM_data4: + return 4; + case dwarf::DW_FORM_data8: + return 8; + case dwarf::DW_FORM_sec_offset: + return AP->getDwarfOffsetByteSize(); + default: + llvm_unreachable("DIE Value form not supported yet"); + } +} + +LLVM_DUMP_METHOD +void DIELabelPlusOffset::print(raw_ostream &O) const { + O << "Del: " << Label->getName() << "-" << Offset; +} + +//===----------------------------------------------------------------------===// // DIEString Implementation //===----------------------------------------------------------------------===// diff --git a/llvm/lib/CodeGen/AsmPrinter/DIEHash.cpp b/llvm/lib/CodeGen/AsmPrinter/DIEHash.cpp --- a/llvm/lib/CodeGen/AsmPrinter/DIEHash.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/DIEHash.cpp @@ -319,6 +319,7 @@ case DIEValue::isLabel: case DIEValue::isBaseTypeRef: case DIEValue::isDelta: + case DIEValue::isLabelPlusOffset: llvm_unreachable("Add support for additional value types."); } } diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.h b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.h --- a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.h +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.h @@ -277,6 +277,10 @@ const MCSymbol *Label, const MCSymbol *Sec); + /// Add a label plus some offset. + DIE::value_iterator addLabelPlusOffset(DIE &Die, dwarf::Attribute Attribute, + const MCSymbol *Label, int64_t Offset); + /// Get context owner's DIE. DIE *createTypeDIE(const DICompositeType *Ty); diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp --- a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp @@ -1734,6 +1734,14 @@ } DIE::value_iterator +DwarfUnit::addLabelPlusOffset(DIE &Die, dwarf::Attribute Attribute, + const MCSymbol *Label, int64_t Offset) { + return Die.addValue( + DIEValueAllocator, Attribute, DD->getDwarfSectionOffsetForm(), + new (DIEValueAllocator) DIELabelPlusOffset(Label, Offset)); +} + +DIE::value_iterator DwarfUnit::addSectionLabel(DIE &Die, dwarf::Attribute Attribute, const MCSymbol *Label, const MCSymbol *Sec) { if (Asm->MAI->doesDwarfUseRelocationsAcrossSections())