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