Index: include/llvm/CodeGen/DIE.h =================================================================== --- include/llvm/CodeGen/DIE.h +++ include/llvm/CodeGen/DIE.h @@ -52,13 +52,20 @@ /// Dwarf form code. dwarf::Form Form; + /// Dwarf attribute value for DW_FORM_implicit_const + int64_t Value; + public: - DIEAbbrevData(dwarf::Attribute A, dwarf::Form F) : Attribute(A), Form(F) {} + DIEAbbrevData(dwarf::Attribute A, dwarf::Form F) + : Attribute(A), Form(F), Value(0) {} + DIEAbbrevData(dwarf::Attribute A, int64_t V) + : Attribute(A), Form(dwarf::DW_FORM_implicit_const), Value(V) {} /// Accessors. /// @{ dwarf::Attribute getAttribute() const { return Attribute; } dwarf::Form getForm() const { return Form; } + int64_t getValue() const { return Value; } /// @} /// Used to gather unique data for the abbreviation folding set. @@ -102,6 +109,11 @@ Data.push_back(DIEAbbrevData(Attribute, Form)); } + /// Adds attribute with DW_FORM_implicit_const value + void AddImplicitConstAttribute(dwarf::Attribute Attribute, int64_t Value) { + Data.push_back(DIEAbbrevData(Attribute, Value)); + } + /// Used to gather unique data for the abbreviation folding set. void Profile(FoldingSetNodeID &ID) const; Index: include/llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h =================================================================== --- include/llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h +++ include/llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h @@ -23,8 +23,9 @@ class DWARFAbbreviationDeclaration { public: struct AttributeSpec { - AttributeSpec(dwarf::Attribute A, dwarf::Form F, Optional S) - : Attr(A), Form(F), ByteSize(S) {} + AttributeSpec(dwarf::Attribute A, dwarf::Form F, Optional S, + Optional V) + : Attr(A), Form(F), ByteSize(S), Value(V) {} dwarf::Attribute Attr; dwarf::Form Form; /// If ByteSize has a value, then it contains the fixed size in bytes for @@ -33,6 +34,8 @@ /// contained in or the value size varies and must be decoded from the /// debug information in order to determine its size. Optional ByteSize; + /// Optional value (for DW_FORM_implicit_const). + Optional Value; /// Get the fixed byte size of this Form if possible. This function might /// use the DWARFUnit to calculate the size of the Form, like for /// DW_AT_address and DW_AT_ref_addr, so this isn't just an accessor for Index: include/llvm/DebugInfo/DWARF/DWARFFormValue.h =================================================================== --- include/llvm/DebugInfo/DWARF/DWARFFormValue.h +++ include/llvm/DebugInfo/DWARF/DWARFFormValue.h @@ -57,6 +57,9 @@ DWARFFormValue(dwarf::Form F = dwarf::Form(0)) : Form(F), U(nullptr) {} dwarf::Form getForm() const { return Form; } void setForm(dwarf::Form F) { Form = F; } + void setUValue(uint64_t V) { Value.uval = V; } + void setSValue(int64_t V) { Value.sval = V; } + void setPValue(const char *V) { Value.cstr = V; } bool isFormClass(FormClass FC) const; const DWARFUnit *getUnit() const { return U; } void dump(raw_ostream &OS) const; Index: lib/CodeGen/AsmPrinter/DIE.cpp =================================================================== --- lib/CodeGen/AsmPrinter/DIE.cpp +++ lib/CodeGen/AsmPrinter/DIE.cpp @@ -79,6 +79,14 @@ // Emit form type. AP->EmitULEB128(AttrData.getForm(), dwarf::FormEncodingString(AttrData.getForm()).data()); + + // Emit value for DW_FORM_implicit_const. + if (AttrData.getForm() == dwarf::DW_FORM_implicit_const) { + if (AP->getDwarfVersion() < 5) + report_fatal_error( + "DW_FORM_implicit_const is supported starting from DWARFv5"); + AP->EmitSLEB128(AttrData.getValue()); + } } // Mark end of abbreviation. @@ -160,7 +168,11 @@ DIEAbbrev DIE::generateAbbrev() const { DIEAbbrev Abbrev(Tag, hasChildren()); for (const DIEValue &V : values()) - Abbrev.AddAttribute(V.getAttribute(), V.getForm()); + if (V.getForm() == dwarf::DW_FORM_implicit_const) + Abbrev.AddImplicitConstAttribute(V.getAttribute(), + V.getDIEInteger().getValue()); + else + Abbrev.AddAttribute(V.getAttribute(), V.getForm()); return Abbrev; } @@ -398,6 +410,9 @@ case dwarf::DW_FORM_sdata: Asm->EmitSLEB128(Integer); return; + case dwarf::DW_FORM_implicit_const: + // We do not need to emit anything here: value goes to .debug_abbrev + return; default: llvm_unreachable("DIE Value form not supported yet"); } } @@ -450,6 +465,8 @@ case dwarf::DW_FORM_udata: return getULEB128Size(Integer); case dwarf::DW_FORM_sdata: + LLVM_FALLTHROUGH; + case dwarf::DW_FORM_implicit_const: return getSLEB128Size(Integer); case dwarf::DW_FORM_addr: return AP->getPointerSize(); Index: lib/CodeGen/AsmPrinter/DwarfUnit.cpp =================================================================== --- lib/CodeGen/AsmPrinter/DwarfUnit.cpp +++ lib/CodeGen/AsmPrinter/DwarfUnit.cpp @@ -200,6 +200,8 @@ Optional Form, uint64_t Integer) { if (!Form) Form = DIEInteger::BestForm(false, Integer); + assert(Form != dwarf::DW_FORM_implicit_const && + "DW_FORM_implicit_const is used only for signed integers"); Die.addValue(DIEValueAllocator, Attribute, *Form, DIEInteger(Integer)); } Index: lib/DebugInfo/DWARF/DWARFAbbreviationDeclaration.cpp =================================================================== --- lib/DebugInfo/DWARF/DWARFAbbreviationDeclaration.cpp +++ lib/DebugInfo/DWARF/DWARFAbbreviationDeclaration.cpp @@ -57,7 +57,10 @@ auto F = static_cast
(Data.getULEB128(OffsetPtr)); if (A && F) { auto FixedFormByteSize = DWARFFormValue::getFixedByteSize(F); - AttributeSpecs.push_back(AttributeSpec(A, F, FixedFormByteSize)); + Optional V; + if (F == DW_FORM_implicit_const) + V = Data.getSLEB128(OffsetPtr); + AttributeSpecs.push_back(AttributeSpec(A, F, FixedFormByteSize, V)); // If this abbrevation still has a fixed byte size, then update the // FixedAttributeSize as needed. if (FixedAttributeSize) { @@ -129,6 +132,8 @@ OS << formString; else OS << format("DW_FORM_Unknown_%x", Spec.Form); + if (Spec.Value) + OS << '\t' << Spec.Value.getValue(); OS << '\n'; } OS << '\n'; @@ -160,6 +165,11 @@ if (*MatchAttrIndex == AttrIndex) { // We have arrived at the attribute to extract, extract if from Offset. DWARFFormValue FormValue(Spec.Form); + if (Spec.Form == DW_FORM_implicit_const) { + if (Spec.Value) + FormValue.setSValue(Spec.Value.getValue()); + return FormValue; + } if (FormValue.extractValue(DebugInfoData, &Offset, &U)) return FormValue; } Index: lib/DebugInfo/DWARF/DWARFFormValue.cpp =================================================================== --- lib/DebugInfo/DWARF/DWARFFormValue.cpp +++ lib/DebugInfo/DWARF/DWARFFormValue.cpp @@ -153,7 +153,7 @@ return 16; case DW_FORM_implicit_const: - // The implicit value is stored in the abbreviation as a ULEB128, any + // The implicit value is stored in the abbreviation as a SLEB128, any // there no data in debug info. return 0; Index: test/DebugInfo/dwarfdump-implicit-const.test =================================================================== --- /dev/null +++ test/DebugInfo/dwarfdump-implicit-const.test @@ -0,0 +1,2 @@ +RUN: llvm-dwarfdump -debug-dump=abbrev %p/Inputs/implicit-const-test.o | FileCheck %s +CHECK: DW_FORM_implicit_const -9223372036854775808 Index: unittests/DebugInfo/DWARF/DWARFDebugInfoTest.cpp =================================================================== --- unittests/DebugInfo/DWARF/DWARFDebugInfoTest.cpp +++ unittests/DebugInfo/DWARF/DWARFDebugInfoTest.cpp @@ -77,6 +77,7 @@ const uint64_t Data8 = 0x0011223344556677ULL; const uint64_t Data8_2 = 0xAABBCCDDEEFF0011ULL; const int64_t SData = INT64_MIN; + const int64_t ICSData = INT64_MAX; // DW_FORM_implicit_const SData const uint64_t UData[] = {UINT64_MAX - 1, UINT64_MAX - 2, UINT64_MAX - 3, UINT64_MAX - 4, UINT64_MAX - 5, UINT64_MAX - 6, UINT64_MAX - 7, UINT64_MAX - 8, UINT64_MAX - 9}; @@ -181,6 +182,12 @@ const auto Attr_DW_FORM_sdata = static_cast(Attr++); CUDie.addAttribute(Attr_DW_FORM_sdata, DW_FORM_sdata, SData); + const auto Attr_DW_FORM_implicit_const = + static_cast(Attr++); + if (Version >= 5) + CUDie.addAttribute(Attr_DW_FORM_implicit_const, DW_FORM_implicit_const, + ICSData); + //---------------------------------------------------------------------- // Test ULEB128 based forms //---------------------------------------------------------------------- @@ -323,13 +330,14 @@ Attr_DW_FORM_flag_present, 0ULL), 1ULL); - // TODO: test Attr_DW_FORM_implicit_const extraction - //---------------------------------------------------------------------- // Test SLEB128 based forms //---------------------------------------------------------------------- EXPECT_EQ(DieDG.getAttributeValueAsSignedConstant(Attr_DW_FORM_sdata, 0), SData); + if (Version >= 5) + EXPECT_EQ(DieDG.getAttributeValueAsSignedConstant( + Attr_DW_FORM_implicit_const, 0), ICSData); //---------------------------------------------------------------------- // Test ULEB128 based forms @@ -408,6 +416,24 @@ TestAllForms<4, AddrType, RefAddrType>(); } +TEST(DWARFDebugInfo, TestDWARF32Version5Addr4AllForms) { + // Test that we can decode all forms for DWARF32, version 5, with 4 byte + // addresses. + typedef uint32_t AddrType; + // DW_FORM_ref_addr are 4 bytes in DWARF32 for version 3 and later + typedef uint32_t RefAddrType; + TestAllForms<4, AddrType, RefAddrType>(); +} + +TEST(DWARFDebugInfo, TestDWARF32Version5Addr8AllForms) { + // Test that we can decode all forms for DWARF32, version 5, with 8 byte + // addresses. + typedef uint64_t AddrType; + // DW_FORM_ref_addr are 4 bytes in DWARF32 for version 3 and later + typedef uint32_t RefAddrType; + TestAllForms<5, AddrType, RefAddrType>(); +} + template void TestChildren() { // Test that we can decode DW_FORM_ref_addr values correctly in DWARF 2 with // 4 byte addresses. DW_FORM_ref_addr values should be 4 bytes when using