Fix the build.
[mono.git] / mono / mini / aot-compiler.c
index 787a0b127627166dc79d15ed00f845c1922849f7..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);
 
@@ -508,9 +510,31 @@ emit_symbol_size (MonoAotCompile *acfg, const char *name, const char *end_label)
        mono_img_writer_emit_symbol_size (acfg->w, name, end_label);
 }
 
+/* Emit a symbol which is referenced by the MonoAotFileInfo structure */
+static void
+emit_info_symbol (MonoAotCompile *acfg, const char *name)
+{
+       char symbol [256];
+
+       if (acfg->llvm) {
+               emit_label (acfg, name);
+               /* LLVM generated code references this */
+               sprintf (symbol, "%s%s%s", acfg->user_symbol_prefix, acfg->global_prefix, name);
+               emit_label (acfg, symbol);
+               emit_global_inner (acfg, symbol, FALSE);
+       } else {
+               emit_label (acfg, name);
+       }
+}
+
 static void
 emit_string_symbol (MonoAotCompile *acfg, const char *name, const char *value)
 {
+       if (acfg->llvm) {
+               mono_llvm_emit_aot_data (name, (guint8*)value, strlen (value) + 1);
+               return;
+       }
+
        mono_img_writer_emit_section_change (acfg->w, RODATA_SECT, 1);
 #ifdef TARGET_MACH
        /* On apple, all symbols need to be aligned to avoid warnings from ld */
@@ -1174,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:
  *
@@ -1197,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;
@@ -1289,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);
@@ -1355,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
@@ -1524,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);
@@ -2422,11 +2501,14 @@ emit_offset_table (MonoAotCompile *acfg, const char *symbol, int noffsets, int g
 
        g_assert (p - buf <= buf_size);
 
-       emit_section_change (acfg, RODATA_SECT, 1);
-       emit_alignment (acfg, 8);
-       emit_label (acfg, symbol);
-
-       emit_bytes (acfg, buf, p - buf);
+       if (acfg->llvm) {
+               mono_llvm_emit_aot_data (symbol, buf, p - buf);
+       } else {
+               emit_section_change (acfg, RODATA_SECT, 1);
+               emit_alignment (acfg, 8);
+               emit_label (acfg, symbol);
+               emit_bytes (acfg, buf, p - buf);
+       }
 
        g_free (buf);
        g_free (data_buf);
@@ -3112,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:
@@ -3312,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));
@@ -3338,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);
@@ -5298,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:
@@ -5349,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:
@@ -5893,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) {
@@ -5910,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;
@@ -5953,7 +6021,7 @@ emit_plt (MonoAotCompile *acfg)
 
        emit_section_change (acfg, ".text", 0);
        emit_alignment_code (acfg, NACL_SIZE(16, kNaClAlignment));
-       emit_label (acfg, symbol);
+       emit_info_symbol (acfg, symbol);
        emit_label (acfg, acfg->plt_symbol);
 
        for (i = 0; i < acfg->plt_offset; ++i) {
@@ -6058,7 +6126,7 @@ emit_plt (MonoAotCompile *acfg)
        emit_symbol_size (acfg, acfg->plt_symbol, ".");
 
        sprintf (symbol, "plt_end");
-       emit_label (acfg, symbol);
+       emit_info_symbol (acfg, symbol);
 }
 
 /*
@@ -6177,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
@@ -6222,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);
@@ -6366,7 +6423,7 @@ emit_trampolines (MonoAotCompile *acfg)
                                emit_local_symbol (acfg, symbol, end_symbol, TRUE);
 
                        emit_alignment_code (acfg, AOT_FUNC_ALIGNMENT);
-                       emit_label (acfg, symbol);
+                       emit_info_symbol (acfg, symbol);
 
                        acfg->trampoline_got_offset_base [ntype] = tramp_got_offset;
 
@@ -6516,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="));
@@ -6655,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) {
@@ -6663,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
@@ -6756,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:
@@ -6961,8 +7093,21 @@ compile_method (MonoAotCompile *acfg, MonoMethod *method)
        if (!acfg->aot_opts.no_instances && depth < 32) {
                for (patch_info = cfg->patch_info; patch_info; patch_info = patch_info->next) {
                        switch (patch_info->type) {
+                       case MONO_PATCH_INFO_RGCTX_FETCH:
                        case MONO_PATCH_INFO_METHOD: {
-                               MonoMethod *m = patch_info->data.method;
+                               MonoMethod *m = NULL;
+
+                               if (patch_info->type == MONO_PATCH_INFO_RGCTX_FETCH) {
+                                       MonoJumpInfoRgctxEntry *e = patch_info->data.rgctx_entry;
+
+                                       if (e->info_type == MONO_RGCTX_INFO_GENERIC_METHOD_CODE)
+                                               m = e->data->data.method;
+                               } else {
+                                       m = patch_info->data.method;
+                               }
+
+                               if (!m)
+                                       break;
                                if (m->is_inflated) {
                                        if (!(mono_class_generic_sharing_enabled (m->klass) &&
                                                  mono_method_is_generic_sharable_full (m, FALSE, FALSE, FALSE)) &&
@@ -7404,7 +7549,7 @@ emit_llvm_file (MonoAotCompile *acfg)
        if (acfg->aot_opts.mtriple)
                g_string_append_printf (acfg->llc_args, " -mtriple=%s", acfg->aot_opts.mtriple);
 
-       g_string_append_printf (acfg->llc_args, " -mono-eh-frame-symbol=%s", acfg->llvm_eh_frame_symbol);
+       g_string_append_printf (acfg->llc_args, " -mono-eh-frame-symbol=%s%s", acfg->user_symbol_prefix, acfg->llvm_eh_frame_symbol);
 
 #if defined(TARGET_MACH) && defined(TARGET_ARM)
        /* ios requires PIC code now */
@@ -7415,7 +7560,6 @@ emit_llvm_file (MonoAotCompile *acfg)
        else
                g_string_append_printf (acfg->llc_args, " -relocation-model=pic");
 #endif
-       unlink (acfg->tmpfname);
 
        if (acfg->llvm_owriter) {
                /* Emit an object file directly */
@@ -7439,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)
@@ -7456,7 +7601,7 @@ emit_code (MonoAotCompile *acfg)
         */
        emit_section_change (acfg, ".text", 0);
        emit_alignment_code (acfg, 8);
-       emit_label (acfg, "jit_code_start");
+       emit_info_symbol (acfg, "jit_code_start");
 
        /* 
         * Emit some padding so the local symbol for the first method doesn't have the
@@ -7506,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)
@@ -7516,7 +7678,7 @@ emit_code (MonoAotCompile *acfg)
 
        emit_section_change (acfg, ".text", 0);
        emit_alignment_code (acfg, 8);
-       emit_label (acfg, "jit_code_end");
+       emit_info_symbol (acfg, "jit_code_end");
 
        /* To distinguish it from the next symbol */
        emit_padding (acfg, 4);
@@ -7543,7 +7705,7 @@ emit_code (MonoAotCompile *acfg)
        sprintf (symbol, "method_addresses");
        emit_section_change (acfg, ".text", 1);
        emit_alignment_code (acfg, 8);
-       emit_label (acfg, symbol);
+       emit_info_symbol (acfg, symbol);
        emit_local_symbol (acfg, symbol, "method_addresses_end", TRUE);
        emit_unset_mode (acfg);
        if (acfg->need_no_dead_strip)
@@ -7568,7 +7730,7 @@ emit_code (MonoAotCompile *acfg)
        sprintf (symbol, "unbox_trampolines");
        emit_section_change (acfg, RODATA_SECT, 0);
        emit_alignment (acfg, 8);
-       emit_label (acfg, symbol);
+       emit_info_symbol (acfg, symbol);
 
        prev_index = -1;
        for (i = 0; i < acfg->nmethods; ++i) {
@@ -7592,14 +7754,14 @@ emit_code (MonoAotCompile *acfg)
                }
        }
        sprintf (symbol, "unbox_trampolines_end");
-       emit_label (acfg, symbol);
+       emit_info_symbol (acfg, symbol);
        emit_int32 (acfg, 0);
 
        /* Emit a separate table with the trampoline addresses/offsets */
        sprintf (symbol, "unbox_trampoline_addresses");
        emit_section_change (acfg, ".text", 0);
        emit_alignment_code (acfg, 8);
-       emit_label (acfg, symbol);
+       emit_info_symbol (acfg, symbol);
 
        for (i = 0; i < acfg->nmethods; ++i) {
                MonoCompile *cfg;
@@ -7964,11 +8126,15 @@ emit_extra_methods (MonoAotCompile *acfg)
        g_assert (p - buf <= buf_size);
 
        /* Emit the table */
-       sprintf (symbol, "extra_method_table");
-       emit_section_change (acfg, RODATA_SECT, 0);
-       emit_alignment (acfg, 8);
-       emit_label (acfg, symbol);
-       emit_bytes (acfg, buf, p - buf);
+       if (acfg->llvm) {
+               mono_llvm_emit_aot_data ("extra_method_table", buf, p - buf);
+       } else {
+               sprintf (symbol, "extra_method_table");
+               emit_section_change (acfg, RODATA_SECT, 0);
+               emit_alignment (acfg, 8);
+               emit_label (acfg, symbol);
+               emit_bytes (acfg, buf, p - buf);
+       }
 
        /* 
         * Emit a table reverse mapping method indexes to their index in extra_method_info.
@@ -7983,11 +8149,15 @@ emit_extra_methods (MonoAotCompile *acfg)
                encode_int (get_method_index (acfg, method), p, &p);
                encode_int (info_offsets [i], p, &p);
        }
-       sprintf (symbol, "extra_method_info_offsets");
-       emit_section_change (acfg, RODATA_SECT, 0);
-       emit_alignment (acfg, 8);
-       emit_label (acfg, symbol);
-       emit_bytes (acfg, buf, p - buf);
+       if (acfg->llvm) {
+               mono_llvm_emit_aot_data ("extra_method_info_offsets", buf, p - buf);
+       } else {
+               sprintf (symbol, "extra_method_info_offsets");
+               emit_section_change (acfg, RODATA_SECT, 0);
+               emit_alignment (acfg, 8);
+               emit_label (acfg, symbol);
+               emit_bytes (acfg, buf, p - buf);
+       }
 }      
 
 static void
@@ -8051,7 +8221,7 @@ emit_unwind_info (MonoAotCompile *acfg)
        sprintf (symbol, "unwind_info");
        emit_section_change (acfg, RODATA_SECT, 1);
        emit_alignment (acfg, 8);
-       emit_label (acfg, symbol);
+       emit_info_symbol (acfg, symbol);
 
        for (i = 0; i < acfg->unwind_ops->len; ++i) {
                guint32 index = GPOINTER_TO_UINT (g_ptr_array_index (acfg->unwind_ops, i));
@@ -8163,11 +8333,15 @@ emit_class_name_table (MonoAotCompile *acfg)
        }
        g_assert (p - buf <= buf_size);
 
-       sprintf (symbol, "class_name_table");
-       emit_section_change (acfg, RODATA_SECT, 0);
-       emit_alignment (acfg, 8);
-       emit_label (acfg, symbol);
-       emit_bytes (acfg, buf, p - buf);
+       if (acfg->llvm) {
+               mono_llvm_emit_aot_data ("class_name_table", buf, p - buf);
+       } else {
+               sprintf (symbol, "class_name_table");
+               emit_section_change (acfg, RODATA_SECT, 0);
+               emit_alignment (acfg, 8);
+               emit_label (acfg, symbol);
+               emit_bytes (acfg, buf, p - buf);
+       }
 }
 
 static void
@@ -8214,11 +8388,15 @@ emit_image_table (MonoAotCompile *acfg)
        }
        g_assert (p - buf <= buf_size);
 
-       sprintf (symbol, "image_table");
-       emit_section_change (acfg, RODATA_SECT, 1);
-       emit_alignment (acfg, 8);
-       emit_label (acfg, symbol);
-       emit_bytes (acfg, buf, p - buf);
+       if (acfg->llvm) {
+               mono_llvm_emit_aot_data ("image_table", buf, p - buf);
+       } else {
+               sprintf (symbol, "image_table");
+               emit_section_change (acfg, RODATA_SECT, 1);
+               emit_alignment (acfg, 8);
+               emit_label (acfg, symbol);
+               emit_bytes (acfg, buf, p - buf);
+       }
 
        g_free (buf);
 }
@@ -8298,12 +8476,24 @@ 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);
        emit_label (acfg, symbol);
+       if (acfg->llvm)
+               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);
@@ -8403,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);
@@ -8662,7 +8852,10 @@ emit_file_info (MonoAotCompile *acfg)
        info = g_new0 (MonoAotFileInfo, 1);
        init_aot_file_info (acfg, info, gc_name_offset);
 
-       emit_aot_file_info (acfg, info);
+       if (acfg->llvm)
+               mono_llvm_emit_aot_file_info (info, acfg->has_jitted_code);
+       else
+               emit_aot_file_info (acfg, info);
 }
 
 static void
@@ -8670,6 +8863,11 @@ emit_blob (MonoAotCompile *acfg)
 {
        char symbol [128];
 
+       if (acfg->llvm) {
+               mono_llvm_emit_aot_data ("blob", (guint8*)acfg->blob.data, acfg->blob.index);
+               return;
+       }
+
        sprintf (symbol, "blob");
        emit_section_change (acfg, RODATA_SECT, 1);
        emit_alignment (acfg, 8);
@@ -8773,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;
                }
 
@@ -8997,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 ("");
        }
@@ -9006,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);
@@ -9047,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;
@@ -9495,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
 
@@ -9545,8 +9743,6 @@ mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options)
 
 #ifdef ENABLE_LLVM
        if (acfg->llvm) {
-               gboolean res;
-
                if (acfg->aot_opts.asm_only) {
                        if (acfg->aot_opts.outfile) {
                                acfg->tmpfname = g_strdup_printf ("%s", acfg->aot_opts.outfile);
@@ -9570,10 +9766,6 @@ mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options)
                        acfg->llvm_sfile = g_strdup_printf ("%s-llvm.s", acfg->tmpbasename);
                        acfg->llvm_ofile = g_strdup_printf ("%s-llvm.o", acfg->tmpbasename);
                }
-
-               res = emit_llvm_file (acfg);
-               if (!res)
-                       return 1;
        }
 #endif
 
@@ -9643,7 +9835,7 @@ mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options)
                //acfg->gas_line_numbers = TRUE;
        }
 
-       if (!acfg->aot_opts.nodebug || acfg->aot_opts.dwarf_debug) {
+       if ((!acfg->aot_opts.nodebug || acfg->aot_opts.dwarf_debug) && acfg->has_jitted_code) {
                if (acfg->aot_opts.dwarf_debug && !mono_debug_enabled ()) {
                        aot_printerrf (acfg, "The dwarf AOT option requires the --debug option.\n");
                        return 1;
@@ -9706,6 +9898,16 @@ mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options)
                        fprintf (acfg->fp, "\n.section  .note.GNU-stack,\"\",@progbits\n");
        }
 
+#ifdef ENABLE_LLVM
+       if (acfg->llvm) {
+               gboolean res;
+
+               res = emit_llvm_file (acfg);
+               if (!res)
+                       return 1;
+       }
+#endif
+
        TV_GETTIME (btv);
 
        acfg->stats.gen_time = TV_ELAPSED (atv, btv);