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