mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-01-01 00:33:09 +00: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. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@215050 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
15c8452584
commit
7cc1de1090
@ -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
|
||||
|
@ -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;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -39,6 +39,7 @@ add_llvm_library(LLVMMC
|
||||
MCTargetOptions.cpp
|
||||
MCValue.cpp
|
||||
MCWin64EH.cpp
|
||||
MCWinEH.cpp
|
||||
MachObjectWriter.cpp
|
||||
StringTableBuilder.cpp
|
||||
SubtargetFeature.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();
|
||||
|
@ -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
64
lib/MC/MCWinEH.cpp
Normal 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 "";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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() {
|
||||
|
Loading…
Reference in New Issue
Block a user