Add more logging to the sdb debugger thread.
[mono.git] / mono / mini / aot-compiler.c
index d5919342c1d71af0647a7813d303346e0c1d1513..df4253f1f61e5f8c196be1508f7c59cee8d43cdd 100644 (file)
@@ -65,6 +65,7 @@
 #include "mini.h"
 #include "image-writer.h"
 #include "dwarfwriter.h"
+#include "mini-gc.h"
 
 #if !defined(DISABLE_AOT) && !defined(DISABLE_JIT)
 
@@ -80,9 +81,9 @@
 
 #ifdef TARGET_WIN32
 #define SHARED_EXT ".dll"
-#elif defined(__ppc__) && defined(__APPLE__)
+#elif defined(__ppc__) && defined(TARGET_MACH)
 #define SHARED_EXT ".dylib"
-#elif defined(__APPLE__) && defined(TARGET_X86) && !defined(__native_client_codegen__)
+#elif defined(TARGET_MACH) && defined(TARGET_X86) && !defined(__native_client_codegen__)
 #define SHARED_EXT ".dylib"
 #else
 #define SHARED_EXT ".so"
@@ -123,6 +124,7 @@ typedef struct MonoAotOptions {
        gboolean soft_debug;
        gboolean log_generics;
        gboolean direct_pinvoke;
+       gboolean direct_icalls;
        int nthreads;
        int ntrampolines;
        int nrgctx_trampolines;
@@ -183,6 +185,7 @@ typedef struct MonoAotCompile {
        MonoAotOptions aot_opts;
        guint32 nmethods;
        guint32 opts;
+       guint32 simd_opts;
        MonoMemPool *mempool;
        MonoAotStats stats;
        int method_index;
@@ -405,7 +408,7 @@ static void
 emit_string_symbol (MonoAotCompile *acfg, const char *name, const char *value)
 {
        img_writer_emit_section_change (acfg->w, RODATA_SECT, 1);
-#ifdef __APPLE__
+#ifdef TARGET_MACH
        /* On apple, all symbols need to be aligned to avoid warnings from ld */
        emit_alignment (acfg, 4);
 #endif
@@ -529,7 +532,7 @@ encode_sleb128 (gint32 value, guint8 *buf, guint8 **endbuf)
 #endif
 
 #ifdef TARGET_ARM
-#ifdef __MACH__
+#ifdef TARGET_MACH
 #define AOT_TARGET_STR "ARM (MACH)"
 #else
 #define AOT_TARGET_STR "ARM (!MACH)"
@@ -585,7 +588,7 @@ arch_init (MonoAotCompile *acfg)
                g_string_append (acfg->llc_args, "-mattr=+v6");
        } else {
 #ifdef ARM_FPU_VFP
-               g_string_append (acfg->llc_args, " -mattr=+vfp2,+d16");
+               g_string_append (acfg->llc_args, " -mattr=+vfp2,-neon,+d16");
                g_string_append (acfg->as_args, " -mfpu=vfp3");
 #else
                g_string_append (acfg->llc_args, " -soft-float");
@@ -598,7 +601,7 @@ arch_init (MonoAotCompile *acfg)
                mono_arch_set_target (acfg->aot_opts.mtriple);
 #endif
 
-#ifdef __APPLE__
+#ifdef TARGET_MACH
        acfg->llvm_label_prefix = "_";
        acfg->need_no_dead_strip = TRUE;
 #endif
@@ -619,8 +622,13 @@ arch_emit_direct_call (MonoAotCompile *acfg, const char *target, int *call_size)
 {
 #if defined(TARGET_X86) || defined(TARGET_AMD64)
        /* Need to make sure this is exactly 5 bytes long */
-       emit_byte (acfg, '\xe8');
-       emit_symbol_diff (acfg, target, ".", -4);
+       if (FALSE && !acfg->use_bin_writer) {
+               img_writer_emit_unset_mode (acfg->w);
+               fprintf (acfg->fp, "call %s\n", target);
+       } else {
+               emit_byte (acfg, '\xe8');
+               emit_symbol_diff (acfg, target, ".", -4);
+       }
        *call_size = 5;
 #elif defined(TARGET_ARM)
        if (acfg->use_bin_writer) {
@@ -1323,7 +1331,7 @@ arch_emit_imt_thunk (MonoAotCompile *acfg, int offset, int *tramp_size)
 #if defined(__native_client_codegen__)
        guint8 *buf_alloc;
 #endif
-       guint8 *labels [3];
+       guint8 *labels [16];
        guint8 mov_buf[3];
        guint8 *mov_buf_ptr = mov_buf;
 
@@ -1363,8 +1371,18 @@ arch_emit_imt_thunk (MonoAotCompile *acfg, int offset, int *tramp_size)
        amd64_jump_membase (code, MONO_ARCH_IMT_SCRATCH_REG, 0);
 
        /* No match */
-       /* FIXME: */
        mono_amd64_patch (labels [1], code);
+       /* Load fail tramp */
+       amd64_alu_reg_imm (code, X86_ADD, MONO_ARCH_IMT_SCRATCH_REG, sizeof (gpointer));
+       /* Check if there is a fail tramp */
+       amd64_alu_membase_imm (code, X86_CMP, MONO_ARCH_IMT_SCRATCH_REG, 0, 0);
+       labels [3] = code;
+       amd64_branch8 (code, X86_CC_Z, 0, FALSE);
+       /* Jump to fail tramp */
+       amd64_jump_membase (code, MONO_ARCH_IMT_SCRATCH_REG, 0);
+
+       /* Fail */
+       mono_amd64_patch (labels [3], code);
        x86_breakpoint (code);
 
        /* mov <OFFSET>(%rip), MONO_ARCH_IMT_SCRATCH_REG */
@@ -1393,7 +1411,7 @@ arch_emit_imt_thunk (MonoAotCompile *acfg, int offset, int *tramp_size)
 #ifdef __native_client_codegen__
        guint8 *buf_alloc;
 #endif
-       guint8 *labels [3];
+       guint8 *labels [16];
 
 #if defined(__default_codegen__)
        code = buf = g_malloc (256);
@@ -1438,8 +1456,19 @@ arch_emit_imt_thunk (MonoAotCompile *acfg, int offset, int *tramp_size)
        x86_ret (code);
 
        /* No match */
-       /* FIXME: */
        mono_x86_patch (labels [1], code);
+       /* Load fail tramp */
+       x86_mov_reg_membase (code, X86_EAX, X86_EAX, sizeof (gpointer), 4);
+       x86_alu_membase_imm (code, X86_CMP, X86_EAX, 0, 0);
+       labels [3] = code;
+       x86_branch8 (code, X86_CC_Z, FALSE, 0);
+       /* Jump to fail tramp */
+       x86_mov_membase_reg (code, X86_ESP, 4, X86_EAX, 4);
+       x86_pop_reg (code, X86_EAX);
+       x86_ret (code);
+
+       /* Fail */
+       mono_x86_patch (labels [3], code);
        x86_breakpoint (code);
 
 #ifdef __native_client_codegen__
@@ -1919,17 +1948,23 @@ encode_klass_ref_inner (MonoAotCompile *acfg, MonoClass *klass, guint8 *buf, gui
                }
        } else if ((klass->byval_arg.type == MONO_TYPE_VAR) || (klass->byval_arg.type == MONO_TYPE_MVAR)) {
                MonoGenericContainer *container = mono_type_get_generic_param_owner (&klass->byval_arg);
-               g_assert (container);
+               MonoGenericParam *par = klass->byval_arg.data.generic_param;
 
                encode_value (MONO_AOT_TYPEREF_VAR, p, &p);
                encode_value (klass->byval_arg.type, p, &p);
                encode_value (mono_type_get_generic_param_num (&klass->byval_arg), p, &p);
-               
-               encode_value (container->is_method, p, &p);
-               if (container->is_method)
-                       encode_method_ref (acfg, container->owner.method, p, &p);
-               else
-                       encode_klass_ref (acfg, container->owner.klass, p, &p);
+
+               encode_value (container ? 1 : 0, p, &p);
+               if (container) {
+                       encode_value (container->is_method, p, &p);
+                       g_assert (par->serial == 0);
+                       if (container->is_method)
+                               encode_method_ref (acfg, container->owner.method, p, &p);
+                       else
+                               encode_klass_ref (acfg, container->owner.klass, p, &p);
+               } else {
+                       encode_value (par->serial, p, &p);
+               }
        } else if (klass->byval_arg.type == MONO_TYPE_PTR) {
                encode_value (MONO_AOT_TYPEREF_PTR, p, &p);
                encode_type (acfg, &klass->byval_arg, p, &p);
@@ -2241,6 +2276,8 @@ encode_method_ref (MonoAotCompile *acfg, MonoMethod *method, guint8 *buf, guint8
                        if (info->subtype == WRAPPER_SUBTYPE_PTR_TO_STRUCTURE ||
                                info->subtype == WRAPPER_SUBTYPE_STRUCTURE_TO_PTR)
                                encode_klass_ref (acfg, method->klass, p, &p);
+                       else if (info->subtype == WRAPPER_SUBTYPE_SYNCHRONIZED_INNER)
+                               encode_method_ref (acfg, info->d.synchronized_inner.method, p, &p);
                        break;
                }
                case MONO_WRAPPER_MANAGED_TO_NATIVE: {
@@ -2251,6 +2288,8 @@ encode_method_ref (MonoAotCompile *acfg, MonoMethod *method, guint8 *buf, guint8
                        if (info->subtype == WRAPPER_SUBTYPE_ICALL_WRAPPER) {
                                strcpy ((char*)p, method->name);
                                p += strlen (method->name) + 1;
+                       } else if (info->subtype == WRAPPER_SUBTYPE_NATIVE_FUNC_AOT) {
+                               encode_method_ref (acfg, info->d.managed_to_native.method, p, &p);
                        } else {
                                g_assert (info->subtype == WRAPPER_SUBTYPE_NONE);
                                encode_method_ref (acfg, info->d.managed_to_native.method, p, &p);
@@ -2475,7 +2514,7 @@ is_plt_patch (MonoJumpInfo *patch_info)
 static char*
 get_plt_symbol (MonoAotCompile *acfg, int plt_offset, MonoJumpInfo *patch_info)
 {
-#ifdef __APPLE__
+#ifdef TARGET_MACH
        /* 
         * The Apple linker reorganizes object files, so it doesn't like branches to local
         * labels, since those have no relocations.
@@ -2711,7 +2750,7 @@ can_marshal_struct (MonoClass *klass)
 
        /* Special cases */
        /* Its hard to compute whenever these can be marshalled or not */
-       if (!strcmp (klass->name_space, "System.Net.NetworkInformation.MacOsStructs"))
+       if (!strcmp (klass->name_space, "System.Net.NetworkInformation.MacOsStructs") && strcmp (klass->name, "sockaddr_dl"))
                return TRUE;
 
        return can_marshal;
@@ -2922,7 +2961,8 @@ add_wrappers (MonoAotCompile *acfg)
                        mono_method_desc_free (desc);
                        if (m) {
                                m = mono_monitor_get_fast_path (m);
-                               add_method (acfg, m);
+                               if (m)
+                                       add_method (acfg, m);
                        }
                }
 #endif
@@ -2954,6 +2994,7 @@ add_wrappers (MonoAotCompile *acfg)
        /* delegate-invoke wrappers */
        for (i = 0; i < acfg->image->tables [MONO_TABLE_TYPEDEF].rows; ++i) {
                MonoClass *klass;
+               MonoCustomAttrInfo *cattr;
                
                token = MONO_TOKEN_TYPE_DEF | (i + 1);
                klass = mono_class_get (acfg->image, token);
@@ -2977,6 +3018,18 @@ add_wrappers (MonoAotCompile *acfg)
                        method = mono_class_get_method_from_name_flags (klass, "EndInvoke", -1, 0);
                        if (method)
                                add_method (acfg, mono_marshal_get_delegate_end_invoke (method));
+
+                       cattr = mono_custom_attrs_from_class (klass);
+
+                       if (cattr) {
+                               int j;
+
+                               for (j = 0; j < cattr->num_attrs; ++j)
+                                       if (cattr->attrs [j].ctor && (!strcmp (cattr->attrs [j].ctor->klass->name, "MonoNativeFunctionWrapperAttribute") || !strcmp (cattr->attrs [j].ctor->klass->name, "UnmanagedFunctionPointerAttribute")))
+                                               break;
+                               if (j < cattr->num_attrs)
+                                       add_method (acfg, mono_marshal_get_native_func_wrapper_aot (klass));
+                       }
                }
        }
 
@@ -3221,6 +3274,7 @@ static void
 add_generic_class_with_depth (MonoAotCompile *acfg, MonoClass *klass, int depth, const char *ref)
 {
        MonoMethod *method;
+       MonoClassField *field;
        gpointer iter;
 
        if (!acfg->ginst_hash)
@@ -3268,6 +3322,12 @@ add_generic_class_with_depth (MonoAotCompile *acfg, MonoClass *klass, int depth,
                add_extra_method_with_depth (acfg, method, depth + 1);
        }
 
+       iter = NULL;
+       while ((field = mono_class_get_fields (klass, &iter))) {
+               if (field->type->type == MONO_TYPE_GENERICINST)
+                       add_generic_class_with_depth (acfg, mono_class_from_mono_type (field->type), depth + 1, "field");
+       }
+
        if (klass->delegate) {
                method = mono_get_delegate_invoke (klass);
 
@@ -3384,6 +3444,32 @@ add_instances_of (MonoAotCompile *acfg, MonoClass *klass, MonoType **insts, int
        }
 }
 
+static void
+add_types_from_method_header (MonoAotCompile *acfg, MonoMethod *method)
+{
+       MonoMethodHeader *header;
+       MonoMethodSignature *sig;
+       int j, depth;
+
+       depth = GPOINTER_TO_UINT (g_hash_table_lookup (acfg->method_depth, method));
+
+       sig = mono_method_signature (method);
+
+       if (sig) {
+               for (j = 0; j < sig->param_count; ++j)
+                       if (sig->params [j]->type == MONO_TYPE_GENERICINST)
+                               add_generic_class_with_depth (acfg, mono_class_from_mono_type (sig->params [j]), depth + 1, "arg");
+       }
+
+       header = mono_method_get_header (method);
+
+       if (header) {
+               for (j = 0; j < header->num_locals; ++j)
+                       if (header->locals [j]->type == MONO_TYPE_GENERICINST)
+                               add_generic_class_with_depth (acfg, mono_class_from_mono_type (header->locals [j]), depth + 1, "local");
+       }
+}
+
 /*
  * add_generic_instances:
  *
@@ -3395,8 +3481,6 @@ add_generic_instances (MonoAotCompile *acfg)
        int i;
        guint32 token;
        MonoMethod *method;
-       MonoMethodHeader *header;
-       MonoMethodSignature *sig;
        MonoGenericContext *context;
 
        for (i = 0; i < acfg->image->tables [MONO_TABLE_METHODSPEC].rows; ++i) {
@@ -3517,27 +3601,8 @@ add_generic_instances (MonoAotCompile *acfg)
 
        /* Add types of args/locals */
        for (i = 0; i < acfg->methods->len; ++i) {
-               int j, depth;
-
                method = g_ptr_array_index (acfg->methods, i);
-
-               depth = GPOINTER_TO_UINT (g_hash_table_lookup (acfg->method_depth, method));
-
-               sig = mono_method_signature (method);
-
-               if (sig) {
-                       for (j = 0; j < sig->param_count; ++j)
-                               if (sig->params [j]->type == MONO_TYPE_GENERICINST)
-                                       add_generic_class_with_depth (acfg, mono_class_from_mono_type (sig->params [j]), depth + 1, "arg");
-               }
-
-               header = mono_method_get_header (method);
-
-               if (header) {
-                       for (j = 0; j < header->num_locals; ++j)
-                               if (header->locals [j]->type == MONO_TYPE_GENERICINST)
-                                       add_generic_class_with_depth (acfg, mono_class_from_mono_type (header->locals [j]), depth + 1, "local");
-               }
+               add_types_from_method_header (acfg, method);
        }
 
        if (acfg->image == mono_defaults.corlib) {
@@ -3652,6 +3717,10 @@ is_direct_callable (MonoAotCompile *acfg, MonoMethod *method, MonoJumpInfo *patc
        } else if ((patch_info->type == MONO_PATCH_INFO_ICALL_ADDR && patch_info->data.method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL)) {
                if (acfg->aot_opts.direct_pinvoke)
                        return TRUE;
+       } else if (patch_info->type == MONO_PATCH_INFO_ICALL_ADDR) {
+               if (acfg->aot_opts.direct_icalls)
+                       return TRUE;
+               return FALSE;
        }
 
        return FALSE;
@@ -3667,7 +3736,6 @@ get_pinvoke_import (MonoAotCompile *acfg, MonoMethod *method)
        MonoTableInfo *mr = &tables [MONO_TABLE_MODULEREF];
        guint32 im_cols [MONO_IMPLMAP_SIZE];
        char *import;
-       const char *prefix;
 
        import = g_hash_table_lookup (acfg->method_to_pinvoke_import, method);
        if (import != NULL)
@@ -3681,13 +3749,7 @@ get_pinvoke_import (MonoAotCompile *acfg, MonoMethod *method)
        if (!im_cols [MONO_IMPLMAP_SCOPE] || im_cols [MONO_IMPLMAP_SCOPE] > mr->rows)
                return NULL;
 
-#if defined(__APPLE__)
-       prefix = "_";
-#else
-       prefix = "";
-#endif
-
-       import = g_strdup_printf ("%s%s", prefix, mono_metadata_string_heap (image, im_cols [MONO_IMPLMAP_NAME]));
+       import = g_strdup_printf ("%s", mono_metadata_string_heap (image, im_cols [MONO_IMPLMAP_NAME]));
 
        g_hash_table_insert (acfg->method_to_pinvoke_import, method, import);
        
@@ -3766,22 +3828,34 @@ emit_and_reloc_code (MonoAotCompile *acfg, MonoMethod *method, guint8 *code, gui
                                                direct_call = TRUE;
                                                g_assert (strlen (callee_cfg->asm_symbol) < 1000);
                                                sprintf (direct_call_target, "%s", callee_cfg->asm_symbol);
-                                               patch_info->type = MONO_PATCH_INFO_NONE;
-                                               acfg->stats.direct_calls ++;
                                        }
 
                                        acfg->stats.all_calls ++;
-                               } else if ((patch_info->type == MONO_PATCH_INFO_ICALL_ADDR) && (patch_info->data.method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL)) {
+                               } else if (patch_info->type == MONO_PATCH_INFO_ICALL_ADDR) {
                                        if (!got_only && is_direct_callable (acfg, method, patch_info)) {
-                                               direct_call = TRUE;
-                                               direct_pinvoke = get_pinvoke_import (acfg, patch_info->data.method);
-                                               g_assert (strlen (direct_pinvoke) < 1000);
-                                               sprintf (direct_call_target, "%s", direct_pinvoke);
-                                               patch_info->type = MONO_PATCH_INFO_NONE;
-                                               acfg->stats.direct_calls ++;
+                                               if (!(patch_info->data.method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
+                                                       direct_pinvoke = mono_lookup_icall_symbol (patch_info->data.method);
+                                               else
+                                                       direct_pinvoke = get_pinvoke_import (acfg, patch_info->data.method);
+                                               if (direct_pinvoke) {
+                                                       const char*prefix;
+#if defined(TARGET_MACH)
+                                                       prefix = "_";
+#else
+                                                       prefix = "";
+#endif
+                                                       direct_call = TRUE;
+                                                       g_assert (strlen (direct_pinvoke) < 1000);
+                                                       sprintf (direct_call_target, "%s%s", prefix, direct_pinvoke);
+                                               }
                                        }
                                }
 
+                               if (direct_call) {
+                                       patch_info->type = MONO_PATCH_INFO_NONE;
+                                       acfg->stats.direct_calls ++;
+                               }
+
                                if (!got_only && !direct_call) {
                                        MonoPltEntry *plt_entry = get_plt_entry (acfg, patch_info);
                                        if (plt_entry) {
@@ -4658,18 +4732,20 @@ emit_plt (MonoAotCompile *acfg)
                        if (ji && is_direct_callable (acfg, NULL, ji) && !acfg->use_bin_writer) {
                                MonoCompile *callee_cfg = g_hash_table_lookup (acfg->method_to_cfg, ji->data.method);
 
-                               if (acfg->thumb_mixed && !callee_cfg->compile_llvm) {
-                                       /* LLVM calls the PLT entries using bl, so emit a stub */
-                                       fprintf (acfg->fp, "\n.thumb_func\n");
-                                       emit_label (acfg, plt_entry->llvm_symbol);
-                                       fprintf (acfg->fp, "bx pc\n");
-                                       fprintf (acfg->fp, "nop\n");
-                                       fprintf (acfg->fp, ".arm\n");
-                                       fprintf (acfg->fp, "b %s\n", callee_cfg->asm_symbol);
-                               } else {
-                                       fprintf (acfg->fp, "\n.set %s, %s\n", plt_entry->llvm_symbol, callee_cfg->asm_symbol);
+                               if (callee_cfg) {
+                                       if (acfg->thumb_mixed && !callee_cfg->compile_llvm) {
+                                               /* LLVM calls the PLT entries using bl, so emit a stub */
+                                               fprintf (acfg->fp, "\n.thumb_func\n");
+                                               emit_label (acfg, plt_entry->llvm_symbol);
+                                               fprintf (acfg->fp, "bx pc\n");
+                                               fprintf (acfg->fp, "nop\n");
+                                               fprintf (acfg->fp, ".arm\n");
+                                               fprintf (acfg->fp, "b %s\n", callee_cfg->asm_symbol);
+                                       } else {
+                                               fprintf (acfg->fp, "\n.set %s, %s\n", plt_entry->llvm_symbol, callee_cfg->asm_symbol);
+                                       }
+                                       continue;
                                }
-                               continue;
                        }
                }
 
@@ -4729,7 +4805,7 @@ emit_plt (MonoAotCompile *acfg)
                        }
 
                        if (debug_sym) {
-#if defined(__APPLE__)
+#if defined(TARGET_MACH)
                                fprintf (acfg->fp, "    .thumb_func %s\n", debug_sym);
                                fprintf (acfg->fp, "    .no_dead_strip %s\n", debug_sym);
 #endif
@@ -5168,6 +5244,12 @@ mono_aot_parse_options (const char *aot_options, MonoAotOptions *opts)
                        opts->soft_debug = TRUE;
                } else if (str_begins_with (arg, "direct-pinvoke")) {
                        opts->direct_pinvoke = TRUE;
+               } else if (str_begins_with (arg, "direct-icalls")) {
+                       opts->direct_icalls = TRUE;
+#if defined(TARGET_ARM)
+               } else if (str_begins_with (arg, "iphone-abi")) {
+                       // older full-aot users did depend on this.
+#endif
                } else if (str_begins_with (arg, "print-skipped")) {
                        opts->print_skipped_methods = TRUE;
                } else if (str_begins_with (arg, "stats")) {
@@ -5183,6 +5265,8 @@ mono_aot_parse_options (const char *aot_options, MonoAotOptions *opts)
                } else if (str_begins_with (arg, "info")) {
                        printf ("AOT target setup: %s.\n", AOT_TARGET_STR);
                        exit (0);
+               } else if (str_begins_with (arg, "gc-maps")) {
+                       mini_gc_enable_gc_maps_for_aot ();
                } else if (str_begins_with (arg, "help") || str_begins_with (arg, "?")) {
                        printf ("Supported options for --aot:\n");
                        printf ("    outfile=\n");
@@ -5204,6 +5288,7 @@ mono_aot_parse_options (const char *aot_options, MonoAotOptions *opts)
                        printf ("    tool-prefix=\n");
                        printf ("    readonly-value=\n");
                        printf ("    soft-debug\n");
+                       printf ("    gc-maps\n");
                        printf ("    print-skipped\n");
                        printf ("    stats\n");
                        printf ("    info\n");
@@ -5480,6 +5565,7 @@ compile_method (MonoAotCompile *acfg, MonoMethod *method)
                                                                add_extra_method_with_depth (acfg, mono_marshal_get_native_wrapper (m, TRUE, TRUE), depth + 1);
                                                } else {
                                                        add_extra_method_with_depth (acfg, m, depth + 1);
+                                                       add_types_from_method_header (acfg, m);
                                                }
                                        }
                                        add_generic_class_with_depth (acfg, m->klass, depth + 5, "method");
@@ -5760,7 +5846,7 @@ mono_aot_get_plt_symbol (MonoJumpInfoType type, gconstpointer data)
        plt_entry = get_plt_entry (llvm_acfg, ji);
        plt_entry->llvm_used = TRUE;
 
-#if defined(__APPLE__)
+#if defined(TARGET_MACH)
        return g_strdup_printf (plt_entry->llvm_symbol + strlen (llvm_acfg->llvm_label_prefix));
 #else
        return g_strdup_printf (plt_entry->llvm_symbol);
@@ -5790,7 +5876,7 @@ mono_aot_patch_info_dup (MonoJumpInfo* ji)
 static void
 emit_llvm_file (MonoAotCompile *acfg)
 {
-       char *command, *opts;
+       char *command, *opts, *tempbc;
        int i;
        MonoJumpInfo *patch_info;
 
@@ -5832,7 +5918,9 @@ emit_llvm_file (MonoAotCompile *acfg)
        }
 
 
-       mono_llvm_emit_aot_module ("temp.bc", acfg->final_got_size);
+       tempbc = g_strdup_printf ("%s.bc", acfg->tmpfname);
+       mono_llvm_emit_aot_module (tempbc, acfg->final_got_size);
+       g_free (tempbc);
 
        /*
         * FIXME: Experiment with adding optimizations, the -std-compile-opts set takes
@@ -5851,7 +5939,7 @@ emit_llvm_file (MonoAotCompile *acfg)
        opts = g_strdup ("-instcombine -simplifycfg");
        opts = g_strdup ("-simplifycfg -domtree -domfrontier -scalarrepl -instcombine -simplifycfg -domtree -domfrontier -scalarrepl -simplify-libcalls -instcombine -simplifycfg -instcombine -simplifycfg -reassociate -domtree -loops -loop-simplify -domfrontier -loop-simplify -lcssa -loop-rotate -licm -lcssa -loop-unswitch -instcombine -scalar-evolution -loop-simplify -lcssa -iv-users -indvars -loop-deletion -loop-simplify -lcssa -loop-unroll -instcombine -memdep -gvn -memdep -memcpyopt -sccp -instcombine -domtree -memdep -dse -adce -simplifycfg -preverify -domtree -verify");
 #if 1
-       command = g_strdup_printf ("%sopt -f %s -o temp.opt.bc temp.bc", acfg->aot_opts.llvm_path, opts);
+       command = g_strdup_printf ("%sopt -f %s -o %s.opt.bc %s.bc", acfg->aot_opts.llvm_path, opts, acfg->tmpfname, acfg->tmpfname);
        printf ("Executing opt: %s\n", command);
        if (system (command) != 0) {
                exit (1);
@@ -5874,7 +5962,7 @@ emit_llvm_file (MonoAotCompile *acfg)
                g_string_append_printf (acfg->llc_args, " -relocation-model=pic");
        unlink (acfg->tmpfname);
 
-       command = g_strdup_printf ("%sllc %s -disable-gnu-eh-frame -enable-mono-eh-frame -o %s temp.opt.bc", acfg->aot_opts.llvm_path, acfg->llc_args->str, acfg->tmpfname);
+       command = g_strdup_printf ("%sllc %s -disable-gnu-eh-frame -enable-mono-eh-frame -o %s %s.opt.bc", acfg->aot_opts.llvm_path, acfg->llc_args->str, acfg->tmpfname, acfg->tmpfname);
 
        printf ("Executing llc: %s\n", command);
 
@@ -6789,7 +6877,7 @@ emit_globals (MonoAotCompile *acfg)
 
                sprintf (symbol, "name_%d", i);
                emit_section_change (acfg, RODATA_SECT, 1);
-#ifdef __APPLE__
+#ifdef TARGET_MACH
                emit_alignment (acfg, 4);
 #endif
                emit_label (acfg, symbol);
@@ -6955,6 +7043,7 @@ emit_file_info (MonoAotCompile *acfg)
        emit_int32 (acfg, acfg->nmethods);
        emit_int32 (acfg, acfg->flags);
        emit_int32 (acfg, acfg->opts);
+       emit_int32 (acfg, acfg->simd_opts);
        emit_int32 (acfg, gc_name_offset);
 
        for (i = 0; i < MONO_AOT_TRAMP_NUM; ++i)
@@ -6964,7 +7053,7 @@ emit_file_info (MonoAotCompile *acfg)
        for (i = 0; i < MONO_AOT_TRAMP_NUM; ++i)
                emit_int32 (acfg, acfg->trampoline_size [i]);
 
-#if defined (TARGET_ARM) && defined (__APPLE__)
+#if defined (TARGET_ARM) && defined (TARGET_MACH)
        {
                MonoType t;
                int align = 0;
@@ -6992,7 +7081,7 @@ emit_file_info (MonoAotCompile *acfg)
                 * mono_aot_register_module (). The symbol points to a pointer to the the file info
                 * structure.
                 */
-#if defined(__APPLE__) && !defined(__native_client_codegen__)
+#if defined(TARGET_MACH) && !defined(__native_client_codegen__)
                sprintf (symbol, "_mono_aot_module_%s_info", acfg->image->assembly->aname.name);
 #else
                sprintf (symbol, "mono_aot_module_%s_info", acfg->image->assembly->aname.name);
@@ -7179,7 +7268,7 @@ compile_asm (MonoAotCompile *acfg)
 #define LD_OPTIONS "-m elf64ppc"
 #elif defined(sparc) && SIZEOF_VOID_P == 8
 #define AS_OPTIONS "-xarch=v9"
-#elif defined(TARGET_X86) && defined(__APPLE__) && !defined(__native_client_codegen__)
+#elif defined(TARGET_X86) && defined(TARGET_MACH) && !defined(__native_client_codegen__)
 #define AS_OPTIONS "-arch i386 -W"
 #else
 #define AS_OPTIONS ""
@@ -7242,11 +7331,11 @@ compile_asm (MonoAotCompile *acfg)
 
 #if defined(sparc)
        command = g_strdup_printf ("ld -shared -G -o %s %s.o", tmp_outfile_name, acfg->tmpfname);
-#elif defined(__ppc__) && defined(__APPLE__)
+#elif defined(__ppc__) && defined(TARGET_MACH)
        command = g_strdup_printf ("gcc -dynamiclib -o %s %s.o", tmp_outfile_name, acfg->tmpfname);
 #elif defined(HOST_WIN32)
        command = g_strdup_printf ("gcc -shared --dll -mno-cygwin -o %s %s.o", tmp_outfile_name, acfg->tmpfname);
-#elif defined(TARGET_X86) && defined(__APPLE__) && !defined(__native_client_codegen__)
+#elif defined(TARGET_X86) && defined(TARGET_MACH) && !defined(__native_client_codegen__)
        command = g_strdup_printf ("gcc -m32 -dynamiclib -o %s %s.o", tmp_outfile_name, acfg->tmpfname);
 #else
        command = g_strdup_printf ("%sld %s %s -shared -o %s %s.o", tool_prefix, EH_LD_OPTIONS, LD_OPTIONS, tmp_outfile_name, acfg->tmpfname);
@@ -7261,13 +7350,13 @@ compile_asm (MonoAotCompile *acfg)
        }
 
        g_free (command);
-       unlink (objfile);
+
        /*com = g_strdup_printf ("strip --strip-unneeded %s%s", acfg->image->name, SHARED_EXT);
        printf ("Stripping the binary: %s\n", com);
        system (com);
        g_free (com);*/
 
-#if defined(TARGET_ARM) && !defined(__APPLE__)
+#if defined(TARGET_ARM) && !defined(TARGET_MACH)
        /* 
         * gas generates 'mapping symbols' each time code and data is mixed, which 
         * happens a lot in emit_and_reloc_code (), so we need to get rid of them.
@@ -7285,6 +7374,17 @@ compile_asm (MonoAotCompile *acfg)
 
        rename (tmp_outfile_name, outfile_name);
 
+#if defined(TARGET_MACH)
+       command = g_strdup_printf ("dsymutil %s", outfile_name);
+       printf ("Generating debug symbols: %s\n", command);
+       if (system (command) != 0) {
+               return 1;
+       }
+#endif
+
+       if (!acfg->aot_opts.save_temps)
+               unlink (objfile);
+
        g_free (tmp_outfile_name);
        g_free (outfile_name);
        g_free (objfile);
@@ -7323,6 +7423,8 @@ acfg_create (MonoAssembly *ass, guint32 opts)
        acfg->globals = g_ptr_array_new ();
        acfg->image = image;
        acfg->opts = opts;
+       /* TODO: Write out set of SIMD instructions used, rather than just those available */
+       acfg->simd_opts = mono_arch_cpu_enumerate_simd_versions ();
        acfg->mempool = mono_mempool_new ();
        acfg->extra_methods = g_ptr_array_new ();
        acfg->unwind_info_offsets = g_hash_table_new (NULL, NULL);
@@ -7619,6 +7721,7 @@ mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options)
                 */
                sprintf (symbol, "thumb_end");
                emit_section_change (acfg, ".text", 0);
+               emit_alignment (acfg, 8);
                emit_label (acfg, symbol);
                emit_zero_bytes (acfg, 16);
 
@@ -7679,6 +7782,20 @@ mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options)
                g_assert (acfg->got_offset <= acfg->final_got_size);
 
        printf ("Code: %d Info: %d Ex Info: %d Unwind Info: %d Class Info: %d PLT: %d GOT Info: %d GOT: %d Offsets: %d\n", acfg->stats.code_size, acfg->stats.info_size, acfg->stats.ex_info_size, acfg->stats.unwind_info_size, acfg->stats.class_info_size, acfg->plt_offset, acfg->stats.got_info_size, (int)(acfg->got_offset * sizeof (gpointer)), acfg->stats.offsets_size);
+       printf ("Compiled: %d/%d (%d%%), No GOT slots: %d (%d%%), Direct calls: %d (%d%%)\n", 
+                       acfg->stats.ccount, acfg->stats.mcount, acfg->stats.mcount ? (acfg->stats.ccount * 100) / acfg->stats.mcount : 100,
+                       acfg->stats.methods_without_got_slots, acfg->stats.mcount ? (acfg->stats.methods_without_got_slots * 100) / acfg->stats.mcount : 100,
+                       acfg->stats.direct_calls, acfg->stats.all_calls ? (acfg->stats.direct_calls * 100) / acfg->stats.all_calls : 100);
+       if (acfg->stats.genericcount)
+               printf ("%d methods are generic (%d%%)\n", acfg->stats.genericcount, acfg->stats.mcount ? (acfg->stats.genericcount * 100) / acfg->stats.mcount : 100);
+       if (acfg->stats.abscount)
+               printf ("%d methods contain absolute addresses (%d%%)\n", acfg->stats.abscount, acfg->stats.mcount ? (acfg->stats.abscount * 100) / acfg->stats.mcount : 100);
+       if (acfg->stats.lmfcount)
+               printf ("%d methods contain lmf pointers (%d%%)\n", acfg->stats.lmfcount, acfg->stats.mcount ? (acfg->stats.lmfcount * 100) / acfg->stats.mcount : 100);
+       if (acfg->stats.ocount)
+               printf ("%d methods have other problems (%d%%)\n", acfg->stats.ocount, acfg->stats.mcount ? (acfg->stats.ocount * 100) / acfg->stats.mcount : 100);
+       if (acfg->llvm)
+               printf ("Methods compiled with LLVM: %d (%d%%)\n", acfg->stats.llvm_count, acfg->stats.mcount ? (acfg->stats.llvm_count * 100) / acfg->stats.mcount : 100);
 
        TV_GETTIME (atv);
        res = img_writer_emit_writeout (acfg->w);
@@ -7703,20 +7820,6 @@ mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options)
        TV_GETTIME (btv);
        acfg->stats.link_time = TV_ELAPSED (atv, btv);
 
-       printf ("Compiled %d out of %d methods (%d%%)\n", acfg->stats.ccount, acfg->stats.mcount, acfg->stats.mcount ? (acfg->stats.ccount * 100) / acfg->stats.mcount : 100);
-       if (acfg->stats.genericcount)
-               printf ("%d methods are generic (%d%%)\n", acfg->stats.genericcount, acfg->stats.mcount ? (acfg->stats.genericcount * 100) / acfg->stats.mcount : 100);
-       if (acfg->stats.abscount)
-               printf ("%d methods contain absolute addresses (%d%%)\n", acfg->stats.abscount, acfg->stats.mcount ? (acfg->stats.abscount * 100) / acfg->stats.mcount : 100);
-       if (acfg->stats.lmfcount)
-               printf ("%d methods contain lmf pointers (%d%%)\n", acfg->stats.lmfcount, acfg->stats.mcount ? (acfg->stats.lmfcount * 100) / acfg->stats.mcount : 100);
-       if (acfg->stats.ocount)
-               printf ("%d methods have other problems (%d%%)\n", acfg->stats.ocount, acfg->stats.mcount ? (acfg->stats.ocount * 100) / acfg->stats.mcount : 100);
-       if (acfg->llvm)
-               printf ("Methods compiled with LLVM: %d (%d%%)\n", acfg->stats.llvm_count, acfg->stats.mcount ? (acfg->stats.llvm_count * 100) / acfg->stats.mcount : 100);
-       printf ("Methods without GOT slots: %d (%d%%)\n", acfg->stats.methods_without_got_slots, acfg->stats.mcount ? (acfg->stats.methods_without_got_slots * 100) / acfg->stats.mcount : 100);
-       printf ("Direct calls: %d (%d%%)\n", acfg->stats.direct_calls, acfg->stats.all_calls ? (acfg->stats.direct_calls * 100) / acfg->stats.all_calls : 100);
-
        if (acfg->aot_opts.stats) {
                int i;