1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-10-18 18:42:46 +02:00

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
This commit is contained in:
Saleem Abdulrasool 2014-08-07 02:59:41 +00:00
parent e540e9c357
commit 37f9f1e4f7
7 changed files with 115 additions and 74 deletions

View File

@ -20,9 +20,8 @@
#include <vector>
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

View File

@ -13,7 +13,11 @@
#include <vector>
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;
};
}
}

View File

@ -39,6 +39,7 @@ add_llvm_library(LLVMMC
MCTargetOptions.cpp
MCValue.cpp
MCWin64EH.cpp
MCWinEH.cpp
MachObjectWriter.cpp
StringTableBuilder.cpp
SubtargetFeature.cpp

View File

@ -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();

View File

@ -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<MCSectionCOFF>(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

64
lib/MC/MCWinEH.cpp Normal file
View File

@ -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<MCSectionCOFF>(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 "";
}
}
}

View File

@ -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() {