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 void EmitSymbol(MCStreamer &streamer, const MCSymbol &symbol,
unsigned symbolEncoding) {
+ 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;
- }
+ 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(
namespace {
class FrameEmitterImpl {
int CFAOffset;
+ int CIENum;
+ bool UsingCFI;
+ bool IsEH;
+ const MCSymbol *SectionStart;
public:
- FrameEmitterImpl() : CFAOffset(0) {
+ FrameEmitterImpl(bool usingCFI, bool isEH, const MCSymbol *sectionStart) :
+ CFAOffset(0), CIENum(0), UsingCFI(usingCFI), IsEH(isEH),
+ SectionStart(sectionStart) {
}
+ /// 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,
unsigned personalityEncoding,
// If advancing cfa.
if (Dst.isReg() && Dst.getReg() == MachineLocation::VirtualFP) {
- assert(!Src.isReg() && "Machine move not supported yet.");
-
if (Src.getReg() == MachineLocation::VirtualFP) {
Streamer.EmitIntValue(dwarf::DW_CFA_def_cfa_offset, 1);
} else {
}
}
+/// 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) {
+#if 1
+ return false;
+#else
+ MCContext &Context = Streamer.getContext();
+ const TargetAsmInfo &TAI = Context.getTargetAsmInfo();
+ Streamer.SwitchSection(TAI.getCompactUnwindSection());
+
+ unsigned FDEEncoding = TAI.getFDEEncoding(UsingCFI);
+ unsigned Size = getSizeForEncoding(Streamer, FDEEncoding);
+
+ // 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
+
+ // Range Start
+ EmitSymbol(Streamer, *Frame.Begin, FDEEncoding);
+
+ // Range Length
+ const MCExpr *Range = MakeStartMinusEndExpr(Streamer, *Frame.Begin,
+ *Frame.End, 0);
+ Streamer.EmitAbsValue(Range, Size);
+
+ return true;
+#endif
+}
+
const MCSymbol &FrameEmitterImpl::EmitCIE(MCStreamer &streamer,
const MCSymbol *personality,
unsigned personalityEncoding,
unsigned lsdaEncoding) {
MCContext &context = streamer.getContext();
const TargetAsmInfo &asmInfo = context.getTargetAsmInfo();
- const MCSection §ion = *asmInfo.getEHFrameSection();
- streamer.SwitchSection(§ion);
- MCSymbol *sectionStart = context.CreateTempSymbol();
+
+ MCSymbol *sectionStart;
+ if (asmInfo.isFunctionEHFrameSymbolPrivate() || !IsEH)
+ sectionStart = context.CreateTempSymbol();
+ else
+ sectionStart = context.GetOrCreateSymbol(Twine("EH_frame") + Twine(CIENum));
+
+ CIENum++;
+
MCSymbol *sectionEnd = streamer.getContext().CreateTempSymbol();
// Length
streamer.EmitAbsValue(Length, 4);
// CIE ID
- streamer.EmitIntValue(0, 4);
+ unsigned CIE_ID = IsEH ? 0 : -1;
+ streamer.EmitIntValue(CIE_ID, 4);
// 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) {
+ Augmentation += "z";
+ if (personality)
+ Augmentation += "P";
+ if (lsda)
+ Augmentation += "L";
+ Augmentation += "R";
+ streamer.EmitBytes(Augmentation.str(), 0);
+ }
streamer.EmitIntValue(0, 1);
// Code Alignment Factor
streamer.EmitULEB128IntValue(asmInfo.getDwarfRARegNum(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;
+
+ streamer.EmitULEB128IntValue(augmentationLength);
+
+ // Augmentation Data (optional)
+ if (personality) {
+ // Personality Encoding
+ streamer.EmitIntValue(personalityEncoding, 1);
+ // Personality
+ EmitPersonality(streamer, *personality, personalityEncoding);
+ }
+ if (lsda)
+ streamer.EmitIntValue(lsdaEncoding, 1); // LSDA Encoding
+ // Encoding of the FDE pointers
+ streamer.EmitIntValue(asmInfo.getFDEEncoding(UsingCFI), 1);
}
- // Encoding of the FDE pointers
- streamer.EmitIntValue(asmInfo.getFDEEncoding(), 1);
- streamer.EmitLabel(augmentationEnd);
// Initial Instructions
EmitCFIInstructions(streamer, Instructions, NULL);
// Padding
- streamer.EmitValueToAlignment(4);
+ streamer.EmitValueToAlignment(IsEH ? 4 : asmInfo.getPointerSize());
streamer.EmitLabel(sectionEnd);
return *sectionStart;
MCContext &context = streamer.getContext();
MCSymbol *fdeStart = context.CreateTempSymbol();
MCSymbol *fdeEnd = context.CreateTempSymbol();
- const TargetAsmInfo &asmInfo = context.getTargetAsmInfo();
+ const TargetAsmInfo &TAsmInfo = context.getTargetAsmInfo();
- if (!asmInfo.isFunctionEHFrameSymbolPrivate()) {
- Twine EHName = frame.Function->getName() + Twine(".eh");
- MCSymbol *EHSym = context.GetOrCreateSymbol(EHName);
+ if (!TAsmInfo.isFunctionEHFrameSymbolPrivate() && IsEH) {
+ MCSymbol *EHSym = context.GetOrCreateSymbol(
+ frame.Function->getName() + Twine(".eh"));
+ streamer.EmitEHSymAttributes(frame.Function, EHSym);
streamer.EmitLabel(EHSym);
}
streamer.EmitAbsValue(Length, 4);
streamer.EmitLabel(fdeStart);
+
// CIE Pointer
- const MCExpr *offset = MakeStartMinusEndExpr(streamer, cieStart, *fdeStart,
- 0);
- streamer.EmitAbsValue(offset, 4);
- unsigned fdeEncoding = asmInfo.getFDEEncoding();
+ const MCAsmInfo &asmInfo = context.getAsmInfo();
+ if (IsEH) {
+ const MCExpr *offset = MakeStartMinusEndExpr(streamer, cieStart, *fdeStart,
+ 0);
+ 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 = TAsmInfo.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);
// PC Range
const MCExpr *Range = MakeStartMinusEndExpr(streamer, *frame.Begin,
*frame.End, 0);
streamer.EmitAbsValue(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 (IsEH) {
+ // Augmentation Data Length
+ unsigned augmentationLength = 0;
+
+ if (frame.Lsda)
+ augmentationLength += getSizeForEncoding(streamer, frame.LsdaEncoding);
+
+ streamer.EmitULEB128IntValue(augmentationLength);
+
+ // Augmentation Data
+ if (frame.Lsda)
+ EmitSymbol(streamer, *frame.Lsda, frame.LsdaEncoding);
+ }
+
// Call Frame Instructions
EmitCFIInstructions(streamer, frame.Instructions, frame.Begin);
// Padding
- streamer.EmitValueToAlignment(size);
+ streamer.EmitValueToAlignment(PCBeginSize);
return fdeEnd;
}
};
}
-void MCDwarfFrameEmitter::Emit(MCStreamer &streamer) {
- const MCContext &context = streamer.getContext();
+void MCDwarfFrameEmitter::Emit(MCStreamer &streamer,
+ bool usingCFI,
+ bool isEH) {
+ MCContext &context = streamer.getContext();
const TargetAsmInfo &asmInfo = context.getTargetAsmInfo();
+ const MCSection §ion = isEH ?
+ *asmInfo.getEHFrameSection() :
+ *asmInfo.getDwarfFrameSection();
+ streamer.SwitchSection(§ion);
+ MCSymbol *SectionStart = context.CreateTempSymbol();
+ streamer.EmitLabel(SectionStart);
+
MCSymbol *fdeEnd = NULL;
DenseMap<CIEKey, const MCSymbol*> CIEStarts;
- FrameEmitterImpl Emitter;
+ FrameEmitterImpl Emitter(usingCFI, isEH, SectionStart);
+ const MCSymbol *DummyDebugKey = NULL;
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];
+ const MCSymbol *&cieStart = isEH ? CIEStarts[key] : DummyDebugKey;
+ if (isEH && asmInfo.getSupportsCompactUnwindInfo() &&
+ Emitter.EmitCompactUnwind(streamer, frame))
+ continue;
+
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);
}