diff --git a/bolt/include/bolt/Core/DebugData.h b/bolt/include/bolt/Core/DebugData.h --- a/bolt/include/bolt/Core/DebugData.h +++ b/bolt/include/bolt/Core/DebugData.h @@ -155,7 +155,7 @@ uint64_t getSectionOffset(); /// Returns a buffer containing Ranges. - virtual std::unique_ptr finalize() { + virtual std::unique_ptr releaseBuffer() { return std::move(RangesBuffer); } @@ -165,6 +165,12 @@ return Writer->getKind() == RangesWriterKind::DebugRangesWriter; } + /// Writes out range lists for a current CU being processed. + void virtual finalizeSection(){}; + + /// Needs to be invoked before each \p CU is processed. + void virtual initSection(DWARFUnit &CU){}; + protected: std::unique_ptr RangesBuffer; @@ -203,16 +209,18 @@ /// Add ranges and return offset into section. virtual uint64_t addRanges(const DebugAddressRangesVector &Ranges) override; - virtual std::unique_ptr finalize() override { + virtual std::unique_ptr releaseBuffer() override { return std::move(RangesBuffer); } - /// Needs to be invoked before each CU is processed. - /// \p CUID is a unique ID of each CU. - void initSection(uint64_t CUID); + /// Needs to be invoked before each \p CU is processed. + void virtual initSection(DWARFUnit &CU) override; /// Writes out range lists for a current CU being processed. - void finalizeSection(); + void virtual finalizeSection() override; + + // Returns true if section is empty. + bool empty() { return RangesBuffer->empty(); } static bool classof(const DebugRangesSectionWriter *Writer) { return Writer->getKind() == RangesWriterKind::DebugRangeListsWriter; @@ -220,8 +228,8 @@ private: static DebugAddrWriter *AddrWriter; - /// Unique ID of CU being processed. - uint64_t CUID{0}; + /// Used to find unique CU ID. + DWARFUnit *CU; /// Current relative offset of range list entry within this CUs rangelist /// body. uint32_t CurrentOffset{0}; @@ -275,10 +283,10 @@ virtual ~DebugAddrWriter(){}; /// Given an address returns an index in .debug_addr. /// Adds Address to map. - uint32_t getIndexFromAddress(uint64_t Address, uint64_t CUID); + uint32_t getIndexFromAddress(uint64_t Address, DWARFUnit &CU); - /// Adds {Address, Index} to DWO ID CU. - void addIndexAddress(uint64_t Address, uint32_t Index, uint64_t CUID); + /// Adds {\p Address, \p Index} to \p CU. + void addIndexAddress(uint64_t Address, uint32_t Index, DWARFUnit &CU); /// Creates consolidated .debug_addr section, and builds DWOID to offset map. virtual AddressSectionBuffer finalize(); @@ -338,6 +346,12 @@ IndexToAddressMap IndexToAddress; uint32_t CurrentIndex{0}; }; + + virtual uint64_t getCUID(DWARFUnit &Unit) { + assert(Unit.getDWOId() && "Unit is not Skeleton CU."); + return *Unit.getDWOId(); + } + BinaryContext *BC; /// Maps DWOID to AddressForDWOCU. std::unordered_map AddressMaps; @@ -357,14 +371,60 @@ /// Given DWARFUnit \p Unit returns offset of this CU in to .debug_addr /// section. virtual uint64_t getOffset(DWARFUnit &Unit) override; + +protected: + /// Given DWARFUnit \p Unit returns either DWO ID or it's offset within + /// .debug_info. + virtual uint64_t getCUID(DWARFUnit &Unit) override { + if (Unit.isDWOUnit()) { + DWARFUnit *SkeletonCU = Unit.getLinkedUnit(); + return SkeletonCU->getOffset(); + } + return Unit.getOffset(); + } +}; + +/// This class is NOT thread safe. +using DebugStrOffsetsBufferVector = SmallVector; +class DebugStrOffsetsWriter { +public: + DebugStrOffsetsWriter() { + StrOffsetsBuffer = std::make_unique(); + StrOffsetsStream = std::make_unique(*StrOffsetsBuffer); + } + + /// Initializes Buffer and Stream. + void initialize(const DWARFSection &StrOffsetsSection, + const Optional Contr); + + /// Update Str offset in .debug_str in .debug_str_offsets. + void updateAddressMap(uint32_t Index, uint32_t Address); + + /// Writes out current sections entry into .debug_str_offsets. + void finalizeSection(); + + /// Returns False if no strings were added to .debug_str. + bool isFinalized() const { return !StrOffsetsBuffer->empty(); } + + /// Returns buffer containing .debug_str_offsets. + std::unique_ptr releaseBuffer() { + return std::move(StrOffsetsBuffer); + } + +private: + std::unique_ptr StrOffsetsBuffer; + std::unique_ptr StrOffsetsStream; + std::map IndexToAddressMap; + // Section size not including header. + uint32_t CurrentSectionSize{0}; }; using DebugStrBufferVector = SmallVector; class DebugStrWriter { public: DebugStrWriter() = delete; - DebugStrWriter(BinaryContext *Bc) : BC(Bc) { create(); } - std::unique_ptr finalize() { + DebugStrWriter(BinaryContext &BC) : BC(BC) { create(); } + std::unique_ptr releaseBuffer() { return std::move(StrBuffer); } @@ -384,7 +444,7 @@ void create(); std::unique_ptr StrBuffer; std::unique_ptr StrStream; - BinaryContext *BC; + BinaryContext &BC; }; enum class LocWriterKind { DebugLocWriter, DebugLoclistWriter }; @@ -451,9 +511,9 @@ public: ~DebugLoclistWriter() {} DebugLoclistWriter() = delete; - DebugLoclistWriter(BinaryContext *BC, uint64_t CID, + DebugLoclistWriter(BinaryContext *BC, DWARFUnit &Unit, uint32_t LocListsBaseAttrOffset, uint8_t DV, bool SD) - : DebugLocWriter(BC), CUID(CID), + : DebugLocWriter(BC), CU(Unit), LocListsBaseAttrOffset(LocListsBaseAttrOffset), IsSplitDwarf(SD) { Kind = LocWriterKind::DebugLoclistWriter; DwarfVersion = DV; @@ -472,8 +532,12 @@ void finalize(uint64_t SectionOffset, SimpleBinaryPatcher &DebugInfoPatcher) override; - /// Returns DWO ID. - uint64_t getCUID() const { return CUID; } + /// Returns CU ID. + /// For Skelton CU it is a CU Offset. + /// For DWO CU it is a DWO ID. + uint64_t getCUID() const { + return CU.isDWOUnit() ? *CU.getDWOId() : CU.getOffset(); + } LocWriterKind getKind() const { return DebugLocWriter::getKind(); } @@ -511,7 +575,7 @@ uint64_t Address{0}; }; static DebugAddrWriter *AddrWriter; - uint64_t CUID{0}; + DWARFUnit &CU; uint32_t LocListsBaseAttrOffset{InvalidLocListsBaseAttrOffset}; bool IsSplitDwarf{false}; }; diff --git a/bolt/include/bolt/Rewrite/DWARFRewriter.h b/bolt/include/bolt/Rewrite/DWARFRewriter.h --- a/bolt/include/bolt/Rewrite/DWARFRewriter.h +++ b/bolt/include/bolt/Rewrite/DWARFRewriter.h @@ -48,6 +48,10 @@ /// Does not do de-duplication. std::unique_ptr StrWriter; + /// Stores and serializes information that will be put in to the + /// .debug_str_offsets DWARF section. + std::unique_ptr StrOffstsWriter; + /// .debug_abbrev section writer for the main binary. std::unique_ptr AbbrevWriter; @@ -55,6 +59,12 @@ /// Use a separate location list writer for each compilation unit LocWriters LocListWritersByCU; + using RangeListsDWOWriers = + std::unordered_map>; + /// Store Rangelists writer for each DWO CU. + RangeListsDWOWriers RangeListsWritersByCU; + using DebugAbbrevDWOWriters = std::unordered_map>; /// Abbrev section writers for DWOs. @@ -167,6 +177,14 @@ return static_cast(Iter->second.get()); } + /// Adds a \p Str to .debug_str section. + /// Uses \p AttrInfoVal to either update entry in a DIE for legacy DWARF using + /// \p DebugInfoPatcher, or for DWARF5 update an index in .debug_str_offsets + /// for this contribution of \p Unit. + void addStringHelper(DebugInfoBinaryPatcher &DebugInfoPatcher, + const DWARFUnit &Unit, const AttrInfo &AttrInfoVal, + StringRef Str); + public: DWARFRewriter(BinaryContext &BC) : BC(BC) {} diff --git a/bolt/lib/Core/BinaryContext.cpp b/bolt/lib/Core/BinaryContext.cpp --- a/bolt/lib/Core/BinaryContext.cpp +++ b/bolt/lib/Core/BinaryContext.cpp @@ -1500,6 +1500,8 @@ << DwCtx->getNumCompileUnits() << " CUs will be updated\n"; } + preprocessDWODebugInfo(); + // Populate MCContext with DWARF files from all units. StringRef GlobalPrefix = AsmInfo->getPrivateGlobalPrefix(); for (const std::unique_ptr &CU : DwCtx->compile_units()) { @@ -1521,10 +1523,16 @@ Optional Checksum = None; if (LineTable->Prologue.ContentTypes.HasMD5) Checksum = LineTable->Prologue.FileNames[0].Checksum; - BinaryLineTable.setRootFile( - CU->getCompilationDir(), - dwarf::toString(CU->getUnitDIE().find(dwarf::DW_AT_name), nullptr), - Checksum, None); + Optional Name = + dwarf::toString(CU->getUnitDIE().find(dwarf::DW_AT_name), nullptr); + if (Optional DWOID = CU->getDWOId()) { + auto Iter = DWOCUs.find(*DWOID); + assert(Iter != DWOCUs.end() && "DWO CU was not found."); + Name = dwarf::toString( + Iter->second->getUnitDIE().find(dwarf::DW_AT_name), nullptr); + } + BinaryLineTable.setRootFile(CU->getCompilationDir(), *Name, Checksum, + None); } BinaryLineTable.setDwarfVersion(DwarfVersion); @@ -1557,8 +1565,6 @@ getDwarfFile(Dir, FileName, 0, Checksum, None, CUID, DwarfVersion)); } } - - preprocessDWODebugInfo(); } bool BinaryContext::shouldEmit(const BinaryFunction &Function) const { diff --git a/bolt/lib/Core/DebugData.cpp b/bolt/lib/Core/DebugData.cpp --- a/bolt/lib/Core/DebugData.cpp +++ b/bolt/lib/Core/DebugData.cpp @@ -29,6 +29,7 @@ #include #include #include +#include #define DEBUG_TYPE "bolt-debug-info" @@ -207,7 +208,7 @@ support::endian::write(*CUBodyStream, static_cast(dwarf::DW_RLE_startx_length), support::little); - const uint32_t Index = AddrWriter->getIndexFromAddress(Range.LowPC, CUID); + uint32_t Index = AddrWriter->getIndexFromAddress(Range.LowPC, *CU); encodeULEB128(Index, *CUBodyStream); encodeULEB128(Range.HighPC - Range.LowPC, *CUBodyStream); } @@ -238,12 +239,12 @@ SectionOffset = RangesBuffer->size(); } -void DebugRangeListsSectionWriter::initSection(uint64_t CUId_) { +void DebugRangeListsSectionWriter::initSection(DWARFUnit &Unit) { CUBodyBuffer = std::make_unique(); CUBodyStream = std::make_unique(*CUBodyBuffer); RangeEntries.clear(); CurrentOffset = 0; - CUID = CUId_; + CU = &Unit; } void DebugARangesSectionWriter::addCURanges(uint64_t CUOffset, @@ -311,8 +312,9 @@ for (auto &Pair : SortedMap) dbgs() << Twine::utohexstr(Pair.second) << "\t" << Pair.first << "\n"; } -uint32_t DebugAddrWriter::getIndexFromAddress(uint64_t Address, uint64_t CUID) { +uint32_t DebugAddrWriter::getIndexFromAddress(uint64_t Address, DWARFUnit &CU) { std::lock_guard Lock(WriterMutex); + const uint64_t CUID = getCUID(CU); if (!AddressMaps.count(CUID)) AddressMaps[CUID] = AddressForDWOCU(); @@ -330,8 +332,9 @@ // IndexToAddrss. Case3) Address is in the map but Index is lower. Need to // update AddressToIndex and IndexToAddress void DebugAddrWriter::addIndexAddress(uint64_t Address, uint32_t Index, - uint64_t CUID) { + DWARFUnit &CU) { std::lock_guard Lock(WriterMutex); + const uint64_t CUID = getCUID(CU); AddressForDWOCU &Map = AddressMaps[CUID]; auto Entry = Map.find(Address); if (Entry != Map.end()) { @@ -349,16 +352,16 @@ AddressSectionBuffer Buffer; raw_svector_ostream AddressStream(Buffer); for (std::unique_ptr &CU : BC->DwCtx->compile_units()) { - Optional DWOId = CU->getDWOId(); // Handling the case wehre debug information is a mix of Debug fission and // monolitic. - if (!DWOId) + if (!CU->getDWOId()) continue; - auto AM = AddressMaps.find(*DWOId); + const uint64_t CUID = getCUID(*CU.get()); + auto AM = AddressMaps.find(CUID); assert(AM != AddressMaps.end() && "Address Map not found."); // Adding to map even if it did not contribute to .debug_addr. // The Skeleton CU will still have DW_AT_GNU_addr_base. - DWOIdToOffsetMap[*DWOId] = Buffer.size(); + DWOIdToOffsetMap[CUID] = Buffer.size(); // If does not exist this CUs DWO section didn't contribute to .debug_addr. if (AM == AddressMaps.end()) continue; @@ -410,13 +413,13 @@ DIDumpOptions DumpOpts; constexpr uint32_t HeaderSize = 8; for (std::unique_ptr &CU : BC->DwCtx->compile_units()) { - const uint64_t CUID = CU->getOffset(); + const uint64_t CUID = getCUID(*CU.get()); const uint8_t AddrSize = CU->getAddressByteSize(); - auto Iter = AddressMaps.find(CUID); + auto AMIter = AddressMaps.find(CUID); // A case where CU has entry in .debug_addr, but we don't modify addresses // for it. - if (Iter == AddressMaps.end()) { - Iter = AddressMaps.insert({CUID, AddressForDWOCU()}).first; + if (AMIter == AddressMaps.end()) { + AMIter = AddressMaps.insert({CUID, AddressForDWOCU()}).first; Optional BaseOffset = CU->getAddrOffsetSectionBase(); if (!BaseOffset) continue; @@ -430,13 +433,14 @@ } uint32_t Index = 0; for (uint64_t Addr : AddrTable.getAddressEntries()) - Iter->second.insert(Addr, Index++); + AMIter->second.insert(Addr, Index++); } DWOIdToOffsetMap[CUID] = Buffer.size() + HeaderSize; - std::vector SortedMap(Iter->second.indexToAddressBegin(), - Iter->second.indexToAdddessEnd()); + std::vector SortedMap( + AMIter->second.indexToAddressBegin(), + AMIter->second.indexToAdddessEnd()); // Sorting address in increasing order of indices. std::sort(SortedMap.begin(), SortedMap.end(), [](const IndexAddressPair &A, const IndexAddressPair &B) { @@ -478,16 +482,16 @@ } uint64_t DebugAddrWriter::getOffset(DWARFUnit &Unit) { - Optional DWOId = Unit.getDWOId(); - assert(DWOId && "Can't get offset, not a skeleton CU."); - auto Iter = DWOIdToOffsetMap.find(*DWOId); + const uint64_t CUID = getCUID(Unit); + assert(CUID && "Can't get offset, not a skeleton CU."); + auto Iter = DWOIdToOffsetMap.find(CUID); assert(Iter != DWOIdToOffsetMap.end() && "Offset in to.debug_addr was not found for DWO ID."); return Iter->second; } uint64_t DebugAddrWriterDwarf5::getOffset(DWARFUnit &Unit) { - auto Iter = DWOIdToOffsetMap.find(Unit.getOffset()); + auto Iter = DWOIdToOffsetMap.find(getCUID(Unit)); assert(Iter != DWOIdToOffsetMap.end() && "Offset in to.debug_addr was not found for DWO ID."); return Iter->second; @@ -601,7 +605,7 @@ support::endian::write(*LocBodyStream, static_cast(dwarf::DW_LLE_startx_length), support::little); - const uint32_t Index = AddrWriter->getIndexFromAddress(Entry.LowPC, CUID); + const uint32_t Index = AddrWriter->getIndexFromAddress(Entry.LowPC, CU); encodeULEB128(Index, *LocBodyStream); encodeULEB128(Entry.HighPC - Entry.LowPC, *LocBodyStream); encodeULEB128(Entry.Expr.size(), *LocBodyStream); @@ -647,7 +651,7 @@ support::endian::write(*LocStream, static_cast(dwarf::DW_LLE_startx_length), support::little); - const uint32_t Index = AddrWriter->getIndexFromAddress(Entry.LowPC, CUID); + const uint32_t Index = AddrWriter->getIndexFromAddress(Entry.LowPC, CU); encodeULEB128(Index, *LocStream); // TODO: Support DWARF5 @@ -1053,13 +1057,48 @@ return NewBinaryContents; } +void DebugStrOffsetsWriter::initialize( + const DWARFSection &StrOffsetsSection, + const Optional Contr) { + if (!Contr) + return; + + const uint8_t DwarfOffsetByteSize = Contr->getDwarfOffsetByteSize(); + assert(DwarfOffsetByteSize == 4 && + "Dwarf String Offsets Byte Size is not supported."); + uint32_t Index = 0; + for (uint64_t Offset = 0; Offset < Contr->Size; Offset += DwarfOffsetByteSize) + IndexToAddressMap[Index++] = *reinterpret_cast( + StrOffsetsSection.Data.data() + Contr->Base + Offset); +} + +void DebugStrOffsetsWriter::updateAddressMap(uint32_t Index, uint32_t Address) { + assert(IndexToAddressMap.count(Index) > 0 && "Index is not found."); + IndexToAddressMap[Index] = Address; +} + +void DebugStrOffsetsWriter::finalizeSection() { + if (IndexToAddressMap.empty()) + return; + // Writing out the header for each section. + support::endian::write(*StrOffsetsStream, CurrentSectionSize + 4, + support::little); + support::endian::write(*StrOffsetsStream, static_cast(5), + support::little); + support::endian::write(*StrOffsetsStream, static_cast(0), + support::little); + for (const auto &Entry : IndexToAddressMap) + support::endian::write(*StrOffsetsStream, Entry.second, support::little); + IndexToAddressMap.clear(); +} + void DebugStrWriter::create() { StrBuffer = std::make_unique(); StrStream = std::make_unique(*StrBuffer); } void DebugStrWriter::initialize() { - auto StrSection = BC->DwCtx->getDWARFObj().getStrSection(); + auto StrSection = BC.DwCtx->getDWARFObj().getStrSection(); (*StrStream) << StrSection; } diff --git a/bolt/lib/Rewrite/DWARFRewriter.cpp b/bolt/lib/Rewrite/DWARFRewriter.cpp --- a/bolt/lib/Rewrite/DWARFRewriter.cpp +++ b/bolt/lib/Rewrite/DWARFRewriter.cpp @@ -163,6 +163,19 @@ return DWOName; } +void DWARFRewriter::addStringHelper(DebugInfoBinaryPatcher &DebugInfoPatcher, + const DWARFUnit &Unit, + const AttrInfo &AttrInfoVal, + StringRef Str) { + uint32_t NewOffset = StrWriter->addString(Str); + if (Unit.getVersion() == 5) { + StrOffstsWriter->updateAddressMap(AttrInfoVal.V.getRawUValue(), NewOffset); + return; + } + DebugInfoPatcher.addLE32Patch(AttrInfoVal.Offset, NewOffset, + AttrInfoVal.Size); +} + void DWARFRewriter::updateDebugInfo() { ErrorOr DebugInfo = BC.getUniqueSectionByName(".debug_info"); if (!DebugInfo) @@ -172,7 +185,10 @@ static_cast(DebugInfo->getPatcher()); ARangesSectionWriter = std::make_unique(); - StrWriter = std::make_unique(&BC); + StrWriter = std::make_unique(BC); + + StrOffstsWriter = std::make_unique(); + AbbrevWriter = std::make_unique(*BC.DwCtx); if (BC.isDWARF5Used()) { @@ -191,19 +207,39 @@ size_t CUIndex = 0; for (std::unique_ptr &CU : BC.DwCtx->compile_units()) { - if (CU->getVersion() >= 5) { + const uint16_t DwarfVersion = CU->getVersion(); + if (DwarfVersion >= 5) { uint32_t AttrInfoOffset = DebugLoclistWriter::InvalidLocListsBaseAttrOffset; if (Optional AttrInfoVal = - findAttributeInfo(CU->getUnitDIE(), dwarf::DW_AT_loclists_base)) + findAttributeInfo(CU->getUnitDIE(), dwarf::DW_AT_loclists_base)) { AttrInfoOffset = AttrInfoVal->Offset; + LocListWritersByCU[CUIndex] = std::make_unique( + &BC, *CU.get(), AttrInfoOffset, DwarfVersion, false); + } + if (Optional DWOId = CU->getDWOId()) { + assert(LocListWritersByCU.count(*DWOId) == 0 && + "RangeLists writer for DWO unit already exists."); + auto RangeListsSectionWriter = + std::make_unique(); + RangeListsSectionWriter->initSection(*CU.get()); + RangeListsWritersByCU[*DWOId] = std::move(RangeListsSectionWriter); + } - LocListWritersByCU[CUIndex] = std::make_unique( - &BC, CU->isDWOUnit() ? *CU->getDWOId() : CU->getOffset(), - AttrInfoOffset, 5, false); } else { LocListWritersByCU[CUIndex] = std::make_unique(&BC); } + + if (Optional DWOId = CU->getDWOId()) { + assert(LocListWritersByCU.count(*DWOId) == 0 && + "LocList writer for DWO unit already exists."); + // Work around some bug in llvm-15. If I pass in directly lld reports + // undefined symbol. + auto constexpr WorkAround = + DebugLoclistWriter::InvalidLocListsBaseAttrOffset; + LocListWritersByCU[*DWOId] = std::make_unique( + &BC, *CU.get(), WorkAround, DwarfVersion, true); + } ++CUIndex; } @@ -226,19 +262,15 @@ std::lock_guard Lock(AccessMutex); ObjectName = getDWOName(Unit, &NameToIndexMap, DWOIdToName); } - - uint32_t NewOffset = StrWriter->addString(ObjectName.c_str()); - DebugInfoPatcher->addLE32Patch(AttrInfoVal->Offset, NewOffset, - AttrInfoVal->Size); + addStringHelper(*DebugInfoPatcher, Unit, *AttrInfoVal, ObjectName.c_str()); AttrInfoVal = findAttributeInfo(DIE, dwarf::DW_AT_comp_dir); (void)AttrInfoVal; assert(AttrInfoVal && "DW_AT_comp_dir is not in Skeleton CU."); if (!opts::DwarfOutputPath.empty()) { - uint32_t NewOffset = StrWriter->addString(opts::DwarfOutputPath.c_str()); - DebugInfoPatcher->addLE32Patch(AttrInfoVal->Offset, NewOffset, - AttrInfoVal->Size); + addStringHelper(*DebugInfoPatcher, Unit, *AttrInfoVal, + opts::DwarfOutputPath.c_str()); } }; @@ -248,6 +280,8 @@ Optional SplitCU; Optional RangesBase; llvm::Optional DWOId = Unit->getDWOId(); + StrOffstsWriter->initialize(Unit->getStringOffsetSection(), + Unit->getStringOffsetsTableContribution()); if (DWOId) SplitCU = BC.getDWOCU(*DWOId); @@ -256,56 +290,59 @@ if (SplitCU) { updateDWONameCompDir(*Unit); - // Assuming there is unique DWOID per binary. i.e. two or more CUs don't - // have same DWO ID. - assert(LocListWritersByCU.count(*DWOId) == 0 && - "LocList writer for DWO unit already exists."); - { - std::lock_guard Lock(AccessMutex); - DebugLocWriter = - LocListWritersByCU - .insert({*DWOId, std::make_unique( - &BC, *DWOId, 0, Unit->getVersion(), true)}) - .first->second.get(); - } DebugInfoBinaryPatcher *DwoDebugInfoPatcher = llvm::cast( getBinaryDWODebugInfoPatcher(*DWOId)); - RangesBase = RangesSectionWriter->getSectionOffset(); DWARFContext *DWOCtx = BC.getDWOContext(); // Setting this CU offset with DWP to normalize DIE offsets to uint32_t if (DWOCtx && !DWOCtx->getCUIndex().getRows().empty()) DwoDebugInfoPatcher->setDWPOffset((*SplitCU)->getOffset()); - DwoDebugInfoPatcher->setRangeBase(*RangesBase); + + { + std::lock_guard Lock(AccessMutex); + DebugLocWriter = LocListWritersByCU[*DWOId].get(); + } + DebugRangesSectionWriter *TempRangesSectionWriter = + RangesSectionWriter.get(); + if (Unit->getVersion() >= 5) { + TempRangesSectionWriter = RangeListsWritersByCU[*DWOId].get(); + } else { + RangesBase = RangesSectionWriter->getSectionOffset(); + // For DWARF5 there is now .debug_rnglists.dwo, so don't need to + // update rnglists base. + DwoDebugInfoPatcher->setRangeBase(*RangesBase); + } + DwoDebugInfoPatcher->addUnitBaseOffsetLabel((*SplitCU)->getOffset()); DebugAbbrevWriter *DWOAbbrevWriter = createBinaryDWOAbbrevWriter((*SplitCU)->getContext(), *DWOId); updateUnitDebugInfo(*(*SplitCU), *DwoDebugInfoPatcher, *DWOAbbrevWriter, - *DebugLocWriter, *RangesSectionWriter); + *DebugLocWriter, *TempRangesSectionWriter); DwoDebugInfoPatcher->clearDestinationLabels(); if (!DwoDebugInfoPatcher->getWasRangBasedUsed()) RangesBase = None; + if (Unit->getVersion() >= 5) + TempRangesSectionWriter->finalizeSection(); } { std::lock_guard Lock(AccessMutex); - DebugLocWriter = LocListWritersByCU[CUIndex].get(); + auto LocListWriterIter = LocListWritersByCU.find(CUIndex); + if (LocListWriterIter != LocListWritersByCU.end()) + DebugLocWriter = LocListWriterIter->second.get(); } if (Unit->getVersion() >= 5) { RangesBase = RangesSectionWriter->getSectionOffset() + getDWARF5RngListLocListHeaderSize(); - reinterpret_cast( - RangesSectionWriter.get()) - ->initSection(Unit->getOffset()); + RangesSectionWriter.get()->initSection(*Unit); + StrOffstsWriter->finalizeSection(); } DebugInfoPatcher->addUnitBaseOffsetLabel(Unit->getOffset()); updateUnitDebugInfo(*Unit, *DebugInfoPatcher, *AbbrevWriter, *DebugLocWriter, *RangesSectionWriter, RangesBase); if (Unit->getVersion() >= 5) - reinterpret_cast( - RangesSectionWriter.get()) - ->finalizeSection(); + RangesSectionWriter.get()->finalizeSection(); }; CUIndex = 0; @@ -336,14 +373,6 @@ updateGdbIndexSection(OffsetMap); } -static uint64_t getCUId(DWARFUnit &Unit) { - if (Unit.getVersion() >= 5) - return Unit.getOffset(); - - assert(Unit.isDWOUnit() && "Unit is not Skeleton CU."); - return *Unit.getDWOId(); -} - void DWARFRewriter::updateUnitDebugInfo( DWARFUnit &Unit, DebugInfoBinaryPatcher &DebugInfoPatcher, DebugAbbrevWriter &AbbrevWriter, DebugLocWriter &DebugLocWriter, @@ -376,7 +405,16 @@ DWARFDie DIE(&Unit, &Die); switch (DIE.getTag()) { - case dwarf::DW_TAG_compile_unit: { + case dwarf::DW_TAG_compile_unit: + case dwarf::DW_TAG_skeleton_unit: { + // For dwarf5 section 3.1.3 + // The following attributes are not part of a split full compilation unit + // entry but instead are inherited (if present) from the corresponding + // skeleton compilation unit: DW_AT_low_pc, DW_AT_high_pc, DW_AT_ranges, + // DW_AT_stmt_list, DW_AT_comp_dir, DW_AT_str_offsets_base, + // DW_AT_addr_base and DW_AT_rnglists_base. + if (Unit.getVersion() == 5 && Unit.isDWOUnit()) + continue; auto ModuleRangesOrError = DIE.getAddressRanges(); if (!ModuleRangesOrError) { consumeError(ModuleRangesOrError.takeError()); @@ -501,7 +539,7 @@ case dwarf::DW_LLE_offset_pair: assert( (Entry.SectionIndex == SectionedAddress::UndefSection && - !Unit.isDWOUnit()) && + (!Unit.isDWOUnit() || Unit.getVersion() == 5)) && "absolute address expected"); InputLL.emplace_back(DebugLocationEntry{ BaseAddress + Entry.Value0, BaseAddress + Entry.Value1, @@ -614,7 +652,7 @@ const uint32_t EncodingSize = Expr.getOperandEndOffset(0) - PrevOffset - SizeOfOpcode; const uint32_t Index = AddrWriter->getIndexFromAddress( - EntryAddress->Address, getCUId(Unit)); + EntryAddress->Address, Unit); // Encoding new size. SmallString<8> Tmp; raw_svector_ostream OSE(Tmp); @@ -626,8 +664,7 @@ } else { // TODO: Re-do this as DWARF5. AddrWriter->addIndexAddress(EntryAddress->Address, - static_cast(Index), - getCUId(Unit)); + static_cast(Index), Unit); } if (Expr.getDescription().Op[1] == DWARFExpression::Operation::SizeNA) @@ -669,10 +706,10 @@ // TODO: We can now re-write .debug_info. This can be simplified to // just getting a new index and creating a patch. AddrWriter->addIndexAddress(NewAddress ? NewAddress : Address, - Index, getCUId(Unit)); + Index, Unit); } else if (Form == dwarf::DW_FORM_addrx) { const uint32_t Index = AddrWriter->getIndexFromAddress( - NewAddress ? NewAddress : Address, getCUId(Unit)); + NewAddress ? NewAddress : Address, Unit); DebugInfoPatcher.addUDataPatch(AttrOffset, Index, AttrVal->Size); } else { DebugInfoPatcher.addLE64Patch(AttrOffset, NewAddress); @@ -908,14 +945,23 @@ if (StrWriter->isInitialized()) { RewriteInstance::addToDebugSectionsToOverwrite(".debug_str"); std::unique_ptr DebugStrSectionContents = - StrWriter->finalize(); + StrWriter->releaseBuffer(); BC.registerOrUpdateNoteSection(".debug_str", copyByteArray(*DebugStrSectionContents), DebugStrSectionContents->size()); } + if (StrOffstsWriter->isFinalized()) { + RewriteInstance::addToDebugSectionsToOverwrite(".debug_str_offsets"); + std::unique_ptr + DebugStrOffsetsSectionContents = StrOffstsWriter->releaseBuffer(); + BC.registerOrUpdateNoteSection( + ".debug_str_offsets", copyByteArray(*DebugStrOffsetsSectionContents), + DebugStrOffsetsSectionContents->size()); + } + std::unique_ptr RangesSectionContents = - RangesSectionWriter->finalize(); + RangesSectionWriter->releaseBuffer(); BC.registerOrUpdateNoteSection( llvm::isa(*RangesSectionWriter) ? ".debug_rnglists" @@ -1076,7 +1122,11 @@ {"debug_str.dwo", {MCOFI.getDwarfStrDWOSection(), DW_SECT_EXT_unknown}}, {"debug_loc.dwo", {MCOFI.getDwarfLocDWOSection(), DW_SECT_EXT_LOC}}, {"debug_abbrev.dwo", {MCOFI.getDwarfAbbrevDWOSection(), DW_SECT_ABBREV}}, - {"debug_line.dwo", {MCOFI.getDwarfLineDWOSection(), DW_SECT_LINE}}}; + {"debug_line.dwo", {MCOFI.getDwarfLineDWOSection(), DW_SECT_LINE}}, + {"debug_loclists.dwo", + {MCOFI.getDwarfLoclistsDWOSection(), DW_SECT_LOCLISTS}}, + {"debug_rnglists.dwo", + {MCOFI.getDwarfRnglistsDWOSection(), DW_SECT_RNGLISTS}}}; return KnownSectionsTemp; } @@ -1090,11 +1140,14 @@ // Exctracts an appropriate slice if input is DWP. // Applies patches or overwrites the section. -Optional updateDebugData( - DWARFContext &DWCtx, std::string &Storage, const SectionRef &Section, - const StringMap &KnownSections, MCStreamer &Streamer, - DWARFRewriter &Writer, const DWARFUnitIndex::Entry *DWOEntry, - uint64_t DWOId, std::unique_ptr &OutputBuffer) { +Optional +updateDebugData(DWARFContext &DWCtx, std::string &Storage, + StringRef SectionName, StringRef SectionContents, + const StringMap &KnownSections, + MCStreamer &Streamer, DWARFRewriter &Writer, + const DWARFUnitIndex::Entry *DWOEntry, uint64_t DWOId, + std::unique_ptr &OutputBuffer, + DebugRangeListsSectionWriter *RangeListsWriter) { auto applyPatch = [&](DebugInfoBinaryPatcher *Patcher, StringRef Data) -> StringRef { Patcher->computeNewOffsets(DWCtx, true); @@ -1115,20 +1168,18 @@ return OutData; }; - StringRef Name = getSectionName(Section); - auto SectionIter = KnownSections.find(Name); + auto SectionIter = KnownSections.find(SectionName); if (SectionIter == KnownSections.end()) return None; Streamer.SwitchSection(SectionIter->second.first); - Expected Contents = Section.getContents(); - assert(Contents && "Invalid contents."); - StringRef OutData = *Contents; + StringRef OutData = SectionContents; uint32_t DWPOffset = 0; switch (SectionIter->second.second) { default: { - if (!Name.equals("debug_str.dwo")) - errs() << "BOLT-WARNING: Unsupported Debug section: " << Name << "\n"; + if (!SectionName.equals("debug_str.dwo")) + errs() << "BOLT-WARNING: unsupported debug section: " << SectionName + << "\n"; return OutData; } case DWARFSectionKind::DW_SECT_INFO: { @@ -1155,7 +1206,8 @@ return StringRef(reinterpret_cast(OutputBuffer->data()), OutputBuffer->size()); } - case DWARFSectionKind::DW_SECT_EXT_LOC: { + case DWARFSectionKind::DW_SECT_EXT_LOC: + case DWARFSectionKind::DW_SECT_LOCLISTS: { DebugLocWriter *LocWriter = Writer.getDebugLocWriter(DWOId); OutputBuffer = LocWriter->getBuffer(); // Creating explicit StringRef here, otherwise @@ -1168,6 +1220,11 @@ return getSliceData(DWOEntry, OutData, DWARFSectionKind::DW_SECT_LINE, DWPOffset); } + case DWARFSectionKind::DW_SECT_RNGLISTS: { + OutputBuffer = RangeListsWriter->releaseBuffer(); + return StringRef(reinterpret_cast(OutputBuffer->data()), + OutputBuffer->size()); + } } } @@ -1255,12 +1312,23 @@ bool StrSectionWrittenOut = false; const object::ObjectFile *DWOFile = (*DWOCU)->getContext().getDWARFObj().getFile(); + + DebugRangeListsSectionWriter *RangeListssWriter = nullptr; + if (CU->getVersion() == 5) { + assert(RangeListsWritersByCU.count(*DWOId) != 0 && + "No RangeListsWriter for DWO ID."); + RangeListssWriter = RangeListsWritersByCU[*DWOId].get(); + } for (const SectionRef &Section : DWOFile->sections()) { std::string Storage = ""; std::unique_ptr OutputData; - Optional TOutData = updateDebugData( - (*DWOCU)->getContext(), Storage, Section, KnownSections, *Streamer, - *this, DWOEntry, *DWOId, OutputData); + StringRef SectionName = getSectionName(Section); + Expected Contents = Section.getContents(); + assert(Contents && "Invalid contents."); + Optional TOutData = + updateDebugData((*DWOCU)->getContext(), Storage, SectionName, + *Contents, KnownSections, *Streamer, *this, DWOEntry, + *DWOId, OutputData, RangeListssWriter); if (!TOutData) continue; @@ -1355,12 +1423,36 @@ StringMap KnownSections = createKnownSectionsMap(*Streamer->getContext().getObjectFileInfo()); + DebugRangeListsSectionWriter *RangeListssWriter = nullptr; + if (CU->getVersion() == 5) { + assert(RangeListsWritersByCU.count(*DWOId) != 0 && + "No RangeListsWriter for DWO ID."); + RangeListssWriter = RangeListsWritersByCU[*DWOId].get(); + + // Handling .debug_rnglists.dwo seperatly. The original .o/.dwo might not + // have .debug_rnglists so won't be part of the loop below. + if (!RangeListssWriter->empty()) { + std::string Storage = ""; + std::unique_ptr OutputData; + if (Optional OutData = updateDebugData( + (*DWOCU)->getContext(), Storage, "debug_rnglists.dwo", "", + KnownSections, *Streamer, *this, DWOEntry, *DWOId, OutputData, + RangeListssWriter)) + Streamer->emitBytes(*OutData); + } + } for (const SectionRef &Section : File->sections()) { std::string Storage = ""; std::unique_ptr OutputData; - if (Optional OutData = updateDebugData( - (*DWOCU)->getContext(), Storage, Section, KnownSections, - *Streamer, *this, DWOEntry, *DWOId, OutputData)) + StringRef SectionName = getSectionName(Section); + if (SectionName == "debug_rnglists.dwo") + continue; + Expected Contents = Section.getContents(); + assert(Contents && "Invalid contents."); + if (Optional OutData = + updateDebugData((*DWOCU)->getContext(), Storage, SectionName, + *Contents, KnownSections, *Streamer, *this, + DWOEntry, *DWOId, OutputData, RangeListssWriter)) Streamer->emitBytes(*OutData); } Streamer->Finish(); @@ -1630,8 +1722,8 @@ // DW_FORM_addrx. Former is when DW_AT_rnglists_base is present. Latter is // when it's absent. if (LowForm == dwarf::DW_FORM_addrx) { - uint32_t Index = - AddrWriter->getIndexFromAddress(0, DIE.getDwarfUnit()->getOffset()); + const uint32_t Index = + AddrWriter->getIndexFromAddress(0, *DIE.getDwarfUnit()); DebugInfoPatcher.addUDataPatch(LowPCOffset, Index, LowPCVal->Size); } else DebugInfoPatcher.addLE64Patch(LowPCOffset, 0); diff --git a/bolt/test/X86/Inputs/dwarf4-df-dualcu-helper.ll b/bolt/test/X86/Inputs/dwarf4-df-dualcu-helper.ll new file mode 100644 --- /dev/null +++ b/bolt/test/X86/Inputs/dwarf4-df-dualcu-helper.ll @@ -0,0 +1,81 @@ +; clang++ -g -gdwarf-4 -emit-llvm -S helper.cpp +; int z = 0; +; int d = 0; +; +; int helper(int z_, int d_) { +; z += z_; +; d += d_; +; return z * d; +; } + +; ModuleID = 'helper.cpp' +source_filename = "helper.cpp" +target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +@z = dso_local global i32 0, align 4, !dbg !0 +@d = dso_local global i32 0, align 4, !dbg !5 + +; Function Attrs: mustprogress noinline nounwind optnone uwtable +define dso_local noundef i32 @_Z6helperii(i32 noundef %z_, i32 noundef %d_) #0 !dbg !14 { +entry: + %z_.addr = alloca i32, align 4 + %d_.addr = alloca i32, align 4 + store i32 %z_, i32* %z_.addr, align 4 + call void @llvm.dbg.declare(metadata i32* %z_.addr, metadata !18, metadata !DIExpression()), !dbg !19 + store i32 %d_, i32* %d_.addr, align 4 + call void @llvm.dbg.declare(metadata i32* %d_.addr, metadata !20, metadata !DIExpression()), !dbg !21 + %0 = load i32, i32* %z_.addr, align 4, !dbg !22 + %1 = load i32, i32* @z, align 4, !dbg !23 + %add = add nsw i32 %1, %0, !dbg !23 + store i32 %add, i32* @z, align 4, !dbg !23 + %2 = load i32, i32* %d_.addr, align 4, !dbg !24 + %3 = load i32, i32* @d, align 4, !dbg !25 + %add1 = add nsw i32 %3, %2, !dbg !25 + store i32 %add1, i32* @d, align 4, !dbg !25 + %4 = load i32, i32* @z, align 4, !dbg !26 + %5 = load i32, i32* @d, align 4, !dbg !27 + %mul = mul nsw i32 %4, %5, !dbg !28 + ret i32 %mul, !dbg !29 +} + +; Function Attrs: nofree nosync nounwind readnone speculatable willreturn +declare void @llvm.dbg.declare(metadata, metadata, metadata) #1 + +attributes #0 = { mustprogress noinline nounwind optnone uwtable "frame-pointer"="all" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" } +attributes #1 = { nofree nosync nounwind readnone speculatable willreturn } + +!llvm.dbg.cu = !{!2} +!llvm.module.flags = !{!8, !9, !10, !11, !12} +!llvm.ident = !{!13} + +!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression()) +!1 = distinct !DIGlobalVariable(name: "z", scope: !2, file: !3, line: 1, type: !7, isLocal: false, isDefinition: true) +!2 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !3, producer: "clang version 15.0.0", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, globals: !4, splitDebugInlining: false, nameTableKind: None) +!3 = !DIFile(filename: "helper.cpp", directory: ".") +!4 = !{!0, !5} +!5 = !DIGlobalVariableExpression(var: !6, expr: !DIExpression()) +!6 = distinct !DIGlobalVariable(name: "d", scope: !2, file: !3, line: 2, type: !7, isLocal: false, isDefinition: true) +!7 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!8 = !{i32 7, !"Dwarf Version", i32 4} +!9 = !{i32 2, !"Debug Info Version", i32 3} +!10 = !{i32 1, !"wchar_size", i32 4} +!11 = !{i32 7, !"uwtable", i32 2} +!12 = !{i32 7, !"frame-pointer", i32 2} +!13 = !{!"clang version 15.0.0"} +!14 = distinct !DISubprogram(name: "helper", linkageName: "_Z6helperii", scope: !3, file: !3, line: 4, type: !15, scopeLine: 4, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !2, retainedNodes: !17) +!15 = !DISubroutineType(types: !16) +!16 = !{!7, !7, !7} +!17 = !{} +!18 = !DILocalVariable(name: "z_", arg: 1, scope: !14, file: !3, line: 4, type: !7) +!19 = !DILocation(line: 4, column: 16, scope: !14) +!20 = !DILocalVariable(name: "d_", arg: 2, scope: !14, file: !3, line: 4, type: !7) +!21 = !DILocation(line: 4, column: 24, scope: !14) +!22 = !DILocation(line: 5, column: 7, scope: !14) +!23 = !DILocation(line: 5, column: 4, scope: !14) +!24 = !DILocation(line: 6, column: 7, scope: !14) +!25 = !DILocation(line: 6, column: 4, scope: !14) +!26 = !DILocation(line: 7, column: 9, scope: !14) +!27 = !DILocation(line: 7, column: 13, scope: !14) +!28 = !DILocation(line: 7, column: 11, scope: !14) +!29 = !DILocation(line: 7, column: 2, scope: !14) diff --git a/bolt/test/X86/Inputs/dwarf4-df-dualcu-loclist-helper.ll b/bolt/test/X86/Inputs/dwarf4-df-dualcu-loclist-helper.ll new file mode 100644 --- /dev/null +++ b/bolt/test/X86/Inputs/dwarf4-df-dualcu-loclist-helper.ll @@ -0,0 +1,61 @@ +; ModuleID = 'helper.cpp' +source_filename = "helper.cpp" +target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +@z = dso_local local_unnamed_addr global i32 0, align 4, !dbg !0 +@d = dso_local local_unnamed_addr global i32 0, align 4, !dbg !5 + +; Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn uwtable +define dso_local noundef i32 @_Z6helperii(i32 noundef %z_, i32 noundef %d_) local_unnamed_addr #0 !dbg !13 { +entry: + call void @llvm.dbg.value(metadata i32 %z_, metadata !17, metadata !DIExpression()), !dbg !19 + call void @llvm.dbg.value(metadata i32 %d_, metadata !18, metadata !DIExpression()), !dbg !19 + %0 = load i32, i32* @z, align 4, !dbg !20, !tbaa !21 + %add = add nsw i32 %0, %z_, !dbg !20 + store i32 %add, i32* @z, align 4, !dbg !20, !tbaa !21 + %1 = load i32, i32* @d, align 4, !dbg !25, !tbaa !21 + %add1 = add nsw i32 %1, %d_, !dbg !25 + store i32 %add1, i32* @d, align 4, !dbg !25, !tbaa !21 + %mul = mul nsw i32 %add1, %add, !dbg !26 + ret i32 %mul, !dbg !27 +} + +; Function Attrs: nocallback nofree nosync nounwind readnone speculatable willreturn +declare void @llvm.dbg.value(metadata, metadata, metadata) #1 + +attributes #0 = { mustprogress nofree norecurse nosync nounwind willreturn uwtable "frame-pointer"="none" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" } +attributes #1 = { nocallback nofree nosync nounwind readnone speculatable willreturn } + +!llvm.dbg.cu = !{!2} +!llvm.module.flags = !{!8, !9, !10, !11} +!llvm.ident = !{!12} + +!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression()) +!1 = distinct !DIGlobalVariable(name: "z", scope: !2, file: !3, line: 1, type: !7, isLocal: false, isDefinition: true) +!2 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !3, producer: "clang version 15.0.0", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, globals: !4, splitDebugInlining: false, nameTableKind: None) +!3 = !DIFile(filename: "helper.cpp", directory: ".") +!4 = !{!0, !5} +!5 = !DIGlobalVariableExpression(var: !6, expr: !DIExpression()) +!6 = distinct !DIGlobalVariable(name: "d", scope: !2, file: !3, line: 2, type: !7, isLocal: false, isDefinition: true) +!7 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!8 = !{i32 7, !"Dwarf Version", i32 4} +!9 = !{i32 2, !"Debug Info Version", i32 3} +!10 = !{i32 1, !"wchar_size", i32 4} +!11 = !{i32 7, !"uwtable", i32 2} +!12 = !{!"clang version 15.0.0"} +!13 = distinct !DISubprogram(name: "helper", linkageName: "_Z6helperii", scope: !3, file: !3, line: 4, type: !14, scopeLine: 4, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !2, retainedNodes: !16) +!14 = !DISubroutineType(types: !15) +!15 = !{!7, !7, !7} +!16 = !{!17, !18} +!17 = !DILocalVariable(name: "z_", arg: 1, scope: !13, file: !3, line: 4, type: !7) +!18 = !DILocalVariable(name: "d_", arg: 2, scope: !13, file: !3, line: 4, type: !7) +!19 = !DILocation(line: 0, scope: !13) +!20 = !DILocation(line: 5, column: 4, scope: !13) +!21 = !{!22, !22, i64 0} +!22 = !{!"int", !23, i64 0} +!23 = !{!"omnipotent char", !24, i64 0} +!24 = !{!"Simple C++ TBAA"} +!25 = !DILocation(line: 6, column: 4, scope: !13) +!26 = !DILocation(line: 7, column: 11, scope: !13) +!27 = !DILocation(line: 7, column: 2, scope: !13) diff --git a/bolt/test/X86/Inputs/dwarf4-df-dualcu-loclist-main.ll b/bolt/test/X86/Inputs/dwarf4-df-dualcu-loclist-main.ll new file mode 100644 --- /dev/null +++ b/bolt/test/X86/Inputs/dwarf4-df-dualcu-loclist-main.ll @@ -0,0 +1,99 @@ +; ModuleID = 'main.cpp' +source_filename = "main.cpp" +target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +@x = dso_local local_unnamed_addr global i32 0, align 4, !dbg !0 +@y = dso_local local_unnamed_addr global i32 1, align 4, !dbg !5 + +; Function Attrs: argmemonly mustprogress nofree norecurse nosync nounwind willreturn uwtable +define dso_local void @_Z3usePiS_(i32* nocapture noundef %x, i32* nocapture noundef %y) local_unnamed_addr #0 !dbg !13 { +entry: + call void @llvm.dbg.value(metadata i32* %x, metadata !18, metadata !DIExpression()), !dbg !20 + call void @llvm.dbg.value(metadata i32* %y, metadata !19, metadata !DIExpression()), !dbg !20 + %0 = load i32, i32* %x, align 4, !dbg !21, !tbaa !22 + %add = add nsw i32 %0, 4, !dbg !21 + store i32 %add, i32* %x, align 4, !dbg !21, !tbaa !22 + %1 = load i32, i32* %y, align 4, !dbg !26, !tbaa !22 + %sub = add nsw i32 %1, -2, !dbg !26 + store i32 %sub, i32* %y, align 4, !dbg !26, !tbaa !22 + ret void, !dbg !27 +} + +; Function Attrs: mustprogress norecurse uwtable +define dso_local noundef i32 @main(i32 noundef %argc, i8** nocapture noundef readnone %argv) local_unnamed_addr #1 !dbg !28 { +entry: + call void @llvm.dbg.value(metadata i32 %argc, metadata !35, metadata !DIExpression()), !dbg !37 + call void @llvm.dbg.value(metadata i8** %argv, metadata !36, metadata !DIExpression()), !dbg !37 + call void @llvm.dbg.value(metadata i32* @x, metadata !18, metadata !DIExpression()), !dbg !38 + call void @llvm.dbg.value(metadata i32* @y, metadata !19, metadata !DIExpression()), !dbg !38 + %add.i = add nsw i32 %argc, 4, !dbg !40 + store i32 %add.i, i32* @x, align 4, !dbg !40, !tbaa !22 + %sub.i = add nsw i32 %argc, 1, !dbg !41 + store i32 %sub.i, i32* @y, align 4, !dbg !41, !tbaa !22 + %call = tail call noundef i32 @_Z6helperii(i32 noundef %add.i, i32 noundef %sub.i), !dbg !42 + ret i32 %call, !dbg !43 +} + +declare !dbg !44 dso_local noundef i32 @_Z6helperii(i32 noundef, i32 noundef) local_unnamed_addr #2 + +; Function Attrs: nocallback nofree nosync nounwind readnone speculatable willreturn +declare void @llvm.dbg.value(metadata, metadata, metadata) #3 + +attributes #0 = { argmemonly mustprogress nofree norecurse nosync nounwind willreturn uwtable "frame-pointer"="none" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" } +attributes #1 = { mustprogress norecurse uwtable "frame-pointer"="none" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" } +attributes #2 = { "frame-pointer"="none" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" } +attributes #3 = { nocallback nofree nosync nounwind readnone speculatable willreturn } + +!llvm.dbg.cu = !{!2} +!llvm.module.flags = !{!8, !9, !10, !11} +!llvm.ident = !{!12} + +!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression()) +!1 = distinct !DIGlobalVariable(name: "x", scope: !2, file: !3, line: 7, type: !7, isLocal: false, isDefinition: true) +!2 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !3, producer: "clang version 15.0.0", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, globals: !4, splitDebugInlining: false, nameTableKind: None) +!3 = !DIFile(filename: "main.cpp", directory: ".") +!4 = !{!0, !5} +!5 = !DIGlobalVariableExpression(var: !6, expr: !DIExpression()) +!6 = distinct !DIGlobalVariable(name: "y", scope: !2, file: !3, line: 8, type: !7, isLocal: false, isDefinition: true) +!7 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!8 = !{i32 7, !"Dwarf Version", i32 4} +!9 = !{i32 2, !"Debug Info Version", i32 3} +!10 = !{i32 1, !"wchar_size", i32 4} +!11 = !{i32 7, !"uwtable", i32 2} +!12 = !{!"clang version 15.0.0"} +!13 = distinct !DISubprogram(name: "use", linkageName: "_Z3usePiS_", scope: !3, file: !3, line: 1, type: !14, scopeLine: 1, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !2, retainedNodes: !17) +!14 = !DISubroutineType(types: !15) +!15 = !{null, !16, !16} +!16 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !7, size: 64) +!17 = !{!18, !19} +!18 = !DILocalVariable(name: "x", arg: 1, scope: !13, file: !3, line: 1, type: !16) +!19 = !DILocalVariable(name: "y", arg: 2, scope: !13, file: !3, line: 1, type: !16) +!20 = !DILocation(line: 0, scope: !13) +!21 = !DILocation(line: 2, column: 4, scope: !13) +!22 = !{!23, !23, i64 0} +!23 = !{!"int", !24, i64 0} +!24 = !{!"omnipotent char", !25, i64 0} +!25 = !{!"Simple C++ TBAA"} +!26 = !DILocation(line: 3, column: 4, scope: !13) +!27 = !DILocation(line: 4, column: 1, scope: !13) +!28 = distinct !DISubprogram(name: "main", scope: !3, file: !3, line: 9, type: !29, scopeLine: 9, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !2, retainedNodes: !34) +!29 = !DISubroutineType(types: !30) +!30 = !{!7, !7, !31} +!31 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !32, size: 64) +!32 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !33, size: 64) +!33 = !DIBasicType(name: "char", size: 8, encoding: DW_ATE_signed_char) +!34 = !{!35, !36} +!35 = !DILocalVariable(name: "argc", arg: 1, scope: !28, file: !3, line: 9, type: !7) +!36 = !DILocalVariable(name: "argv", arg: 2, scope: !28, file: !3, line: 9, type: !31) +!37 = !DILocation(line: 0, scope: !28) +!38 = !DILocation(line: 0, scope: !13, inlinedAt: !39) +!39 = distinct !DILocation(line: 12, column: 4, scope: !28) +!40 = !DILocation(line: 2, column: 4, scope: !13, inlinedAt: !39) +!41 = !DILocation(line: 3, column: 4, scope: !13, inlinedAt: !39) +!42 = !DILocation(line: 13, column: 11, scope: !28) +!43 = !DILocation(line: 13, column: 4, scope: !28) +!44 = !DISubprogram(name: "helper", linkageName: "_Z6helperii", scope: !3, file: !3, line: 6, type: !45, flags: DIFlagPrototyped, spFlags: DISPFlagOptimized, retainedNodes: !47) +!45 = !DISubroutineType(types: !46) +!46 = !{!7, !7, !7} +!47 = !{} diff --git a/bolt/test/X86/Inputs/dwarf4-df-dualcu-main.ll b/bolt/test/X86/Inputs/dwarf4-df-dualcu-main.ll new file mode 100644 --- /dev/null +++ b/bolt/test/X86/Inputs/dwarf4-df-dualcu-main.ll @@ -0,0 +1,129 @@ +; clang++ -g -gdwarf-4 -emit-llvm -S main.cpp +; void use(int * x, int * y) { +; *x += 4; +; *y -= 2; +; } +; +; int helper(int z_, int d_); +; int x = 0; +; int y = 1; +; int main(int argc, char *argv[]) { +; x = argc; +; y = argc + 3; +; use(&x, &y); +; return helper(x, y); +; } + +; ModuleID = 'main.cpp' +source_filename = "main.cpp" +target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +@x = dso_local global i32 0, align 4, !dbg !0 +@y = dso_local global i32 1, align 4, !dbg !5 + +; Function Attrs: mustprogress noinline nounwind optnone uwtable +define dso_local void @_Z3usePiS_(i32* noundef %x, i32* noundef %y) #0 !dbg !14 { +entry: + %x.addr = alloca i32*, align 8 + %y.addr = alloca i32*, align 8 + store i32* %x, i32** %x.addr, align 8 + call void @llvm.dbg.declare(metadata i32** %x.addr, metadata !19, metadata !DIExpression()), !dbg !20 + store i32* %y, i32** %y.addr, align 8 + call void @llvm.dbg.declare(metadata i32** %y.addr, metadata !21, metadata !DIExpression()), !dbg !22 + %0 = load i32*, i32** %x.addr, align 8, !dbg !23 + %1 = load i32, i32* %0, align 4, !dbg !24 + %add = add nsw i32 %1, 4, !dbg !24 + store i32 %add, i32* %0, align 4, !dbg !24 + %2 = load i32*, i32** %y.addr, align 8, !dbg !25 + %3 = load i32, i32* %2, align 4, !dbg !26 + %sub = sub nsw i32 %3, 2, !dbg !26 + store i32 %sub, i32* %2, align 4, !dbg !26 + ret void, !dbg !27 +} + +; Function Attrs: nofree nosync nounwind readnone speculatable willreturn +declare void @llvm.dbg.declare(metadata, metadata, metadata) #1 + +; Function Attrs: mustprogress noinline norecurse optnone uwtable +define dso_local noundef i32 @main(i32 noundef %argc, i8** noundef %argv) #2 !dbg !28 { +entry: + %retval = alloca i32, align 4 + %argc.addr = alloca i32, align 4 + %argv.addr = alloca i8**, align 8 + store i32 0, i32* %retval, align 4 + store i32 %argc, i32* %argc.addr, align 4 + call void @llvm.dbg.declare(metadata i32* %argc.addr, metadata !34, metadata !DIExpression()), !dbg !35 + store i8** %argv, i8*** %argv.addr, align 8 + call void @llvm.dbg.declare(metadata i8*** %argv.addr, metadata !36, metadata !DIExpression()), !dbg !37 + %0 = load i32, i32* %argc.addr, align 4, !dbg !38 + store i32 %0, i32* @x, align 4, !dbg !39 + %1 = load i32, i32* %argc.addr, align 4, !dbg !40 + %add = add nsw i32 %1, 3, !dbg !41 + store i32 %add, i32* @y, align 4, !dbg !42 + call void @_Z3usePiS_(i32* noundef @x, i32* noundef @y), !dbg !43 + %2 = load i32, i32* @x, align 4, !dbg !44 + %3 = load i32, i32* @y, align 4, !dbg !45 + %call = call noundef i32 @_Z6helperii(i32 noundef %2, i32 noundef %3), !dbg !46 + ret i32 %call, !dbg !47 +} + +declare dso_local noundef i32 @_Z6helperii(i32 noundef, i32 noundef) #3 + +attributes #0 = { mustprogress noinline nounwind optnone uwtable "frame-pointer"="all" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" } +attributes #1 = { nofree nosync nounwind readnone speculatable willreturn } +attributes #2 = { mustprogress noinline norecurse optnone uwtable "frame-pointer"="all" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" } +attributes #3 = { "frame-pointer"="all" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" } + +!llvm.dbg.cu = !{!2} +!llvm.module.flags = !{!8, !9, !10, !11, !12} +!llvm.ident = !{!13} + +!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression()) +!1 = distinct !DIGlobalVariable(name: "x", scope: !2, file: !3, line: 7, type: !7, isLocal: false, isDefinition: true) +!2 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !3, producer: "clang version 15.0.0", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, globals: !4, splitDebugInlining: false, nameTableKind: None) +!3 = !DIFile(filename: "main.cpp", directory: ".") +!4 = !{!0, !5} +!5 = !DIGlobalVariableExpression(var: !6, expr: !DIExpression()) +!6 = distinct !DIGlobalVariable(name: "y", scope: !2, file: !3, line: 8, type: !7, isLocal: false, isDefinition: true) +!7 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!8 = !{i32 7, !"Dwarf Version", i32 4} +!9 = !{i32 2, !"Debug Info Version", i32 3} +!10 = !{i32 1, !"wchar_size", i32 4} +!11 = !{i32 7, !"uwtable", i32 2} +!12 = !{i32 7, !"frame-pointer", i32 2} +!13 = !{!"clang version 15.0.0"} +!14 = distinct !DISubprogram(name: "use", linkageName: "_Z3usePiS_", scope: !3, file: !3, line: 1, type: !15, scopeLine: 1, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !2, retainedNodes: !18) +!15 = !DISubroutineType(types: !16) +!16 = !{null, !17, !17} +!17 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !7, size: 64) +!18 = !{} +!19 = !DILocalVariable(name: "x", arg: 1, scope: !14, file: !3, line: 1, type: !17) +!20 = !DILocation(line: 1, column: 16, scope: !14) +!21 = !DILocalVariable(name: "y", arg: 2, scope: !14, file: !3, line: 1, type: !17) +!22 = !DILocation(line: 1, column: 25, scope: !14) +!23 = !DILocation(line: 2, column: 2, scope: !14) +!24 = !DILocation(line: 2, column: 4, scope: !14) +!25 = !DILocation(line: 3, column: 2, scope: !14) +!26 = !DILocation(line: 3, column: 4, scope: !14) +!27 = !DILocation(line: 4, column: 1, scope: !14) +!28 = distinct !DISubprogram(name: "main", scope: !3, file: !3, line: 9, type: !29, scopeLine: 9, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !2, retainedNodes: !18) +!29 = !DISubroutineType(types: !30) +!30 = !{!7, !7, !31} +!31 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !32, size: 64) +!32 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !33, size: 64) +!33 = !DIBasicType(name: "char", size: 8, encoding: DW_ATE_signed_char) +!34 = !DILocalVariable(name: "argc", arg: 1, scope: !28, file: !3, line: 9, type: !7) +!35 = !DILocation(line: 9, column: 15, scope: !28) +!36 = !DILocalVariable(name: "argv", arg: 2, scope: !28, file: !3, line: 9, type: !31) +!37 = !DILocation(line: 9, column: 27, scope: !28) +!38 = !DILocation(line: 10, column: 8, scope: !28) +!39 = !DILocation(line: 10, column: 6, scope: !28) +!40 = !DILocation(line: 11, column: 8, scope: !28) +!41 = !DILocation(line: 11, column: 13, scope: !28) +!42 = !DILocation(line: 11, column: 6, scope: !28) +!43 = !DILocation(line: 12, column: 4, scope: !28) +!44 = !DILocation(line: 13, column: 18, scope: !28) +!45 = !DILocation(line: 13, column: 21, scope: !28) +!46 = !DILocation(line: 13, column: 11, scope: !28) +!47 = !DILocation(line: 13, column: 4, scope: !28) diff --git a/bolt/test/X86/Inputs/dwarf5-df-dualcu-helper.ll b/bolt/test/X86/Inputs/dwarf5-df-dualcu-helper.ll new file mode 100644 --- /dev/null +++ b/bolt/test/X86/Inputs/dwarf5-df-dualcu-helper.ll @@ -0,0 +1,81 @@ +; clang++ -g -gdwarf-5 -emit-llvm -S helper.cpp +; int z = 0; +; int d = 0; +; +; int helper(int z_, int d_) { +; z += z_; +; d += d_; +; return z * d; +; } + +; ModuleID = 'helper.cpp' +source_filename = "helper.cpp" +target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +@z = dso_local global i32 0, align 4, !dbg !0 +@d = dso_local global i32 0, align 4, !dbg !5 + +; Function Attrs: mustprogress noinline nounwind optnone uwtable +define dso_local noundef i32 @_Z6helperii(i32 noundef %z_, i32 noundef %d_) #0 !dbg !14 { +entry: + %z_.addr = alloca i32, align 4 + %d_.addr = alloca i32, align 4 + store i32 %z_, i32* %z_.addr, align 4 + call void @llvm.dbg.declare(metadata i32* %z_.addr, metadata !18, metadata !DIExpression()), !dbg !19 + store i32 %d_, i32* %d_.addr, align 4 + call void @llvm.dbg.declare(metadata i32* %d_.addr, metadata !20, metadata !DIExpression()), !dbg !21 + %0 = load i32, i32* %z_.addr, align 4, !dbg !22 + %1 = load i32, i32* @z, align 4, !dbg !23 + %add = add nsw i32 %1, %0, !dbg !23 + store i32 %add, i32* @z, align 4, !dbg !23 + %2 = load i32, i32* %d_.addr, align 4, !dbg !24 + %3 = load i32, i32* @d, align 4, !dbg !25 + %add1 = add nsw i32 %3, %2, !dbg !25 + store i32 %add1, i32* @d, align 4, !dbg !25 + %4 = load i32, i32* @z, align 4, !dbg !26 + %5 = load i32, i32* @d, align 4, !dbg !27 + %mul = mul nsw i32 %4, %5, !dbg !28 + ret i32 %mul, !dbg !29 +} + +; Function Attrs: nofree nosync nounwind readnone speculatable willreturn +declare void @llvm.dbg.declare(metadata, metadata, metadata) #1 + +attributes #0 = { mustprogress noinline nounwind optnone uwtable "frame-pointer"="all" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" } +attributes #1 = { nofree nosync nounwind readnone speculatable willreturn } + +!llvm.dbg.cu = !{!2} +!llvm.module.flags = !{!8, !9, !10, !11, !12} +!llvm.ident = !{!13} + +!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression()) +!1 = distinct !DIGlobalVariable(name: "z", scope: !2, file: !3, line: 1, type: !7, isLocal: false, isDefinition: true) +!2 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !3, producer: "clang version 15.0.0", isOptimized: false, runtimeVersion: 0, splitDebugFilename: "helper.dwo", emissionKind: FullDebug, globals: !4, splitDebugInlining: false, nameTableKind: GNU) +!3 = !DIFile(filename: "helper.cpp", directory: ".", checksumkind: CSK_MD5, checksum: "e635924a35b65444173d0c76a54b866f") +!4 = !{!0, !5} +!5 = !DIGlobalVariableExpression(var: !6, expr: !DIExpression()) +!6 = distinct !DIGlobalVariable(name: "d", scope: !2, file: !3, line: 2, type: !7, isLocal: false, isDefinition: true) +!7 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!8 = !{i32 7, !"Dwarf Version", i32 5} +!9 = !{i32 2, !"Debug Info Version", i32 3} +!10 = !{i32 1, !"wchar_size", i32 4} +!11 = !{i32 7, !"uwtable", i32 2} +!12 = !{i32 7, !"frame-pointer", i32 2} +!13 = !{!"clang version 15.0.0"} +!14 = distinct !DISubprogram(name: "helper", linkageName: "_Z6helperii", scope: !3, file: !3, line: 4, type: !15, scopeLine: 4, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !2, retainedNodes: !17) +!15 = !DISubroutineType(types: !16) +!16 = !{!7, !7, !7} +!17 = !{} +!18 = !DILocalVariable(name: "z_", arg: 1, scope: !14, file: !3, line: 4, type: !7) +!19 = !DILocation(line: 4, column: 16, scope: !14) +!20 = !DILocalVariable(name: "d_", arg: 2, scope: !14, file: !3, line: 4, type: !7) +!21 = !DILocation(line: 4, column: 24, scope: !14) +!22 = !DILocation(line: 5, column: 7, scope: !14) +!23 = !DILocation(line: 5, column: 4, scope: !14) +!24 = !DILocation(line: 6, column: 7, scope: !14) +!25 = !DILocation(line: 6, column: 4, scope: !14) +!26 = !DILocation(line: 7, column: 9, scope: !14) +!27 = !DILocation(line: 7, column: 13, scope: !14) +!28 = !DILocation(line: 7, column: 11, scope: !14) +!29 = !DILocation(line: 7, column: 2, scope: !14) diff --git a/bolt/test/X86/Inputs/dwarf5-df-dualcu-loclist-helper.ll b/bolt/test/X86/Inputs/dwarf5-df-dualcu-loclist-helper.ll new file mode 100644 --- /dev/null +++ b/bolt/test/X86/Inputs/dwarf5-df-dualcu-loclist-helper.ll @@ -0,0 +1,61 @@ +; ModuleID = 'helper.cpp' +source_filename = "helper.cpp" +target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +@z = dso_local local_unnamed_addr global i32 0, align 4, !dbg !0 +@d = dso_local local_unnamed_addr global i32 0, align 4, !dbg !5 + +; Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn uwtable +define dso_local noundef i32 @_Z6helperii(i32 noundef %z_, i32 noundef %d_) local_unnamed_addr #0 !dbg !13 { +entry: + call void @llvm.dbg.value(metadata i32 %z_, metadata !17, metadata !DIExpression()), !dbg !19 + call void @llvm.dbg.value(metadata i32 %d_, metadata !18, metadata !DIExpression()), !dbg !19 + %0 = load i32, i32* @z, align 4, !dbg !20, !tbaa !21 + %add = add nsw i32 %0, %z_, !dbg !20 + store i32 %add, i32* @z, align 4, !dbg !20, !tbaa !21 + %1 = load i32, i32* @d, align 4, !dbg !25, !tbaa !21 + %add1 = add nsw i32 %1, %d_, !dbg !25 + store i32 %add1, i32* @d, align 4, !dbg !25, !tbaa !21 + %mul = mul nsw i32 %add1, %add, !dbg !26 + ret i32 %mul, !dbg !27 +} + +; Function Attrs: nocallback nofree nosync nounwind readnone speculatable willreturn +declare void @llvm.dbg.value(metadata, metadata, metadata) #1 + +attributes #0 = { mustprogress nofree norecurse nosync nounwind willreturn uwtable "frame-pointer"="none" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" } +attributes #1 = { nocallback nofree nosync nounwind readnone speculatable willreturn } + +!llvm.dbg.cu = !{!2} +!llvm.module.flags = !{!8, !9, !10, !11} +!llvm.ident = !{!12} + +!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression()) +!1 = distinct !DIGlobalVariable(name: "z", scope: !2, file: !3, line: 1, type: !7, isLocal: false, isDefinition: true) +!2 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !3, producer: "clang version 15.0.0", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, globals: !4, splitDebugInlining: false, nameTableKind: None) +!3 = !DIFile(filename: "helper.cpp", directory: ".", checksumkind: CSK_MD5, checksum: "e635924a35b65444173d0c76a54b866f") +!4 = !{!0, !5} +!5 = !DIGlobalVariableExpression(var: !6, expr: !DIExpression()) +!6 = distinct !DIGlobalVariable(name: "d", scope: !2, file: !3, line: 2, type: !7, isLocal: false, isDefinition: true) +!7 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!8 = !{i32 7, !"Dwarf Version", i32 5} +!9 = !{i32 2, !"Debug Info Version", i32 3} +!10 = !{i32 1, !"wchar_size", i32 4} +!11 = !{i32 7, !"uwtable", i32 2} +!12 = !{!"clang version 15.0.0"} +!13 = distinct !DISubprogram(name: "helper", linkageName: "_Z6helperii", scope: !3, file: !3, line: 4, type: !14, scopeLine: 4, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !2, retainedNodes: !16) +!14 = !DISubroutineType(types: !15) +!15 = !{!7, !7, !7} +!16 = !{!17, !18} +!17 = !DILocalVariable(name: "z_", arg: 1, scope: !13, file: !3, line: 4, type: !7) +!18 = !DILocalVariable(name: "d_", arg: 2, scope: !13, file: !3, line: 4, type: !7) +!19 = !DILocation(line: 0, scope: !13) +!20 = !DILocation(line: 5, column: 4, scope: !13) +!21 = !{!22, !22, i64 0} +!22 = !{!"int", !23, i64 0} +!23 = !{!"omnipotent char", !24, i64 0} +!24 = !{!"Simple C++ TBAA"} +!25 = !DILocation(line: 6, column: 4, scope: !13) +!26 = !DILocation(line: 7, column: 11, scope: !13) +!27 = !DILocation(line: 7, column: 2, scope: !13) diff --git a/bolt/test/X86/Inputs/dwarf5-df-dualcu-loclist-main.ll b/bolt/test/X86/Inputs/dwarf5-df-dualcu-loclist-main.ll new file mode 100644 --- /dev/null +++ b/bolt/test/X86/Inputs/dwarf5-df-dualcu-loclist-main.ll @@ -0,0 +1,99 @@ +; ModuleID = 'main.cpp' +source_filename = "main.cpp" +target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +@x = dso_local local_unnamed_addr global i32 0, align 4, !dbg !0 +@y = dso_local local_unnamed_addr global i32 1, align 4, !dbg !5 + +; Function Attrs: argmemonly mustprogress nofree norecurse nosync nounwind willreturn uwtable +define dso_local void @_Z3usePiS_(i32* nocapture noundef %x, i32* nocapture noundef %y) local_unnamed_addr #0 !dbg !13 { +entry: + call void @llvm.dbg.value(metadata i32* %x, metadata !18, metadata !DIExpression()), !dbg !20 + call void @llvm.dbg.value(metadata i32* %y, metadata !19, metadata !DIExpression()), !dbg !20 + %0 = load i32, i32* %x, align 4, !dbg !21, !tbaa !22 + %add = add nsw i32 %0, 4, !dbg !21 + store i32 %add, i32* %x, align 4, !dbg !21, !tbaa !22 + %1 = load i32, i32* %y, align 4, !dbg !26, !tbaa !22 + %sub = add nsw i32 %1, -2, !dbg !26 + store i32 %sub, i32* %y, align 4, !dbg !26, !tbaa !22 + ret void, !dbg !27 +} + +; Function Attrs: mustprogress norecurse uwtable +define dso_local noundef i32 @main(i32 noundef %argc, i8** nocapture noundef readnone %argv) local_unnamed_addr #1 !dbg !28 { +entry: + call void @llvm.dbg.value(metadata i32 %argc, metadata !35, metadata !DIExpression()), !dbg !37 + call void @llvm.dbg.value(metadata i8** %argv, metadata !36, metadata !DIExpression()), !dbg !37 + call void @llvm.dbg.value(metadata i32* @x, metadata !18, metadata !DIExpression()), !dbg !38 + call void @llvm.dbg.value(metadata i32* @y, metadata !19, metadata !DIExpression()), !dbg !38 + %add.i = add nsw i32 %argc, 4, !dbg !40 + store i32 %add.i, i32* @x, align 4, !dbg !40, !tbaa !22 + %sub.i = add nsw i32 %argc, 1, !dbg !41 + store i32 %sub.i, i32* @y, align 4, !dbg !41, !tbaa !22 + %call = tail call noundef i32 @_Z6helperii(i32 noundef %add.i, i32 noundef %sub.i), !dbg !42 + ret i32 %call, !dbg !43 +} + +declare !dbg !44 dso_local noundef i32 @_Z6helperii(i32 noundef, i32 noundef) local_unnamed_addr #2 + +; Function Attrs: nocallback nofree nosync nounwind readnone speculatable willreturn +declare void @llvm.dbg.value(metadata, metadata, metadata) #3 + +attributes #0 = { argmemonly mustprogress nofree norecurse nosync nounwind willreturn uwtable "frame-pointer"="none" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" } +attributes #1 = { mustprogress norecurse uwtable "frame-pointer"="none" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" } +attributes #2 = { "frame-pointer"="none" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" } +attributes #3 = { nocallback nofree nosync nounwind readnone speculatable willreturn } + +!llvm.dbg.cu = !{!2} +!llvm.module.flags = !{!8, !9, !10, !11} +!llvm.ident = !{!12} + +!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression()) +!1 = distinct !DIGlobalVariable(name: "x", scope: !2, file: !3, line: 7, type: !7, isLocal: false, isDefinition: true) +!2 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !3, producer: "clang version 15.0.0", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, globals: !4, splitDebugInlining: false, nameTableKind: None) +!3 = !DIFile(filename: "main.cpp", directory: ".", checksumkind: CSK_MD5, checksum: "1f627913a0daee879e00a3a51726f0ef") +!4 = !{!0, !5} +!5 = !DIGlobalVariableExpression(var: !6, expr: !DIExpression()) +!6 = distinct !DIGlobalVariable(name: "y", scope: !2, file: !3, line: 8, type: !7, isLocal: false, isDefinition: true) +!7 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!8 = !{i32 7, !"Dwarf Version", i32 5} +!9 = !{i32 2, !"Debug Info Version", i32 3} +!10 = !{i32 1, !"wchar_size", i32 4} +!11 = !{i32 7, !"uwtable", i32 2} +!12 = !{!"clang version 15.0.0"} +!13 = distinct !DISubprogram(name: "use", linkageName: "_Z3usePiS_", scope: !3, file: !3, line: 1, type: !14, scopeLine: 1, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !2, retainedNodes: !17) +!14 = !DISubroutineType(types: !15) +!15 = !{null, !16, !16} +!16 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !7, size: 64) +!17 = !{!18, !19} +!18 = !DILocalVariable(name: "x", arg: 1, scope: !13, file: !3, line: 1, type: !16) +!19 = !DILocalVariable(name: "y", arg: 2, scope: !13, file: !3, line: 1, type: !16) +!20 = !DILocation(line: 0, scope: !13) +!21 = !DILocation(line: 2, column: 4, scope: !13) +!22 = !{!23, !23, i64 0} +!23 = !{!"int", !24, i64 0} +!24 = !{!"omnipotent char", !25, i64 0} +!25 = !{!"Simple C++ TBAA"} +!26 = !DILocation(line: 3, column: 4, scope: !13) +!27 = !DILocation(line: 4, column: 1, scope: !13) +!28 = distinct !DISubprogram(name: "main", scope: !3, file: !3, line: 9, type: !29, scopeLine: 9, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !2, retainedNodes: !34) +!29 = !DISubroutineType(types: !30) +!30 = !{!7, !7, !31} +!31 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !32, size: 64) +!32 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !33, size: 64) +!33 = !DIBasicType(name: "char", size: 8, encoding: DW_ATE_signed_char) +!34 = !{!35, !36} +!35 = !DILocalVariable(name: "argc", arg: 1, scope: !28, file: !3, line: 9, type: !7) +!36 = !DILocalVariable(name: "argv", arg: 2, scope: !28, file: !3, line: 9, type: !31) +!37 = !DILocation(line: 0, scope: !28) +!38 = !DILocation(line: 0, scope: !13, inlinedAt: !39) +!39 = distinct !DILocation(line: 12, column: 4, scope: !28) +!40 = !DILocation(line: 2, column: 4, scope: !13, inlinedAt: !39) +!41 = !DILocation(line: 3, column: 4, scope: !13, inlinedAt: !39) +!42 = !DILocation(line: 13, column: 11, scope: !28) +!43 = !DILocation(line: 13, column: 4, scope: !28) +!44 = !DISubprogram(name: "helper", linkageName: "_Z6helperii", scope: !3, file: !3, line: 6, type: !45, flags: DIFlagPrototyped, spFlags: DISPFlagOptimized, retainedNodes: !47) +!45 = !DISubroutineType(types: !46) +!46 = !{!7, !7, !7} +!47 = !{} diff --git a/bolt/test/X86/Inputs/dwarf5-df-dualcu-main.ll b/bolt/test/X86/Inputs/dwarf5-df-dualcu-main.ll new file mode 100644 --- /dev/null +++ b/bolt/test/X86/Inputs/dwarf5-df-dualcu-main.ll @@ -0,0 +1,129 @@ +; clang++ -g -gdwarf-5 -emit-llvm -S main.cpp +; void use(int * x, int * y) { +; *x += 4; +; *y -= 2; +; } +; +; int helper(int z_, int d_); +; int x = 0; +; int y = 1; +; int main(int argc, char *argv[]) { +; x = argc; +; y = argc + 3; +; use(&x, &y); +; return helper(x, y); +; } + +; ModuleID = 'main.cpp' +source_filename = "main.cpp" +target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +@x = dso_local global i32 0, align 4, !dbg !0 +@y = dso_local global i32 1, align 4, !dbg !5 + +; Function Attrs: mustprogress noinline nounwind optnone uwtable +define dso_local void @_Z3usePiS_(i32* noundef %x, i32* noundef %y) #0 !dbg !14 { +entry: + %x.addr = alloca i32*, align 8 + %y.addr = alloca i32*, align 8 + store i32* %x, i32** %x.addr, align 8 + call void @llvm.dbg.declare(metadata i32** %x.addr, metadata !19, metadata !DIExpression()), !dbg !20 + store i32* %y, i32** %y.addr, align 8 + call void @llvm.dbg.declare(metadata i32** %y.addr, metadata !21, metadata !DIExpression()), !dbg !22 + %0 = load i32*, i32** %x.addr, align 8, !dbg !23 + %1 = load i32, i32* %0, align 4, !dbg !24 + %add = add nsw i32 %1, 4, !dbg !24 + store i32 %add, i32* %0, align 4, !dbg !24 + %2 = load i32*, i32** %y.addr, align 8, !dbg !25 + %3 = load i32, i32* %2, align 4, !dbg !26 + %sub = sub nsw i32 %3, 2, !dbg !26 + store i32 %sub, i32* %2, align 4, !dbg !26 + ret void, !dbg !27 +} + +; Function Attrs: nofree nosync nounwind readnone speculatable willreturn +declare void @llvm.dbg.declare(metadata, metadata, metadata) #1 + +; Function Attrs: mustprogress noinline norecurse optnone uwtable +define dso_local noundef i32 @main(i32 noundef %argc, i8** noundef %argv) #2 !dbg !28 { +entry: + %retval = alloca i32, align 4 + %argc.addr = alloca i32, align 4 + %argv.addr = alloca i8**, align 8 + store i32 0, i32* %retval, align 4 + store i32 %argc, i32* %argc.addr, align 4 + call void @llvm.dbg.declare(metadata i32* %argc.addr, metadata !34, metadata !DIExpression()), !dbg !35 + store i8** %argv, i8*** %argv.addr, align 8 + call void @llvm.dbg.declare(metadata i8*** %argv.addr, metadata !36, metadata !DIExpression()), !dbg !37 + %0 = load i32, i32* %argc.addr, align 4, !dbg !38 + store i32 %0, i32* @x, align 4, !dbg !39 + %1 = load i32, i32* %argc.addr, align 4, !dbg !40 + %add = add nsw i32 %1, 3, !dbg !41 + store i32 %add, i32* @y, align 4, !dbg !42 + call void @_Z3usePiS_(i32* noundef @x, i32* noundef @y), !dbg !43 + %2 = load i32, i32* @x, align 4, !dbg !44 + %3 = load i32, i32* @y, align 4, !dbg !45 + %call = call noundef i32 @_Z6helperii(i32 noundef %2, i32 noundef %3), !dbg !46 + ret i32 %call, !dbg !47 +} + +declare dso_local noundef i32 @_Z6helperii(i32 noundef, i32 noundef) #3 + +attributes #0 = { mustprogress noinline nounwind optnone uwtable "frame-pointer"="all" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" } +attributes #1 = { nofree nosync nounwind readnone speculatable willreturn } +attributes #2 = { mustprogress noinline norecurse optnone uwtable "frame-pointer"="all" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" } +attributes #3 = { "frame-pointer"="all" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" } + +!llvm.dbg.cu = !{!2} +!llvm.module.flags = !{!8, !9, !10, !11, !12} +!llvm.ident = !{!13} + +!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression()) +!1 = distinct !DIGlobalVariable(name: "x", scope: !2, file: !3, line: 7, type: !7, isLocal: false, isDefinition: true) +!2 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !3, producer: "clang version 15.0.0", isOptimized: false, runtimeVersion: 0, splitDebugFilename: "main.dwo", emissionKind: FullDebug, globals: !4, splitDebugInlining: false, nameTableKind: GNU) +!3 = !DIFile(filename: "main.cpp", directory: ".", checksumkind: CSK_MD5, checksum: "1f627913a0daee879e00a3a51726f0ef") +!4 = !{!0, !5} +!5 = !DIGlobalVariableExpression(var: !6, expr: !DIExpression()) +!6 = distinct !DIGlobalVariable(name: "y", scope: !2, file: !3, line: 8, type: !7, isLocal: false, isDefinition: true) +!7 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!8 = !{i32 7, !"Dwarf Version", i32 5} +!9 = !{i32 2, !"Debug Info Version", i32 3} +!10 = !{i32 1, !"wchar_size", i32 4} +!11 = !{i32 7, !"uwtable", i32 2} +!12 = !{i32 7, !"frame-pointer", i32 2} +!13 = !{!"clang version 15.0.0"} +!14 = distinct !DISubprogram(name: "use", linkageName: "_Z3usePiS_", scope: !3, file: !3, line: 1, type: !15, scopeLine: 1, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !2, retainedNodes: !18) +!15 = !DISubroutineType(types: !16) +!16 = !{null, !17, !17} +!17 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !7, size: 64) +!18 = !{} +!19 = !DILocalVariable(name: "x", arg: 1, scope: !14, file: !3, line: 1, type: !17) +!20 = !DILocation(line: 1, column: 16, scope: !14) +!21 = !DILocalVariable(name: "y", arg: 2, scope: !14, file: !3, line: 1, type: !17) +!22 = !DILocation(line: 1, column: 25, scope: !14) +!23 = !DILocation(line: 2, column: 2, scope: !14) +!24 = !DILocation(line: 2, column: 4, scope: !14) +!25 = !DILocation(line: 3, column: 2, scope: !14) +!26 = !DILocation(line: 3, column: 4, scope: !14) +!27 = !DILocation(line: 4, column: 1, scope: !14) +!28 = distinct !DISubprogram(name: "main", scope: !3, file: !3, line: 9, type: !29, scopeLine: 9, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !2, retainedNodes: !18) +!29 = !DISubroutineType(types: !30) +!30 = !{!7, !7, !31} +!31 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !32, size: 64) +!32 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !33, size: 64) +!33 = !DIBasicType(name: "char", size: 8, encoding: DW_ATE_signed_char) +!34 = !DILocalVariable(name: "argc", arg: 1, scope: !28, file: !3, line: 9, type: !7) +!35 = !DILocation(line: 9, column: 15, scope: !28) +!36 = !DILocalVariable(name: "argv", arg: 2, scope: !28, file: !3, line: 9, type: !31) +!37 = !DILocation(line: 9, column: 27, scope: !28) +!38 = !DILocation(line: 10, column: 8, scope: !28) +!39 = !DILocation(line: 10, column: 6, scope: !28) +!40 = !DILocation(line: 11, column: 8, scope: !28) +!41 = !DILocation(line: 11, column: 13, scope: !28) +!42 = !DILocation(line: 11, column: 6, scope: !28) +!43 = !DILocation(line: 12, column: 4, scope: !28) +!44 = !DILocation(line: 13, column: 18, scope: !28) +!45 = !DILocation(line: 13, column: 21, scope: !28) +!46 = !DILocation(line: 13, column: 11, scope: !28) +!47 = !DILocation(line: 13, column: 4, scope: !28) diff --git a/bolt/test/X86/Inputs/dwarf5-df-mono-helper.ll b/bolt/test/X86/Inputs/dwarf5-df-mono-helper.ll new file mode 100644 --- /dev/null +++ b/bolt/test/X86/Inputs/dwarf5-df-mono-helper.ll @@ -0,0 +1,81 @@ +; clang++ -g -gdwarf-5 -emit-llvm -S helper.cpp +; int z = 0; +; int d = 0; +; +; int helper(int z_, int d_) { +; z += z_; +; d += d_; +; return z * d; +; } + +; ModuleID = 'helper.cpp' +source_filename = "helper.cpp" +target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +@z = dso_local global i32 0, align 4, !dbg !0 +@d = dso_local global i32 0, align 4, !dbg !5 + +; Function Attrs: mustprogress noinline nounwind optnone uwtable +define dso_local noundef i32 @_Z6helperii(i32 noundef %z_, i32 noundef %d_) #0 !dbg !14 { +entry: + %z_.addr = alloca i32, align 4 + %d_.addr = alloca i32, align 4 + store i32 %z_, i32* %z_.addr, align 4 + call void @llvm.dbg.declare(metadata i32* %z_.addr, metadata !18, metadata !DIExpression()), !dbg !19 + store i32 %d_, i32* %d_.addr, align 4 + call void @llvm.dbg.declare(metadata i32* %d_.addr, metadata !20, metadata !DIExpression()), !dbg !21 + %0 = load i32, i32* %z_.addr, align 4, !dbg !22 + %1 = load i32, i32* @z, align 4, !dbg !23 + %add = add nsw i32 %1, %0, !dbg !23 + store i32 %add, i32* @z, align 4, !dbg !23 + %2 = load i32, i32* %d_.addr, align 4, !dbg !24 + %3 = load i32, i32* @d, align 4, !dbg !25 + %add1 = add nsw i32 %3, %2, !dbg !25 + store i32 %add1, i32* @d, align 4, !dbg !25 + %4 = load i32, i32* @z, align 4, !dbg !26 + %5 = load i32, i32* @d, align 4, !dbg !27 + %mul = mul nsw i32 %4, %5, !dbg !28 + ret i32 %mul, !dbg !29 +} + +; Function Attrs: nocallback nofree nosync nounwind readnone speculatable willreturn +declare void @llvm.dbg.declare(metadata, metadata, metadata) #1 + +attributes #0 = { mustprogress noinline nounwind optnone uwtable "frame-pointer"="all" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" } +attributes #1 = { nocallback nofree nosync nounwind readnone speculatable willreturn } + +!llvm.dbg.cu = !{!2} +!llvm.module.flags = !{!8, !9, !10, !11, !12} +!llvm.ident = !{!13} + +!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression()) +!1 = distinct !DIGlobalVariable(name: "z", scope: !2, file: !3, line: 1, type: !7, isLocal: false, isDefinition: true) +!2 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !3, producer: "clang version 15.0.0", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, globals: !4, splitDebugInlining: false, nameTableKind: None) +!3 = !DIFile(filename: "helper.cpp", directory: ".", checksumkind: CSK_MD5, checksum: "e635924a35b65444173d0c76a54b866f") +!4 = !{!0, !5} +!5 = !DIGlobalVariableExpression(var: !6, expr: !DIExpression()) +!6 = distinct !DIGlobalVariable(name: "d", scope: !2, file: !3, line: 2, type: !7, isLocal: false, isDefinition: true) +!7 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!8 = !{i32 7, !"Dwarf Version", i32 5} +!9 = !{i32 2, !"Debug Info Version", i32 3} +!10 = !{i32 1, !"wchar_size", i32 4} +!11 = !{i32 7, !"uwtable", i32 2} +!12 = !{i32 7, !"frame-pointer", i32 2} +!13 = !{!"clang version 15.0.0"} +!14 = distinct !DISubprogram(name: "helper", linkageName: "_Z6helperii", scope: !3, file: !3, line: 4, type: !15, scopeLine: 4, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !2, retainedNodes: !17) +!15 = !DISubroutineType(types: !16) +!16 = !{!7, !7, !7} +!17 = !{} +!18 = !DILocalVariable(name: "z_", arg: 1, scope: !14, file: !3, line: 4, type: !7) +!19 = !DILocation(line: 4, column: 16, scope: !14) +!20 = !DILocalVariable(name: "d_", arg: 2, scope: !14, file: !3, line: 4, type: !7) +!21 = !DILocation(line: 4, column: 24, scope: !14) +!22 = !DILocation(line: 5, column: 7, scope: !14) +!23 = !DILocation(line: 5, column: 4, scope: !14) +!24 = !DILocation(line: 6, column: 7, scope: !14) +!25 = !DILocation(line: 6, column: 4, scope: !14) +!26 = !DILocation(line: 7, column: 9, scope: !14) +!27 = !DILocation(line: 7, column: 13, scope: !14) +!28 = !DILocation(line: 7, column: 11, scope: !14) +!29 = !DILocation(line: 7, column: 2, scope: !14) diff --git a/bolt/test/X86/Inputs/dwarf5-df-mono-main.ll b/bolt/test/X86/Inputs/dwarf5-df-mono-main.ll new file mode 100644 --- /dev/null +++ b/bolt/test/X86/Inputs/dwarf5-df-mono-main.ll @@ -0,0 +1,129 @@ +; clang++ -g -gdwarf-5 -gsplit-dwarf=split -emit-llvm -S main.cpp +; void use(int * x, int * y) { +; *x += 4; +; *y -= 2; +; } +; +; int helper(int z_, int d_); +; int x = 0; +; int y = 1; +; int main(int argc, char *argv[]) { +; x = argc; +; y = argc + 3; +; use(&x, &y); +; return helper(x, y); +; } + +; ModuleID = 'main.cpp' +source_filename = "main.cpp" +target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +@x = dso_local global i32 0, align 4, !dbg !0 +@y = dso_local global i32 1, align 4, !dbg !5 + +; Function Attrs: mustprogress noinline nounwind optnone uwtable +define dso_local void @_Z3usePiS_(i32* noundef %x, i32* noundef %y) #0 !dbg !14 { +entry: + %x.addr = alloca i32*, align 8 + %y.addr = alloca i32*, align 8 + store i32* %x, i32** %x.addr, align 8 + call void @llvm.dbg.declare(metadata i32** %x.addr, metadata !19, metadata !DIExpression()), !dbg !20 + store i32* %y, i32** %y.addr, align 8 + call void @llvm.dbg.declare(metadata i32** %y.addr, metadata !21, metadata !DIExpression()), !dbg !22 + %0 = load i32*, i32** %x.addr, align 8, !dbg !23 + %1 = load i32, i32* %0, align 4, !dbg !24 + %add = add nsw i32 %1, 4, !dbg !24 + store i32 %add, i32* %0, align 4, !dbg !24 + %2 = load i32*, i32** %y.addr, align 8, !dbg !25 + %3 = load i32, i32* %2, align 4, !dbg !26 + %sub = sub nsw i32 %3, 2, !dbg !26 + store i32 %sub, i32* %2, align 4, !dbg !26 + ret void, !dbg !27 +} + +; Function Attrs: nocallback nofree nosync nounwind readnone speculatable willreturn +declare void @llvm.dbg.declare(metadata, metadata, metadata) #1 + +; Function Attrs: mustprogress noinline norecurse optnone uwtable +define dso_local noundef i32 @main(i32 noundef %argc, i8** noundef %argv) #2 !dbg !28 { +entry: + %retval = alloca i32, align 4 + %argc.addr = alloca i32, align 4 + %argv.addr = alloca i8**, align 8 + store i32 0, i32* %retval, align 4 + store i32 %argc, i32* %argc.addr, align 4 + call void @llvm.dbg.declare(metadata i32* %argc.addr, metadata !34, metadata !DIExpression()), !dbg !35 + store i8** %argv, i8*** %argv.addr, align 8 + call void @llvm.dbg.declare(metadata i8*** %argv.addr, metadata !36, metadata !DIExpression()), !dbg !37 + %0 = load i32, i32* %argc.addr, align 4, !dbg !38 + store i32 %0, i32* @x, align 4, !dbg !39 + %1 = load i32, i32* %argc.addr, align 4, !dbg !40 + %add = add nsw i32 %1, 3, !dbg !41 + store i32 %add, i32* @y, align 4, !dbg !42 + call void @_Z3usePiS_(i32* noundef @x, i32* noundef @y), !dbg !43 + %2 = load i32, i32* @x, align 4, !dbg !44 + %3 = load i32, i32* @y, align 4, !dbg !45 + %call = call noundef i32 @_Z6helperii(i32 noundef %2, i32 noundef %3), !dbg !46 + ret i32 %call, !dbg !47 +} + +declare dso_local noundef i32 @_Z6helperii(i32 noundef, i32 noundef) #3 + +attributes #0 = { mustprogress noinline nounwind optnone uwtable "frame-pointer"="all" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" } +attributes #1 = { nocallback nofree nosync nounwind readnone speculatable willreturn } +attributes #2 = { mustprogress noinline norecurse optnone uwtable "frame-pointer"="all" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" } +attributes #3 = { "frame-pointer"="all" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" } + +!llvm.dbg.cu = !{!2} +!llvm.module.flags = !{!8, !9, !10, !11, !12} +!llvm.ident = !{!13} + +!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression()) +!1 = distinct !DIGlobalVariable(name: "x", scope: !2, file: !3, line: 7, type: !7, isLocal: false, isDefinition: true) +!2 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !3, producer: "clang version 15.0.0", isOptimized: false, runtimeVersion: 0, splitDebugFilename: "main.dwo", emissionKind: FullDebug, globals: !4, splitDebugInlining: false, nameTableKind: GNU) +!3 = !DIFile(filename: "main.cpp", directory: ".", checksumkind: CSK_MD5, checksum: "1f627913a0daee879e00a3a51726f0ef") +!4 = !{!0, !5} +!5 = !DIGlobalVariableExpression(var: !6, expr: !DIExpression()) +!6 = distinct !DIGlobalVariable(name: "y", scope: !2, file: !3, line: 8, type: !7, isLocal: false, isDefinition: true) +!7 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!8 = !{i32 7, !"Dwarf Version", i32 5} +!9 = !{i32 2, !"Debug Info Version", i32 3} +!10 = !{i32 1, !"wchar_size", i32 4} +!11 = !{i32 7, !"uwtable", i32 2} +!12 = !{i32 7, !"frame-pointer", i32 2} +!13 = !{!"clang version 15.0.0"} +!14 = distinct !DISubprogram(name: "use", linkageName: "_Z3usePiS_", scope: !3, file: !3, line: 1, type: !15, scopeLine: 1, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !2, retainedNodes: !18) +!15 = !DISubroutineType(types: !16) +!16 = !{null, !17, !17} +!17 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !7, size: 64) +!18 = !{} +!19 = !DILocalVariable(name: "x", arg: 1, scope: !14, file: !3, line: 1, type: !17) +!20 = !DILocation(line: 1, column: 16, scope: !14) +!21 = !DILocalVariable(name: "y", arg: 2, scope: !14, file: !3, line: 1, type: !17) +!22 = !DILocation(line: 1, column: 25, scope: !14) +!23 = !DILocation(line: 2, column: 2, scope: !14) +!24 = !DILocation(line: 2, column: 4, scope: !14) +!25 = !DILocation(line: 3, column: 2, scope: !14) +!26 = !DILocation(line: 3, column: 4, scope: !14) +!27 = !DILocation(line: 4, column: 1, scope: !14) +!28 = distinct !DISubprogram(name: "main", scope: !3, file: !3, line: 9, type: !29, scopeLine: 9, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !2, retainedNodes: !18) +!29 = !DISubroutineType(types: !30) +!30 = !{!7, !7, !31} +!31 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !32, size: 64) +!32 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !33, size: 64) +!33 = !DIBasicType(name: "char", size: 8, encoding: DW_ATE_signed_char) +!34 = !DILocalVariable(name: "argc", arg: 1, scope: !28, file: !3, line: 9, type: !7) +!35 = !DILocation(line: 9, column: 15, scope: !28) +!36 = !DILocalVariable(name: "argv", arg: 2, scope: !28, file: !3, line: 9, type: !31) +!37 = !DILocation(line: 9, column: 27, scope: !28) +!38 = !DILocation(line: 10, column: 8, scope: !28) +!39 = !DILocation(line: 10, column: 6, scope: !28) +!40 = !DILocation(line: 11, column: 8, scope: !28) +!41 = !DILocation(line: 11, column: 13, scope: !28) +!42 = !DILocation(line: 11, column: 6, scope: !28) +!43 = !DILocation(line: 12, column: 4, scope: !28) +!44 = !DILocation(line: 13, column: 18, scope: !28) +!45 = !DILocation(line: 13, column: 21, scope: !28) +!46 = !DILocation(line: 13, column: 11, scope: !28) +!47 = !DILocation(line: 13, column: 4, scope: !28) diff --git a/bolt/test/X86/debug-fission-single.s b/bolt/test/X86/debug-fission-single.s --- a/bolt/test/X86/debug-fission-single.s +++ b/bolt/test/X86/debug-fission-single.s @@ -19,22 +19,32 @@ # RUN: --update-debug-sections \ # RUN: --dwarf-output-path=%T \ # RUN: -o %t.bolt.1.exe 2>&1 | FileCheck %s -# RUN: not llvm-dwarfdump --show-form --verbose --debug-info %T/debug-fission-simple.dwo0.dwo -o %tAddrIndexTest 2> /dev/null -# RUN: cat %tAddrIndexTest | grep DW_FORM_GNU_addr_index | FileCheck %s --check-prefix=CHECK-ADDR-INDEX +# RUN: llvm-dwarfdump --show-form --verbose --debug-ranges %t.bolt.1.exe &> %tAddrIndexTest +# RUN: not llvm-dwarfdump --show-form --verbose --debug-info %T/debug-fission-simple.dwo0.dwo >> %tAddrIndexTest +# RUN: cat %tAddrIndexTest | FileCheck %s --check-prefix=CHECK-DWO-DWO # RUN: llvm-dwarfdump --show-form --verbose --debug-addr %t.bolt.1.exe | FileCheck %s --check-prefix=CHECK-ADDR-SEC # CHECK-NOT: warning: DWARF unit from offset {{.*}} incl. to offset {{.*}} excl. tries to read DIEs at offset {{.*}} -# CHECK-ADDR-INDEX: DW_AT_low_pc [DW_FORM_GNU_addr_index] (indexed (00000000) -# CHECK-ADDR-INDEX: DW_AT_low_pc [DW_FORM_GNU_addr_index] (indexed (00000000) -# CHECK-ADDR-INDEX: DW_AT_low_pc [DW_FORM_GNU_addr_index] (indexed (00000000) +# CHECK-DWO-DWO: 00000010 +# CHECK-DWO-DWO: 00000010 +# CHECK-DWO-DWO: 00000050 +# CHECK-DWO-DWO: DW_TAG_subprogram +# CHECK-DWO-DWO-NEXT: DW_AT_low_pc [DW_FORM_GNU_addr_index] (indexed (00000000) +# CHECK-DWO-DWO-NEXT: DW_AT_ranges [DW_FORM_sec_offset] (0x00000000 +# CHECK-DWO-DWO: DW_TAG_subprogram +# CHECK-DWO-DWO-NEXT: DW_AT_low_pc [DW_FORM_GNU_addr_index] (indexed (00000000) +# CHECK-DWO-DWO-NEXT: DW_AT_ranges [DW_FORM_sec_offset] (0x00000020 +# CHECK-DWO-DWO: DW_TAG_subprogram +# CHECK-DWO-DWO-NEXT: DW_AT_low_pc [DW_FORM_GNU_addr_index] (indexed (00000000) +# CHECK-DWO-DWO-NEXT: DW_AT_ranges [DW_FORM_sec_offset] (0x00000040 # CHECK-ADDR-SEC: .debug_addr contents: # CHECK-ADDR-SEC: 0x00000000: Addrs: [ # CHECK-ADDR-SEC: 0x0000000000601000 # RUN: llvm-bolt %t.exe --reorder-blocks=reverse -update-debug-sections -dwarf-output-path=%T -o %t.bolt.2.exe --write-dwp=true -# RUN: not llvm-dwarfdump --show-form --verbose --debug-info %t.bolt.2.exe.dwp -o %tAddrIndexTestDwp 2> /dev/null +# RUN: not llvm-dwarfdump --show-form --verbose --debug-info %t.bolt.2.exe.dwp &> %tAddrIndexTestDwp # RUN: cat %tAddrIndexTestDwp | FileCheck %s --check-prefix=CHECK-DWP-DEBUG # CHECK-DWP-DEBUG: DW_TAG_compile_unit [1] * diff --git a/bolt/test/X86/dwarf4-df-dualcu-loclist.test b/bolt/test/X86/dwarf4-df-dualcu-loclist.test new file mode 100644 --- /dev/null +++ b/bolt/test/X86/dwarf4-df-dualcu-loclist.test @@ -0,0 +1,48 @@ +; RUN: rm -rf %t +; RUN: mkdir %t +; RUN: cd %t +; RUN: llc -split-dwarf-file=main.dwo -split-dwarf-output=main.dwo -O2 -mtriple=x86_64-unknown-linux-gnu \ +; RUN: -filetype=obj %p/Inputs/dwarf4-df-dualcu-loclist-main.ll -o=main.o +; RUN: llc -split-dwarf-file=helper.dwo -split-dwarf-output=helper.dwo -O2 -mtriple=x86_64-unknown-linux-gnu \ +; RUN: -filetype=obj %p/Inputs/dwarf4-df-dualcu-loclist-helper.ll -o=helper.o +; RUN: %clang %cflags -gdwarf-5 -O2 -gsplit-dwarf=split main.o helper.o -o main.exe +; RUN: llvm-bolt main.exe -o main.exe.bolt --update-debug-sections +; RUN: llvm-dwarfdump --show-form --verbose --debug-info main.dwo | FileCheck -check-prefix=PRE-BOLT-DWO-MAIN %s +; RUN: not llvm-dwarfdump --show-form --verbose --debug-info main.dwo.dwo | FileCheck -check-prefix=BOLT-DWO-MAIN %s +; RUN: llvm-dwarfdump --show-form --verbose --debug-info helper.dwo | FileCheck -check-prefix=PRE-BOLT-DWO-HELPER %s +; RUN: not llvm-dwarfdump --show-form --verbose --debug-info helper.dwo.dwo | FileCheck -check-prefix=BOLT-DWO-HELPER %s + +; Testing dwarf4 split dwarf for two CUs. Making sure DW_AT_location [DW_FORM_sec_offset] is updated correctly. + +; PRE-BOLT-DWO-MAIN: version = 0x0004 +; PRE-BOLT-DWO-MAIN: DW_TAG_formal_parameter [10] +; PRE-BOLT-DWO-MAIN-NEXT: DW_AT_location [DW_FORM_sec_offset] (0x00000000: +; PRE-BOLT-DWO-MAIN-NEXT: DW_LLE_startx_length (0x0000000000000003, 0x0000000000000014) +; PRE-BOLT-DWO-MAIN-NEXT: DW_LLE_startx_length (0x0000000000000005, 0x0000000000000005) +; PRE-BOLT-DWO-MAIN: DW_TAG_formal_parameter [10] +; PRE-BOLT-DWO-MAIN-NEXT: DW_AT_location [DW_FORM_sec_offset] (0x00000016: +; PRE-BOLT-DWO-MAIN-NEXT: DW_LLE_startx_length (0x0000000000000003, 0x000000000000000c) +; PRE-BOLT-DWO-MAIN-NEXT: DW_LLE_startx_length (0x0000000000000006, 0x000000000000000d) + +; BOLT-DWO-MAIN: version = 0x0004 +; BOLT-DWO-MAIN: DW_TAG_formal_parameter [10] +; BOLT-DWO-MAIN-NEXT: DW_AT_location [DW_FORM_sec_offset] (0x00000000: +; BOLT-DWO-MAIN-NEXT: DW_LLE_startx_length (0x0000000000000002, 0x0000000000000014) +; BOLT-DWO-MAIN-NEXT: DW_LLE_startx_length (0x0000000000000003, 0x0000000000000005) +; BOLT-DWO-MAIN: DW_TAG_formal_parameter [10] +; BOLT-DWO-MAIN-NEXT: DW_AT_location [DW_FORM_sec_offset] (0x00000016: +; BOLT-DWO-MAIN-NEXT: DW_LLE_startx_length (0x0000000000000002, 0x000000000000000c) +; BOLT-DWO-MAIN-NEXT: DW_LLE_startx_length (0x0000000000000005, 0x000000000000000d) + + +; PRE-BOLT-DWO-HELPER: version = 0x0004 +; PRE-BOLT-DWO-HELPER: DW_TAG_formal_parameter [5] +; PRE-BOLT-DWO-HELPER-NEXT: DW_AT_location [DW_FORM_sec_offset] (0x00000000: +; PRE-BOLT-DWO-HELPER-NEXT: DW_LLE_startx_length (0x0000000000000002, 0x0000000000000008) +; PRE-BOLT-DWO-HELPER-NEXT: DW_LLE_startx_length (0x0000000000000003, 0x0000000000000016) + +; BOLT-DWO-HELPER: version = 0x0004 +; BOLT-DWO-HELPER: DW_TAG_formal_parameter [5] +; BOLT-DWO-HELPER-NEXT: DW_AT_location [DW_FORM_sec_offset] (0x00000000: +; BOLT-DWO-HELPER-NEXT: DW_LLE_startx_length (0x0000000000000002, 0x0000000000000008): DW_OP_reg5 RDI +; BOLT-DWO-HELPER-NEXT: DW_LLE_startx_length (0x0000000000000003, 0x0000000000000016) diff --git a/bolt/test/X86/dwarf4-df-dualcu.test b/bolt/test/X86/dwarf4-df-dualcu.test new file mode 100644 --- /dev/null +++ b/bolt/test/X86/dwarf4-df-dualcu.test @@ -0,0 +1,166 @@ +; RUN: rm -rf %t +; RUN: mkdir %t +; RUN: cd %t +; RUN: llc -split-dwarf-file=main.dwo -split-dwarf-output=main.dwo -O0 -mtriple=x86_64-unknown-linux-gnu \ +; RUN: -filetype=obj %p/Inputs/dwarf4-df-dualcu-main.ll -o=main.o +; RUN: llc -split-dwarf-file=helper.dwo -split-dwarf-output=helper.dwo -O0 -mtriple=x86_64-unknown-linux-gnu \ +; RUN: -filetype=obj %p/Inputs/dwarf4-df-dualcu-helper.ll -o=helper.o +; RUN: %clang %cflags -gdwarf-5 -gsplit-dwarf=split main.o helper.o -o main.exe +; RUN: llvm-bolt main.exe -o main.exe.bolt --update-debug-sections +; RUN: llvm-dwarfdump --show-form --verbose --debug-info main.exe | FileCheck -check-prefix=PRE-BOLT %s +; RUN: llvm-dwarfdump --show-form --verbose --debug-ranges main.exe.bolt &> %t/foo.txt +; RUN: llvm-dwarfdump --show-form --verbose --debug-info main.exe.bolt >> %t/foo.txt +; RUN: cat %t/foo.txt | FileCheck -check-prefix=BOLT %s +; RUN: llvm-dwarfdump --show-form --verbose --debug-info main.dwo &> maindwo.txt +; RUN cat maindwo.txt | FileCheck -check-prefix=PRE-BOLT-DWO-MAIN %s +; RUN: not llvm-dwarfdump --show-form --verbose --debug-info main.dwo.dwo &> mainddwodwo.txt +; RUN: cat mainddwodwo.txt | FileCheck -check-prefix=BOLT-DWO-MAIN %s +; RUN: llvm-dwarfdump --show-form --verbose --debug-info helper.dwo &> helperdwo.txt +; RUN: cat helperdwo.txt | FileCheck -check-prefix=PRE-BOLT-DWO-HELPER %s +; RUN: not llvm-dwarfdump --show-form --verbose --debug-info helper.dwo.dwo &> helperdwodwo.txt +; RUN: cat helperdwodwo.txt | FileCheck -check-prefix=BOLT-DWO-HELPER %s + +; Testing dwarf5 split dwarf for two CUs. Making sure DW_AT_low_pc/DW_AT_high_pc are converted correctly in the binary and in dwo. +; Checking that DW_AT_location [DW_FORM_exprloc] (DW_OP_addrx ##) are updated correctly. + +; PRE-BOLT: version = 0x0004 +; PRE-BOLT: DW_TAG_compile_unit +; PRE-BOLT: DW_AT_low_pc [DW_FORM_addr] +; PRE-BOLT-NEXT: DW_AT_high_pc [DW_FORM_data4] +; PRE-BOLT-NEXT: DW_AT_GNU_addr_base [DW_FORM_sec_offset] (0x00000000) +; PRE-BOLT-NEXT: Compile +; PRE-BOLT: version = 0x0004 +; PRE-BOLT: DW_TAG_compile_unit +; PRE-BOLT: DW_AT_low_pc [DW_FORM_addr] +; PRE-BOLT-NEXT: DW_AT_high_pc [DW_FORM_data4] +; PRE-BOLT: DW_AT_GNU_addr_base [DW_FORM_sec_offset] (0x00000020) + +; BOLT: .debug_ranges +; BOLT-NEXT: 00000000 +; BOLT-NEXT: 00000010 [[#%.16x,ADDR:]] [[#%.16x,ADDRB:]] +; BOLT-NEXT: 00000010 +; BOLT-NEXT: 00000030 [[#%.16x,ADDR1:]] [[#%.16x,ADDR1B:]] +; BOLT-NEXT: 00000030 +; BOLT-NEXT: 00000050 [[#%.16x,ADDR2:]] [[#%.16x,ADDR2B:]] +; BOLT-NEXT: 00000050 [[#%.16x,ADDR3:]] [[#%.16x,ADDR3B:]] +; BOLT-NEXT: 00000050 +; BOLT-NEXT: 00000080 [[#%.16x,ADDR4:]] [[#%.16x,ADDR4B:]] +; BOLT-NEXT: 00000080 +; BOLT-NEXT: 000000a0 [[#%.16x,ADDR5:]] [[#%.16x,ADDR5B:]] +; BOLT-NEXT: 000000a0 + +; BOLT: DW_TAG_compile_unit +; BOLT: DW_AT_GNU_dwo_name [DW_FORM_strp] ( .debug_str[0x00000016] = "main.dwo.dwo") +; BOLT-NEXT: DW_AT_GNU_dwo_id +; BOLT-NEXT: DW_AT_low_pc [DW_FORM_addr] (0x0000000000000000) +; BOLT-NEXT: DW_AT_ranges [DW_FORM_sec_offset] (0x00000050 +; BOLT-NEXT: [0x[[#ADDR2]], 0x[[#ADDR2B]]) +; BOLT-NEXT: [0x[[#ADDR3]], 0x[[#ADDR3B]])) +; BOLT-NEXT: DW_AT_GNU_addr_base [DW_FORM_sec_offset] (0x00000000) +; BOLT-NEXT: DW_AT_GNU_ranges_base [DW_FORM_sec_offset] (0x00000010) +; BOLT-NEXT: Compile +; BOLT: DW_TAG_compile_unit +; BOLT: DW_AT_GNU_dwo_name [DW_FORM_strp] ( .debug_str[0x00000023] = "helper.dwo.dwo") +; BOLT-NEXT: DW_AT_GNU_dwo_id +; BOLT-NEXT: DW_AT_low_pc [DW_FORM_addr] (0x0000000000000000) +; BOLT-NEXT: DW_AT_ranges [DW_FORM_sec_offset] (0x000000a0 +; BOLT-NEXT: [0x[[#ADDR5]], 0x[[#ADDR5B]]) +; BOLT-NEXT: DW_AT_GNU_addr_base [DW_FORM_sec_offset] (0x00000010) +; BOLT-NEXT: DW_AT_GNU_ranges_base [DW_FORM_sec_offset] (0x00000080) + +; PRE-BOLT-DWO-MAIN: version = 0x0004 +; PRE-BOLT-DWO-MAIN: DW_TAG_compile_unit +; PRE-BOLT-DWO-MAIN: DW_TAG_variable [2] +; PRE-BOLT-DWO-MAIN-NEXT: DW_AT_name [DW_FORM_GNU_str_index] (indexed (00000000) string = "x") +; PRE-BOLT-DWO-MAIN-NEXT: DW_AT_type +; PRE-BOLT-DWO-MAIN-NEXT: DW_AT_external +; PRE-BOLT-DWO-MAIN-NEXT: DW_AT_decl_file +; PRE-BOLT-DWO-MAIN-NEXT: DW_AT_decl_line +; PRE-BOLT-DWO-MAIN-NEXT: DW_AT_location [DW_FORM_exprloc] (DW_OP_GNU_addr_index 0x0) +; PRE-BOLT-DWO-MAIN: DW_TAG_variable [2] +; PRE-BOLT-DWO-MAIN-NEXT: DW_AT_name [DW_FORM_GNU_str_index] (indexed (00000002) string = "y") +; PRE-BOLT-DWO-MAIN-NEXT: DW_AT_type +; PRE-BOLT-DWO-MAIN-NEXT: DW_AT_external +; PRE-BOLT-DWO-MAIN-NEXT: DW_AT_decl_file +; PRE-BOLT-DWO-MAIN-NEXT: DW_AT_decl_line +; PRE-BOLT-DWO-MAIN-NEXT: DW_AT_location [DW_FORM_exprloc] (DW_OP_GNU_addr_index 0x1) +; PRE-BOLT-DWO-MAIN: DW_TAG_subprogram +; PRE-BOLT-DWO-MAIN-NEXT: DW_AT_low_pc [DW_FORM_GNU_addr_index] (indexed (00000002) +; PRE-BOLT-DWO-MAIN-NEXT: DW_AT_high_pc [DW_FORM_data4] (0x00000024) +; PRE-BOLT-DWO-MAIN-NEXT: DW_AT_frame_base +; PRE-BOLT-DWO-MAIN-NEXT: DW_AT_linkage_name [DW_FORM_GNU_str_index] (indexed (00000003) string = "_Z3usePiS_") +; PRE-BOLT-DWO-MAIN-NEXT: DW_AT_name [DW_FORM_GNU_str_index] (indexed (00000004) string = "use") +; PRE-BOLT-DWO-MAIN: DW_TAG_subprogram +; PRE-BOLT-DWO-MAIN-NEXT: DW_AT_low_pc [DW_FORM_GNU_addr_index] (indexed (00000003) +; PRE-BOLT-DWO-MAIN-NEXT: DW_AT_high_pc [DW_FORM_data4] (0x0000005f) +; PRE-BOLT-DWO-MAIN-NEXT: DW_AT_frame_base +; PRE-BOLT-DWO-MAIN-NEXT: DW_AT_name [DW_FORM_GNU_str_index] (indexed (00000005) string = "main") + +; BOLT-DWO-MAIN: version = 0x0004 +; BOLT-DWO-MAIN: DW_TAG_compile_unit +; BOLT-DWO-MAIN: DW_TAG_variable [2] +; BOLT-DWO-MAIN-NEXT: DW_AT_name [DW_FORM_GNU_str_index] (indexed (00000000) string = "x") +; BOLT-DWO-MAIN-NEXT: DW_AT_type +; BOLT-DWO-MAIN-NEXT: DW_AT_external +; BOLT-DWO-MAIN-NEXT: DW_AT_decl_file +; BOLT-DWO-MAIN-NEXT: DW_AT_decl_line +; BOLT-DWO-MAIN-NEXT: DW_AT_location [DW_FORM_exprloc] (DW_OP_GNU_addr_index 0x0) +; BOLT-DWO-MAIN: DW_TAG_variable [2] +; BOLT-DWO-MAIN-NEXT: DW_AT_name [DW_FORM_GNU_str_index] (indexed (00000002) string = "y") +; BOLT-DWO-MAIN-NEXT: DW_AT_type +; BOLT-DWO-MAIN-NEXT: DW_AT_external +; BOLT-DWO-MAIN-NEXT: DW_AT_decl_file +; BOLT-DWO-MAIN-NEXT: DW_AT_decl_line +; BOLT-DWO-MAIN-NEXT: DW_AT_location [DW_FORM_exprloc] (DW_OP_GNU_addr_index 0x1) +; BOLT-DWO-MAIN: DW_TAG_subprogram [4] +; BOLT-DWO-MAIN-NEXT: DW_AT_low_pc [DW_FORM_GNU_addr_index] (indexed (00000000) +; BOLT-DWO-MAIN-NEXT: DW_AT_ranges [DW_FORM_sec_offset] (0x00000000 +; BOLT-DWO-MAIN-NEXT: ) +; BOLT-DWO-MAIN-NEXT: DW_AT_frame_base +; BOLT-DWO-MAIN-NEXT: DW_AT_linkage_name [DW_FORM_GNU_str_index] (indexed (00000003) string = "_Z3usePiS_") +; BOLT-DWO-MAIN-NEXT: DW_AT_name [DW_FORM_GNU_str_index] (indexed (00000004) string = "use") +; BOLT-DWO-MAIN: DW_TAG_subprogram [6] +; BOLT-DWO-MAIN-NEXT: DW_AT_low_pc [DW_FORM_GNU_addr_index] (indexed (00000000) +; BOLT-DWO-MAIN-NEXT: DW_AT_ranges [DW_FORM_sec_offset] (0x00000020 +; BOLT-DWO-MAIN-NEXT: ) +; BOLT-DWO-MAIN-NEXT: DW_AT_frame_base [DW_FORM_exprloc] (DW_OP_reg6 RBP) +; BOLT-DWO-MAIN-NEXT: DW_AT_name [DW_FORM_GNU_str_index] (indexed (00000005) string = "main") + + +; PRE-BOLT-DWO-HELPER: version = 0x0004 +; PRE-BOLT-DWO-HELPER: DW_TAG_variable [2] +; PRE-BOLT-DWO-HELPER-NEXT: DW_AT_name [DW_FORM_GNU_str_index] (indexed (00000000) string = "z") +; PRE-BOLT-DWO-HELPER-NEXT: DW_AT_type +; PRE-BOLT-DWO-HELPER-NEXT: DW_AT_external +; PRE-BOLT-DWO-HELPER-NEXT: DW_AT_decl_file +; PRE-BOLT-DWO-HELPER-NEXT: DW_AT_decl_line +; PRE-BOLT-DWO-HELPER-NEXT: DW_AT_location [DW_FORM_exprloc] (DW_OP_GNU_addr_index 0x0) +; PRE-BOLT-DWO-HELPER: DW_TAG_variable [2] +; PRE-BOLT-DWO-HELPER-NEXT: DW_AT_name [DW_FORM_GNU_str_index] (indexed (00000002) string = "d") +; PRE-BOLT-DWO-HELPER-NEXT: DW_AT_type +; PRE-BOLT-DWO-HELPER-NEXT: DW_AT_external +; PRE-BOLT-DWO-HELPER-NEXT: DW_AT_decl_file +; PRE-BOLT-DWO-HELPER-NEXT: DW_AT_decl_line +; PRE-BOLT-DWO-HELPER-NEXT: DW_AT_location [DW_FORM_exprloc] (DW_OP_GNU_addr_index 0x1) +; PRE-BOLT-DWO-HELPER: DW_TAG_subprogram [4] +; PRE-BOLT-DWO-HELPER-NEXT: DW_AT_low_pc [DW_FORM_GNU_addr_index] (indexed (00000002) +; PRE-BOLT-DWO-HELPER-NEXT: DW_AT_high_pc [DW_FORM_data4] (0x0000003d) + +; BOLT-DWO-HELPER: version = 0x0004 +; BOLT-DWO-HELPER: DW_TAG_variable [2] +; BOLT-DWO-HELPER-NEXT: DW_AT_name [DW_FORM_GNU_str_index] (indexed (00000000) string = "z") +; BOLT-DWO-HELPER-NEXT: DW_AT_type +; BOLT-DWO-HELPER-NEXT: DW_AT_external +; BOLT-DWO-HELPER-NEXT: DW_AT_decl_file +; BOLT-DWO-HELPER-NEXT: DW_AT_decl_line +; BOLT-DWO-HELPER-NEXT: DW_AT_location [DW_FORM_exprloc] (DW_OP_GNU_addr_index 0x0) +; BOLT-DWO-HELPER: DW_TAG_variable [2] +; BOLT-DWO-HELPER-NEXT: DW_AT_name [DW_FORM_GNU_str_index] (indexed (00000002) string = "d") +; BOLT-DWO-HELPER-NEXT: DW_AT_type +; BOLT-DWO-HELPER-NEXT: DW_AT_external +; BOLT-DWO-HELPER-NEXT: DW_AT_decl_file +; BOLT-DWO-HELPER-NEXT: DW_AT_decl_line +; BOLT-DWO-HELPER-NEXT: DW_AT_location [DW_FORM_exprloc] (DW_OP_GNU_addr_index 0x1) +; BOLT-DWO-HELPER: DW_TAG_subprogram [4] +; BOLT-DWO-HELPER-NEXT: DW_AT_low_pc [DW_FORM_GNU_addr_index] (indexed (00000000) +; BOLT-DWO-HELPER-NEXT: DW_AT_ranges [DW_FORM_sec_offset] (0x00000000 diff --git a/bolt/test/X86/dwarf5-df-dualcu-loclist.test b/bolt/test/X86/dwarf5-df-dualcu-loclist.test new file mode 100644 --- /dev/null +++ b/bolt/test/X86/dwarf5-df-dualcu-loclist.test @@ -0,0 +1,51 @@ +; RUN: rm -rf %t +; RUN: mkdir %t +; RUN: cd %t +; RUN: llc -split-dwarf-file=main.dwo -split-dwarf-output=main.dwo -O2 -mtriple=x86_64-unknown-linux-gnu \ +; RUN: -filetype=obj %p/Inputs/dwarf5-df-dualcu-loclist-main.ll -o=main.o +; RUN: llc -split-dwarf-file=helper.dwo -split-dwarf-output=helper.dwo -O2 -mtriple=x86_64-unknown-linux-gnu \ +; RUN: -filetype=obj %p/Inputs/dwarf5-df-dualcu-loclist-helper.ll -o=helper.o +; RUN: %clang %cflags -gdwarf-5 -O2 -gsplit-dwarf=split main.o helper.o -o main.exe +; RUN: llvm-bolt main.exe -o main.exe.bolt --update-debug-sections +; RUN: llvm-dwarfdump --show-form --verbose --debug-info main.dwo | FileCheck -check-prefix=PRE-BOLT-DWO-MAIN %s +; RUN: llvm-dwarfdump --show-form --verbose --debug-info main.dwo.dwo | FileCheck -check-prefix=BOLT-DWO-MAIN %s +; RUN: llvm-dwarfdump --show-form --verbose --debug-info helper.dwo | FileCheck -check-prefix=PRE-BOLT-DWO-HELPER %s +; RUN: llvm-dwarfdump --show-form --verbose --debug-info helper.dwo.dwo | FileCheck -check-prefix=BOLT-DWO-HELPER %s + +; Testing dwarf5 split dwarf for two CUs. Making sure DW_AT_location [DW_FORM_loclistx] is updated correctly. + +; PRE-BOLT-DWO-MAIN: version = 0x0005 +; PRE-BOLT-DWO-MAIN: DW_TAG_formal_parameter [10] +; PRE-BOLT-DWO-MAIN-NEXT: DW_AT_location [DW_FORM_loclistx] (indexed (0x0) loclist = 0x00000014: +; PRE-BOLT-DWO-MAIN-NEXT: DW_LLE_base_addressx (0x0000000000000002) +; PRE-BOLT-DWO-MAIN-NEXT: DW_LLE_offset_pair (0x0000000000000010, 0x0000000000000024) +; PRE-BOLT-DWO-MAIN-NEXT: DW_LLE_offset_pair (0x0000000000000024, 0x0000000000000029) +; PRE-BOLT-DWO-MAIN: DW_TAG_formal_parameter [10] +; PRE-BOLT-DWO-MAIN-NEXT: DW_AT_location [DW_FORM_loclistx] (indexed (0x1) loclist = 0x00000024: +; PRE-BOLT-DWO-MAIN-NEXT: DW_LLE_base_addressx (0x0000000000000002) +; PRE-BOLT-DWO-MAIN-NEXT: DW_LLE_offset_pair (0x0000000000000010, 0x000000000000001c) +; PRE-BOLT-DWO-MAIN-NEXT: DW_LLE_offset_pair (0x000000000000001c, 0x0000000000000029) + +; BOLT-DWO-MAIN: version = 0x0005 +; BOLT-DWO-MAIN: DW_TAG_formal_parameter [10] +; BOLT-DWO-MAIN-NEXT: DW_AT_location [DW_FORM_loclistx] (indexed (0x0) loclist = 0x00000014: +; BOLT-DWO-MAIN-NEXT: DW_LLE_startx_length (0x0000000000000004, 0x0000000000000014) +; BOLT-DWO-MAIN-NEXT: DW_LLE_startx_length (0x0000000000000005, 0x0000000000000005) +; BOLT-DWO-MAIN: DW_TAG_formal_parameter [10] +; BOLT-DWO-MAIN-NEXT: DW_AT_location [DW_FORM_loclistx] (indexed (0x1) loclist = 0x00000022: +; BOLT-DWO-MAIN-NEXT: DW_LLE_startx_length (0x0000000000000004, 0x000000000000000c) +; BOLT-DWO-MAIN-NEXT: DW_LLE_startx_length (0x0000000000000006, 0x000000000000000d) + + +; PRE-BOLT-DWO-HELPER: version = 0x0005 +; PRE-BOLT-DWO-HELPER: DW_TAG_formal_parameter [5] +; PRE-BOLT-DWO-HELPER-NEXT: DW_AT_location [DW_FORM_loclistx] (indexed (0x0) loclist = 0x00000010: +; PRE-BOLT-DWO-HELPER-NEXT: DW_LLE_base_addressx (0x0000000000000002) +; PRE-BOLT-DWO-HELPER-NEXT: DW_LLE_offset_pair (0x0000000000000000, 0x0000000000000008) +; PRE-BOLT-DWO-HELPER-NEXT: DW_LLE_offset_pair (0x0000000000000008, 0x000000000000001e) + +; BOLT-DWO-HELPER: version = 0x0005 +; BOLT-DWO-HELPER: DW_TAG_formal_parameter [5] +; BOLT-DWO-HELPER-NEXT: DW_AT_location [DW_FORM_loclistx] (indexed (0x0) loclist = 0x00000010: +; BOLT-DWO-HELPER-NEXT: DW_LLE_startx_length (0x0000000000000002, 0x0000000000000008) +; BOLT-DWO-HELPER-NEXT: DW_LLE_startx_length (0x0000000000000004, 0x0000000000000016) diff --git a/bolt/test/X86/dwarf5-df-dualcu.test b/bolt/test/X86/dwarf5-df-dualcu.test new file mode 100644 --- /dev/null +++ b/bolt/test/X86/dwarf5-df-dualcu.test @@ -0,0 +1,152 @@ +; RUN: rm -rf %t +; RUN: mkdir %t +; RUN: cd %t +; RUN: llc -split-dwarf-file=main.dwo -split-dwarf-output=main.dwo -O0 -mtriple=x86_64-unknown-linux-gnu \ +; RUN: -filetype=obj %p/Inputs/dwarf5-df-dualcu-main.ll -o=main.o +; RUN: llc -split-dwarf-file=helper.dwo -split-dwarf-output=helper.dwo -O0 -mtriple=x86_64-unknown-linux-gnu \ +; RUN: -filetype=obj %p/Inputs/dwarf5-df-dualcu-helper.ll -o=helper.o +; RUN: %clang %cflags -gdwarf-5 -gsplit-dwarf=split main.o helper.o -o main.exe +; RUN: llvm-bolt main.exe -o main.exe.bolt --update-debug-sections +; RUN: llvm-dwarfdump --show-form --verbose --debug-info main.exe | FileCheck -check-prefix=PRE-BOLT %s +; RUN: llvm-dwarfdump --show-form --verbose --debug-addr main.exe.bolt &> %t/foo.txt +; RUN: llvm-dwarfdump --show-form --verbose --debug-info main.exe.bolt >> %t/foo.txt +; RUN: cat %t/foo.txt | FileCheck -check-prefix=BOLT %s +; RUN: llvm-dwarfdump --show-form --verbose --debug-info main.dwo | FileCheck -check-prefix=PRE-BOLT-DWO-MAIN %s +; RUN: llvm-dwarfdump --show-form --verbose --debug-info main.dwo.dwo | FileCheck -check-prefix=BOLT-DWO-MAIN %s +; RUN: llvm-dwarfdump --show-form --verbose --debug-info helper.dwo | FileCheck -check-prefix=PRE-BOLT-DWO-HELPER %s +; RUN: llvm-dwarfdump --show-form --verbose --debug-info helper.dwo.dwo | FileCheck -check-prefix=BOLT-DWO-HELPER %s + +; Testing dwarf5 split dwarf for two CUs. Making sure DW_AT_low_pc/DW_AT_high_pc are converted correctly in the binary and in dwo. +; Checking that DW_AT_location [DW_FORM_exprloc] (DW_OP_addrx ##) are updated correctly. + +; PRE-BOLT: version = 0x0005 +; PRE-BOLT: DW_TAG_skeleton_unit +; PRE-BOLT: DW_AT_low_pc [DW_FORM_addrx] +; PRE-BOLT-NEXT: DW_AT_high_pc [DW_FORM_data4] +; PRE-BOLT: DW_AT_addr_base [DW_FORM_sec_offset] (0x00000008) + +; BOLT: Addrs: [ +; BOLT-NEXT: 0x +; BOLT-NEXT: 0x +; BOLT-NEXT: 0x[[#%.16x,ADDR:]] +; BOLT-NEXT: 0x +; BOLT-NEXT: 0x[[#%.16x,ADDR2:]] +; BOLT: Addrs: [ +; BOLT-NEXT: 0x +; BOLT-NEXT: 0x +; BOLT-NEXT: 0x[[#%.16x,ADDR3:]] +; BOLT: DW_TAG_skeleton_unit +; BOLT: DW_AT_dwo_name [DW_FORM_strx1] (indexed (00000001) string = "main.dwo.dwo") +; BOLT-NEXT: DW_AT_low_pc [DW_FORM_addrx] (indexed (00000003) address = 0x0000000000000000) +; BOLT-NEXT: DW_AT_ranges [DW_FORM_rnglistx] (indexed (0x0) rangelist = 0x00000010 +; BOLT-NEXT: [0x[[#ADDR]] +; BOLT-SAME: 0x[[#ADDR + 0x24]] +; BOLT-NEXT: [0x[[#ADDR2]] +; BOLT-SAME: 0x[[#ADDR2 + 0x59]] +; BOLT-NEXT: DW_AT_addr_base [DW_FORM_sec_offset] (0x00000008) +; BOLT-NEXT: DW_AT_rnglists_base [DW_FORM_sec_offset] (0x0000000c) +; BOLT: DW_TAG_skeleton_unit +; BOLT: DW_AT_dwo_name [DW_FORM_strx1] (indexed (00000001) string = "helper.dwo.dwo") +; BOLT-NEXT: DW_AT_low_pc [DW_FORM_addrx] (indexed (00000003) address = 0x0000000000000000) +; BOLT-NEXT: DW_AT_ranges [DW_FORM_rnglistx] (indexed (0x0) rangelist = 0x00000027 +; BOLT-NEXT: [0x[[#ADDR3]] +; BOLT-SAME: 0x[[#ADDR3 + 0x3D]] +; BOLT-NEXT: DW_AT_addr_base [DW_FORM_sec_offset] (0x00000038) +; BOLT-NEXT: DW_AT_rnglists_base [DW_FORM_sec_offset] (0x00000023) + +; PRE-BOLT-DWO-MAIN: version = 0x0005 +; PRE-BOLT-DWO-MAIN: DW_TAG_compile_unit +; PRE-BOLT-DWO-MAIN: DW_TAG_variable [2] +; PRE-BOLT-DWO-MAIN-NEXT: DW_AT_name [DW_FORM_strx1] (indexed (00000000) string = "x") +; PRE-BOLT-DWO-MAIN-NEXT: DW_AT_type +; PRE-BOLT-DWO-MAIN-NEXT: DW_AT_external +; PRE-BOLT-DWO-MAIN-NEXT: DW_AT_decl_file +; PRE-BOLT-DWO-MAIN-NEXT: DW_AT_decl_line +; PRE-BOLT-DWO-MAIN-NEXT: DW_AT_location [DW_FORM_exprloc] (DW_OP_addrx 0x0) +; PRE-BOLT-DWO-MAIN: DW_TAG_variable [2] +; PRE-BOLT-DWO-MAIN-NEXT: DW_AT_name [DW_FORM_strx1] (indexed (00000002) string = "y") +; PRE-BOLT-DWO-MAIN-NEXT: DW_AT_type +; PRE-BOLT-DWO-MAIN-NEXT: DW_AT_external +; PRE-BOLT-DWO-MAIN-NEXT: DW_AT_decl_file +; PRE-BOLT-DWO-MAIN-NEXT: DW_AT_decl_line +; PRE-BOLT-DWO-MAIN-NEXT: DW_AT_location [DW_FORM_exprloc] (DW_OP_addrx 0x1) +; PRE-BOLT-DWO-MAIN: DW_TAG_subprogram +; PRE-BOLT-DWO-MAIN-NEXT: DW_AT_low_pc [DW_FORM_addrx] (indexed (00000002) +; PRE-BOLT-DWO-MAIN-NEXT: DW_AT_high_pc [DW_FORM_data4] (0x00000024) +; PRE-BOLT-DWO-MAIN-NEXT: DW_AT_frame_base +; PRE-BOLT-DWO-MAIN-NEXT: DW_AT_linkage_name [DW_FORM_strx1] (indexed (00000003) string = "_Z3usePiS_") +; PRE-BOLT-DWO-MAIN-NEXT: DW_AT_name [DW_FORM_strx1] (indexed (00000004) string = "use") +; PRE-BOLT-DWO-MAIN: DW_TAG_subprogram +; PRE-BOLT-DWO-MAIN-NEXT: DW_AT_low_pc [DW_FORM_addrx] (indexed (00000003) +; PRE-BOLT-DWO-MAIN-NEXT: DW_AT_high_pc [DW_FORM_data4] (0x0000005f) +; PRE-BOLT-DWO-MAIN-NEXT: DW_AT_frame_base +; PRE-BOLT-DWO-MAIN-NEXT: DW_AT_name [DW_FORM_strx1] (indexed (00000005) string = "main") + +; BOLT-DWO-MAIN: DW_TAG_compile_unit +; BOLT-DWO-MAIN: DW_TAG_variable [2] +; BOLT-DWO-MAIN-NEXT: DW_AT_name [DW_FORM_strx1] (indexed (00000000) string = "x") +; BOLT-DWO-MAIN-NEXT: DW_AT_type +; BOLT-DWO-MAIN-NEXT: DW_AT_external +; BOLT-DWO-MAIN-NEXT: DW_AT_decl_file +; BOLT-DWO-MAIN-NEXT: DW_AT_decl_line +; BOLT-DWO-MAIN-NEXT: DW_AT_location [DW_FORM_exprloc] (DW_OP_addrx 0x0) +; BOLT-DWO-MAIN: DW_TAG_variable [2] +; BOLT-DWO-MAIN-NEXT: DW_AT_name [DW_FORM_strx1] (indexed (00000002) string = "y") +; BOLT-DWO-MAIN-NEXT: DW_AT_type +; BOLT-DWO-MAIN-NEXT: DW_AT_external +; BOLT-DWO-MAIN-NEXT: DW_AT_decl_file +; BOLT-DWO-MAIN-NEXT: DW_AT_decl_line +; BOLT-DWO-MAIN-NEXT: DW_AT_location [DW_FORM_exprloc] (DW_OP_addrx 0x1) +; BOLT-DWO-MAIN: DW_TAG_subprogram [4] +; BOLT-DWO-MAIN-NEXT: DW_AT_low_pc [DW_FORM_addrx] (indexed (00000003) +; BOLT-DWO-MAIN-NEXT: DW_AT_ranges [DW_FORM_rnglistx] (indexed (0x0) rangelist = 0x00000014 +; BOLT-DWO-MAIN-NEXT: [0x0000000000000000, 0x0000000000000024)) +; BOLT-DWO-MAIN-NEXT: DW_AT_frame_base +; BOLT-DWO-MAIN-NEXT: DW_AT_linkage_name [DW_FORM_strx1] (indexed (00000003) string = "_Z3usePiS_") +; BOLT-DWO-MAIN-NEXT: DW_AT_name [DW_FORM_strx1] (indexed (00000004) string = "use") +; BOLT-DWO-MAIN: DW_TAG_subprogram [6] +; BOLT-DWO-MAIN-NEXT: DW_AT_low_pc [DW_FORM_addrx] (indexed (00000003) +; BOLT-DWO-MAIN-NEXT: DW_AT_ranges [DW_FORM_rnglistx] (indexed (0x1) rangelist = 0x00000018 +; BOLT-DWO-MAIN-NEXT: [0x0000000000000000, 0x0000000000000059)) +; BOLT-DWO-MAIN-NEXT: DW_AT_frame_base [DW_FORM_exprloc] (DW_OP_reg6 RBP) +; BOLT-DWO-MAIN-NEXT: DW_AT_name [DW_FORM_strx1] (indexed (00000005) string = "main") + + +; PRE-BOLT-DWO-HELPER: version = 0x0005 +; PRE-BOLT-DWO-HELPER: DW_TAG_variable [2] +; PRE-BOLT-DWO-HELPER-NEXT: DW_AT_name [DW_FORM_strx1] (indexed (00000000) string = "z") +; PRE-BOLT-DWO-HELPER-NEXT: DW_AT_type +; PRE-BOLT-DWO-HELPER-NEXT: DW_AT_external +; PRE-BOLT-DWO-HELPER-NEXT: DW_AT_decl_file +; PRE-BOLT-DWO-HELPER-NEXT: DW_AT_decl_line +; PRE-BOLT-DWO-HELPER-NEXT: DW_AT_location [DW_FORM_exprloc] (DW_OP_addrx 0x0) +; PRE-BOLT-DWO-HELPER: DW_TAG_variable [2] +; PRE-BOLT-DWO-HELPER-NEXT: DW_AT_name [DW_FORM_strx1] (indexed (00000002) string = "d") +; PRE-BOLT-DWO-HELPER-NEXT: DW_AT_type +; PRE-BOLT-DWO-HELPER-NEXT: DW_AT_external +; PRE-BOLT-DWO-HELPER-NEXT: DW_AT_decl_file +; PRE-BOLT-DWO-HELPER-NEXT: DW_AT_decl_line +; PRE-BOLT-DWO-HELPER-NEXT: DW_AT_location [DW_FORM_exprloc] (DW_OP_addrx 0x1) +; PRE-BOLT-DWO-HELPER: DW_TAG_subprogram [4] +; PRE-BOLT-DWO-HELPER-NEXT: DW_AT_low_pc [DW_FORM_addrx] (indexed (00000002) +; PRE-BOLT-DWO-HELPER-NEXT: DW_AT_high_pc [DW_FORM_data4] (0x0000003d) + +; BOLT-DWO-HELPER: version = 0x0005 +; BOLT-DWO-HELPER: DW_TAG_variable [2] +; BOLT-DWO-HELPER-NEXT: DW_AT_name [DW_FORM_strx1] (indexed (00000000) string = "z") +; BOLT-DWO-HELPER-NEXT: DW_AT_type +; BOLT-DWO-HELPER-NEXT: DW_AT_external +; BOLT-DWO-HELPER-NEXT: DW_AT_decl_file +; BOLT-DWO-HELPER-NEXT: DW_AT_decl_line +; BOLT-DWO-HELPER-NEXT: DW_AT_location [DW_FORM_exprloc] (DW_OP_addrx 0x0) +; BOLT-DWO-HELPER: DW_TAG_variable [2] +; BOLT-DWO-HELPER-NEXT: DW_AT_name [DW_FORM_strx1] (indexed (00000002) string = "d") +; BOLT-DWO-HELPER-NEXT: DW_AT_type +; BOLT-DWO-HELPER-NEXT: DW_AT_external +; BOLT-DWO-HELPER-NEXT: DW_AT_decl_file +; BOLT-DWO-HELPER-NEXT: DW_AT_decl_line +; BOLT-DWO-HELPER-NEXT: DW_AT_location [DW_FORM_exprloc] (DW_OP_addrx 0x1) +; BOLT-DWO-HELPER: DW_TAG_subprogram [4] +; BOLT-DWO-HELPER-NEXT: DW_AT_low_pc [DW_FORM_addrx] (indexed (00000003) +; BOLT-DWO-HELPER-NEXT: DW_AT_ranges [DW_FORM_rnglistx] (indexed (0x0) rangelist = 0x00000010 +; BOLT-DWO-HELPER-NEXT: [0x0000000000000000, 0x000000000000003d)) diff --git a/bolt/test/X86/dwarf5-df-mono-dualcu.test b/bolt/test/X86/dwarf5-df-mono-dualcu.test new file mode 100644 --- /dev/null +++ b/bolt/test/X86/dwarf5-df-mono-dualcu.test @@ -0,0 +1,130 @@ +; RUN: rm -rf %t +; RUN: mkdir %t +; RUN: cd %t +; RUN: llc -split-dwarf-file=main.dwo -split-dwarf-output=main.dwo -O0 -mtriple=x86_64-unknown-linux-gnu \ +; RUN: -filetype=obj %p/Inputs/dwarf5-df-mono-main.ll -o=main.o +; RUN: llc -O0 -mtriple=x86_64-unknown-linux-gnu -filetype=obj %p/Inputs/dwarf5-df-mono-helper.ll -o=helper.o +; RUN: %clang %cflags -gdwarf-5 main.o helper.o -o main.exe +; RUN: llvm-bolt main.exe -o main.exe.bolt --update-debug-sections +; RUN: llvm-dwarfdump --show-form --verbose --debug-info main.exe | FileCheck -check-prefix=PRE-BOLT %s +; RUN: llvm-dwarfdump --show-form --verbose --debug-addr main.exe.bolt &> %t/foo.txt +; RUN: llvm-dwarfdump --show-form --verbose --debug-info main.exe.bolt >> %t/foo.txt +; RUN: cat %t/foo.txt | FileCheck -check-prefix=BOLT %s +; RUN: llvm-dwarfdump --show-form --verbose --debug-info main.dwo | FileCheck -check-prefix=PRE-BOLT-DWO-MAIN %s +; RUN: llvm-dwarfdump --show-form --verbose --debug-info main.dwo.dwo | FileCheck -check-prefix=BOLT-DWO-MAIN %s + +; Testing dwarf5 mix of split dwarf and monolithic CUs. + +; PRE-BOLT: version = 0x0005 +; PRE-BOLT: DW_TAG_skeleton_unit +; PRE-BOLT: DW_AT_low_pc [DW_FORM_addrx] +; PRE-BOLT-NEXT: DW_AT_high_pc [DW_FORM_data4] +; PRE-BOLT: DW_AT_addr_base [DW_FORM_sec_offset] (0x00000008) +; PRE-BOLT: version = 0x0005 +; PRE-BOLT: DW_TAG_compile_unit +; PRE-BOLT: DW_AT_low_pc [DW_FORM_addrx] (indexed (00000002) +; PRE-BOLT-NEXT: DW_AT_high_pc [DW_FORM_data4] (0x0000003d) +; PRE-BOLT-NEXT: DW_AT_addr_base [DW_FORM_sec_offset] (0x00000030) + +; BOLT: Addrs: [ +; BOLT-NEXT: 0x +; BOLT-NEXT: 0x +; BOLT-NEXT: 0x[[#%.16x,ADDR:]] +; BOLT-NEXT: 0x +; BOLT-NEXT: 0x[[#%.16x,ADDR2:]] +; BOLT: Addrs: [ +; BOLT-NEXT: 0x[[#%.16x,ADDR3:]] +; BOLT: DW_TAG_skeleton_unit +; BOLT: DW_AT_dwo_name [DW_FORM_strx1] (indexed (00000001) string = "main.dwo.dwo") +; BOLT-NEXT: DW_AT_low_pc [DW_FORM_addrx] (indexed (00000003) address = 0x0000000000000000) +; BOLT-NEXT: DW_AT_ranges [DW_FORM_rnglistx] (indexed (0x0) rangelist = 0x00000010 +; BOLT-NEXT: [0x[[#ADDR]] +; BOLT-SAME: 0x[[#ADDR + 0x24]] +; BOLT-NEXT: [0x[[#ADDR2]] +; BOLT-SAME: 0x[[#ADDR2 + 0x59]] +; BOLT-NEXT: DW_AT_addr_base [DW_FORM_sec_offset] (0x00000008) +; BOLT-NEXT: DW_AT_rnglists_base [DW_FORM_sec_offset] (0x0000000c) +; BOLT: DW_TAG_compile_unit +; BOLT: DW_AT_name [DW_FORM_strx1] (indexed (00000001) string = "helper.cpp") +; BOLT: DW_AT_low_pc [DW_FORM_addrx] (indexed (00000001) address = 0x0000000000000000) +; BOLT-NEXT: DW_AT_ranges [DW_FORM_rnglistx] (indexed (0x0) rangelist = 0x0000002b +; BOLT-NEXT: [0x[[#ADDR3]] +; BOLT-SAME: 0x[[#ADDR3 + 0x3D]] +; BOLT-NEXT: DW_AT_addr_base [DW_FORM_sec_offset] (0x00000038) +; BOLT-NEXT: DW_AT_rnglists_base [DW_FORM_sec_offset] (0x00000023) +; BOLT: DW_TAG_variable +; BOLT-NEXT: DW_AT_name [DW_FORM_strx1] (indexed (00000003) string = "z") +; BOLT-NEXT: DW_AT_type +; BOLT-NEXT: DW_AT_external +; BOLT-NEXT: DW_AT_decl_file +; BOLT-NEXT: DW_AT_decl_line +; BOLT-NEXT: DW_AT_location [DW_FORM_exprloc] (DW_OP_addrx 0x2) +; BOLT: DW_TAG_variable +; BOLT-NEXT: DW_AT_name [DW_FORM_strx1] (indexed (00000005) string = "d") +; BOLT-NEXT: DW_AT_type +; BOLT-NEXT: DW_AT_external +; BOLT-NEXT: DW_AT_decl_file +; BOLT-NEXT: DW_AT_decl_line +; BOLT-NEXT: DW_AT_location [DW_FORM_exprloc] (DW_OP_addrx 0x3) +; BOLT: DW_TAG_subprogram +; BOLT-NEXT: DW_AT_low_pc [DW_FORM_addrx] (indexed (00000001) address = 0x0000000000000000) +; BOLT-NEXT: DW_AT_ranges [DW_FORM_rnglistx] (indexed (0x1) rangelist = 0x0000002f +; BOLT-NEXT: [0x[[#ADDR3]] +; BOLT-SAME: 0x[[#ADDR3 + 0x3D]] + +; PRE-BOLT-DWO-MAIN: version = 0x0005 +; PRE-BOLT-DWO-MAIN: DW_TAG_compile_unit +; PRE-BOLT-DWO-MAIN: DW_TAG_variable [2] +; PRE-BOLT-DWO-MAIN-NEXT: DW_AT_name [DW_FORM_strx1] (indexed (00000000) string = "x") +; PRE-BOLT-DWO-MAIN-NEXT: DW_AT_type +; PRE-BOLT-DWO-MAIN-NEXT: DW_AT_external +; PRE-BOLT-DWO-MAIN-NEXT: DW_AT_decl_file +; PRE-BOLT-DWO-MAIN-NEXT: DW_AT_decl_line +; PRE-BOLT-DWO-MAIN-NEXT: DW_AT_location [DW_FORM_exprloc] (DW_OP_addrx 0x0) +; PRE-BOLT-DWO-MAIN: DW_TAG_variable [2] +; PRE-BOLT-DWO-MAIN-NEXT: DW_AT_name [DW_FORM_strx1] (indexed (00000002) string = "y") +; PRE-BOLT-DWO-MAIN-NEXT: DW_AT_type +; PRE-BOLT-DWO-MAIN-NEXT: DW_AT_external +; PRE-BOLT-DWO-MAIN-NEXT: DW_AT_decl_file +; PRE-BOLT-DWO-MAIN-NEXT: DW_AT_decl_line +; PRE-BOLT-DWO-MAIN-NEXT: DW_AT_location [DW_FORM_exprloc] (DW_OP_addrx 0x1) +; PRE-BOLT-DWO-MAIN: DW_TAG_subprogram +; PRE-BOLT-DWO-MAIN-NEXT: DW_AT_low_pc [DW_FORM_addrx] (indexed (00000002) +; PRE-BOLT-DWO-MAIN-NEXT: DW_AT_high_pc [DW_FORM_data4] (0x00000024) +; PRE-BOLT-DWO-MAIN-NEXT: DW_AT_frame_base +; PRE-BOLT-DWO-MAIN-NEXT: DW_AT_linkage_name [DW_FORM_strx1] (indexed (00000003) string = "_Z3usePiS_") +; PRE-BOLT-DWO-MAIN-NEXT: DW_AT_name [DW_FORM_strx1] (indexed (00000004) string = "use") +; PRE-BOLT-DWO-MAIN: DW_TAG_subprogram +; PRE-BOLT-DWO-MAIN-NEXT: DW_AT_low_pc [DW_FORM_addrx] (indexed (00000003) +; PRE-BOLT-DWO-MAIN-NEXT: DW_AT_high_pc [DW_FORM_data4] (0x0000005f) +; PRE-BOLT-DWO-MAIN-NEXT: DW_AT_frame_base +; PRE-BOLT-DWO-MAIN-NEXT: DW_AT_name [DW_FORM_strx1] (indexed (00000005) string = "main") + +; BOLT-DWO-MAIN: DW_TAG_compile_unit +; BOLT-DWO-MAIN: DW_TAG_variable [2] +; BOLT-DWO-MAIN-NEXT: DW_AT_name [DW_FORM_strx1] (indexed (00000000) string = "x") +; BOLT-DWO-MAIN-NEXT: DW_AT_type +; BOLT-DWO-MAIN-NEXT: DW_AT_external +; BOLT-DWO-MAIN-NEXT: DW_AT_decl_file +; BOLT-DWO-MAIN-NEXT: DW_AT_decl_line +; BOLT-DWO-MAIN-NEXT: DW_AT_location [DW_FORM_exprloc] (DW_OP_addrx 0x0) +; BOLT-DWO-MAIN: DW_TAG_variable [2] +; BOLT-DWO-MAIN-NEXT: DW_AT_name [DW_FORM_strx1] (indexed (00000002) string = "y") +; BOLT-DWO-MAIN-NEXT: DW_AT_type +; BOLT-DWO-MAIN-NEXT: DW_AT_external +; BOLT-DWO-MAIN-NEXT: DW_AT_decl_file +; BOLT-DWO-MAIN-NEXT: DW_AT_decl_line +; BOLT-DWO-MAIN-NEXT: DW_AT_location [DW_FORM_exprloc] (DW_OP_addrx 0x1) +; BOLT-DWO-MAIN: DW_TAG_subprogram [4] +; BOLT-DWO-MAIN-NEXT: DW_AT_low_pc [DW_FORM_addrx] (indexed (00000003) +; BOLT-DWO-MAIN-NEXT: DW_AT_ranges [DW_FORM_rnglistx] (indexed (0x0) rangelist = 0x00000014 +; BOLT-DWO-MAIN-NEXT: [0x0000000000000000, 0x0000000000000024)) +; BOLT-DWO-MAIN-NEXT: DW_AT_frame_base +; BOLT-DWO-MAIN-NEXT: DW_AT_linkage_name [DW_FORM_strx1] (indexed (00000003) string = "_Z3usePiS_") +; BOLT-DWO-MAIN-NEXT: DW_AT_name [DW_FORM_strx1] (indexed (00000004) string = "use") +; BOLT-DWO-MAIN: DW_TAG_subprogram [6] +; BOLT-DWO-MAIN-NEXT: DW_AT_low_pc [DW_FORM_addrx] (indexed (00000003) +; BOLT-DWO-MAIN-NEXT: DW_AT_ranges [DW_FORM_rnglistx] (indexed (0x1) rangelist = 0x00000018 +; BOLT-DWO-MAIN-NEXT: [0x0000000000000000, 0x0000000000000059)) +; BOLT-DWO-MAIN-NEXT: DW_AT_frame_base [DW_FORM_exprloc] (DW_OP_reg6 RBP) +; BOLT-DWO-MAIN-NEXT: DW_AT_name [DW_FORM_strx1] (indexed (00000005) string = "main") diff --git a/bolt/test/X86/dwarf5-locaddrx.test b/bolt/test/X86/dwarf5-locaddrx.test new file mode 100644 --- /dev/null +++ b/bolt/test/X86/dwarf5-locaddrx.test @@ -0,0 +1,209 @@ +; RUN: rm -rf %t +; RUN: mkdir %t +; RUN: cd %t +; RUN: llc -split-dwarf-file=mainlocadddrx.dwo -split-dwarf-output=mainlocadddrx.dwo -O0 -mtriple=x86_64-unknown-linux-gnu -filetype=obj %s -o=mainlocadddrx.o +; RUN: %clang %cflags -gdwarf-5 -gsplit-dwarf=split mainlocadddrx.o -o mainlocadddrx.exe +; RUN: llvm-bolt mainlocadddrx.exe -o mainlocadddrx.exe.bolt --update-debug-sections +; RUN: llvm-dwarfdump --show-form --verbose --debug-info mainlocadddrx.exe | FileCheck -check-prefix=PRE-BOLT %s +; RUN: llvm-dwarfdump --show-form --verbose --debug-addr mainlocadddrx.exe.bolt &> %t/foo.txt +; RUN: llvm-dwarfdump --show-form --verbose --debug-info mainlocadddrx.exe.bolt >> %t/foo.txt +; RUN: cat %t/foo.txt | FileCheck -check-prefix=BOLT %s +; RUN: llvm-dwarfdump --show-form --verbose --debug-info mainlocadddrx.dwo | FileCheck -check-prefix=PRE-BOLT-DWO %s +; RUN: llvm-dwarfdump --show-form --verbose --debug-info mainlocadddrx.dwo.dwo | FileCheck -check-prefix=BOLT-DWO %s + +; Testing dwarf5 split dwarf. Making sure DW_AT_low_pc/DW_AT_high_pc are converted correctly in the binary and in dwo. +; Checking that DW_AT_location [DW_FORM_exprloc] (DW_OP_addrx 0x0) is updated correctly. + +; PRE-BOLT: version = 0x0005 +; PRE-BOLT: DW_TAG_skeleton_unit +; PRE-BOLT: DW_AT_low_pc [DW_FORM_addrx] +; PRE-BOLT-NEXT: DW_AT_high_pc [DW_FORM_data4] +; PRE-BOLT: DW_AT_addr_base [DW_FORM_sec_offset] (0x00000008) + +; BOLT: Addrs: [ +; BOLT-NEXT: 0x +; BOLT-NEXT: 0x +; BOLT-NEXT: 0x[[#%.16x,ADDR:]] +; BOLT-NEXT: 0x +; BOLT-NEXT: 0x[[#%.16x,ADDR2:]] +; BOLT: DW_TAG_skeleton_unit +; BOLT: DW_AT_low_pc [DW_FORM_addrx] (indexed (00000003) address = 0x0000000000000000) +; BOLT-NEXT: DW_AT_ranges [DW_FORM_rnglistx] (indexed (0x0) rangelist = 0x00000010 +; BOLT-NEXT: [0x[[#ADDR]] +; BOLT-SAME: 0x[[#ADDR + 0x24]] +; BOLT-NEXT: [0x[[#ADDR2]] +; BOLT-SAME: 0x[[#ADDR2 + 0x54]] +; BOLT-NEXT: DW_AT_addr_base [DW_FORM_sec_offset] (0x00000008) +; BOLT-NEXT: DW_AT_rnglists_base [DW_FORM_sec_offset] (0x0000000c) + +; PRE-BOLT-DWO: version = 0x0005 +; PRE-BOLT-DWO: DW_TAG_compile_unit +; PRE-BOLT-DWO: DW_TAG_variable [2] +; PRE-BOLT-DWO-NEXT: DW_AT_name [DW_FORM_strx1] (indexed (00000000) string = "x") +; PRE-BOLT-DWO-NEXT: DW_AT_type +; PRE-BOLT-DWO-NEXT: DW_AT_external +; PRE-BOLT-DWO-NEXT: DW_AT_decl_file +; PRE-BOLT-DWO-NEXT: DW_AT_decl_line +; PRE-BOLT-DWO-NEXT: DW_AT_location [DW_FORM_exprloc] (DW_OP_addrx 0x0) +; PRE-BOLT-DWO: DW_TAG_variable [2] +; PRE-BOLT-DWO-NEXT: DW_AT_name [DW_FORM_strx1] (indexed (00000002) string = "y") +; PRE-BOLT-DWO-NEXT: DW_AT_type +; PRE-BOLT-DWO-NEXT: DW_AT_external +; PRE-BOLT-DWO-NEXT: DW_AT_decl_file +; PRE-BOLT-DWO-NEXT: DW_AT_decl_line +; PRE-BOLT-DWO-NEXT: DW_AT_location [DW_FORM_exprloc] (DW_OP_addrx 0x1) +; PRE-BOLT-DWO: DW_TAG_subprogram +; PRE-BOLT-DWO-NEXT: DW_AT_low_pc [DW_FORM_addrx] (indexed (00000002) +; PRE-BOLT-DWO-NEXT: DW_AT_high_pc [DW_FORM_data4] (0x00000024) +; PRE-BOLT-DWO: DW_TAG_subprogram +; PRE-BOLT-DWO-NEXT: DW_AT_low_pc [DW_FORM_addrx] (indexed (00000003) +; PRE-BOLT-DWO-NEXT: DW_AT_high_pc [DW_FORM_data4] (0x0000005a) + +; BOLT-DWO: DW_TAG_compile_unit +; BOLT-DWO: DW_TAG_variable [2] +; BOLT-DWO-NEXT: DW_AT_name [DW_FORM_strx1] (indexed (00000000) string = "x") +; BOLT-DWO-NEXT: DW_AT_type +; BOLT-DWO-NEXT: DW_AT_external +; BOLT-DWO-NEXT: DW_AT_decl_file +; BOLT-DWO-NEXT: DW_AT_decl_line +; BOLT-DWO-NEXT: DW_AT_location [DW_FORM_exprloc] (DW_OP_addrx 0x0) +; BOLT-DWO: DW_TAG_variable [2] +; BOLT-DWO-NEXT: DW_AT_name [DW_FORM_strx1] (indexed (00000002) string = "y") +; BOLT-DWO-NEXT: DW_AT_type +; BOLT-DWO-NEXT: DW_AT_external +; BOLT-DWO-NEXT: DW_AT_decl_file +; BOLT-DWO-NEXT: DW_AT_decl_line +; BOLT-DWO-NEXT: DW_AT_location [DW_FORM_exprloc] (DW_OP_addrx 0x1) +; BOLT-DWO: DW_TAG_subprogram [4] +; BOLT-DWO-NEXT: DW_AT_low_pc [DW_FORM_addrx] (indexed (00000003) +; BOLT-DWO-NEXT: DW_AT_ranges [DW_FORM_rnglistx] (indexed (0x0) rangelist = 0x00000014 +; BOLT-DWO-NEXT: [0x0000000000000000, 0x0000000000000024)) +; BOLT-DWO: DW_TAG_subprogram [6] +; BOLT-DWO-NEXT: DW_AT_low_pc [DW_FORM_addrx] (indexed (00000003) +; BOLT-DWO-NEXT: DW_AT_ranges [DW_FORM_rnglistx] (indexed (0x1) rangelist = 0x00000018 +; BOLT-DWO-NEXT: [0x0000000000000000, 0x0000000000000054)) + +; void use(int * x, int * y) { +; *x += 4; +; *y -= 2; +; } +; +; int x = 0; +; int y = 1; +; int main(int argc, char *argv[]) { +; x = argc; +; y = argc + 3; +; use(&x, &y); +; return x + y; +; } + +; ModuleID = 'mainlocadddrx.cpp' +source_filename = "mainlocadddrx.cpp" +target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +@x = dso_local global i32 0, align 4, !dbg !0 +@y = dso_local global i32 1, align 4, !dbg !5 + +; Function Attrs: mustprogress noinline nounwind optnone uwtable +define dso_local void @_Z3usePiS_(i32* noundef %x, i32* noundef %y) #0 !dbg !14 { +entry: + %x.addr = alloca i32*, align 8 + %y.addr = alloca i32*, align 8 + store i32* %x, i32** %x.addr, align 8 + call void @llvm.dbg.declare(metadata i32** %x.addr, metadata !19, metadata !DIExpression()), !dbg !20 + store i32* %y, i32** %y.addr, align 8 + call void @llvm.dbg.declare(metadata i32** %y.addr, metadata !21, metadata !DIExpression()), !dbg !22 + %0 = load i32*, i32** %x.addr, align 8, !dbg !23 + %1 = load i32, i32* %0, align 4, !dbg !24 + %add = add nsw i32 %1, 4, !dbg !24 + store i32 %add, i32* %0, align 4, !dbg !24 + %2 = load i32*, i32** %y.addr, align 8, !dbg !25 + %3 = load i32, i32* %2, align 4, !dbg !26 + %sub = sub nsw i32 %3, 2, !dbg !26 + store i32 %sub, i32* %2, align 4, !dbg !26 + ret void, !dbg !27 +} + +; Function Attrs: nofree nosync nounwind readnone speculatable willreturn +declare void @llvm.dbg.declare(metadata, metadata, metadata) #1 + +; Function Attrs: mustprogress noinline norecurse nounwind optnone uwtable +define dso_local noundef i32 @main(i32 noundef %argc, i8** noundef %argv) #2 !dbg !28 { +entry: + %retval = alloca i32, align 4 + %argc.addr = alloca i32, align 4 + %argv.addr = alloca i8**, align 8 + store i32 0, i32* %retval, align 4 + store i32 %argc, i32* %argc.addr, align 4 + call void @llvm.dbg.declare(metadata i32* %argc.addr, metadata !34, metadata !DIExpression()), !dbg !35 + store i8** %argv, i8*** %argv.addr, align 8 + call void @llvm.dbg.declare(metadata i8*** %argv.addr, metadata !36, metadata !DIExpression()), !dbg !37 + %0 = load i32, i32* %argc.addr, align 4, !dbg !38 + store i32 %0, i32* @x, align 4, !dbg !39 + %1 = load i32, i32* %argc.addr, align 4, !dbg !40 + %add = add nsw i32 %1, 3, !dbg !41 + store i32 %add, i32* @y, align 4, !dbg !42 + call void @_Z3usePiS_(i32* noundef @x, i32* noundef @y), !dbg !43 + %2 = load i32, i32* @x, align 4, !dbg !44 + %3 = load i32, i32* @y, align 4, !dbg !45 + %add1 = add nsw i32 %2, %3, !dbg !46 + ret i32 %add1, !dbg !47 +} + +attributes #0 = { mustprogress noinline nounwind optnone uwtable "frame-pointer"="all" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" } +attributes #1 = { nofree nosync nounwind readnone speculatable willreturn } +attributes #2 = { mustprogress noinline norecurse nounwind optnone uwtable "frame-pointer"="all" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" } + +!llvm.dbg.cu = !{!2} +!llvm.module.flags = !{!8, !9, !10, !11, !12} +!llvm.ident = !{!13} + +!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression()) +!1 = distinct !DIGlobalVariable(name: "x", scope: !2, file: !3, line: 6, type: !7, isLocal: false, isDefinition: true) +!2 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !3, producer: "clang version 15.0.0", isOptimized: false, runtimeVersion: 0, splitDebugFilename: "mainlocadddrx.dwo", emissionKind: FullDebug, globals: !4, splitDebugInlining: false, nameTableKind: GNU) +!3 = !DIFile(filename: "mainlocadddrx.cpp", directory: ".", checksumkind: CSK_MD5, checksum: "d4fd79ce0087c4cefd089752bf2182c6") +!4 = !{!0, !5} +!5 = !DIGlobalVariableExpression(var: !6, expr: !DIExpression()) +!6 = distinct !DIGlobalVariable(name: "y", scope: !2, file: !3, line: 7, type: !7, isLocal: false, isDefinition: true) +!7 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!8 = !{i32 7, !"Dwarf Version", i32 5} +!9 = !{i32 2, !"Debug Info Version", i32 3} +!10 = !{i32 1, !"wchar_size", i32 4} +!11 = !{i32 7, !"uwtable", i32 2} +!12 = !{i32 7, !"frame-pointer", i32 2} +!13 = !{!"clang version 15.0.0"} +!14 = distinct !DISubprogram(name: "use", linkageName: "_Z3usePiS_", scope: !3, file: !3, line: 1, type: !15, scopeLine: 1, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !2, retainedNodes: !18) +!15 = !DISubroutineType(types: !16) +!16 = !{null, !17, !17} +!17 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !7, size: 64) +!18 = !{} +!19 = !DILocalVariable(name: "x", arg: 1, scope: !14, file: !3, line: 1, type: !17) +!20 = !DILocation(line: 1, column: 16, scope: !14) +!21 = !DILocalVariable(name: "y", arg: 2, scope: !14, file: !3, line: 1, type: !17) +!22 = !DILocation(line: 1, column: 25, scope: !14) +!23 = !DILocation(line: 2, column: 2, scope: !14) +!24 = !DILocation(line: 2, column: 4, scope: !14) +!25 = !DILocation(line: 3, column: 2, scope: !14) +!26 = !DILocation(line: 3, column: 4, scope: !14) +!27 = !DILocation(line: 4, column: 1, scope: !14) +!28 = distinct !DISubprogram(name: "main", scope: !3, file: !3, line: 8, type: !29, scopeLine: 8, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !2, retainedNodes: !18) +!29 = !DISubroutineType(types: !30) +!30 = !{!7, !7, !31} +!31 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !32, size: 64) +!32 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !33, size: 64) +!33 = !DIBasicType(name: "char", size: 8, encoding: DW_ATE_signed_char) +!34 = !DILocalVariable(name: "argc", arg: 1, scope: !28, file: !3, line: 8, type: !7) +!35 = !DILocation(line: 8, column: 15, scope: !28) +!36 = !DILocalVariable(name: "argv", arg: 2, scope: !28, file: !3, line: 8, type: !31) +!37 = !DILocation(line: 8, column: 27, scope: !28) +!38 = !DILocation(line: 9, column: 8, scope: !28) +!39 = !DILocation(line: 9, column: 6, scope: !28) +!40 = !DILocation(line: 10, column: 8, scope: !28) +!41 = !DILocation(line: 10, column: 13, scope: !28) +!42 = !DILocation(line: 10, column: 6, scope: !28) +!43 = !DILocation(line: 11, column: 4, scope: !28) +!44 = !DILocation(line: 12, column: 11, scope: !28) +!45 = !DILocation(line: 12, column: 15, scope: !28) +!46 = !DILocation(line: 12, column: 13, scope: !28) +!47 = !DILocation(line: 12, column: 4, scope: !28)