diff --git a/include/llvm/MC/MCObjectFileInfo.h b/include/llvm/MC/MCObjectFileInfo.h index 25246929ce5..1c5c19e51c3 100644 --- a/include/llvm/MC/MCObjectFileInfo.h +++ b/include/llvm/MC/MCObjectFileInfo.h @@ -39,6 +39,11 @@ protected: /// non-.globl label. This defaults to true. bool IsFunctionEHFrameSymbolPrivate; + /// SupportsCompactUnwindWithoutEHFrame - True if the target object file + /// supports emitting a compact unwind section without an associated EH frame + /// section. + bool SupportsCompactUnwindWithoutEHFrame; + /// PersonalityEncoding, LSDAEncoding, FDEEncoding, TTypeEncoding - Some /// encoding values for EH. unsigned PersonalityEncoding; @@ -203,6 +208,9 @@ public: bool getSupportsWeakOmittedEHFrame() const { return SupportsWeakOmittedEHFrame; } + bool getSupportsCompactUnwindWithoutEHFrame() const { + return SupportsCompactUnwindWithoutEHFrame; + } bool getCommDirectiveSupportsAlignment() const { return CommDirectiveSupportsAlignment; } diff --git a/lib/MC/MCDwarf.cpp b/lib/MC/MCDwarf.cpp index 79f1312fcaa..5fa8f66422b 100644 --- a/lib/MC/MCDwarf.cpp +++ b/lib/MC/MCDwarf.cpp @@ -1502,6 +1502,7 @@ void MCDwarfFrameEmitter::Emit(MCStreamer &Streamer, MCAsmBackend *MAB, ArrayRef FrameArray = Streamer.getFrameInfos(); // Emit the compact unwind info if available. + bool NeedsEHFrameSection = !MOFI->getSupportsCompactUnwindWithoutEHFrame(); if (IsEH && MOFI->getCompactUnwindSection()) { bool SectionEmitted = false; for (unsigned i = 0, n = FrameArray.size(); i < n; ++i) { @@ -1512,13 +1513,19 @@ void MCDwarfFrameEmitter::Emit(MCStreamer &Streamer, MCAsmBackend *MAB, Streamer.EmitValueToAlignment(Context.getAsmInfo()->getPointerSize()); SectionEmitted = true; } + NeedsEHFrameSection |= + Frame.CompactUnwindEncoding == + MOFI->getCompactUnwindDwarfEHFrameOnly(); Emitter.EmitCompactUnwind(Streamer, Frame); } } + if (!NeedsEHFrameSection) return; + const MCSection &Section = IsEH ? *const_cast(MOFI)->getEHFrameSection() : *MOFI->getDwarfFrameSection(); + Streamer.SwitchSection(&Section); MCSymbol *SectionStart = Context.CreateTempSymbol(); Streamer.EmitLabel(SectionStart); @@ -1528,8 +1535,22 @@ void MCDwarfFrameEmitter::Emit(MCStreamer &Streamer, MCAsmBackend *MAB, DenseMap CIEStarts; const MCSymbol *DummyDebugKey = NULL; + NeedsEHFrameSection = !MOFI->getSupportsCompactUnwindWithoutEHFrame(); for (unsigned i = 0, n = FrameArray.size(); i < n; ++i) { const MCDwarfFrameInfo &Frame = FrameArray[i]; + + // Emit the label from the previous iteration + if (FDEEnd) { + Streamer.EmitLabel(FDEEnd); + FDEEnd = NULL; + } + + if (!NeedsEHFrameSection && Frame.CompactUnwindEncoding != + MOFI->getCompactUnwindDwarfEHFrameOnly()) + // Don't generate an EH frame if we don't need one. I.e., it's taken care + // of by the compact unwind encoding. + continue; + CIEKey Key(Frame.Personality, Frame.PersonalityEncoding, Frame.LsdaEncoding, Frame.IsSignalFrame, Frame.IsSimple); const MCSymbol *&CIEStart = IsEH ? CIEStarts[Key] : DummyDebugKey; @@ -1541,9 +1562,6 @@ void MCDwarfFrameEmitter::Emit(MCStreamer &Streamer, MCAsmBackend *MAB, Frame.IsSimple); FDEEnd = Emitter.EmitFDE(Streamer, *CIEStart, Frame); - - if (i != n - 1) - Streamer.EmitLabel(FDEEnd); } Streamer.EmitValueToAlignment(Context.getAsmInfo()->getPointerSize()); diff --git a/lib/MC/MCObjectFileInfo.cpp b/lib/MC/MCObjectFileInfo.cpp index 87ff0d359d1..e808d0ca6e6 100644 --- a/lib/MC/MCObjectFileInfo.cpp +++ b/lib/MC/MCObjectFileInfo.cpp @@ -743,6 +743,7 @@ void MCObjectFileInfo::InitMCObjectFileInfo(StringRef TT, Reloc::Model relocm, CommDirectiveSupportsAlignment = true; SupportsWeakOmittedEHFrame = true; IsFunctionEHFrameSymbolPrivate = true; + SupportsCompactUnwindWithoutEHFrame = false; PersonalityEncoding = LSDAEncoding = FDEEncoding = FDECFIEncoding = TTypeEncoding = dwarf::DW_EH_PE_absptr;