xref: /freebsd/contrib/llvm-project/llvm/lib/DWARFLinker/Parallel/DWARFEmitterImpl.cpp (revision 1db9f3b21e39176dd5b67cf8ac378633b172463e)
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/MCObjectWriter.h"
14 #include "llvm/MC/MCSubtargetInfo.h"
15 #include "llvm/MC/MCTargetOptions.h"
16 #include "llvm/MC/MCTargetOptionsCommandFlags.h"
17 #include "llvm/MC/TargetRegistry.h"
18 #include "llvm/Support/FormattedStream.h"
19 
20 using namespace llvm;
21 using namespace dwarf_linker;
22 using namespace dwarf_linker::parallel;
23 
24 Error DwarfEmitterImpl::init(Triple TheTriple,
25                              StringRef Swift5ReflectionSegmentName) {
26   std::string ErrorStr;
27   std::string TripleName;
28 
29   // Get the target.
30   const Target *TheTarget =
31       TargetRegistry::lookupTarget(TripleName, TheTriple, ErrorStr);
32   if (!TheTarget)
33     return createStringError(std::errc::invalid_argument, ErrorStr.c_str());
34   TripleName = TheTriple.getTriple();
35 
36   // Create all the MC Objects.
37   MRI.reset(TheTarget->createMCRegInfo(TripleName));
38   if (!MRI)
39     return createStringError(std::errc::invalid_argument,
40                              "no register info for target %s",
41                              TripleName.c_str());
42 
43   MCTargetOptions MCOptions = mc::InitMCTargetOptionsFromFlags();
44   MAI.reset(TheTarget->createMCAsmInfo(*MRI, TripleName, MCOptions));
45   if (!MAI)
46     return createStringError(std::errc::invalid_argument,
47                              "no asm info for target %s", TripleName.c_str());
48 
49   MSTI.reset(TheTarget->createMCSubtargetInfo(TripleName, "", ""));
50   if (!MSTI)
51     return createStringError(std::errc::invalid_argument,
52                              "no subtarget info for target %s",
53                              TripleName.c_str());
54 
55   MC.reset(new MCContext(TheTriple, MAI.get(), MRI.get(), MSTI.get(), nullptr,
56                          nullptr, true, Swift5ReflectionSegmentName));
57   MOFI.reset(TheTarget->createMCObjectFileInfo(*MC, /*PIC=*/false, false));
58   MC->setObjectFileInfo(MOFI.get());
59 
60   MAB = TheTarget->createMCAsmBackend(*MSTI, *MRI, MCOptions);
61   if (!MAB)
62     return createStringError(std::errc::invalid_argument,
63                              "no asm backend for target %s",
64                              TripleName.c_str());
65 
66   MII.reset(TheTarget->createMCInstrInfo());
67   if (!MII)
68     return createStringError(std::errc::invalid_argument,
69                              "no instr info info for target %s",
70                              TripleName.c_str());
71 
72   MCE = TheTarget->createMCCodeEmitter(*MII, *MC);
73   if (!MCE)
74     return createStringError(std::errc::invalid_argument,
75                              "no code emitter for target %s",
76                              TripleName.c_str());
77 
78   switch (OutFileType) {
79   case DWARFLinker::OutputFileType::Assembly: {
80     MIP = TheTarget->createMCInstPrinter(TheTriple, MAI->getAssemblerDialect(),
81                                          *MAI, *MII, *MRI);
82     MS = TheTarget->createAsmStreamer(
83         *MC, std::make_unique<formatted_raw_ostream>(OutFile), true, true, MIP,
84         std::unique_ptr<MCCodeEmitter>(MCE), std::unique_ptr<MCAsmBackend>(MAB),
85         true);
86     break;
87   }
88   case DWARFLinker::OutputFileType::Object: {
89     MS = TheTarget->createMCObjectStreamer(
90         TheTriple, *MC, std::unique_ptr<MCAsmBackend>(MAB),
91         MAB->createObjectWriter(OutFile), std::unique_ptr<MCCodeEmitter>(MCE),
92         *MSTI, MCOptions.MCRelaxAll, MCOptions.MCIncrementalLinkerCompatible,
93         /*DWARFMustBeAtTheEnd*/ false);
94     break;
95   }
96   }
97 
98   if (!MS)
99     return createStringError(std::errc::invalid_argument,
100                              "no object streamer for target %s",
101                              TripleName.c_str());
102 
103   // Finally create the AsmPrinter we'll use to emit the DIEs.
104   TM.reset(TheTarget->createTargetMachine(TripleName, "", "", TargetOptions(),
105                                           std::nullopt));
106   if (!TM)
107     return createStringError(std::errc::invalid_argument,
108                              "no target machine for target %s",
109                              TripleName.c_str());
110 
111   Asm.reset(TheTarget->createAsmPrinter(*TM, std::unique_ptr<MCStreamer>(MS)));
112   if (!Asm)
113     return createStringError(std::errc::invalid_argument,
114                              "no asm printer for target %s",
115                              TripleName.c_str());
116   Asm->setDwarfUsesRelocationsAcrossSections(false);
117 
118   DebugInfoSectionSize = 0;
119 
120   return Error::success();
121 }
122 
123 void DwarfEmitterImpl::emitSwiftAST(StringRef Buffer) {
124   MCSection *SwiftASTSection = MOFI->getDwarfSwiftASTSection();
125   SwiftASTSection->setAlignment(Align(32));
126   MS->switchSection(SwiftASTSection);
127   MS->emitBytes(Buffer);
128 }
129 
130 /// Emit the swift reflection section stored in \p Buffer.
131 void DwarfEmitterImpl::emitSwiftReflectionSection(
132     llvm::binaryformat::Swift5ReflectionSectionKind ReflSectionKind,
133     StringRef Buffer, uint32_t Alignment, uint32_t) {
134   MCSection *ReflectionSection =
135       MOFI->getSwift5ReflectionSection(ReflSectionKind);
136   if (ReflectionSection == nullptr)
137     return;
138   ReflectionSection->setAlignment(Align(Alignment));
139   MS->switchSection(ReflectionSection);
140   MS->emitBytes(Buffer);
141 }
142 
143 void DwarfEmitterImpl::emitSectionContents(StringRef SecData,
144                                            StringRef SecName) {
145   if (SecData.empty())
146     return;
147 
148   if (MCSection *Section = switchSection(SecName)) {
149     MS->switchSection(Section);
150 
151     MS->emitBytes(SecData);
152   }
153 }
154 
155 MCSection *DwarfEmitterImpl::switchSection(StringRef SecName) {
156   return StringSwitch<MCSection *>(SecName)
157       .Case("debug_info", MC->getObjectFileInfo()->getDwarfInfoSection())
158       .Case("debug_abbrev", MC->getObjectFileInfo()->getDwarfAbbrevSection())
159       .Case("debug_line", MC->getObjectFileInfo()->getDwarfLineSection())
160       .Case("debug_loc", MC->getObjectFileInfo()->getDwarfLocSection())
161       .Case("debug_ranges", MC->getObjectFileInfo()->getDwarfRangesSection())
162       .Case("debug_frame", MC->getObjectFileInfo()->getDwarfFrameSection())
163       .Case("debug_aranges", MC->getObjectFileInfo()->getDwarfARangesSection())
164       .Case("debug_rnglists",
165             MC->getObjectFileInfo()->getDwarfRnglistsSection())
166       .Case("debug_loclists",
167             MC->getObjectFileInfo()->getDwarfLoclistsSection())
168       .Case("debug_macro", MC->getObjectFileInfo()->getDwarfMacroSection())
169       .Case("debug_macinfo", MC->getObjectFileInfo()->getDwarfMacinfoSection())
170       .Case("debug_addr", MC->getObjectFileInfo()->getDwarfAddrSection())
171       .Case("debug_str", MC->getObjectFileInfo()->getDwarfStrSection())
172       .Case("debug_line_str", MC->getObjectFileInfo()->getDwarfLineStrSection())
173       .Case("debug_str_offsets",
174             MC->getObjectFileInfo()->getDwarfStrOffSection())
175       .Case("debug_pubnames",
176             MC->getObjectFileInfo()->getDwarfPubNamesSection())
177       .Case("debug_pubtypes",
178             MC->getObjectFileInfo()->getDwarfPubTypesSection())
179       .Case("debug_names", MC->getObjectFileInfo()->getDwarfDebugNamesSection())
180       .Case("apple_names", MC->getObjectFileInfo()->getDwarfAccelNamesSection())
181       .Case("apple_namespac",
182             MC->getObjectFileInfo()->getDwarfAccelNamespaceSection())
183       .Case("apple_objc", MC->getObjectFileInfo()->getDwarfAccelObjCSection())
184       .Case("apple_types", MC->getObjectFileInfo()->getDwarfAccelTypesSection())
185 
186       .Default(nullptr);
187 }
188 
189 void DwarfEmitterImpl::emitAbbrevs(
190     const SmallVector<std::unique_ptr<DIEAbbrev>> &Abbrevs,
191     unsigned DwarfVersion) {
192   MS->switchSection(MOFI->getDwarfAbbrevSection());
193   MC->setDwarfVersion(DwarfVersion);
194   Asm->emitDwarfAbbrevs(Abbrevs);
195 }
196 
197 void DwarfEmitterImpl::emitCompileUnitHeader(DwarfUnit &Unit) {
198   MS->switchSection(MOFI->getDwarfInfoSection());
199   MC->setDwarfVersion(Unit.getVersion());
200 
201   // Emit size of content not including length itself. The size has already
202   // been computed in CompileUnit::computeOffsets(). Subtract 4 to that size to
203   // account for the length field.
204   Asm->emitInt32(Unit.getUnitSize() - 4);
205   Asm->emitInt16(Unit.getVersion());
206 
207   if (Unit.getVersion() >= 5) {
208     Asm->emitInt8(dwarf::DW_UT_compile);
209     Asm->emitInt8(Unit.getFormParams().AddrSize);
210     // Proper offset to the abbreviations table will be set later.
211     Asm->emitInt32(0);
212     DebugInfoSectionSize += 12;
213   } else {
214     // Proper offset to the abbreviations table will be set later.
215     Asm->emitInt32(0);
216     Asm->emitInt8(Unit.getFormParams().AddrSize);
217     DebugInfoSectionSize += 11;
218   }
219 }
220 
221 void DwarfEmitterImpl::emitDIE(DIE &Die) {
222   MS->switchSection(MOFI->getDwarfInfoSection());
223   Asm->emitDwarfDIE(Die);
224   DebugInfoSectionSize += Die.getSize();
225 }
226 
227 void DwarfEmitterImpl::emitDebugNames(DWARF5AccelTable &Table,
228                                       DebugNamesUnitsOffsets &CUOffsets,
229                                       CompUnitIDToIdx &CUidToIdx) {
230   if (CUOffsets.empty())
231     return;
232 
233   Asm->OutStreamer->switchSection(MOFI->getDwarfDebugNamesSection());
234   dwarf::Form Form =
235       DIEInteger::BestForm(/*IsSigned*/ false, (uint64_t)CUidToIdx.size() - 1);
236   // FIXME: add support for type units + .debug_names. For now the behavior is
237   // unsuported.
238   emitDWARF5AccelTable(
239       Asm.get(), Table, CUOffsets,
240       [&](const DWARF5AccelTableData &Entry)
241           -> std::optional<DWARF5AccelTable::UnitIndexAndEncoding> {
242         if (CUidToIdx.size() > 1)
243           return {{CUidToIdx[Entry.getUnitID()],
244                    {dwarf::DW_IDX_compile_unit, Form}}};
245         return std::nullopt;
246       });
247 }
248 
249 void DwarfEmitterImpl::emitAppleNamespaces(
250     AccelTable<AppleAccelTableStaticOffsetData> &Table) {
251   Asm->OutStreamer->switchSection(MOFI->getDwarfAccelNamespaceSection());
252   auto *SectionBegin = Asm->createTempSymbol("namespac_begin");
253   Asm->OutStreamer->emitLabel(SectionBegin);
254   emitAppleAccelTable(Asm.get(), Table, "namespac", SectionBegin);
255 }
256 
257 void DwarfEmitterImpl::emitAppleNames(
258     AccelTable<AppleAccelTableStaticOffsetData> &Table) {
259   Asm->OutStreamer->switchSection(MOFI->getDwarfAccelNamesSection());
260   auto *SectionBegin = Asm->createTempSymbol("names_begin");
261   Asm->OutStreamer->emitLabel(SectionBegin);
262   emitAppleAccelTable(Asm.get(), Table, "names", SectionBegin);
263 }
264 
265 void DwarfEmitterImpl::emitAppleObjc(
266     AccelTable<AppleAccelTableStaticOffsetData> &Table) {
267   Asm->OutStreamer->switchSection(MOFI->getDwarfAccelObjCSection());
268   auto *SectionBegin = Asm->createTempSymbol("objc_begin");
269   Asm->OutStreamer->emitLabel(SectionBegin);
270   emitAppleAccelTable(Asm.get(), Table, "objc", SectionBegin);
271 }
272 
273 void DwarfEmitterImpl::emitAppleTypes(
274     AccelTable<AppleAccelTableStaticTypeData> &Table) {
275   Asm->OutStreamer->switchSection(MOFI->getDwarfAccelTypesSection());
276   auto *SectionBegin = Asm->createTempSymbol("types_begin");
277   Asm->OutStreamer->emitLabel(SectionBegin);
278   emitAppleAccelTable(Asm.get(), Table, "types", SectionBegin);
279 }
280