Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter/AsmPrinterDwarf.cpp
35271 views
1
//===-- AsmPrinterDwarf.cpp - AsmPrinter Dwarf Support --------------------===//
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
// This file implements the Dwarf emissions parts of AsmPrinter.
10
//
11
//===----------------------------------------------------------------------===//
12
13
#include "llvm/ADT/Twine.h"
14
#include "llvm/BinaryFormat/Dwarf.h"
15
#include "llvm/CodeGen/AsmPrinter.h"
16
#include "llvm/CodeGen/DIE.h"
17
#include "llvm/CodeGen/MachineFunction.h"
18
#include "llvm/IR/DataLayout.h"
19
#include "llvm/MC/MCAsmInfo.h"
20
#include "llvm/MC/MCDwarf.h"
21
#include "llvm/MC/MCSection.h"
22
#include "llvm/MC/MCStreamer.h"
23
#include "llvm/MC/MCSymbol.h"
24
#include "llvm/Support/ErrorHandling.h"
25
#include "llvm/Target/TargetLoweringObjectFile.h"
26
#include <cstdint>
27
using namespace llvm;
28
29
#define DEBUG_TYPE "asm-printer"
30
31
//===----------------------------------------------------------------------===//
32
// Dwarf Emission Helper Routines
33
//===----------------------------------------------------------------------===//
34
35
static const char *DecodeDWARFEncoding(unsigned Encoding) {
36
switch (Encoding) {
37
case dwarf::DW_EH_PE_absptr:
38
return "absptr";
39
case dwarf::DW_EH_PE_omit:
40
return "omit";
41
case dwarf::DW_EH_PE_pcrel:
42
return "pcrel";
43
case dwarf::DW_EH_PE_uleb128:
44
return "uleb128";
45
case dwarf::DW_EH_PE_sleb128:
46
return "sleb128";
47
case dwarf::DW_EH_PE_udata4:
48
return "udata4";
49
case dwarf::DW_EH_PE_udata8:
50
return "udata8";
51
case dwarf::DW_EH_PE_sdata4:
52
return "sdata4";
53
case dwarf::DW_EH_PE_sdata8:
54
return "sdata8";
55
case dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_udata4:
56
return "pcrel udata4";
57
case dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4:
58
return "pcrel sdata4";
59
case dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_udata8:
60
return "pcrel udata8";
61
case dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata8:
62
return "pcrel sdata8";
63
case dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_udata4
64
:
65
return "indirect pcrel udata4";
66
case dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4
67
:
68
return "indirect pcrel sdata4";
69
case dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_udata8
70
:
71
return "indirect pcrel udata8";
72
case dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata8
73
:
74
return "indirect pcrel sdata8";
75
case dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_datarel |
76
dwarf::DW_EH_PE_sdata4:
77
return "indirect datarel sdata4";
78
case dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_datarel |
79
dwarf::DW_EH_PE_sdata8:
80
return "indirect datarel sdata8";
81
}
82
83
return "<unknown encoding>";
84
}
85
86
/// EmitEncodingByte - Emit a .byte 42 directive that corresponds to an
87
/// encoding. If verbose assembly output is enabled, we output comments
88
/// describing the encoding. Desc is an optional string saying what the
89
/// encoding is specifying (e.g. "LSDA").
90
void AsmPrinter::emitEncodingByte(unsigned Val, const char *Desc) const {
91
if (isVerbose()) {
92
if (Desc)
93
OutStreamer->AddComment(Twine(Desc) + " Encoding = " +
94
Twine(DecodeDWARFEncoding(Val)));
95
else
96
OutStreamer->AddComment(Twine("Encoding = ") + DecodeDWARFEncoding(Val));
97
}
98
99
OutStreamer->emitIntValue(Val, 1);
100
}
101
102
/// GetSizeOfEncodedValue - Return the size of the encoding in bytes.
103
unsigned AsmPrinter::GetSizeOfEncodedValue(unsigned Encoding) const {
104
if (Encoding == dwarf::DW_EH_PE_omit)
105
return 0;
106
107
switch (Encoding & 0x07) {
108
default:
109
llvm_unreachable("Invalid encoded value.");
110
case dwarf::DW_EH_PE_absptr:
111
return MAI->getCodePointerSize();
112
case dwarf::DW_EH_PE_udata2:
113
return 2;
114
case dwarf::DW_EH_PE_udata4:
115
return 4;
116
case dwarf::DW_EH_PE_udata8:
117
return 8;
118
}
119
}
120
121
void AsmPrinter::emitTTypeReference(const GlobalValue *GV, unsigned Encoding) {
122
if (GV) {
123
const TargetLoweringObjectFile &TLOF = getObjFileLowering();
124
125
const MCExpr *Exp =
126
TLOF.getTTypeGlobalReference(GV, Encoding, TM, MMI, *OutStreamer);
127
OutStreamer->emitValue(Exp, GetSizeOfEncodedValue(Encoding));
128
} else
129
OutStreamer->emitIntValue(0, GetSizeOfEncodedValue(Encoding));
130
}
131
132
void AsmPrinter::emitDwarfSymbolReference(const MCSymbol *Label,
133
bool ForceOffset) const {
134
if (!ForceOffset) {
135
// On COFF targets, we have to emit the special .secrel32 directive.
136
if (MAI->needsDwarfSectionOffsetDirective()) {
137
assert(!isDwarf64() &&
138
"emitting DWARF64 is not implemented for COFF targets");
139
OutStreamer->emitCOFFSecRel32(Label, /*Offset=*/0);
140
return;
141
}
142
143
// If the format uses relocations with dwarf, refer to the symbol directly.
144
if (doesDwarfUseRelocationsAcrossSections()) {
145
OutStreamer->emitSymbolValue(Label, getDwarfOffsetByteSize());
146
return;
147
}
148
}
149
150
// Otherwise, emit it as a label difference from the start of the section.
151
emitLabelDifference(Label, Label->getSection().getBeginSymbol(),
152
getDwarfOffsetByteSize());
153
}
154
155
void AsmPrinter::emitDwarfStringOffset(DwarfStringPoolEntry S) const {
156
if (doesDwarfUseRelocationsAcrossSections()) {
157
assert(S.Symbol && "No symbol available");
158
emitDwarfSymbolReference(S.Symbol);
159
return;
160
}
161
162
// Just emit the offset directly; no need for symbol math.
163
OutStreamer->emitIntValue(S.Offset, getDwarfOffsetByteSize());
164
}
165
166
void AsmPrinter::emitDwarfOffset(const MCSymbol *Label, uint64_t Offset) const {
167
emitLabelPlusOffset(Label, Offset, getDwarfOffsetByteSize());
168
}
169
170
void AsmPrinter::emitDwarfLengthOrOffset(uint64_t Value) const {
171
assert(isDwarf64() || Value <= UINT32_MAX);
172
OutStreamer->emitIntValue(Value, getDwarfOffsetByteSize());
173
}
174
175
void AsmPrinter::emitDwarfUnitLength(uint64_t Length,
176
const Twine &Comment) const {
177
OutStreamer->emitDwarfUnitLength(Length, Comment);
178
}
179
180
MCSymbol *AsmPrinter::emitDwarfUnitLength(const Twine &Prefix,
181
const Twine &Comment) const {
182
return OutStreamer->emitDwarfUnitLength(Prefix, Comment);
183
}
184
185
void AsmPrinter::emitCallSiteOffset(const MCSymbol *Hi, const MCSymbol *Lo,
186
unsigned Encoding) const {
187
// The least significant 3 bits specify the width of the encoding
188
if ((Encoding & 0x7) == dwarf::DW_EH_PE_uleb128)
189
emitLabelDifferenceAsULEB128(Hi, Lo);
190
else
191
emitLabelDifference(Hi, Lo, GetSizeOfEncodedValue(Encoding));
192
}
193
194
void AsmPrinter::emitCallSiteValue(uint64_t Value, unsigned Encoding) const {
195
// The least significant 3 bits specify the width of the encoding
196
if ((Encoding & 0x7) == dwarf::DW_EH_PE_uleb128)
197
emitULEB128(Value);
198
else
199
OutStreamer->emitIntValue(Value, GetSizeOfEncodedValue(Encoding));
200
}
201
202
//===----------------------------------------------------------------------===//
203
// Dwarf Lowering Routines
204
//===----------------------------------------------------------------------===//
205
206
void AsmPrinter::emitCFIInstruction(const MCCFIInstruction &Inst) const {
207
SMLoc Loc = Inst.getLoc();
208
switch (Inst.getOperation()) {
209
default:
210
llvm_unreachable("Unexpected instruction");
211
case MCCFIInstruction::OpDefCfaOffset:
212
OutStreamer->emitCFIDefCfaOffset(Inst.getOffset(), Loc);
213
break;
214
case MCCFIInstruction::OpAdjustCfaOffset:
215
OutStreamer->emitCFIAdjustCfaOffset(Inst.getOffset(), Loc);
216
break;
217
case MCCFIInstruction::OpDefCfa:
218
OutStreamer->emitCFIDefCfa(Inst.getRegister(), Inst.getOffset(), Loc);
219
break;
220
case MCCFIInstruction::OpDefCfaRegister:
221
OutStreamer->emitCFIDefCfaRegister(Inst.getRegister(), Loc);
222
break;
223
case MCCFIInstruction::OpLLVMDefAspaceCfa:
224
OutStreamer->emitCFILLVMDefAspaceCfa(Inst.getRegister(), Inst.getOffset(),
225
Inst.getAddressSpace(), Loc);
226
break;
227
case MCCFIInstruction::OpOffset:
228
OutStreamer->emitCFIOffset(Inst.getRegister(), Inst.getOffset(), Loc);
229
break;
230
case MCCFIInstruction::OpRegister:
231
OutStreamer->emitCFIRegister(Inst.getRegister(), Inst.getRegister2(), Loc);
232
break;
233
case MCCFIInstruction::OpWindowSave:
234
OutStreamer->emitCFIWindowSave(Loc);
235
break;
236
case MCCFIInstruction::OpNegateRAState:
237
OutStreamer->emitCFINegateRAState(Loc);
238
break;
239
case MCCFIInstruction::OpSameValue:
240
OutStreamer->emitCFISameValue(Inst.getRegister(), Loc);
241
break;
242
case MCCFIInstruction::OpGnuArgsSize:
243
OutStreamer->emitCFIGnuArgsSize(Inst.getOffset(), Loc);
244
break;
245
case MCCFIInstruction::OpEscape:
246
OutStreamer->AddComment(Inst.getComment());
247
OutStreamer->emitCFIEscape(Inst.getValues(), Loc);
248
break;
249
case MCCFIInstruction::OpRestore:
250
OutStreamer->emitCFIRestore(Inst.getRegister(), Loc);
251
break;
252
case MCCFIInstruction::OpUndefined:
253
OutStreamer->emitCFIUndefined(Inst.getRegister(), Loc);
254
break;
255
case MCCFIInstruction::OpRememberState:
256
OutStreamer->emitCFIRememberState(Loc);
257
break;
258
case MCCFIInstruction::OpRestoreState:
259
OutStreamer->emitCFIRestoreState(Loc);
260
break;
261
}
262
}
263
264
void AsmPrinter::emitDwarfDIE(const DIE &Die) const {
265
// Emit the code (index) for the abbreviation.
266
if (isVerbose())
267
OutStreamer->AddComment("Abbrev [" + Twine(Die.getAbbrevNumber()) + "] 0x" +
268
Twine::utohexstr(Die.getOffset()) + ":0x" +
269
Twine::utohexstr(Die.getSize()) + " " +
270
dwarf::TagString(Die.getTag()));
271
emitULEB128(Die.getAbbrevNumber());
272
273
// Emit the DIE attribute values.
274
for (const auto &V : Die.values()) {
275
dwarf::Attribute Attr = V.getAttribute();
276
assert(V.getForm() && "Too many attributes for DIE (check abbreviation)");
277
278
if (isVerbose()) {
279
OutStreamer->AddComment(dwarf::AttributeString(Attr));
280
if (Attr == dwarf::DW_AT_accessibility)
281
OutStreamer->AddComment(
282
dwarf::AccessibilityString(V.getDIEInteger().getValue()));
283
}
284
285
// Emit an attribute using the defined form.
286
V.emitValue(this);
287
}
288
289
// Emit the DIE children if any.
290
if (Die.hasChildren()) {
291
for (const auto &Child : Die.children())
292
emitDwarfDIE(Child);
293
294
OutStreamer->AddComment("End Of Children Mark");
295
emitInt8(0);
296
}
297
}
298
299
void AsmPrinter::emitDwarfAbbrev(const DIEAbbrev &Abbrev) const {
300
// Emit the abbreviations code (base 1 index.)
301
emitULEB128(Abbrev.getNumber(), "Abbreviation Code");
302
303
// Emit the abbreviations data.
304
Abbrev.Emit(this);
305
}
306
307