xref: /freebsd/contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter/AsmPrinterDwarf.cpp (revision 06c3fb2749bda94cb5201f81ffdb8fa6c3161b2e)
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