MC: make WinEH opcode an opaque value
authorSaleem Abdulrasool <compnerd@compnerd.org>
Thu, 17 Jul 2014 03:08:50 +0000 (03:08 +0000)
committerSaleem Abdulrasool <compnerd@compnerd.org>
Thu, 17 Jul 2014 03:08:50 +0000 (03:08 +0000)
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

llvm/include/llvm/MC/MCWin64EH.h
llvm/include/llvm/MC/MCWinEH.h [new file with mode: 0644]
llvm/lib/MC/MCStreamer.cpp
llvm/lib/MC/MCWin64EH.cpp

index 907b033..3df0d0a 100644 (file)
@@ -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 {
diff --git a/llvm/include/llvm/MC/MCWinEH.h b/llvm/include/llvm/MC/MCWinEH.h
new file mode 100644 (file)
index 0000000..1cd1b0f
--- /dev/null
@@ -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
index c99fe93..f356402 100644 (file)
@@ -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);
 }
 
index 4c0bf8c..95e1983 100644 (file)
 #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);
   }