Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/llvm/lib/DWARFLinker/Parallel/DWARFEmitterImpl.cpp
35292 views
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
216