AsmPrinterDwarf.cpp revision c06b4740af510c449b41bf2a2f25216f1525a0af
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#define DEBUG_TYPE "asm-printer" 15#include "llvm/CodeGen/AsmPrinter.h" 16#include "llvm/MC/MCAsmInfo.h" 17#include "llvm/MC/MCSection.h" 18#include "llvm/MC/MCStreamer.h" 19#include "llvm/MC/MCSymbol.h" 20#include "llvm/Target/TargetData.h" 21#include "llvm/Target/TargetLoweringObjectFile.h" 22#include "llvm/Target/TargetMachine.h" 23#include "llvm/ADT/Twine.h" 24#include "llvm/Support/Dwarf.h" 25using namespace llvm; 26 27/// EmitSLEB128 - emit the specified signed leb128 value. 28void AsmPrinter::EmitSLEB128(int Value, const char *Desc) const { 29 if (isVerbose() && Desc) 30 OutStreamer.AddComment(Desc); 31 32 if (MAI->hasLEB128()) { 33 // FIXME: MCize. 34 OutStreamer.EmitRawText("\t.sleb128\t" + Twine(Value)); 35 return; 36 } 37 38 // If we don't have .sleb128, emit as .bytes. 39 int Sign = Value >> (8 * sizeof(Value) - 1); 40 bool IsMore; 41 42 do { 43 unsigned char Byte = static_cast<unsigned char>(Value & 0x7f); 44 Value >>= 7; 45 IsMore = Value != Sign || ((Byte ^ Sign) & 0x40) != 0; 46 if (IsMore) Byte |= 0x80; 47 OutStreamer.EmitIntValue(Byte, 1, /*addrspace*/0); 48 } while (IsMore); 49} 50 51/// EmitULEB128 - emit the specified signed leb128 value. 52void AsmPrinter::EmitULEB128(unsigned Value, const char *Desc, 53 unsigned PadTo) const { 54 if (isVerbose() && Desc) 55 OutStreamer.AddComment(Desc); 56 57 if (MAI->hasLEB128() && PadTo == 0) { 58 // FIXME: MCize. 59 OutStreamer.EmitRawText("\t.uleb128\t" + Twine(Value)); 60 return; 61 } 62 63 // If we don't have .uleb128 or we want to emit padding, emit as .bytes. 64 do { 65 unsigned char Byte = static_cast<unsigned char>(Value & 0x7f); 66 Value >>= 7; 67 if (Value || PadTo != 0) Byte |= 0x80; 68 OutStreamer.EmitIntValue(Byte, 1, /*addrspace*/0); 69 } while (Value); 70 71 if (PadTo) { 72 if (PadTo > 1) 73 OutStreamer.EmitFill(PadTo - 1, 0x80/*fillval*/, 0/*addrspace*/); 74 OutStreamer.EmitFill(1, 0/*fillval*/, 0/*addrspace*/); 75 } 76} 77 78/// EmitCFAByte - Emit a .byte 42 directive for a DW_CFA_xxx value. 79void AsmPrinter::EmitCFAByte(unsigned Val) const { 80 if (isVerbose()) { 81 if (Val >= dwarf::DW_CFA_offset && Val < dwarf::DW_CFA_offset+64) 82 OutStreamer.AddComment("DW_CFA_offset + Reg (" + 83 Twine(Val-dwarf::DW_CFA_offset) + ")"); 84 else 85 OutStreamer.AddComment(dwarf::CallFrameString(Val)); 86 } 87 OutStreamer.EmitIntValue(Val, 1, 0/*addrspace*/); 88} 89 90static const char *DecodeDWARFEncoding(unsigned Encoding) { 91 switch (Encoding) { 92 case dwarf::DW_EH_PE_absptr: return "absptr"; 93 case dwarf::DW_EH_PE_omit: return "omit"; 94 case dwarf::DW_EH_PE_pcrel: return "pcrel"; 95 case dwarf::DW_EH_PE_udata4: return "udata4"; 96 case dwarf::DW_EH_PE_udata8: return "udata8"; 97 case dwarf::DW_EH_PE_sdata4: return "sdata4"; 98 case dwarf::DW_EH_PE_sdata8: return "sdata8"; 99 case dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_udata4: return "pcrel udata4"; 100 case dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4: return "pcrel sdata4"; 101 case dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_udata8: return "pcrel udata8"; 102 case dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata8: return "pcrel sdata8"; 103 case dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel |dwarf::DW_EH_PE_udata4: 104 return "indirect pcrel udata4"; 105 case dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel |dwarf::DW_EH_PE_sdata4: 106 return "indirect pcrel sdata4"; 107 case dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel |dwarf::DW_EH_PE_udata8: 108 return "indirect pcrel udata8"; 109 case dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel |dwarf::DW_EH_PE_sdata8: 110 return "indirect pcrel sdata8"; 111 } 112 113 return "<unknown encoding>"; 114} 115 116 117/// EmitEncodingByte - Emit a .byte 42 directive that corresponds to an 118/// encoding. If verbose assembly output is enabled, we output comments 119/// describing the encoding. Desc is an optional string saying what the 120/// encoding is specifying (e.g. "LSDA"). 121void AsmPrinter::EmitEncodingByte(unsigned Val, const char *Desc) { 122 if (isVerbose()) { 123 if (Desc != 0) 124 OutStreamer.AddComment(Twine(Desc)+" Encoding = " + 125 Twine(DecodeDWARFEncoding(Val))); 126 else 127 OutStreamer.AddComment(Twine("Encoding = ") + 128 DecodeDWARFEncoding(Val)); 129 } 130 131 OutStreamer.EmitIntValue(Val, 1, 0/*addrspace*/); 132} 133 134/// GetSizeOfEncodedValue - Return the size of the encoding in bytes. 135unsigned AsmPrinter::GetSizeOfEncodedValue(unsigned Encoding) const { 136 if (Encoding == dwarf::DW_EH_PE_omit) 137 return 0; 138 139 switch (Encoding & 0x07) { 140 default: assert(0 && "Invalid encoded value."); 141 case dwarf::DW_EH_PE_absptr: return TM.getTargetData()->getPointerSize(); 142 case dwarf::DW_EH_PE_udata2: return 2; 143 case dwarf::DW_EH_PE_udata4: return 4; 144 case dwarf::DW_EH_PE_udata8: return 8; 145 } 146} 147 148void AsmPrinter::EmitReference(const MCSymbol *Sym, unsigned Encoding) const { 149 const TargetLoweringObjectFile &TLOF = getObjFileLowering(); 150 151 const MCExpr *Exp = 152 TLOF.getExprForDwarfReference(Sym, Mang, MMI, Encoding, OutStreamer); 153 OutStreamer.EmitValue(Exp, GetSizeOfEncodedValue(Encoding), /*addrspace*/0); 154} 155 156void AsmPrinter::EmitReference(const GlobalValue *GV, unsigned Encoding)const{ 157 const TargetLoweringObjectFile &TLOF = getObjFileLowering(); 158 159 const MCExpr *Exp = 160 TLOF.getExprForDwarfGlobalReference(GV, Mang, MMI, Encoding, OutStreamer); 161 OutStreamer.EmitValue(Exp, GetSizeOfEncodedValue(Encoding), /*addrspace*/0); 162} 163 164/// EmitSectionOffset - Emit the 4-byte offset of Label from the start of its 165/// section. This can be done with a special directive if the target supports 166/// it (e.g. cygwin) or by emitting it as an offset from a label at the start 167/// of the section. 168/// 169/// SectionLabel is a temporary label emitted at the start of the section that 170/// Label lives in. 171void AsmPrinter::EmitSectionOffset(const MCSymbol *Label, 172 const MCSymbol *SectionLabel) const { 173 // On COFF targets, we have to emit the special .secrel32 directive. 174 if (const char *SecOffDir = MAI->getDwarfSectionOffsetDirective()) { 175 // FIXME: MCize. 176 OutStreamer.EmitRawText(SecOffDir + Twine(Label->getName())); 177 return; 178 } 179 180 // Get the section that we're referring to, based on SectionLabel. 181 const MCSection &Section = SectionLabel->getSection(); 182 183 // If Label has already been emitted, verify that it is in the same section as 184 // section label for sanity. 185 assert((!Label->isInSection() || &Label->getSection() == &Section) && 186 "Section offset using wrong section base for label"); 187 188 // If the section in question will end up with an address of 0 anyway, we can 189 // just emit an absolute reference to save a relocation. 190 if (Section.isBaseAddressKnownZero()) { 191 OutStreamer.EmitSymbolValue(Label, 4, 0/*AddrSpace*/); 192 return; 193 } 194 195 // Otherwise, emit it as a label difference from the start of the section. 196 EmitLabelDifference(Label, SectionLabel, 4); 197} 198 199 200