diff options
Diffstat (limited to 'contrib/llvm-project/llvm/lib/DWARFLinker/Parallel/DWARFEmitterImpl.cpp')
-rw-r--r-- | contrib/llvm-project/llvm/lib/DWARFLinker/Parallel/DWARFEmitterImpl.cpp | 279 |
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); +} |