summaryrefslogtreecommitdiffstats
path: root/contrib/llvm/lib/MC/MCDwarf.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm/lib/MC/MCDwarf.cpp')
-rw-r--r--contrib/llvm/lib/MC/MCDwarf.cpp459
1 files changed, 414 insertions, 45 deletions
diff --git a/contrib/llvm/lib/MC/MCDwarf.cpp b/contrib/llvm/lib/MC/MCDwarf.cpp
index 4658a30..84a34f1 100644
--- a/contrib/llvm/lib/MC/MCDwarf.cpp
+++ b/contrib/llvm/lib/MC/MCDwarf.cpp
@@ -19,10 +19,12 @@
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"
-#include "llvm/ADT/FoldingSet.h"
+#include "llvm/Support/Path.h"
+#include "llvm/Support/SourceMgr.h"
+#include "llvm/ADT/Hashing.h"
#include "llvm/ADT/SmallString.h"
-#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/Twine.h"
+#include "llvm/Config/config.h"
using namespace llvm;
// Given a special op, return the address skip amount (in units of
@@ -207,7 +209,7 @@ static inline void EmitDwarfLineTable(MCStreamer *MCOS,
//
// This emits the Dwarf file and the line tables.
//
-void MCDwarfFileTable::Emit(MCStreamer *MCOS) {
+const MCSymbol *MCDwarfFileTable::Emit(MCStreamer *MCOS) {
MCContext &context = MCOS->getContext();
// Switch to the section where the table will be emitted into.
MCOS->SwitchSection(context.getObjectFileInfo()->getDwarfLineSection());
@@ -320,6 +322,8 @@ void MCDwarfFileTable::Emit(MCStreamer *MCOS) {
// This is the end of the section, so set the value of the symbol at the end
// of this section (that was used in a previous expression).
MCOS->EmitLabel(LineEndSym);
+
+ return LineStartSym;
}
/// Utility function to write the encoding to an object writer.
@@ -372,10 +376,7 @@ void MCDwarfLineAddr::Encode(int64_t LineDelta, uint64_t AddrDelta,
// it with DW_LNS_advance_line.
if (Temp >= DWARF2_LINE_RANGE) {
OS << char(dwarf::DW_LNS_advance_line);
- SmallString<32> Tmp;
- raw_svector_ostream OSE(Tmp);
- MCObjectWriter::EncodeSLEB128(LineDelta, OSE);
- OS << OSE.str();
+ MCObjectWriter::EncodeSLEB128(LineDelta, OS);
LineDelta = 0;
Temp = 0 - DWARF2_LINE_BASE;
@@ -411,10 +412,7 @@ void MCDwarfLineAddr::Encode(int64_t LineDelta, uint64_t AddrDelta,
// Otherwise use DW_LNS_advance_pc.
OS << char(dwarf::DW_LNS_advance_pc);
- SmallString<32> Tmp;
- raw_svector_ostream OSE(Tmp);
- MCObjectWriter::EncodeULEB128(AddrDelta, OSE);
- OS << OSE.str();
+ MCObjectWriter::EncodeULEB128(AddrDelta, OS);
if (NeedCopy)
OS << char(dwarf::DW_LNS_copy);
@@ -430,6 +428,349 @@ void MCDwarfFile::dump() const {
print(dbgs());
}
+// Utility function to write a tuple for .debug_abbrev.
+static void EmitAbbrev(MCStreamer *MCOS, uint64_t Name, uint64_t Form) {
+ MCOS->EmitULEB128IntValue(Name);
+ MCOS->EmitULEB128IntValue(Form);
+}
+
+// When generating dwarf for assembly source files this emits
+// the data for .debug_abbrev section which contains three DIEs.
+static void EmitGenDwarfAbbrev(MCStreamer *MCOS) {
+ MCContext &context = MCOS->getContext();
+ MCOS->SwitchSection(context.getObjectFileInfo()->getDwarfAbbrevSection());
+
+ // DW_TAG_compile_unit DIE abbrev (1).
+ MCOS->EmitULEB128IntValue(1);
+ MCOS->EmitULEB128IntValue(dwarf::DW_TAG_compile_unit);
+ MCOS->EmitIntValue(dwarf::DW_CHILDREN_yes, 1);
+ EmitAbbrev(MCOS, dwarf::DW_AT_stmt_list, dwarf::DW_FORM_data4);
+ EmitAbbrev(MCOS, dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr);
+ EmitAbbrev(MCOS, dwarf::DW_AT_high_pc, dwarf::DW_FORM_addr);
+ EmitAbbrev(MCOS, dwarf::DW_AT_name, dwarf::DW_FORM_string);
+ EmitAbbrev(MCOS, dwarf::DW_AT_comp_dir, dwarf::DW_FORM_string);
+ StringRef DwarfDebugFlags = context.getDwarfDebugFlags();
+ if (!DwarfDebugFlags.empty())
+ EmitAbbrev(MCOS, dwarf::DW_AT_APPLE_flags, dwarf::DW_FORM_string);
+ EmitAbbrev(MCOS, dwarf::DW_AT_producer, dwarf::DW_FORM_string);
+ EmitAbbrev(MCOS, dwarf::DW_AT_language, dwarf::DW_FORM_data2);
+ EmitAbbrev(MCOS, 0, 0);
+
+ // DW_TAG_label DIE abbrev (2).
+ MCOS->EmitULEB128IntValue(2);
+ MCOS->EmitULEB128IntValue(dwarf::DW_TAG_label);
+ MCOS->EmitIntValue(dwarf::DW_CHILDREN_yes, 1);
+ EmitAbbrev(MCOS, dwarf::DW_AT_name, dwarf::DW_FORM_string);
+ EmitAbbrev(MCOS, dwarf::DW_AT_decl_file, dwarf::DW_FORM_data4);
+ EmitAbbrev(MCOS, dwarf::DW_AT_decl_line, dwarf::DW_FORM_data4);
+ EmitAbbrev(MCOS, dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr);
+ EmitAbbrev(MCOS, dwarf::DW_AT_prototyped, dwarf::DW_FORM_flag);
+ EmitAbbrev(MCOS, 0, 0);
+
+ // DW_TAG_unspecified_parameters DIE abbrev (3).
+ MCOS->EmitULEB128IntValue(3);
+ MCOS->EmitULEB128IntValue(dwarf::DW_TAG_unspecified_parameters);
+ MCOS->EmitIntValue(dwarf::DW_CHILDREN_no, 1);
+ EmitAbbrev(MCOS, 0, 0);
+
+ // Terminate the abbreviations for this compilation unit.
+ MCOS->EmitIntValue(0, 1);
+}
+
+// When generating dwarf for assembly source files this emits the data for
+// .debug_aranges section. Which contains a header and a table of pairs of
+// PointerSize'ed values for the address and size of section(s) with line table
+// entries (just the default .text in our case) and a terminating pair of zeros.
+static void EmitGenDwarfAranges(MCStreamer *MCOS) {
+ MCContext &context = MCOS->getContext();
+
+ // Create a symbol at the end of the section that we are creating the dwarf
+ // debugging info to use later in here as part of the expression to calculate
+ // the size of the section for the table.
+ MCOS->SwitchSection(context.getGenDwarfSection());
+ MCSymbol *SectionEndSym = context.CreateTempSymbol();
+ MCOS->EmitLabel(SectionEndSym);
+ context.setGenDwarfSectionEndSym(SectionEndSym);
+
+ MCOS->SwitchSection(context.getObjectFileInfo()->getDwarfARangesSection());
+
+ // This will be the length of the .debug_aranges section, first account for
+ // the size of each item in the header (see below where we emit these items).
+ int Length = 4 + 2 + 4 + 1 + 1;
+
+ // Figure the padding after the header before the table of address and size
+ // pairs who's values are PointerSize'ed.
+ const MCAsmInfo &asmInfo = context.getAsmInfo();
+ int AddrSize = asmInfo.getPointerSize();
+ int Pad = 2 * AddrSize - (Length & (2 * AddrSize - 1));
+ if (Pad == 2 * AddrSize)
+ Pad = 0;
+ Length += Pad;
+
+ // Add the size of the pair of PointerSize'ed values for the address and size
+ // of the one default .text section we have in the table.
+ Length += 2 * AddrSize;
+ // And the pair of terminating zeros.
+ Length += 2 * AddrSize;
+
+
+ // Emit the header for this section.
+ // The 4 byte length not including the 4 byte value for the length.
+ MCOS->EmitIntValue(Length - 4, 4);
+ // The 2 byte version, which is 2.
+ MCOS->EmitIntValue(2, 2);
+ // The 4 byte offset to the compile unit in the .debug_info from the start
+ // of the .debug_info, it is at the start of that section so this is zero.
+ MCOS->EmitIntValue(0, 4);
+ // The 1 byte size of an address.
+ MCOS->EmitIntValue(AddrSize, 1);
+ // The 1 byte size of a segment descriptor, we use a value of zero.
+ MCOS->EmitIntValue(0, 1);
+ // Align the header with the padding if needed, before we put out the table.
+ for(int i = 0; i < Pad; i++)
+ MCOS->EmitIntValue(0, 1);
+
+ // Now emit the table of pairs of PointerSize'ed values for the section(s)
+ // address and size, in our case just the one default .text section.
+ const MCExpr *Addr = MCSymbolRefExpr::Create(
+ context.getGenDwarfSectionStartSym(), MCSymbolRefExpr::VK_None, context);
+ const MCExpr *Size = MakeStartMinusEndExpr(*MCOS,
+ *context.getGenDwarfSectionStartSym(), *SectionEndSym, 0);
+ MCOS->EmitAbsValue(Addr, AddrSize);
+ MCOS->EmitAbsValue(Size, AddrSize);
+
+ // And finally the pair of terminating zeros.
+ MCOS->EmitIntValue(0, AddrSize);
+ MCOS->EmitIntValue(0, AddrSize);
+}
+
+// When generating dwarf for assembly source files this emits the data for
+// .debug_info section which contains three parts. The header, the compile_unit
+// DIE and a list of label DIEs.
+static void EmitGenDwarfInfo(MCStreamer *MCOS,
+ const MCSymbol *AbbrevSectionSymbol,
+ const MCSymbol *LineSectionSymbol) {
+ MCContext &context = MCOS->getContext();
+
+ MCOS->SwitchSection(context.getObjectFileInfo()->getDwarfInfoSection());
+
+ // Create a symbol at the start and end of this section used in here for the
+ // expression to calculate the length in the header.
+ MCSymbol *InfoStart = context.CreateTempSymbol();
+ MCOS->EmitLabel(InfoStart);
+ MCSymbol *InfoEnd = context.CreateTempSymbol();
+
+ // First part: the header.
+
+ // The 4 byte total length of the information for this compilation unit, not
+ // including these 4 bytes.
+ const MCExpr *Length = MakeStartMinusEndExpr(*MCOS, *InfoStart, *InfoEnd, 4);
+ MCOS->EmitAbsValue(Length, 4);
+
+ // The 2 byte DWARF version, which is 2.
+ MCOS->EmitIntValue(2, 2);
+
+ // The 4 byte offset to the debug abbrevs from the start of the .debug_abbrev,
+ // it is at the start of that section so this is zero.
+ if (AbbrevSectionSymbol) {
+ MCOS->EmitSymbolValue(AbbrevSectionSymbol, 4);
+ } else {
+ MCOS->EmitIntValue(0, 4);
+ }
+
+ const MCAsmInfo &asmInfo = context.getAsmInfo();
+ int AddrSize = asmInfo.getPointerSize();
+ // The 1 byte size of an address.
+ MCOS->EmitIntValue(AddrSize, 1);
+
+ // Second part: the compile_unit DIE.
+
+ // The DW_TAG_compile_unit DIE abbrev (1).
+ MCOS->EmitULEB128IntValue(1);
+
+ // DW_AT_stmt_list, a 4 byte offset from the start of the .debug_line section,
+ // which is at the start of that section so this is zero.
+ if (LineSectionSymbol) {
+ MCOS->EmitSymbolValue(LineSectionSymbol, 4);
+ } else {
+ MCOS->EmitIntValue(0, 4);
+ }
+
+ // AT_low_pc, the first address of the default .text section.
+ const MCExpr *Start = MCSymbolRefExpr::Create(
+ context.getGenDwarfSectionStartSym(), MCSymbolRefExpr::VK_None, context);
+ MCOS->EmitAbsValue(Start, AddrSize);
+
+ // AT_high_pc, the last address of the default .text section.
+ const MCExpr *End = MCSymbolRefExpr::Create(
+ context.getGenDwarfSectionEndSym(), MCSymbolRefExpr::VK_None, context);
+ MCOS->EmitAbsValue(End, AddrSize);
+
+ // AT_name, the name of the source file. Reconstruct from the first directory
+ // and file table entries.
+ const std::vector<StringRef> &MCDwarfDirs =
+ context.getMCDwarfDirs();
+ if (MCDwarfDirs.size() > 0) {
+ MCOS->EmitBytes(MCDwarfDirs[0], 0);
+ MCOS->EmitBytes("/", 0);
+ }
+ const std::vector<MCDwarfFile *> &MCDwarfFiles =
+ MCOS->getContext().getMCDwarfFiles();
+ MCOS->EmitBytes(MCDwarfFiles[1]->getName(), 0);
+ MCOS->EmitIntValue(0, 1); // NULL byte to terminate the string.
+
+ // AT_comp_dir, the working directory the assembly was done in.
+ llvm::sys::Path CWD = llvm::sys::Path::GetCurrentDirectory();
+ MCOS->EmitBytes(StringRef(CWD.c_str()), 0);
+ MCOS->EmitIntValue(0, 1); // NULL byte to terminate the string.
+
+ // AT_APPLE_flags, the command line arguments of the assembler tool.
+ StringRef DwarfDebugFlags = context.getDwarfDebugFlags();
+ if (!DwarfDebugFlags.empty()){
+ MCOS->EmitBytes(DwarfDebugFlags, 0);
+ MCOS->EmitIntValue(0, 1); // NULL byte to terminate the string.
+ }
+
+ // AT_producer, the version of the assembler tool.
+ MCOS->EmitBytes(StringRef("llvm-mc (based on LLVM "), 0);
+ MCOS->EmitBytes(StringRef(PACKAGE_VERSION), 0);
+ MCOS->EmitBytes(StringRef(")"), 0);
+ MCOS->EmitIntValue(0, 1); // NULL byte to terminate the string.
+
+ // AT_language, a 4 byte value. We use DW_LANG_Mips_Assembler as the dwarf2
+ // draft has no standard code for assembler.
+ MCOS->EmitIntValue(dwarf::DW_LANG_Mips_Assembler, 2);
+
+ // Third part: the list of label DIEs.
+
+ // Loop on saved info for dwarf labels and create the DIEs for them.
+ const std::vector<const MCGenDwarfLabelEntry *> &Entries =
+ MCOS->getContext().getMCGenDwarfLabelEntries();
+ for (std::vector<const MCGenDwarfLabelEntry *>::const_iterator it =
+ Entries.begin(), ie = Entries.end(); it != ie;
+ ++it) {
+ const MCGenDwarfLabelEntry *Entry = *it;
+
+ // The DW_TAG_label DIE abbrev (2).
+ MCOS->EmitULEB128IntValue(2);
+
+ // AT_name, of the label without any leading underbar.
+ MCOS->EmitBytes(Entry->getName(), 0);
+ MCOS->EmitIntValue(0, 1); // NULL byte to terminate the string.
+
+ // AT_decl_file, index into the file table.
+ MCOS->EmitIntValue(Entry->getFileNumber(), 4);
+
+ // AT_decl_line, source line number.
+ MCOS->EmitIntValue(Entry->getLineNumber(), 4);
+
+ // AT_low_pc, start address of the label.
+ const MCExpr *AT_low_pc = MCSymbolRefExpr::Create(Entry->getLabel(),
+ MCSymbolRefExpr::VK_None, context);
+ MCOS->EmitAbsValue(AT_low_pc, AddrSize);
+
+ // DW_AT_prototyped, a one byte flag value of 0 saying we have no prototype.
+ MCOS->EmitIntValue(0, 1);
+
+ // The DW_TAG_unspecified_parameters DIE abbrev (3).
+ MCOS->EmitULEB128IntValue(3);
+
+ // Add the NULL DIE terminating the DW_TAG_unspecified_parameters DIE's.
+ MCOS->EmitIntValue(0, 1);
+ }
+ // Deallocate the MCGenDwarfLabelEntry classes that saved away the info
+ // for the dwarf labels.
+ for (std::vector<const MCGenDwarfLabelEntry *>::const_iterator it =
+ Entries.begin(), ie = Entries.end(); it != ie;
+ ++it) {
+ const MCGenDwarfLabelEntry *Entry = *it;
+ delete Entry;
+ }
+
+ // Add the NULL DIE terminating the Compile Unit DIE's.
+ MCOS->EmitIntValue(0, 1);
+
+ // Now set the value of the symbol at the end of the info section.
+ MCOS->EmitLabel(InfoEnd);
+}
+
+//
+// When generating dwarf for assembly source files this emits the Dwarf
+// sections.
+//
+void MCGenDwarfInfo::Emit(MCStreamer *MCOS, const MCSymbol *LineSectionSymbol) {
+ // Create the dwarf sections in this order (.debug_line already created).
+ MCContext &context = MCOS->getContext();
+ const MCAsmInfo &AsmInfo = context.getAsmInfo();
+ MCOS->SwitchSection(context.getObjectFileInfo()->getDwarfInfoSection());
+ MCOS->SwitchSection(context.getObjectFileInfo()->getDwarfAbbrevSection());
+ MCSymbol *AbbrevSectionSymbol;
+ if (AsmInfo.doesDwarfRequireRelocationForSectionOffset()) {
+ AbbrevSectionSymbol = context.CreateTempSymbol();
+ MCOS->EmitLabel(AbbrevSectionSymbol);
+ } else {
+ AbbrevSectionSymbol = NULL;
+ LineSectionSymbol = NULL;
+ }
+ MCOS->SwitchSection(context.getObjectFileInfo()->getDwarfARangesSection());
+
+ // If there are no line table entries then do not emit any section contents.
+ if (context.getMCLineSections().empty())
+ return;
+
+ // Output the data for .debug_aranges section.
+ EmitGenDwarfAranges(MCOS);
+
+ // Output the data for .debug_abbrev section.
+ EmitGenDwarfAbbrev(MCOS);
+
+ // Output the data for .debug_info section.
+ EmitGenDwarfInfo(MCOS, AbbrevSectionSymbol, LineSectionSymbol);
+}
+
+//
+// When generating dwarf for assembly source files this is called when symbol
+// for a label is created. If this symbol is not a temporary and is in the
+// section that dwarf is being generated for, save the needed info to create
+// a dwarf label.
+//
+void MCGenDwarfLabelEntry::Make(MCSymbol *Symbol, MCStreamer *MCOS,
+ SourceMgr &SrcMgr, SMLoc &Loc) {
+ // We won't create dwarf labels for temporary symbols or symbols not in
+ // the default text.
+ if (Symbol->isTemporary())
+ return;
+ MCContext &context = MCOS->getContext();
+ if (context.getGenDwarfSection() != MCOS->getCurrentSection())
+ return;
+
+ // The dwarf label's name does not have the symbol name's leading
+ // underbar if any.
+ StringRef Name = Symbol->getName();
+ if (Name.startswith("_"))
+ Name = Name.substr(1, Name.size()-1);
+
+ // Get the dwarf file number to be used for the dwarf label.
+ unsigned FileNumber = context.getGenDwarfFileNumber();
+
+ // Finding the line number is the expensive part which is why we just don't
+ // pass it in as for some symbols we won't create a dwarf label.
+ int CurBuffer = SrcMgr.FindBufferContainingLoc(Loc);
+ unsigned LineNumber = SrcMgr.FindLineNumber(Loc, CurBuffer);
+
+ // We create a temporary symbol for use for the AT_high_pc and AT_low_pc
+ // values so that they don't have things like an ARM thumb bit from the
+ // original symbol. So when used they won't get a low bit set after
+ // relocation.
+ MCSymbol *Label = context.CreateTempSymbol();
+ MCOS->EmitLabel(Label);
+
+ // Create and entry for the info and add it to the other entries.
+ MCGenDwarfLabelEntry *Entry =
+ new MCGenDwarfLabelEntry(Name, FileNumber, LineNumber, Label);
+ MCOS->getContext().addMCGenDwarfLabelEntry(Entry);
+}
+
static int getDataAlignmentFactor(MCStreamer &streamer) {
MCContext &context = streamer.getContext();
const MCAsmInfo &asmInfo = context.getAsmInfo();
@@ -445,8 +786,7 @@ static unsigned getSizeForEncoding(MCStreamer &streamer,
MCContext &context = streamer.getContext();
unsigned format = symbolEncoding & 0x0f;
switch (format) {
- default:
- assert(0 && "Unknown Encoding");
+ default: llvm_unreachable("Unknown Encoding");
case dwarf::DW_EH_PE_absptr:
case dwarf::DW_EH_PE_signed:
return context.getAsmInfo().getPointerSize();
@@ -520,6 +860,7 @@ namespace {
const MCSymbol *personality,
unsigned personalityEncoding,
const MCSymbol *lsda,
+ bool IsSignalFrame,
unsigned lsdaEncoding);
MCSymbol *EmitFDE(MCStreamer &streamer,
const MCSymbol &cieStart,
@@ -536,28 +877,40 @@ namespace {
static void EmitEncodingByte(MCStreamer &Streamer, unsigned Encoding,
StringRef Prefix) {
if (Streamer.isVerboseAsm()) {
- const char *EncStr = 0;
+ const char *EncStr;
switch (Encoding) {
- default: EncStr = "<unknown encoding>";
- case dwarf::DW_EH_PE_absptr: EncStr = "absptr";
- case dwarf::DW_EH_PE_omit: EncStr = "omit";
- case dwarf::DW_EH_PE_pcrel: EncStr = "pcrel";
- case dwarf::DW_EH_PE_udata4: EncStr = "udata4";
- case dwarf::DW_EH_PE_udata8: EncStr = "udata8";
- case dwarf::DW_EH_PE_sdata4: EncStr = "sdata4";
- case dwarf::DW_EH_PE_sdata8: EncStr = "sdata8";
- case dwarf::DW_EH_PE_pcrel |dwarf::DW_EH_PE_udata4: EncStr = "pcrel udata4";
- case dwarf::DW_EH_PE_pcrel |dwarf::DW_EH_PE_sdata4: EncStr = "pcrel sdata4";
- case dwarf::DW_EH_PE_pcrel |dwarf::DW_EH_PE_udata8: EncStr = "pcrel udata8";
- case dwarf::DW_EH_PE_pcrel |dwarf::DW_EH_PE_sdata8: EncStr = "pcrel sdata8";
+ default: EncStr = "<unknown encoding>"; break;
+ case dwarf::DW_EH_PE_absptr: EncStr = "absptr"; break;
+ case dwarf::DW_EH_PE_omit: EncStr = "omit"; break;
+ case dwarf::DW_EH_PE_pcrel: EncStr = "pcrel"; break;
+ case dwarf::DW_EH_PE_udata4: EncStr = "udata4"; break;
+ case dwarf::DW_EH_PE_udata8: EncStr = "udata8"; break;
+ case dwarf::DW_EH_PE_sdata4: EncStr = "sdata4"; break;
+ case dwarf::DW_EH_PE_sdata8: EncStr = "sdata8"; break;
+ case dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_udata4:
+ EncStr = "pcrel udata4";
+ break;
+ case dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4:
+ EncStr = "pcrel sdata4";
+ break;
+ case dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_udata8:
+ EncStr = "pcrel udata8";
+ break;
+ case dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata8:
+ EncStr = "screl sdata8";
+ break;
case dwarf::DW_EH_PE_indirect |dwarf::DW_EH_PE_pcrel|dwarf::DW_EH_PE_udata4:
EncStr = "indirect pcrel udata4";
+ break;
case dwarf::DW_EH_PE_indirect |dwarf::DW_EH_PE_pcrel|dwarf::DW_EH_PE_sdata4:
EncStr = "indirect pcrel sdata4";
+ break;
case dwarf::DW_EH_PE_indirect |dwarf::DW_EH_PE_pcrel|dwarf::DW_EH_PE_udata8:
EncStr = "indirect pcrel udata8";
+ break;
case dwarf::DW_EH_PE_indirect |dwarf::DW_EH_PE_pcrel|dwarf::DW_EH_PE_sdata8:
EncStr = "indirect pcrel sdata8";
+ break;
}
Streamer.AddComment(Twine(Prefix) + " = " + EncStr);
@@ -639,11 +992,11 @@ void FrameEmitterImpl::EmitCFIInstruction(MCStreamer &Streamer,
}
return;
}
- case MCCFIInstruction::Remember:
+ case MCCFIInstruction::RememberState:
if (VerboseAsm) Streamer.AddComment("DW_CFA_remember_state");
Streamer.EmitIntValue(dwarf::DW_CFA_remember_state, 1);
return;
- case MCCFIInstruction::Restore:
+ case MCCFIInstruction::RestoreState:
if (VerboseAsm) Streamer.AddComment("DW_CFA_restore_state");
Streamer.EmitIntValue(dwarf::DW_CFA_restore_state, 1);
return;
@@ -655,6 +1008,19 @@ void FrameEmitterImpl::EmitCFIInstruction(MCStreamer &Streamer,
Streamer.EmitULEB128IntValue(Reg);
return;
}
+ case MCCFIInstruction::Restore: {
+ unsigned Reg = Instr.getDestination().getReg();
+ if (VerboseAsm) {
+ Streamer.AddComment("DW_CFA_restore");
+ Streamer.AddComment(Twine("Reg ") + Twine(Reg));
+ }
+ Streamer.EmitIntValue(dwarf::DW_CFA_restore | Reg, 1);
+ return;
+ }
+ case MCCFIInstruction::Escape:
+ if (VerboseAsm) Streamer.AddComment("Escape bytes");
+ Streamer.EmitBytes(Instr.getValues(), 0);
+ return;
}
llvm_unreachable("Unhandled case in switch");
}
@@ -738,8 +1104,8 @@ bool FrameEmitterImpl::EmitCompactUnwind(MCStreamer &Streamer,
// Compact Encoding
Size = getSizeForEncoding(Streamer, dwarf::DW_EH_PE_udata4);
- if (VerboseAsm) Streamer.AddComment(Twine("Compact Unwind Encoding: 0x") +
- Twine(llvm::utohexstr(Encoding)));
+ if (VerboseAsm) Streamer.AddComment("Compact Unwind Encoding: 0x" +
+ Twine::utohexstr(Encoding));
Streamer.EmitIntValue(Encoding, Size);
@@ -766,6 +1132,7 @@ const MCSymbol &FrameEmitterImpl::EmitCIE(MCStreamer &streamer,
const MCSymbol *personality,
unsigned personalityEncoding,
const MCSymbol *lsda,
+ bool IsSignalFrame,
unsigned lsdaEncoding) {
MCContext &context = streamer.getContext();
const MCRegisterInfo &MRI = context.getRegisterInfo();
@@ -808,6 +1175,8 @@ const MCSymbol &FrameEmitterImpl::EmitCIE(MCStreamer &streamer,
if (lsda)
Augmentation += "L";
Augmentation += "R";
+ if (IsSignalFrame)
+ Augmentation += "S";
streamer.EmitBytes(Augmentation.str(), 0);
}
streamer.EmitIntValue(0, 1);
@@ -967,17 +1336,18 @@ MCSymbol *FrameEmitterImpl::EmitFDE(MCStreamer &streamer,
namespace {
struct CIEKey {
- static const CIEKey getEmptyKey() { return CIEKey(0, 0, -1); }
- static const CIEKey getTombstoneKey() { return CIEKey(0, -1, 0); }
+ static const CIEKey getEmptyKey() { return CIEKey(0, 0, -1, false); }
+ static const CIEKey getTombstoneKey() { return CIEKey(0, -1, 0, false); }
CIEKey(const MCSymbol* Personality_, unsigned PersonalityEncoding_,
- unsigned LsdaEncoding_) : Personality(Personality_),
- PersonalityEncoding(PersonalityEncoding_),
- LsdaEncoding(LsdaEncoding_) {
+ unsigned LsdaEncoding_, bool IsSignalFrame_) :
+ Personality(Personality_), PersonalityEncoding(PersonalityEncoding_),
+ LsdaEncoding(LsdaEncoding_), IsSignalFrame(IsSignalFrame_) {
}
const MCSymbol* Personality;
unsigned PersonalityEncoding;
unsigned LsdaEncoding;
+ bool IsSignalFrame;
};
}
@@ -991,17 +1361,17 @@ namespace llvm {
return CIEKey::getTombstoneKey();
}
static unsigned getHashValue(const CIEKey &Key) {
- FoldingSetNodeID ID;
- ID.AddPointer(Key.Personality);
- ID.AddInteger(Key.PersonalityEncoding);
- ID.AddInteger(Key.LsdaEncoding);
- return ID.ComputeHash();
+ return static_cast<unsigned>(hash_combine(Key.Personality,
+ Key.PersonalityEncoding,
+ Key.LsdaEncoding,
+ Key.IsSignalFrame));
}
static bool isEqual(const CIEKey &LHS,
const CIEKey &RHS) {
return LHS.Personality == RHS.Personality &&
LHS.PersonalityEncoding == RHS.PersonalityEncoding &&
- LHS.LsdaEncoding == RHS.LsdaEncoding;
+ LHS.LsdaEncoding == RHS.LsdaEncoding &&
+ LHS.IsSignalFrame == RHS.IsSignalFrame;
}
};
}
@@ -1016,12 +1386,10 @@ void MCDwarfFrameEmitter::Emit(MCStreamer &Streamer,
ArrayRef<MCDwarfFrameInfo> FrameArray = Streamer.getFrameInfos();
// Emit the compact unwind info if available.
- // FIXME: This emits both the compact unwind and the old CIE/FDE
- // information. Only one of those is needed.
if (IsEH && MOFI->getCompactUnwindSection())
for (unsigned i = 0, n = Streamer.getNumFrameInfos(); i < n; ++i) {
const MCDwarfFrameInfo &Frame = Streamer.getFrameInfo(i);
- if (!Frame.CompactUnwindEncoding)
+ if (Frame.CompactUnwindEncoding)
Emitter.EmitCompactUnwind(Streamer, Frame);
}
@@ -1039,11 +1407,12 @@ void MCDwarfFrameEmitter::Emit(MCStreamer &Streamer,
for (unsigned i = 0, n = FrameArray.size(); i < n; ++i) {
const MCDwarfFrameInfo &Frame = FrameArray[i];
CIEKey Key(Frame.Personality, Frame.PersonalityEncoding,
- Frame.LsdaEncoding);
+ Frame.LsdaEncoding, Frame.IsSignalFrame);
const MCSymbol *&CIEStart = IsEH ? CIEStarts[Key] : DummyDebugKey;
if (!CIEStart)
CIEStart = &Emitter.EmitCIE(Streamer, Frame.Personality,
Frame.PersonalityEncoding, Frame.Lsda,
+ Frame.IsSignalFrame,
Frame.LsdaEncoding);
FDEEnd = Emitter.EmitFDE(Streamer, *CIEStart, Frame);
OpenPOWER on IntegriCloud