Merge pull request #2998 from lateralusX/jlorenss/win-x64-full-aot-support
authorAlexander Köplinger <alex.koeplinger@outlook.com>
Thu, 19 May 2016 11:36:19 +0000 (13:36 +0200)
committerAlexander Köplinger <alex.koeplinger@outlook.com>
Thu, 19 May 2016 11:36:19 +0000 (13:36 +0200)
Windows x64 full AOT support for mono/mini regression tests.

mono/metadata/threads.c
mono/mini/cpu-amd64.md
mono/mini/mini-amd64.c
mono/mini/mini-amd64.h
mono/mini/mini-windows.c

index 9618e30553347c2ed34ad7a65052f7b706f9543a..8acb6f5efafa01e91926c3b54cdc1dd87f3849a9 100644 (file)
@@ -257,8 +257,14 @@ mono_thread_get_tls_key (void)
 gint32
 mono_thread_get_tls_offset (void)
 {
-       int offset;
+       int offset = -1;
+
+#ifdef HOST_WIN32
+       if (current_object_key)
+               offset = current_object_key;
+#else
        MONO_THREAD_VAR_OFFSET (tls_current_object,offset);
+#endif
        return offset;
 }
 
index bc3459ed3080b2a8f780b7c86e71cd836c7898ba..99a6d9a18bfdc1c2496e0398859274b843eb437a 100755 (executable)
@@ -326,7 +326,7 @@ amd64_set_xmmreg_r4: dest:f src1:f len:14 clob:m
 amd64_set_xmmreg_r8: dest:f src1:f len:14 clob:m
 amd64_save_sp_to_lmf: len:16
 tls_get: dest:i len:32
-tls_get_reg: dest:i src1:i len:32
+tls_get_reg: dest:i src1:i len:64
 tls_set: src1:i len:16
 tls_set_reg: src1:i src2:i len:32
 atomic_add_i4: src1:b src2:i dest:i len:32
index 0a3f9ba9250b5300280809aff40dd17899bb02a3..aa7acf5abc72eb26d1200dce837653f7885f2eab 100644 (file)
@@ -3443,6 +3443,73 @@ mono_amd64_emit_tls_get (guint8* code, int dreg, int tls_offset)
        return code;
 }
 
+#ifdef TARGET_WIN32
+
+#define MAX_TEB_TLS_SLOTS 64
+#define TEB_TLS_SLOTS_OFFSET 0x1480
+#define TEB_TLS_EXPANSION_SLOTS_OFFSET 0x1780
+
+static guint8*
+emit_tls_get_reg_windows (guint8* code, int dreg, int offset_reg)
+{
+       int tmp_reg = -1;
+       guint8 * more_than_64_slots = NULL;
+       guint8 * empty_slot = NULL;
+       guint8 * tls_get_reg_done = NULL;
+       
+       //Use temporary register for offset calculation?
+       if (dreg == offset_reg) {
+               tmp_reg = dreg == AMD64_RAX ? AMD64_RCX : AMD64_RAX;
+               amd64_push_reg (code, tmp_reg);
+               amd64_mov_reg_reg (code, tmp_reg, offset_reg, sizeof (gpointer));
+               offset_reg = tmp_reg;
+       }
+
+       //TEB TLS slot array only contains MAX_TEB_TLS_SLOTS items, if more is used the expansion slots must be addressed.
+       amd64_alu_reg_imm (code, X86_CMP, offset_reg, MAX_TEB_TLS_SLOTS);
+       more_than_64_slots = code;
+       amd64_branch8 (code, X86_CC_GE, 0, TRUE);
+
+       //TLS slot array, _TEB.TlsSlots, is at offset TEB_TLS_SLOTS_OFFSET and index is offset * 8 in Windows 64-bit _TEB structure.
+       amd64_shift_reg_imm (code, X86_SHL, offset_reg, 3);
+       amd64_alu_reg_imm (code, X86_ADD, offset_reg, TEB_TLS_SLOTS_OFFSET);
+
+       //TEB pointer is stored in GS segment register on Windows x64. TLS slot is located at calculated offset from that pointer.
+       x86_prefix (code, X86_GS_PREFIX);
+       amd64_mov_reg_membase (code, dreg, offset_reg, 0, sizeof (gpointer));
+               
+       tls_get_reg_done = code;
+       amd64_jump8 (code, 0);
+
+       amd64_patch (more_than_64_slots, code);
+
+       //TLS expansion slots, _TEB.TlsExpansionSlots, is at offset TEB_TLS_EXPANSION_SLOTS_OFFSET in Windows 64-bit _TEB structure.
+       x86_prefix (code, X86_GS_PREFIX);
+       amd64_mov_reg_mem (code, dreg, TEB_TLS_EXPANSION_SLOTS_OFFSET, sizeof (gpointer));
+       
+       //Check for NULL in _TEB.TlsExpansionSlots.
+       amd64_test_reg_reg (code, dreg, dreg);
+       empty_slot = code;
+       amd64_branch8 (code, X86_CC_EQ, 0, TRUE);
+       
+       //TLS expansion slots are at index offset into the expansion array.
+       //Calculate for the MAX_TEB_TLS_SLOTS offsets, since the interessting offset is offset_reg - MAX_TEB_TLS_SLOTS.
+       amd64_alu_reg_imm (code, X86_SUB, offset_reg, MAX_TEB_TLS_SLOTS);
+       amd64_shift_reg_imm (code, X86_SHL, offset_reg, 3);
+       
+       amd64_mov_reg_memindex (code, dreg, dreg, 0, offset_reg, 0, sizeof (gpointer));
+       
+       amd64_patch (empty_slot, code);
+       amd64_patch (tls_get_reg_done, code);
+
+       if (tmp_reg != -1)
+               amd64_pop_reg (code, tmp_reg);
+
+       return code;
+}
+
+#endif
+
 static guint8*
 emit_tls_get_reg (guint8* code, int dreg, int offset_reg)
 {
@@ -3467,6 +3534,8 @@ emit_tls_get_reg (guint8* code, int dreg, int offset_reg)
        amd64_mov_reg_memindex (code, dreg, dreg, 0, offset_reg, 0, 8);
        if (tmpreg != -1)
                amd64_mov_reg_membase (code, tmpreg, AMD64_RSP, -8, 8);
+#elif defined(TARGET_WIN32)
+       code = emit_tls_get_reg_windows (code, dreg, offset_reg);
 #else
        g_assert_not_reached ();
 #endif
index ff684cbce54f91ed2220113f9153658f59c43989..33c815d75762d6a97121fb703e0660b844fa6c2d 100644 (file)
@@ -407,7 +407,7 @@ typedef struct {
 #define MONO_ARCH_HAVE_UNWIND_BACKTRACE 1
 #endif
 
-#if defined(TARGET_OSX) || defined(__linux__)
+#if defined(TARGET_OSX) || defined(__linux__) || defined(TARGET_WIN32)
 #define MONO_ARCH_HAVE_TLS_GET_REG 1
 #endif
 
index 621a7a5fc31970e22d3e75e4993623ae10dddece..e7764e91beb749709474b294aef00cb5c30932ce 100644 (file)
@@ -59,14 +59,12 @@ void
 mono_runtime_install_handlers (void)
 {
 #ifndef MONO_CROSS_COMPILE
-       if (!mono_aot_only) {
-               win32_seh_init();
-               win32_seh_set_handler(SIGFPE, mono_sigfpe_signal_handler);
-               win32_seh_set_handler(SIGILL, mono_sigill_signal_handler);
-               win32_seh_set_handler(SIGSEGV, mono_sigsegv_signal_handler);
-               if (mini_get_debug_options ()->handle_sigint)
-                       win32_seh_set_handler(SIGINT, mono_sigint_signal_handler);
-       }
+       win32_seh_init();
+       win32_seh_set_handler(SIGFPE, mono_sigfpe_signal_handler);
+       win32_seh_set_handler(SIGILL, mono_sigill_signal_handler);
+       win32_seh_set_handler(SIGSEGV, mono_sigsegv_signal_handler);
+       if (mini_get_debug_options ()->handle_sigint)
+               win32_seh_set_handler(SIGINT, mono_sigint_signal_handler);
 #endif
 }
 
@@ -74,9 +72,7 @@ void
 mono_runtime_cleanup_handlers (void)
 {
 #ifndef MONO_CROSS_COMPILE
-       if (!mono_aot_only) {
-               win32_seh_cleanup();
-       }
+       win32_seh_cleanup();
 #endif
 }