Merge branch 'master' into msbuilddll2
[mono.git] / mono / mini / aot-compiler.c
old mode 100644 (file)
new mode 100755 (executable)
index fe45c28..4f66e39
@@ -71,6 +71,8 @@
 
 #if defined(__linux__) || defined(__native_client_codegen__)
 #define RODATA_SECT ".rodata"
+#elif defined(TARGET_MACH)
+#define RODATA_SECT ".section __TEXT, __const"
 #else
 #define RODATA_SECT ".text"
 #endif
@@ -131,6 +133,7 @@ typedef struct MonoAotOptions {
        gboolean no_direct_calls;
        gboolean use_trampolines_page;
        gboolean no_instances;
+       gboolean gnu_asm;
        int nthreads;
        int ntrampolines;
        int nrgctx_trampolines;
@@ -162,7 +165,7 @@ typedef struct MonoAotCompile {
        GHashTable *method_depth;
        MonoCompile **cfgs;
        int cfgs_size;
-       GHashTable *patch_to_plt_entry;
+       GHashTable **patch_to_plt_entry;
        GHashTable *plt_offset_to_entry;
        GHashTable *patch_to_got_offset;
        GHashTable **patch_to_got_offset_by_type;
@@ -185,10 +188,12 @@ typedef struct MonoAotCompile {
        guint32 final_got_size;
        /* Number of GOT entries reserved for trampolines */
        guint32 num_trampoline_got_entries;
+       guint32 tramp_page_size;
 
        guint32 num_trampolines [MONO_AOT_TRAMP_NUM];
        guint32 trampoline_got_offset_base [MONO_AOT_TRAMP_NUM];
        guint32 trampoline_size [MONO_AOT_TRAMP_NUM];
+       guint32 tramp_page_code_offsets [MONO_AOT_TRAMP_NUM];
 
        MonoAotOptions aot_opts;
        guint32 nmethods;
@@ -200,9 +205,11 @@ typedef struct MonoAotCompile {
        char *static_linking_symbol;
        CRITICAL_SECTION mutex;
        gboolean use_bin_writer;
+       gboolean gas_line_numbers;
        MonoImageWriter *w;
        MonoDwarfWriter *dwarf;
        FILE *fp;
+       char *tmpbasename;
        char *tmpfname;
        GSList *cie_program;
        GHashTable *unwind_info_offsets;
@@ -211,6 +218,7 @@ typedef struct MonoAotCompile {
        char *got_symbol_base;
        char *got_symbol;
        char *plt_symbol;
+       char *methods_symbol;
        GHashTable *method_label_hash;
        const char *temp_prefix;
        const char *user_symbol_prefix;
@@ -226,8 +234,12 @@ typedef struct MonoAotCompile {
        GHashTable *plt_entry_debug_sym_cache;
        gboolean thumb_mixed, need_no_dead_strip, need_pt_gnu_stack;
        GHashTable *ginst_hash;
+       GHashTable *dwarf_ln_filenames;
        gboolean global_symbols;
        gboolean direct_method_addresses;
+       int objc_selector_index, objc_selector_index_2;
+       GPtrArray *objc_selectors;
+       GHashTable *objc_selector_to_index;
 } MonoAotCompile;
 
 typedef struct {
@@ -526,6 +538,26 @@ encode_sleb128 (gint32 value, guint8 *buf, guint8 **endbuf)
        *endbuf = p;
 }
 
+static void
+emit_unset_mode (MonoAotCompile *acfg)
+{
+       img_writer_emit_unset_mode (acfg->w);
+}
+
+static G_GNUC_UNUSED void
+emit_set_thumb_mode (MonoAotCompile *acfg)
+{
+       emit_unset_mode (acfg);
+       fprintf (acfg->fp, ".code 16\n");
+}
+
+static G_GNUC_UNUSED void
+emit_set_arm_mode (MonoAotCompile *acfg)
+{
+       emit_unset_mode (acfg);
+       fprintf (acfg->fp, ".code 32\n");
+}
+
 /* ARCHITECTURE SPECIFIC CODE */
 
 #if defined(TARGET_X86) || defined(TARGET_AMD64) || defined(TARGET_ARM) || defined(TARGET_POWERPC)
@@ -607,6 +639,10 @@ arch_init (MonoAotCompile *acfg)
        acfg->llvm_label_prefix = "";
        acfg->user_symbol_prefix = "";
 
+#if defined(TARGET_AMD64)
+       g_string_append (acfg->llc_args, " -march=x86-64");
+#endif
+
 #ifdef TARGET_ARM
        if (acfg->aot_opts.mtriple && strstr (acfg->aot_opts.mtriple, "darwin")) {
                g_string_append (acfg->llc_args, "-mattr=+v6");
@@ -629,6 +665,7 @@ arch_init (MonoAotCompile *acfg)
        acfg->user_symbol_prefix = "_";
        acfg->llvm_label_prefix = "_";
        acfg->need_no_dead_strip = TRUE;
+       acfg->aot_opts.gnu_asm = TRUE;
 #endif
 
 #if defined(__linux__) && !defined(TARGET_ARM)
@@ -648,12 +685,12 @@ arch_init (MonoAotCompile *acfg)
  * calling code.
  */
 static void
-arch_emit_direct_call (MonoAotCompile *acfg, const char *target, gboolean external, int *call_size)
+arch_emit_direct_call (MonoAotCompile *acfg, const char *target, gboolean external, MonoJumpInfo *ji, int *call_size)
 {
 #if defined(TARGET_X86) || defined(TARGET_AMD64)
        /* Need to make sure this is exactly 5 bytes long */
        if (external && !acfg->use_bin_writer) {
-               img_writer_emit_unset_mode (acfg->w);
+               emit_unset_mode (acfg);
                fprintf (acfg->fp, "call %s\n", target);
        } else {
                emit_byte (acfg, '\xe8');
@@ -671,7 +708,7 @@ arch_emit_direct_call (MonoAotCompile *acfg, const char *target, gboolean extern
                img_writer_emit_reloc (acfg->w, R_ARM_CALL, target, -8);
                emit_bytes (acfg, buf, 4);
        } else {
-               img_writer_emit_unset_mode (acfg->w);
+               emit_unset_mode (acfg);
                fprintf (acfg->fp, "bl %s\n", target);
        }
        *call_size = 4;
@@ -679,7 +716,7 @@ arch_emit_direct_call (MonoAotCompile *acfg, const char *target, gboolean extern
        if (acfg->use_bin_writer) {
                g_assert_not_reached ();
        } else {
-               img_writer_emit_unset_mode (acfg->w);
+               emit_unset_mode (acfg);
                fprintf (acfg->fp, "bl %s\n", target);
                *call_size = 4;
        }
@@ -732,7 +769,7 @@ arch_emit_got_offset (MonoAotCompile *acfg, guint8 *code, int *code_size)
 {
 #if defined(TARGET_POWERPC64)
        g_assert (!acfg->use_bin_writer);
-       img_writer_emit_unset_mode (acfg->w);
+       emit_unset_mode (acfg);
        /* 
         * The ppc32 code doesn't seem to work on ppc64, the assembler complains about
         * unsupported relocations. So we store the got address into the .Lgot_addr
@@ -747,7 +784,7 @@ arch_emit_got_offset (MonoAotCompile *acfg, guint8 *code, int *code_size)
        *code_size = 16;
 #elif defined(TARGET_POWERPC)
        g_assert (!acfg->use_bin_writer);
-       img_writer_emit_unset_mode (acfg->w);
+       emit_unset_mode (acfg);
        fprintf (acfg->fp, ".L%d:\n", acfg->label_generator);
        fprintf (acfg->fp, "lis 0, (%s + 4 - .L%d)@h\n", acfg->got_symbol, acfg->label_generator);
        fprintf (acfg->fp, "ori 0, 0, (%s + 4 - .L%d)@l\n", acfg->got_symbol, acfg->label_generator);
@@ -803,6 +840,35 @@ arch_emit_got_access (MonoAotCompile *acfg, guint8 *code, int got_slot, int *cod
 
 #endif
 
+/*
+ * arch_emit_objc_selector_ref:
+ *
+ *   Emit the implementation of OP_OBJC_GET_SELECTOR, which itself implements @selector(foo:) in objective-c.
+ */
+static void
+arch_emit_objc_selector_ref (MonoAotCompile *acfg, guint8 *code, int index, int *code_size)
+{
+#if defined(TARGET_ARM)
+       char symbol1 [256];
+       char symbol2 [256];
+       int lindex = acfg->objc_selector_index_2 ++;
+
+       /* Emit ldr.imm/b */
+       emit_bytes (acfg, code, 8);
+
+       sprintf (symbol1, "L_OBJC_SELECTOR_%d", lindex);
+       sprintf (symbol2, "L_OBJC_SELECTOR_REFERENCES_%d", index);
+
+       emit_label (acfg, symbol1);
+       img_writer_emit_unset_mode (acfg->w);
+       fprintf (acfg->fp, ".long %s-(%s+12)", symbol2, symbol1);
+
+       *code_size = 12;
+#else
+       g_assert_not_reached ();
+#endif
+}
+
 /*
  * arch_emit_plt_entry:
  *
@@ -883,7 +949,7 @@ arch_emit_plt_entry (MonoAotCompile *acfg, int index)
 
                /* The GOT address is guaranteed to be in r30 by OP_LOAD_GOTADDR */
                g_assert (!acfg->use_bin_writer);
-               img_writer_emit_unset_mode (acfg->w);
+               emit_unset_mode (acfg);
                fprintf (acfg->fp, "lis 11, %d@h\n", offset);
                fprintf (acfg->fp, "ori 11, 11, %d@l\n", offset);
                fprintf (acfg->fp, "add 11, 11, 30\n");
@@ -915,13 +981,23 @@ arch_emit_llvm_plt_entry (MonoAotCompile *acfg, int index)
        /* LLVM calls the PLT entries using bl, so these have to be thumb2 */
        /* The caller already transitioned to thumb */
        /* The code below should be 12 bytes long */
+       /* clang has trouble encoding these instructions, so emit the binary */
+#if 0
        fprintf (acfg->fp, "ldr ip, [pc, #8]\n");
        /* thumb can't encode ld pc, [pc, ip] */
        fprintf (acfg->fp, "add ip, pc, ip\n");
        fprintf (acfg->fp, "ldr ip, [ip, #0]\n");
        fprintf (acfg->fp, "bx ip\n");
+#endif
+       emit_set_thumb_mode (acfg);
+       fprintf (acfg->fp, ".4byte 0xc008f8df\n");
+       fprintf (acfg->fp, ".2byte 0x44fc\n");
+       fprintf (acfg->fp, ".4byte 0xc000f8dc\n");
+       fprintf (acfg->fp, ".2byte 0x4760\n");
        emit_symbol_diff (acfg, acfg->got_symbol, ".", ((acfg->plt_got_offset_base + index) * sizeof (gpointer)) + 4);
        emit_int32 (acfg, acfg->plt_got_info_offsets [index]);
+       emit_unset_mode (acfg);
+       emit_set_arm_mode (acfg);
 #else
        g_assert_not_reached ();
 #endif
@@ -957,6 +1033,8 @@ arch_emit_specific_trampoline_pages (MonoAotCompile *acfg)
        if (!acfg->aot_opts.use_trampolines_page)
                return;
 
+       acfg->tramp_page_size = mono_pagesize ();
+
        sprintf (symbol, "%sspecific_trampolines_page", acfg->user_symbol_prefix);
        emit_alignment (acfg, mono_pagesize ());
        emit_global (acfg, symbol, TRUE);
@@ -1229,7 +1307,7 @@ arch_emit_specific_trampoline (MonoAotCompile *acfg, int offset, int *tramp_size
         * in the second got slot of every aot image. The caller already computed
         * the address of its got and placed it into r30.
         */
-       img_writer_emit_unset_mode (acfg->w);
+       emit_unset_mode (acfg);
        /* Load mscorlib got address */
        fprintf (acfg->fp, "%s 0, %d(30)\n", PPC_LD_OP, (int)sizeof (gpointer));
        /* Load generic trampoline address */
@@ -1461,7 +1539,7 @@ arch_emit_static_rgctx_trampoline (MonoAotCompile *acfg, int offset, int *tramp_
         * in the second got slot of every aot image. The caller already computed
         * the address of its got and placed it into r30.
         */
-       img_writer_emit_unset_mode (acfg->w);
+       emit_unset_mode (acfg);
        /* Load mscorlib got address */
        fprintf (acfg->fp, "%s 0, %d(30)\n", PPC_LD_OP, (int)sizeof (gpointer));
        /* Load rgctx */
@@ -1875,7 +1953,7 @@ arch_emit_autoreg (MonoAotCompile *acfg, char *symbol)
 {
 #if defined(TARGET_POWERPC) && defined(__mono_ilp32__)
        /* Based on code generated by gcc */
-       img_writer_emit_unset_mode (acfg->w);
+       emit_unset_mode (acfg);
 
        fprintf (acfg->fp,
 #if defined(_MSC_VER) || defined(MONO_CROSS_COMPILE) 
@@ -2555,6 +2633,8 @@ encode_method_ref (MonoAotCompile *acfg, MonoMethod *method, guint8 *buf, guint8
                                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);
+                       else if (info->subtype == WRAPPER_SUBTYPE_ARRAY_ACCESSOR)
+                               encode_method_ref (acfg, info->d.array_accessor.method, p, &p);
                        break;
                }
                case MONO_WRAPPER_MANAGED_TO_NATIVE: {
@@ -2625,8 +2705,11 @@ encode_method_ref (MonoAotCompile *acfg, MonoMethod *method, guint8 *buf, guint8
                                encode_klass_ref (acfg, method->klass, p, &p);
                        } else {
                                MonoMethodSignature *sig = mono_method_signature (method);
+                               WrapperInfo *info = mono_marshal_get_wrapper_info (method);
 
                                encode_value (0, p, &p);
+                               if (method->wrapper_type == MONO_WRAPPER_DELEGATE_INVOKE)
+                                       encode_value (info ? info->subtype : 0, p, &p);
                                encode_signature (acfg, sig, p, &p);
                        }
                        break;
@@ -2823,7 +2906,9 @@ get_plt_entry (MonoAotCompile *acfg, MonoJumpInfo *patch_info)
        if (!is_plt_patch (patch_info))
                return NULL;
 
-       res = g_hash_table_lookup (acfg->patch_to_plt_entry, patch_info);
+       if (!acfg->patch_to_plt_entry [patch_info->type])
+               acfg->patch_to_plt_entry [patch_info->type] = g_hash_table_new (mono_patch_info_hash, mono_patch_info_equal);
+       res = g_hash_table_lookup (acfg->patch_to_plt_entry [patch_info->type], patch_info);
 
        // FIXME: This breaks the calculation of final_got_size         
        if (!acfg->llvm && patch_info->type == MONO_PATCH_INFO_METHOD && (patch_info->data.method->iflags & METHOD_IMPL_ATTRIBUTE_SYNCHRONIZED)) {
@@ -2853,7 +2938,7 @@ get_plt_entry (MonoAotCompile *acfg, MonoJumpInfo *patch_info)
                else
                        res->llvm_symbol = g_strdup_printf ("%s_llvm", res->symbol);
 
-               g_hash_table_insert (acfg->patch_to_plt_entry, new_ji, res);
+               g_hash_table_insert (acfg->patch_to_plt_entry [new_ji->type], new_ji, res);
 
                g_hash_table_insert (acfg->plt_offset_to_entry, GUINT_TO_POINTER (res->plt_offset), res);
 
@@ -3132,12 +3217,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);
@@ -3150,9 +3229,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)
@@ -3160,10 +3236,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
@@ -3191,11 +3271,9 @@ add_wrappers (MonoAotCompile *acfg)
        }
 
        if (strcmp (acfg->image->assembly->aname.name, "mscorlib") == 0) {
-#ifdef MONO_ARCH_HAVE_TLS_GET
                MonoMethodDesc *desc;
                MonoMethod *orig_method;
                int nallocators;
-#endif
 
                /* Runtime invoke wrappers */
 
@@ -3260,41 +3338,37 @@ add_wrappers (MonoAotCompile *acfg)
                add_method (acfg, mono_marshal_get_runtime_invoke_dynamic ());
 #endif
 
-               /* JIT icall wrappers */
-               /* FIXME: locking */
-               g_hash_table_foreach (mono_get_jit_icall_info (), add_jit_icall_wrapper, acfg);
-
                /* stelemref */
                add_method (acfg, mono_marshal_get_stelemref ());
 
-#ifdef MONO_ARCH_HAVE_TLS_GET
-               /* Managed Allocators */
-               nallocators = mono_gc_get_managed_allocator_types ();
-               for (i = 0; i < nallocators; ++i) {
-                       m = mono_gc_get_managed_allocator_by_type (i);
-                       if (m)
-                               add_method (acfg, m);
-               }
+               if (MONO_ARCH_HAVE_TLS_GET) {
+                       /* Managed Allocators */
+                       nallocators = mono_gc_get_managed_allocator_types ();
+                       for (i = 0; i < nallocators; ++i) {
+                               m = mono_gc_get_managed_allocator_by_type (i);
+                               if (m)
+                                       add_method (acfg, m);
+                       }
+
+                       /* Monitor Enter/Exit */
+                       desc = mono_method_desc_new ("Monitor:Enter(object,bool&)", FALSE);
+                       orig_method = mono_method_desc_search_in_class (desc, mono_defaults.monitor_class);
+                       /* This is a v4 method */
+                       if (orig_method) {
+                               method = mono_monitor_get_fast_path (orig_method);
+                               if (method)
+                                       add_method (acfg, method);
+                       }
+                       mono_method_desc_free (desc);
 
-               /* Monitor Enter/Exit */
-               desc = mono_method_desc_new ("Monitor:Enter(object,bool&)", FALSE);
-               orig_method = mono_method_desc_search_in_class (desc, mono_defaults.monitor_class);
-               /* This is a v4 method */
-               if (orig_method) {
+                       desc = mono_method_desc_new ("Monitor:Exit(object)", FALSE);
+                       orig_method = mono_method_desc_search_in_class (desc, mono_defaults.monitor_class);
+                       g_assert (orig_method);
+                       mono_method_desc_free (desc);
                        method = mono_monitor_get_fast_path (orig_method);
                        if (method)
-                       add_method (acfg, method);
+                               add_method (acfg, method);
                }
-               mono_method_desc_free (desc);
-
-               desc = mono_method_desc_new ("Monitor:Exit(object)", FALSE);
-               orig_method = mono_method_desc_search_in_class (desc, mono_defaults.monitor_class);
-               g_assert (orig_method);
-               mono_method_desc_free (desc);
-               method = mono_monitor_get_fast_path (orig_method);
-               if (method)
-                       add_method (acfg, method);
-#endif
 
                /* Stelemref wrappers */
                {
@@ -3327,6 +3401,10 @@ add_wrappers (MonoAotCompile *acfg)
                        }
                }
 #endif
+
+               /* JIT icall wrappers */
+               /* 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);
        }
 
        /* 
@@ -3440,13 +3518,62 @@ add_wrappers (MonoAotCompile *acfg)
                }
        }
 
+       /* array access wrappers */
+       for (i = 0; i < acfg->image->tables [MONO_TABLE_TYPESPEC].rows; ++i) {
+               MonoClass *klass;
+               
+               token = MONO_TOKEN_TYPE_SPEC | (i + 1);
+               klass = mono_class_get (acfg->image, token);
+
+               if (!klass) {
+                       mono_loader_clear_error ();
+                       continue;
+               }
+
+               if (klass->rank && MONO_TYPE_IS_PRIMITIVE (&klass->element_class->byval_arg)) {
+                       MonoMethod *m, *wrapper;
+
+                       /* Add runtime-invoke wrappers too */
+
+                       m = mono_class_get_method_from_name (klass, "Get", -1);
+                       g_assert (m);
+                       wrapper = mono_marshal_get_array_accessor_wrapper (m);
+                       add_extra_method (acfg, wrapper);
+                       add_extra_method (acfg, mono_marshal_get_runtime_invoke (wrapper, FALSE));
+
+                       m = mono_class_get_method_from_name (klass, "Set", -1);
+                       g_assert (m);
+                       wrapper = mono_marshal_get_array_accessor_wrapper (m);
+                       add_extra_method (acfg, wrapper);
+                       add_extra_method (acfg, mono_marshal_get_runtime_invoke (wrapper, FALSE));
+               }
+       }
+
        /* Synchronized wrappers */
        for (i = 0; i < acfg->image->tables [MONO_TABLE_METHOD].rows; ++i) {
                token = MONO_TOKEN_METHOD_DEF | (i + 1);
                method = mono_get_method (acfg->image, token, NULL);
 
-               if (method->iflags & METHOD_IMPL_ATTRIBUTE_SYNCHRONIZED && !method->is_generic)
-                       add_method (acfg, mono_marshal_get_synchronized_wrapper (method));
+               if (method->iflags & METHOD_IMPL_ATTRIBUTE_SYNCHRONIZED) {
+                       if (method->is_generic) {
+                               // FIXME:
+                       } else if (method->klass->generic_container) {
+                               MonoGenericContext ctx;
+                               MonoMethod *inst, *gshared, *m;
+
+                               /*
+                                * Create a generic wrapper for a generic instance, and AOT that.
+                                */
+                               create_gsharedvt_inst (acfg, method, &ctx);
+                               inst = mono_class_inflate_generic_method (method, &ctx);        
+                               m = mono_marshal_get_synchronized_wrapper (inst);
+                               g_assert (m->is_inflated);
+                               gshared = mini_get_shared_method_full (m, FALSE, TRUE);
+                               add_method (acfg, gshared);
+                       } else {
+                               add_method (acfg, mono_marshal_get_synchronized_wrapper (method));
+                       }
+               }
        }
 
        /* pinvoke wrappers */
@@ -3611,6 +3738,21 @@ has_type_vars (MonoClass *klass)
                                        return TRUE;
                }
        }
+       if (klass->generic_container)
+               return TRUE;
+       return FALSE;
+}
+
+static gboolean
+is_vt_inst (MonoGenericInst *inst)
+{
+       int i;
+
+       for (i = 0; i < inst->type_argc; ++i) {
+               MonoType *t = inst->type_argv [i];
+               if (t->type == MONO_TYPE_VALUETYPE)
+                       return TRUE;
+       }
        return FALSE;
 }
 
@@ -3684,6 +3826,7 @@ add_generic_class_with_depth (MonoAotCompile *acfg, MonoClass *klass, int depth,
        MonoMethod *method;
        MonoClassField *field;
        gpointer iter;
+       gboolean use_gsharedvt = FALSE;
 
        if (!acfg->ginst_hash)
                acfg->ginst_hash = g_hash_table_new (NULL, NULL);
@@ -3716,9 +3859,23 @@ add_generic_class_with_depth (MonoAotCompile *acfg, MonoClass *klass, int depth,
 
        g_hash_table_insert (acfg->ginst_hash, klass, klass);
 
+       /*
+        * 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")))
+               use_gsharedvt = TRUE;
+
        iter = NULL;
        while ((method = mono_class_get_methods (klass, &iter))) {
-               if (mono_method_is_generic_sharable_full (method, FALSE, FALSE, FALSE))
+               if ((acfg->opts & MONO_OPT_GSHAREDVT) && method->is_inflated && mono_method_get_context (method)->method_inst) {
+                       /*
+                        * This is partial sharing, and we can't handle it yet
+                        */
+                       continue;
+               }
+               
+               if (mono_method_is_generic_sharable_full (method, FALSE, FALSE, use_gsharedvt))
                        /* Already added */
                        continue;
 
@@ -3881,6 +4038,8 @@ add_types_from_method_header (MonoAotCompile *acfg, MonoMethod *method)
                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");
+       } else {
+               mono_loader_clear_error ();
        }
 }
 
@@ -4148,6 +4307,10 @@ is_direct_callable (MonoAotCompile *acfg, MonoMethod *method, MonoJumpInfo *patc
                                direct_callable = FALSE;
                        }
 
+                       if (callee_cfg->method->wrapper_type == MONO_WRAPPER_ALLOC)
+                               /* sgen does some initialization when the allocator method is created */
+                               direct_callable = FALSE;
+
                        if (direct_callable)
                                return TRUE;
                }
@@ -4193,6 +4356,119 @@ get_pinvoke_import (MonoAotCompile *acfg, MonoMethod *method)
        return import;
 }
 
+static gint
+compare_lne (MonoDebugLineNumberEntry *a, MonoDebugLineNumberEntry *b)
+{
+       if (a->native_offset == b->native_offset)
+               return a->il_offset - b->il_offset;
+       else
+               return a->native_offset - b->native_offset;
+}
+
+/*
+ * compute_line_numbers:
+ *
+ * Returns a sparse array of size CODE_SIZE containing MonoDebugSourceLocation* entries for the native offsets which have a corresponding line number
+ * entry.
+ */
+static MonoDebugSourceLocation**
+compute_line_numbers (MonoMethod *method, int code_size, MonoDebugMethodJitInfo *debug_info)
+{
+       MonoDebugMethodInfo *minfo;
+       MonoDebugLineNumberEntry *ln_array;
+       MonoDebugSourceLocation *loc;
+       int i, prev_line, prev_il_offset;
+       int *native_to_il_offset = NULL;
+       MonoDebugSourceLocation **res;
+       gboolean first;
+
+       minfo = mono_debug_lookup_method (method);
+       if (!minfo)
+               return NULL;
+       // FIXME: This seems to happen when two methods have the same cfg->method_to_register
+       if (debug_info->code_size != code_size)
+               return NULL;
+
+       g_assert (code_size);
+
+       /* Compute the native->IL offset mapping */
+
+       ln_array = g_new0 (MonoDebugLineNumberEntry, debug_info->num_line_numbers);
+       memcpy (ln_array, debug_info->line_numbers, debug_info->num_line_numbers * sizeof (MonoDebugLineNumberEntry));
+
+       qsort (ln_array, debug_info->num_line_numbers, sizeof (MonoDebugLineNumberEntry), (gpointer)compare_lne);
+
+       native_to_il_offset = g_new0 (int, code_size + 1);
+
+       for (i = 0; i < debug_info->num_line_numbers; ++i) {
+               int j;
+               MonoDebugLineNumberEntry *lne = &ln_array [i];
+
+               if (i == 0) {
+                       for (j = 0; j < lne->native_offset; ++j)
+                               native_to_il_offset [j] = -1;
+               }
+
+               if (i < debug_info->num_line_numbers - 1) {
+                       MonoDebugLineNumberEntry *lne_next = &ln_array [i + 1];
+
+                       for (j = lne->native_offset; j < lne_next->native_offset; ++j)
+                               native_to_il_offset [j] = lne->il_offset;
+               } else {
+                       for (j = lne->native_offset; j < code_size; ++j)
+                               native_to_il_offset [j] = lne->il_offset;
+               }
+       }
+       g_free (ln_array);
+
+       /* Compute the native->line number mapping */
+       res = g_new0 (MonoDebugSourceLocation*, code_size);
+       prev_il_offset = -1;
+       prev_line = -1;
+       first = TRUE;
+       for (i = 0; i < code_size; ++i) {
+               int il_offset = native_to_il_offset [i];
+
+               if (il_offset == -1 || il_offset == prev_il_offset)
+                       continue;
+               prev_il_offset = il_offset;
+               loc = mono_debug_symfile_lookup_location (minfo, il_offset);
+               if (!(loc && loc->source_file))
+                       continue;
+               if (loc->row == prev_line) {
+                       mono_debug_symfile_free_location (loc);
+                       continue;
+               }
+               prev_line = loc->row;
+               //printf ("D: %s:%d il=%x native=%x\n", loc->source_file, loc->row, il_offset, i);
+               if (first)
+                       /* This will cover the prolog too */
+                       res [0] = loc;
+               else
+                       res [i] = loc;
+               first = FALSE;
+       }
+       return res;
+}
+
+static int
+get_file_index (MonoAotCompile *acfg, const char *source_file)
+{
+       int findex;
+
+       // FIXME: Free these
+       if (!acfg->dwarf_ln_filenames)
+               acfg->dwarf_ln_filenames = g_hash_table_new (g_str_hash, g_str_equal);
+       findex = GPOINTER_TO_INT (g_hash_table_lookup (acfg->dwarf_ln_filenames, source_file));
+       if (!findex) {
+               findex = g_hash_table_size (acfg->dwarf_ln_filenames) + 1;
+               g_hash_table_insert (acfg->dwarf_ln_filenames, g_strdup (source_file), GINT_TO_POINTER (findex));
+               emit_unset_mode (acfg);
+               fprintf (acfg->fp, ".file %d \"%s\"\n", findex, mono_dwarf_escape_path (source_file));
+       }
+       return findex;
+}
+
 /*
  * emit_and_reloc_code:
  *
@@ -4202,15 +4478,16 @@ get_pinvoke_import (MonoAotCompile *acfg, MonoMethod *method)
  * since trampolines are needed to make PTL work.
  */
 static void
-emit_and_reloc_code (MonoAotCompile *acfg, MonoMethod *method, guint8 *code, guint32 code_len, MonoJumpInfo *relocs, gboolean got_only)
+emit_and_reloc_code (MonoAotCompile *acfg, MonoMethod *method, guint8 *code, guint32 code_len, MonoJumpInfo *relocs, gboolean got_only, MonoDebugMethodJitInfo *debug_info)
 {
        int i, pindex, start_index, method_index;
        GPtrArray *patches;
        MonoJumpInfo *patch_info;
        MonoMethodHeader *header;
+       MonoDebugSourceLocation **locs = NULL;
        gboolean skip, direct_call, external_call;
        guint32 got_slot;
-       const char *direct_call_target;
+       const char *direct_call_target = 0;
        const char *direct_pinvoke;
 
        if (method) {
@@ -4219,6 +4496,15 @@ emit_and_reloc_code (MonoAotCompile *acfg, MonoMethod *method, guint8 *code, gui
                method_index = get_method_index (acfg, method);
        }
 
+       if (acfg->gas_line_numbers && method && debug_info) {
+               locs = compute_line_numbers (method, code_len, debug_info);
+               if (!locs) {
+                       int findex = get_file_index (acfg, "<unknown>");
+                       emit_unset_mode (acfg);
+                       fprintf (acfg->fp, ".loc %d %d 0\n", findex, 1);
+               }
+       }
+
        /* Collect and sort relocations */
        patches = g_ptr_array_new ();
        for (patch_info = relocs; patch_info; patch_info = patch_info->next)
@@ -4234,8 +4520,18 @@ emit_and_reloc_code (MonoAotCompile *acfg, MonoMethod *method, guint8 *code, gui
                                break;
                }
 
-#ifdef MONO_ARCH_AOT_SUPPORTED
+               if (locs && locs [i]) {
+                       MonoDebugSourceLocation *loc = locs [i];
+                       int findex;
+
+                       findex = get_file_index (acfg, loc->source_file);
+                       emit_unset_mode (acfg);
+                       fprintf (acfg->fp, ".loc %d %d 0\n", findex, loc->row);
+                       mono_debug_symfile_free_location (loc);
+               }
+
                skip = FALSE;
+#ifdef MONO_ARCH_AOT_SUPPORTED
                if (patch_info && (patch_info->ip.i == i) && (pindex < patches->len)) {
                        start_index = pindex;
 
@@ -4251,6 +4547,30 @@ emit_and_reloc_code (MonoAotCompile *acfg, MonoMethod *method, guint8 *code, gui
                                patch_info->type = MONO_PATCH_INFO_NONE;
                                break;
                        }
+                       case MONO_PATCH_INFO_OBJC_SELECTOR_REF: {
+                               int code_size, index;
+                               char *selector = (void*)patch_info->data.target;
+
+                               if (!acfg->objc_selector_to_index)
+                                       acfg->objc_selector_to_index = g_hash_table_new (g_str_hash, g_str_equal);
+                               if (!acfg->objc_selectors)
+                                       acfg->objc_selectors = g_ptr_array_new ();
+                               index = GPOINTER_TO_UINT (g_hash_table_lookup (acfg->objc_selector_to_index, selector));
+                               if (index)
+                                       index --;
+                               else {
+                                       index = acfg->objc_selector_index;
+                                       g_ptr_array_add (acfg->objc_selectors, (void*)patch_info->data.target);
+                                       g_hash_table_insert (acfg->objc_selector_to_index, selector, GUINT_TO_POINTER (index + 1));
+                                       acfg->objc_selector_index ++;
+                               }
+
+                               arch_emit_objc_selector_ref (acfg, code + i, index, &code_size);
+                               i += code_size - 1;
+                               skip = TRUE;
+                               patch_info->type = MONO_PATCH_INFO_NONE;
+                               break;
+                       }
                        default: {
                                /*
                                 * If this patch is a call, try emitting a direct call instead of
@@ -4324,7 +4644,7 @@ 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, &call_size);
+                                       arch_emit_direct_call (acfg, direct_call_target, external_call, patch_info, &call_size);
                                        i += call_size - 1;
                                } else {
                                        int code_size;
@@ -4351,28 +4671,72 @@ emit_and_reloc_code (MonoAotCompile *acfg, MonoMethod *method, guint8 *code, gui
 
                        /* Try to emit multiple bytes at once */
                        if (pindex < patches->len && patch_info->ip.i > i) {
-                               emit_bytes (acfg, code + i, patch_info->ip.i - i);
-                               i = patch_info->ip.i - 1;
+                               int limit;
+
+                               for (limit = i + 1; limit < patch_info->ip.i; ++limit) {
+                                       if (locs && locs [limit])
+                                               break;
+                               }
+
+                               emit_bytes (acfg, code + i, limit - i);
+                               i = limit - 1;
                        } else {
                                emit_bytes (acfg, code + i, 1);
                        }
                }
        }
+
+       g_free (locs);
 }
 
 /*
  * 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*
@@ -4478,7 +4842,7 @@ emit_method_code (MonoAotCompile *acfg, MonoCompile *cfg)
 
        acfg->cfgs [method_index]->got_offset = acfg->got_offset;
 
-       emit_and_reloc_code (acfg, method, code, cfg->code_len, cfg->patch_info, FALSE);
+       emit_and_reloc_code (acfg, method, code, cfg->code_len, cfg->patch_info, FALSE, mono_debug_find_method (cfg->jit_info->d.method, mono_domain_get ()));
 
        emit_line (acfg);
 
@@ -4529,6 +4893,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:
@@ -4619,7 +4984,7 @@ encode_patch (MonoAotCompile *acfg, MonoJumpInfo *patch_info, guint8 *buf, guint
                }
 
                encode_value (offset, p, &p);
-               g_assert (entry->info_type < 256);
+               g_assert ((int)entry->info_type < 256);
                g_assert (entry->data->type < 256);
                encode_value ((entry->in_mrgctx ? 1 : 0) | (entry->info_type << 1) | (entry->data->type << 9), p, &p);
                encode_patch (acfg, entry->data, p, &p);
@@ -4637,10 +5002,37 @@ encode_patch (MonoAotCompile *acfg, MonoJumpInfo *patch_info, guint8 *buf, guint
        case MONO_PATCH_INFO_SIGNATURE:
                encode_signature (acfg, (MonoMethodSignature*)patch_info->data.target, p, &p);
                break;
+       case MONO_PATCH_INFO_TLS_OFFSET:
+               encode_value (GPOINTER_TO_INT (patch_info->data.target), p, &p);
+               break;
        case MONO_PATCH_INFO_GSHAREDVT_CALL:
                encode_signature (acfg, (MonoMethodSignature*)patch_info->data.gsharedvt->sig, p, &p);
                encode_method_ref (acfg, patch_info->data.gsharedvt->method, p, &p);
                break;
+       case MONO_PATCH_INFO_GSHAREDVT_METHOD: {
+               MonoGSharedVtMethodInfo *info = patch_info->data.gsharedvt_method;
+               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 (template->info_type, p, &p);
+                       switch (mini_rgctx_info_type_to_patch_info_type (template->info_type)) {
+                       case MONO_PATCH_INFO_CLASS:
+                               encode_klass_ref (acfg, mono_class_from_mono_type (template->data), p, &p);
+                               break;
+                       case MONO_PATCH_INFO_FIELD:
+                               encode_field_info (acfg, template->data, p, &p);
+                               break;
+                       default:
+                               g_assert_not_reached ();
+                               break;
+                       }
+               }
+               break;
+       }
        default:
                g_warning ("unable to handle jump info %d", patch_info->type);
                g_assert_not_reached ();
@@ -4829,12 +5221,10 @@ emit_exception_debug_info (MonoAotCompile *acfg, MonoCompile *cfg)
 
        seq_points = cfg->seq_point_info;
 
-       buf_size = header->num_clauses * 256 + debug_info_size + 2048 + (seq_points ? (seq_points->len * 64) : 0) + cfg->gc_map_size;
+       buf_size = header->num_clauses * 256 + debug_info_size + 2048 + (seq_points ? (seq_points->len * 128) : 0) + cfg->gc_map_size;
        p = buf = g_malloc (buf_size);
 
-#ifdef MONO_ARCH_HAVE_XP_UNWIND
        use_unwind_ops = cfg->unwind_ops != NULL;
-#endif
 
        flags = (jinfo->has_generic_jit_info ? 1 : 0) | (use_unwind_ops ? 2 : 0) | (header->num_clauses ? 4 : 0) | (seq_points ? 8 : 0) | (cfg->compile_llvm ? 16 : 0) | (jinfo->has_try_block_holes ? 32 : 0) | (cfg->gc_map ? 64 : 0) | (jinfo->has_arch_eh_info ? 128 : 0);
 
@@ -4911,8 +5301,18 @@ emit_exception_debug_info (MonoAotCompile *acfg, MonoCompile *cfg)
                                encode_value ((gint)((guint8*)ei->data.filter - code), p, &p);
                        else {
                                if (ei->data.catch_class) {
-                                       encode_value (1, p, &p);
-                                       encode_klass_ref (acfg, ei->data.catch_class, p, &p);
+                                       guint8 *buf2, *p2;
+                                       int len;
+
+                                       buf2 = g_malloc (4096);
+                                       p2 = buf2;
+                                       encode_klass_ref (acfg, ei->data.catch_class, p2, &p2);
+                                       len = p2 - buf2;
+                                       g_assert (len < 4096);
+                                       encode_value (len, p, &p);
+                                       memcpy (p, buf2, len);
+                                       p += p2 - buf2;
+                                       g_free (buf2);
                                } else {
                                        encode_value (0, p, &p);
                                }
@@ -4924,10 +5324,29 @@ emit_exception_debug_info (MonoAotCompile *acfg, MonoCompile *cfg)
                }
        }
 
+       if (jinfo->has_try_block_holes) {
+               MonoTryBlockHoleTableJitInfo *table = mono_jit_info_get_try_block_hole_table_info (jinfo);
+               for (i = 0; i < table->num_holes; ++i) {
+                       MonoTryBlockHoleJitInfo *hole = &table->holes [i];
+                       encode_value (hole->clause, p, &p);
+                       encode_value (hole->length, p, &p);
+                       encode_value (hole->offset, p, &p);
+               }
+       }
+
+       if (jinfo->has_arch_eh_info) {
+               MonoArchEHJitInfo *eh_info;
+
+               eh_info = mono_jit_info_get_arch_eh_info (jinfo);
+               encode_value (eh_info->stack_size, p, &p);
+       }
+
        if (jinfo->has_generic_jit_info) {
                MonoGenericJitInfo *gi = mono_jit_info_get_generic_jit_info (jinfo);
                MonoGenericSharingContext* gsctx = gi->generic_sharing_context;
                guint8 *p1;
+               guint8 *buf2, *p2;
+               int len;
 
                p1 = p;
                encode_value (gi->nlocs, p, &p);
@@ -4957,15 +5376,23 @@ emit_exception_debug_info (MonoAotCompile *acfg, MonoCompile *cfg)
                 * Need to encode jinfo->method too, since it is not equal to 'method'
                 * when using generic sharing.
                 */
-               encode_method_ref (acfg, jinfo->method, p, &p);
+               buf2 = g_malloc (4096);
+               p2 = buf2;
+               encode_method_ref (acfg, jinfo->d.method, p2, &p2);
+               len = p2 - buf2;
+               g_assert (len < 4096);
+               encode_value (len, p, &p);
+               memcpy (p, buf2, len);
+               p += p2 - buf2;
+               g_free (buf2);
 
                if (gsctx && (gsctx->var_is_vt || gsctx->mvar_is_vt)) {
                        MonoMethodInflated *inflated;
                        MonoGenericContext *context;
                        MonoGenericInst *inst;
 
-                       g_assert (jinfo->method->is_inflated);
-                       inflated = (MonoMethodInflated*)jinfo->method;
+                       g_assert (jinfo->d.method->is_inflated);
+                       inflated = (MonoMethodInflated*)jinfo->d.method;
                        context = &inflated->context;
 
                        encode_value (1, p, &p);
@@ -4992,23 +5419,6 @@ emit_exception_debug_info (MonoAotCompile *acfg, MonoCompile *cfg)
                }
        }
 
-       if (jinfo->has_try_block_holes) {
-               MonoTryBlockHoleTableJitInfo *table = mono_jit_info_get_try_block_hole_table_info (jinfo);
-               for (i = 0; i < table->num_holes; ++i) {
-                       MonoTryBlockHoleJitInfo *hole = &table->holes [i];
-                       encode_value (hole->clause, p, &p);
-                       encode_value (hole->length, p, &p);
-                       encode_value (hole->offset, p, &p);
-               }
-       }
-
-       if (jinfo->has_arch_eh_info) {
-               MonoArchEHJitInfo *eh_info;
-
-               eh_info = mono_jit_info_get_arch_eh_info (jinfo);
-               encode_value (eh_info->stack_size, p, &p);
-       }
-
        if (seq_points) {
                int il_offset, native_offset, last_il_offset, last_native_offset, j;
 
@@ -5023,6 +5433,7 @@ emit_exception_debug_info (MonoAotCompile *acfg, MonoCompile *cfg)
                        last_il_offset = il_offset;
                        last_native_offset = native_offset;
 
+                       encode_value (sp->flags, p, &p);
                        encode_value (sp->next_len, p, &p);
                        for (j = 0; j < sp->next_len; ++j)
                                encode_value (sp->next [j], p, &p);
@@ -5152,6 +5563,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:
@@ -5161,8 +5573,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 ++);
@@ -5184,7 +5597,7 @@ get_plt_entry_debug_sym (MonoAotCompile *acfg, MonoJumpInfo *ji, GHashTable *cac
                break;
        }
 
-       return debug_sym;
+       return sanitize_symbol (acfg, debug_sym);
 }
 
 /*
@@ -5234,11 +5647,12 @@ emit_plt (MonoAotCompile *acfg)
                                if (callee_cfg) {
                                        if (acfg->thumb_mixed && !callee_cfg->compile_llvm) {
                                                /* LLVM calls the PLT entries using bl, so emit a stub */
+                                               emit_set_thumb_mode (acfg);
                                                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");
+                                               emit_set_arm_mode (acfg);
                                                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);
@@ -5259,7 +5673,7 @@ emit_plt (MonoAotCompile *acfg)
 
                if (debug_sym) {
                        if (acfg->need_no_dead_strip) {
-                               img_writer_emit_unset_mode (acfg->w);
+                               emit_unset_mode (acfg);
                                fprintf (acfg->fp, "    .no_dead_strip %s\n", debug_sym);
                        }
                        emit_local_symbol (acfg, debug_sym, NULL, TRUE);
@@ -5354,6 +5768,8 @@ emit_trampoline_full (MonoAotCompile *acfg, int got_offset, MonoTrampInfo *info,
        MonoJumpInfo *ji;
        GSList *unwind_ops;
 
+       g_assert (info);
+
        name = info->name;
        code = info->code;
        code_size = info->code_size;
@@ -5380,7 +5796,7 @@ emit_trampoline_full (MonoAotCompile *acfg, int got_offset, MonoTrampInfo *info,
         * The code should access everything through the GOT, so we pass
         * TRUE here.
         */
-       emit_and_reloc_code (acfg, NULL, code, code_size, ji, TRUE);
+       emit_and_reloc_code (acfg, NULL, code, code_size, ji, TRUE, NULL);
 
        emit_symbol_size (acfg, start_symbol, ".");
 
@@ -5479,6 +5895,14 @@ emit_trampolines (MonoAotCompile *acfg)
                 */
                for (tramp_type = 0; tramp_type < MONO_TRAMPOLINE_NUM; ++tramp_type) {
                        /* we overload the boolean here to indicate the slightly different trampoline needed, see mono_arch_create_generic_trampoline() */
+#ifdef DISABLE_REMOTING
+                       if (tramp_type == MONO_TRAMPOLINE_GENERIC_VIRTUAL_REMOTING)
+                               continue;
+#endif
+#ifndef MONO_ARCH_HAVE_HANDLER_BLOCK_GUARD
+                       if (tramp_type == MONO_TRAMPOLINE_HANDLER_BLOCK_GUARD)
+                               continue;
+#endif
                        mono_arch_create_generic_trampoline (tramp_type, &info, acfg->aot_opts.use_trampolines_page? 2: TRUE);
                        emit_trampoline (acfg, acfg->got_offset, info);
                }
@@ -5660,6 +6084,7 @@ emit_trampolines (MonoAotCompile *acfg)
                        }
 
                        emit_label (acfg, end_symbol);
+                       emit_int32 (acfg, 0);
                }
 
                arch_emit_specific_trampoline_pages (acfg);
@@ -5931,6 +6356,7 @@ can_encode_method (MonoAotCompile *acfg, MonoMethod *method)
                        case MONO_WRAPPER_DELEGATE_INVOKE:
                        case MONO_WRAPPER_DELEGATE_BEGIN_INVOKE:
                        case MONO_WRAPPER_DELEGATE_END_INVOKE:
+                       case MONO_WRAPPER_SYNCHRONIZED:
                                break;
                        case MONO_WRAPPER_MANAGED_TO_MANAGED:
                        case MONO_WRAPPER_CASTCLASS: {
@@ -5964,7 +6390,8 @@ 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);
@@ -6055,6 +6482,8 @@ compile_method (MonoAotCompile *acfg, MonoMethod *method)
         * 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);
+       mono_loader_clear_error ();
+
        if (cfg->exception_type == MONO_EXCEPTION_GENERIC_SHARING_FAILED) {
                if (acfg->aot_opts.print_skipped_methods)
                        printf ("Skip (gshared failure): %s (%s)\n", mono_method_full_name (method, TRUE), cfg->exception_message);
@@ -6075,6 +6504,7 @@ compile_method (MonoAotCompile *acfg, MonoMethod *method)
                mono_destroy_compile (cfg);
                return;
        }
+       cfg->method_index = index;
 
        /* Nullify patches which need no aot processing */
        for (patch_info = cfg->patch_info; patch_info; patch_info = patch_info->next) {
@@ -6445,6 +6875,13 @@ mono_aot_get_plt_symbol (MonoJumpInfoType type, gconstpointer data)
 #endif
 }
 
+int
+mono_aot_get_method_index (MonoMethod *method)
+{
+       g_assert (llvm_acfg);
+       return get_method_index (llvm_acfg, method);
+}
+
 MonoJumpInfo*
 mono_aot_patch_info_dup (MonoJumpInfo* ji)
 {
@@ -6510,7 +6947,7 @@ emit_llvm_file (MonoAotCompile *acfg)
        }
 
 
-       tempbc = g_strdup_printf ("%s.bc", acfg->tmpfname);
+       tempbc = g_strdup_printf ("%s.bc", acfg->tmpbasename);
        mono_llvm_emit_aot_module (tempbc, acfg->final_got_size);
        g_free (tempbc);
 
@@ -6526,12 +6963,14 @@ emit_llvm_file (MonoAotCompile *acfg)
         * - 'prune-eh' and 'functionattrs' depend on 'basiccg'.
         * The opt list below was produced by taking the output of:
         * llvm-as < /dev/null | opt -O2 -disable-output -debug-pass=Arguments
-        * then removing tailcallelim + the global opts, and adding a second gvn.
+        * then removing tailcallelim + the global opts.
+        * 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 ("-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");
 #if 1
-       command = g_strdup_printf ("%sopt -f %s -o %s.opt.bc %s.bc", acfg->aot_opts.llvm_path, opts, acfg->tmpfname, acfg->tmpfname);
+       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);
        if (system (command) != 0) {
                exit (1);
@@ -6548,13 +6987,18 @@ emit_llvm_file (MonoAotCompile *acfg)
        if (acfg->aot_opts.mtriple)
                g_string_append_printf (acfg->llc_args, " -mtriple=%s", acfg->aot_opts.mtriple);
 
+#if defined(TARGET_MACH) && defined(TARGET_ARM)
+       /* ios requires PIC code now */
+       g_string_append_printf (acfg->llc_args, " -relocation-model=pic");
+#else
        if (llvm_acfg->aot_opts.static_link)
                g_string_append_printf (acfg->llc_args, " -relocation-model=static");
        else
                g_string_append_printf (acfg->llc_args, " -relocation-model=pic");
+#endif
        unlink (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);
+       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->tmpbasename);
 
        printf ("Executing llc: %s\n", command);
 
@@ -6569,7 +7013,6 @@ emit_code (MonoAotCompile *acfg)
 {
        int oindex, i, prev_index;
        char symbol [256];
-       char end_symbol [256];
 
 #if defined(TARGET_POWERPC64)
        sprintf (symbol, ".Lgot_addr");
@@ -6584,21 +7027,20 @@ emit_code (MonoAotCompile *acfg)
         * code_offsets array. It is also used to compute the memory ranges occupied by
         * AOT code, so it must be equal to the address of the first emitted method.
         */
-       sprintf (symbol, "methods");
        emit_section_change (acfg, ".text", 0);
        emit_alignment (acfg, 8);
        if (acfg->llvm) {
                for (i = 0; i < acfg->nmethods; ++i) {
                        if (acfg->cfgs [i] && acfg->cfgs [i]->compile_llvm) {
-                               fprintf (acfg->fp, "\n.set methods, %s\n", acfg->cfgs [i]->asm_symbol);
+                               acfg->methods_symbol = g_strdup (acfg->cfgs [i]->asm_symbol);
                                break;
                        }
                }
-               if (i == acfg->nmethods)
-                       /* No LLVM compiled methods */
-                       emit_label (acfg, symbol);
-       } else {
+       }
+       if (!acfg->methods_symbol) {
+               sprintf (symbol, "methods");
                emit_label (acfg, symbol);
+               acfg->methods_symbol = g_strdup (symbol);
        }
 
        /* 
@@ -6638,12 +7080,18 @@ emit_code (MonoAotCompile *acfg)
                        emit_alignment (acfg, AOT_FUNC_ALIGNMENT);
 #endif
 
-                       if (acfg->thumb_mixed && cfg->compile_llvm)
+                       if (acfg->thumb_mixed && cfg->compile_llvm) {
+                               emit_set_thumb_mode (acfg);
                                fprintf (acfg->fp, "\n.thumb_func\n");
+                       }
 
                        emit_label (acfg, symbol);
 
                        arch_emit_unbox_trampoline (acfg, cfg, cfg->orig_method, cfg->asm_symbol);
+
+                       if (acfg->thumb_mixed && cfg->compile_llvm) {
+                               emit_set_arm_mode (acfg);
+                       }
                }
 
                if (cfg->compile_llvm)
@@ -6683,11 +7131,11 @@ emit_code (MonoAotCompile *acfg)
                 * This is PIE code, and the linker can update it if needed.
                 */
                sprintf (symbol, "method_addresses");
-               emit_section_change (acfg, RODATA_SECT, 1);
+               emit_section_change (acfg, ".text", 1);
                emit_alignment (acfg, 8);
                emit_label (acfg, symbol);
                emit_local_symbol (acfg, symbol, "method_addresses_end", TRUE);
-               img_writer_emit_unset_mode (acfg->w);
+               emit_unset_mode (acfg);
                if (acfg->need_no_dead_strip)
                        fprintf (acfg->fp, "    .no_dead_strip %s\n", symbol);
 
@@ -6719,10 +7167,9 @@ emit_code (MonoAotCompile *acfg)
 
                acfg->stats.offsets_size += acfg->nmethods * 4;
 
-               sprintf (end_symbol, "methods");
                for (i = 0; i < acfg->nmethods; ++i) {
                        if (acfg->cfgs [i]) {
-                               emit_symbol_diff (acfg, acfg->cfgs [i]->asm_symbol, end_symbol, 0);
+                               emit_symbol_diff (acfg, acfg->cfgs [i]->asm_symbol, acfg->methods_symbol, 0);
                        } else {
                                emit_int32 (acfg, 0xffffffff);
                        }
@@ -6736,10 +7183,9 @@ emit_code (MonoAotCompile *acfg)
 
        acfg->stats.offsets_size += acfg->nmethods * 4;
 
-       sprintf (end_symbol, "methods");
        for (i = 0; i < acfg->nmethods; ++i) {
                if (acfg->cfgs [i]) {
-                       emit_symbol_diff (acfg, acfg->cfgs [i]->asm_symbol, end_symbol, 0);
+                       emit_symbol_diff (acfg, acfg->cfgs [i]->asm_symbol, acfg->methods_symbol, 0);
                } else {
                        emit_int32 (acfg, 0xffffffff);
                }
@@ -6749,11 +7195,13 @@ emit_code (MonoAotCompile *acfg)
 
        /* Emit a sorted table mapping methods to their unbox trampolines */
        sprintf (symbol, "unbox_trampolines");
-       emit_section_change (acfg, RODATA_SECT, 1);
+       if (acfg->direct_method_addresses)
+               emit_section_change (acfg, ".text", 0);
+       else
+               emit_section_change (acfg, RODATA_SECT, 0);
        emit_alignment (acfg, 8);
        emit_label (acfg, symbol);
 
-       sprintf (end_symbol, "methods");
        prev_index = -1;
        for (i = 0; i < acfg->nmethods; ++i) {
                MonoCompile *cfg;
@@ -6772,13 +7220,13 @@ emit_code (MonoAotCompile *acfg)
 
                        emit_int32 (acfg, index);
                        if (acfg->direct_method_addresses) {
-                               img_writer_emit_unset_mode (acfg->w);
+                               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);
                        } else {
-                               emit_symbol_diff (acfg, symbol, end_symbol, 0);
+                               emit_symbol_diff (acfg, symbol, acfg->methods_symbol, 0);
                        }
                        /* Make sure the table is sorted by index */
                        g_assert (index > prev_index);
@@ -6787,6 +7235,7 @@ emit_code (MonoAotCompile *acfg)
        }
        sprintf (symbol, "unbox_trampolines_end");
        emit_label (acfg, symbol);
+       emit_int32 (acfg, 0);
 }
 
 static void
@@ -7070,6 +7519,7 @@ emit_extra_methods (MonoAotCompile *acfg)
                value = get_method_index (acfg, method);
 
                hash = mono_aot_method_hash (method) % table_size;
+               //printf ("X: %s %d\n", mono_method_full_name (method, 1), hash);
 
                chain_lengths [hash] ++;
                max_chain_length = MAX (max_chain_length, chain_lengths [hash]);
@@ -7615,7 +8065,7 @@ emit_file_info (MonoAotCompile *acfg)
         * various problems (i.e. arm/thumb).
         */
        emit_pointer (acfg, acfg->got_symbol);
-       emit_pointer (acfg, "methods");
+       emit_pointer (acfg, acfg->methods_symbol);
        if (acfg->llvm) {
                /*
                 * Emit a reference to the mono_eh_frame table created by our modified LLVM compiler.
@@ -7695,7 +8145,6 @@ emit_file_info (MonoAotCompile *acfg)
                memset (&t, 0, sizeof (MonoType));
                t.type = MONO_TYPE_R8;
                mono_type_size (&t, &align);
-
                emit_int32 (acfg, align);
 
                memset (&t, 0, sizeof (MonoType));
@@ -7708,6 +8157,10 @@ emit_file_info (MonoAotCompile *acfg)
        emit_int32 (acfg, __alignof__ (double));
        emit_int32 (acfg, __alignof__ (gint64));
 #endif
+       emit_int32 (acfg, MONO_TRAMPOLINE_NUM);
+       emit_int32 (acfg, acfg->tramp_page_size);
+       for (i = 0; i < MONO_AOT_TRAMP_NUM; ++i)
+               emit_int32 (acfg, acfg->tramp_page_code_offsets [i]);
 
        if (acfg->aot_opts.static_link) {
                char *p;
@@ -7727,6 +8180,7 @@ emit_file_info (MonoAotCompile *acfg)
                }
                acfg->static_linking_symbol = g_strdup (symbol);
                emit_global_inner (acfg, symbol, FALSE);
+               emit_alignment (acfg, sizeof (gpointer));
                emit_label (acfg, symbol);
                emit_pointer_2 (acfg, acfg->user_symbol_prefix, "mono_aot_file_info");
        }
@@ -7745,6 +8199,45 @@ emit_blob (MonoAotCompile *acfg)
        emit_bytes (acfg, (guint8*)acfg->blob.data, acfg->blob.index);
 }
 
+static void
+emit_objc_selectors (MonoAotCompile *acfg)
+{
+       int i;
+
+       if (!acfg->objc_selectors || acfg->objc_selectors->len == 0)
+               return;
+
+       /*
+        * From
+        * cat > foo.m << EOF
+        * void *ret ()
+        * {
+        * return @selector(print:);
+        * }
+        * EOF
+        */
+
+       img_writer_emit_unset_mode (acfg->w);
+       g_assert (acfg->fp);
+       fprintf (acfg->fp, ".section    __DATA,__objc_selrefs,literal_pointers,no_dead_strip\n");
+       fprintf (acfg->fp, ".align      2\n");
+       for (i = 0; i < acfg->objc_selectors->len; ++i) {
+               fprintf (acfg->fp, "L_OBJC_SELECTOR_REFERENCES_%d:\n", i);
+               fprintf (acfg->fp, ".long       L_OBJC_METH_VAR_NAME_%d\n", i);
+       }
+       fprintf (acfg->fp, ".section    __TEXT,__cstring,cstring_literals\n");
+       for (i = 0; i < acfg->objc_selectors->len; ++i) {
+               fprintf (acfg->fp, "L_OBJC_METH_VAR_NAME_%d:\n", i);
+               fprintf (acfg->fp, ".asciz \"%s\"\n", (char*)g_ptr_array_index (acfg->objc_selectors, i));
+       }
+
+       fprintf (acfg->fp, ".section    __DATA,__objc_imageinfo,regular,no_dead_strip\n");
+       fprintf (acfg->fp, ".align      2\n");
+       fprintf (acfg->fp, "L_OBJC_IMAGE_INFO:\n");
+       fprintf (acfg->fp, ".long       0\n");
+       fprintf (acfg->fp, ".long       16\n");
+}
+
 static void
 emit_dwarf_info (MonoAotCompile *acfg)
 {
@@ -7765,7 +8258,7 @@ emit_dwarf_info (MonoAotCompile *acfg)
 
                sprintf (symbol2, "%sme_%x", acfg->temp_prefix, i);
 
-               mono_dwarf_writer_emit_method (acfg->dwarf, cfg, cfg->method, cfg->asm_symbol, symbol2, cfg->jit_info->code_start, cfg->jit_info->code_size, cfg->args, cfg->locals, cfg->unwind_ops, mono_debug_find_method (cfg->jit_info->method, mono_domain_get ()));
+               mono_dwarf_writer_emit_method (acfg->dwarf, cfg, cfg->method, cfg->asm_symbol, symbol2, cfg->jit_info->code_start, cfg->jit_info->code_size, cfg->args, cfg->locals, cfg->unwind_ops, mono_debug_find_method (cfg->jit_info->d.method, mono_domain_get ()));
        }
 #endif
 }
@@ -7829,6 +8322,14 @@ collect_methods (MonoAotCompile *acfg)
                method = mono_get_method (acfg->image, token, NULL);
                if (!method)
                        continue;
+               /*
+               if (strcmp (method->name, "gshared2"))
+                       continue;
+               */
+               /*
+               if (!strstr (method->klass->image->name, "mini"))
+                       continue;
+               */
                if (method->is_generic || method->klass->generic_container) {
                        MonoMethod *gshared;
 
@@ -7930,6 +8431,8 @@ compile_asm (MonoAotCompile *acfg)
 #else
 #define AS_NAME "nacl-as"
 #endif
+#elif defined(TARGET_OSX)
+#define AS_NAME "clang -c -x assembler"
 #else
 #define AS_NAME "as"
 #endif
@@ -7938,7 +8441,17 @@ compile_asm (MonoAotCompile *acfg)
 #define LD_OPTIONS ""
 #endif
 
-#define EH_LD_OPTIONS ""
+#if defined(sparc)
+#define LD_NAME "ld -shared -G"
+#elif defined(__ppc__) && defined(TARGET_MACH)
+#define LD_NAME "gcc -dynamiclib"
+#elif defined(TARGET_AMD64) && defined(TARGET_MACH)
+#define LD_NAME "clang --shared"
+#elif defined(HOST_WIN32)
+#define LD_NAME "gcc -shared --dll"
+#elif defined(TARGET_X86) && defined(TARGET_MACH) && !defined(__native_client_codegen__)
+#define LD_NAME "clang -m32 -dynamiclib"
+#endif
 
        if (acfg->aot_opts.asm_only) {
                printf ("Output file: '%s'.\n", acfg->tmpfname);
@@ -7979,18 +8492,10 @@ compile_asm (MonoAotCompile *acfg)
 
        tmp_outfile_name = g_strdup_printf ("%s.tmp", outfile_name);
 
-#if defined(sparc)
-       command = g_strdup_printf ("ld -shared -G -o %s %s.o", tmp_outfile_name, acfg->tmpfname);
-#elif defined(__ppc__) && defined(TARGET_MACH)
-       command = g_strdup_printf ("gcc -dynamiclib -o %s %s.o", tmp_outfile_name, acfg->tmpfname);
-#elif defined(TARGET_AMD64) && defined(TARGET_MACH)
-       command = g_strdup_printf ("gcc --shared -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(TARGET_MACH) && !defined(__native_client_codegen__)
-       command = g_strdup_printf ("gcc -m32 -dynamiclib -o %s %s.o", tmp_outfile_name, acfg->tmpfname);
+#ifdef LD_NAME
+       command = g_strdup_printf ("%s -o %s %s.o", LD_NAME, 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);
+       command = g_strdup_printf ("%sld %s -shared -o %s %s.o", tool_prefix, LD_OPTIONS, tmp_outfile_name, acfg->tmpfname);
 #endif
        printf ("Executing the native linker: %s\n", command);
        if (system (command) != 0) {
@@ -8028,7 +8533,7 @@ compile_asm (MonoAotCompile *acfg)
 
 #if defined(TARGET_MACH)
        command = g_strdup_printf ("dsymutil %s", outfile_name);
-       printf ("Generating debug symbols: %s\n", command);
+       printf ("Executing dsymutil: %s\n", command);
        if (system (command) != 0) {
                return 1;
        }
@@ -8061,7 +8566,7 @@ acfg_create (MonoAssembly *ass, guint32 opts)
        acfg->method_indexes = g_hash_table_new (NULL, NULL);
        acfg->method_depth = g_hash_table_new (NULL, NULL);
        acfg->plt_offset_to_entry = g_hash_table_new (NULL, NULL);
-       acfg->patch_to_plt_entry = g_hash_table_new (mono_patch_info_hash, mono_patch_info_equal);
+       acfg->patch_to_plt_entry = g_new0 (GHashTable*, MONO_PATCH_INFO_NUM);
        acfg->patch_to_got_offset = g_hash_table_new (mono_patch_info_hash, mono_patch_info_equal);
        acfg->patch_to_got_offset_by_type = g_new0 (GHashTable*, MONO_PATCH_INFO_NUM);
        for (i = 0; i < MONO_PATCH_INFO_NUM; ++i)
@@ -8113,7 +8618,11 @@ acfg_free (MonoAotCompile *acfg)
        g_hash_table_destroy (acfg->method_indexes);
        g_hash_table_destroy (acfg->method_depth);
        g_hash_table_destroy (acfg->plt_offset_to_entry);
-       g_hash_table_destroy (acfg->patch_to_plt_entry);
+       for (i = 0; i < MONO_PATCH_INFO_NUM; ++i) {
+               if (acfg->patch_to_plt_entry [i])
+                       g_hash_table_destroy (acfg->patch_to_plt_entry [i]);
+       }
+       g_free (acfg->patch_to_plt_entry);
        g_hash_table_destroy (acfg->patch_to_got_offset);
        g_hash_table_destroy (acfg->method_to_cfg);
        g_hash_table_destroy (acfg->token_info_hash);
@@ -8139,11 +8648,15 @@ mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options)
        int i, res;
        MonoAotCompile *acfg;
        char *outfile_name, *tmp_outfile_name, *p;
+       char llvm_stats_msg [256];
        TV_DECLARE (atv);
        TV_DECLARE (btv);
 
-#ifndef MONO_ARCH_GSHAREDVT_SUPPORTED
-       opts &= ~MONO_OPT_GSHAREDVT;
+#if !defined(MONO_ARCH_GSHAREDVT_SUPPORTED) || (!defined(MONO_EXTENSIONS) && !defined(MONOTOUCH))
+       if (opts & MONO_OPT_GSHAREDVT) {
+               fprintf (stderr, "-O=gsharedvt not supported on this platform.\n");
+               exit (1);
+       }
 #endif
 
        printf ("Mono Ahead of Time compiler - compiling assembly %s\n", image->name);
@@ -8158,7 +8671,7 @@ mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options)
        acfg->aot_opts.nrgctx_fetch_trampolines = 128;
        acfg->aot_opts.ngsharedvt_arg_trampolines = 128;
        acfg->aot_opts.llvm_path = g_strdup ("");
-#if MONOTOUCH
+#ifdef MONOTOUCH
        acfg->aot_opts.use_trampolines_page = TRUE;
 #endif
 
@@ -8190,7 +8703,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;
                }
@@ -8247,8 +8760,11 @@ mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options)
 
        acfg->method_index = 1;
 
+       // FIXME:
+       /*
        if (acfg->aot_opts.full_aot)
                mono_set_partial_sharing_supported (TRUE);
+       */
 
        collect_methods (acfg);
 
@@ -8303,12 +8819,16 @@ mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options)
 #ifdef ENABLE_LLVM
        if (acfg->llvm) {
                if (acfg->aot_opts.asm_only) {
-                       if (acfg->aot_opts.outfile)
+                       if (acfg->aot_opts.outfile) {
                                acfg->tmpfname = g_strdup_printf ("%s", acfg->aot_opts.outfile);
-                       else
-                               acfg->tmpfname = g_strdup_printf ("%s.s", acfg->image->name);
+                               acfg->tmpbasename = g_strdup (acfg->tmpfname);
+                       } else {
+                               acfg->tmpbasename = g_strdup_printf ("%s", acfg->image->name);
+                               acfg->tmpfname = g_strdup_printf ("%s.s", acfg->tmpbasename);
+                       }
                } else {
-                       acfg->tmpfname = g_strdup ("temp.s");
+                       acfg->tmpbasename = g_strdup_printf ("%s", "temp");
+                       acfg->tmpfname = g_strdup_printf ("%s.s", acfg->tmpbasename);
                }
 
                emit_llvm_file (acfg);
@@ -8351,10 +8871,10 @@ mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options)
                                int i = g_file_open_tmp ("mono_aot_XXXXXX", &acfg->tmpfname, NULL);
                                acfg->fp = fdopen (i, "w+");
                        }
-                       if (acfg->fp == 0) {
-                               fprintf (stderr, "Unable to open file '%s': %s\n", acfg->tmpfname, strerror (errno));
-                               return 1;
-                       }
+               }
+               if (acfg->fp == 0) {
+                       fprintf (stderr, "Unable to open file '%s': %s\n", acfg->tmpfname, strerror (errno));
+                       return 1;
                }
                acfg->w = img_writer_create (acfg->fp, FALSE);
                
@@ -8379,18 +8899,25 @@ 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
+                */
+               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;
                }
-               acfg->dwarf = mono_dwarf_writer_create (acfg->w, NULL, 0, FALSE);
+               acfg->dwarf = mono_dwarf_writer_create (acfg->w, NULL, 0, FALSE, !acfg->gas_line_numbers);
        }
 
        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];
@@ -8435,6 +8962,8 @@ mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options)
 
        emit_blob (acfg);
 
+       emit_objc_selectors (acfg);
+
        emit_globals (acfg);
 
        emit_autoreg (acfg);
@@ -8460,9 +8989,14 @@ mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options)
        if (acfg->llvm)
                g_assert (acfg->got_offset <= acfg->final_got_size);
 
+       if (acfg->llvm)
+               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);
-       printf ("Compiled: %d/%d (%d%%), No GOT slots: %d (%d%%), Direct calls: %d (%d%%)\n", 
+       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,
                        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)
@@ -8473,8 +9007,6 @@ mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options)
                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);