//
//===----------------------------------------------------------------------===//
-#include "llvm/ADT/FoldingSet.h"
-#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCDwarf.h"
-#include "llvm/MC/MCAssembler.h"
+#include "llvm/MC/MCAsmInfo.h"
+#include "llvm/MC/MCContext.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"
#include "llvm/MC/MCExpr.h"
-#include "llvm/MC/MCContext.h"
-#include "llvm/MC/MCObjectWriter.h"
-#include "llvm/ADT/SmallString.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"
-#include "llvm/Target/TargetAsmBackend.h"
-#include "llvm/Target/TargetAsmInfo.h"
+#include "llvm/ADT/FoldingSet.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/Twine.h"
using namespace llvm;
// Given a special op, return the address skip amount (in units of
#define SPECIAL_ADDR(op) (((op) - DWARF2_LINE_OPCODE_BASE)/DWARF2_LINE_RANGE)
// The maximum address skip amount that can be encoded with a special op.
-#define MAX_SPECIAL_ADDR_DELTA SPECIAL_ADDR(255)
+#define MAX_SPECIAL_ADDR_DELTA SPECIAL_ADDR(255)
// First special line opcode - leave room for the standard opcodes.
// Note: If you want to change this, you'll have to update the
// "standard_opcode_lengths" table that is emitted in DwarfFileTable::Emit().
-#define DWARF2_LINE_OPCODE_BASE 13
+#define DWARF2_LINE_OPCODE_BASE 13
// Minimum line offset in a special line info. opcode. This value
// was chosen to give a reasonable range of values.
-#define DWARF2_LINE_BASE -5
+#define DWARF2_LINE_BASE -5
// Range of line offsets in a special line info. opcode.
-# define DWARF2_LINE_RANGE 14
+#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
+#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)
-{
+static inline uint64_t ScaleAddrDelta(uint64_t AddrDelta) {
if (DWARF2_LINE_MIN_INSN_LENGTH == 1)
return AddrDelta;
if (AddrDelta % DWARF2_LINE_MIN_INSN_LENGTH != 0) {
// 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.
- MCOS->EmitDwarfAdvanceLineAddr(LineDelta, LastLabel, Label);
+ const MCAsmInfo &asmInfo = MCOS->getContext().getAsmInfo();
+ MCOS->EmitDwarfAdvanceLineAddr(LineDelta, LastLabel, Label,
+ asmInfo.getPointerSize());
LastLine = it->getLine();
LastLabel = Label;
MCOS->EmitLabel(SectionEnd);
// Switch back the the dwarf line section.
- MCOS->SwitchSection(context.getTargetAsmInfo().getDwarfLineSection());
+ MCOS->SwitchSection(context.getObjectFileInfo()->getDwarfLineSection());
- MCOS->EmitDwarfAdvanceLineAddr(INT64_MAX, LastLabel, SectionEnd);
+ const MCAsmInfo &asmInfo = MCOS->getContext().getAsmInfo();
+ MCOS->EmitDwarfAdvanceLineAddr(INT64_MAX, LastLabel, SectionEnd,
+ asmInfo.getPointerSize());
}
//
void MCDwarfFileTable::Emit(MCStreamer *MCOS) {
MCContext &context = MCOS->getContext();
// Switch to the section where the table will be emitted into.
- MCOS->SwitchSection(context.getTargetAsmInfo().getDwarfLineSection());
+ MCOS->SwitchSection(context.getObjectFileInfo()->getDwarfLineSection());
// Create a symbol at the beginning of this section.
MCSymbol *LineStartSym = context.CreateTempSymbol();
const std::vector<const MCSection *> &MCLineSectionOrder =
MCOS->getContext().getMCLineSectionOrder();
for (std::vector<const MCSection*>::const_iterator it =
- MCLineSectionOrder.begin(), ie = MCLineSectionOrder.end(); it != ie;
+ MCLineSectionOrder.begin(), ie = MCLineSectionOrder.end(); it != ie;
++it) {
const MCSection *Sec = *it;
const MCLineSection *Line = MCLineSections.lookup(Sec);
OS << char(dwarf::DW_LNS_const_add_pc);
else {
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);
}
OS << char(dwarf::DW_LNS_extended_op);
OS << char(1);
static int getDataAlignmentFactor(MCStreamer &streamer) {
MCContext &context = streamer.getContext();
- const TargetAsmInfo &asmInfo = context.getTargetAsmInfo();
+ const MCAsmInfo &asmInfo = context.getAsmInfo();
int size = asmInfo.getPointerSize();
- if (asmInfo.getStackGrowthDirection() == TargetFrameLowering::StackGrowsUp)
+ if (asmInfo.isStackGrowthDirectionUp())
return size;
- else
- return -size;
+ else
+ return -size;
}
static unsigned getSizeForEncoding(MCStreamer &streamer,
unsigned symbolEncoding) {
MCContext &context = streamer.getContext();
- const TargetAsmInfo &asmInfo = context.getTargetAsmInfo();
unsigned format = symbolEncoding & 0x0f;
switch (format) {
default:
assert(0 && "Unknown Encoding");
case dwarf::DW_EH_PE_absptr:
case dwarf::DW_EH_PE_signed:
- return asmInfo.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) {
+ unsigned symbolEncoding, const char *comment = 0) {
MCContext &context = streamer.getContext();
+ const MCAsmInfo &asmInfo = context.getAsmInfo();
+ const MCExpr *v = asmInfo.getExprForFDESymbol(&symbol,
+ symbolEncoding,
+ streamer);
unsigned size = getSizeForEncoding(streamer, symbolEncoding);
- unsigned application = symbolEncoding & 0x70;
- switch (application) {
- default:
- assert(0 && "Unknown Encoding");
- break;
- case 0:
- streamer.EmitSymbolValue(&symbol, size);
- break;
- case dwarf::DW_EH_PE_pcrel:
- streamer.EmitPCRelSymbolValue(&symbol, size);
- break;
- }
+ 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);
+ unsigned size = getSizeForEncoding(streamer, symbolEncoding);
+ streamer.EmitValue(v, size);
}
static const MachineLocation TranslateMachineLocation(
- const TargetAsmInfo &AsmInfo,
+ const MCRegisterInfo &MRI,
const MachineLocation &Loc) {
unsigned Reg = Loc.getReg() == MachineLocation::VirtualFP ?
MachineLocation::VirtualFP :
- unsigned(AsmInfo.getDwarfRegNum(Loc.getReg(), true));
+ unsigned(MRI.getDwarfRegNum(Loc.getReg(), true));
const MachineLocation &NewLoc = Loc.isReg() ?
MachineLocation(Reg) : MachineLocation(Reg, Loc.getOffset());
return NewLoc;
namespace {
class FrameEmitterImpl {
int CFAOffset;
-
+ int CIENum;
+ bool UsingCFI;
+ bool IsEH;
+ const MCSymbol *SectionStart;
public:
- FrameEmitterImpl() : CFAOffset(0) {
- }
+ FrameEmitterImpl(bool usingCFI, bool isEH)
+ : CFAOffset(0), CIENum(0), UsingCFI(usingCFI), IsEH(isEH),
+ SectionStart(0) {}
+
+ 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,
+ const MCDwarfFrameInfo &frame);
const MCSymbol &EmitCIE(MCStreamer &streamer,
const MCSymbol *personality,
void EmitCFIInstruction(MCStreamer &Streamer,
const MCCFIInstruction &Instr);
};
+
+} // end anonymous namespace
+
+static void EmitEncodingByte(MCStreamer &Streamer, unsigned Encoding,
+ StringRef Prefix) {
+ if (Streamer.isVerboseAsm()) {
+ const char *EncStr = 0;
+ 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";
+ case dwarf::DW_EH_PE_indirect |dwarf::DW_EH_PE_pcrel|dwarf::DW_EH_PE_udata4:
+ EncStr = "indirect pcrel udata4";
+ case dwarf::DW_EH_PE_indirect |dwarf::DW_EH_PE_pcrel|dwarf::DW_EH_PE_sdata4:
+ EncStr = "indirect pcrel sdata4";
+ case dwarf::DW_EH_PE_indirect |dwarf::DW_EH_PE_pcrel|dwarf::DW_EH_PE_udata8:
+ EncStr = "indirect pcrel udata8";
+ case dwarf::DW_EH_PE_indirect |dwarf::DW_EH_PE_pcrel|dwarf::DW_EH_PE_sdata8:
+ EncStr = "indirect pcrel sdata8";
+ }
+
+ Streamer.AddComment(Twine(Prefix) + " = " + EncStr);
+ }
+
+ Streamer.EmitIntValue(Encoding, 1);
}
void FrameEmitterImpl::EmitCFIInstruction(MCStreamer &Streamer,
const MCCFIInstruction &Instr) {
int dataAlignmentFactor = getDataAlignmentFactor(Streamer);
+ bool VerboseAsm = Streamer.isVerboseAsm();
switch (Instr.getOperation()) {
case MCCFIInstruction::Move:
// If advancing cfa.
if (Dst.isReg() && Dst.getReg() == MachineLocation::VirtualFP) {
- assert(!Src.isReg() && "Machine move not supported yet.");
-
if (Src.getReg() == MachineLocation::VirtualFP) {
+ if (VerboseAsm) Streamer.AddComment("DW_CFA_def_cfa_offset");
Streamer.EmitIntValue(dwarf::DW_CFA_def_cfa_offset, 1);
} else {
+ if (VerboseAsm) Streamer.AddComment("DW_CFA_def_cfa");
Streamer.EmitIntValue(dwarf::DW_CFA_def_cfa, 1);
+ if (VerboseAsm) Streamer.AddComment(Twine("Reg ") +
+ Twine(Src.getReg()));
Streamer.EmitULEB128IntValue(Src.getReg());
}
else
CFAOffset = -Src.getOffset();
+ if (VerboseAsm) Streamer.AddComment(Twine("Offset " + Twine(CFAOffset)));
Streamer.EmitULEB128IntValue(CFAOffset);
return;
}
if (Src.isReg() && Src.getReg() == MachineLocation::VirtualFP) {
assert(Dst.isReg() && "Machine move not supported yet.");
+ if (VerboseAsm) Streamer.AddComment("DW_CFA_def_cfa_register");
Streamer.EmitIntValue(dwarf::DW_CFA_def_cfa_register, 1);
+ if (VerboseAsm) Streamer.AddComment(Twine("Reg ") + Twine(Dst.getReg()));
Streamer.EmitULEB128IntValue(Dst.getReg());
return;
}
unsigned Reg = Src.getReg();
-
int Offset = Dst.getOffset();
if (IsRelative)
Offset -= CFAOffset;
Offset = Offset / dataAlignmentFactor;
if (Offset < 0) {
+ if (VerboseAsm) Streamer.AddComment("DW_CFA_offset_extended_sf");
Streamer.EmitIntValue(dwarf::DW_CFA_offset_extended_sf, 1);
+ if (VerboseAsm) Streamer.AddComment(Twine("Reg ") + Twine(Reg));
Streamer.EmitULEB128IntValue(Reg);
+ if (VerboseAsm) Streamer.AddComment(Twine("Offset ") + Twine(Offset));
Streamer.EmitSLEB128IntValue(Offset);
} else if (Reg < 64) {
+ if (VerboseAsm) Streamer.AddComment(Twine("DW_CFA_offset + Reg(") +
+ Twine(Reg) + ")");
Streamer.EmitIntValue(dwarf::DW_CFA_offset + Reg, 1);
+ if (VerboseAsm) Streamer.AddComment(Twine("Offset ") + Twine(Offset));
Streamer.EmitULEB128IntValue(Offset);
} else {
+ if (VerboseAsm) Streamer.AddComment("DW_CFA_offset_extended");
Streamer.EmitIntValue(dwarf::DW_CFA_offset_extended, 1);
+ if (VerboseAsm) Streamer.AddComment(Twine("Reg ") + Twine(Reg));
Streamer.EmitULEB128IntValue(Reg);
+ if (VerboseAsm) Streamer.AddComment(Twine("Offset ") + Twine(Offset));
Streamer.EmitULEB128IntValue(Offset);
}
return;
}
case MCCFIInstruction::Remember:
+ if (VerboseAsm) Streamer.AddComment("DW_CFA_remember_state");
Streamer.EmitIntValue(dwarf::DW_CFA_remember_state, 1);
return;
case MCCFIInstruction::Restore:
+ if (VerboseAsm) Streamer.AddComment("DW_CFA_restore_state");
Streamer.EmitIntValue(dwarf::DW_CFA_restore_state, 1);
return;
case MCCFIInstruction::SameValue: {
unsigned Reg = Instr.getDestination().getReg();
+ if (VerboseAsm) Streamer.AddComment("DW_CFA_same_value");
Streamer.EmitIntValue(dwarf::DW_CFA_same_value, 1);
+ if (VerboseAsm) Streamer.AddComment(Twine("Reg ") + Twine(Reg));
Streamer.EmitULEB128IntValue(Reg);
return;
}
if (BaseLabel && Label) {
MCSymbol *ThisSym = Label;
if (ThisSym != BaseLabel) {
+ if (streamer.isVerboseAsm()) streamer.AddComment("DW_CFA_advance_loc4");
streamer.EmitDwarfAdvanceFrameAddr(BaseLabel, ThisSym);
BaseLabel = ThisSym;
}
}
}
+/// 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,
+ const MCDwarfFrameInfo &Frame) {
+ MCContext &Context = Streamer.getContext();
+ const MCObjectFileInfo *MOFI = Context.getObjectFileInfo();
+ bool VerboseAsm = Streamer.isVerboseAsm();
+
+ // range-start range-length compact-unwind-enc personality-func lsda
+ // _foo LfooEnd-_foo 0x00000023 0 0
+ // _bar LbarEnd-_bar 0x00000025 __gxx_personality except_tab1
+ //
+ // .section __LD,__compact_unwind,regular,debug
+ //
+ // # compact unwind for _foo
+ // .quad _foo
+ // .set L1,LfooEnd-_foo
+ // .long L1
+ // .long 0x01010001
+ // .quad 0
+ // .quad 0
+ //
+ // # compact unwind for _bar
+ // .quad _bar
+ // .set L2,LbarEnd-_bar
+ // .long L2
+ // .long 0x01020011
+ // .quad __gxx_personality
+ // .quad except_tab1
+
+ uint32_t Encoding = Frame.CompactUnwindEncoding;
+ if (!Encoding) return false;
+
+ // The encoding needs to know we have an LSDA.
+ if (Frame.Lsda)
+ Encoding |= 0x40000000;
+
+ Streamer.SwitchSection(MOFI->getCompactUnwindSection());
+
+ // Range Start
+ unsigned FDEEncoding = MOFI->getFDEEncoding(UsingCFI);
+ unsigned Size = getSizeForEncoding(Streamer, FDEEncoding);
+ if (VerboseAsm) Streamer.AddComment("Range Start");
+ Streamer.EmitSymbolValue(Frame.Function, Size);
+
+ // Range Length
+ const MCExpr *Range = MakeStartMinusEndExpr(Streamer, *Frame.Begin,
+ *Frame.End, 0);
+ if (VerboseAsm) Streamer.AddComment("Range Length");
+ Streamer.EmitAbsValue(Range, 4);
+
+ // Compact Encoding
+ Size = getSizeForEncoding(Streamer, dwarf::DW_EH_PE_udata4);
+ if (VerboseAsm) Streamer.AddComment(Twine("Compact Unwind Encoding: 0x") +
+ Twine(llvm::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)
+ 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)
+ Streamer.EmitSymbolValue(Frame.Lsda, Size);
+ else
+ Streamer.EmitIntValue(0, Size); // No LSDA
+
+ return true;
+}
+
const MCSymbol &FrameEmitterImpl::EmitCIE(MCStreamer &streamer,
const MCSymbol *personality,
unsigned personalityEncoding,
const MCSymbol *lsda,
unsigned lsdaEncoding) {
MCContext &context = streamer.getContext();
- const TargetAsmInfo &asmInfo = context.getTargetAsmInfo();
- const MCSection §ion = *asmInfo.getEHFrameSection();
- streamer.SwitchSection(§ion);
- MCSymbol *sectionStart = streamer.getContext().CreateTempSymbol();
- MCSymbol *sectionEnd = streamer.getContext().CreateTempSymbol();
+ const MCRegisterInfo &MRI = context.getRegisterInfo();
+ const MCObjectFileInfo *MOFI = context.getObjectFileInfo();
+ bool verboseAsm = streamer.isVerboseAsm();
+
+ MCSymbol *sectionStart;
+ if (MOFI->isFunctionEHFrameSymbolPrivate() || !IsEH)
+ sectionStart = context.CreateTempSymbol();
+ else
+ sectionStart = context.GetOrCreateSymbol(Twine("EH_frame") + Twine(CIENum));
+
+ streamer.EmitLabel(sectionStart);
+ CIENum++;
+
+ MCSymbol *sectionEnd = context.CreateTempSymbol();
// Length
const MCExpr *Length = MakeStartMinusEndExpr(streamer, *sectionStart,
*sectionEnd, 4);
- streamer.EmitLabel(sectionStart);
- streamer.EmitValue(Length, 4);
+ if (verboseAsm) streamer.AddComment("CIE Length");
+ streamer.EmitAbsValue(Length, 4);
// CIE ID
- streamer.EmitIntValue(0, 4);
+ unsigned CIE_ID = IsEH ? 0 : -1;
+ if (verboseAsm) streamer.AddComment("CIE ID Tag");
+ streamer.EmitIntValue(CIE_ID, 4);
// Version
+ if (verboseAsm) streamer.AddComment("DW_CIE_VERSION");
streamer.EmitIntValue(dwarf::DW_CIE_VERSION, 1);
// Augmentation String
SmallString<8> Augmentation;
- Augmentation += "z";
- if (personality)
- Augmentation += "P";
- if (lsda)
- Augmentation += "L";
- Augmentation += "R";
- streamer.EmitBytes(Augmentation.str(), 0);
+ if (IsEH) {
+ if (verboseAsm) streamer.AddComment("CIE Augmentation");
+ Augmentation += "z";
+ if (personality)
+ Augmentation += "P";
+ if (lsda)
+ Augmentation += "L";
+ Augmentation += "R";
+ streamer.EmitBytes(Augmentation.str(), 0);
+ }
streamer.EmitIntValue(0, 1);
// Code Alignment Factor
+ if (verboseAsm) streamer.AddComment("CIE Code Alignment Factor");
streamer.EmitULEB128IntValue(1);
// Data Alignment Factor
+ if (verboseAsm) streamer.AddComment("CIE Data Alignment Factor");
streamer.EmitSLEB128IntValue(getDataAlignmentFactor(streamer));
// Return Address Register
- streamer.EmitULEB128IntValue(asmInfo.getDwarfRARegNum(true));
+ if (verboseAsm) streamer.AddComment("CIE Return Address Column");
+ streamer.EmitULEB128IntValue(MRI.getDwarfRegNum(MRI.getRARegister(), true));
// Augmentation Data Length (optional)
- MCSymbol *augmentationStart = streamer.getContext().CreateTempSymbol();
- MCSymbol *augmentationEnd = streamer.getContext().CreateTempSymbol();
- const MCExpr *augmentationLength = MakeStartMinusEndExpr(streamer,
- *augmentationStart,
- *augmentationEnd, 0);
- streamer.EmitULEB128Value(augmentationLength);
-
- // Augmentation Data (optional)
- streamer.EmitLabel(augmentationStart);
- if (personality) {
- // Personality Encoding
- streamer.EmitIntValue(personalityEncoding, 1);
- // Personality
- EmitSymbol(streamer, *personality, personalityEncoding);
- }
- if (lsda) {
- // LSDA Encoding
- streamer.EmitIntValue(lsdaEncoding, 1);
+
+ unsigned augmentationLength = 0;
+ if (IsEH) {
+ if (personality) {
+ // Personality Encoding
+ augmentationLength += 1;
+ // Personality
+ augmentationLength += getSizeForEncoding(streamer, personalityEncoding);
+ }
+ if (lsda)
+ augmentationLength += 1;
+ // Encoding of the FDE pointers
+ augmentationLength += 1;
+
+ if (verboseAsm) streamer.AddComment("Augmentation Size");
+ streamer.EmitULEB128IntValue(augmentationLength);
+
+ // Augmentation Data (optional)
+ if (personality) {
+ // Personality Encoding
+ EmitEncodingByte(streamer, personalityEncoding,
+ "Personality Encoding");
+ // Personality
+ if (verboseAsm) streamer.AddComment("Personality");
+ EmitPersonality(streamer, *personality, personalityEncoding);
+ }
+
+ if (lsda)
+ EmitEncodingByte(streamer, lsdaEncoding, "LSDA Encoding");
+
+ // Encoding of the FDE pointers
+ EmitEncodingByte(streamer, MOFI->getFDEEncoding(UsingCFI),
+ "FDE Encoding");
}
- // Encoding of the FDE pointers
- streamer.EmitIntValue(asmInfo.getFDEEncoding(), 1);
- streamer.EmitLabel(augmentationEnd);
// Initial Instructions
- const std::vector<MachineMove> Moves = asmInfo.getInitialFrameState();
+ 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(asmInfo, Moves[i].getDestination());
+ TranslateMachineLocation(MRI, Moves[i].getDestination());
const MachineLocation &Src =
- TranslateMachineLocation(asmInfo, Moves[i].getSource());
+ TranslateMachineLocation(MRI, Moves[i].getSource());
MCCFIInstruction Inst(Label, Dst, Src);
Instructions.push_back(Inst);
}
EmitCFIInstructions(streamer, Instructions, NULL);
// Padding
- streamer.EmitValueToAlignment(4);
+ streamer.EmitValueToAlignment(IsEH
+ ? 4 : context.getAsmInfo().getPointerSize());
streamer.EmitLabel(sectionEnd);
return *sectionStart;
MCContext &context = streamer.getContext();
MCSymbol *fdeStart = context.CreateTempSymbol();
MCSymbol *fdeEnd = context.CreateTempSymbol();
- const TargetAsmInfo &asmInfo = context.getTargetAsmInfo();
+ const MCObjectFileInfo *MOFI = context.getObjectFileInfo();
+ bool verboseAsm = streamer.isVerboseAsm();
+
+ if (!MOFI->isFunctionEHFrameSymbolPrivate() && IsEH) {
+ MCSymbol *EHSym =
+ context.GetOrCreateSymbol(frame.Function->getName() + Twine(".eh"));
+ streamer.EmitEHSymAttributes(frame.Function, EHSym);
+ streamer.EmitLabel(EHSym);
+ }
// Length
const MCExpr *Length = MakeStartMinusEndExpr(streamer, *fdeStart, *fdeEnd, 0);
- streamer.EmitValue(Length, 4);
+ if (verboseAsm) streamer.AddComment("FDE Length");
+ streamer.EmitAbsValue(Length, 4);
streamer.EmitLabel(fdeStart);
+
// CIE Pointer
- const MCExpr *offset = MakeStartMinusEndExpr(streamer, cieStart, *fdeStart,
- 0);
- streamer.EmitValue(offset, 4);
- unsigned fdeEncoding = asmInfo.getFDEEncoding();
+ 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.doesDwarfRequireRelocationForSectionOffset()) {
+ const MCExpr *offset = MakeStartMinusEndExpr(streamer, *SectionStart,
+ cieStart, 0);
+ streamer.EmitAbsValue(offset, 4);
+ } else {
+ streamer.EmitSymbolValue(&cieStart, 4);
+ }
+
+ unsigned fdeEncoding = MOFI->getFDEEncoding(UsingCFI);
unsigned size = getSizeForEncoding(streamer, fdeEncoding);
// PC Begin
- streamer.EmitPCRelSymbolValue(frame.Begin, size);
+ unsigned PCBeginEncoding = IsEH ? fdeEncoding :
+ (unsigned)dwarf::DW_EH_PE_absptr;
+ unsigned PCBeginSize = getSizeForEncoding(streamer, PCBeginEncoding);
+ EmitSymbol(streamer, *frame.Begin, PCBeginEncoding, "FDE initial location");
// PC Range
const MCExpr *Range = MakeStartMinusEndExpr(streamer, *frame.Begin,
*frame.End, 0);
- streamer.EmitValue(Range, size);
-
- // Augmentation Data Length
- MCSymbol *augmentationStart = streamer.getContext().CreateTempSymbol();
- MCSymbol *augmentationEnd = streamer.getContext().CreateTempSymbol();
- const MCExpr *augmentationLength = MakeStartMinusEndExpr(streamer,
- *augmentationStart,
- *augmentationEnd, 0);
- streamer.EmitULEB128Value(augmentationLength);
-
- // Augmentation Data
- streamer.EmitLabel(augmentationStart);
- if (frame.Lsda)
- EmitSymbol(streamer, *frame.Lsda, frame.LsdaEncoding);
- streamer.EmitLabel(augmentationEnd);
+ if (verboseAsm) streamer.AddComment("FDE address range");
+ streamer.EmitAbsValue(Range, size);
+
+ if (IsEH) {
+ // Augmentation Data Length
+ unsigned augmentationLength = 0;
+
+ if (frame.Lsda)
+ augmentationLength += getSizeForEncoding(streamer, frame.LsdaEncoding);
+
+ if (verboseAsm) streamer.AddComment("Augmentation size");
+ streamer.EmitULEB128IntValue(augmentationLength);
+
+ // Augmentation Data
+ if (frame.Lsda)
+ EmitSymbol(streamer, *frame.Lsda, frame.LsdaEncoding,
+ "Language Specific Data Area");
+ }
+
// Call Frame Instructions
EmitCFIInstructions(streamer, frame.Instructions, frame.Begin);
// Padding
- streamer.EmitValueToAlignment(4);
+ streamer.EmitValueToAlignment(PCBeginSize);
return fdeEnd;
}
};
}
-void MCDwarfFrameEmitter::Emit(MCStreamer &streamer) {
- const MCContext &context = streamer.getContext();
- const TargetAsmInfo &asmInfo = context.getTargetAsmInfo();
- MCSymbol *fdeEnd = NULL;
+void MCDwarfFrameEmitter::Emit(MCStreamer &Streamer,
+ bool UsingCFI,
+ bool IsEH) {
+ MCContext &Context = Streamer.getContext();
+ MCObjectFileInfo *MOFI =
+ const_cast<MCObjectFileInfo*>(Context.getObjectFileInfo());
+ FrameEmitterImpl Emitter(UsingCFI, IsEH);
+ SmallVector<MCDwarfFrameInfo, 8> RequiresFDE;
+ ArrayRef<MCDwarfFrameInfo> FrameArray;
+
+ 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))
+ RequiresFDE.push_back(Streamer.getFrameInfo(i));
+ }
+
+ // Early exit if we don't need to emit FDEs.
+ if (RequiresFDE.empty()) return;
+ FrameArray = RequiresFDE;
+ } else {
+ FrameArray = Streamer.getFrameInfos();
+ }
+
+ const MCSection &Section = IsEH ? *MOFI->getEHFrameSection() :
+ *MOFI->getDwarfFrameSection();
+ Streamer.SwitchSection(&Section);
+ MCSymbol *SectionStart = Context.CreateTempSymbol();
+ Streamer.EmitLabel(SectionStart);
+ Emitter.setSectionStart(SectionStart);
+
+ MCSymbol *FDEEnd = NULL;
DenseMap<CIEKey, const MCSymbol*> CIEStarts;
- FrameEmitterImpl Emitter;
-
- for (unsigned i = 0, n = streamer.getNumFrameInfos(); i < n; ++i) {
- const MCDwarfFrameInfo &frame = streamer.getFrameInfo(i);
- CIEKey key(frame.Personality, frame.PersonalityEncoding,
- frame.LsdaEncoding);
- const MCSymbol *&cieStart = CIEStarts[key];
- if (!cieStart)
- cieStart = &Emitter.EmitCIE(streamer, frame.Personality,
- frame.PersonalityEncoding, frame.Lsda,
- frame.LsdaEncoding);
- fdeEnd = Emitter.EmitFDE(streamer, *cieStart, frame);
+
+ const MCSymbol *DummyDebugKey = NULL;
+ for (unsigned i = 0, n = FrameArray.size(); i < n; ++i) {
+ const MCDwarfFrameInfo &Frame = FrameArray[i];
+ CIEKey Key(Frame.Personality, Frame.PersonalityEncoding,
+ Frame.LsdaEncoding);
+ const MCSymbol *&CIEStart = IsEH ? CIEStarts[Key] : DummyDebugKey;
+ if (!CIEStart)
+ CIEStart = &Emitter.EmitCIE(Streamer, Frame.Personality,
+ Frame.PersonalityEncoding, Frame.Lsda,
+ Frame.LsdaEncoding);
+
+ FDEEnd = Emitter.EmitFDE(Streamer, *CIEStart, Frame);
+
if (i != n - 1)
- streamer.EmitLabel(fdeEnd);
+ Streamer.EmitLabel(FDEEnd);
}
- streamer.EmitValueToAlignment(asmInfo.getPointerSize());
- if (fdeEnd)
- streamer.EmitLabel(fdeEnd);
+ Streamer.EmitValueToAlignment(Context.getAsmInfo().getPointerSize());
+ if (FDEEnd)
+ Streamer.EmitLabel(FDEEnd);
}
void MCDwarfFrameEmitter::EmitAdvanceLoc(MCStreamer &Streamer,