#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCExpr.h"
#include "llvm/MC/MCObjectFileInfo.h"
-#include "llvm/MC/MCObjectWriter.h"
#include "llvm/MC/MCRegisterInfo.h"
#include "llvm/MC/MCStreamer.h"
#include "llvm/MC/MCSymbol.h"
// Range of line offsets in a special line info. opcode.
#define DWARF2_LINE_RANGE 14
-// Define the architecture-dependent minimum instruction length (in bytes).
-// This value should be rather too small than too big.
-#define DWARF2_LINE_MIN_INSN_LENGTH 1
-
-// Note: when DWARF2_LINE_MIN_INSN_LENGTH == 1 which is the current setting,
-// this routine is a nop and will be optimized away.
-static inline uint64_t ScaleAddrDelta(uint64_t AddrDelta) {
- if (DWARF2_LINE_MIN_INSN_LENGTH == 1)
+static inline uint64_t ScaleAddrDelta(MCContext &Context, uint64_t AddrDelta) {
+ unsigned MinInsnLength = Context.getAsmInfo()->getMinInstAlignment();
+ if (MinInsnLength == 1)
return AddrDelta;
- if (AddrDelta % DWARF2_LINE_MIN_INSN_LENGTH != 0) {
+ if (AddrDelta % MinInsnLength != 0) {
// TODO: report this error, but really only once.
;
}
- return AddrDelta / DWARF2_LINE_MIN_INSN_LENGTH;
+ return AddrDelta / MinInsnLength;
}
//
// clear DwarfLocSeen saying the current .loc info is now used.
MCOS->getContext().ClearDwarfLocSeen();
- // Get the MCLineSection for this section, if one does not exist for this
- // section create it.
- const DenseMap<const MCSection *, MCLineSection *> &MCLineSections =
- MCOS->getContext().getMCLineSections();
- MCLineSection *LineSection = MCLineSections.lookup(Section);
- if (!LineSection) {
- // Create a new MCLineSection. This will be deleted after the dwarf line
- // table is created using it by iterating through the MCLineSections
- // DenseMap.
- LineSection = new MCLineSection;
- // Save a pointer to the new LineSection into the MCLineSections DenseMap.
- MCOS->getContext().addMCLineSection(Section, LineSection);
- }
-
// Add the line entry to this section's entries.
- LineSection->addLineEntry(LineEntry,
- MCOS->getContext().getDwarfCompileUnitID());
+ MCOS->getContext()
+ .getMCDwarfLineTable(MCOS->getContext().getDwarfCompileUnitID())
+ .getMCLineSections()
+ .addLineEntry(LineEntry, Section);
}
//
// This emits the Dwarf line table for the specified section from the entries
// in the LineSection.
//
-static inline void EmitDwarfLineTable(MCStreamer *MCOS,
- const MCSection *Section,
- const MCLineSection *LineSection,
- unsigned CUID) {
- // This LineSection does not contain any LineEntry for the given Compile Unit.
- if (!LineSection->containEntriesForID(CUID))
- return;
-
+static inline void
+EmitDwarfLineTable(MCStreamer *MCOS, const MCSection *Section,
+ const MCLineSection::MCLineEntryCollection &LineEntries) {
unsigned FileNum = 1;
unsigned LastLine = 1;
unsigned Column = 0;
unsigned Flags = DWARF2_LINE_DEFAULT_IS_STMT ? DWARF2_FLAG_IS_STMT : 0;
unsigned Isa = 0;
+ unsigned Discriminator = 0;
MCSymbol *LastLabel = NULL;
// Loop through each MCLineEntry and encode the dwarf line number table.
- for (MCLineSection::const_iterator
- it = LineSection->getMCLineEntries(CUID).begin(),
- ie = LineSection->getMCLineEntries(CUID).end(); it != ie; ++it) {
+ for (auto it = LineEntries.begin(),
+ ie = LineEntries.end();
+ it != ie; ++it) {
if (FileNum != it->getFileNum()) {
FileNum = it->getFileNum();
MCOS->EmitIntValue(dwarf::DW_LNS_set_column, 1);
MCOS->EmitULEB128IntValue(Column);
}
+ if (Discriminator != it->getDiscriminator()) {
+ Discriminator = it->getDiscriminator();
+ unsigned Size = getULEB128Size(Discriminator);
+ MCOS->EmitIntValue(dwarf::DW_LNS_extended_op, 1);
+ MCOS->EmitULEB128IntValue(Size + 1);
+ MCOS->EmitIntValue(dwarf::DW_LNE_set_discriminator, 1);
+ MCOS->EmitULEB128IntValue(Discriminator);
+ }
if (Isa != it->getIsa()) {
Isa = it->getIsa();
MCOS->EmitIntValue(dwarf::DW_LNS_set_isa, 1);
// At this point we want to emit/create the sequence to encode the delta in
// line numbers and the increment of the address from the previous Label
// and the current Label.
- const MCAsmInfo &asmInfo = MCOS->getContext().getAsmInfo();
+ const MCAsmInfo *asmInfo = MCOS->getContext().getAsmInfo();
MCOS->EmitDwarfAdvanceLineAddr(LineDelta, LastLabel, Label,
- asmInfo.getPointerSize());
+ asmInfo->getPointerSize());
LastLine = it->getLine();
LastLabel = Label;
// Switch back the dwarf line section.
MCOS->SwitchSection(context.getObjectFileInfo()->getDwarfLineSection());
- const MCAsmInfo &asmInfo = MCOS->getContext().getAsmInfo();
+ const MCAsmInfo *asmInfo = MCOS->getContext().getAsmInfo();
MCOS->EmitDwarfAdvanceLineAddr(INT64_MAX, LastLabel, SectionEnd,
- asmInfo.getPointerSize());
+ asmInfo->getPointerSize());
}
//
// This emits the Dwarf file and the line tables.
//
-const MCSymbol *MCDwarfFileTable::Emit(MCStreamer *MCOS) {
+const MCSymbol *MCDwarfLineTable::Emit(MCStreamer *MCOS) {
MCContext &context = MCOS->getContext();
- // Switch to the section where the table will be emitted into.
- MCOS->SwitchSection(context.getObjectFileInfo()->getDwarfLineSection());
- const DenseMap<unsigned, MCSymbol *> &MCLineTableSymbols =
- MCOS->getContext().getMCLineTableSymbols();
// CUID and MCLineTableSymbols are set in DwarfDebug, when DwarfDebug does
// not exist, CUID will be 0 and MCLineTableSymbols will be empty.
// Handle Compile Unit 0, the line table start symbol is the section symbol.
- const MCSymbol *LineStartSym = EmitCU(MCOS, 0);
+ auto I = MCOS->getContext().getMCDwarfLineTables().begin(),
+ E = MCOS->getContext().getMCDwarfLineTables().end();
+
+ // Switch to the section where the table will be emitted into.
+ MCOS->SwitchSection(context.getObjectFileInfo()->getDwarfLineSection());
+
+ const MCSymbol *LineStartSym = I->second.EmitCU(MCOS);
// Handle the rest of the Compile Units.
- for (unsigned Is = 1, Ie = MCLineTableSymbols.size(); Is < Ie; Is++)
- EmitCU(MCOS, Is);
-
- // Now delete the MCLineSections that were created in MCLineEntry::Make()
- // and used to emit the line table.
- const DenseMap<const MCSection *, MCLineSection *> &MCLineSections =
- MCOS->getContext().getMCLineSections();
- for (DenseMap<const MCSection *, MCLineSection *>::const_iterator it =
- MCLineSections.begin(), ie = MCLineSections.end(); it != ie;
- ++it)
- delete it->second;
+ for (++I; I != E; ++I)
+ I->second.EmitCU(MCOS);
return LineStartSym;
}
-const MCSymbol *MCDwarfFileTable::EmitCU(MCStreamer *MCOS, unsigned CUID) {
+std::pair<MCSymbol *, MCSymbol *> MCDwarfLineTableHeader::Emit(MCStreamer *MCOS) const {
MCContext &context = MCOS->getContext();
// Create a symbol at the beginning of the line table.
- MCSymbol *LineStartSym = MCOS->getContext().getMCLineTableSymbol(CUID);
+ MCSymbol *LineStartSym = Label;
if (!LineStartSym)
LineStartSym = context.CreateTempSymbol();
// Set the value of the symbol, as we are at the start of the line table.
// total length, the 2 bytes for the version, and these 4 bytes for the
// length of the prologue.
MCOS->EmitAbsValue(MakeStartMinusEndExpr(*MCOS, *LineStartSym, *ProEndSym,
- (4 + 2 + 4)), 4, 0);
+ (4 + 2 + 4)), 4);
// Parameters of the state machine, are next.
- MCOS->EmitIntValue(DWARF2_LINE_MIN_INSN_LENGTH, 1);
+ MCOS->EmitIntValue(context.getAsmInfo()->getMinInstAlignment(), 1);
MCOS->EmitIntValue(DWARF2_LINE_DEFAULT_IS_STMT, 1);
MCOS->EmitIntValue(DWARF2_LINE_BASE, 1);
MCOS->EmitIntValue(DWARF2_LINE_RANGE, 1);
// Put out the directory and file tables.
// First the directory table.
- const SmallVectorImpl<StringRef> &MCDwarfDirs =
- context.getMCDwarfDirs(CUID);
for (unsigned i = 0; i < MCDwarfDirs.size(); i++) {
MCOS->EmitBytes(MCDwarfDirs[i]); // the DirectoryName
MCOS->EmitBytes(StringRef("\0", 1)); // the null term. of the string
MCOS->EmitIntValue(0, 1); // Terminate the directory list
// Second the file table.
- const SmallVectorImpl<MCDwarfFile *> &MCDwarfFiles =
- MCOS->getContext().getMCDwarfFiles(CUID);
for (unsigned i = 1; i < MCDwarfFiles.size(); i++) {
- MCOS->EmitBytes(MCDwarfFiles[i]->getName()); // FileName
+ MCOS->EmitBytes(MCDwarfFiles[i].Name); // FileName
MCOS->EmitBytes(StringRef("\0", 1)); // the null term. of the string
// the Directory num
- MCOS->EmitULEB128IntValue(MCDwarfFiles[i]->getDirIndex());
+ MCOS->EmitULEB128IntValue(MCDwarfFiles[i].DirIndex);
MCOS->EmitIntValue(0, 1); // last modification timestamp (always 0)
MCOS->EmitIntValue(0, 1); // filesize (always 0)
}
// end of the prologue (that was used in a previous expression).
MCOS->EmitLabel(ProEndSym);
+ return std::make_pair(LineStartSym, LineEndSym);
+}
+
+const MCSymbol *MCDwarfLineTable::EmitCU(MCStreamer *MCOS) const {
+ MCSymbol *LineStartSym;
+ MCSymbol *LineEndSym;
+ std::tie(LineStartSym, LineEndSym) = Header.Emit(MCOS);
+
// Put out the line tables.
- const DenseMap<const MCSection *, MCLineSection *> &MCLineSections =
- MCOS->getContext().getMCLineSections();
- const std::vector<const MCSection *> &MCLineSectionOrder =
- MCOS->getContext().getMCLineSectionOrder();
- for (std::vector<const MCSection*>::const_iterator it =
- MCLineSectionOrder.begin(), ie = MCLineSectionOrder.end(); it != ie;
- ++it) {
- const MCSection *Sec = *it;
- const MCLineSection *Line = MCLineSections.lookup(Sec);
- EmitDwarfLineTable(MCOS, Sec, Line, CUID);
- }
+ for (const auto &LineSec : MCLineSections.getMCLineEntries())
+ EmitDwarfLineTable(MCOS, LineSec.first, LineSec.second);
- if (MCOS->getContext().getAsmInfo().getLinkerRequiresNonEmptyDwarfLines()
- && MCLineSectionOrder.begin() == MCLineSectionOrder.end()) {
+ if (MCOS->getContext().getAsmInfo()->getLinkerRequiresNonEmptyDwarfLines() &&
+ MCLineSections.getMCLineEntries().empty()) {
// The darwin9 linker has a bug (see PR8715). For for 32-bit architectures
// it requires:
// total_length >= prologue_length + 10
return LineStartSym;
}
-/// Utility function to write the encoding to an object writer.
-void MCDwarfLineAddr::Write(MCObjectWriter *OW, int64_t LineDelta,
- uint64_t AddrDelta) {
- SmallString<256> Tmp;
- raw_svector_ostream OS(Tmp);
- MCDwarfLineAddr::Encode(LineDelta, AddrDelta, OS);
- OW->WriteBytes(OS.str());
+unsigned MCDwarfLineTable::getFile(StringRef Directory, StringRef FileName,
+ unsigned FileNumber) {
+ return Header.getFile(Directory, FileName, FileNumber);
+}
+
+unsigned MCDwarfLineTableHeader::getFile(StringRef Directory, StringRef FileName, unsigned FileNumber) {
+ // Make space for this FileNumber in the MCDwarfFiles vector if needed.
+ MCDwarfFiles.resize(FileNumber + 1);
+
+ // Get the new MCDwarfFile slot for this FileNumber.
+ MCDwarfFile &File = MCDwarfFiles[FileNumber];
+
+ // It is an error to use see the same number more than once.
+ if (!File.Name.empty())
+ return 0;
+
+ if (Directory.empty()) {
+ // Separate the directory part from the basename of the FileName.
+ StringRef tFileName = sys::path::filename(FileName);
+ if (!tFileName.empty()) {
+ Directory = sys::path::parent_path(FileName);
+ if (!Directory.empty())
+ FileName = tFileName;
+ }
+ }
+
+ // Find or make an entry in the MCDwarfDirs vector for this Directory.
+ // Capture directory name.
+ unsigned DirIndex;
+ if (Directory.empty()) {
+ // For FileNames with no directories a DirIndex of 0 is used.
+ DirIndex = 0;
+ } else {
+ DirIndex = 0;
+ for (unsigned End = MCDwarfDirs.size(); DirIndex < End; DirIndex++) {
+ if (Directory == MCDwarfDirs[DirIndex])
+ break;
+ }
+ if (DirIndex >= MCDwarfDirs.size())
+ MCDwarfDirs.push_back(Directory);
+ // The DirIndex is one based, as DirIndex of 0 is used for FileNames with
+ // no directories. MCDwarfDirs[] is unlike MCDwarfFiles[] in that the
+ // directory names are stored at MCDwarfDirs[DirIndex-1] where FileNames
+ // are stored at MCDwarfFiles[FileNumber].Name .
+ DirIndex++;
+ }
+
+ File.Name = FileName;
+ File.DirIndex = DirIndex;
+
+ // return the allocated FileNumber.
+ return FileNumber;
}
/// Utility function to emit the encoding to a streamer.
void MCDwarfLineAddr::Emit(MCStreamer *MCOS, int64_t LineDelta,
uint64_t AddrDelta) {
+ MCContext &Context = MCOS->getContext();
SmallString<256> Tmp;
raw_svector_ostream OS(Tmp);
- MCDwarfLineAddr::Encode(LineDelta, AddrDelta, OS);
+ MCDwarfLineAddr::Encode(Context, LineDelta, AddrDelta, OS);
MCOS->EmitBytes(OS.str());
}
/// Utility function to encode a Dwarf pair of LineDelta and AddrDeltas.
-void MCDwarfLineAddr::Encode(int64_t LineDelta, uint64_t AddrDelta,
- raw_ostream &OS) {
+void MCDwarfLineAddr::Encode(MCContext &Context, int64_t LineDelta,
+ uint64_t AddrDelta, raw_ostream &OS) {
uint64_t Temp, Opcode;
bool NeedCopy = false;
// Scale the address delta by the minimum instruction length.
- AddrDelta = ScaleAddrDelta(AddrDelta);
+ AddrDelta = ScaleAddrDelta(Context, AddrDelta);
// A LineDelta of INT64_MAX is a signal that this is actually a
// DW_LNE_end_sequence. We cannot use special opcodes here, since we want the
OS << char(Temp);
}
-void MCDwarfFile::print(raw_ostream &OS) const {
- OS << '"' << getName() << '"';
-}
-
-#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
-void MCDwarfFile::dump() const {
- print(dbgs());
-}
-#endif
-
// Utility function to write a tuple for .debug_abbrev.
static void EmitAbbrev(MCStreamer *MCOS, uint64_t Name, uint64_t Form) {
MCOS->EmitULEB128IntValue(Name);
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);
+ if (!context.getCompilationDir().empty())
+ 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);
// 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();
+ const MCAsmInfo *asmInfo = context.getAsmInfo();
+ int AddrSize = asmInfo->getPointerSize();
int Pad = 2 * AddrSize - (Length & (2 * AddrSize - 1));
if (Pad == 2 * AddrSize)
Pad = 0;
MCOS->EmitIntValue(0, 4);
}
- const MCAsmInfo &asmInfo = context.getAsmInfo();
- int AddrSize = asmInfo.getPointerSize();
+ const MCAsmInfo *asmInfo = context.getAsmInfo();
+ int AddrSize = asmInfo->getPointerSize();
// The 1 byte size of an address.
MCOS->EmitIntValue(AddrSize, 1);
// AT_name, the name of the source file. Reconstruct from the first directory
// and file table entries.
- const SmallVectorImpl<StringRef> &MCDwarfDirs =
- context.getMCDwarfDirs();
+ const SmallVectorImpl<std::string> &MCDwarfDirs = context.getMCDwarfDirs();
if (MCDwarfDirs.size() > 0) {
MCOS->EmitBytes(MCDwarfDirs[0]);
MCOS->EmitBytes("/");
}
- const SmallVectorImpl<MCDwarfFile *> &MCDwarfFiles =
+ const SmallVectorImpl<MCDwarfFile> &MCDwarfFiles =
MCOS->getContext().getMCDwarfFiles();
- MCOS->EmitBytes(MCDwarfFiles[1]->getName());
+ MCOS->EmitBytes(MCDwarfFiles[1].Name);
MCOS->EmitIntValue(0, 1); // NULL byte to terminate the string.
// AT_comp_dir, the working directory the assembly was done in.
- MCOS->EmitBytes(context.getCompilationDir());
- MCOS->EmitIntValue(0, 1); // NULL byte to terminate the string.
+ if (!context.getCompilationDir().empty()) {
+ MCOS->EmitBytes(context.getCompilationDir());
+ 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();
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();
+ const MCAsmInfo *AsmInfo = context.getAsmInfo();
bool CreateDwarfSectionSymbols =
- AsmInfo.doesDwarfUseRelocationsAcrossSections();
+ AsmInfo->doesDwarfUseRelocationsAcrossSections();
if (!CreateDwarfSectionSymbols)
LineSectionSymbol = NULL;
MCSymbol *AbbrevSectionSymbol = NULL;
MCOS->SwitchSection(context.getObjectFileInfo()->getDwarfARangesSection());
// If there are no line table entries then do not emit any section contents.
- if (context.getMCLineSections().empty())
+ if (!context.hasMCLineSections())
return;
// Output the data for .debug_aranges section.
static int getDataAlignmentFactor(MCStreamer &streamer) {
MCContext &context = streamer.getContext();
- const MCAsmInfo &asmInfo = context.getAsmInfo();
- int size = asmInfo.getCalleeSaveStackSlotSize();
- if (asmInfo.isStackGrowthDirectionUp())
+ const MCAsmInfo *asmInfo = context.getAsmInfo();
+ int size = asmInfo->getCalleeSaveStackSlotSize();
+ if (asmInfo->isStackGrowthDirectionUp())
return size;
else
return -size;
default: llvm_unreachable("Unknown Encoding");
case dwarf::DW_EH_PE_absptr:
case dwarf::DW_EH_PE_signed:
- return context.getAsmInfo().getPointerSize();
+ return context.getAsmInfo()->getPointerSize();
case dwarf::DW_EH_PE_udata2:
case dwarf::DW_EH_PE_sdata2:
return 2;
}
}
-static void EmitSymbol(MCStreamer &streamer, const MCSymbol &symbol,
- unsigned symbolEncoding, const char *comment = 0) {
+static void EmitFDESymbol(MCStreamer &streamer, const MCSymbol &symbol,
+ unsigned symbolEncoding, bool isEH,
+ const char *comment = 0) {
MCContext &context = streamer.getContext();
- const MCAsmInfo &asmInfo = context.getAsmInfo();
- const MCExpr *v = asmInfo.getExprForFDESymbol(&symbol,
- symbolEncoding,
- streamer);
+ const MCAsmInfo *asmInfo = context.getAsmInfo();
+ const MCExpr *v = asmInfo->getExprForFDESymbol(&symbol,
+ symbolEncoding,
+ streamer);
unsigned size = getSizeForEncoding(streamer, symbolEncoding);
if (streamer.isVerboseAsm() && comment) streamer.AddComment(comment);
- streamer.EmitAbsValue(v, size);
+ if (asmInfo->doDwarfFDESymbolsUseAbsDiff() && isEH)
+ streamer.EmitAbsValue(v, size);
+ else
+ streamer.EmitValue(v, size);
}
static void EmitPersonality(MCStreamer &streamer, const MCSymbol &symbol,
unsigned symbolEncoding) {
MCContext &context = streamer.getContext();
- const MCAsmInfo &asmInfo = context.getAsmInfo();
- const MCExpr *v = asmInfo.getExprForPersonalitySymbol(&symbol,
- symbolEncoding,
- streamer);
+ const MCAsmInfo *asmInfo = context.getAsmInfo();
+ const MCExpr *v = asmInfo->getExprForPersonalitySymbol(&symbol,
+ symbolEncoding,
+ streamer);
unsigned size = getSizeForEncoding(streamer, symbolEncoding);
streamer.EmitValue(v, size);
}
void setSectionStart(const MCSymbol *Label) { SectionStart = Label; }
- /// EmitCompactUnwind - Emit the unwind information in a compact way. If
- /// we're successful, return 'true'. Otherwise, return 'false' and it will
- /// emit the normal CIE and FDE.
+ /// EmitCompactUnwind - Emit the unwind information in a compact way.
void EmitCompactUnwind(MCStreamer &streamer,
const MCDwarfFrameInfo &frame);
unsigned personalityEncoding,
const MCSymbol *lsda,
bool IsSignalFrame,
- unsigned lsdaEncoding);
+ unsigned lsdaEncoding,
+ bool IsSimple);
MCSymbol *EmitFDE(MCStreamer &streamer,
const MCSymbol &cieStart,
const MCDwarfFrameInfo &frame);
void EmitCFIInstructions(MCStreamer &streamer,
- const std::vector<MCCFIInstruction> &Instrs,
+ ArrayRef<MCCFIInstruction> Instrs,
MCSymbol *BaseLabel);
void EmitCFIInstruction(MCStreamer &Streamer,
const MCCFIInstruction &Instr);
Streamer.EmitULEB128IntValue(Reg2);
return;
}
+ case MCCFIInstruction::OpWindowSave: {
+ Streamer.EmitIntValue(dwarf::DW_CFA_GNU_window_save, 1);
+ return;
+ }
case MCCFIInstruction::OpUndefined: {
unsigned Reg = Instr.getRegister();
if (VerboseAsm) {
/// EmitFrameMoves - Emit frame instructions to describe the layout of the
/// frame.
void FrameEmitterImpl::EmitCFIInstructions(MCStreamer &streamer,
- const std::vector<MCCFIInstruction> &Instrs,
+ ArrayRef<MCCFIInstruction> Instrs,
MCSymbol *BaseLabel) {
for (unsigned i = 0, N = Instrs.size(); i < N; ++i) {
const MCCFIInstruction &Instr = Instrs[i];
}
}
-/// EmitCompactUnwind - Emit the unwind information in a compact way. If we're
-/// successful, return 'true'. Otherwise, return 'false' and it will emit the
-/// normal CIE and FDE.
+/// EmitCompactUnwind - Emit the unwind information in a compact way.
void FrameEmitterImpl::EmitCompactUnwind(MCStreamer &Streamer,
const MCDwarfFrameInfo &Frame) {
MCContext &Context = Streamer.getContext();
unsigned personalityEncoding,
const MCSymbol *lsda,
bool IsSignalFrame,
- unsigned lsdaEncoding) {
+ unsigned lsdaEncoding,
+ bool IsSimple) {
MCContext &context = streamer.getContext();
- const MCRegisterInfo &MRI = context.getRegisterInfo();
+ const MCRegisterInfo *MRI = context.getRegisterInfo();
const MCObjectFileInfo *MOFI = context.getObjectFileInfo();
bool verboseAsm = streamer.isVerboseAsm();
// Code Alignment Factor
if (verboseAsm) streamer.AddComment("CIE Code Alignment Factor");
- streamer.EmitULEB128IntValue(1);
+ streamer.EmitULEB128IntValue(context.getAsmInfo()->getMinInstAlignment());
// Data Alignment Factor
if (verboseAsm) streamer.AddComment("CIE Data Alignment Factor");
// Return Address Register
if (verboseAsm) streamer.AddComment("CIE Return Address Column");
- streamer.EmitULEB128IntValue(MRI.getDwarfRegNum(MRI.getRARegister(), true));
+ streamer.EmitULEB128IntValue(MRI->getDwarfRegNum(MRI->getRARegister(), true));
// Augmentation Data Length (optional)
// Initial Instructions
- const MCAsmInfo &MAI = context.getAsmInfo();
- const std::vector<MCCFIInstruction> &Instructions =
- MAI.getInitialFrameState();
- EmitCFIInstructions(streamer, Instructions, NULL);
+ const MCAsmInfo *MAI = context.getAsmInfo();
+ if (!IsSimple) {
+ const std::vector<MCCFIInstruction> &Instructions =
+ MAI->getInitialFrameState();
+ EmitCFIInstructions(streamer, Instructions, NULL);
+ }
// Padding
- streamer.EmitValueToAlignment(IsEH
- ? 4 : context.getAsmInfo().getPointerSize());
+ streamer.EmitValueToAlignment(IsEH ? 4 : MAI->getPointerSize());
streamer.EmitLabel(sectionEnd);
return *sectionStart;
streamer.EmitLabel(fdeStart);
// CIE Pointer
- const MCAsmInfo &asmInfo = context.getAsmInfo();
+ const MCAsmInfo *asmInfo = context.getAsmInfo();
if (IsEH) {
const MCExpr *offset = MakeStartMinusEndExpr(streamer, cieStart, *fdeStart,
0);
if (verboseAsm) streamer.AddComment("FDE CIE Offset");
streamer.EmitAbsValue(offset, 4);
- } else if (!asmInfo.doesDwarfUseRelocationsAcrossSections()) {
+ } else if (!asmInfo->doesDwarfUseRelocationsAcrossSections()) {
const MCExpr *offset = MakeStartMinusEndExpr(streamer, *SectionStart,
cieStart, 0);
streamer.EmitAbsValue(offset, 4);
unsigned PCEncoding = IsEH ? MOFI->getFDEEncoding(UsingCFI)
: (unsigned)dwarf::DW_EH_PE_absptr;
unsigned PCSize = getSizeForEncoding(streamer, PCEncoding);
- EmitSymbol(streamer, *frame.Begin, PCEncoding, "FDE initial location");
+ EmitFDESymbol(streamer, *frame.Begin, PCEncoding, IsEH, "FDE initial location");
// PC Range
const MCExpr *Range = MakeStartMinusEndExpr(streamer, *frame.Begin,
// Augmentation Data
if (frame.Lsda)
- EmitSymbol(streamer, *frame.Lsda, frame.LsdaEncoding,
- "Language Specific Data Area");
+ EmitFDESymbol(streamer, *frame.Lsda, frame.LsdaEncoding, true,
+ "Language Specific Data Area");
}
// Call Frame Instructions
namespace {
struct CIEKey {
- static const CIEKey getEmptyKey() { return CIEKey(0, 0, -1, false); }
- static const CIEKey getTombstoneKey() { return CIEKey(0, -1, 0, false); }
+ static const CIEKey getEmptyKey() { return CIEKey(0, 0, -1, false, false); }
+ static const CIEKey getTombstoneKey() { return CIEKey(0, -1, 0, false, false); }
CIEKey(const MCSymbol* Personality_, unsigned PersonalityEncoding_,
- unsigned LsdaEncoding_, bool IsSignalFrame_) :
+ unsigned LsdaEncoding_, bool IsSignalFrame_, bool IsSimple_) :
Personality(Personality_), PersonalityEncoding(PersonalityEncoding_),
- LsdaEncoding(LsdaEncoding_), IsSignalFrame(IsSignalFrame_) {
+ LsdaEncoding(LsdaEncoding_), IsSignalFrame(IsSignalFrame_),
+ IsSimple(IsSimple_) {
}
const MCSymbol* Personality;
unsigned PersonalityEncoding;
unsigned LsdaEncoding;
bool IsSignalFrame;
+ bool IsSimple;
};
}
return static_cast<unsigned>(hash_combine(Key.Personality,
Key.PersonalityEncoding,
Key.LsdaEncoding,
- Key.IsSignalFrame));
+ Key.IsSignalFrame,
+ Key.IsSimple));
}
static bool isEqual(const CIEKey &LHS,
const CIEKey &RHS) {
return LHS.Personality == RHS.Personality &&
LHS.PersonalityEncoding == RHS.PersonalityEncoding &&
LHS.LsdaEncoding == RHS.LsdaEncoding &&
- LHS.IsSignalFrame == RHS.IsSignalFrame;
+ LHS.IsSignalFrame == RHS.IsSignalFrame &&
+ LHS.IsSimple == RHS.IsSimple;
}
};
}
-void MCDwarfFrameEmitter::Emit(MCStreamer &Streamer,
- bool UsingCFI,
- bool IsEH) {
+void MCDwarfFrameEmitter::Emit(MCStreamer &Streamer, MCAsmBackend *MAB,
+ bool UsingCFI, bool IsEH) {
+ Streamer.generateCompactUnwindEncodings(MAB);
+
MCContext &Context = Streamer.getContext();
const MCObjectFileInfo *MOFI = Context.getObjectFileInfo();
FrameEmitterImpl Emitter(UsingCFI, IsEH);
if (Frame.CompactUnwindEncoding == 0) continue;
if (!SectionEmitted) {
Streamer.SwitchSection(MOFI->getCompactUnwindSection());
- Streamer.EmitValueToAlignment(Context.getAsmInfo().getPointerSize());
+ Streamer.EmitValueToAlignment(Context.getAsmInfo()->getPointerSize());
SectionEmitted = true;
}
Emitter.EmitCompactUnwind(Streamer, Frame);
for (unsigned i = 0, n = FrameArray.size(); i < n; ++i) {
const MCDwarfFrameInfo &Frame = FrameArray[i];
CIEKey Key(Frame.Personality, Frame.PersonalityEncoding,
- Frame.LsdaEncoding, Frame.IsSignalFrame);
+ Frame.LsdaEncoding, Frame.IsSignalFrame, Frame.IsSimple);
const MCSymbol *&CIEStart = IsEH ? CIEStarts[Key] : DummyDebugKey;
if (!CIEStart)
CIEStart = &Emitter.EmitCIE(Streamer, Frame.Personality,
Frame.PersonalityEncoding, Frame.Lsda,
Frame.IsSignalFrame,
- Frame.LsdaEncoding);
+ Frame.LsdaEncoding,
+ Frame.IsSimple);
FDEEnd = Emitter.EmitFDE(Streamer, *CIEStart, Frame);
Streamer.EmitLabel(FDEEnd);
}
- Streamer.EmitValueToAlignment(Context.getAsmInfo().getPointerSize());
+ Streamer.EmitValueToAlignment(Context.getAsmInfo()->getPointerSize());
if (FDEEnd)
Streamer.EmitLabel(FDEEnd);
}
void MCDwarfFrameEmitter::EmitAdvanceLoc(MCStreamer &Streamer,
uint64_t AddrDelta) {
+ MCContext &Context = Streamer.getContext();
SmallString<256> Tmp;
raw_svector_ostream OS(Tmp);
- MCDwarfFrameEmitter::EncodeAdvanceLoc(AddrDelta, OS);
+ MCDwarfFrameEmitter::EncodeAdvanceLoc(Context, AddrDelta, OS);
Streamer.EmitBytes(OS.str());
}
-void MCDwarfFrameEmitter::EncodeAdvanceLoc(uint64_t AddrDelta,
+void MCDwarfFrameEmitter::EncodeAdvanceLoc(MCContext &Context,
+ uint64_t AddrDelta,
raw_ostream &OS) {
- // FIXME: Assumes the code alignment factor is 1.
+ // Scale the address delta by the minimum instruction length.
+ AddrDelta = ScaleAddrDelta(Context, AddrDelta);
+
if (AddrDelta == 0) {
} else if (isUIntN(6, AddrDelta)) {
uint8_t Opcode = dwarf::DW_CFA_advance_loc | AddrDelta;