aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm-project/llvm/lib/DWARFLinkerParallel/DWARFLinkerUnit.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm-project/llvm/lib/DWARFLinkerParallel/DWARFLinkerUnit.cpp')
-rw-r--r--contrib/llvm-project/llvm/lib/DWARFLinkerParallel/DWARFLinkerUnit.cpp250
1 files changed, 250 insertions, 0 deletions
diff --git a/contrib/llvm-project/llvm/lib/DWARFLinkerParallel/DWARFLinkerUnit.cpp b/contrib/llvm-project/llvm/lib/DWARFLinkerParallel/DWARFLinkerUnit.cpp
new file mode 100644
index 000000000000..b1da1900d65e
--- /dev/null
+++ b/contrib/llvm-project/llvm/lib/DWARFLinkerParallel/DWARFLinkerUnit.cpp
@@ -0,0 +1,250 @@
+//===- DWARFLinkerUnit.cpp ------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "DWARFLinkerUnit.h"
+#include "DWARFEmitterImpl.h"
+#include "DebugLineSectionEmitter.h"
+
+namespace llvm {
+namespace dwarflinker_parallel {
+
+void DwarfUnit::assignAbbrev(DIEAbbrev &Abbrev) {
+ // Check the set for priors.
+ FoldingSetNodeID ID;
+ Abbrev.Profile(ID);
+ void *InsertToken;
+
+ DIEAbbrev *InSet = AbbreviationsSet.FindNodeOrInsertPos(ID, InsertToken);
+ // If it's newly added.
+ if (InSet) {
+ // Assign existing abbreviation number.
+ Abbrev.setNumber(InSet->getNumber());
+ } else {
+ // Add to abbreviation list.
+ Abbreviations.push_back(
+ std::make_unique<DIEAbbrev>(Abbrev.getTag(), Abbrev.hasChildren()));
+ for (const auto &Attr : Abbrev.getData())
+ Abbreviations.back()->AddAttribute(Attr);
+ AbbreviationsSet.InsertNode(Abbreviations.back().get(), InsertToken);
+ // Assign the unique abbreviation number.
+ Abbrev.setNumber(Abbreviations.size());
+ Abbreviations.back()->setNumber(Abbreviations.size());
+ }
+}
+
+Error DwarfUnit::emitAbbreviations() {
+ const std::vector<std::unique_ptr<DIEAbbrev>> &Abbrevs = getAbbreviations();
+ if (Abbrevs.empty())
+ return Error::success();
+
+ SectionDescriptor &AbbrevSection =
+ getOrCreateSectionDescriptor(DebugSectionKind::DebugAbbrev);
+
+ // For each abbreviation.
+ for (const auto &Abbrev : Abbrevs)
+ emitDwarfAbbrevEntry(*Abbrev, AbbrevSection);
+
+ // Mark end of abbreviations.
+ encodeULEB128(0, AbbrevSection.OS);
+
+ return Error::success();
+}
+
+void DwarfUnit::emitDwarfAbbrevEntry(const DIEAbbrev &Abbrev,
+ SectionDescriptor &AbbrevSection) {
+ // Emit the abbreviations code (base 1 index.)
+ encodeULEB128(Abbrev.getNumber(), AbbrevSection.OS);
+
+ // Emit the abbreviations data.
+ // Emit its Dwarf tag type.
+ encodeULEB128(Abbrev.getTag(), AbbrevSection.OS);
+
+ // Emit whether it has children DIEs.
+ encodeULEB128((unsigned)Abbrev.hasChildren(), AbbrevSection.OS);
+
+ // For each attribute description.
+ const SmallVectorImpl<DIEAbbrevData> &Data = Abbrev.getData();
+ for (unsigned i = 0, N = Data.size(); i < N; ++i) {
+ const DIEAbbrevData &AttrData = Data[i];
+
+ // Emit attribute type.
+ encodeULEB128(AttrData.getAttribute(), AbbrevSection.OS);
+
+ // Emit form type.
+ encodeULEB128(AttrData.getForm(), AbbrevSection.OS);
+
+ // Emit value for DW_FORM_implicit_const.
+ if (AttrData.getForm() == dwarf::DW_FORM_implicit_const)
+ encodeSLEB128(AttrData.getValue(), AbbrevSection.OS);
+ }
+
+ // Mark end of abbreviation.
+ encodeULEB128(0, AbbrevSection.OS);
+ encodeULEB128(0, AbbrevSection.OS);
+}
+
+Error DwarfUnit::emitDebugInfo(const Triple &TargetTriple) {
+ DIE *OutUnitDIE = getOutUnitDIE();
+ if (OutUnitDIE == nullptr)
+ return Error::success();
+
+ // FIXME: Remove dependence on DwarfEmitterImpl/AsmPrinter and emit DIEs
+ // directly.
+
+ SectionDescriptor &OutSection =
+ getOrCreateSectionDescriptor(DebugSectionKind::DebugInfo);
+ DwarfEmitterImpl Emitter(DWARFLinker::OutputFileType::Object, OutSection.OS);
+ if (Error Err = Emitter.init(TargetTriple, "__DWARF"))
+ return Err;
+
+ // Emit compile unit header.
+ Emitter.emitCompileUnitHeader(*this);
+ size_t OffsetToAbbreviationTableOffset =
+ (getFormParams().Version >= 5) ? 8 : 6;
+ OutSection.notePatch(DebugOffsetPatch{
+ OffsetToAbbreviationTableOffset,
+ &getOrCreateSectionDescriptor(DebugSectionKind::DebugAbbrev)});
+
+ // Emit DIEs.
+ Emitter.emitDIE(*OutUnitDIE);
+ Emitter.finish();
+
+ // Set start offset ans size for .debug_info section.
+ OutSection.setSizesForSectionCreatedByAsmPrinter();
+ return Error::success();
+}
+
+Error DwarfUnit::emitDebugLine(const Triple &TargetTriple,
+ const DWARFDebugLine::LineTable &OutLineTable) {
+ DebugLineSectionEmitter DebugLineEmitter(TargetTriple, *this);
+
+ return DebugLineEmitter.emit(OutLineTable);
+}
+
+Error DwarfUnit::emitDebugStringOffsetSection() {
+ if (getVersion() < 5)
+ return Error::success();
+
+ if (DebugStringIndexMap.empty())
+ return Error::success();
+
+ SectionDescriptor &OutDebugStrOffsetsSection =
+ getOrCreateSectionDescriptor(DebugSectionKind::DebugStrOffsets);
+
+ // Emit section header.
+
+ // Emit length.
+ OutDebugStrOffsetsSection.emitUnitLength(0xBADDEF);
+ uint64_t OffsetAfterSectionLength = OutDebugStrOffsetsSection.OS.tell();
+
+ // Emit version.
+ OutDebugStrOffsetsSection.emitIntVal(5, 2);
+
+ // Emit padding.
+ OutDebugStrOffsetsSection.emitIntVal(0, 2);
+
+ // Emit index to offset map.
+ for (const StringEntry *String : DebugStringIndexMap.getValues()) {
+ // Note patch for string offset value.
+ OutDebugStrOffsetsSection.notePatch(
+ DebugStrPatch{{OutDebugStrOffsetsSection.OS.tell()}, String});
+
+ // Emit placeholder for offset value.
+ OutDebugStrOffsetsSection.emitOffset(0xBADDEF);
+ }
+
+ // Patch section length.
+ OutDebugStrOffsetsSection.apply(
+ OffsetAfterSectionLength -
+ OutDebugStrOffsetsSection.getFormParams().getDwarfOffsetByteSize(),
+ dwarf::DW_FORM_sec_offset,
+ OutDebugStrOffsetsSection.OS.tell() - OffsetAfterSectionLength);
+
+ return Error::success();
+}
+
+/// Emit the pubnames or pubtypes section contribution for \p
+/// Unit into \p Sec. The data is provided in \p Info.
+std::optional<uint64_t>
+DwarfUnit::emitPubAcceleratorEntry(SectionDescriptor &OutSection,
+ const DwarfUnit::AccelInfo &Info,
+ std::optional<uint64_t> LengthOffset) {
+ if (!LengthOffset) {
+ // Emit the header.
+ OutSection.emitIntVal(0xBADDEF,
+ getFormParams().getDwarfOffsetByteSize()); // Length
+ LengthOffset = OutSection.OS.tell();
+
+ OutSection.emitIntVal(dwarf::DW_PUBNAMES_VERSION, 2); // Version
+
+ OutSection.notePatch(DebugOffsetPatch{
+ OutSection.OS.tell(),
+ &getOrCreateSectionDescriptor(DebugSectionKind::DebugInfo)});
+ OutSection.emitOffset(0xBADDEF); // Unit offset
+
+ OutSection.emitIntVal(getUnitSize(), 4); // Size
+ }
+ OutSection.emitOffset(Info.OutOffset);
+
+ // Emit the string itself.
+ OutSection.emitInplaceString(Info.String->first());
+
+ return LengthOffset;
+}
+
+/// Emit .debug_pubnames and .debug_pubtypes for \p Unit.
+void DwarfUnit::emitPubAccelerators() {
+ std::optional<uint64_t> NamesLengthOffset;
+ std::optional<uint64_t> TypesLengthOffset;
+
+ forEachAcceleratorRecord([&](const DwarfUnit::AccelInfo &Info) {
+ if (Info.AvoidForPubSections)
+ return;
+
+ switch (Info.Type) {
+ case DwarfUnit::AccelType::Name: {
+ NamesLengthOffset = emitPubAcceleratorEntry(
+ getOrCreateSectionDescriptor(DebugSectionKind::DebugPubNames), Info,
+ NamesLengthOffset);
+ } break;
+ case DwarfUnit::AccelType::Type: {
+ TypesLengthOffset = emitPubAcceleratorEntry(
+ getOrCreateSectionDescriptor(DebugSectionKind::DebugPubTypes), Info,
+ TypesLengthOffset);
+ } break;
+ default: {
+ // Nothing to do.
+ } break;
+ }
+ });
+
+ if (NamesLengthOffset) {
+ SectionDescriptor &OutSection =
+ getOrCreateSectionDescriptor(DebugSectionKind::DebugPubNames);
+ OutSection.emitIntVal(0, 4); // End marker.
+
+ OutSection.apply(*NamesLengthOffset -
+ OutSection.getFormParams().getDwarfOffsetByteSize(),
+ dwarf::DW_FORM_sec_offset,
+ OutSection.OS.tell() - *NamesLengthOffset);
+ }
+
+ if (TypesLengthOffset) {
+ SectionDescriptor &OutSection =
+ getOrCreateSectionDescriptor(DebugSectionKind::DebugPubTypes);
+ OutSection.emitIntVal(0, 4); // End marker.
+
+ OutSection.apply(*TypesLengthOffset -
+ OutSection.getFormParams().getDwarfOffsetByteSize(),
+ dwarf::DW_FORM_sec_offset,
+ OutSection.OS.tell() - *TypesLengthOffset);
+ }
+}
+
+} // end of namespace dwarflinker_parallel
+} // end of namespace llvm