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