Revert "Merge branch 'master' of https://github.com/mono/mono"
[mono.git] / mono / mini / aot-compiler.c
old mode 100755 (executable)
new mode 100644 (file)
index fa91e5c..c28ec1d
@@ -128,6 +128,7 @@ typedef struct MonoAotOptions {
        gboolean dwarf_debug;
        gboolean soft_debug;
        gboolean log_generics;
+       gboolean log_instances;
        gboolean direct_pinvoke;
        gboolean direct_icalls;
        gboolean no_direct_calls;
@@ -146,11 +147,12 @@ typedef struct MonoAotOptions {
        gboolean autoreg;
        char *mtriple;
        char *llvm_path;
+       char *instances_logfile_path;
 } MonoAotOptions;
 
 typedef struct MonoAotStats {
        int ccount, mcount, lmfcount, abscount, gcount, ocount, genericcount;
-       int code_size, info_size, ex_info_size, unwind_info_size, got_size, class_info_size, got_info_size;
+       int code_size, info_size, ex_info_size, unwind_info_size, got_size, class_info_size, got_info_size, plt_size;
        int methods_without_got_slots, direct_calls, all_calls, llvm_count;
        int got_slots, offsets_size;
        int got_slot_types [MONO_PATCH_INFO_NONE];
@@ -240,6 +242,7 @@ typedef struct MonoAotCompile {
        int objc_selector_index, objc_selector_index_2;
        GPtrArray *objc_selectors;
        GHashTable *objc_selector_to_index;
+       FILE *instances_logfile;
 } MonoAotCompile;
 
 typedef struct {
@@ -558,6 +561,12 @@ emit_set_arm_mode (MonoAotCompile *acfg)
        fprintf (acfg->fp, ".code 32\n");
 }
 
+static inline void
+emit_code_bytes (MonoAotCompile *acfg, const guint8* buf, int size)
+{
+       emit_bytes (acfg, buf, size);
+}
+
 /* ARCHITECTURE SPECIFIC CODE */
 
 #if defined(TARGET_X86) || defined(TARGET_AMD64) || defined(TARGET_ARM) || defined(TARGET_POWERPC)
@@ -678,6 +687,7 @@ arch_init (MonoAotCompile *acfg)
 #endif
 }
 
+#ifdef MONO_ARCH_AOT_SUPPORTED
 /*
  * arch_emit_direct_call:
  *
@@ -685,7 +695,7 @@ arch_init (MonoAotCompile *acfg)
  * calling code.
  */
 static void
-arch_emit_direct_call (MonoAotCompile *acfg, const char *target, gboolean external, MonoJumpInfo *ji, int *call_size)
+arch_emit_direct_call (MonoAotCompile *acfg, const char *target, gboolean external, gboolean thumb, MonoJumpInfo *ji, int *call_size)
 {
 #if defined(TARGET_X86) || defined(TARGET_AMD64)
        /* Need to make sure this is exactly 5 bytes long */
@@ -709,7 +719,10 @@ arch_emit_direct_call (MonoAotCompile *acfg, const char *target, gboolean extern
                emit_bytes (acfg, buf, 4);
        } else {
                emit_unset_mode (acfg);
-               fprintf (acfg->fp, "bl %s\n", target);
+               if (thumb)
+                       fprintf (acfg->fp, "blx %s\n", target);
+               else
+                       fprintf (acfg->fp, "bl %s\n", target);
        }
        *call_size = 4;
 #elif defined(TARGET_POWERPC)
@@ -724,6 +737,7 @@ arch_emit_direct_call (MonoAotCompile *acfg, const char *target, gboolean extern
        g_assert_not_reached ();
 #endif
 }
+#endif
 
 /*
  * PPC32 design:
@@ -840,6 +854,7 @@ arch_emit_got_access (MonoAotCompile *acfg, guint8 *code, int got_slot, int *cod
 
 #endif
 
+#ifdef MONO_ARCH_AOT_SUPPORTED
 /*
  * arch_emit_objc_selector_ref:
  *
@@ -868,6 +883,7 @@ arch_emit_objc_selector_ref (MonoAotCompile *acfg, guint8 *code, int index, int
        g_assert_not_reached ();
 #endif
 }
+#endif
 
 /*
  * arch_emit_plt_entry:
@@ -912,6 +928,7 @@ arch_emit_plt_entry (MonoAotCompile *acfg, int index)
                emit_symbol_diff (acfg, acfg->got_symbol, ".", ((acfg->plt_got_offset_base + index) * sizeof (gpointer)) -4);
                /* Used by mono_aot_get_plt_info_offset */
                emit_int32 (acfg, acfg->plt_got_info_offsets [index]);
+               acfg->stats.plt_size += 10;
 #elif defined(__native_client_codegen__)
                guint8 buf [256];
                guint8 *buf_aligned = ALIGN_TO(buf, kNaClAlignment);
@@ -2648,7 +2665,7 @@ encode_method_ref (MonoAotCompile *acfg, MonoMethod *method, guint8 *buf, guint8
                        } 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);
+                               g_assert (info->subtype == WRAPPER_SUBTYPE_NONE || info->subtype == WRAPPER_SUBTYPE_PINVOKE);
                                encode_method_ref (acfg, info->d.managed_to_native.method, p, &p);
                        }
                        break;
@@ -3217,12 +3234,6 @@ add_wrappers (MonoAotCompile *acfg)
         * so there is only one wrapper of a given type, or inlining their contents into their
         * callers.
         */
-
-       /* 
-        * FIXME: This depends on the fact that different wrappers have different 
-        * names.
-        */
-
        for (i = 0; i < acfg->image->tables [MONO_TABLE_METHOD].rows; ++i) {
                MonoMethod *method;
                guint32 token = MONO_TOKEN_METHOD_DEF | (i + 1);
@@ -3235,9 +3246,6 @@ add_wrappers (MonoAotCompile *acfg)
                        (method->flags & METHOD_ATTRIBUTE_ABSTRACT))
                        skip = TRUE;
 
-               if (method->is_generic || method->klass->generic_container)
-                       skip = TRUE;
-
                /* Skip methods which can not be handled by get_runtime_invoke () */
                sig = mono_method_signature (method);
                if (!sig)
@@ -3245,10 +3253,14 @@ add_wrappers (MonoAotCompile *acfg)
                if ((sig->ret->type == MONO_TYPE_PTR) ||
                        (sig->ret->type == MONO_TYPE_TYPEDBYREF))
                        skip = TRUE;
+               if (mono_class_is_open_constructed_type (sig->ret))
+                       skip = TRUE;
 
                for (j = 0; j < sig->param_count; j++) {
                        if (sig->params [j]->type == MONO_TYPE_TYPEDBYREF)
                                skip = TRUE;
+                       if (mono_class_is_open_constructed_type (sig->params [j]))
+                               skip = TRUE;
                }
 
 #ifdef MONO_ARCH_DYN_CALL_SUPPORTED
@@ -3408,7 +3420,7 @@ add_wrappers (MonoAotCompile *acfg)
 #endif
 
                /* JIT icall wrappers */
-               /* FIXME: locking */
+               /* FIXME: locking - this is "safe" as full-AOT threads don't mutate the icall hash*/
                g_hash_table_foreach (mono_get_jit_icall_info (), add_jit_icall_wrapper, acfg);
        }
 
@@ -3820,6 +3832,9 @@ check_type_depth (MonoType *t, int depth)
        return FALSE;
 }
 
+static void
+add_types_from_method_header (MonoAotCompile *acfg, MonoMethod *method);
+
 /*
  * add_generic_class:
  *
@@ -3868,7 +3883,8 @@ add_generic_class_with_depth (MonoAotCompile *acfg, MonoClass *klass, int depth,
         * Use gsharedvt for generic collections with vtype arguments to avoid code blowup.
         * Enable this only for some classes since gsharedvt might not support all methods.
         */
-       if ((acfg->opts & MONO_OPT_GSHAREDVT) && klass->image == mono_defaults.corlib && klass->generic_class && klass->generic_class->context.class_inst && is_vt_inst (klass->generic_class->context.class_inst) && (!strcmp (klass->name, "Dictionary`2") || !strcmp (klass->name, "List`1")))
+       if ((acfg->opts & MONO_OPT_GSHAREDVT) && klass->image == mono_defaults.corlib && klass->generic_class && klass->generic_class->context.class_inst && is_vt_inst (klass->generic_class->context.class_inst) &&
+               (!strcmp (klass->name, "Dictionary`2") || !strcmp (klass->name, "List`1") || !strcmp (klass->name, "ReadOnlyCollection`1")))
                use_gsharedvt = TRUE;
 
        iter = NULL;
@@ -3880,9 +3896,11 @@ add_generic_class_with_depth (MonoAotCompile *acfg, MonoClass *klass, int depth,
                        continue;
                }
                
-               if (mono_method_is_generic_sharable_full (method, FALSE, FALSE, use_gsharedvt))
+               if (mono_method_is_generic_sharable_full (method, FALSE, FALSE, use_gsharedvt)) {
                        /* Already added */
+                       add_types_from_method_header (acfg, method);
                        continue;
+               }
 
                if (method->is_generic)
                        /* FIXME: */
@@ -4331,6 +4349,7 @@ is_direct_callable (MonoAotCompile *acfg, MonoMethod *method, MonoJumpInfo *patc
        return FALSE;
 }
 
+#ifdef MONO_ARCH_AOT_SUPPORTED
 static const char *
 get_pinvoke_import (MonoAotCompile *acfg, MonoMethod *method)
 {
@@ -4360,6 +4379,7 @@ get_pinvoke_import (MonoAotCompile *acfg, MonoMethod *method)
        
        return import;
 }
+#endif
 
 static gint
 compare_lne (MonoDebugLineNumberEntry *a, MonoDebugLineNumberEntry *b)
@@ -4474,6 +4494,8 @@ get_file_index (MonoAotCompile *acfg, const char *source_file)
        return findex;
 }
 
+#define INST_LEN 1
+
 /*
  * emit_and_reloc_code:
  *
@@ -4490,10 +4512,13 @@ emit_and_reloc_code (MonoAotCompile *acfg, MonoMethod *method, guint8 *code, gui
        MonoJumpInfo *patch_info;
        MonoMethodHeader *header;
        MonoDebugSourceLocation **locs = NULL;
-       gboolean skip, direct_call, external_call;
+       gboolean skip;
+#ifdef MONO_ARCH_AOT_SUPPORTED
+       gboolean direct_call, external_call;
        guint32 got_slot;
        const char *direct_call_target = 0;
        const char *direct_pinvoke;
+#endif
 
        if (method) {
                header = mono_method_get_header (method);
@@ -4517,7 +4542,7 @@ emit_and_reloc_code (MonoAotCompile *acfg, MonoMethod *method, guint8 *code, gui
        g_ptr_array_sort (patches, compare_patches);
 
        start_index = 0;
-       for (i = 0; i < code_len; i++) {
+       for (i = 0; i < code_len; i += INST_LEN) {
                patch_info = NULL;
                for (pindex = start_index; pindex < patches->len; ++pindex) {
                        patch_info = g_ptr_array_index (patches, pindex);
@@ -4547,7 +4572,7 @@ emit_and_reloc_code (MonoAotCompile *acfg, MonoMethod *method, guint8 *code, gui
                                int code_size;
  
                                arch_emit_got_offset (acfg, code + i, &code_size);
-                               i += code_size - 1;
+                               i += code_size - INST_LEN;
                                skip = TRUE;
                                patch_info->type = MONO_PATCH_INFO_NONE;
                                break;
@@ -4571,7 +4596,7 @@ emit_and_reloc_code (MonoAotCompile *acfg, MonoMethod *method, guint8 *code, gui
                                }
 
                                arch_emit_objc_selector_ref (acfg, code + i, index, &code_size);
-                               i += code_size - 1;
+                               i += code_size - INST_LEN;
                                skip = TRUE;
                                patch_info->type = MONO_PATCH_INFO_NONE;
                                break;
@@ -4649,15 +4674,15 @@ emit_and_reloc_code (MonoAotCompile *acfg, MonoMethod *method, guint8 *code, gui
                                if (direct_call) {
                                        int call_size;
 
-                                       arch_emit_direct_call (acfg, direct_call_target, external_call, patch_info, &call_size);
-                                       i += call_size - 1;
+                                       arch_emit_direct_call (acfg, direct_call_target, external_call, FALSE, patch_info, &call_size);
+                                       i += call_size - INST_LEN;
                                } else {
                                        int code_size;
 
                                        got_slot = get_got_offset (acfg, patch_info);
 
                                        arch_emit_got_access (acfg, code + i, got_slot, &code_size);
-                                       i += code_size - 1;
+                                       i += code_size - INST_LEN;
                                }
                                skip = TRUE;
                        }
@@ -4678,15 +4703,15 @@ emit_and_reloc_code (MonoAotCompile *acfg, MonoMethod *method, guint8 *code, gui
                        if (pindex < patches->len && patch_info->ip.i > i) {
                                int limit;
 
-                               for (limit = i + 1; limit < patch_info->ip.i; ++limit) {
+                               for (limit = i + INST_LEN; limit < patch_info->ip.i; limit += INST_LEN) {
                                        if (locs && locs [limit])
                                                break;
                                }
 
-                               emit_bytes (acfg, code + i, limit - i);
-                               i = limit - 1;
+                               emit_code_bytes (acfg, code + i, limit - i);
+                               i = limit - INST_LEN;
                        } else {
-                               emit_bytes (acfg, code + i, 1);
+                               emit_code_bytes (acfg, code + i, INST_LEN);
                        }
                }
        }
@@ -4697,16 +4722,51 @@ emit_and_reloc_code (MonoAotCompile *acfg, MonoMethod *method, guint8 *code, gui
 /*
  * sanitize_symbol:
  *
- *   Modify SYMBOL so it only includes characters permissible in symbols.
+ *   Return a modified version of S which only includes characters permissible in symbols.
  */
-static void
-sanitize_symbol (char *symbol)
+static char*
+sanitize_symbol (MonoAotCompile *acfg, char *s)
 {
-       int i, len = strlen (symbol);
+       gboolean process = FALSE;
+       int i, len;
+       GString *gs;
+       char *res;
 
+       if (!s)
+               return s;
+
+       len = strlen (s);
        for (i = 0; i < len; ++i)
-               if (!isalnum (symbol [i]) && (symbol [i] != '_'))
-                       symbol [i] = '_';
+               if (!(s [i] <= 0x7f && (isalnum (s [i]) || s [i] == '_')))
+                       process = TRUE;
+       if (!process)
+               return s;
+
+       gs = g_string_sized_new (len);
+       for (i = 0; i < len; ++i) {
+               guint8 c = s [i];
+               if (c <= 0x7f && (isalnum (c) || c == '_')) {
+                       g_string_append_c (gs, c);
+               } else if (c > 0x7f) {
+                       /* multi-byte utf8 */
+                       g_string_append_printf (gs, "_0x%x", c);
+                       i ++;
+                       c = s [i];
+                       while (c >> 6 == 0x2) {
+                               g_string_append_printf (gs, "%x", c);
+                               i ++;
+                               c = s [i];
+                       }
+                       g_string_append_printf (gs, "_");
+                       i --;
+               } else {
+                       g_string_append_c (gs, '_');
+               }
+       }
+
+       res = mono_mempool_strdup (acfg->mempool, gs->str);
+       g_string_free (gs, TRUE);
+       return res;
 }
 
 static char*
@@ -4863,6 +4923,7 @@ encode_patch (MonoAotCompile *acfg, MonoJumpInfo *patch_info, guint8 *buf, guint
        case MONO_PATCH_INFO_METHOD_JUMP:
        case MONO_PATCH_INFO_ICALL_ADDR:
        case MONO_PATCH_INFO_METHOD_RGCTX:
+       case MONO_PATCH_INFO_METHOD_CODE_SLOT:
                encode_method_ref (acfg, patch_info->data.method, p, &p);
                break;
        case MONO_PATCH_INFO_INTERNAL_METHOD:
@@ -4915,11 +4976,17 @@ 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_CLASS_INIT:
        case MONO_PATCH_INFO_DELEGATE_TRAMPOLINE:
-               encode_klass_ref (acfg, patch_info->data.klass, p, &p);
+               encode_klass_ref (acfg, patch_info->data.del_tramp->klass, p, &p);
+               if (patch_info->data.del_tramp->method) {
+                       encode_value (1, p, &p);
+                       encode_method_ref (acfg, patch_info->data.del_tramp->method, p, &p);
+               } else {
+                       encode_value (0, p, &p);
+               }
                break;
        case MONO_PATCH_INFO_FIELD:
        case MONO_PATCH_INFO_SFLDA:
@@ -4983,9 +5050,9 @@ encode_patch (MonoAotCompile *acfg, MonoJumpInfo *patch_info, guint8 *buf, guint
                int i;
 
                encode_method_ref (acfg, info->method, p, &p);
-               encode_value (info->entries->len, p, &p);
-               for (i = 0; i < info->entries->len; ++i) {
-                       MonoRuntimeGenericContextInfoTemplate *template = g_ptr_array_index (info->entries, i);
+               encode_value (info->num_entries, p, &p);
+               for (i = 0; i < info->num_entries; ++i) {
+                       MonoRuntimeGenericContextInfoTemplate *template = &info->entries [i];
 
                        encode_value (template->info_type, p, &p);
                        switch (mini_rgctx_info_type_to_patch_info_type (template->info_type)) {
@@ -5532,6 +5599,7 @@ static char*
 get_plt_entry_debug_sym (MonoAotCompile *acfg, MonoJumpInfo *ji, GHashTable *cache)
 {
        char *debug_sym = NULL;
+       char *s;
 
        switch (ji->type) {
        case MONO_PATCH_INFO_METHOD:
@@ -5541,8 +5609,9 @@ get_plt_entry_debug_sym (MonoAotCompile *acfg, MonoJumpInfo *ji, GHashTable *cac
                debug_sym = g_strdup_printf ("plt__jit_icall_%s", ji->data.name);
                break;
        case MONO_PATCH_INFO_CLASS_INIT:
-               debug_sym = g_strdup_printf ("plt__class_init_%s", mono_type_get_name (&ji->data.klass->byval_arg));
-               sanitize_symbol (debug_sym);
+               s = mono_type_get_name (&ji->data.klass->byval_arg);
+               debug_sym = g_strdup_printf ("plt__class_init_%s", s);
+               g_free (s);
                break;
        case MONO_PATCH_INFO_RGCTX_FETCH:
                debug_sym = g_strdup_printf ("plt__rgctx_fetch_%d", acfg->label_generator ++);
@@ -5564,7 +5633,7 @@ get_plt_entry_debug_sym (MonoAotCompile *acfg, MonoJumpInfo *ji, GHashTable *cac
                break;
        }
 
-       return debug_sym;
+       return sanitize_symbol (acfg, debug_sym);
 }
 
 /*
@@ -6219,6 +6288,11 @@ mono_aot_parse_options (const char *aot_options, MonoAotOptions *opts)
                        opts->no_instances = TRUE;
                } else if (str_begins_with (arg, "log-generics")) {
                        opts->log_generics = TRUE;
+               } else if (str_begins_with (arg, "log-instances=")) {
+                       opts->log_instances = TRUE;
+                       opts->instances_logfile_path = g_strdup (arg + strlen ("log-instances="));
+               } else if (str_begins_with (arg, "log-instances")) {
+                       opts->log_instances = TRUE;
                } else if (str_begins_with (arg, "mtriple=")) {
                        opts->mtriple = g_strdup (arg + strlen ("mtriple="));
                } else if (str_begins_with (arg, "llvm-path=")) {
@@ -6357,14 +6431,14 @@ can_encode_patch (MonoAotCompile *acfg, MonoJumpInfo *patch_info)
 {
        switch (patch_info->type) {
        case MONO_PATCH_INFO_METHOD:
-       case MONO_PATCH_INFO_METHODCONST: {
+       case MONO_PATCH_INFO_METHODCONST:
+       case MONO_PATCH_INFO_METHOD_CODE_SLOT: {
                MonoMethod *method = patch_info->data.method;
 
                return can_encode_method (acfg, method);
        }
        case MONO_PATCH_INFO_VTABLE:
        case MONO_PATCH_INFO_CLASS_INIT:
-       case MONO_PATCH_INFO_DELEGATE_TRAMPOLINE:
        case MONO_PATCH_INFO_CLASS:
        case MONO_PATCH_INFO_IID:
        case MONO_PATCH_INFO_ADJUSTED_IID:
@@ -6373,6 +6447,13 @@ can_encode_patch (MonoAotCompile *acfg, MonoJumpInfo *patch_info)
                        return FALSE;
                }
                break;
+       case MONO_PATCH_INFO_DELEGATE_TRAMPOLINE: {
+               if (!can_encode_class (acfg, patch_info->data.del_tramp->klass)) {
+                       //printf ("Skip: %s\n", mono_type_full_name (&patch_info->data.klass->byval_arg));
+                       return FALSE;
+               }
+               break;
+       }
        case MONO_PATCH_INFO_RGCTX_FETCH: {
                MonoJumpInfoRgctxEntry *entry = patch_info->data.rgctx_entry;
 
@@ -6447,7 +6528,7 @@ compile_method (MonoAotCompile *acfg, MonoMethod *method)
         * the runtime will not see AOT methods during AOT compilation,so it
         * does not need to support them by creating a fake GOT etc.
         */
-       cfg = mini_method_compile (method, acfg->opts, mono_get_root_domain (), FALSE, TRUE, 0);
+       cfg = mini_method_compile (method, acfg->opts, mono_get_root_domain (), acfg->aot_opts.full_aot ? (JIT_FLAG_AOT|JIT_FLAG_FULL_AOT) : (JIT_FLAG_AOT), 0);
        mono_loader_clear_error ();
 
        if (cfg->exception_type == MONO_EXCEPTION_GENERIC_SHARING_FAILED) {
@@ -6533,6 +6614,13 @@ compile_method (MonoAotCompile *acfg, MonoMethod *method)
                return;
        }
 
+       if (method->is_inflated && acfg->aot_opts.log_instances) {
+               if (acfg->instances_logfile)
+                       fprintf (acfg->instances_logfile, "%s ### %d\n", mono_method_full_name (method, TRUE), cfg->code_size);
+               else
+                       printf ("%s ### %d\n", mono_method_full_name (method, TRUE), cfg->code_size);
+       }
+
        /* Adds generic instances referenced by this method */
        /* 
         * The depth is used to avoid infinite loops when generic virtual recursion is 
@@ -6933,8 +7021,19 @@ emit_llvm_file (MonoAotCompile *acfg)
         * strip-dead-prototypes deletes unused intrinsics definitions.
         */
        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");
-       opts = g_strdup ("-targetlibinfo -no-aa -basicaa -notti -instcombine -simplifycfg -sroa -domtree -early-cse -lazy-value-info -correlated-propagation -simplifycfg -instcombine -simplifycfg -reassociate -domtree -loops -loop-simplify -lcssa -loop-rotate -licm -lcssa -loop-unswitch -instcombine -scalar-evolution -loop-simplify -lcssa -indvars -loop-idiom -loop-deletion -loop-unroll -memdep -gvn -memdep -memcpyopt -sccp -instcombine -lazy-value-info -correlated-propagation -domtree -memdep -dse -adce -simplifycfg -instcombine -strip-dead-prototypes -preverify -domtree -verify");
+       //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 -domtree -verify");
+       /* The dse pass is disabled because of #13734 and #17616 */
+       /*
+        * The dse bug is in DeadStoreElimination.cpp:isOverwrite ():
+        * // If we have no DataLayout information around, then the size of the store
+        *  // is inferrable from the pointee type.  If they are the same type, then
+        * // we know that the store is safe.
+        * if (AA.getDataLayout() == 0 &&
+        * Later.Ptr->getType() == Earlier.Ptr->getType()) {
+        * return OverwriteComplete;
+        * Here, if 'Earlier' refers to a memset, and Later has no size info, it mistakenly thinks the memset is redundant.
+        */
+       opts = g_strdup ("-targetlibinfo -no-aa -basicaa -notti -instcombine -simplifycfg -sroa -domtree -early-cse -lazy-value-info -correlated-propagation -simplifycfg -instcombine -simplifycfg -reassociate -domtree -loops -loop-simplify -lcssa -loop-rotate -licm -lcssa -loop-unswitch -instcombine -scalar-evolution -loop-simplify -lcssa -indvars -loop-idiom -loop-deletion -loop-unroll -memdep -gvn -memdep -memcpyopt -sccp -instcombine -lazy-value-info -correlated-propagation -domtree -memdep -adce -simplifycfg -instcombine -strip-dead-prototypes -domtree -verify");
 #if 1
        command = g_strdup_printf ("%sopt -f %s -o \"%s.opt.bc\" \"%s.bc\"", acfg->aot_opts.llvm_path, opts, acfg->tmpbasename, acfg->tmpbasename);
        printf ("Executing opt: %s\n", command);
@@ -7088,7 +7187,6 @@ emit_code (MonoAotCompile *acfg)
                }
        }
 
-#ifdef MONOTOUCH
        if (acfg->direct_method_addresses) {
                acfg->flags |= MONO_AOT_FILE_FLAG_DIRECT_METHOD_ADDRESSES;
 
@@ -7106,14 +7204,14 @@ emit_code (MonoAotCompile *acfg)
                        fprintf (acfg->fp, "    .no_dead_strip %s\n", symbol);
 
                for (i = 0; i < acfg->nmethods; ++i) {
-                       if (acfg->cfgs [i]) {
-                               if (acfg->thumb_mixed && acfg->cfgs [i]->compile_llvm)
-                                       fprintf (acfg->fp, "\tblx %s\n", acfg->cfgs [i]->asm_symbol);
-                               else
-                                       fprintf (acfg->fp, "\tbl %s\n", acfg->cfgs [i]->asm_symbol);
-                       } else {
-                               fprintf (acfg->fp, "\tbl method_addresses\n");
-                       }
+                       int call_size;
+
+#ifdef MONO_ARCH_AOT_SUPPORTED
+                       if (acfg->cfgs [i])
+                               arch_emit_direct_call (acfg, acfg->cfgs [i]->asm_symbol, FALSE, acfg->thumb_mixed && acfg->cfgs [i]->compile_llvm, NULL, &call_size);
+                       else
+                               arch_emit_direct_call (acfg, "method_addresses", FALSE, FALSE, NULL, &call_size);
+#endif
                }
 
                sprintf (symbol, "method_addresses_end");
@@ -7141,22 +7239,6 @@ emit_code (MonoAotCompile *acfg)
                        }
                }
        }
-#else
-       sprintf (symbol, "code_offsets");
-       emit_section_change (acfg, RODATA_SECT, 1);
-       emit_alignment (acfg, 8);
-       emit_label (acfg, symbol);
-
-       acfg->stats.offsets_size += acfg->nmethods * 4;
-
-       for (i = 0; i < acfg->nmethods; ++i) {
-               if (acfg->cfgs [i]) {
-                       emit_symbol_diff (acfg, acfg->cfgs [i]->asm_symbol, acfg->methods_symbol, 0);
-               } else {
-                       emit_int32 (acfg, 0xffffffff);
-               }
-       }
-#endif
        emit_line (acfg);
 
        /* Emit a sorted table mapping methods to their unbox trampolines */
@@ -7181,16 +7263,16 @@ emit_code (MonoAotCompile *acfg)
                method = cfg->orig_method;
 
                if (acfg->aot_opts.full_aot && cfg->orig_method->klass->valuetype) {
+                       int call_size;
+
                        index = get_method_index (acfg, method);
                        sprintf (symbol, "ut_%d", index);
 
                        emit_int32 (acfg, index);
                        if (acfg->direct_method_addresses) {
-                               emit_unset_mode (acfg);
-                               if (acfg->thumb_mixed && cfg->compile_llvm)
-                                       fprintf (acfg->fp, "\n\tblx %s\n", symbol);
-                               else
-                                       fprintf (acfg->fp, "\n\tbl %s\n", symbol);
+#ifdef MONO_ARCH_AOT_SUPPORTED
+                               arch_emit_direct_call (acfg, symbol, FALSE, acfg->thumb_mixed && cfg->compile_llvm, NULL, &call_size);
+#endif
                        } else {
                                emit_symbol_diff (acfg, symbol, acfg->methods_symbol, 0);
                        }
@@ -8244,6 +8326,7 @@ collect_methods (MonoAotCompile *acfg)
 
                if (!method) {
                        printf ("Failed to load method 0x%x from '%s'.\n", token, image->name);
+                       printf ("Run with MONO_LOG_LEVEL=debug for more information.\n");
                        exit (1);
                }
                        
@@ -8352,7 +8435,7 @@ compile_methods (MonoAotCompile *acfg)
                        user_data [1] = acfg;
                        user_data [2] = frag;
                        
-                       handle = mono_create_thread (NULL, 0, (gpointer)compile_thread_main, user_data, 0, NULL);
+                       handle = mono_threads_create_thread ((gpointer)compile_thread_main, user_data, 0, 0, NULL);
                        g_ptr_array_add (threads, handle);
                }
                g_free (methods);
@@ -8386,7 +8469,7 @@ compile_asm (MonoAotCompile *acfg)
 #elif defined(sparc) && SIZEOF_VOID_P == 8
 #define AS_OPTIONS "-xarch=v9"
 #elif defined(TARGET_X86) && defined(TARGET_MACH) && !defined(__native_client_codegen__)
-#define AS_OPTIONS "-arch i386 -W"
+#define AS_OPTIONS "-arch i386"
 #else
 #define AS_OPTIONS ""
 #endif
@@ -8611,14 +8694,14 @@ int
 mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options)
 {
        MonoImage *image = ass->image;
-       int i, res;
+       int i, res, all_sizes;
        MonoAotCompile *acfg;
        char *outfile_name, *tmp_outfile_name, *p;
        char llvm_stats_msg [256];
        TV_DECLARE (atv);
        TV_DECLARE (btv);
 
-#if !defined(MONO_ARCH_GSHAREDVT_SUPPORTED) || (!defined(MONO_EXTENSIONS) && !defined(MONOTOUCH))
+#if !defined(MONO_ARCH_GSHAREDVT_SUPPORTED) || !defined(ENABLE_GSHAREDVT)
        if (opts & MONO_OPT_GSHAREDVT) {
                fprintf (stderr, "-O=gsharedvt not supported on this platform.\n");
                exit (1);
@@ -8669,7 +8752,7 @@ mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options)
                opt->mdb_optimizations = TRUE;
                opt->gen_seq_points = TRUE;
 
-               if (mono_debug_format == MONO_DEBUG_FORMAT_NONE) {
+               if (!mono_debug_enabled ()) {
                        fprintf (stderr, "The soft-debug AOT option requires the --debug option.\n");
                        return 1;
                }
@@ -8690,6 +8773,14 @@ mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options)
        if (acfg->aot_opts.full_aot)
                acfg->flags |= MONO_AOT_FILE_FLAG_FULL_AOT;
 
+       if (acfg->aot_opts.instances_logfile_path) {
+               acfg->instances_logfile = fopen (acfg->aot_opts.instances_logfile_path, "w");
+               if (!acfg->instances_logfile) {
+                       fprintf (stderr, "Unable to create logfile: '%s'.\n", acfg->aot_opts.instances_logfile_path);
+                       exit (1);
+               }
+       }
+
        load_profile_files (acfg);
 
        acfg->num_trampolines [MONO_AOT_TRAMP_SPECIFIC] = acfg->aot_opts.full_aot ? acfg->aot_opts.ntrampolines : 0;
@@ -8868,12 +8959,14 @@ mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options)
        if (acfg->aot_opts.dwarf_debug && acfg->aot_opts.asm_only && acfg->aot_opts.gnu_asm) {
                /*
                 * CLANG supports GAS .file/.loc directives, so emit line number information this way
+                * FIXME: CLANG only emits line number info for .loc directives followed by assembly, not
+                * .byte directives.
                 */
-               acfg->gas_line_numbers = TRUE;
+               //acfg->gas_line_numbers = TRUE;
        }
 
        if (!acfg->aot_opts.nodebug || acfg->aot_opts.dwarf_debug) {
-               if (acfg->aot_opts.dwarf_debug && mono_debug_format == MONO_DEBUG_FORMAT_NONE) {
+               if (acfg->aot_opts.dwarf_debug && !mono_debug_enabled ()) {
                        fprintf (stderr, "The dwarf AOT option requires the --debug option.\n");
                        return 1;
                }
@@ -8883,7 +8976,7 @@ mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options)
        img_writer_emit_start (acfg->w);
 
        if (acfg->dwarf)
-               mono_dwarf_writer_emit_base_info (acfg->dwarf, mono_unwind_get_cie_program ());
+               mono_dwarf_writer_emit_base_info (acfg->dwarf, g_path_get_basename (acfg->image->name), mono_unwind_get_cie_program ());
 
        if (acfg->thumb_mixed) {
                char symbol [256];
@@ -8959,7 +9052,19 @@ mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options)
                sprintf (llvm_stats_msg, ", LLVM: %d (%d%%)", acfg->stats.llvm_count, acfg->stats.mcount ? (acfg->stats.llvm_count * 100) / acfg->stats.mcount : 100);
        else
                strcpy (llvm_stats_msg, "");
-       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);
+
+       all_sizes = acfg->stats.code_size + acfg->stats.info_size + acfg->stats.ex_info_size + acfg->stats.unwind_info_size + acfg->stats.class_info_size + acfg->stats.got_info_size + acfg->stats.offsets_size + acfg->stats.plt_size;
+
+       printf ("Code: %d(%d%%) Info: %d(%d%%) Ex Info: %d(%d%%) Unwind Info: %d(%d%%) Class Info: %d(%d%%) PLT: %d(%d%%) GOT Info: %d(%d%%) Offsets: %d(%d%%) GOT: %d\n",
+                       acfg->stats.code_size, acfg->stats.code_size * 100 / all_sizes,
+                       acfg->stats.info_size, acfg->stats.info_size * 100 / all_sizes,
+                       acfg->stats.ex_info_size, acfg->stats.ex_info_size * 100 / all_sizes,
+                       acfg->stats.unwind_info_size, acfg->stats.unwind_info_size * 100 / all_sizes,
+                       acfg->stats.class_info_size, acfg->stats.class_info_size * 100 / all_sizes,
+                       acfg->stats.plt_size ? acfg->stats.plt_size : acfg->plt_offset, acfg->stats.plt_size ? acfg->stats.plt_size * 100 / all_sizes : 0,
+                       acfg->stats.got_info_size, acfg->stats.got_info_size * 100 / all_sizes,
+                       acfg->stats.offsets_size, acfg->stats.offsets_size * 100 / all_sizes,
+                       (int)(acfg->got_offset * sizeof (gpointer)));
        printf ("Compiled: %d/%d (%d%%)%s, 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,
                        llvm_stats_msg,