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(T: Twine(Desc) + " Encoding = " + |
94 | Twine(DecodeDWARFEncoding(Encoding: Val))); |
95 | else |
96 | OutStreamer->AddComment(T: Twine("Encoding = " ) + DecodeDWARFEncoding(Encoding: Val)); |
97 | } |
98 | |
99 | OutStreamer->emitIntValue(Value: Val, Size: 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, Streamer&: *OutStreamer); |
127 | OutStreamer->emitValue(Value: Exp, Size: GetSizeOfEncodedValue(Encoding)); |
128 | } else |
129 | OutStreamer->emitIntValue(Value: 0, Size: 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(Symbol: 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(Sym: Label, Size: getDwarfOffsetByteSize()); |
146 | return; |
147 | } |
148 | } |
149 | |
150 | // Otherwise, emit it as a label difference from the start of the section. |
151 | emitLabelDifference(Hi: Label, Lo: Label->getSection().getBeginSymbol(), |
152 | Size: getDwarfOffsetByteSize()); |
153 | } |
154 | |
155 | void AsmPrinter::emitDwarfStringOffset(DwarfStringPoolEntry S) const { |
156 | if (doesDwarfUseRelocationsAcrossSections()) { |
157 | assert(S.Symbol && "No symbol available" ); |
158 | emitDwarfSymbolReference(Label: S.Symbol); |
159 | return; |
160 | } |
161 | |
162 | // Just emit the offset directly; no need for symbol math. |
163 | OutStreamer->emitIntValue(Value: S.Offset, Size: getDwarfOffsetByteSize()); |
164 | } |
165 | |
166 | void AsmPrinter::emitDwarfOffset(const MCSymbol *Label, uint64_t Offset) const { |
167 | emitLabelPlusOffset(Label, Offset, Size: getDwarfOffsetByteSize()); |
168 | } |
169 | |
170 | void AsmPrinter::emitDwarfLengthOrOffset(uint64_t Value) const { |
171 | assert(isDwarf64() || Value <= UINT32_MAX); |
172 | OutStreamer->emitIntValue(Value, Size: getDwarfOffsetByteSize()); |
173 | } |
174 | |
175 | void AsmPrinter::emitDwarfUnitLength(uint64_t Length, |
176 | const Twine &) const { |
177 | OutStreamer->emitDwarfUnitLength(Length, Comment); |
178 | } |
179 | |
180 | MCSymbol *AsmPrinter::emitDwarfUnitLength(const Twine &Prefix, |
181 | const Twine &) 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, Size: 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, Size: 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(Offset: Inst.getOffset(), Loc); |
213 | break; |
214 | case MCCFIInstruction::OpAdjustCfaOffset: |
215 | OutStreamer->emitCFIAdjustCfaOffset(Adjustment: Inst.getOffset(), Loc); |
216 | break; |
217 | case MCCFIInstruction::OpDefCfa: |
218 | OutStreamer->emitCFIDefCfa(Register: Inst.getRegister(), Offset: Inst.getOffset(), Loc); |
219 | break; |
220 | case MCCFIInstruction::OpDefCfaRegister: |
221 | OutStreamer->emitCFIDefCfaRegister(Register: Inst.getRegister(), Loc); |
222 | break; |
223 | case MCCFIInstruction::OpLLVMDefAspaceCfa: |
224 | OutStreamer->emitCFILLVMDefAspaceCfa(Register: Inst.getRegister(), Offset: Inst.getOffset(), |
225 | AddressSpace: Inst.getAddressSpace(), Loc); |
226 | break; |
227 | case MCCFIInstruction::OpOffset: |
228 | OutStreamer->emitCFIOffset(Register: Inst.getRegister(), Offset: Inst.getOffset(), Loc); |
229 | break; |
230 | case MCCFIInstruction::OpRegister: |
231 | OutStreamer->emitCFIRegister(Register1: Inst.getRegister(), Register2: 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(Register: Inst.getRegister(), Loc); |
241 | break; |
242 | case MCCFIInstruction::OpGnuArgsSize: |
243 | OutStreamer->emitCFIGnuArgsSize(Size: Inst.getOffset(), Loc); |
244 | break; |
245 | case MCCFIInstruction::OpEscape: |
246 | OutStreamer->AddComment(T: Inst.getComment()); |
247 | OutStreamer->emitCFIEscape(Values: Inst.getValues(), Loc); |
248 | break; |
249 | case MCCFIInstruction::OpRestore: |
250 | OutStreamer->emitCFIRestore(Register: Inst.getRegister(), Loc); |
251 | break; |
252 | case MCCFIInstruction::OpUndefined: |
253 | OutStreamer->emitCFIUndefined(Register: 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(T: "Abbrev [" + Twine(Die.getAbbrevNumber()) + "] 0x" + |
268 | Twine::utohexstr(Val: Die.getOffset()) + ":0x" + |
269 | Twine::utohexstr(Val: Die.getSize()) + " " + |
270 | dwarf::TagString(Tag: Die.getTag())); |
271 | emitULEB128(Value: 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(T: dwarf::AttributeString(Attribute: Attr)); |
280 | if (Attr == dwarf::DW_AT_accessibility) |
281 | OutStreamer->AddComment( |
282 | T: dwarf::AccessibilityString(Access: V.getDIEInteger().getValue())); |
283 | } |
284 | |
285 | // Emit an attribute using the defined form. |
286 | V.emitValue(AP: this); |
287 | } |
288 | |
289 | // Emit the DIE children if any. |
290 | if (Die.hasChildren()) { |
291 | for (const auto &Child : Die.children()) |
292 | emitDwarfDIE(Die: Child); |
293 | |
294 | OutStreamer->AddComment(T: "End Of Children Mark" ); |
295 | emitInt8(Value: 0); |
296 | } |
297 | } |
298 | |
299 | void AsmPrinter::emitDwarfAbbrev(const DIEAbbrev &Abbrev) const { |
300 | // Emit the abbreviations code (base 1 index.) |
301 | emitULEB128(Value: Abbrev.getNumber(), Desc: "Abbreviation Code" ); |
302 | |
303 | // Emit the abbreviations data. |
304 | Abbrev.Emit(AP: this); |
305 | } |
306 | |