1 //===-- AsmPrinterDwarf.cpp - AsmPrinter Dwarf Support --------------------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // This file implements the Dwarf emissions parts of AsmPrinter. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #include "ByteStreamer.h" 15 #include "llvm/ADT/Twine.h" 16 #include "llvm/BinaryFormat/Dwarf.h" 17 #include "llvm/CodeGen/AsmPrinter.h" 18 #include "llvm/CodeGen/DIE.h" 19 #include "llvm/CodeGen/MachineFunction.h" 20 #include "llvm/IR/DataLayout.h" 21 #include "llvm/MC/MCAsmInfo.h" 22 #include "llvm/MC/MCRegisterInfo.h" 23 #include "llvm/MC/MCSection.h" 24 #include "llvm/MC/MCStreamer.h" 25 #include "llvm/MC/MCSymbol.h" 26 #include "llvm/MC/MachineLocation.h" 27 #include "llvm/Support/ErrorHandling.h" 28 #include "llvm/Target/TargetLoweringObjectFile.h" 29 #include "llvm/Target/TargetMachine.h" 30 using namespace llvm; 31 32 #define DEBUG_TYPE "asm-printer" 33 34 //===----------------------------------------------------------------------===// 35 // Dwarf Emission Helper Routines 36 //===----------------------------------------------------------------------===// 37 38 /// EmitSLEB128 - emit the specified signed leb128 value. 39 void AsmPrinter::EmitSLEB128(int64_t Value, const char *Desc) const { 40 if (isVerbose() && Desc) 41 OutStreamer->AddComment(Desc); 42 43 OutStreamer->EmitSLEB128IntValue(Value); 44 } 45 46 void AsmPrinter::EmitULEB128(uint64_t Value, const char *Desc) const { 47 if (isVerbose() && Desc) 48 OutStreamer->AddComment(Desc); 49 50 OutStreamer->EmitULEB128IntValue(Value); 51 } 52 53 /// Emit something like ".uleb128 Hi-Lo". 54 void AsmPrinter::EmitLabelDifferenceAsULEB128(const MCSymbol *Hi, 55 const MCSymbol *Lo) const { 56 OutStreamer->emitAbsoluteSymbolDiffAsULEB128(Hi, Lo); 57 } 58 59 static const char *DecodeDWARFEncoding(unsigned Encoding) { 60 switch (Encoding) { 61 case dwarf::DW_EH_PE_absptr: 62 return "absptr"; 63 case dwarf::DW_EH_PE_omit: 64 return "omit"; 65 case dwarf::DW_EH_PE_pcrel: 66 return "pcrel"; 67 case dwarf::DW_EH_PE_uleb128: 68 return "uleb128"; 69 case dwarf::DW_EH_PE_sleb128: 70 return "sleb128"; 71 case dwarf::DW_EH_PE_udata4: 72 return "udata4"; 73 case dwarf::DW_EH_PE_udata8: 74 return "udata8"; 75 case dwarf::DW_EH_PE_sdata4: 76 return "sdata4"; 77 case dwarf::DW_EH_PE_sdata8: 78 return "sdata8"; 79 case dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_udata4: 80 return "pcrel udata4"; 81 case dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4: 82 return "pcrel sdata4"; 83 case dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_udata8: 84 return "pcrel udata8"; 85 case dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata8: 86 return "pcrel sdata8"; 87 case dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_udata4 88 : 89 return "indirect pcrel udata4"; 90 case dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4 91 : 92 return "indirect pcrel sdata4"; 93 case dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_udata8 94 : 95 return "indirect pcrel udata8"; 96 case dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata8 97 : 98 return "indirect pcrel sdata8"; 99 } 100 101 return "<unknown encoding>"; 102 } 103 104 /// EmitEncodingByte - Emit a .byte 42 directive that corresponds to an 105 /// encoding. If verbose assembly output is enabled, we output comments 106 /// describing the encoding. Desc is an optional string saying what the 107 /// encoding is specifying (e.g. "LSDA"). 108 void AsmPrinter::EmitEncodingByte(unsigned Val, const char *Desc) const { 109 if (isVerbose()) { 110 if (Desc) 111 OutStreamer->AddComment(Twine(Desc) + " Encoding = " + 112 Twine(DecodeDWARFEncoding(Val))); 113 else 114 OutStreamer->AddComment(Twine("Encoding = ") + DecodeDWARFEncoding(Val)); 115 } 116 117 OutStreamer->EmitIntValue(Val, 1); 118 } 119 120 /// GetSizeOfEncodedValue - Return the size of the encoding in bytes. 121 unsigned AsmPrinter::GetSizeOfEncodedValue(unsigned Encoding) const { 122 if (Encoding == dwarf::DW_EH_PE_omit) 123 return 0; 124 125 switch (Encoding & 0x07) { 126 default: 127 llvm_unreachable("Invalid encoded value."); 128 case dwarf::DW_EH_PE_absptr: 129 return MF->getDataLayout().getPointerSize(); 130 case dwarf::DW_EH_PE_udata2: 131 return 2; 132 case dwarf::DW_EH_PE_udata4: 133 return 4; 134 case dwarf::DW_EH_PE_udata8: 135 return 8; 136 } 137 } 138 139 void AsmPrinter::EmitTTypeReference(const GlobalValue *GV, 140 unsigned Encoding) const { 141 if (GV) { 142 const TargetLoweringObjectFile &TLOF = getObjFileLowering(); 143 144 const MCExpr *Exp = 145 TLOF.getTTypeGlobalReference(GV, Encoding, TM, MMI, *OutStreamer); 146 OutStreamer->EmitValue(Exp, GetSizeOfEncodedValue(Encoding)); 147 } else 148 OutStreamer->EmitIntValue(0, GetSizeOfEncodedValue(Encoding)); 149 } 150 151 void AsmPrinter::emitDwarfSymbolReference(const MCSymbol *Label, 152 bool ForceOffset) const { 153 if (!ForceOffset) { 154 // On COFF targets, we have to emit the special .secrel32 directive. 155 if (MAI->needsDwarfSectionOffsetDirective()) { 156 OutStreamer->EmitCOFFSecRel32(Label, /*Offset=*/0); 157 return; 158 } 159 160 // If the format uses relocations with dwarf, refer to the symbol directly. 161 if (MAI->doesDwarfUseRelocationsAcrossSections()) { 162 OutStreamer->EmitSymbolValue(Label, 4); 163 return; 164 } 165 } 166 167 // Otherwise, emit it as a label difference from the start of the section. 168 EmitLabelDifference(Label, Label->getSection().getBeginSymbol(), 4); 169 } 170 171 void AsmPrinter::emitDwarfStringOffset(DwarfStringPoolEntry S) const { 172 if (MAI->doesDwarfUseRelocationsAcrossSections()) { 173 assert(S.Symbol && "No symbol available"); 174 emitDwarfSymbolReference(S.Symbol); 175 return; 176 } 177 178 // Just emit the offset directly; no need for symbol math. 179 emitInt32(S.Offset); 180 } 181 182 void AsmPrinter::EmitDwarfOffset(const MCSymbol *Label, uint64_t Offset) const { 183 EmitLabelPlusOffset(Label, Offset, MAI->getCodePointerSize()); 184 } 185 186 //===----------------------------------------------------------------------===// 187 // Dwarf Lowering Routines 188 //===----------------------------------------------------------------------===// 189 190 void AsmPrinter::emitCFIInstruction(const MCCFIInstruction &Inst) const { 191 switch (Inst.getOperation()) { 192 default: 193 llvm_unreachable("Unexpected instruction"); 194 case MCCFIInstruction::OpDefCfaOffset: 195 OutStreamer->EmitCFIDefCfaOffset(Inst.getOffset()); 196 break; 197 case MCCFIInstruction::OpAdjustCfaOffset: 198 OutStreamer->EmitCFIAdjustCfaOffset(Inst.getOffset()); 199 break; 200 case MCCFIInstruction::OpDefCfa: 201 OutStreamer->EmitCFIDefCfa(Inst.getRegister(), Inst.getOffset()); 202 break; 203 case MCCFIInstruction::OpDefCfaRegister: 204 OutStreamer->EmitCFIDefCfaRegister(Inst.getRegister()); 205 break; 206 case MCCFIInstruction::OpOffset: 207 OutStreamer->EmitCFIOffset(Inst.getRegister(), Inst.getOffset()); 208 break; 209 case MCCFIInstruction::OpRegister: 210 OutStreamer->EmitCFIRegister(Inst.getRegister(), Inst.getRegister2()); 211 break; 212 case MCCFIInstruction::OpWindowSave: 213 OutStreamer->EmitCFIWindowSave(); 214 break; 215 case MCCFIInstruction::OpNegateRAState: 216 OutStreamer->EmitCFINegateRAState(); 217 break; 218 case MCCFIInstruction::OpSameValue: 219 OutStreamer->EmitCFISameValue(Inst.getRegister()); 220 break; 221 case MCCFIInstruction::OpGnuArgsSize: 222 OutStreamer->EmitCFIGnuArgsSize(Inst.getOffset()); 223 break; 224 case MCCFIInstruction::OpEscape: 225 OutStreamer->EmitCFIEscape(Inst.getValues()); 226 break; 227 case MCCFIInstruction::OpRestore: 228 OutStreamer->EmitCFIRestore(Inst.getRegister()); 229 break; 230 } 231 } 232 233 void AsmPrinter::emitDwarfDIE(const DIE &Die) const { 234 // Emit the code (index) for the abbreviation. 235 if (isVerbose()) 236 OutStreamer->AddComment("Abbrev [" + Twine(Die.getAbbrevNumber()) + "] 0x" + 237 Twine::utohexstr(Die.getOffset()) + ":0x" + 238 Twine::utohexstr(Die.getSize()) + " " + 239 dwarf::TagString(Die.getTag())); 240 EmitULEB128(Die.getAbbrevNumber()); 241 242 // Emit the DIE attribute values. 243 for (const auto &V : Die.values()) { 244 dwarf::Attribute Attr = V.getAttribute(); 245 assert(V.getForm() && "Too many attributes for DIE (check abbreviation)"); 246 247 if (isVerbose()) { 248 OutStreamer->AddComment(dwarf::AttributeString(Attr)); 249 if (Attr == dwarf::DW_AT_accessibility) 250 OutStreamer->AddComment( 251 dwarf::AccessibilityString(V.getDIEInteger().getValue())); 252 } 253 254 // Emit an attribute using the defined form. 255 V.EmitValue(this); 256 } 257 258 // Emit the DIE children if any. 259 if (Die.hasChildren()) { 260 for (auto &Child : Die.children()) 261 emitDwarfDIE(Child); 262 263 OutStreamer->AddComment("End Of Children Mark"); 264 emitInt8(0); 265 } 266 } 267 268 void AsmPrinter::emitDwarfAbbrev(const DIEAbbrev &Abbrev) const { 269 // Emit the abbreviations code (base 1 index.) 270 EmitULEB128(Abbrev.getNumber(), "Abbreviation Code"); 271 272 // Emit the abbreviations data. 273 Abbrev.Emit(this); 274 } 275