LLVM 18.0.0git
DWARFEmitterImpl.cpp
Go to the documentation of this file.
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"
19
20namespace llvm {
21namespace dwarflinker_parallel {
22
24 StringRef Swift5ReflectionSegmentName) {
25 std::string ErrorStr;
26 std::string TripleName;
27
28 // Get the target.
29 const Target *TheTarget =
30 TargetRegistry::lookupTarget(TripleName, TheTriple, ErrorStr);
31 if (!TheTarget)
32 return createStringError(std::errc::invalid_argument, ErrorStr.c_str());
33 TripleName = TheTriple.getTriple();
34
35 // Create all the MC Objects.
36 MRI.reset(TheTarget->createMCRegInfo(TripleName));
37 if (!MRI)
38 return createStringError(std::errc::invalid_argument,
39 "no register info for target %s",
40 TripleName.c_str());
41
43 MAI.reset(TheTarget->createMCAsmInfo(*MRI, TripleName, MCOptions));
44 if (!MAI)
45 return createStringError(std::errc::invalid_argument,
46 "no asm info for target %s", TripleName.c_str());
47
48 MSTI.reset(TheTarget->createMCSubtargetInfo(TripleName, "", ""));
49 if (!MSTI)
50 return createStringError(std::errc::invalid_argument,
51 "no subtarget info for target %s",
52 TripleName.c_str());
53
54 MC.reset(new MCContext(TheTriple, MAI.get(), MRI.get(), MSTI.get(), nullptr,
55 nullptr, true, Swift5ReflectionSegmentName));
56 MOFI.reset(TheTarget->createMCObjectFileInfo(*MC, /*PIC=*/false, false));
57 MC->setObjectFileInfo(MOFI.get());
58
59 MAB = TheTarget->createMCAsmBackend(*MSTI, *MRI, MCOptions);
60 if (!MAB)
61 return createStringError(std::errc::invalid_argument,
62 "no asm backend for target %s",
63 TripleName.c_str());
64
65 MII.reset(TheTarget->createMCInstrInfo());
66 if (!MII)
67 return createStringError(std::errc::invalid_argument,
68 "no instr info info for target %s",
69 TripleName.c_str());
70
71 MCE = TheTarget->createMCCodeEmitter(*MII, *MC);
72 if (!MCE)
73 return createStringError(std::errc::invalid_argument,
74 "no code emitter for target %s",
75 TripleName.c_str());
76
77 switch (OutFileType) {
79 MIP = TheTarget->createMCInstPrinter(TheTriple, MAI->getAssemblerDialect(),
80 *MAI, *MII, *MRI);
81 MS = TheTarget->createAsmStreamer(
82 *MC, std::make_unique<formatted_raw_ostream>(OutFile), true, true, MIP,
83 std::unique_ptr<MCCodeEmitter>(MCE), std::unique_ptr<MCAsmBackend>(MAB),
84 true);
85 break;
86 }
88 MS = TheTarget->createMCObjectStreamer(
89 TheTriple, *MC, std::unique_ptr<MCAsmBackend>(MAB),
90 MAB->createObjectWriter(OutFile), std::unique_ptr<MCCodeEmitter>(MCE),
91 *MSTI, MCOptions.MCRelaxAll, MCOptions.MCIncrementalLinkerCompatible,
92 /*DWARFMustBeAtTheEnd*/ false);
93 break;
94 }
95 }
96
97 if (!MS)
98 return createStringError(std::errc::invalid_argument,
99 "no object streamer for target %s",
100 TripleName.c_str());
101
102 // Finally create the AsmPrinter we'll use to emit the DIEs.
103 TM.reset(TheTarget->createTargetMachine(TripleName, "", "", TargetOptions(),
104 std::nullopt));
105 if (!TM)
106 return createStringError(std::errc::invalid_argument,
107 "no target machine for target %s",
108 TripleName.c_str());
109
110 Asm.reset(TheTarget->createAsmPrinter(*TM, std::unique_ptr<MCStreamer>(MS)));
111 if (!Asm)
112 return createStringError(std::errc::invalid_argument,
113 "no asm printer for target %s",
114 TripleName.c_str());
115 Asm->setDwarfUsesRelocationsAcrossSections(false);
116
117 DebugInfoSectionSize = 0;
118
119 return Error::success();
120}
121
123 MCSection *SwiftASTSection = MOFI->getDwarfSwiftASTSection();
124 SwiftASTSection->setAlignment(Align(32));
125 MS->switchSection(SwiftASTSection);
126 MS->emitBytes(Buffer);
127}
128
129/// Emit the swift reflection section stored in \p Buffer.
132 StringRef Buffer, uint32_t Alignment, uint32_t) {
133 MCSection *ReflectionSection =
134 MOFI->getSwift5ReflectionSection(ReflSectionKind);
135 if (ReflectionSection == nullptr)
136 return;
137 ReflectionSection->setAlignment(Align(Alignment));
138 MS->switchSection(ReflectionSection);
139 MS->emitBytes(Buffer);
140}
141
143 StringRef SecName) {
144 if (SecData.empty())
145 return;
146
147 if (MCSection *Section = switchSection(SecName)) {
148 MS->switchSection(Section);
149
150 MS->emitBytes(SecData);
151 }
152}
153
154MCSection *DwarfEmitterImpl::switchSection(StringRef SecName) {
155 return StringSwitch<MCSection *>(SecName)
156 .Case("debug_info", MC->getObjectFileInfo()->getDwarfInfoSection())
157 .Case("debug_abbrev", MC->getObjectFileInfo()->getDwarfAbbrevSection())
158 .Case("debug_line", MC->getObjectFileInfo()->getDwarfLineSection())
159 .Case("debug_loc", MC->getObjectFileInfo()->getDwarfLocSection())
160 .Case("debug_ranges", MC->getObjectFileInfo()->getDwarfRangesSection())
161 .Case("debug_frame", MC->getObjectFileInfo()->getDwarfFrameSection())
162 .Case("debug_aranges", MC->getObjectFileInfo()->getDwarfARangesSection())
163 .Case("debug_rnglists",
164 MC->getObjectFileInfo()->getDwarfRnglistsSection())
165 .Case("debug_loclists",
166 MC->getObjectFileInfo()->getDwarfLoclistsSection())
167 .Case("debug_macro", MC->getObjectFileInfo()->getDwarfMacroSection())
168 .Case("debug_macinfo", MC->getObjectFileInfo()->getDwarfMacinfoSection())
169 .Case("debug_addr", MC->getObjectFileInfo()->getDwarfAddrSection())
170 .Case("debug_str", MC->getObjectFileInfo()->getDwarfStrSection())
171 .Case("debug_line_str", MC->getObjectFileInfo()->getDwarfLineStrSection())
172 .Case("debug_str_offsets",
173 MC->getObjectFileInfo()->getDwarfStrOffSection())
174 .Case("debug_pubnames",
175 MC->getObjectFileInfo()->getDwarfPubNamesSection())
176 .Case("debug_pubtypes",
177 MC->getObjectFileInfo()->getDwarfPubTypesSection())
178 .Case("debug_names", MC->getObjectFileInfo()->getDwarfDebugNamesSection())
179 .Case("apple_names", MC->getObjectFileInfo()->getDwarfAccelNamesSection())
180 .Case("apple_namespac",
181 MC->getObjectFileInfo()->getDwarfAccelNamespaceSection())
182 .Case("apple_objc", MC->getObjectFileInfo()->getDwarfAccelObjCSection())
183 .Case("apple_types", MC->getObjectFileInfo()->getDwarfAccelTypesSection())
184
185 .Default(nullptr);
186}
187
189 const SmallVector<std::unique_ptr<DIEAbbrev>> &Abbrevs,
190 unsigned DwarfVersion) {
191 MS->switchSection(MOFI->getDwarfAbbrevSection());
192 MC->setDwarfVersion(DwarfVersion);
193 Asm->emitDwarfAbbrevs(Abbrevs);
194}
195
197 MS->switchSection(MOFI->getDwarfInfoSection());
198 MC->setDwarfVersion(Unit.getVersion());
199
200 // Emit size of content not including length itself. The size has already
201 // been computed in CompileUnit::computeOffsets(). Subtract 4 to that size to
202 // account for the length field.
203 Asm->emitInt32(Unit.getUnitSize() - 4);
204 Asm->emitInt16(Unit.getVersion());
205
206 if (Unit.getVersion() >= 5) {
207 Asm->emitInt8(dwarf::DW_UT_compile);
208 Asm->emitInt8(Unit.getFormParams().AddrSize);
209 // Proper offset to the abbreviations table will be set later.
210 Asm->emitInt32(0);
211 DebugInfoSectionSize += 12;
212 } else {
213 // Proper offset to the abbreviations table will be set later.
214 Asm->emitInt32(0);
215 Asm->emitInt8(Unit.getFormParams().AddrSize);
216 DebugInfoSectionSize += 11;
217 }
218}
219
221 MS->switchSection(MOFI->getDwarfInfoSection());
222 Asm->emitDwarfDIE(Die);
223 DebugInfoSectionSize += Die.getSize();
224}
225
227 DebugNamesUnitsOffsets &CUOffsets,
228 CompUnitIDToIdx &CUidToIdx) {
229 if (CUOffsets.empty())
230 return;
231
232 Asm->OutStreamer->switchSection(MOFI->getDwarfDebugNamesSection());
234 DIEInteger::BestForm(/*IsSigned*/ false, (uint64_t)CUidToIdx.size() - 1);
235 // FIXME: add support for type units + .debug_names. For now the behavior is
236 // unsuported.
238 Asm.get(), Table, CUOffsets,
239 [&](const DWARF5AccelTableData &Entry)
240 -> std::optional<DWARF5AccelTable::UnitIndexAndEncoding> {
241 if (CUidToIdx.size() > 1)
242 return {{CUidToIdx[Entry.getUnitID()],
243 {dwarf::DW_IDX_compile_unit, Form}}};
244 return std::nullopt;
245 });
246}
247
248void DwarfEmitterImpl::emitAppleNamespaces(
250 Asm->OutStreamer->switchSection(MOFI->getDwarfAccelNamespaceSection());
251 auto *SectionBegin = Asm->createTempSymbol("namespac_begin");
252 Asm->OutStreamer->emitLabel(SectionBegin);
253 emitAppleAccelTable(Asm.get(), Table, "namespac", SectionBegin);
254}
255
256void DwarfEmitterImpl::emitAppleNames(
258 Asm->OutStreamer->switchSection(MOFI->getDwarfAccelNamesSection());
259 auto *SectionBegin = Asm->createTempSymbol("names_begin");
260 Asm->OutStreamer->emitLabel(SectionBegin);
261 emitAppleAccelTable(Asm.get(), Table, "names", SectionBegin);
262}
263
264void DwarfEmitterImpl::emitAppleObjc(
266 Asm->OutStreamer->switchSection(MOFI->getDwarfAccelObjCSection());
267 auto *SectionBegin = Asm->createTempSymbol("objc_begin");
268 Asm->OutStreamer->emitLabel(SectionBegin);
269 emitAppleAccelTable(Asm.get(), Table, "objc", SectionBegin);
270}
271
272void DwarfEmitterImpl::emitAppleTypes(
274 Asm->OutStreamer->switchSection(MOFI->getDwarfAccelTypesSection());
275 auto *SectionBegin = Asm->createTempSymbol("types_begin");
276 Asm->OutStreamer->emitLabel(SectionBegin);
277 emitAppleAccelTable(Asm.get(), Table, "types", SectionBegin);
278}
279
280} // end of namespace dwarflinker_parallel
281} // namespace llvm
This class holds an abstract representation of an Accelerator Table, consisting of a sequence of buck...
Definition: AccelTable.h:194
static dwarf::Form BestForm(bool IsSigned, uint64_t Int)
Choose the best form for integer.
Definition: DIE.h:175
A structured debug information entry.
Definition: DIE.h:819
unsigned getSize() const
Definition: DIE.h:862
The Data class implementation for DWARF v5 accelerator table.
Definition: AccelTable.h:254
unsigned size() const
Definition: DenseMap.h:99
Lightweight error class with error context and mandatory checking.
Definition: Error.h:160
static ErrorSuccess success()
Create a success value.
Definition: Error.h:334
std::unique_ptr< MCObjectWriter > createObjectWriter(raw_pwrite_stream &OS) const
Create a new MCObjectWriter instance for use by the assembler backend to emit the final object file.
Context object for machine code objects.
Definition: MCContext.h:76
Instances of this class represent a uniqued identifier for a section in the current translation unit.
Definition: MCSection.h:39
void setAlignment(Align Value)
Definition: MCSection.h:141
virtual void switchSection(MCSection *Section, const MCExpr *Subsection=nullptr)
Set the current section where code is being emitted to Section.
virtual void emitBytes(StringRef Data)
Emit the bytes in Data into the output.
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1200
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:50
A switch()-like statement whose cases are string literals.
Definition: StringSwitch.h:44
StringSwitch & Case(StringLiteral S, T Value)
Definition: StringSwitch.h:69
R Default(T Value)
Definition: StringSwitch.h:182
Target - Wrapper for Target specific information.
MCCodeEmitter * createMCCodeEmitter(const MCInstrInfo &II, MCContext &Ctx) const
createMCCodeEmitter - Create a target specific code emitter.
MCObjectFileInfo * createMCObjectFileInfo(MCContext &Ctx, bool PIC, bool LargeCodeModel=false) const
Create a MCObjectFileInfo implementation for the specified target triple.
MCSubtargetInfo * createMCSubtargetInfo(StringRef TheTriple, StringRef CPU, StringRef Features) const
createMCSubtargetInfo - Create a MCSubtargetInfo implementation.
MCStreamer * createAsmStreamer(MCContext &Ctx, std::unique_ptr< formatted_raw_ostream > OS, bool IsVerboseAsm, bool UseDwarfDirectory, MCInstPrinter *InstPrint, std::unique_ptr< MCCodeEmitter > &&CE, std::unique_ptr< MCAsmBackend > &&TAB, bool ShowInst) const
MCAsmBackend * createMCAsmBackend(const MCSubtargetInfo &STI, const MCRegisterInfo &MRI, const MCTargetOptions &Options) const
createMCAsmBackend - Create a target specific assembly parser.
MCRegisterInfo * createMCRegInfo(StringRef TT) const
createMCRegInfo - Create a MCRegisterInfo implementation.
TargetMachine * createTargetMachine(StringRef TT, StringRef CPU, StringRef Features, const TargetOptions &Options, std::optional< Reloc::Model > RM, std::optional< CodeModel::Model > CM=std::nullopt, CodeGenOptLevel OL=CodeGenOptLevel::Default, bool JIT=false) const
createTargetMachine - Create a target specific machine implementation for the specified Triple.
MCAsmInfo * createMCAsmInfo(const MCRegisterInfo &MRI, StringRef TheTriple, const MCTargetOptions &Options) const
createMCAsmInfo - Create a MCAsmInfo implementation for the specified target triple.
MCInstPrinter * createMCInstPrinter(const Triple &T, unsigned SyntaxVariant, const MCAsmInfo &MAI, const MCInstrInfo &MII, const MCRegisterInfo &MRI) const
MCStreamer * createMCObjectStreamer(const Triple &T, MCContext &Ctx, std::unique_ptr< MCAsmBackend > &&TAB, std::unique_ptr< MCObjectWriter > &&OW, std::unique_ptr< MCCodeEmitter > &&Emitter, const MCSubtargetInfo &STI, bool RelaxAll, bool IncrementalLinkerCompatible, bool DWARFMustBeAtTheEnd) const
Create a target specific MCStreamer.
AsmPrinter * createAsmPrinter(TargetMachine &TM, std::unique_ptr< MCStreamer > &&Streamer) const
createAsmPrinter - Create a target specific assembly printer pass.
MCInstrInfo * createMCInstrInfo() const
createMCInstrInfo - Create a MCInstrInfo implementation.
Triple - Helper class for working with autoconf configuration names.
Definition: Triple.h:44
const std::string & getTriple() const
Definition: Triple.h:418
void emitDIE(DIE &Die)
Emit DIE recursively.
void emitCompileUnitHeader(DwarfUnit &Unit)
Emit compile unit header.
Error init(Triple TheTriple, StringRef Swift5ReflectionSegmentName)
Initialize AsmPrinter data.
void emitSwiftReflectionSection(llvm::binaryformat::Swift5ReflectionSectionKind ReflSectionKind, StringRef Buffer, uint32_t Alignment, uint32_t) override
Emit the swift reflection section stored in Buffer.
void emitDebugNames(DWARF5AccelTable &Table, DebugNamesUnitsOffsets &CUOffsets, CompUnitIDToIdx &UnitIDToIdxMap)
Emits .debug_names section according to the specified Table.
void emitAbbrevs(const SmallVector< std::unique_ptr< DIEAbbrev > > &Abbrevs, unsigned DwarfVersion)
Emit abbreviations.
void emitSwiftAST(StringRef Buffer) override
Emit the swift_ast section stored in Buffer.
void emitSectionContents(StringRef SecData, StringRef SecName) override
Emit specified section data.
Base class for all Dwarf units(Compile unit/Type table unit).
Swift5ReflectionSectionKind
Definition: Swift.h:14
std::vector< std::variant< MCSymbol *, uint64_t > > DebugNamesUnitsOffsets
MCTargetOptions InitMCTargetOptionsFromFlags()
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
Error createStringError(std::error_code EC, char const *Fmt, const Ts &... Vals)
Create formatted StringError object.
Definition: Error.h:1244
void emitAppleAccelTable(AsmPrinter *Asm, AccelTable< DataT > &Contents, StringRef Prefix, const MCSymbol *SecBegin)
Emit an Apple Accelerator Table consisting of entries in the specified AccelTable.
Definition: AccelTable.h:355
void emitDWARF5AccelTable(AsmPrinter *Asm, DWARF5AccelTable &Contents, const DwarfDebug &DD, ArrayRef< std::unique_ptr< DwarfCompileUnit > > CUs)
Definition: AccelTable.cpp:594
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition: Alignment.h:39
static const Target * lookupTarget(StringRef Triple, std::string &Error)
lookupTarget - Lookup a target based on a target triple.