From 64a8cc7d0d63f5479b48c1e3e1adf85b1d0208c5 Mon Sep 17 00:00:00 2001 From: Saleem Abdulrasool Date: Thu, 7 Aug 2014 02:59:41 +0000 Subject: [PATCH] MC: split Win64EHUnwindEmitter into a shared streamer This changes Win64EHEmitter into a utility WinEH UnwindEmitter that can be shared across multiple architectures and a target specific bit which is overridden (Win64::UnwindEmitter). This enables sharing the section selection code across X86 and the intended use in ARM for emitting unwind information for Windows on ARM. llvm-svn: 215050 --- llvm/include/llvm/MC/MCWin64EH.h | 21 +++---- llvm/include/llvm/MC/MCWinEH.h | 19 ++++++ llvm/lib/MC/CMakeLists.txt | 1 + llvm/lib/MC/MCAsmStreamer.cpp | 7 +-- llvm/lib/MC/MCWin64EH.cpp | 71 +++++----------------- llvm/lib/MC/MCWinEH.cpp | 64 +++++++++++++++++++ .../Target/X86/MCTargetDesc/X86WinCOFFStreamer.cpp | 6 +- 7 files changed, 115 insertions(+), 74 deletions(-) create mode 100644 llvm/lib/MC/MCWinEH.cpp diff --git a/llvm/include/llvm/MC/MCWin64EH.h b/llvm/include/llvm/MC/MCWin64EH.h index be510d6..0e81a19 100644 --- a/llvm/include/llvm/MC/MCWin64EH.h +++ b/llvm/include/llvm/MC/MCWin64EH.h @@ -20,9 +20,8 @@ #include namespace llvm { - class StringRef; - class MCStreamer; - class MCSymbol; +class MCStreamer; +class MCSymbol; namespace Win64EH { struct Instruction { @@ -52,17 +51,13 @@ struct Instruction { return WinEH::Instruction(UOP_SetFPReg, L, Reg, Off); } }; -} - class MCWin64EHUnwindEmitter { - public: - static StringRef GetSectionSuffix(const MCSymbol *func); - // - // This emits the unwind info sections (.pdata and .xdata in PE/COFF). - // - static void Emit(MCStreamer &streamer); - static void EmitUnwindInfo(MCStreamer &streamer, WinEH::FrameInfo *info); - }; +class UnwindEmitter : public WinEH::UnwindEmitter { +public: + void Emit(MCStreamer &Streamer) const override; + void EmitUnwindInfo(MCStreamer &Streamer, WinEH::FrameInfo *FI) const override; +}; +} } // end namespace llvm #endif diff --git a/llvm/include/llvm/MC/MCWinEH.h b/llvm/include/llvm/MC/MCWinEH.h index 8510ae1..5069faf 100644 --- a/llvm/include/llvm/MC/MCWinEH.h +++ b/llvm/include/llvm/MC/MCWinEH.h @@ -13,7 +13,11 @@ #include namespace llvm { +class MCContext; +class MCSection; +class MCStreamer; class MCSymbol; +class StringRef; namespace WinEH { struct Instruction { @@ -58,6 +62,21 @@ struct FrameInfo { HandlesUnwind(false), HandlesExceptions(false), LastFrameInst(-1), ChainedParent(ChainedParent), Instructions() {} }; + +class UnwindEmitter { +public: + static StringRef GetSectionSuffix(const MCSymbol *Function); + static const MCSection *GetPDataSection(StringRef Suffix, MCContext &Context); + static const MCSection *GetXDataSection(StringRef Suffix, MCContext &Context); + + virtual ~UnwindEmitter() { } + + // + // This emits the unwind info sections (.pdata and .xdata in PE/COFF). + // + virtual void Emit(MCStreamer &Streamer) const = 0; + virtual void EmitUnwindInfo(MCStreamer &Streamer, FrameInfo *FI) const = 0; +}; } } diff --git a/llvm/lib/MC/CMakeLists.txt b/llvm/lib/MC/CMakeLists.txt index 9e78d45..855dcde 100644 --- a/llvm/lib/MC/CMakeLists.txt +++ b/llvm/lib/MC/CMakeLists.txt @@ -39,6 +39,7 @@ add_llvm_library(LLVMMC MCTargetOptions.cpp MCValue.cpp MCWin64EH.cpp + MCWinEH.cpp MachObjectWriter.cpp StringTableBuilder.cpp SubtargetFeature.cpp diff --git a/llvm/lib/MC/MCAsmStreamer.cpp b/llvm/lib/MC/MCAsmStreamer.cpp index 11d6de8..27cbd49 100644 --- a/llvm/lib/MC/MCAsmStreamer.cpp +++ b/llvm/lib/MC/MCAsmStreamer.cpp @@ -1110,10 +1110,9 @@ void MCAsmStreamer::EmitWinEHHandlerData() { // We only do this so the section switch that terminates the handler // data block is visible. WinEH::FrameInfo *CurFrame = getCurrentWinFrameInfo(); - StringRef suffix=MCWin64EHUnwindEmitter::GetSectionSuffix(CurFrame->Function); - const MCSection *xdataSect = getWin64EHTableSection(suffix, getContext()); - if (xdataSect) - SwitchSectionNoChange(xdataSect); + StringRef Suffix = WinEH::UnwindEmitter::GetSectionSuffix(CurFrame->Function); + if (const MCSection *XData = getWin64EHTableSection(Suffix, getContext())) + SwitchSectionNoChange(XData); OS << "\t.seh_handlerdata"; EmitEOL(); diff --git a/llvm/lib/MC/MCWin64EH.cpp b/llvm/lib/MC/MCWin64EH.cpp index e59854c..ecb9ae1 100644 --- a/llvm/lib/MC/MCWin64EH.cpp +++ b/llvm/lib/MC/MCWin64EH.cpp @@ -218,65 +218,14 @@ static void EmitUnwindInfo(MCStreamer &streamer, WinEH::FrameInfo *info) { } } -StringRef MCWin64EHUnwindEmitter::GetSectionSuffix(const MCSymbol *func) { - if (!func || !func->isInSection()) return ""; - const MCSection *section = &func->getSection(); - const MCSectionCOFF *COFFSection; - if ((COFFSection = dyn_cast(section))) { - StringRef name = COFFSection->getSectionName(); - size_t dollar = name.find('$'); - size_t dot = name.find('.', 1); - if (dollar == StringRef::npos && dot == StringRef::npos) - return ""; - if (dot == StringRef::npos) - return name.substr(dollar); - if (dollar == StringRef::npos || dot < dollar) - return name.substr(dot); - return name.substr(dollar); - } - return ""; -} - -static const MCSection *getWin64EHTableSection(StringRef suffix, - MCContext &context) { - if (suffix == "") - return context.getObjectFileInfo()->getXDataSection(); - - return context.getCOFFSection((".xdata"+suffix).str(), - COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | - COFF::IMAGE_SCN_MEM_READ, - SectionKind::getDataRel()); -} - -static const MCSection *getWin64EHFuncTableSection(StringRef suffix, - MCContext &context) { - if (suffix == "") - return context.getObjectFileInfo()->getPDataSection(); - return context.getCOFFSection((".pdata"+suffix).str(), - COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | - COFF::IMAGE_SCN_MEM_READ, - SectionKind::getDataRel()); -} - -void MCWin64EHUnwindEmitter::EmitUnwindInfo(MCStreamer &streamer, - WinEH::FrameInfo *info) { - // Switch sections (the static function above is meant to be called from - // here and from Emit(). - MCContext &context = streamer.getContext(); - const MCSection *xdataSect = - getWin64EHTableSection(GetSectionSuffix(info->Function), context); - streamer.SwitchSection(xdataSect); - - llvm::EmitUnwindInfo(streamer, info); -} - -void MCWin64EHUnwindEmitter::Emit(MCStreamer &Streamer) { +namespace Win64EH { +void UnwindEmitter::Emit(MCStreamer &Streamer) const { MCContext &Context = Streamer.getContext(); // Emit the unwind info structs first. for (const auto &CFI : Streamer.getWinFrameInfos()) { const MCSection *XData = - getWin64EHTableSection(GetSectionSuffix(CFI->Function), Context); + GetXDataSection(GetSectionSuffix(CFI->Function), Context); Streamer.SwitchSection(XData); EmitUnwindInfo(Streamer, CFI); } @@ -284,11 +233,23 @@ void MCWin64EHUnwindEmitter::Emit(MCStreamer &Streamer) { // Now emit RUNTIME_FUNCTION entries. for (const auto &CFI : Streamer.getWinFrameInfos()) { const MCSection *PData = - getWin64EHFuncTableSection(GetSectionSuffix(CFI->Function), Context); + GetPDataSection(GetSectionSuffix(CFI->Function), Context); Streamer.SwitchSection(PData); EmitRuntimeFunction(Streamer, CFI); } } +void UnwindEmitter::EmitUnwindInfo(MCStreamer &Streamer, + WinEH::FrameInfo *info) const { + // Switch sections (the static function above is meant to be called from + // here and from Emit(). + MCContext &context = Streamer.getContext(); + const MCSection *xdataSect = + GetXDataSection(GetSectionSuffix(info->Function), context); + Streamer.SwitchSection(xdataSect); + + llvm::EmitUnwindInfo(Streamer, info); +} +} } // End of namespace llvm diff --git a/llvm/lib/MC/MCWinEH.cpp b/llvm/lib/MC/MCWinEH.cpp new file mode 100644 index 0000000..8faf707 --- /dev/null +++ b/llvm/lib/MC/MCWinEH.cpp @@ -0,0 +1,64 @@ +//===- lib/MC/MCWinEH.cpp - Windows EH implementation ---------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/ADT/StringRef.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCObjectFileInfo.h" +#include "llvm/MC/MCSectionCOFF.h" +#include "llvm/MC/MCSymbol.h" +#include "llvm/MC/MCWinEH.h" +#include "llvm/Support/COFF.h" + +namespace llvm { +namespace WinEH { +const MCSection *UnwindEmitter::GetPDataSection(StringRef Suffix, + MCContext &Context) { + if (Suffix.empty()) + return Context.getObjectFileInfo()->getPDataSection(); + return Context.getCOFFSection((".pdata" + Suffix).str(), + COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | + COFF::IMAGE_SCN_MEM_READ, + SectionKind::getDataRel()); +} + +const MCSection *UnwindEmitter::GetXDataSection(StringRef Suffix, + MCContext &Context) { + if (Suffix.empty()) + return Context.getObjectFileInfo()->getXDataSection(); + return Context.getCOFFSection((".xdata" + Suffix).str(), + COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | + COFF::IMAGE_SCN_MEM_READ, + SectionKind::getDataRel()); +} + +StringRef UnwindEmitter::GetSectionSuffix(const MCSymbol *Function) { + if (!Function || !Function->isInSection()) + return ""; + + const MCSection *FunctionSection = &Function->getSection(); + if (const auto Section = dyn_cast(FunctionSection)) { + StringRef Name = Section->getSectionName(); + size_t Dollar = Name.find('$'); + size_t Dot = Name.find('.', 1); + + if (Dollar == StringRef::npos && Dot == StringRef::npos) + return ""; + if (Dot == StringRef::npos) + return Name.substr(Dollar); + if (Dollar == StringRef::npos || Dot < Dollar) + return Name.substr(Dot); + + return Name.substr(Dollar); + } + + return ""; +} +} +} + diff --git a/llvm/lib/Target/X86/MCTargetDesc/X86WinCOFFStreamer.cpp b/llvm/lib/Target/X86/MCTargetDesc/X86WinCOFFStreamer.cpp index a57988a..5f1596c 100644 --- a/llvm/lib/Target/X86/MCTargetDesc/X86WinCOFFStreamer.cpp +++ b/llvm/lib/Target/X86/MCTargetDesc/X86WinCOFFStreamer.cpp @@ -8,12 +8,14 @@ //===----------------------------------------------------------------------===// #include "X86MCTargetDesc.h" +#include "llvm/MC/MCWin64EH.h" #include "llvm/MC/MCWinCOFFStreamer.h" using namespace llvm; namespace { class X86WinCOFFStreamer : public MCWinCOFFStreamer { + Win64EH::UnwindEmitter EHStreamer; public: X86WinCOFFStreamer(MCContext &C, MCAsmBackend &AB, MCCodeEmitter *CE, raw_ostream &OS) @@ -29,13 +31,13 @@ void X86WinCOFFStreamer::EmitWinEHHandlerData() { // We have to emit the unwind info now, because this directive // actually switches to the .xdata section! - MCWin64EHUnwindEmitter::EmitUnwindInfo(*this, getCurrentWinFrameInfo()); + EHStreamer.EmitUnwindInfo(*this, getCurrentWinFrameInfo()); } void X86WinCOFFStreamer::EmitWindowsUnwindTables() { if (!getNumWinFrameInfos()) return; - MCWin64EHUnwindEmitter::Emit(*this); + EHStreamer.Emit(*this); } void X86WinCOFFStreamer::FinishImpl() { -- 2.7.4