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> 26 using namespace llvm; 27 28 #define DEBUG_TYPE "asm-printer" 29 30 //===----------------------------------------------------------------------===// 31 // Dwarf Emission Helper Routines 32 //===----------------------------------------------------------------------===// 33 34 static 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"). 89 void AsmPrinter::emitEncodingByte(unsigned Val, const char *Desc) const { 90 if (isVerbose()) { 91 if (Desc) 92 OutStreamer->AddComment(Twine(Desc) + " Encoding = " + 93 Twine(DecodeDWARFEncoding(Val))); 94 else 95 OutStreamer->AddComment(Twine("Encoding = ") + DecodeDWARFEncoding(Val)); 96 } 97 98 OutStreamer->emitIntValue(Val, 1); 99 } 100 101 /// GetSizeOfEncodedValue - Return the size of the encoding in bytes. 102 unsigned 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 120 void 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, *OutStreamer); 126 OutStreamer->emitValue(Exp, GetSizeOfEncodedValue(Encoding)); 127 } else 128 OutStreamer->emitIntValue(0, GetSizeOfEncodedValue(Encoding)); 129 } 130 131 void 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(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(Label, getDwarfOffsetByteSize()); 145 return; 146 } 147 } 148 149 // Otherwise, emit it as a label difference from the start of the section. 150 emitLabelDifference(Label, Label->getSection().getBeginSymbol(), 151 getDwarfOffsetByteSize()); 152 } 153 154 void AsmPrinter::emitDwarfStringOffset(DwarfStringPoolEntry S) const { 155 if (doesDwarfUseRelocationsAcrossSections()) { 156 assert(S.Symbol && "No symbol available"); 157 emitDwarfSymbolReference(S.Symbol); 158 return; 159 } 160 161 // Just emit the offset directly; no need for symbol math. 162 OutStreamer->emitIntValue(S.Offset, getDwarfOffsetByteSize()); 163 } 164 165 void AsmPrinter::emitDwarfOffset(const MCSymbol *Label, uint64_t Offset) const { 166 emitLabelPlusOffset(Label, Offset, getDwarfOffsetByteSize()); 167 } 168 169 void AsmPrinter::emitDwarfLengthOrOffset(uint64_t Value) const { 170 assert(isDwarf64() || Value <= UINT32_MAX); 171 OutStreamer->emitIntValue(Value, getDwarfOffsetByteSize()); 172 } 173 174 void AsmPrinter::emitDwarfUnitLength(uint64_t Length, 175 const Twine &Comment) const { 176 OutStreamer->emitDwarfUnitLength(Length, Comment); 177 } 178 179 MCSymbol *AsmPrinter::emitDwarfUnitLength(const Twine &Prefix, 180 const Twine &Comment) const { 181 return OutStreamer->emitDwarfUnitLength(Prefix, Comment); 182 } 183 184 void 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, GetSizeOfEncodedValue(Encoding)); 191 } 192 193 void 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, GetSizeOfEncodedValue(Encoding)); 199 } 200 201 //===----------------------------------------------------------------------===// 202 // Dwarf Lowering Routines 203 //===----------------------------------------------------------------------===// 204 205 void 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(Inst.getOffset(), Loc); 212 break; 213 case MCCFIInstruction::OpAdjustCfaOffset: 214 OutStreamer->emitCFIAdjustCfaOffset(Inst.getOffset(), Loc); 215 break; 216 case MCCFIInstruction::OpDefCfa: 217 OutStreamer->emitCFIDefCfa(Inst.getRegister(), Inst.getOffset(), Loc); 218 break; 219 case MCCFIInstruction::OpDefCfaRegister: 220 OutStreamer->emitCFIDefCfaRegister(Inst.getRegister(), Loc); 221 break; 222 case MCCFIInstruction::OpLLVMDefAspaceCfa: 223 OutStreamer->emitCFILLVMDefAspaceCfa(Inst.getRegister(), Inst.getOffset(), 224 Inst.getAddressSpace(), Loc); 225 break; 226 case MCCFIInstruction::OpOffset: 227 OutStreamer->emitCFIOffset(Inst.getRegister(), Inst.getOffset(), Loc); 228 break; 229 case MCCFIInstruction::OpRegister: 230 OutStreamer->emitCFIRegister(Inst.getRegister(), 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(Inst.getRegister(), Loc); 243 break; 244 case MCCFIInstruction::OpGnuArgsSize: 245 OutStreamer->emitCFIGnuArgsSize(Inst.getOffset(), Loc); 246 break; 247 case MCCFIInstruction::OpEscape: 248 OutStreamer->AddComment(Inst.getComment()); 249 OutStreamer->emitCFIEscape(Inst.getValues(), Loc); 250 break; 251 case MCCFIInstruction::OpRestore: 252 OutStreamer->emitCFIRestore(Inst.getRegister(), Loc); 253 break; 254 case MCCFIInstruction::OpUndefined: 255 OutStreamer->emitCFIUndefined(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(Inst.getRegister(), Inst.getOffset(), Loc); 265 break; 266 } 267 } 268 269 void AsmPrinter::emitDwarfDIE(const DIE &Die) const { 270 // Emit the code (index) for the abbreviation. 271 if (isVerbose()) 272 OutStreamer->AddComment("Abbrev [" + Twine(Die.getAbbrevNumber()) + "] 0x" + 273 Twine::utohexstr(Die.getOffset()) + ":0x" + 274 Twine::utohexstr(Die.getSize()) + " " + 275 dwarf::TagString(Die.getTag())); 276 emitULEB128(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(dwarf::AttributeString(Attr)); 285 if (Attr == dwarf::DW_AT_accessibility) 286 OutStreamer->AddComment( 287 dwarf::AccessibilityString(V.getDIEInteger().getValue())); 288 } 289 290 // Emit an attribute using the defined form. 291 V.emitValue(this); 292 } 293 294 // Emit the DIE children if any. 295 if (Die.hasChildren()) { 296 for (const auto &Child : Die.children()) 297 emitDwarfDIE(Child); 298 299 OutStreamer->AddComment("End Of Children Mark"); 300 emitInt8(0); 301 } 302 } 303 304 void AsmPrinter::emitDwarfAbbrev(const DIEAbbrev &Abbrev) const { 305 // Emit the abbreviations code (base 1 index.) 306 emitULEB128(Abbrev.getNumber(), "Abbreviation Code"); 307 308 // Emit the abbreviations data. 309 Abbrev.Emit(this); 310 } 311