Merge pull request #2794 from xmcclure/win-aot-basic
authormonojenkins <jo.shields+jenkins@xamarin.com>
Tue, 29 Mar 2016 16:31:13 +0000 (17:31 +0100)
committermonojenkins <jo.shields+jenkins@xamarin.com>
Tue, 29 Mar 2016 16:31:13 +0000 (17:31 +0100)
Make AOT compilation on 64 bit windows produce executables

This PR contains three commits (see commit descriptions) which:

- Fix 64-bit debug windows builds in MSVC 2015
- Make it possible to use the tool-prefix aot option with mono/mini make fullaotcheck (necessary if you are in cygwin and wish to invoke `x86_64-w64-mingw32-gcc`)
- Change mini so that `--aot=full` successfully emits 64-bit windows executables.

Building 32 bit executables will generally fail because we do not follow cdecl. The 64 bit executables do not run properly when executed.

mono/mini/Makefile.am.in
mono/mini/aot-compiler.c
mono/mini/genmdesc.c
mono/mini/image-writer.c
mono/mini/mini-windows.c

index 2366d17c3377b188fad1685e65a70182d3a17d61..f75db695f358153a26e0a0ec5c21958fec9390f4 100755 (executable)
@@ -725,9 +725,9 @@ FULLAOT_LIBS = \
 fullaotcheck: $(mono) $(fullaot_regtests)
        rm -rf fullaot-tmp
        mkdir fullaot-tmp
-       $(MAKE) fullaot-libs AOT_FLAGS=full GSHAREDVT=$(GSHAREDVT)
+       $(MAKE) fullaot-libs AOT_FLAGS="full,$(MONO_FULLAOT_ADDITIONAL_ARGS)" GSHAREDVT=$(GSHAREDVT)
        cp $(regtests) $(fullaot_regtests) generics-variant-types.dll TestDriver.dll fullaot-tmp/
-       MONO_PATH=fullaot-tmp $(top_builddir)/runtime/mono-wrapper $(LLVM_AOT_RUNTIME_OPTS) $(GSHAREDVT_RUNTIME_OPTS) --aot=full fullaot-tmp/{generics-variant-types.dll,TestDriver.dll,*.exe} || exit 1
+       MONO_PATH=fullaot-tmp $(top_builddir)/runtime/mono-wrapper $(LLVM_AOT_RUNTIME_OPTS) $(GSHAREDVT_RUNTIME_OPTS) --aot="full,$(MONO_FULLAOT_ADDITIONAL_ARGS)" fullaot-tmp/{generics-variant-types.dll,TestDriver.dll,*.exe} || exit 1
        ln -s $(if $(MONO_EXECUTABLE),$(MONO_EXECUTABLE),$$PWD/mono) fullaot-tmp/
        for i in $(fullaot_regtests); do echo $$i; MONO_PATH=fullaot-tmp $(top_builddir)/runtime/mono-wrapper --full-aot fullaot-tmp/$$i --exclude '!FULLAOT' $(ARCH_FULLAOT_EXCLUDE) || exit 1; done
 
@@ -748,7 +748,7 @@ llvmonly_regtests = $(fullaot_regtests) gshared.exe
 llvmonlycheck: mono $(llvmonly_regtests)
        rm -rf fullaot-tmp
        mkdir fullaot-tmp
-       $(MAKE) fullaot-libs AOT_FLAGS=llvmonly
+       $(MAKE) fullaot-libs AOT_FLAGS="llvmonly,$(MONO_FULLAOT_ADDITIONAL_ARGS)"
        cp $(llvmonly_regtests) generics-variant-types.dll TestDriver.dll fullaot-tmp/
        MONO_PATH=fullaot-tmp $(top_builddir)/runtime/mono-wrapper  --aot=llvmonly fullaot-tmp/{generics-variant-types.dll,TestDriver.dll,*.exe} || exit 1
        ln -s $$PWD/mono fullaot-tmp/
index 63327ec449843186befd139b376e058bcd0e0301..b74b1107fbfb328cc1cd69361a9c3d68449052cd 100644 (file)
@@ -6676,6 +6676,15 @@ wrap_path (gchar * path)
        return clean;
 }
 
+// Duplicate a char range and add it to a ptrarray, but only if it is nonempty
+static void
+ptr_array_add_range_if_nonempty(GPtrArray *args, gchar const *start, gchar const *end)
+{
+       ptrdiff_t len = end-start;
+       if (len > 0)
+               g_ptr_array_add (args, g_strndup (start, len));
+}
+
 static GPtrArray *
 mono_aot_split_options (const char *aot_options)
 {
@@ -6731,6 +6740,7 @@ mono_aot_split_options (const char *aot_options)
 
        next:
                aot_options++;
+       restart:
                // If the next character is end of string, then process the last option.
                if (*(aot_options) == '\0') {
                        end_of_string = TRUE;
@@ -6739,11 +6749,11 @@ mono_aot_split_options (const char *aot_options)
                continue;
 
        new_opt:
-               g_ptr_array_add (args, g_strndup (opt_start, aot_options - opt_start));
+               ptr_array_add_range_if_nonempty (args, opt_start, aot_options);
                opt_start = ++aot_options;
                if (end_of_string)
                        break;
-               goto next;
+               goto restart; // Check for null and continue loop
        }
 
        return args;
@@ -9550,7 +9560,6 @@ compile_asm (MonoAotCompile *acfg)
 #define AS_OPTIONS "--64"
 #elif defined(TARGET_POWERPC64)
 #define AS_OPTIONS "-a64 -mppc64"
-#define LD_OPTIONS "-m elf64ppc"
 #elif defined(sparc) && SIZEOF_VOID_P == 8
 #define AS_OPTIONS "-xarch=v9"
 #elif defined(TARGET_X86) && defined(TARGET_MACH) && !defined(__native_client_codegen__)
@@ -9571,22 +9580,30 @@ compile_asm (MonoAotCompile *acfg)
 #define AS_NAME "as"
 #endif
 
-#ifndef LD_OPTIONS
-#define LD_OPTIONS ""
-#endif
-
 #if defined(sparc)
-#define LD_NAME "ld -shared -G"
+#define LD_NAME "ld"
+#define LD_OPTIONS "-shared -G"
 #elif defined(__ppc__) && defined(TARGET_MACH)
-#define LD_NAME "gcc -dynamiclib"
+#define LD_NAME "gcc"
+#define LD_OPTIONS "-dynamiclib"
 #elif defined(TARGET_AMD64) && defined(TARGET_MACH)
-#define LD_NAME "clang --shared"
+#define LD_NAME "clang"
+#define LD_OPTIONS "--shared"
 #elif defined(TARGET_WIN32) && !defined(TARGET_ANDROID)
-#define LD_NAME "gcc -shared --dll"
+#define LD_NAME "gcc"
+#define LD_OPTIONS "-shared"
 #elif defined(TARGET_X86) && defined(TARGET_MACH) && !defined(__native_client_codegen__)
-#define LD_NAME "clang -m32 -dynamiclib"
+#define LD_NAME "clang"
+#define LD_OPTIONS "-m32 -dynamiclib"
 #elif defined(TARGET_ARM) && !defined(TARGET_ANDROID)
-#define LD_NAME "gcc --shared"
+#define LD_NAME "gcc"
+#define LD_OPTIONS "--shared"
+#elif defined(TARGET_POWERPC64)
+#define LD_OPTIONS "-m elf64ppc"
+#endif
+
+#ifndef LD_OPTIONS
+#define LD_OPTIONS ""
 #endif
 
        if (acfg->aot_opts.asm_only) {
@@ -9662,10 +9679,11 @@ compile_asm (MonoAotCompile *acfg)
                ld_flags = g_strdup_printf ("%s %s", ld_flags, "-lstdc++");
 
 #ifdef LD_NAME
-       command = g_strdup_printf ("%s -o %s %s %s %s", LD_NAME,
+       command = g_strdup_printf ("%s%s %s -o %s %s %s %s", tool_prefix, LD_NAME, LD_OPTIONS,
                wrap_path (tmp_outfile_name), wrap_path (llvm_ofile),
                wrap_path (g_strdup_printf ("%s.o", acfg->tmpfname)), ld_flags);
 #else
+       // Default (linux)
        command = g_strdup_printf ("\"%sld\" %s -shared -o %s %s %s %s", tool_prefix, LD_OPTIONS,
                wrap_path (tmp_outfile_name), wrap_path (llvm_ofile),
                wrap_path (g_strdup_printf ("%s.o", acfg->tmpfname)), ld_flags);
index b996f8f83b55a07a401a31409d4f5c437228d43c..7118e19c8cec06cd9fb7588d5e7c89f2e9564706 100644 (file)
@@ -54,6 +54,14 @@ static GHashTable *template_table;
 
 #define eat_whitespace(s) while (*(s) && isspace (*(s))) s++;
 
+// Per spec isalnum() expects input in the range 0-255
+// and can misbehave if you pass in a signed char.
+static int
+isalnum_char(char c)
+{
+       return isalnum ((unsigned char)c);
+}
+
 static int
 load_file (const char *name) {
        FILE *f;
@@ -163,7 +171,7 @@ load_file (const char *name) {
                                OpDesc *tdesc;
                                p += 9;
                                tname = p;
-                               while (*p && isalnum (*p)) ++p;
+                               while (*p && isalnum_char (*p)) ++p;
                                *p++ = 0;
                                tdesc = (OpDesc *)g_hash_table_lookup (template_table, tname);
                                if (!tdesc)
@@ -181,7 +189,7 @@ load_file (const char *name) {
                                        g_error ("Duplicated name tag in template %s at '%s' at line %d in %s\n", desc->name, p, line, name);
                                p += 5;
                                tname = p;
-                               while (*p && isalnum (*p)) ++p;
+                               while (*p && isalnum_char (*p)) ++p;
                                *p++ = 0;
                                if (g_hash_table_lookup (template_table, tname))
                                        g_error ("Duplicated template %s at line %d in %s\n", tname, line, name);
@@ -220,7 +228,7 @@ init_table (void) {
 
 static void
 output_char (FILE *f, char c) {
-       if (isalnum (c))
+       if (isalnum_char (c))
                fprintf (f, "%c", c);
        else
                fprintf (f, "\\x%x\" \"", (guint8)c);
index c060fdc99a66028193f1d3efa63033a18d6a0eca..4992565ba0d162951515dee73e1177f56124f4f8 100644 (file)
@@ -1762,8 +1762,14 @@ asm_writer_emit_symbol_type (MonoImageWriter *acfg, const char *name, gboolean f
                stype = "object";
 
        asm_writer_emit_unset_mode (acfg);
+
 #if defined(TARGET_ASM_APPLE)
 
+#elif defined(TARGET_WIN32)
+       if (func)
+               fprintf (acfg->fp, "\t.def %s; .scl 2; .type 32; .endef\n", name);
+       else
+               fprintf (acfg->fp, "\t.data\n");
 #elif defined(TARGET_ARM)
        fprintf (acfg->fp, "\t.type %s,#%s\n", name, stype);
 #else
@@ -1786,7 +1792,7 @@ asm_writer_emit_local_symbol (MonoImageWriter *acfg, const char *name, const cha
 {
        asm_writer_emit_unset_mode (acfg);
 
-#ifndef TARGET_ASM_APPLE
+#if !defined(TARGET_ASM_APPLE) && !defined(TARGET_WIN32)
        fprintf (acfg->fp, "\t.local %s\n", name);
 #endif
 
@@ -1798,7 +1804,8 @@ asm_writer_emit_symbol_size (MonoImageWriter *acfg, const char *name, const char
 {
        asm_writer_emit_unset_mode (acfg);
 
-#ifndef TARGET_ASM_APPLE
+
+#if !defined(TARGET_ASM_APPLE) && !defined(TARGET_WIN32)
        fprintf (acfg->fp, "\t.size %s,%s-%s\n", name, end_label, name);
 #endif
 }
index 4bcc19b5bfb64d86d12da04f3653159639057a1f..41f12051f906929073be867a6b0076a04b8dbf11 100644 (file)
@@ -58,12 +58,14 @@ void
 mono_runtime_install_handlers (void)
 {
 #ifndef MONO_CROSS_COMPILE
-       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);
+       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);
+       }
 #endif
 }
 
@@ -71,7 +73,9 @@ void
 mono_runtime_cleanup_handlers (void)
 {
 #ifndef MONO_CROSS_COMPILE
-       win32_seh_cleanup();
+       if (!mono_aot_only) {
+               win32_seh_cleanup();
+       }
 #endif
 }