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); }