From adcb2d163697501745445aea2281a18bff4a571f Mon Sep 17 00:00:00 2001 From: Saleem Abdulrasool Date: Thu, 17 Jul 2014 03:08:50 +0000 Subject: [PATCH] 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 --- include/llvm/MC/MCWin64EH.h | 56 ++++++++++++++++++------------------- include/llvm/MC/MCWinEH.h | 29 +++++++++++++++++++ lib/MC/MCStreamer.cpp | 32 ++++++++++++++------- lib/MC/MCWin64EH.cpp | 13 +++++---- 4 files changed, 85 insertions(+), 45 deletions(-) create mode 100644 include/llvm/MC/MCWinEH.h diff --git a/include/llvm/MC/MCWin64EH.h b/include/llvm/MC/MCWin64EH.h index 907b033f7e7..3df0d0ab8c4 100644 --- a/include/llvm/MC/MCWin64EH.h +++ b/include/llvm/MC/MCWin64EH.h @@ -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 #include 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 Instructions; + std::vector Instructions; }; class MCWin64EHUnwindEmitter { diff --git a/include/llvm/MC/MCWinEH.h b/include/llvm/MC/MCWinEH.h new file mode 100644 index 00000000000..1cd1b0f1b8c --- /dev/null +++ b/include/llvm/MC/MCWinEH.h @@ -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 diff --git a/lib/MC/MCStreamer.cpp b/lib/MC/MCStreamer.cpp index c99fe93dcee..f3564027bf3 100644 --- a/lib/MC/MCStreamer.cpp +++ b/lib/MC/MCStreamer.cpp @@ -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); } diff --git a/lib/MC/MCWin64EH.cpp b/lib/MC/MCWin64EH.cpp index 4c0bf8c536d..95e19839372 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 &Insns) { +static uint8_t CountOfUnwindCodes(std::vector &Insns) { uint8_t Count = 0; for (const auto &I : Insns) { - switch (I.Operation) { + switch (static_cast(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(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); } -- 2.34.1