]> gitweb.factorcode.org Git - factor.git/blob - vm/os-windows-x86.64.cpp
VM: Fix Windows 64-bit build on Visual Studio 2012
[factor.git] / vm / os-windows-x86.64.cpp
1 #include "master.hpp"
2
3 namespace factor {
4
5 typedef unsigned char UBYTE;
6
7 #ifndef UNW_FLAG_EHANDLER
8 const UBYTE UNW_FLAG_EHANDLER = 0x1;
9 #endif
10
11 struct UNWIND_INFO {
12   UBYTE Version : 3;
13   UBYTE Flags : 5;
14   UBYTE SizeOfProlog;
15   UBYTE CountOfCodes;
16   UBYTE FrameRegister : 4;
17   UBYTE FrameOffset : 4;
18   ULONG ExceptionHandler;
19   ULONG ExceptionData[1];
20 };
21
22 struct seh_data {
23   UNWIND_INFO unwind_info;
24   RUNTIME_FUNCTION func;
25   UBYTE handler[32];
26 };
27
28 void factor_vm::c_to_factor_toplevel(cell quot) {
29   /* The annoying thing about Win64 SEH is that the offsets in
30    * function tables are 32-bit integers, and the exception handler
31    * itself must reside between the start and end pointers, so
32    * we stick everything at the beginning of the code heap and
33    * generate a small trampoline that jumps to the real
34    * exception handler. */
35
36   seh_data* seh_area = (seh_data*)code->seh_area;
37   cell base = code->seg->start;
38
39   /* Should look at generating this with the Factor assembler */
40
41   /* mov rax,0 */
42   seh_area->handler[0] = 0x48;
43   seh_area->handler[1] = 0xb8;
44   seh_area->handler[2] = 0x0;
45   seh_area->handler[3] = 0x0;
46   seh_area->handler[4] = 0x0;
47   seh_area->handler[5] = 0x0;
48   seh_area->handler[6] = 0x0;
49   seh_area->handler[7] = 0x0;
50   seh_area->handler[8] = 0x0;
51   seh_area->handler[9] = 0x0;
52
53   /* jmp rax */
54   seh_area->handler[10] = 0x48;
55   seh_area->handler[11] = 0xff;
56   seh_area->handler[12] = 0xe0;
57
58   /* Store address of exception handler in the operand of the 'mov' */
59   cell handler = (cell)&factor::exception_handler;
60   memcpy(&seh_area->handler[2], &handler, sizeof(cell));
61
62   UNWIND_INFO* unwind_info = &seh_area->unwind_info;
63   unwind_info->Version = 1;
64   unwind_info->Flags = UNW_FLAG_EHANDLER;
65   unwind_info->SizeOfProlog = 0;
66   unwind_info->CountOfCodes = 0;
67   unwind_info->FrameRegister = 0;
68   unwind_info->FrameOffset = 0;
69   unwind_info->ExceptionHandler = (DWORD)((cell)&seh_area->handler[0] - base);
70   unwind_info->ExceptionData[0] = 0;
71
72   RUNTIME_FUNCTION* func = &seh_area->func;
73   func->BeginAddress = 0;
74   func->EndAddress = (DWORD)(code->seg->end - base);
75   func->UnwindData = (DWORD)((cell)&seh_area->unwind_info - base);
76
77   if (!RtlAddFunctionTable(func, 1, base))
78     fatal_error("RtlAddFunctionTable() failed", 0);
79
80   c_to_factor(quot);
81
82   if (!RtlDeleteFunctionTable(func))
83     fatal_error("RtlDeleteFunctionTable() failed", 0);
84 }
85
86 }