diff options
Diffstat (limited to 'lib/CodeGen/AsmPrinter/DwarfPrinter.cpp')
-rw-r--r-- | lib/CodeGen/AsmPrinter/DwarfPrinter.cpp | 214 |
1 files changed, 158 insertions, 56 deletions
diff --git a/lib/CodeGen/AsmPrinter/DwarfPrinter.cpp b/lib/CodeGen/AsmPrinter/DwarfPrinter.cpp index 20b959b..d204bba 100644 --- a/lib/CodeGen/AsmPrinter/DwarfPrinter.cpp +++ b/lib/CodeGen/AsmPrinter/DwarfPrinter.cpp @@ -18,21 +18,22 @@ #include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineModuleInfo.h" #include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCStreamer.h" +#include "llvm/MC/MCSymbol.h" #include "llvm/Target/TargetData.h" #include "llvm/Target/TargetFrameInfo.h" #include "llvm/Target/TargetRegisterInfo.h" #include "llvm/Support/Dwarf.h" #include "llvm/Support/ErrorHandling.h" -#include "llvm/ADT/StringExtras.h" using namespace llvm; -Dwarf::Dwarf(raw_ostream &OS, AsmPrinter *A, const MCAsmInfo *T, - const char *flavor) +DwarfPrinter::DwarfPrinter(raw_ostream &OS, AsmPrinter *A, const MCAsmInfo *T, + const char *flavor) : O(OS), Asm(A), MAI(T), TD(Asm->TM.getTargetData()), RI(Asm->TM.getRegisterInfo()), M(NULL), MF(NULL), MMI(NULL), SubprogramCount(0), Flavor(flavor), SetCounter(1) {} -void Dwarf::PrintRelDirective(bool Force32Bit, bool isInSection) const { +void DwarfPrinter::PrintRelDirective(bool Force32Bit, bool isInSection) const { if (isInSection && MAI->getDwarfSectionOffsetDirective()) O << MAI->getDwarfSectionOffsetDirective(); else if (Force32Bit || TD->getPointerSize() == sizeof(int32_t)) @@ -41,14 +42,125 @@ void Dwarf::PrintRelDirective(bool Force32Bit, bool isInSection) const { O << MAI->getData64bitsDirective(); } +/// EOL - Print a newline character to asm stream. If a comment is present +/// then it will be printed first. Comments should not contain '\n'. +void DwarfPrinter::EOL(const Twine &Comment) const { + if (Asm->VerboseAsm && !Comment.isTriviallyEmpty()) { + Asm->O.PadToColumn(MAI->getCommentColumn()); + Asm->O << Asm->MAI->getCommentString() << ' ' << Comment; + } + Asm->O << '\n'; +} + +static const char *DecodeDWARFEncoding(unsigned Encoding) { + switch (Encoding) { + case dwarf::DW_EH_PE_absptr: return "absptr"; + case dwarf::DW_EH_PE_omit: return "omit"; + case dwarf::DW_EH_PE_pcrel: return "pcrel"; + case dwarf::DW_EH_PE_udata4: return "udata4"; + case dwarf::DW_EH_PE_udata8: return "udata8"; + case dwarf::DW_EH_PE_sdata4: return "sdata4"; + case dwarf::DW_EH_PE_sdata8: return "sdata8"; + case dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_udata4: return "pcrel udata4"; + case dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4: return "pcrel sdata4"; + case dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_udata8: return "pcrel udata8"; + case dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata8: return "pcrel sdata8"; + case dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel |dwarf::DW_EH_PE_udata4: + return "indirect pcrel udata4"; + case dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel |dwarf::DW_EH_PE_sdata4: + return "indirect pcrel sdata4"; + case dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel |dwarf::DW_EH_PE_udata8: + return "indirect pcrel udata8"; + case dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel |dwarf::DW_EH_PE_sdata8: + return "indirect pcrel sdata8"; + } + + return "<unknown encoding>"; +} + +/// EmitEncodingByte - Emit a .byte 42 directive that corresponds to an +/// encoding. If verbose assembly output is enabled, we output comments +/// describing the encoding. Desc is an optional string saying what the +/// encoding is specifying (e.g. "LSDA"). +void DwarfPrinter::EmitEncodingByte(unsigned Val, const char *Desc) { + if (Asm->VerboseAsm) { + if (Desc != 0) + Asm->OutStreamer.AddComment(Twine(Desc)+" Encoding = " + + Twine(DecodeDWARFEncoding(Val))); + else + Asm->OutStreamer.AddComment(Twine("Encoding = ") + + DecodeDWARFEncoding(Val)); + } + + Asm->OutStreamer.EmitIntValue(Val, 1, 0/*addrspace*/); +} + +/// EmitCFAByte - Emit a .byte 42 directive for a DW_CFA_xxx value. +void DwarfPrinter::EmitCFAByte(unsigned Val) { + if (Asm->VerboseAsm) { + if (Val >= dwarf::DW_CFA_offset && Val < dwarf::DW_CFA_offset+64) + Asm->OutStreamer.AddComment("DW_CFA_offset + Reg (" + + Twine(Val-dwarf::DW_CFA_offset) + ")"); + else + Asm->OutStreamer.AddComment(dwarf::CallFrameString(Val)); + } + Asm->OutStreamer.EmitIntValue(Val, 1, 0/*addrspace*/); +} + +/// EmitSLEB128 - emit the specified signed leb128 value. +void DwarfPrinter::EmitSLEB128(int Value, const char *Desc) const { + if (Asm->VerboseAsm && Desc) + Asm->OutStreamer.AddComment(Desc); + + if (MAI->hasLEB128()) { + O << "\t.sleb128\t" << Value; + Asm->OutStreamer.AddBlankLine(); + return; + } + + // If we don't have .sleb128, emit as .bytes. + int Sign = Value >> (8 * sizeof(Value) - 1); + bool IsMore; + + do { + unsigned char Byte = static_cast<unsigned char>(Value & 0x7f); + Value >>= 7; + IsMore = Value != Sign || ((Byte ^ Sign) & 0x40) != 0; + if (IsMore) Byte |= 0x80; + + Asm->OutStreamer.EmitIntValue(Byte, 1, /*addrspace*/0); + } while (IsMore); +} + +/// EmitULEB128 - emit the specified signed leb128 value. +void DwarfPrinter::EmitULEB128(unsigned Value, const char *Desc) const { + if (Asm->VerboseAsm && Desc) + Asm->OutStreamer.AddComment(Desc); + + if (MAI->hasLEB128()) { + O << "\t.uleb128\t" << Value; + Asm->OutStreamer.AddBlankLine(); + return; + } + + // If we don't have .uleb128, emit as .bytes. + do { + unsigned char Byte = static_cast<unsigned char>(Value & 0x7f); + Value >>= 7; + if (Value) Byte |= 0x80; + Asm->OutStreamer.EmitIntValue(Byte, 1, /*addrspace*/0); + } while (Value); +} + + /// PrintLabelName - Print label name in form used by Dwarf writer. /// -void Dwarf::PrintLabelName(const char *Tag, unsigned Number) const { +void DwarfPrinter::PrintLabelName(const char *Tag, unsigned Number) const { O << MAI->getPrivateGlobalPrefix() << Tag; if (Number) O << Number; } -void Dwarf::PrintLabelName(const char *Tag, unsigned Number, - const char *Suffix) const { +void DwarfPrinter::PrintLabelName(const char *Tag, unsigned Number, + const char *Suffix) const { O << MAI->getPrivateGlobalPrefix() << Tag; if (Number) O << Number; O << Suffix; @@ -56,32 +168,39 @@ void Dwarf::PrintLabelName(const char *Tag, unsigned Number, /// EmitLabel - Emit location label for internal use by Dwarf. /// -void Dwarf::EmitLabel(const char *Tag, unsigned Number) const { +void DwarfPrinter::EmitLabel(const char *Tag, unsigned Number) const { PrintLabelName(Tag, Number); O << ":\n"; } /// EmitReference - Emit a reference to a label. /// -void Dwarf::EmitReference(const char *Tag, unsigned Number, - bool IsPCRelative, bool Force32Bit) const { +void DwarfPrinter::EmitReference(const char *Tag, unsigned Number, + bool IsPCRelative, bool Force32Bit) const { PrintRelDirective(Force32Bit); PrintLabelName(Tag, Number); if (IsPCRelative) O << "-" << MAI->getPCSymbol(); } -void Dwarf::EmitReference(const std::string &Name, bool IsPCRelative, - bool Force32Bit) const { +void DwarfPrinter::EmitReference(const std::string &Name, bool IsPCRelative, + bool Force32Bit) const { PrintRelDirective(Force32Bit); O << Name; if (IsPCRelative) O << "-" << MAI->getPCSymbol(); } +void DwarfPrinter::EmitReference(const MCSymbol *Sym, bool IsPCRelative, + bool Force32Bit) const { + PrintRelDirective(Force32Bit); + O << *Sym; + if (IsPCRelative) O << "-" << MAI->getPCSymbol(); +} + /// EmitDifference - Emit the difference between two labels. Some assemblers do /// not behave with absolute expressions with data directives, so there is an /// option (needsSet) to use an intermediary set expression. -void Dwarf::EmitDifference(const char *TagHi, unsigned NumberHi, - const char *TagLo, unsigned NumberLo, - bool IsSmall) { +void DwarfPrinter::EmitDifference(const char *TagHi, unsigned NumberHi, + const char *TagLo, unsigned NumberLo, + bool IsSmall) { if (MAI->needsSet()) { O << "\t.set\t"; PrintLabelName("set", SetCounter, Flavor); @@ -102,10 +221,11 @@ void Dwarf::EmitDifference(const char *TagHi, unsigned NumberHi, } } -void Dwarf::EmitSectionOffset(const char* Label, const char* Section, - unsigned LabelNumber, unsigned SectionNumber, - bool IsSmall, bool isEH, - bool useSet) { +void DwarfPrinter::EmitSectionOffset(const char* Label, const char* Section, + unsigned LabelNumber, + unsigned SectionNumber, + bool IsSmall, bool isEH, + bool useSet) { bool printAbsolute = false; if (isEH) printAbsolute = MAI->isAbsoluteEHSectionOffsets(); @@ -140,8 +260,9 @@ void Dwarf::EmitSectionOffset(const char* Label, const char* Section, /// EmitFrameMoves - Emit frame instructions to describe the layout of the /// frame. -void Dwarf::EmitFrameMoves(const char *BaseLabel, unsigned BaseLabelID, - const std::vector<MachineMove> &Moves, bool isEH) { +void DwarfPrinter::EmitFrameMoves(const char *BaseLabel, unsigned BaseLabelID, + const std::vector<MachineMove> &Moves, + bool isEH) { int stackGrowth = Asm->TM.getFrameInfo()->getStackGrowthDirection() == TargetFrameInfo::StackGrowsUp ? @@ -164,10 +285,9 @@ void Dwarf::EmitFrameMoves(const char *BaseLabel, unsigned BaseLabelID, // Advance row if new location. if (BaseLabel && LabelID && (BaseLabelID != LabelID || !IsLocal)) { - Asm->EmitInt8(dwarf::DW_CFA_advance_loc4); - Asm->EOL("DW_CFA_advance_loc4"); + EmitCFAByte(dwarf::DW_CFA_advance_loc4); EmitDifference("label", LabelID, BaseLabel, BaseLabelID, true); - Asm->EOL(); + Asm->O << '\n'; BaseLabelID = LabelID; BaseLabel = "label"; @@ -178,29 +298,22 @@ void Dwarf::EmitFrameMoves(const char *BaseLabel, unsigned BaseLabelID, if (Dst.isReg() && Dst.getReg() == MachineLocation::VirtualFP) { if (!Src.isReg()) { if (Src.getReg() == MachineLocation::VirtualFP) { - Asm->EmitInt8(dwarf::DW_CFA_def_cfa_offset); - Asm->EOL("DW_CFA_def_cfa_offset"); + EmitCFAByte(dwarf::DW_CFA_def_cfa_offset); } else { - Asm->EmitInt8(dwarf::DW_CFA_def_cfa); - Asm->EOL("DW_CFA_def_cfa"); - Asm->EmitULEB128Bytes(RI->getDwarfRegNum(Src.getReg(), isEH)); - Asm->EOL("Register"); + EmitCFAByte(dwarf::DW_CFA_def_cfa); + EmitULEB128(RI->getDwarfRegNum(Src.getReg(), isEH), "Register"); } int Offset = -Src.getOffset(); - - Asm->EmitULEB128Bytes(Offset); - Asm->EOL("Offset"); + EmitULEB128(Offset, "Offset"); } else { llvm_unreachable("Machine move not supported yet."); } } else if (Src.isReg() && Src.getReg() == MachineLocation::VirtualFP) { if (Dst.isReg()) { - Asm->EmitInt8(dwarf::DW_CFA_def_cfa_register); - Asm->EOL("DW_CFA_def_cfa_register"); - Asm->EmitULEB128Bytes(RI->getDwarfRegNum(Dst.getReg(), isEH)); - Asm->EOL("Register"); + EmitCFAByte(dwarf::DW_CFA_def_cfa_register); + EmitULEB128(RI->getDwarfRegNum(Dst.getReg(), isEH), "Register"); } else { llvm_unreachable("Machine move not supported yet."); } @@ -209,27 +322,16 @@ void Dwarf::EmitFrameMoves(const char *BaseLabel, unsigned BaseLabelID, int Offset = Dst.getOffset() / stackGrowth; if (Offset < 0) { - Asm->EmitInt8(dwarf::DW_CFA_offset_extended_sf); - Asm->EOL("DW_CFA_offset_extended_sf"); - Asm->EmitULEB128Bytes(Reg); - Asm->EOL("Reg"); - Asm->EmitSLEB128Bytes(Offset); - Asm->EOL("Offset"); + EmitCFAByte(dwarf::DW_CFA_offset_extended_sf); + EmitULEB128(Reg, "Reg"); + EmitSLEB128(Offset, "Offset"); } else if (Reg < 64) { - Asm->EmitInt8(dwarf::DW_CFA_offset + Reg); - if (Asm->isVerbose()) - Asm->EOL("DW_CFA_offset + Reg (" + utostr(Reg) + ")"); - else - Asm->EOL(); - Asm->EmitULEB128Bytes(Offset); - Asm->EOL("Offset"); + EmitCFAByte(dwarf::DW_CFA_offset + Reg); + EmitULEB128(Offset, "Offset"); } else { - Asm->EmitInt8(dwarf::DW_CFA_offset_extended); - Asm->EOL("DW_CFA_offset_extended"); - Asm->EmitULEB128Bytes(Reg); - Asm->EOL("Reg"); - Asm->EmitULEB128Bytes(Offset); - Asm->EOL("Offset"); + EmitCFAByte(dwarf::DW_CFA_offset_extended); + EmitULEB128(Reg, "Reg"); + EmitULEB128(Offset, "Offset"); } } } |