Fix the build.
[mono.git] / mono / mini / aot-compiler.c
index 2d9a03b1bb2f72394c03b84ec92022caab725148..0e5fac63d80cdb7e06b32a517892f5890a19e9db 100644 (file)
@@ -42,7 +42,6 @@
 #include <mono/metadata/metadata-internals.h>
 #include <mono/metadata/marshal.h>
 #include <mono/metadata/gc-internal.h>
-#include <mono/metadata/monitor.h>
 #include <mono/metadata/mempool-internals.h>
 #include <mono/metadata/mono-endian.h>
 #include <mono/metadata/threads-types.h>
@@ -298,6 +297,9 @@ get_patch_name (int info)
 
 #endif
 
+static guint32
+get_unwind_info_offset (MonoAotCompile *acfg, guint8 *encoded, guint32 encoded_len);
+
 static char*
 get_plt_entry_debug_sym (MonoAotCompile *acfg, MonoJumpInfo *ji, GHashTable *cache);
 
@@ -517,9 +519,9 @@ emit_info_symbol (MonoAotCompile *acfg, const char *name)
        if (acfg->llvm) {
                emit_label (acfg, name);
                /* LLVM generated code references this */
-               sprintf (symbol, "%s%s", acfg->user_symbol_prefix, name);
+               sprintf (symbol, "%s%s%s", acfg->user_symbol_prefix, acfg->global_prefix, name);
                emit_label (acfg, symbol);
-               emit_global (acfg, symbol, FALSE);
+               emit_global_inner (acfg, symbol, FALSE);
        } else {
                emit_label (acfg, name);
        }
@@ -1196,6 +1198,22 @@ arch_emit_llvm_plt_entry (MonoAotCompile *acfg, const char *got_symbol, int offs
 #endif
 }
 
+/* Save unwind_info in the module and emit the offset to the information at symbol */
+static void save_unwind_info (MonoAotCompile *acfg, char *symbol, GSList *unwind_ops)
+{
+       guint32 uw_offset, encoded_len;
+       guint8 *encoded;
+
+       emit_section_change (acfg, RODATA_SECT, 0);
+       emit_global (acfg, symbol, FALSE);
+       emit_label (acfg, symbol);
+
+       encoded = mono_unwind_ops_encode (unwind_ops, &encoded_len);
+       uw_offset = get_unwind_info_offset (acfg, encoded, encoded_len);
+       g_free (encoded);
+       emit_int32 (acfg, uw_offset);
+}
+
 /*
  * arch_emit_specific_trampoline_pages:
  *
@@ -1219,6 +1237,7 @@ arch_emit_specific_trampoline_pages (MonoAotCompile *acfg)
        guint8 *loop_start, *loop_branch_back, *loop_end_check, *imt_found_check;
        int i;
        int pagesize = MONO_AOT_TRAMP_PAGE_SIZE;
+       GSList *unwind_ops = NULL;
 #define COMMON_TRAMP_SIZE 16
        int count = (pagesize - COMMON_TRAMP_SIZE) / 8;
        int imm8, rot_amount;
@@ -1311,7 +1330,6 @@ arch_emit_specific_trampoline_pages (MonoAotCompile *acfg)
        /* now the imt trampolines: each specific trampolines puts in the ip register
         * the instruction pointer address, so the generic trampoline at the start of the page
         * subtracts 4096 to get to the data page and loads the values
-        * We again fit the generic trampiline in 16 bytes.
         */
 #define IMT_TRAMP_SIZE 72
        sprintf (symbol, "%simt_trampolines_page", acfg->user_symbol_prefix);
@@ -1377,6 +1395,53 @@ arch_emit_specific_trampoline_pages (MonoAotCompile *acfg)
        acfg->tramp_page_code_offsets [MONO_AOT_TRAMP_STATIC_RGCTX] = 16;
        acfg->tramp_page_code_offsets [MONO_AOT_TRAMP_IMT_THUNK] = 72;
        acfg->tramp_page_code_offsets [MONO_AOT_TRAMP_GSHAREDVT_ARG] = 16;
+
+       /* Unwind info for specifc trampolines */
+       sprintf (symbol, "%sspecific_trampolines_page_gen_p", acfg->user_symbol_prefix);
+       /* We unwind to the original caller, from the stack, since lr is clobbered */
+       mono_add_unwind_op_def_cfa (unwind_ops, 0, 0, ARMREG_SP, 14 * sizeof (mgreg_t));
+       mono_add_unwind_op_offset (unwind_ops, 0, 0, ARMREG_LR, -4);
+       save_unwind_info (acfg, symbol, unwind_ops);
+       mono_free_unwind_info (unwind_ops);
+
+       sprintf (symbol, "%sspecific_trampolines_page_sp_p", acfg->user_symbol_prefix);
+       mono_add_unwind_op_def_cfa (unwind_ops, 0, 0, ARMREG_SP, 0);
+       mono_add_unwind_op_def_cfa_offset (unwind_ops, 4, 0, 14 * sizeof (mgreg_t));
+       save_unwind_info (acfg, symbol, unwind_ops);
+       mono_free_unwind_info (unwind_ops);
+
+       /* Unwind info for rgctx trampolines */
+       sprintf (symbol, "%srgctx_trampolines_page_gen_p", acfg->user_symbol_prefix);
+       mono_add_unwind_op_def_cfa (unwind_ops, 0, 0, ARMREG_SP, 0);
+       save_unwind_info (acfg, symbol, unwind_ops);
+
+       sprintf (symbol, "%srgctx_trampolines_page_sp_p", acfg->user_symbol_prefix);
+       save_unwind_info (acfg, symbol, unwind_ops);
+       mono_free_unwind_info (unwind_ops);
+
+       /* Unwind info for gsharedvt trampolines */
+       sprintf (symbol, "%sgsharedvt_trampolines_page_gen_p", acfg->user_symbol_prefix);
+       mono_add_unwind_op_def_cfa (unwind_ops, 0, 0, ARMREG_SP, 0);
+       mono_add_unwind_op_def_cfa_offset (unwind_ops, 4, 0, 4 * sizeof (mgreg_t));
+       save_unwind_info (acfg, symbol, unwind_ops);
+       mono_free_unwind_info (unwind_ops);
+
+       sprintf (symbol, "%sgsharedvt_trampolines_page_sp_p", acfg->user_symbol_prefix);
+       mono_add_unwind_op_def_cfa (unwind_ops, 0, 0, ARMREG_SP, 0);
+       save_unwind_info (acfg, symbol, unwind_ops);
+       mono_free_unwind_info (unwind_ops);
+
+       /* Unwind info for imt trampolines */
+       sprintf (symbol, "%simt_trampolines_page_gen_p", acfg->user_symbol_prefix);
+       mono_add_unwind_op_def_cfa (unwind_ops, 0, 0, ARMREG_SP, 0);
+       mono_add_unwind_op_def_cfa_offset (unwind_ops, 4, 0, 3 * sizeof (mgreg_t));
+       save_unwind_info (acfg, symbol, unwind_ops);
+       mono_free_unwind_info (unwind_ops);
+
+       sprintf (symbol, "%simt_trampolines_page_sp_p", acfg->user_symbol_prefix);
+       mono_add_unwind_op_def_cfa (unwind_ops, 0, 0, ARMREG_SP, 0);
+       save_unwind_info (acfg, symbol, unwind_ops);
+       mono_free_unwind_info (unwind_ops);
 #elif defined(TARGET_ARM64)
        arm64_emit_specific_trampoline_pages (acfg);
 #endif
@@ -1546,14 +1611,6 @@ arch_emit_specific_trampoline (MonoAotCompile *acfg, int offset, int *tramp_size
 
        /* FIXME: Could this clobber the register needed by get_vcall_slot () ? */
 
-       /* We clobber ECX, since EAX is used as MONO_ARCH_MONITOR_OBJECT_REG */
-#ifdef MONO_ARCH_MONITOR_OBJECT_REG
-       g_assert (MONO_ARCH_MONITOR_OBJECT_REG != X86_ECX);
-#ifdef MONO_ARCH_MONITOR_LOCK_TAKEN_REG
-       g_assert (MONO_ARCH_MONITOR_LOCK_TAKEN_REG != X86_ECX);
-#endif
-#endif
-
        code = buf;
        /* Load mscorlib got address */
        x86_mov_reg_membase (code, X86_ECX, MONO_ARCH_GOT_REG, sizeof (gpointer), 4);
@@ -3137,11 +3194,7 @@ is_plt_patch (MonoJumpInfo *patch_info)
        case MONO_PATCH_INFO_INTERNAL_METHOD:
        case MONO_PATCH_INFO_JIT_ICALL_ADDR:
        case MONO_PATCH_INFO_ICALL_ADDR:
-       case MONO_PATCH_INFO_CLASS_INIT:
        case MONO_PATCH_INFO_RGCTX_FETCH:
-       case MONO_PATCH_INFO_MONITOR_ENTER:
-       case MONO_PATCH_INFO_MONITOR_ENTER_V4:
-       case MONO_PATCH_INFO_MONITOR_EXIT:
        case MONO_PATCH_INFO_LLVM_IMT_TRAMPOLINE:
                return TRUE;
        default:
@@ -3337,7 +3390,7 @@ add_extra_method_with_depth (MonoAotCompile *acfg, MonoMethod *method, int depth
                method = mini_get_shared_method (method);
        else if ((acfg->opts & MONO_OPT_GSHAREDVT) && prefer_gsharedvt_method (acfg, method) && mono_method_is_generic_sharable_full (method, FALSE, FALSE, TRUE))
                /* Use the gsharedvt version */
-               return;
+               method = mini_get_shared_method_full (method, TRUE, TRUE);
 
        if (acfg->aot_opts.log_generics)
                aot_printf (acfg, "%*sAdding method %s.\n", depth, "", mono_method_full_name (method, TRUE));
@@ -3363,7 +3416,7 @@ add_jit_icall_wrapper (gpointer key, gpointer value, gpointer user_data)
                return;
 
        name = g_strdup_printf ("__icall_wrapper_%s", callinfo->name);
-       wrapper = mono_marshal_get_icall_wrapper (callinfo->sig, name, callinfo->func, check_for_pending_exc);
+       wrapper = mono_marshal_get_icall_wrapper (callinfo->sig, name, callinfo->func, TRUE);
        g_free (name);
 
        add_method (acfg, wrapper);
@@ -5323,7 +5376,6 @@ encode_patch (MonoAotCompile *acfg, MonoJumpInfo *patch_info, guint8 *buf, guint
        case MONO_PATCH_INFO_CLASS:
        case MONO_PATCH_INFO_IID:
        case MONO_PATCH_INFO_ADJUSTED_IID:
-       case MONO_PATCH_INFO_CLASS_INIT:
                encode_klass_ref (acfg, patch_info->data.klass, p, &p);
                break;
        case MONO_PATCH_INFO_DELEGATE_TRAMPOLINE:
@@ -5374,9 +5426,6 @@ encode_patch (MonoAotCompile *acfg, MonoJumpInfo *patch_info, guint8 *buf, guint
                encode_patch (acfg, entry->data, p, &p);
                break;
        }
-       case MONO_PATCH_INFO_MONITOR_ENTER:
-       case MONO_PATCH_INFO_MONITOR_ENTER_V4:
-       case MONO_PATCH_INFO_MONITOR_EXIT:
        case MONO_PATCH_INFO_SEQ_POINT_INFO:
                break;
        case MONO_PATCH_INFO_LLVM_IMT_TRAMPOLINE:
@@ -5918,7 +5967,6 @@ static char*
 get_plt_entry_debug_sym (MonoAotCompile *acfg, MonoJumpInfo *ji, GHashTable *cache)
 {
        char *debug_sym = NULL;
-       char *s;
        char *prefix;
 
        if (acfg->llvm && llvm_acfg->aot_opts.static_link) {
@@ -5935,11 +5983,6 @@ get_plt_entry_debug_sym (MonoAotCompile *acfg, MonoJumpInfo *ji, GHashTable *cac
        case MONO_PATCH_INFO_INTERNAL_METHOD:
                debug_sym = g_strdup_printf ("%s_jit_icall_%s", prefix, ji->data.name);
                break;
-       case MONO_PATCH_INFO_CLASS_INIT:
-               s = mono_type_get_name (&ji->data.klass->byval_arg);
-               debug_sym = g_strdup_printf ("%s__class_init_%s", prefix, s);
-               g_free (s);
-               break;
        case MONO_PATCH_INFO_RGCTX_FETCH:
                debug_sym = g_strdup_printf ("%s_rgctx_fetch_%d", prefix, acfg->label_generator ++);
                break;
@@ -6202,7 +6245,7 @@ emit_trampoline_full (MonoAotCompile *acfg, int got_offset, MonoTrampInfo *info,
 static G_GNUC_UNUSED void
 emit_trampoline (MonoAotCompile *acfg, int got_offset, MonoTrampInfo *info)
 {
-       emit_trampoline_full (acfg, got_offset, info, FALSE);
+       emit_trampoline_full (acfg, got_offset, info, TRUE);
 }
 
 static void
@@ -6247,17 +6290,6 @@ emit_trampolines (MonoAotCompile *acfg)
                        emit_trampoline (acfg, acfg->got_offset, info);
                }
 
-#if defined(MONO_ARCH_MONITOR_OBJECT_REG)
-               mono_arch_create_monitor_enter_trampoline (&info, FALSE, TRUE);
-               emit_trampoline (acfg, acfg->got_offset, info);
-#if defined(MONO_ARCH_MONITOR_LOCK_TAKEN_REG)
-               mono_arch_create_monitor_enter_trampoline (&info, TRUE, TRUE);
-               emit_trampoline (acfg, acfg->got_offset, info);
-#endif
-               mono_arch_create_monitor_exit_trampoline (&info, TRUE);
-               emit_trampoline (acfg, acfg->got_offset, info);
-#endif
-
                /* Emit the exception related code pieces */
                mono_arch_get_restore_context (&info, TRUE);
                emit_trampoline (acfg, acfg->got_offset, info);
@@ -6541,14 +6573,87 @@ clean_path (gchar * path)
        return clean;
 }
 
+static GPtrArray *
+mono_aot_split_options (const char *aot_options)
+{
+       enum MonoAotOptionState {
+               MONO_AOT_OPTION_STATE_DEFAULT,
+               MONO_AOT_OPTION_STATE_STRING,
+               MONO_AOT_OPTION_STATE_ESCAPE,
+       };
+
+       GPtrArray *args = g_ptr_array_new ();
+       enum MonoAotOptionState state = MONO_AOT_OPTION_STATE_DEFAULT;
+       gchar const *opt_start = aot_options;
+       gboolean end_of_string = FALSE;
+       gchar cur;
+
+       g_return_val_if_fail (aot_options != NULL, NULL);
+
+       while ((cur = *aot_options) != '\0') {
+               if (state == MONO_AOT_OPTION_STATE_ESCAPE)
+                       goto next;
+
+               switch (cur) {
+               case '"':
+                       // If we find a quote, then if we're in the default case then
+                       // it means we've found the start of a string, if not then it
+                       // means we've found the end of the string and should switch
+                       // back to the default case.            
+                       switch (state) {
+                       case MONO_AOT_OPTION_STATE_DEFAULT:
+                               state = MONO_AOT_OPTION_STATE_STRING;
+                               break;
+                       case MONO_AOT_OPTION_STATE_STRING:
+                               state = MONO_AOT_OPTION_STATE_DEFAULT;
+                               break;
+                       case MONO_AOT_OPTION_STATE_ESCAPE:
+                               g_assert_not_reached ();
+                               break;
+                       }
+                       break;
+               case '\\':
+                       // If we've found an escaping operator, then this means we
+                       // should not process the next character if inside a string.            
+                       if (state == MONO_AOT_OPTION_STATE_STRING) 
+                               state = MONO_AOT_OPTION_STATE_ESCAPE;
+                       break;
+               case ',':
+                       // If we're in the default state then this means we've found
+                       // an option, store it for later processing.
+                       if (state == MONO_AOT_OPTION_STATE_DEFAULT)
+                               goto new_opt;
+                       break;
+               }
+
+       next:
+               aot_options++;
+               // If the next character is end of string, then process the last option.
+               if (*(aot_options) == '\0') {
+                       end_of_string = TRUE;
+                       goto new_opt;
+               }
+               continue;
+
+       new_opt:
+               g_ptr_array_add (args, g_strndup (opt_start, aot_options - opt_start));
+               opt_start = ++aot_options;
+               if (end_of_string)
+                       break;
+               goto next;
+       }
+
+       return args;
+}
+
 static void
 mono_aot_parse_options (const char *aot_options, MonoAotOptions *opts)
 {
-       gchar **args, **ptr;
+       GPtrArray* args;
 
-       args = g_strsplit (aot_options ? aot_options : "", ",", -1);
-       for (ptr = args; ptr && *ptr; ptr ++) {
-               const char *arg = *ptr;
+       args = mono_aot_split_options (aot_options ? aot_options : "");
+       for (int i = 0; i < args->len; ++i) {
+               const char *arg = g_ptr_array_index (args, i);
 
                if (str_begins_with (arg, "outfile=")) {
                        opts->outfile = g_strdup (arg + strlen ("outfile="));
@@ -6680,6 +6785,8 @@ mono_aot_parse_options (const char *aot_options, MonoAotOptions *opts)
                        fprintf (stderr, "AOT : Unknown argument '%s'.\n", arg);
                        exit (1);
                }
+
+               g_free ((gpointer) arg);
        }
 
        if (opts->use_trampolines_page) {
@@ -6688,7 +6795,8 @@ mono_aot_parse_options (const char *aot_options, MonoAotOptions *opts)
                opts->nimt_trampolines = 0;
                opts->ngsharedvt_arg_trampolines = 0;
        }
-       g_strfreev (args);
+
+       g_ptr_array_free (args, /*free_seg=*/TRUE);
 }
 
 static void
@@ -6781,7 +6889,6 @@ can_encode_patch (MonoAotCompile *acfg, MonoJumpInfo *patch_info)
                return can_encode_method (acfg, method);
        }
        case MONO_PATCH_INFO_VTABLE:
-       case MONO_PATCH_INFO_CLASS_INIT:
        case MONO_PATCH_INFO_CLASS:
        case MONO_PATCH_INFO_IID:
        case MONO_PATCH_INFO_ADJUSTED_IID:
@@ -7476,6 +7583,7 @@ static void
 emit_code (MonoAotCompile *acfg)
 {
        int oindex, i, prev_index;
+       gboolean saved_unbox_info = FALSE;
        char symbol [256];
 
 #if defined(TARGET_POWERPC64)
@@ -7543,6 +7651,23 @@ emit_code (MonoAotCompile *acfg)
 
                        if (acfg->thumb_mixed && cfg->compile_llvm)
                                emit_set_arm_mode (acfg);
+
+                       if (!saved_unbox_info) {
+                               char user_symbol [128];
+                               GSList *unwind_ops;
+                               sprintf (user_symbol, "%sunbox_trampoline_p", acfg->user_symbol_prefix);
+
+                               emit_label (acfg, "ut_end");
+
+                               unwind_ops = mono_unwind_get_cie_program ();
+                               save_unwind_info (acfg, user_symbol, unwind_ops);
+                               mono_free_unwind_info (unwind_ops);
+
+                               /* Save the unbox trampoline size */
+                               emit_symbol_diff (acfg, "ut_end", symbol, 0);
+
+                               saved_unbox_info = TRUE;
+                       }
                }
 
                if (cfg->compile_llvm)
@@ -8351,6 +8476,15 @@ emit_got (MonoAotCompile *acfg)
 
        /* Don't make GOT global so accesses to it don't need relocations */
        sprintf (symbol, "%s", acfg->got_symbol);
+
+#ifdef TARGET_MACH
+       emit_unset_mode (acfg);
+       fprintf (acfg->fp, ".section __DATA, __bss\n");
+       emit_alignment (acfg, 8);
+       if (acfg->llvm)
+               emit_info_symbol (acfg, "jit_got");
+       fprintf (acfg->fp, ".lcomm %s, %d\n", acfg->got_symbol, (int)(acfg->got_offset * sizeof (gpointer)));
+#else
        emit_section_change (acfg, ".bss", 0);
        emit_alignment (acfg, 8);
        emit_local_symbol (acfg, symbol, "got_end", FALSE);
@@ -8359,6 +8493,7 @@ emit_got (MonoAotCompile *acfg)
                emit_info_symbol (acfg, "jit_got");
        if (acfg->got_offset > 0)
                emit_zero_bytes (acfg, (int)(acfg->got_offset * sizeof (gpointer)));
+#endif
 
        sprintf (symbol, "got_end");
        emit_label (acfg, symbol);
@@ -8458,7 +8593,7 @@ emit_globals (MonoAotCompile *acfg)
        emit_section_change (acfg, ".data", 0);
        /* This is not a global, since it is accessed by the init function */
        emit_alignment (acfg, 8);
-       emit_label (acfg, symbol);
+       emit_info_symbol (acfg, symbol);
 
        sprintf (symbol, "%sglobals_hash", acfg->temp_prefix);
        emit_pointer (acfg, symbol);
@@ -8836,7 +8971,7 @@ collect_methods (MonoAotCompile *acfg)
                if (mono_aot_mode_is_full (&acfg->aot_opts) && method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
                        /* Compile the wrapper instead */
                        /* We do this here instead of add_wrappers () because it is easy to do it here */
-                       MonoMethod *wrapper = mono_marshal_get_native_wrapper (method, check_for_pending_exc, TRUE);
+                       MonoMethod *wrapper = mono_marshal_get_native_wrapper (method, TRUE, TRUE);
                        method = wrapper;
                }
 
@@ -9060,7 +9195,7 @@ compile_asm (MonoAotCompile *acfg)
        tmp_outfile_name = g_strdup_printf ("%s.tmp", outfile_name);
 
        if (acfg->llvm) {
-               llvm_ofile = g_strdup (acfg->llvm_ofile);
+               llvm_ofile = g_strdup_printf ("\"%s\"", acfg->llvm_ofile);
        } else {
                llvm_ofile = g_strdup ("");
        }
@@ -9069,7 +9204,7 @@ compile_asm (MonoAotCompile *acfg)
        g_strdelimit (ld_flags, ";", ' ');
 
 #ifdef LD_NAME
-       command = g_strdup_printf ("%s -o %s %s %s.o %s", LD_NAME, tmp_outfile_name, llvm_ofile, acfg->tmpfname, ld_flags);
+       command = g_strdup_printf ("%s -o \"%s\" %s \"%s.o\" %s", LD_NAME, tmp_outfile_name, llvm_ofile, acfg->tmpfname, ld_flags);
 #else
        command = g_strdup_printf ("\"%sld\" %s -shared -o %s %s %s.o %s", tool_prefix, LD_OPTIONS, tmp_outfile_name, llvm_ofile,
                acfg->tmpfname, ld_flags);
@@ -9110,7 +9245,7 @@ compile_asm (MonoAotCompile *acfg)
        rename (tmp_outfile_name, outfile_name);
 
 #if defined(TARGET_MACH)
-       command = g_strdup_printf ("dsymutil %s", outfile_name);
+       command = g_strdup_printf ("dsymutil \"%s\"", outfile_name);
        aot_printf (acfg, "Executing dsymutil: %s\n", command);
        if (execute_system (command) != 0) {
                return 1;
@@ -9558,7 +9693,7 @@ mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options)
 #ifdef ENABLE_LLVM
        if (acfg->llvm) {
                llvm_acfg = acfg;
-               mono_llvm_create_aot_module (acfg->global_prefix, TRUE);
+               mono_llvm_create_aot_module (acfg->image->assembly, acfg->global_prefix, TRUE, acfg->aot_opts.static_link);
        }
 #endif