216 lines · cpp
1//===- DWARFEmitterImpl.cpp -----------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "DWARFEmitterImpl.h"10#include "DWARFLinkerCompileUnit.h"11#include "llvm/MC/MCAsmBackend.h"12#include "llvm/MC/MCCodeEmitter.h"13#include "llvm/MC/MCInstPrinter.h"14#include "llvm/MC/MCObjectWriter.h"15#include "llvm/MC/MCSubtargetInfo.h"16#include "llvm/MC/MCTargetOptions.h"17#include "llvm/MC/MCTargetOptionsCommandFlags.h"18#include "llvm/MC/TargetRegistry.h"19#include "llvm/Support/FormattedStream.h"20 21using namespace llvm;22using namespace dwarf_linker;23using namespace dwarf_linker::parallel;24 25Error DwarfEmitterImpl::init(Triple TheTriple,26 StringRef Swift5ReflectionSegmentName) {27 std::string ErrorStr;28 std::string TripleName;29 30 // Get the target.31 const Target *TheTarget =32 TargetRegistry::lookupTarget(TripleName, TheTriple, ErrorStr);33 if (!TheTarget)34 return createStringError(std::errc::invalid_argument, ErrorStr.c_str());35 TripleName = TheTriple.getTriple();36 37 // Create all the MC Objects.38 MRI.reset(TheTarget->createMCRegInfo(TheTriple));39 if (!MRI)40 return createStringError(std::errc::invalid_argument,41 "no register info for target %s",42 TripleName.c_str());43 44 MCTargetOptions MCOptions = mc::InitMCTargetOptionsFromFlags();45 MCOptions.AsmVerbose = true;46 MCOptions.MCUseDwarfDirectory = MCTargetOptions::EnableDwarfDirectory;47 MAI.reset(TheTarget->createMCAsmInfo(*MRI, TheTriple, MCOptions));48 if (!MAI)49 return createStringError(std::errc::invalid_argument,50 "no asm info for target %s", TripleName.c_str());51 52 MSTI.reset(TheTarget->createMCSubtargetInfo(TheTriple, "", ""));53 if (!MSTI)54 return createStringError(std::errc::invalid_argument,55 "no subtarget info for target %s",56 TripleName.c_str());57 58 MC.reset(new MCContext(TheTriple, MAI.get(), MRI.get(), MSTI.get(), nullptr,59 nullptr, true, Swift5ReflectionSegmentName));60 MOFI.reset(TheTarget->createMCObjectFileInfo(*MC, /*PIC=*/false, false));61 MC->setObjectFileInfo(MOFI.get());62 63 MAB = TheTarget->createMCAsmBackend(*MSTI, *MRI, MCOptions);64 if (!MAB)65 return createStringError(std::errc::invalid_argument,66 "no asm backend for target %s",67 TripleName.c_str());68 69 MII.reset(TheTarget->createMCInstrInfo());70 if (!MII)71 return createStringError(std::errc::invalid_argument,72 "no instr info info for target %s",73 TripleName.c_str());74 75 MCE = TheTarget->createMCCodeEmitter(*MII, *MC);76 if (!MCE)77 return createStringError(std::errc::invalid_argument,78 "no code emitter for target %s",79 TripleName.c_str());80 81 switch (OutFileType) {82 case DWARFLinker::OutputFileType::Assembly: {83 std::unique_ptr<MCInstPrinter> MIP(TheTarget->createMCInstPrinter(84 TheTriple, MAI->getAssemblerDialect(), *MAI, *MII, *MRI));85 MS = TheTarget->createAsmStreamer(86 *MC, std::make_unique<formatted_raw_ostream>(OutFile), std::move(MIP),87 std::unique_ptr<MCCodeEmitter>(MCE),88 std::unique_ptr<MCAsmBackend>(MAB));89 break;90 }91 case DWARFLinker::OutputFileType::Object: {92 MS = TheTarget->createMCObjectStreamer(93 TheTriple, *MC, std::unique_ptr<MCAsmBackend>(MAB),94 MAB->createObjectWriter(OutFile), std::unique_ptr<MCCodeEmitter>(MCE),95 *MSTI);96 break;97 }98 }99 100 if (!MS)101 return createStringError(std::errc::invalid_argument,102 "no object streamer for target %s",103 TripleName.c_str());104 105 // Finally create the AsmPrinter we'll use to emit the DIEs.106 TM.reset(TheTarget->createTargetMachine(TheTriple, "", "", TargetOptions(),107 std::nullopt));108 if (!TM)109 return createStringError(std::errc::invalid_argument,110 "no target machine for target %s",111 TripleName.c_str());112 113 Asm.reset(TheTarget->createAsmPrinter(*TM, std::unique_ptr<MCStreamer>(MS)));114 if (!Asm)115 return createStringError(std::errc::invalid_argument,116 "no asm printer for target %s",117 TripleName.c_str());118 Asm->setDwarfUsesRelocationsAcrossSections(false);119 120 DebugInfoSectionSize = 0;121 122 return Error::success();123}124 125void DwarfEmitterImpl::emitAbbrevs(126 const SmallVector<std::unique_ptr<DIEAbbrev>> &Abbrevs,127 unsigned DwarfVersion) {128 MS->switchSection(MOFI->getDwarfAbbrevSection());129 MC->setDwarfVersion(DwarfVersion);130 Asm->emitDwarfAbbrevs(Abbrevs);131}132 133void DwarfEmitterImpl::emitCompileUnitHeader(DwarfUnit &Unit) {134 MS->switchSection(MOFI->getDwarfInfoSection());135 MC->setDwarfVersion(Unit.getVersion());136 137 // Emit size of content not including length itself. The size has already138 // been computed in CompileUnit::computeOffsets(). Subtract 4 to that size to139 // account for the length field.140 Asm->emitInt32(Unit.getUnitSize() - 4);141 Asm->emitInt16(Unit.getVersion());142 143 if (Unit.getVersion() >= 5) {144 Asm->emitInt8(dwarf::DW_UT_compile);145 Asm->emitInt8(Unit.getFormParams().AddrSize);146 // Proper offset to the abbreviations table will be set later.147 Asm->emitInt32(0);148 DebugInfoSectionSize += 12;149 } else {150 // Proper offset to the abbreviations table will be set later.151 Asm->emitInt32(0);152 Asm->emitInt8(Unit.getFormParams().AddrSize);153 DebugInfoSectionSize += 11;154 }155}156 157void DwarfEmitterImpl::emitDIE(DIE &Die) {158 MS->switchSection(MOFI->getDwarfInfoSection());159 Asm->emitDwarfDIE(Die);160 DebugInfoSectionSize += Die.getSize();161}162 163void DwarfEmitterImpl::emitDebugNames(DWARF5AccelTable &Table,164 DebugNamesUnitsOffsets &CUOffsets,165 CompUnitIDToIdx &CUidToIdx) {166 if (CUOffsets.empty())167 return;168 169 Asm->OutStreamer->switchSection(MOFI->getDwarfDebugNamesSection());170 dwarf::Form Form =171 DIEInteger::BestForm(/*IsSigned*/ false, (uint64_t)CUidToIdx.size() - 1);172 // FIXME: add support for type units + .debug_names. For now the behavior is173 // unsuported.174 emitDWARF5AccelTable(175 Asm.get(), Table, CUOffsets,176 [&](const DWARF5AccelTableData &Entry)177 -> std::optional<DWARF5AccelTable::UnitIndexAndEncoding> {178 if (CUidToIdx.size() > 1)179 return {{CUidToIdx[Entry.getUnitID()],180 {dwarf::DW_IDX_compile_unit, Form}}};181 return std::nullopt;182 });183}184 185void DwarfEmitterImpl::emitAppleNamespaces(186 AccelTable<AppleAccelTableStaticOffsetData> &Table) {187 Asm->OutStreamer->switchSection(MOFI->getDwarfAccelNamespaceSection());188 auto *SectionBegin = Asm->createTempSymbol("namespac_begin");189 Asm->OutStreamer->emitLabel(SectionBegin);190 emitAppleAccelTable(Asm.get(), Table, "namespac", SectionBegin);191}192 193void DwarfEmitterImpl::emitAppleNames(194 AccelTable<AppleAccelTableStaticOffsetData> &Table) {195 Asm->OutStreamer->switchSection(MOFI->getDwarfAccelNamesSection());196 auto *SectionBegin = Asm->createTempSymbol("names_begin");197 Asm->OutStreamer->emitLabel(SectionBegin);198 emitAppleAccelTable(Asm.get(), Table, "names", SectionBegin);199}200 201void DwarfEmitterImpl::emitAppleObjc(202 AccelTable<AppleAccelTableStaticOffsetData> &Table) {203 Asm->OutStreamer->switchSection(MOFI->getDwarfAccelObjCSection());204 auto *SectionBegin = Asm->createTempSymbol("objc_begin");205 Asm->OutStreamer->emitLabel(SectionBegin);206 emitAppleAccelTable(Asm.get(), Table, "objc", SectionBegin);207}208 209void DwarfEmitterImpl::emitAppleTypes(210 AccelTable<AppleAccelTableStaticTypeData> &Table) {211 Asm->OutStreamer->switchSection(MOFI->getDwarfAccelTypesSection());212 auto *SectionBegin = Asm->createTempSymbol("types_begin");213 Asm->OutStreamer->emitLabel(SectionBegin);214 emitAppleAccelTable(Asm.get(), Table, "types", SectionBegin);215}216