forked from OSchip/llvm-project
MC: make WinEH opcode an opaque value
This makes the opcode an opaque value (unsigned int) rather than the enumeration. This permits the use of target specific operands. Split out the generic type into a MCWinEH header and add a supporting MCWin64EH::Instruction to abstract out the selection of the opcode and construction of the actual instruction. llvm-svn: 213221
This commit is contained in:
parent
4fc91538e9
commit
ab820860fa
|
@ -15,8 +15,8 @@
|
|||
#ifndef LLVM_MC_MCWIN64EH_H
|
||||
#define LLVM_MC_MCWIN64EH_H
|
||||
|
||||
#include "llvm/MC/MCWinEH.h"
|
||||
#include "llvm/Support/Win64EH.h"
|
||||
#include <cassert>
|
||||
#include <vector>
|
||||
|
||||
namespace llvm {
|
||||
|
@ -24,37 +24,35 @@ namespace llvm {
|
|||
class MCStreamer;
|
||||
class MCSymbol;
|
||||
|
||||
struct MCWin64EHInstruction {
|
||||
typedef Win64EH::UnwindOpcodes OpType;
|
||||
const OpType Operation;
|
||||
const MCSymbol *Label;
|
||||
const unsigned Offset;
|
||||
const unsigned Register;
|
||||
|
||||
MCWin64EHInstruction(OpType Op, MCSymbol *L, unsigned Reg)
|
||||
: Operation(Op), Label(L), Offset(0), Register(Reg) {
|
||||
assert(Op == Win64EH::UOP_PushNonVol);
|
||||
namespace Win64EH {
|
||||
struct Instruction {
|
||||
static WinEH::Instruction PushNonVol(MCSymbol *L, unsigned Reg) {
|
||||
return WinEH::Instruction(Win64EH::UOP_PushNonVol, L, Reg, -1);
|
||||
}
|
||||
|
||||
MCWin64EHInstruction(MCSymbol *L, unsigned Size)
|
||||
: Operation(Size > 128 ? Win64EH::UOP_AllocLarge
|
||||
: Win64EH::UOP_AllocSmall),
|
||||
Label(L), Offset(Size), Register(-1) {}
|
||||
|
||||
MCWin64EHInstruction(OpType Op, MCSymbol *L, unsigned Reg, unsigned Off)
|
||||
: Operation(Op), Label(L), Offset(Off), Register(Reg) {
|
||||
assert(Op == Win64EH::UOP_SetFPReg ||
|
||||
Op == Win64EH::UOP_SaveNonVol ||
|
||||
Op == Win64EH::UOP_SaveNonVolBig ||
|
||||
Op == Win64EH::UOP_SaveXMM128 ||
|
||||
Op == Win64EH::UOP_SaveXMM128Big);
|
||||
static WinEH::Instruction Alloc(MCSymbol *L, unsigned Size) {
|
||||
return WinEH::Instruction(Size > 128 ? UOP_AllocLarge : UOP_AllocSmall, L,
|
||||
-1, Size);
|
||||
}
|
||||
|
||||
MCWin64EHInstruction(OpType Op, MCSymbol *L, bool Code)
|
||||
: Operation(Op), Label(L), Offset(Code ? 1 : 0), Register(-1) {
|
||||
assert(Op == Win64EH::UOP_PushMachFrame);
|
||||
static WinEH::Instruction PushMachFrame(MCSymbol *L, bool Code) {
|
||||
return WinEH::Instruction(UOP_PushMachFrame, L, -1, Code ? 1 : 0);
|
||||
}
|
||||
static WinEH::Instruction SaveNonVol(MCSymbol *L, unsigned Reg,
|
||||
unsigned Offset) {
|
||||
return WinEH::Instruction(Offset > 512 * 1024 - 8 ? UOP_SaveNonVolBig
|
||||
: UOP_SaveNonVol,
|
||||
L, Reg, Offset);
|
||||
}
|
||||
static WinEH::Instruction SaveXMM(MCSymbol *L, unsigned Reg,
|
||||
unsigned Offset) {
|
||||
return WinEH::Instruction(Offset > 512 * 1024 - 8 ? UOP_SaveXMM128Big
|
||||
: UOP_SaveXMM128,
|
||||
L, Reg, Offset);
|
||||
}
|
||||
static WinEH::Instruction SetFPReg(MCSymbol *L, unsigned Reg, unsigned Off) {
|
||||
return WinEH::Instruction(UOP_SetFPReg, L, Reg, Off);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
struct MCWinFrameInfo {
|
||||
MCWinFrameInfo()
|
||||
|
@ -72,7 +70,7 @@ struct MCWin64EHInstruction {
|
|||
bool HandlesExceptions;
|
||||
int LastFrameInst;
|
||||
MCWinFrameInfo *ChainedParent;
|
||||
std::vector<MCWin64EHInstruction> Instructions;
|
||||
std::vector<WinEH::Instruction> Instructions;
|
||||
};
|
||||
|
||||
class MCWin64EHUnwindEmitter {
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
//===- MCWinEH.h - Windows Unwinding Support --------------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_MC_MCWINEH_H
|
||||
#define LLVM_MC_MCWINEH_H
|
||||
|
||||
namespace llvm {
|
||||
class MCSymbol;
|
||||
|
||||
namespace WinEH {
|
||||
struct Instruction {
|
||||
const MCSymbol *Label;
|
||||
const unsigned Offset;
|
||||
const unsigned Register;
|
||||
const unsigned Operation;
|
||||
|
||||
Instruction(unsigned Op, MCSymbol *L, unsigned Reg, unsigned Off)
|
||||
: Label(L), Offset(Off), Register(Reg), Operation(Op) {}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
|
@ -17,6 +17,7 @@
|
|||
#include "llvm/MC/MCObjectFileInfo.h"
|
||||
#include "llvm/MC/MCObjectWriter.h"
|
||||
#include "llvm/MC/MCSymbol.h"
|
||||
#include "llvm/MC/MCWin64EH.h"
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
#include "llvm/Support/LEB128.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
|
@ -479,9 +480,11 @@ void MCStreamer::EmitWinEHHandlerData() {
|
|||
|
||||
void MCStreamer::EmitWinCFIPushReg(unsigned Register) {
|
||||
EnsureValidWinFrameInfo();
|
||||
|
||||
MCSymbol *Label = getContext().CreateTempSymbol();
|
||||
MCWin64EHInstruction Inst(Win64EH::UOP_PushNonVol, Label, Register);
|
||||
EmitLabel(Label);
|
||||
|
||||
WinEH::Instruction Inst = Win64EH::Instruction::PushNonVol(Label, Register);
|
||||
CurrentWinFrameInfo->Instructions.push_back(Inst);
|
||||
}
|
||||
|
||||
|
@ -493,9 +496,12 @@ void MCStreamer::EmitWinCFISetFrame(unsigned Register, unsigned Offset) {
|
|||
report_fatal_error("Misaligned frame pointer offset!");
|
||||
if (Offset > 240)
|
||||
report_fatal_error("Frame offset must be less than or equal to 240!");
|
||||
|
||||
MCSymbol *Label = getContext().CreateTempSymbol();
|
||||
MCWin64EHInstruction Inst(Win64EH::UOP_SetFPReg, Label, Register, Offset);
|
||||
EmitLabel(Label);
|
||||
|
||||
WinEH::Instruction Inst =
|
||||
Win64EH::Instruction::SetFPReg(Label, Register, Offset);
|
||||
CurrentWinFrameInfo->LastFrameInst = CurrentWinFrameInfo->Instructions.size();
|
||||
CurrentWinFrameInfo->Instructions.push_back(Inst);
|
||||
}
|
||||
|
@ -506,9 +512,11 @@ void MCStreamer::EmitWinCFIAllocStack(unsigned Size) {
|
|||
report_fatal_error("Allocation size must be non-zero!");
|
||||
if (Size & 7)
|
||||
report_fatal_error("Misaligned stack allocation!");
|
||||
|
||||
MCSymbol *Label = getContext().CreateTempSymbol();
|
||||
MCWin64EHInstruction Inst(Label, Size);
|
||||
EmitLabel(Label);
|
||||
|
||||
WinEH::Instruction Inst = Win64EH::Instruction::Alloc(Label, Size);
|
||||
CurrentWinFrameInfo->Instructions.push_back(Inst);
|
||||
}
|
||||
|
||||
|
@ -516,11 +524,12 @@ void MCStreamer::EmitWinCFISaveReg(unsigned Register, unsigned Offset) {
|
|||
EnsureValidWinFrameInfo();
|
||||
if (Offset & 7)
|
||||
report_fatal_error("Misaligned saved register offset!");
|
||||
|
||||
MCSymbol *Label = getContext().CreateTempSymbol();
|
||||
MCWin64EHInstruction Inst(
|
||||
Offset > 512*1024-8 ? Win64EH::UOP_SaveNonVolBig : Win64EH::UOP_SaveNonVol,
|
||||
Label, Register, Offset);
|
||||
EmitLabel(Label);
|
||||
|
||||
WinEH::Instruction Inst =
|
||||
Win64EH::Instruction::SaveNonVol(Label, Register, Offset);
|
||||
CurrentWinFrameInfo->Instructions.push_back(Inst);
|
||||
}
|
||||
|
||||
|
@ -528,11 +537,12 @@ void MCStreamer::EmitWinCFISaveXMM(unsigned Register, unsigned Offset) {
|
|||
EnsureValidWinFrameInfo();
|
||||
if (Offset & 0x0F)
|
||||
report_fatal_error("Misaligned saved vector register offset!");
|
||||
|
||||
MCSymbol *Label = getContext().CreateTempSymbol();
|
||||
MCWin64EHInstruction Inst(
|
||||
Offset > 512*1024-16 ? Win64EH::UOP_SaveXMM128Big : Win64EH::UOP_SaveXMM128,
|
||||
Label, Register, Offset);
|
||||
EmitLabel(Label);
|
||||
|
||||
WinEH::Instruction Inst =
|
||||
Win64EH::Instruction::SaveXMM(Label, Register, Offset);
|
||||
CurrentWinFrameInfo->Instructions.push_back(Inst);
|
||||
}
|
||||
|
||||
|
@ -540,9 +550,11 @@ void MCStreamer::EmitWinCFIPushFrame(bool Code) {
|
|||
EnsureValidWinFrameInfo();
|
||||
if (CurrentWinFrameInfo->Instructions.size() > 0)
|
||||
report_fatal_error("If present, PushMachFrame must be the first UOP");
|
||||
|
||||
MCSymbol *Label = getContext().CreateTempSymbol();
|
||||
MCWin64EHInstruction Inst(Win64EH::UOP_PushMachFrame, Label, Code);
|
||||
EmitLabel(Label);
|
||||
|
||||
WinEH::Instruction Inst = Win64EH::Instruction::PushMachFrame(Label, Code);
|
||||
CurrentWinFrameInfo->Instructions.push_back(Inst);
|
||||
}
|
||||
|
||||
|
|
|
@ -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.Operation) {
|
||||
switch (static_cast<Win64EH::UnwindOpcodes>(I.Operation)) {
|
||||
case Win64EH::UOP_PushNonVol:
|
||||
case Win64EH::UOP_AllocSmall:
|
||||
case Win64EH::UOP_SetFPReg:
|
||||
|
@ -56,11 +57,11 @@ static void EmitAbsDifference(MCStreamer &Streamer, const MCSymbol *LHS,
|
|||
}
|
||||
|
||||
static void EmitUnwindCode(MCStreamer &streamer, MCSymbol *begin,
|
||||
MCWin64EHInstruction &inst) {
|
||||
WinEH::Instruction &inst) {
|
||||
uint8_t b2;
|
||||
uint16_t w;
|
||||
b2 = (inst.Operation & 0x0F);
|
||||
switch (inst.Operation) {
|
||||
switch (static_cast<Win64EH::UnwindOpcodes>(inst.Operation)) {
|
||||
case Win64EH::UOP_PushNonVol:
|
||||
EmitAbsDifference(streamer, inst.Label, begin);
|
||||
b2 |= (inst.Register & 0x0F) << 4;
|
||||
|
@ -177,7 +178,7 @@ static void EmitUnwindInfo(MCStreamer &streamer, MCWinFrameInfo *info) {
|
|||
|
||||
uint8_t frame = 0;
|
||||
if (info->LastFrameInst >= 0) {
|
||||
MCWin64EHInstruction &frameInst = info->Instructions[info->LastFrameInst];
|
||||
WinEH::Instruction &frameInst = info->Instructions[info->LastFrameInst];
|
||||
assert(frameInst.Operation == Win64EH::UOP_SetFPReg);
|
||||
frame = (frameInst.Register & 0x0F) | (frameInst.Offset & 0xF0);
|
||||
}
|
||||
|
@ -186,7 +187,7 @@ static void EmitUnwindInfo(MCStreamer &streamer, MCWinFrameInfo *info) {
|
|||
// 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);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue