aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm-project/llvm/lib/DWARFLinker/Parallel/DWARFEmitterImpl.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm-project/llvm/lib/DWARFLinker/Parallel/DWARFEmitterImpl.cpp')
-rw-r--r--contrib/llvm-project/llvm/lib/DWARFLinker/Parallel/DWARFEmitterImpl.cpp279
1 files changed, 279 insertions, 0 deletions
diff --git a/contrib/llvm-project/llvm/lib/DWARFLinker/Parallel/DWARFEmitterImpl.cpp b/contrib/llvm-project/llvm/lib/DWARFLinker/Parallel/DWARFEmitterImpl.cpp
new file mode 100644
index 000000000000..115167f0c7dc
--- /dev/null
+++ b/contrib/llvm-project/llvm/lib/DWARFLinker/Parallel/DWARFEmitterImpl.cpp
@@ -0,0 +1,279 @@
+//===- DWARFEmitterImpl.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 "DWARFEmitterImpl.h"
+#include "DWARFLinkerCompileUnit.h"
+#include "llvm/MC/MCAsmBackend.h"
+#include "llvm/MC/MCCodeEmitter.h"
+#include "llvm/MC/MCObjectWriter.h"
+#include "llvm/MC/MCSubtargetInfo.h"
+#include "llvm/MC/MCTargetOptions.h"
+#include "llvm/MC/MCTargetOptionsCommandFlags.h"
+#include "llvm/MC/TargetRegistry.h"
+#include "llvm/Support/FormattedStream.h"
+
+using namespace llvm;
+using namespace dwarf_linker;
+using namespace dwarf_linker::parallel;
+
+Error DwarfEmitterImpl::init(Triple TheTriple,
+ StringRef Swift5ReflectionSegmentName) {
+ std::string ErrorStr;
+ std::string TripleName;
+
+ // Get the target.
+ const Target *TheTarget =
+ TargetRegistry::lookupTarget(TripleName, TheTriple, ErrorStr);
+ if (!TheTarget)
+ return createStringError(std::errc::invalid_argument, ErrorStr.c_str());
+ TripleName = TheTriple.getTriple();
+
+ // Create all the MC Objects.
+ MRI.reset(TheTarget->createMCRegInfo(TripleName));
+ if (!MRI)
+ return createStringError(std::errc::invalid_argument,
+ "no register info for target %s",
+ TripleName.c_str());
+
+ MCTargetOptions MCOptions = mc::InitMCTargetOptionsFromFlags();
+ MAI.reset(TheTarget->createMCAsmInfo(*MRI, TripleName, MCOptions));
+ if (!MAI)
+ return createStringError(std::errc::invalid_argument,
+ "no asm info for target %s", TripleName.c_str());
+
+ MSTI.reset(TheTarget->createMCSubtargetInfo(TripleName, "", ""));
+ if (!MSTI)
+ return createStringError(std::errc::invalid_argument,
+ "no subtarget info for target %s",
+ TripleName.c_str());
+
+ MC.reset(new MCContext(TheTriple, MAI.get(), MRI.get(), MSTI.get(), nullptr,
+ nullptr, true, Swift5ReflectionSegmentName));
+ MOFI.reset(TheTarget->createMCObjectFileInfo(*MC, /*PIC=*/false, false));
+ MC->setObjectFileInfo(MOFI.get());
+
+ MAB = TheTarget->createMCAsmBackend(*MSTI, *MRI, MCOptions);
+ if (!MAB)
+ return createStringError(std::errc::invalid_argument,
+ "no asm backend for target %s",
+ TripleName.c_str());
+
+ MII.reset(TheTarget->createMCInstrInfo());
+ if (!MII)
+ return createStringError(std::errc::invalid_argument,
+ "no instr info info for target %s",
+ TripleName.c_str());
+
+ MCE = TheTarget->createMCCodeEmitter(*MII, *MC);
+ if (!MCE)
+ return createStringError(std::errc::invalid_argument,
+ "no code emitter for target %s",
+ TripleName.c_str());
+
+ switch (OutFileType) {
+ case DWARFLinker::OutputFileType::Assembly: {
+ MIP = TheTarget->createMCInstPrinter(TheTriple, MAI->getAssemblerDialect(),
+ *MAI, *MII, *MRI);
+ MS = TheTarget->createAsmStreamer(
+ *MC, std::make_unique<formatted_raw_ostream>(OutFile), true, true, MIP,
+ std::unique_ptr<MCCodeEmitter>(MCE), std::unique_ptr<MCAsmBackend>(MAB),
+ true);
+ break;
+ }
+ case DWARFLinker::OutputFileType::Object: {
+ MS = TheTarget->createMCObjectStreamer(
+ TheTriple, *MC, std::unique_ptr<MCAsmBackend>(MAB),
+ MAB->createObjectWriter(OutFile), std::unique_ptr<MCCodeEmitter>(MCE),
+ *MSTI, MCOptions.MCRelaxAll, MCOptions.MCIncrementalLinkerCompatible,
+ /*DWARFMustBeAtTheEnd*/ false);
+ break;
+ }
+ }
+
+ if (!MS)
+ return createStringError(std::errc::invalid_argument,
+ "no object streamer for target %s",
+ TripleName.c_str());
+
+ // Finally create the AsmPrinter we'll use to emit the DIEs.
+ TM.reset(TheTarget->createTargetMachine(TripleName, "", "", TargetOptions(),
+ std::nullopt));
+ if (!TM)
+ return createStringError(std::errc::invalid_argument,
+ "no target machine for target %s",
+ TripleName.c_str());
+
+ Asm.reset(TheTarget->createAsmPrinter(*TM, std::unique_ptr<MCStreamer>(MS)));
+ if (!Asm)
+ return createStringError(std::errc::invalid_argument,
+ "no asm printer for target %s",
+ TripleName.c_str());
+ Asm->setDwarfUsesRelocationsAcrossSections(false);
+
+ DebugInfoSectionSize = 0;
+
+ return Error::success();
+}
+
+void DwarfEmitterImpl::emitSwiftAST(StringRef Buffer) {
+ MCSection *SwiftASTSection = MOFI->getDwarfSwiftASTSection();
+ SwiftASTSection->setAlignment(Align(32));
+ MS->switchSection(SwiftASTSection);
+ MS->emitBytes(Buffer);
+}
+
+/// Emit the swift reflection section stored in \p Buffer.
+void DwarfEmitterImpl::emitSwiftReflectionSection(
+ llvm::binaryformat::Swift5ReflectionSectionKind ReflSectionKind,
+ StringRef Buffer, uint32_t Alignment, uint32_t) {
+ MCSection *ReflectionSection =
+ MOFI->getSwift5ReflectionSection(ReflSectionKind);
+ if (ReflectionSection == nullptr)
+ return;
+ ReflectionSection->setAlignment(Align(Alignment));
+ MS->switchSection(ReflectionSection);
+ MS->emitBytes(Buffer);
+}
+
+void DwarfEmitterImpl::emitSectionContents(StringRef SecData,
+ StringRef SecName) {
+ if (SecData.empty())
+ return;
+
+ if (MCSection *Section = switchSection(SecName)) {
+ MS->switchSection(Section);
+
+ MS->emitBytes(SecData);
+ }
+}
+
+MCSection *DwarfEmitterImpl::switchSection(StringRef SecName) {
+ return StringSwitch<MCSection *>(SecName)
+ .Case("debug_info", MC->getObjectFileInfo()->getDwarfInfoSection())
+ .Case("debug_abbrev", MC->getObjectFileInfo()->getDwarfAbbrevSection())
+ .Case("debug_line", MC->getObjectFileInfo()->getDwarfLineSection())
+ .Case("debug_loc", MC->getObjectFileInfo()->getDwarfLocSection())
+ .Case("debug_ranges", MC->getObjectFileInfo()->getDwarfRangesSection())
+ .Case("debug_frame", MC->getObjectFileInfo()->getDwarfFrameSection())
+ .Case("debug_aranges", MC->getObjectFileInfo()->getDwarfARangesSection())
+ .Case("debug_rnglists",
+ MC->getObjectFileInfo()->getDwarfRnglistsSection())
+ .Case("debug_loclists",
+ MC->getObjectFileInfo()->getDwarfLoclistsSection())
+ .Case("debug_macro", MC->getObjectFileInfo()->getDwarfMacroSection())
+ .Case("debug_macinfo", MC->getObjectFileInfo()->getDwarfMacinfoSection())
+ .Case("debug_addr", MC->getObjectFileInfo()->getDwarfAddrSection())
+ .Case("debug_str", MC->getObjectFileInfo()->getDwarfStrSection())
+ .Case("debug_line_str", MC->getObjectFileInfo()->getDwarfLineStrSection())
+ .Case("debug_str_offsets",
+ MC->getObjectFileInfo()->getDwarfStrOffSection())
+ .Case("debug_pubnames",
+ MC->getObjectFileInfo()->getDwarfPubNamesSection())
+ .Case("debug_pubtypes",
+ MC->getObjectFileInfo()->getDwarfPubTypesSection())
+ .Case("debug_names", MC->getObjectFileInfo()->getDwarfDebugNamesSection())
+ .Case("apple_names", MC->getObjectFileInfo()->getDwarfAccelNamesSection())
+ .Case("apple_namespac",
+ MC->getObjectFileInfo()->getDwarfAccelNamespaceSection())
+ .Case("apple_objc", MC->getObjectFileInfo()->getDwarfAccelObjCSection())
+ .Case("apple_types", MC->getObjectFileInfo()->getDwarfAccelTypesSection())
+
+ .Default(nullptr);
+}
+
+void DwarfEmitterImpl::emitAbbrevs(
+ const SmallVector<std::unique_ptr<DIEAbbrev>> &Abbrevs,
+ unsigned DwarfVersion) {
+ MS->switchSection(MOFI->getDwarfAbbrevSection());
+ MC->setDwarfVersion(DwarfVersion);
+ Asm->emitDwarfAbbrevs(Abbrevs);
+}
+
+void DwarfEmitterImpl::emitCompileUnitHeader(DwarfUnit &Unit) {
+ MS->switchSection(MOFI->getDwarfInfoSection());
+ MC->setDwarfVersion(Unit.getVersion());
+
+ // Emit size of content not including length itself. The size has already
+ // been computed in CompileUnit::computeOffsets(). Subtract 4 to that size to
+ // account for the length field.
+ Asm->emitInt32(Unit.getUnitSize() - 4);
+ Asm->emitInt16(Unit.getVersion());
+
+ if (Unit.getVersion() >= 5) {
+ Asm->emitInt8(dwarf::DW_UT_compile);
+ Asm->emitInt8(Unit.getFormParams().AddrSize);
+ // Proper offset to the abbreviations table will be set later.
+ Asm->emitInt32(0);
+ DebugInfoSectionSize += 12;
+ } else {
+ // Proper offset to the abbreviations table will be set later.
+ Asm->emitInt32(0);
+ Asm->emitInt8(Unit.getFormParams().AddrSize);
+ DebugInfoSectionSize += 11;
+ }
+}
+
+void DwarfEmitterImpl::emitDIE(DIE &Die) {
+ MS->switchSection(MOFI->getDwarfInfoSection());
+ Asm->emitDwarfDIE(Die);
+ DebugInfoSectionSize += Die.getSize();
+}
+
+void DwarfEmitterImpl::emitDebugNames(DWARF5AccelTable &Table,
+ DebugNamesUnitsOffsets &CUOffsets,
+ CompUnitIDToIdx &CUidToIdx) {
+ if (CUOffsets.empty())
+ return;
+
+ Asm->OutStreamer->switchSection(MOFI->getDwarfDebugNamesSection());
+ dwarf::Form Form =
+ DIEInteger::BestForm(/*IsSigned*/ false, (uint64_t)CUidToIdx.size() - 1);
+ // FIXME: add support for type units + .debug_names. For now the behavior is
+ // unsuported.
+ emitDWARF5AccelTable(
+ Asm.get(), Table, CUOffsets,
+ [&](const DWARF5AccelTableData &Entry)
+ -> std::optional<DWARF5AccelTable::UnitIndexAndEncoding> {
+ if (CUidToIdx.size() > 1)
+ return {{CUidToIdx[Entry.getUnitID()],
+ {dwarf::DW_IDX_compile_unit, Form}}};
+ return std::nullopt;
+ });
+}
+
+void DwarfEmitterImpl::emitAppleNamespaces(
+ AccelTable<AppleAccelTableStaticOffsetData> &Table) {
+ Asm->OutStreamer->switchSection(MOFI->getDwarfAccelNamespaceSection());
+ auto *SectionBegin = Asm->createTempSymbol("namespac_begin");
+ Asm->OutStreamer->emitLabel(SectionBegin);
+ emitAppleAccelTable(Asm.get(), Table, "namespac", SectionBegin);
+}
+
+void DwarfEmitterImpl::emitAppleNames(
+ AccelTable<AppleAccelTableStaticOffsetData> &Table) {
+ Asm->OutStreamer->switchSection(MOFI->getDwarfAccelNamesSection());
+ auto *SectionBegin = Asm->createTempSymbol("names_begin");
+ Asm->OutStreamer->emitLabel(SectionBegin);
+ emitAppleAccelTable(Asm.get(), Table, "names", SectionBegin);
+}
+
+void DwarfEmitterImpl::emitAppleObjc(
+ AccelTable<AppleAccelTableStaticOffsetData> &Table) {
+ Asm->OutStreamer->switchSection(MOFI->getDwarfAccelObjCSection());
+ auto *SectionBegin = Asm->createTempSymbol("objc_begin");
+ Asm->OutStreamer->emitLabel(SectionBegin);
+ emitAppleAccelTable(Asm.get(), Table, "objc", SectionBegin);
+}
+
+void DwarfEmitterImpl::emitAppleTypes(
+ AccelTable<AppleAccelTableStaticTypeData> &Table) {
+ Asm->OutStreamer->switchSection(MOFI->getDwarfAccelTypesSection());
+ auto *SectionBegin = Asm->createTempSymbol("types_begin");
+ Asm->OutStreamer->emitLabel(SectionBegin);
+ emitAppleAccelTable(Asm.get(), Table, "types", SectionBegin);
+}