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