xref: /freebsd/contrib/llvm-project/llvm/lib/DWARFLinker/Parallel/DWARFEmitterImpl.cpp (revision 3ceba58a7509418b47b8fca2d2b6bbf088714e26)
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   MCOptions.AsmVerbose = true;
45   MCOptions.MCUseDwarfDirectory = MCTargetOptions::EnableDwarfDirectory;
46   MAI.reset(TheTarget->createMCAsmInfo(*MRI, TripleName, MCOptions));
47   if (!MAI)
48     return createStringError(std::errc::invalid_argument,
49                              "no asm info for target %s", TripleName.c_str());
50 
51   MSTI.reset(TheTarget->createMCSubtargetInfo(TripleName, "", ""));
52   if (!MSTI)
53     return createStringError(std::errc::invalid_argument,
54                              "no subtarget info for target %s",
55                              TripleName.c_str());
56 
57   MC.reset(new MCContext(TheTriple, MAI.get(), MRI.get(), MSTI.get(), nullptr,
58                          nullptr, true, Swift5ReflectionSegmentName));
59   MOFI.reset(TheTarget->createMCObjectFileInfo(*MC, /*PIC=*/false, false));
60   MC->setObjectFileInfo(MOFI.get());
61 
62   MAB = TheTarget->createMCAsmBackend(*MSTI, *MRI, MCOptions);
63   if (!MAB)
64     return createStringError(std::errc::invalid_argument,
65                              "no asm backend for target %s",
66                              TripleName.c_str());
67 
68   MII.reset(TheTarget->createMCInstrInfo());
69   if (!MII)
70     return createStringError(std::errc::invalid_argument,
71                              "no instr info info for target %s",
72                              TripleName.c_str());
73 
74   MCE = TheTarget->createMCCodeEmitter(*MII, *MC);
75   if (!MCE)
76     return createStringError(std::errc::invalid_argument,
77                              "no code emitter for target %s",
78                              TripleName.c_str());
79 
80   switch (OutFileType) {
81   case DWARFLinker::OutputFileType::Assembly: {
82     MIP = TheTarget->createMCInstPrinter(TheTriple, MAI->getAssemblerDialect(),
83                                          *MAI, *MII, *MRI);
84     MS = TheTarget->createAsmStreamer(
85         *MC, std::make_unique<formatted_raw_ostream>(OutFile), MIP,
86         std::unique_ptr<MCCodeEmitter>(MCE),
87         std::unique_ptr<MCAsmBackend>(MAB));
88     break;
89   }
90   case DWARFLinker::OutputFileType::Object: {
91     MS = TheTarget->createMCObjectStreamer(
92         TheTriple, *MC, std::unique_ptr<MCAsmBackend>(MAB),
93         MAB->createObjectWriter(OutFile), std::unique_ptr<MCCodeEmitter>(MCE),
94         *MSTI);
95     break;
96   }
97   }
98 
99   if (!MS)
100     return createStringError(std::errc::invalid_argument,
101                              "no object streamer for target %s",
102                              TripleName.c_str());
103 
104   // Finally create the AsmPrinter we'll use to emit the DIEs.
105   TM.reset(TheTarget->createTargetMachine(TripleName, "", "", TargetOptions(),
106                                           std::nullopt));
107   if (!TM)
108     return createStringError(std::errc::invalid_argument,
109                              "no target machine for target %s",
110                              TripleName.c_str());
111 
112   Asm.reset(TheTarget->createAsmPrinter(*TM, std::unique_ptr<MCStreamer>(MS)));
113   if (!Asm)
114     return createStringError(std::errc::invalid_argument,
115                              "no asm printer for target %s",
116                              TripleName.c_str());
117   Asm->setDwarfUsesRelocationsAcrossSections(false);
118 
119   DebugInfoSectionSize = 0;
120 
121   return Error::success();
122 }
123 
124 void DwarfEmitterImpl::emitAbbrevs(
125     const SmallVector<std::unique_ptr<DIEAbbrev>> &Abbrevs,
126     unsigned DwarfVersion) {
127   MS->switchSection(MOFI->getDwarfAbbrevSection());
128   MC->setDwarfVersion(DwarfVersion);
129   Asm->emitDwarfAbbrevs(Abbrevs);
130 }
131 
132 void DwarfEmitterImpl::emitCompileUnitHeader(DwarfUnit &Unit) {
133   MS->switchSection(MOFI->getDwarfInfoSection());
134   MC->setDwarfVersion(Unit.getVersion());
135 
136   // Emit size of content not including length itself. The size has already
137   // been computed in CompileUnit::computeOffsets(). Subtract 4 to that size to
138   // account for the length field.
139   Asm->emitInt32(Unit.getUnitSize() - 4);
140   Asm->emitInt16(Unit.getVersion());
141 
142   if (Unit.getVersion() >= 5) {
143     Asm->emitInt8(dwarf::DW_UT_compile);
144     Asm->emitInt8(Unit.getFormParams().AddrSize);
145     // Proper offset to the abbreviations table will be set later.
146     Asm->emitInt32(0);
147     DebugInfoSectionSize += 12;
148   } else {
149     // Proper offset to the abbreviations table will be set later.
150     Asm->emitInt32(0);
151     Asm->emitInt8(Unit.getFormParams().AddrSize);
152     DebugInfoSectionSize += 11;
153   }
154 }
155 
156 void DwarfEmitterImpl::emitDIE(DIE &Die) {
157   MS->switchSection(MOFI->getDwarfInfoSection());
158   Asm->emitDwarfDIE(Die);
159   DebugInfoSectionSize += Die.getSize();
160 }
161 
162 void DwarfEmitterImpl::emitDebugNames(DWARF5AccelTable &Table,
163                                       DebugNamesUnitsOffsets &CUOffsets,
164                                       CompUnitIDToIdx &CUidToIdx) {
165   if (CUOffsets.empty())
166     return;
167 
168   Asm->OutStreamer->switchSection(MOFI->getDwarfDebugNamesSection());
169   dwarf::Form Form =
170       DIEInteger::BestForm(/*IsSigned*/ false, (uint64_t)CUidToIdx.size() - 1);
171   // FIXME: add support for type units + .debug_names. For now the behavior is
172   // unsuported.
173   emitDWARF5AccelTable(
174       Asm.get(), Table, CUOffsets,
175       [&](const DWARF5AccelTableData &Entry)
176           -> std::optional<DWARF5AccelTable::UnitIndexAndEncoding> {
177         if (CUidToIdx.size() > 1)
178           return {{CUidToIdx[Entry.getUnitID()],
179                    {dwarf::DW_IDX_compile_unit, Form}}};
180         return std::nullopt;
181       });
182 }
183 
184 void DwarfEmitterImpl::emitAppleNamespaces(
185     AccelTable<AppleAccelTableStaticOffsetData> &Table) {
186   Asm->OutStreamer->switchSection(MOFI->getDwarfAccelNamespaceSection());
187   auto *SectionBegin = Asm->createTempSymbol("namespac_begin");
188   Asm->OutStreamer->emitLabel(SectionBegin);
189   emitAppleAccelTable(Asm.get(), Table, "namespac", SectionBegin);
190 }
191 
192 void DwarfEmitterImpl::emitAppleNames(
193     AccelTable<AppleAccelTableStaticOffsetData> &Table) {
194   Asm->OutStreamer->switchSection(MOFI->getDwarfAccelNamesSection());
195   auto *SectionBegin = Asm->createTempSymbol("names_begin");
196   Asm->OutStreamer->emitLabel(SectionBegin);
197   emitAppleAccelTable(Asm.get(), Table, "names", SectionBegin);
198 }
199 
200 void DwarfEmitterImpl::emitAppleObjc(
201     AccelTable<AppleAccelTableStaticOffsetData> &Table) {
202   Asm->OutStreamer->switchSection(MOFI->getDwarfAccelObjCSection());
203   auto *SectionBegin = Asm->createTempSymbol("objc_begin");
204   Asm->OutStreamer->emitLabel(SectionBegin);
205   emitAppleAccelTable(Asm.get(), Table, "objc", SectionBegin);
206 }
207 
208 void DwarfEmitterImpl::emitAppleTypes(
209     AccelTable<AppleAccelTableStaticTypeData> &Table) {
210   Asm->OutStreamer->switchSection(MOFI->getDwarfAccelTypesSection());
211   auto *SectionBegin = Asm->createTempSymbol("types_begin");
212   Asm->OutStreamer->emitLabel(SectionBegin);
213   emitAppleAccelTable(Asm.get(), Table, "types", SectionBegin);
214 }
215