summaryrefslogtreecommitdiffstats
path: root/lib/CodeGen/AsmPrinter/DwarfPrinter.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/CodeGen/AsmPrinter/DwarfPrinter.cpp')
-rw-r--r--lib/CodeGen/AsmPrinter/DwarfPrinter.cpp214
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");
}
}
}
OpenPOWER on IntegriCloud