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
DecodeDWARFEncoding(unsigned Encoding)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").
emitEncodingByte(unsigned Val,const char * Desc) const90 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.
GetSizeOfEncodedValue(unsigned Encoding) const103 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
emitTTypeReference(const GlobalValue * GV,unsigned Encoding)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
emitDwarfSymbolReference(const MCSymbol * Label,bool ForceOffset) const132 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
emitDwarfStringOffset(DwarfStringPoolEntry S) const155 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
emitDwarfOffset(const MCSymbol * Label,uint64_t Offset) const166 void AsmPrinter::emitDwarfOffset(const MCSymbol *Label, uint64_t Offset) const {
167 emitLabelPlusOffset(Label, Offset, getDwarfOffsetByteSize());
168 }
169
emitDwarfLengthOrOffset(uint64_t Value) const170 void AsmPrinter::emitDwarfLengthOrOffset(uint64_t Value) const {
171 assert(isDwarf64() || Value <= UINT32_MAX);
172 OutStreamer->emitIntValue(Value, getDwarfOffsetByteSize());
173 }
174
emitDwarfUnitLength(uint64_t Length,const Twine & Comment) const175 void AsmPrinter::emitDwarfUnitLength(uint64_t Length,
176 const Twine &Comment) const {
177 OutStreamer->emitDwarfUnitLength(Length, Comment);
178 }
179
emitDwarfUnitLength(const Twine & Prefix,const Twine & Comment) const180 MCSymbol *AsmPrinter::emitDwarfUnitLength(const Twine &Prefix,
181 const Twine &Comment) const {
182 return OutStreamer->emitDwarfUnitLength(Prefix, Comment);
183 }
184
emitCallSiteOffset(const MCSymbol * Hi,const MCSymbol * Lo,unsigned Encoding) const185 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
emitCallSiteValue(uint64_t Value,unsigned Encoding) const194 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
emitCFIInstruction(const MCCFIInstruction & Inst) const206 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
emitDwarfDIE(const DIE & Die) const264 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
emitDwarfAbbrev(const DIEAbbrev & Abbrev) const299 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