xref: /freebsd-src/contrib/llvm-project/llvm/lib/DWARFLinker/Parallel/DWARFEmitterImpl.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
11db9f3b2SDimitry Andric //===- DWARFEmitterImpl.cpp -----------------------------------------------===//
21db9f3b2SDimitry Andric //
31db9f3b2SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
41db9f3b2SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
51db9f3b2SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
61db9f3b2SDimitry Andric //
71db9f3b2SDimitry Andric //===----------------------------------------------------------------------===//
81db9f3b2SDimitry Andric 
91db9f3b2SDimitry Andric #include "DWARFEmitterImpl.h"
101db9f3b2SDimitry Andric #include "DWARFLinkerCompileUnit.h"
111db9f3b2SDimitry Andric #include "llvm/MC/MCAsmBackend.h"
121db9f3b2SDimitry Andric #include "llvm/MC/MCCodeEmitter.h"
131db9f3b2SDimitry Andric #include "llvm/MC/MCObjectWriter.h"
141db9f3b2SDimitry Andric #include "llvm/MC/MCSubtargetInfo.h"
151db9f3b2SDimitry Andric #include "llvm/MC/MCTargetOptions.h"
161db9f3b2SDimitry Andric #include "llvm/MC/MCTargetOptionsCommandFlags.h"
171db9f3b2SDimitry Andric #include "llvm/MC/TargetRegistry.h"
181db9f3b2SDimitry Andric #include "llvm/Support/FormattedStream.h"
191db9f3b2SDimitry Andric 
201db9f3b2SDimitry Andric using namespace llvm;
211db9f3b2SDimitry Andric using namespace dwarf_linker;
221db9f3b2SDimitry Andric using namespace dwarf_linker::parallel;
231db9f3b2SDimitry Andric 
241db9f3b2SDimitry Andric Error DwarfEmitterImpl::init(Triple TheTriple,
251db9f3b2SDimitry Andric                              StringRef Swift5ReflectionSegmentName) {
261db9f3b2SDimitry Andric   std::string ErrorStr;
271db9f3b2SDimitry Andric   std::string TripleName;
281db9f3b2SDimitry Andric 
291db9f3b2SDimitry Andric   // Get the target.
301db9f3b2SDimitry Andric   const Target *TheTarget =
311db9f3b2SDimitry Andric       TargetRegistry::lookupTarget(TripleName, TheTriple, ErrorStr);
321db9f3b2SDimitry Andric   if (!TheTarget)
331db9f3b2SDimitry Andric     return createStringError(std::errc::invalid_argument, ErrorStr.c_str());
341db9f3b2SDimitry Andric   TripleName = TheTriple.getTriple();
351db9f3b2SDimitry Andric 
361db9f3b2SDimitry Andric   // Create all the MC Objects.
371db9f3b2SDimitry Andric   MRI.reset(TheTarget->createMCRegInfo(TripleName));
381db9f3b2SDimitry Andric   if (!MRI)
391db9f3b2SDimitry Andric     return createStringError(std::errc::invalid_argument,
401db9f3b2SDimitry Andric                              "no register info for target %s",
411db9f3b2SDimitry Andric                              TripleName.c_str());
421db9f3b2SDimitry Andric 
431db9f3b2SDimitry Andric   MCTargetOptions MCOptions = mc::InitMCTargetOptionsFromFlags();
44*0fca6ea1SDimitry Andric   MCOptions.AsmVerbose = true;
45*0fca6ea1SDimitry Andric   MCOptions.MCUseDwarfDirectory = MCTargetOptions::EnableDwarfDirectory;
461db9f3b2SDimitry Andric   MAI.reset(TheTarget->createMCAsmInfo(*MRI, TripleName, MCOptions));
471db9f3b2SDimitry Andric   if (!MAI)
481db9f3b2SDimitry Andric     return createStringError(std::errc::invalid_argument,
491db9f3b2SDimitry Andric                              "no asm info for target %s", TripleName.c_str());
501db9f3b2SDimitry Andric 
511db9f3b2SDimitry Andric   MSTI.reset(TheTarget->createMCSubtargetInfo(TripleName, "", ""));
521db9f3b2SDimitry Andric   if (!MSTI)
531db9f3b2SDimitry Andric     return createStringError(std::errc::invalid_argument,
541db9f3b2SDimitry Andric                              "no subtarget info for target %s",
551db9f3b2SDimitry Andric                              TripleName.c_str());
561db9f3b2SDimitry Andric 
571db9f3b2SDimitry Andric   MC.reset(new MCContext(TheTriple, MAI.get(), MRI.get(), MSTI.get(), nullptr,
581db9f3b2SDimitry Andric                          nullptr, true, Swift5ReflectionSegmentName));
591db9f3b2SDimitry Andric   MOFI.reset(TheTarget->createMCObjectFileInfo(*MC, /*PIC=*/false, false));
601db9f3b2SDimitry Andric   MC->setObjectFileInfo(MOFI.get());
611db9f3b2SDimitry Andric 
621db9f3b2SDimitry Andric   MAB = TheTarget->createMCAsmBackend(*MSTI, *MRI, MCOptions);
631db9f3b2SDimitry Andric   if (!MAB)
641db9f3b2SDimitry Andric     return createStringError(std::errc::invalid_argument,
651db9f3b2SDimitry Andric                              "no asm backend for target %s",
661db9f3b2SDimitry Andric                              TripleName.c_str());
671db9f3b2SDimitry Andric 
681db9f3b2SDimitry Andric   MII.reset(TheTarget->createMCInstrInfo());
691db9f3b2SDimitry Andric   if (!MII)
701db9f3b2SDimitry Andric     return createStringError(std::errc::invalid_argument,
711db9f3b2SDimitry Andric                              "no instr info info for target %s",
721db9f3b2SDimitry Andric                              TripleName.c_str());
731db9f3b2SDimitry Andric 
741db9f3b2SDimitry Andric   MCE = TheTarget->createMCCodeEmitter(*MII, *MC);
751db9f3b2SDimitry Andric   if (!MCE)
761db9f3b2SDimitry Andric     return createStringError(std::errc::invalid_argument,
771db9f3b2SDimitry Andric                              "no code emitter for target %s",
781db9f3b2SDimitry Andric                              TripleName.c_str());
791db9f3b2SDimitry Andric 
801db9f3b2SDimitry Andric   switch (OutFileType) {
811db9f3b2SDimitry Andric   case DWARFLinker::OutputFileType::Assembly: {
821db9f3b2SDimitry Andric     MIP = TheTarget->createMCInstPrinter(TheTriple, MAI->getAssemblerDialect(),
831db9f3b2SDimitry Andric                                          *MAI, *MII, *MRI);
841db9f3b2SDimitry Andric     MS = TheTarget->createAsmStreamer(
85*0fca6ea1SDimitry Andric         *MC, std::make_unique<formatted_raw_ostream>(OutFile), MIP,
86*0fca6ea1SDimitry Andric         std::unique_ptr<MCCodeEmitter>(MCE),
87*0fca6ea1SDimitry Andric         std::unique_ptr<MCAsmBackend>(MAB));
881db9f3b2SDimitry Andric     break;
891db9f3b2SDimitry Andric   }
901db9f3b2SDimitry Andric   case DWARFLinker::OutputFileType::Object: {
911db9f3b2SDimitry Andric     MS = TheTarget->createMCObjectStreamer(
921db9f3b2SDimitry Andric         TheTriple, *MC, std::unique_ptr<MCAsmBackend>(MAB),
931db9f3b2SDimitry Andric         MAB->createObjectWriter(OutFile), std::unique_ptr<MCCodeEmitter>(MCE),
94*0fca6ea1SDimitry Andric         *MSTI);
951db9f3b2SDimitry Andric     break;
961db9f3b2SDimitry Andric   }
971db9f3b2SDimitry Andric   }
981db9f3b2SDimitry Andric 
991db9f3b2SDimitry Andric   if (!MS)
1001db9f3b2SDimitry Andric     return createStringError(std::errc::invalid_argument,
1011db9f3b2SDimitry Andric                              "no object streamer for target %s",
1021db9f3b2SDimitry Andric                              TripleName.c_str());
1031db9f3b2SDimitry Andric 
1041db9f3b2SDimitry Andric   // Finally create the AsmPrinter we'll use to emit the DIEs.
1051db9f3b2SDimitry Andric   TM.reset(TheTarget->createTargetMachine(TripleName, "", "", TargetOptions(),
1061db9f3b2SDimitry Andric                                           std::nullopt));
1071db9f3b2SDimitry Andric   if (!TM)
1081db9f3b2SDimitry Andric     return createStringError(std::errc::invalid_argument,
1091db9f3b2SDimitry Andric                              "no target machine for target %s",
1101db9f3b2SDimitry Andric                              TripleName.c_str());
1111db9f3b2SDimitry Andric 
1121db9f3b2SDimitry Andric   Asm.reset(TheTarget->createAsmPrinter(*TM, std::unique_ptr<MCStreamer>(MS)));
1131db9f3b2SDimitry Andric   if (!Asm)
1141db9f3b2SDimitry Andric     return createStringError(std::errc::invalid_argument,
1151db9f3b2SDimitry Andric                              "no asm printer for target %s",
1161db9f3b2SDimitry Andric                              TripleName.c_str());
1171db9f3b2SDimitry Andric   Asm->setDwarfUsesRelocationsAcrossSections(false);
1181db9f3b2SDimitry Andric 
1191db9f3b2SDimitry Andric   DebugInfoSectionSize = 0;
1201db9f3b2SDimitry Andric 
1211db9f3b2SDimitry Andric   return Error::success();
1221db9f3b2SDimitry Andric }
1231db9f3b2SDimitry Andric 
1241db9f3b2SDimitry Andric void DwarfEmitterImpl::emitAbbrevs(
1251db9f3b2SDimitry Andric     const SmallVector<std::unique_ptr<DIEAbbrev>> &Abbrevs,
1261db9f3b2SDimitry Andric     unsigned DwarfVersion) {
1271db9f3b2SDimitry Andric   MS->switchSection(MOFI->getDwarfAbbrevSection());
1281db9f3b2SDimitry Andric   MC->setDwarfVersion(DwarfVersion);
1291db9f3b2SDimitry Andric   Asm->emitDwarfAbbrevs(Abbrevs);
1301db9f3b2SDimitry Andric }
1311db9f3b2SDimitry Andric 
1321db9f3b2SDimitry Andric void DwarfEmitterImpl::emitCompileUnitHeader(DwarfUnit &Unit) {
1331db9f3b2SDimitry Andric   MS->switchSection(MOFI->getDwarfInfoSection());
1341db9f3b2SDimitry Andric   MC->setDwarfVersion(Unit.getVersion());
1351db9f3b2SDimitry Andric 
1361db9f3b2SDimitry Andric   // Emit size of content not including length itself. The size has already
1371db9f3b2SDimitry Andric   // been computed in CompileUnit::computeOffsets(). Subtract 4 to that size to
1381db9f3b2SDimitry Andric   // account for the length field.
1391db9f3b2SDimitry Andric   Asm->emitInt32(Unit.getUnitSize() - 4);
1401db9f3b2SDimitry Andric   Asm->emitInt16(Unit.getVersion());
1411db9f3b2SDimitry Andric 
1421db9f3b2SDimitry Andric   if (Unit.getVersion() >= 5) {
1431db9f3b2SDimitry Andric     Asm->emitInt8(dwarf::DW_UT_compile);
1441db9f3b2SDimitry Andric     Asm->emitInt8(Unit.getFormParams().AddrSize);
1451db9f3b2SDimitry Andric     // Proper offset to the abbreviations table will be set later.
1461db9f3b2SDimitry Andric     Asm->emitInt32(0);
1471db9f3b2SDimitry Andric     DebugInfoSectionSize += 12;
1481db9f3b2SDimitry Andric   } else {
1491db9f3b2SDimitry Andric     // Proper offset to the abbreviations table will be set later.
1501db9f3b2SDimitry Andric     Asm->emitInt32(0);
1511db9f3b2SDimitry Andric     Asm->emitInt8(Unit.getFormParams().AddrSize);
1521db9f3b2SDimitry Andric     DebugInfoSectionSize += 11;
1531db9f3b2SDimitry Andric   }
1541db9f3b2SDimitry Andric }
1551db9f3b2SDimitry Andric 
1561db9f3b2SDimitry Andric void DwarfEmitterImpl::emitDIE(DIE &Die) {
1571db9f3b2SDimitry Andric   MS->switchSection(MOFI->getDwarfInfoSection());
1581db9f3b2SDimitry Andric   Asm->emitDwarfDIE(Die);
1591db9f3b2SDimitry Andric   DebugInfoSectionSize += Die.getSize();
1601db9f3b2SDimitry Andric }
1611db9f3b2SDimitry Andric 
1621db9f3b2SDimitry Andric void DwarfEmitterImpl::emitDebugNames(DWARF5AccelTable &Table,
1631db9f3b2SDimitry Andric                                       DebugNamesUnitsOffsets &CUOffsets,
1641db9f3b2SDimitry Andric                                       CompUnitIDToIdx &CUidToIdx) {
1651db9f3b2SDimitry Andric   if (CUOffsets.empty())
1661db9f3b2SDimitry Andric     return;
1671db9f3b2SDimitry Andric 
1681db9f3b2SDimitry Andric   Asm->OutStreamer->switchSection(MOFI->getDwarfDebugNamesSection());
1691db9f3b2SDimitry Andric   dwarf::Form Form =
1701db9f3b2SDimitry Andric       DIEInteger::BestForm(/*IsSigned*/ false, (uint64_t)CUidToIdx.size() - 1);
1711db9f3b2SDimitry Andric   // FIXME: add support for type units + .debug_names. For now the behavior is
1721db9f3b2SDimitry Andric   // unsuported.
1731db9f3b2SDimitry Andric   emitDWARF5AccelTable(
1741db9f3b2SDimitry Andric       Asm.get(), Table, CUOffsets,
1751db9f3b2SDimitry Andric       [&](const DWARF5AccelTableData &Entry)
1761db9f3b2SDimitry Andric           -> std::optional<DWARF5AccelTable::UnitIndexAndEncoding> {
1771db9f3b2SDimitry Andric         if (CUidToIdx.size() > 1)
1781db9f3b2SDimitry Andric           return {{CUidToIdx[Entry.getUnitID()],
1791db9f3b2SDimitry Andric                    {dwarf::DW_IDX_compile_unit, Form}}};
1801db9f3b2SDimitry Andric         return std::nullopt;
1811db9f3b2SDimitry Andric       });
1821db9f3b2SDimitry Andric }
1831db9f3b2SDimitry Andric 
1841db9f3b2SDimitry Andric void DwarfEmitterImpl::emitAppleNamespaces(
1851db9f3b2SDimitry Andric     AccelTable<AppleAccelTableStaticOffsetData> &Table) {
1861db9f3b2SDimitry Andric   Asm->OutStreamer->switchSection(MOFI->getDwarfAccelNamespaceSection());
1871db9f3b2SDimitry Andric   auto *SectionBegin = Asm->createTempSymbol("namespac_begin");
1881db9f3b2SDimitry Andric   Asm->OutStreamer->emitLabel(SectionBegin);
1891db9f3b2SDimitry Andric   emitAppleAccelTable(Asm.get(), Table, "namespac", SectionBegin);
1901db9f3b2SDimitry Andric }
1911db9f3b2SDimitry Andric 
1921db9f3b2SDimitry Andric void DwarfEmitterImpl::emitAppleNames(
1931db9f3b2SDimitry Andric     AccelTable<AppleAccelTableStaticOffsetData> &Table) {
1941db9f3b2SDimitry Andric   Asm->OutStreamer->switchSection(MOFI->getDwarfAccelNamesSection());
1951db9f3b2SDimitry Andric   auto *SectionBegin = Asm->createTempSymbol("names_begin");
1961db9f3b2SDimitry Andric   Asm->OutStreamer->emitLabel(SectionBegin);
1971db9f3b2SDimitry Andric   emitAppleAccelTable(Asm.get(), Table, "names", SectionBegin);
1981db9f3b2SDimitry Andric }
1991db9f3b2SDimitry Andric 
2001db9f3b2SDimitry Andric void DwarfEmitterImpl::emitAppleObjc(
2011db9f3b2SDimitry Andric     AccelTable<AppleAccelTableStaticOffsetData> &Table) {
2021db9f3b2SDimitry Andric   Asm->OutStreamer->switchSection(MOFI->getDwarfAccelObjCSection());
2031db9f3b2SDimitry Andric   auto *SectionBegin = Asm->createTempSymbol("objc_begin");
2041db9f3b2SDimitry Andric   Asm->OutStreamer->emitLabel(SectionBegin);
2051db9f3b2SDimitry Andric   emitAppleAccelTable(Asm.get(), Table, "objc", SectionBegin);
2061db9f3b2SDimitry Andric }
2071db9f3b2SDimitry Andric 
2081db9f3b2SDimitry Andric void DwarfEmitterImpl::emitAppleTypes(
2091db9f3b2SDimitry Andric     AccelTable<AppleAccelTableStaticTypeData> &Table) {
2101db9f3b2SDimitry Andric   Asm->OutStreamer->switchSection(MOFI->getDwarfAccelTypesSection());
2111db9f3b2SDimitry Andric   auto *SectionBegin = Asm->createTempSymbol("types_begin");
2121db9f3b2SDimitry Andric   Asm->OutStreamer->emitLabel(SectionBegin);
2131db9f3b2SDimitry Andric   emitAppleAccelTable(Asm.get(), Table, "types", SectionBegin);
2141db9f3b2SDimitry Andric }
215