xref: /freebsd/contrib/llvm-project/llvm/lib/DWARFLinker/Parallel/DWARFEmitterImpl.cpp (revision 1342eb5a832fa10e689a29faab3acb6054e4778c)
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-exception
6 //
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 
21 using namespace llvm;
22 using namespace dwarf_linker;
23 using namespace dwarf_linker::parallel;
24 
25 Error 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(TripleName));
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, TripleName, 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(TripleName, "", ""));
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 
125 void 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 
133 void 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 already
138   // been computed in CompileUnit::computeOffsets(). Subtract 4 to that size to
139   // 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 
157 void DwarfEmitterImpl::emitDIE(DIE &Die) {
158   MS->switchSection(MOFI->getDwarfInfoSection());
159   Asm->emitDwarfDIE(Die);
160   DebugInfoSectionSize += Die.getSize();
161 }
162 
163 void 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 is
173   // 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 
185 void 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 
193 void 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 
201 void 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 
209 void 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