mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-02-05 14:34:55 +00:00
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. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@213221 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
8f609696e0
commit
adcb2d1636
@ -15,8 +15,8 @@
|
|||||||
#ifndef LLVM_MC_MCWIN64EH_H
|
#ifndef LLVM_MC_MCWIN64EH_H
|
||||||
#define LLVM_MC_MCWIN64EH_H
|
#define LLVM_MC_MCWIN64EH_H
|
||||||
|
|
||||||
|
#include "llvm/MC/MCWinEH.h"
|
||||||
#include "llvm/Support/Win64EH.h"
|
#include "llvm/Support/Win64EH.h"
|
||||||
#include <cassert>
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
namespace llvm {
|
namespace llvm {
|
||||||
@ -24,37 +24,35 @@ namespace llvm {
|
|||||||
class MCStreamer;
|
class MCStreamer;
|
||||||
class MCSymbol;
|
class MCSymbol;
|
||||||
|
|
||||||
struct MCWin64EHInstruction {
|
namespace Win64EH {
|
||||||
typedef Win64EH::UnwindOpcodes OpType;
|
struct Instruction {
|
||||||
const OpType Operation;
|
static WinEH::Instruction PushNonVol(MCSymbol *L, unsigned Reg) {
|
||||||
const MCSymbol *Label;
|
return WinEH::Instruction(Win64EH::UOP_PushNonVol, L, Reg, -1);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
static WinEH::Instruction Alloc(MCSymbol *L, unsigned Size) {
|
||||||
MCWin64EHInstruction(MCSymbol *L, unsigned Size)
|
return WinEH::Instruction(Size > 128 ? UOP_AllocLarge : UOP_AllocSmall, L,
|
||||||
: Operation(Size > 128 ? Win64EH::UOP_AllocLarge
|
-1, Size);
|
||||||
: 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 PushMachFrame(MCSymbol *L, bool Code) {
|
||||||
MCWin64EHInstruction(OpType Op, MCSymbol *L, bool Code)
|
return WinEH::Instruction(UOP_PushMachFrame, L, -1, Code ? 1 : 0);
|
||||||
: Operation(Op), Label(L), Offset(Code ? 1 : 0), Register(-1) {
|
}
|
||||||
assert(Op == Win64EH::UOP_PushMachFrame);
|
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 {
|
struct MCWinFrameInfo {
|
||||||
MCWinFrameInfo()
|
MCWinFrameInfo()
|
||||||
@ -72,7 +70,7 @@ struct MCWin64EHInstruction {
|
|||||||
bool HandlesExceptions;
|
bool HandlesExceptions;
|
||||||
int LastFrameInst;
|
int LastFrameInst;
|
||||||
MCWinFrameInfo *ChainedParent;
|
MCWinFrameInfo *ChainedParent;
|
||||||
std::vector<MCWin64EHInstruction> Instructions;
|
std::vector<WinEH::Instruction> Instructions;
|
||||||
};
|
};
|
||||||
|
|
||||||
class MCWin64EHUnwindEmitter {
|
class MCWin64EHUnwindEmitter {
|
||||||
|
29
include/llvm/MC/MCWinEH.h
Normal file
29
include/llvm/MC/MCWinEH.h
Normal file
@ -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/MCObjectFileInfo.h"
|
||||||
#include "llvm/MC/MCObjectWriter.h"
|
#include "llvm/MC/MCObjectWriter.h"
|
||||||
#include "llvm/MC/MCSymbol.h"
|
#include "llvm/MC/MCSymbol.h"
|
||||||
|
#include "llvm/MC/MCWin64EH.h"
|
||||||
#include "llvm/Support/ErrorHandling.h"
|
#include "llvm/Support/ErrorHandling.h"
|
||||||
#include "llvm/Support/LEB128.h"
|
#include "llvm/Support/LEB128.h"
|
||||||
#include "llvm/Support/raw_ostream.h"
|
#include "llvm/Support/raw_ostream.h"
|
||||||
@ -479,9 +480,11 @@ void MCStreamer::EmitWinEHHandlerData() {
|
|||||||
|
|
||||||
void MCStreamer::EmitWinCFIPushReg(unsigned Register) {
|
void MCStreamer::EmitWinCFIPushReg(unsigned Register) {
|
||||||
EnsureValidWinFrameInfo();
|
EnsureValidWinFrameInfo();
|
||||||
|
|
||||||
MCSymbol *Label = getContext().CreateTempSymbol();
|
MCSymbol *Label = getContext().CreateTempSymbol();
|
||||||
MCWin64EHInstruction Inst(Win64EH::UOP_PushNonVol, Label, Register);
|
|
||||||
EmitLabel(Label);
|
EmitLabel(Label);
|
||||||
|
|
||||||
|
WinEH::Instruction Inst = Win64EH::Instruction::PushNonVol(Label, Register);
|
||||||
CurrentWinFrameInfo->Instructions.push_back(Inst);
|
CurrentWinFrameInfo->Instructions.push_back(Inst);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -493,9 +496,12 @@ void MCStreamer::EmitWinCFISetFrame(unsigned Register, unsigned Offset) {
|
|||||||
report_fatal_error("Misaligned frame pointer offset!");
|
report_fatal_error("Misaligned frame pointer offset!");
|
||||||
if (Offset > 240)
|
if (Offset > 240)
|
||||||
report_fatal_error("Frame offset must be less than or equal to 240!");
|
report_fatal_error("Frame offset must be less than or equal to 240!");
|
||||||
|
|
||||||
MCSymbol *Label = getContext().CreateTempSymbol();
|
MCSymbol *Label = getContext().CreateTempSymbol();
|
||||||
MCWin64EHInstruction Inst(Win64EH::UOP_SetFPReg, Label, Register, Offset);
|
|
||||||
EmitLabel(Label);
|
EmitLabel(Label);
|
||||||
|
|
||||||
|
WinEH::Instruction Inst =
|
||||||
|
Win64EH::Instruction::SetFPReg(Label, Register, Offset);
|
||||||
CurrentWinFrameInfo->LastFrameInst = CurrentWinFrameInfo->Instructions.size();
|
CurrentWinFrameInfo->LastFrameInst = CurrentWinFrameInfo->Instructions.size();
|
||||||
CurrentWinFrameInfo->Instructions.push_back(Inst);
|
CurrentWinFrameInfo->Instructions.push_back(Inst);
|
||||||
}
|
}
|
||||||
@ -506,9 +512,11 @@ void MCStreamer::EmitWinCFIAllocStack(unsigned Size) {
|
|||||||
report_fatal_error("Allocation size must be non-zero!");
|
report_fatal_error("Allocation size must be non-zero!");
|
||||||
if (Size & 7)
|
if (Size & 7)
|
||||||
report_fatal_error("Misaligned stack allocation!");
|
report_fatal_error("Misaligned stack allocation!");
|
||||||
|
|
||||||
MCSymbol *Label = getContext().CreateTempSymbol();
|
MCSymbol *Label = getContext().CreateTempSymbol();
|
||||||
MCWin64EHInstruction Inst(Label, Size);
|
|
||||||
EmitLabel(Label);
|
EmitLabel(Label);
|
||||||
|
|
||||||
|
WinEH::Instruction Inst = Win64EH::Instruction::Alloc(Label, Size);
|
||||||
CurrentWinFrameInfo->Instructions.push_back(Inst);
|
CurrentWinFrameInfo->Instructions.push_back(Inst);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -516,11 +524,12 @@ void MCStreamer::EmitWinCFISaveReg(unsigned Register, unsigned Offset) {
|
|||||||
EnsureValidWinFrameInfo();
|
EnsureValidWinFrameInfo();
|
||||||
if (Offset & 7)
|
if (Offset & 7)
|
||||||
report_fatal_error("Misaligned saved register offset!");
|
report_fatal_error("Misaligned saved register offset!");
|
||||||
|
|
||||||
MCSymbol *Label = getContext().CreateTempSymbol();
|
MCSymbol *Label = getContext().CreateTempSymbol();
|
||||||
MCWin64EHInstruction Inst(
|
|
||||||
Offset > 512*1024-8 ? Win64EH::UOP_SaveNonVolBig : Win64EH::UOP_SaveNonVol,
|
|
||||||
Label, Register, Offset);
|
|
||||||
EmitLabel(Label);
|
EmitLabel(Label);
|
||||||
|
|
||||||
|
WinEH::Instruction Inst =
|
||||||
|
Win64EH::Instruction::SaveNonVol(Label, Register, Offset);
|
||||||
CurrentWinFrameInfo->Instructions.push_back(Inst);
|
CurrentWinFrameInfo->Instructions.push_back(Inst);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -528,11 +537,12 @@ void MCStreamer::EmitWinCFISaveXMM(unsigned Register, unsigned Offset) {
|
|||||||
EnsureValidWinFrameInfo();
|
EnsureValidWinFrameInfo();
|
||||||
if (Offset & 0x0F)
|
if (Offset & 0x0F)
|
||||||
report_fatal_error("Misaligned saved vector register offset!");
|
report_fatal_error("Misaligned saved vector register offset!");
|
||||||
|
|
||||||
MCSymbol *Label = getContext().CreateTempSymbol();
|
MCSymbol *Label = getContext().CreateTempSymbol();
|
||||||
MCWin64EHInstruction Inst(
|
|
||||||
Offset > 512*1024-16 ? Win64EH::UOP_SaveXMM128Big : Win64EH::UOP_SaveXMM128,
|
|
||||||
Label, Register, Offset);
|
|
||||||
EmitLabel(Label);
|
EmitLabel(Label);
|
||||||
|
|
||||||
|
WinEH::Instruction Inst =
|
||||||
|
Win64EH::Instruction::SaveXMM(Label, Register, Offset);
|
||||||
CurrentWinFrameInfo->Instructions.push_back(Inst);
|
CurrentWinFrameInfo->Instructions.push_back(Inst);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -540,9 +550,11 @@ void MCStreamer::EmitWinCFIPushFrame(bool Code) {
|
|||||||
EnsureValidWinFrameInfo();
|
EnsureValidWinFrameInfo();
|
||||||
if (CurrentWinFrameInfo->Instructions.size() > 0)
|
if (CurrentWinFrameInfo->Instructions.size() > 0)
|
||||||
report_fatal_error("If present, PushMachFrame must be the first UOP");
|
report_fatal_error("If present, PushMachFrame must be the first UOP");
|
||||||
|
|
||||||
MCSymbol *Label = getContext().CreateTempSymbol();
|
MCSymbol *Label = getContext().CreateTempSymbol();
|
||||||
MCWin64EHInstruction Inst(Win64EH::UOP_PushMachFrame, Label, Code);
|
|
||||||
EmitLabel(Label);
|
EmitLabel(Label);
|
||||||
|
|
||||||
|
WinEH::Instruction Inst = Win64EH::Instruction::PushMachFrame(Label, Code);
|
||||||
CurrentWinFrameInfo->Instructions.push_back(Inst);
|
CurrentWinFrameInfo->Instructions.push_back(Inst);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,15 +15,16 @@
|
|||||||
#include "llvm/MC/MCSectionCOFF.h"
|
#include "llvm/MC/MCSectionCOFF.h"
|
||||||
#include "llvm/MC/MCStreamer.h"
|
#include "llvm/MC/MCStreamer.h"
|
||||||
#include "llvm/MC/MCSymbol.h"
|
#include "llvm/MC/MCSymbol.h"
|
||||||
|
#include "llvm/Support/Win64EH.h"
|
||||||
|
|
||||||
namespace llvm {
|
namespace llvm {
|
||||||
|
|
||||||
// NOTE: All relocations generated here are 4-byte image-relative.
|
// 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;
|
uint8_t Count = 0;
|
||||||
for (const auto &I : Insns) {
|
for (const auto &I : Insns) {
|
||||||
switch (I.Operation) {
|
switch (static_cast<Win64EH::UnwindOpcodes>(I.Operation)) {
|
||||||
case Win64EH::UOP_PushNonVol:
|
case Win64EH::UOP_PushNonVol:
|
||||||
case Win64EH::UOP_AllocSmall:
|
case Win64EH::UOP_AllocSmall:
|
||||||
case Win64EH::UOP_SetFPReg:
|
case Win64EH::UOP_SetFPReg:
|
||||||
@ -56,11 +57,11 @@ static void EmitAbsDifference(MCStreamer &Streamer, const MCSymbol *LHS,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void EmitUnwindCode(MCStreamer &streamer, MCSymbol *begin,
|
static void EmitUnwindCode(MCStreamer &streamer, MCSymbol *begin,
|
||||||
MCWin64EHInstruction &inst) {
|
WinEH::Instruction &inst) {
|
||||||
uint8_t b2;
|
uint8_t b2;
|
||||||
uint16_t w;
|
uint16_t w;
|
||||||
b2 = (inst.Operation & 0x0F);
|
b2 = (inst.Operation & 0x0F);
|
||||||
switch (inst.Operation) {
|
switch (static_cast<Win64EH::UnwindOpcodes>(inst.Operation)) {
|
||||||
case Win64EH::UOP_PushNonVol:
|
case Win64EH::UOP_PushNonVol:
|
||||||
EmitAbsDifference(streamer, inst.Label, begin);
|
EmitAbsDifference(streamer, inst.Label, begin);
|
||||||
b2 |= (inst.Register & 0x0F) << 4;
|
b2 |= (inst.Register & 0x0F) << 4;
|
||||||
@ -177,7 +178,7 @@ static void EmitUnwindInfo(MCStreamer &streamer, MCWinFrameInfo *info) {
|
|||||||
|
|
||||||
uint8_t frame = 0;
|
uint8_t frame = 0;
|
||||||
if (info->LastFrameInst >= 0) {
|
if (info->LastFrameInst >= 0) {
|
||||||
MCWin64EHInstruction &frameInst = info->Instructions[info->LastFrameInst];
|
WinEH::Instruction &frameInst = info->Instructions[info->LastFrameInst];
|
||||||
assert(frameInst.Operation == Win64EH::UOP_SetFPReg);
|
assert(frameInst.Operation == Win64EH::UOP_SetFPReg);
|
||||||
frame = (frameInst.Register & 0x0F) | (frameInst.Offset & 0xF0);
|
frame = (frameInst.Register & 0x0F) | (frameInst.Offset & 0xF0);
|
||||||
}
|
}
|
||||||
@ -186,7 +187,7 @@ static void EmitUnwindInfo(MCStreamer &streamer, MCWinFrameInfo *info) {
|
|||||||
// Emit unwind instructions (in reverse order).
|
// Emit unwind instructions (in reverse order).
|
||||||
uint8_t numInst = info->Instructions.size();
|
uint8_t numInst = info->Instructions.size();
|
||||||
for (uint8_t c = 0; c < numInst; ++c) {
|
for (uint8_t c = 0; c < numInst; ++c) {
|
||||||
MCWin64EHInstruction inst = info->Instructions.back();
|
WinEH::Instruction inst = info->Instructions.back();
|
||||||
info->Instructions.pop_back();
|
info->Instructions.pop_back();
|
||||||
EmitUnwindCode(streamer, info->Begin, inst);
|
EmitUnwindCode(streamer, info->Begin, inst);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user