aboutsummaryrefslogtreecommitdiffstats
path: root/lib/MC/MCWin64EH.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/MC/MCWin64EH.cpp')
-rw-r--r--lib/MC/MCWin64EH.cpp173
1 files changed, 67 insertions, 106 deletions
diff --git a/lib/MC/MCWin64EH.cpp b/lib/MC/MCWin64EH.cpp
index bb651647..dfadb3c 100644
--- a/lib/MC/MCWin64EH.cpp
+++ b/lib/MC/MCWin64EH.cpp
@@ -15,15 +15,16 @@
#include "llvm/MC/MCSectionCOFF.h"
#include "llvm/MC/MCStreamer.h"
#include "llvm/MC/MCSymbol.h"
+#include "llvm/Support/Win64EH.h"
namespace llvm {
// NOTE: All relocations generated here are 4-byte image-relative.
-static uint8_t CountOfUnwindCodes(std::vector<MCWin64EHInstruction> &Insns) {
+static uint8_t CountOfUnwindCodes(std::vector<WinEH::Instruction> &Insns) {
uint8_t Count = 0;
for (const auto &I : Insns) {
- switch (I.getOperation()) {
+ switch (static_cast<Win64EH::UnwindOpcodes>(I.Operation)) {
case Win64EH::UOP_PushNonVol:
case Win64EH::UOP_AllocSmall:
case Win64EH::UOP_SetFPReg:
@@ -39,86 +40,83 @@ static uint8_t CountOfUnwindCodes(std::vector<MCWin64EHInstruction> &Insns) {
Count += 3;
break;
case Win64EH::UOP_AllocLarge:
- Count += (I.getSize() > 512 * 1024 - 8) ? 3 : 2;
+ Count += (I.Offset > 512 * 1024 - 8) ? 3 : 2;
break;
}
}
return Count;
}
-static void EmitAbsDifference(MCStreamer &streamer, MCSymbol *lhs,
- MCSymbol *rhs) {
- MCContext &context = streamer.getContext();
- const MCExpr *diff = MCBinaryExpr::CreateSub(MCSymbolRefExpr::Create(
- lhs, context),
- MCSymbolRefExpr::Create(
- rhs, context),
- context);
- streamer.EmitAbsValue(diff, 1);
-
+static void EmitAbsDifference(MCStreamer &Streamer, const MCSymbol *LHS,
+ const MCSymbol *RHS) {
+ MCContext &Context = Streamer.getContext();
+ const MCExpr *Diff =
+ MCBinaryExpr::CreateSub(MCSymbolRefExpr::Create(LHS, Context),
+ MCSymbolRefExpr::Create(RHS, Context), Context);
+ Streamer.EmitValue(Diff, 1);
}
-static void EmitUnwindCode(MCStreamer &streamer, MCSymbol *begin,
- MCWin64EHInstruction &inst) {
+static void EmitUnwindCode(MCStreamer &streamer, const MCSymbol *begin,
+ WinEH::Instruction &inst) {
uint8_t b2;
uint16_t w;
- b2 = (inst.getOperation() & 0x0F);
- switch (inst.getOperation()) {
+ b2 = (inst.Operation & 0x0F);
+ switch (static_cast<Win64EH::UnwindOpcodes>(inst.Operation)) {
case Win64EH::UOP_PushNonVol:
- EmitAbsDifference(streamer, inst.getLabel(), begin);
- b2 |= (inst.getRegister() & 0x0F) << 4;
+ EmitAbsDifference(streamer, inst.Label, begin);
+ b2 |= (inst.Register & 0x0F) << 4;
streamer.EmitIntValue(b2, 1);
break;
case Win64EH::UOP_AllocLarge:
- EmitAbsDifference(streamer, inst.getLabel(), begin);
- if (inst.getSize() > 512*1024-8) {
+ EmitAbsDifference(streamer, inst.Label, begin);
+ if (inst.Offset > 512 * 1024 - 8) {
b2 |= 0x10;
streamer.EmitIntValue(b2, 1);
- w = inst.getSize() & 0xFFF8;
+ w = inst.Offset & 0xFFF8;
streamer.EmitIntValue(w, 2);
- w = inst.getSize() >> 16;
+ w = inst.Offset >> 16;
} else {
streamer.EmitIntValue(b2, 1);
- w = inst.getSize() >> 3;
+ w = inst.Offset >> 3;
}
streamer.EmitIntValue(w, 2);
break;
case Win64EH::UOP_AllocSmall:
- b2 |= (((inst.getSize()-8) >> 3) & 0x0F) << 4;
- EmitAbsDifference(streamer, inst.getLabel(), begin);
+ b2 |= (((inst.Offset - 8) >> 3) & 0x0F) << 4;
+ EmitAbsDifference(streamer, inst.Label, begin);
streamer.EmitIntValue(b2, 1);
break;
case Win64EH::UOP_SetFPReg:
- EmitAbsDifference(streamer, inst.getLabel(), begin);
+ EmitAbsDifference(streamer, inst.Label, begin);
streamer.EmitIntValue(b2, 1);
break;
case Win64EH::UOP_SaveNonVol:
case Win64EH::UOP_SaveXMM128:
- b2 |= (inst.getRegister() & 0x0F) << 4;
- EmitAbsDifference(streamer, inst.getLabel(), begin);
+ b2 |= (inst.Register & 0x0F) << 4;
+ EmitAbsDifference(streamer, inst.Label, begin);
streamer.EmitIntValue(b2, 1);
- w = inst.getOffset() >> 3;
- if (inst.getOperation() == Win64EH::UOP_SaveXMM128)
+ w = inst.Offset >> 3;
+ if (inst.Operation == Win64EH::UOP_SaveXMM128)
w >>= 1;
streamer.EmitIntValue(w, 2);
break;
case Win64EH::UOP_SaveNonVolBig:
case Win64EH::UOP_SaveXMM128Big:
- b2 |= (inst.getRegister() & 0x0F) << 4;
- EmitAbsDifference(streamer, inst.getLabel(), begin);
+ b2 |= (inst.Register & 0x0F) << 4;
+ EmitAbsDifference(streamer, inst.Label, begin);
streamer.EmitIntValue(b2, 1);
- if (inst.getOperation() == Win64EH::UOP_SaveXMM128Big)
- w = inst.getOffset() & 0xFFF0;
+ if (inst.Operation == Win64EH::UOP_SaveXMM128Big)
+ w = inst.Offset & 0xFFF0;
else
- w = inst.getOffset() & 0xFFF8;
+ w = inst.Offset & 0xFFF8;
streamer.EmitIntValue(w, 2);
- w = inst.getOffset() >> 16;
+ w = inst.Offset >> 16;
streamer.EmitIntValue(w, 2);
break;
case Win64EH::UOP_PushMachFrame:
- if (inst.isPushCodeFrame())
+ if (inst.Offset == 1)
b2 |= 0x10;
- EmitAbsDifference(streamer, inst.getLabel(), begin);
+ EmitAbsDifference(streamer, inst.Label, begin);
streamer.EmitIntValue(b2, 1);
break;
}
@@ -138,7 +136,7 @@ static void EmitSymbolRefWithOfs(MCStreamer &streamer,
}
static void EmitRuntimeFunction(MCStreamer &streamer,
- const MCWin64EHUnwindInfo *info) {
+ const WinEH::FrameInfo *info) {
MCContext &context = streamer.getContext();
streamer.EmitValueToAlignment(4);
@@ -149,14 +147,17 @@ static void EmitRuntimeFunction(MCStreamer &streamer,
context), 4);
}
-static void EmitUnwindInfo(MCStreamer &streamer, MCWin64EHUnwindInfo *info) {
+static void EmitUnwindInfo(MCStreamer &streamer, WinEH::FrameInfo *info) {
// If this UNWIND_INFO already has a symbol, it's already been emitted.
- if (info->Symbol) return;
+ if (info->Symbol)
+ return;
MCContext &context = streamer.getContext();
+ MCSymbol *Label = context.CreateTempSymbol();
+
streamer.EmitValueToAlignment(4);
- info->Symbol = context.CreateTempSymbol();
- streamer.EmitLabel(info->Symbol);
+ streamer.EmitLabel(Label);
+ info->Symbol = Label;
// Upper 3 bits are the version number (currently 1).
uint8_t flags = 0x01;
@@ -180,17 +181,16 @@ static void EmitUnwindInfo(MCStreamer &streamer, MCWin64EHUnwindInfo *info) {
uint8_t frame = 0;
if (info->LastFrameInst >= 0) {
- MCWin64EHInstruction &frameInst = info->Instructions[info->LastFrameInst];
- assert(frameInst.getOperation() == Win64EH::UOP_SetFPReg);
- frame = (frameInst.getRegister() & 0x0F) |
- (frameInst.getOffset() & 0xF0);
+ WinEH::Instruction &frameInst = info->Instructions[info->LastFrameInst];
+ assert(frameInst.Operation == Win64EH::UOP_SetFPReg);
+ frame = (frameInst.Register & 0x0F) | (frameInst.Offset & 0xF0);
}
streamer.EmitIntValue(frame, 1);
// Emit unwind instructions (in reverse order).
uint8_t numInst = info->Instructions.size();
for (uint8_t c = 0; c < numInst; ++c) {
- MCWin64EHInstruction inst = info->Instructions.back();
+ WinEH::Instruction inst = info->Instructions.back();
info->Instructions.pop_back();
EmitUnwindCode(streamer, info->Begin, inst);
}
@@ -218,77 +218,38 @@ static void EmitUnwindInfo(MCStreamer &streamer, MCWin64EHUnwindInfo *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,
- MCWin64EHUnwindInfo *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.getW64UnwindInfos()) {
+ for (const auto &CFI : Streamer.getWinFrameInfos()) {
const MCSection *XData =
- getWin64EHTableSection(GetSectionSuffix(CFI->Function), Context);
+ getXDataSection(CFI->Function, Context);
Streamer.SwitchSection(XData);
EmitUnwindInfo(Streamer, CFI);
}
// Now emit RUNTIME_FUNCTION entries.
- for (const auto &CFI : Streamer.getW64UnwindInfos()) {
+ for (const auto &CFI : Streamer.getWinFrameInfos()) {
const MCSection *PData =
- getWin64EHFuncTableSection(GetSectionSuffix(CFI->Function), Context);
+ getPDataSection(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(info->Function, context);
+ Streamer.SwitchSection(xdataSect);
+
+ llvm::EmitUnwindInfo(Streamer, info);
+}
+}
} // End of namespace llvm