#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;
}
//
// 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;
// actually a DW_LNE_end_sequence.
// Switch to the section to be able to create a symbol at its end.
+ // TODO: keep track of the last subsection so that this symbol appears in the
+ // correct place.
MCOS->SwitchSection(Section);
MCContext &context = MCOS->getContext();
// 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());
}
//
// 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 std::vector<StringRef> &MCDwarfDirs =
+ const SmallVectorImpl<StringRef> &MCDwarfDirs =
context.getMCDwarfDirs(CUID);
for (unsigned i = 0; i < MCDwarfDirs.size(); i++) {
MCOS->EmitBytes(MCDwarfDirs[i]); // the DirectoryName
MCOS->EmitIntValue(0, 1); // Terminate the directory list
// Second the file table.
- const std::vector<MCDwarfFile *> &MCDwarfFiles =
+ const SmallVectorImpl<MCDwarfFile *> &MCDwarfFiles =
MCOS->getContext().getMCDwarfFiles(CUID);
for (unsigned i = 1; i < MCDwarfFiles.size(); i++) {
MCOS->EmitBytes(MCDwarfFiles[i]->getName()); // FileName
EmitDwarfLineTable(MCOS, Sec, Line, CUID);
}
- if (MCOS->getContext().getAsmInfo().getLinkerRequiresNonEmptyDwarfLines()
+ if (MCOS->getContext().getAsmInfo()->getLinkerRequiresNonEmptyDwarfLines()
&& MCLineSectionOrder.begin() == MCLineSectionOrder.end()) {
// The darwin9 linker has a bug (see PR8715). For for 32-bit architectures
// it requires:
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());
-}
-
/// 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
// 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 std::vector<StringRef> &MCDwarfDirs =
+ const SmallVectorImpl<StringRef> &MCDwarfDirs =
context.getMCDwarfDirs();
if (MCDwarfDirs.size() > 0) {
MCOS->EmitBytes(MCDwarfDirs[0]);
MCOS->EmitBytes("/");
}
- const std::vector<MCDwarfFile *> &MCDwarfFiles =
+ const SmallVectorImpl<MCDwarfFile *> &MCDwarfFiles =
MCOS->getContext().getMCDwarfFiles();
MCOS->EmitBytes(MCDwarfFiles[1]->getName());
MCOS->EmitIntValue(0, 1); // NULL byte to terminate the string.
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;
if (Symbol->isTemporary())
return;
MCContext &context = MCOS->getContext();
- if (context.getGenDwarfSection() != MCOS->getCurrentSection())
+ if (context.getGenDwarfSection() != MCOS->getCurrentSection().first)
return;
// The dwarf label's name does not have the symbol name's leading
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) {
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);
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);
}
-static const MachineLocation TranslateMachineLocation(
- const MCRegisterInfo &MRI,
- const MachineLocation &Loc) {
- unsigned Reg = Loc.getReg() == MachineLocation::VirtualFP ?
- MachineLocation::VirtualFP :
- unsigned(MRI.getDwarfRegNum(Loc.getReg(), true));
- const MachineLocation &NewLoc = Loc.isReg() ?
- MachineLocation(Reg) : MachineLocation(Reg, Loc.getOffset());
- return NewLoc;
-}
-
namespace {
class FrameEmitterImpl {
int CFAOffset;
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.
- bool EmitCompactUnwind(MCStreamer &streamer,
+ /// EmitCompactUnwind - Emit the unwind information in a compact way.
+ void EmitCompactUnwind(MCStreamer &streamer,
const MCDwarfFrameInfo &frame);
const MCSymbol &EmitCIE(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.
-bool FrameEmitterImpl::EmitCompactUnwind(MCStreamer &Streamer,
+/// EmitCompactUnwind - Emit the unwind information in a compact way.
+void FrameEmitterImpl::EmitCompactUnwind(MCStreamer &Streamer,
const MCDwarfFrameInfo &Frame) {
MCContext &Context = Streamer.getContext();
const MCObjectFileInfo *MOFI = Context.getObjectFileInfo();
// .quad except_tab1
uint32_t Encoding = Frame.CompactUnwindEncoding;
- if (!Encoding) return false;
+ if (!Encoding) return;
+ bool DwarfEHFrameOnly = (Encoding == MOFI->getCompactUnwindDwarfEHFrameOnly());
// The encoding needs to know we have an LSDA.
- if (Frame.Lsda)
+ if (!DwarfEHFrameOnly && Frame.Lsda)
Encoding |= 0x40000000;
- Streamer.SwitchSection(MOFI->getCompactUnwindSection());
-
// Range Start
unsigned FDEEncoding = MOFI->getFDEEncoding(UsingCFI);
unsigned Size = getSizeForEncoding(Streamer, FDEEncoding);
Twine::utohexstr(Encoding));
Streamer.EmitIntValue(Encoding, Size);
-
// Personality Function
Size = getSizeForEncoding(Streamer, dwarf::DW_EH_PE_absptr);
if (VerboseAsm) Streamer.AddComment("Personality Function");
- if (Frame.Personality)
+ if (!DwarfEHFrameOnly && Frame.Personality)
Streamer.EmitSymbolValue(Frame.Personality, Size);
else
Streamer.EmitIntValue(0, Size); // No personality fn
// LSDA
Size = getSizeForEncoding(Streamer, Frame.LsdaEncoding);
if (VerboseAsm) Streamer.AddComment("LSDA");
- if (Frame.Lsda)
+ if (!DwarfEHFrameOnly && Frame.Lsda)
Streamer.EmitSymbolValue(Frame.Lsda, Size);
else
Streamer.EmitIntValue(0, Size); // No LSDA
-
- return true;
}
const MCSymbol &FrameEmitterImpl::EmitCIE(MCStreamer &streamer,
bool IsSignalFrame,
unsigned lsdaEncoding) {
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<MachineMove> &Moves = MAI.getInitialFrameState();
- std::vector<MCCFIInstruction> Instructions;
-
- for (int i = 0, n = Moves.size(); i != n; ++i) {
- MCSymbol *Label = Moves[i].getLabel();
- const MachineLocation &Dst =
- TranslateMachineLocation(MRI, Moves[i].getDestination());
- const MachineLocation &Src =
- TranslateMachineLocation(MRI, Moves[i].getSource());
-
- if (Dst.isReg()) {
- assert(Dst.getReg() == MachineLocation::VirtualFP);
- assert(!Src.isReg());
- MCCFIInstruction Inst =
- MCCFIInstruction::createDefCfa(Label, Src.getReg(), -Src.getOffset());
- Instructions.push_back(Inst);
- } else {
- assert(Src.isReg());
- unsigned Reg = Src.getReg();
- int Offset = Dst.getOffset();
- MCCFIInstruction Inst =
- MCCFIInstruction::createOffset(Label, Reg, Offset);
- Instructions.push_back(Inst);
- }
- }
-
+ const MCAsmInfo *MAI = context.getAsmInfo();
+ 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);
}
// Call Frame Instructions
-
EmitCFIInstructions(streamer, frame.Instructions, frame.Begin);
// Padding
};
}
-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();
- MCObjectFileInfo *MOFI =
- const_cast<MCObjectFileInfo*>(Context.getObjectFileInfo());
+ const MCObjectFileInfo *MOFI = Context.getObjectFileInfo();
FrameEmitterImpl Emitter(UsingCFI, IsEH);
ArrayRef<MCDwarfFrameInfo> FrameArray = Streamer.getFrameInfos();
// Emit the compact unwind info if available.
- if (IsEH && MOFI->getCompactUnwindSection())
- for (unsigned i = 0, n = Streamer.getNumFrameInfos(); i < n; ++i) {
- const MCDwarfFrameInfo &Frame = Streamer.getFrameInfo(i);
- if (Frame.CompactUnwindEncoding)
- Emitter.EmitCompactUnwind(Streamer, Frame);
+ if (IsEH && MOFI->getCompactUnwindSection()) {
+ bool SectionEmitted = false;
+ for (unsigned i = 0, n = FrameArray.size(); i < n; ++i) {
+ const MCDwarfFrameInfo &Frame = FrameArray[i];
+ if (Frame.CompactUnwindEncoding == 0) continue;
+ if (!SectionEmitted) {
+ Streamer.SwitchSection(MOFI->getCompactUnwindSection());
+ Streamer.EmitValueToAlignment(Context.getAsmInfo()->getPointerSize());
+ SectionEmitted = true;
+ }
+ Emitter.EmitCompactUnwind(Streamer, Frame);
}
+ }
- const MCSection &Section = IsEH ? *MOFI->getEHFrameSection() :
- *MOFI->getDwarfFrameSection();
+ const MCSection &Section =
+ IsEH ? *const_cast<MCObjectFileInfo*>(MOFI)->getEHFrameSection() :
+ *MOFI->getDwarfFrameSection();
Streamer.SwitchSection(&Section);
MCSymbol *SectionStart = Context.CreateTempSymbol();
Streamer.EmitLabel(SectionStart);
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;