[threads] Use runtime flag to enable cooperative suspend
[mono.git] / mono / mini / aot-compiler.c
index c4f455f223b56a4aba30cc5c60c6ffd00c6b2833..3eb775044a8182822cc9b7cce42d338133eff13f 100644 (file)
@@ -116,6 +116,7 @@ typedef struct MonoAotOptions {
        gboolean no_instances;
        gboolean gnu_asm;
        gboolean llvm;
+       gboolean llvm_only;
        int nthreads;
        int ntrampolines;
        int nrgctx_trampolines;
@@ -126,7 +127,6 @@ typedef struct MonoAotOptions {
        gboolean stats;
        char *tool_prefix;
        char *ld_flags;
-       gboolean autoreg;
        char *mtriple;
        char *llvm_path;
        char *temp_path;
@@ -178,7 +178,7 @@ typedef struct MonoAotCompile {
        /* Maps MonoMethod* -> blob offset */
        GHashTable *method_blob_hash;
        guint32 *plt_got_info_offsets;
-       guint32 got_offset, llvm_got_offset, plt_offset, plt_got_offset_base;
+       guint32 got_offset, llvm_got_offset, plt_offset, plt_got_offset_base, nshared_got_entries;
        /* Number of GOT entries reserved for trampolines */
        guint32 num_trampoline_got_entries;
        guint32 tramp_page_size;
@@ -197,7 +197,6 @@ typedef struct MonoAotCompile {
        int method_index;
        char *static_linking_symbol;
        mono_mutex_t mutex;
-       gboolean use_bin_writer;
        gboolean gas_line_numbers;
        /* Whenever to emit an object file directly from llc */
        gboolean llvm_owriter;
@@ -854,42 +853,22 @@ arch_emit_direct_call (MonoAotCompile *acfg, const char *target, gboolean extern
 {
 #if defined(TARGET_X86) || defined(TARGET_AMD64)
        /* Need to make sure this is exactly 5 bytes long */
-       if (!acfg->use_bin_writer) {
-               emit_unset_mode (acfg);
-               fprintf (acfg->fp, "call %s\n", target);
-       } else {
-               emit_byte (acfg, '\xe8');
-               emit_symbol_diff (acfg, target, ".", -4);
-       }
+       emit_unset_mode (acfg);
+       fprintf (acfg->fp, "call %s\n", target);
        *call_size = 5;
 #elif defined(TARGET_ARM)
-       if (acfg->use_bin_writer) {
-               guint8 buf [4];
-               guint8 *code;
-
-               code = buf;
-               ARM_BL (code, 0);
-
-               mono_img_writer_emit_reloc (acfg->w, R_ARM_CALL, target, -8);
-               emit_bytes (acfg, buf, 4);
-       } else {
-               emit_unset_mode (acfg);
-               if (thumb)
-                       fprintf (acfg->fp, "blx %s\n", target);
-               else
-                       fprintf (acfg->fp, "bl %s\n", target);
-       }
+       emit_unset_mode (acfg);
+       if (thumb)
+               fprintf (acfg->fp, "blx %s\n", target);
+       else
+               fprintf (acfg->fp, "bl %s\n", target);
        *call_size = 4;
 #elif defined(TARGET_ARM64)
        arm64_emit_direct_call (acfg, target, external, thumb, ji, call_size);
 #elif defined(TARGET_POWERPC)
-       if (acfg->use_bin_writer) {
-               g_assert_not_reached ();
-       } else {
-               emit_unset_mode (acfg);
-               fprintf (acfg->fp, "bl %s\n", target);
-               *call_size = 4;
-       }
+       emit_unset_mode (acfg);
+       fprintf (acfg->fp, "bl %s\n", target);
+       *call_size = 4;
 #else
        g_assert_not_reached ();
 #endif
@@ -939,7 +918,6 @@ static void
 arch_emit_got_offset (MonoAotCompile *acfg, guint8 *code, int *code_size)
 {
 #if defined(TARGET_POWERPC64)
-       g_assert (!acfg->use_bin_writer);
        emit_unset_mode (acfg);
        /* 
         * The ppc32 code doesn't seem to work on ppc64, the assembler complains about
@@ -954,7 +932,6 @@ arch_emit_got_offset (MonoAotCompile *acfg, guint8 *code, int *code_size)
        acfg->label_generator ++;
        *code_size = 16;
 #elif defined(TARGET_POWERPC)
-       g_assert (!acfg->use_bin_writer);
        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);
@@ -1098,14 +1075,8 @@ arch_emit_plt_entry (MonoAotCompile *acfg, const char *got_symbol, int offset, i
 #endif /*__native_client_codegen__*/
 #elif defined(TARGET_AMD64)
 #if defined(__default_codegen__)
-               if (acfg->use_bin_writer) {
-                       emit_byte (acfg, '\xff');
-                       emit_byte (acfg, '\x25');
-                       emit_symbol_diff (acfg, got_symbol, ".", offset - 4);
-               } else {
-                       emit_unset_mode (acfg);
-                       fprintf (acfg->fp, "jmp *%s+%d(%%rip)\n", got_symbol, offset);
-               }
+               emit_unset_mode (acfg);
+               fprintf (acfg->fp, "jmp *%s+%d(%%rip)\n", got_symbol, offset);
                /* Used by mono_aot_get_plt_info_offset */
                emit_int32 (acfg, info_offset);
                acfg->stats.plt_size += 10;
@@ -1145,7 +1116,6 @@ arch_emit_plt_entry (MonoAotCompile *acfg, const char *got_symbol, int offset, i
                arm64_emit_plt_entry (acfg, got_symbol, offset, info_offset);
 #elif defined(TARGET_POWERPC)
                /* The GOT address is guaranteed to be in r30 by OP_LOAD_GOTADDR */
-               g_assert (!acfg->use_bin_writer);
                emit_unset_mode (acfg);
                fprintf (acfg->fp, "lis 11, %d@h\n", offset);
                fprintf (acfg->fp, "ori 11, 11, %d@l\n", offset);
@@ -1571,8 +1541,6 @@ arch_emit_specific_trampoline (MonoAotCompile *acfg, int offset, int *tramp_size
        *tramp_size = 4;
        code = buf;
 
-       g_assert (!acfg->use_bin_writer);
-
        /*
         * PPC has no ip relative addressing, so we need to compute the address
         * of the mscorlib got. That is slow and complex, so instead, we store it
@@ -1696,28 +1664,15 @@ arch_emit_unbox_trampoline (MonoAotCompile *acfg, MonoCompile *cfg, MonoMethod *
 
        emit_bytes (acfg, buf, code - buf);
        /* jump to method */
-       if (acfg->use_bin_writer) {
-               guint8 buf [4];
-               guint8 *code;
-
-               code = buf;
-               ARM_B (code, 0);
-
-               mono_img_writer_emit_reloc (acfg->w, R_ARM_JUMP24, call_target, -8);
-               emit_bytes (acfg, buf, 4);
-       } else {
-               if (acfg->thumb_mixed && cfg->compile_llvm)
-                       fprintf (acfg->fp, "\n\tbx %s\n", call_target);
-               else
-                       fprintf (acfg->fp, "\n\tb %s\n", call_target);
-       }
+       if (acfg->thumb_mixed && cfg->compile_llvm)
+               fprintf (acfg->fp, "\n\tbx %s\n", call_target);
+       else
+               fprintf (acfg->fp, "\n\tb %s\n", call_target);
 #elif defined(TARGET_ARM64)
        arm64_emit_unbox_trampoline (acfg, cfg, method, call_target);
 #elif defined(TARGET_POWERPC)
        int this_pos = 3;
 
-       g_assert (!acfg->use_bin_writer);
-
        fprintf (acfg->fp, "\n\taddi %d, %d, %d\n", this_pos, this_pos, (int)sizeof (MonoObject));
        fprintf (acfg->fp, "\n\tb %s\n", call_target);
 #else
@@ -1813,8 +1768,6 @@ arch_emit_static_rgctx_trampoline (MonoAotCompile *acfg, int offset, int *tramp_
        *tramp_size = 4;
        code = buf;
 
-       g_assert (!acfg->use_bin_writer);
-
        /*
         * PPC has no ip relative addressing, so we need to compute the address
         * of the mscorlib got. That is slow and complex, so instead, we store it
@@ -2240,73 +2193,6 @@ arch_emit_gsharedvt_arg_trampoline (MonoAotCompile *acfg, int offset, int *tramp
 #endif
 }      
 
-static void
-arch_emit_autoreg (MonoAotCompile *acfg, char *symbol)
-{
-#if defined(TARGET_POWERPC) && defined(__mono_ilp32__)
-       /* Based on code generated by gcc */
-       emit_unset_mode (acfg);
-
-       fprintf (acfg->fp,
-#if defined(_MSC_VER) || defined(MONO_CROSS_COMPILE) 
-                        ".section      .ctors,\"aw\",@progbits\n"
-                        ".align 2\n"
-                        ".globl        %s\n"
-                        ".long %s\n"
-                        ".section      .opd,\"aw\"\n"
-                        ".align 2\n"
-                        "%s:\n"
-                        ".long .%s,.TOC.@tocbase32\n"
-                        ".size %s,.-%s\n"
-                        ".section .text\n"
-                        ".type .%s,@function\n"
-                        ".align 2\n"
-                        ".%s:\n", symbol, symbol, symbol, symbol, symbol, symbol, symbol, symbol);
-#else
-                        ".section      .ctors,\"aw\",@progbits\n"
-                        ".align 2\n"
-                        ".globl        %1$s\n"
-                        ".long %1$s\n"
-                        ".section      .opd,\"aw\"\n"
-                        ".align 2\n"
-                        "%1$s:\n"
-                        ".long .%1$s,.TOC.@tocbase32\n"
-                        ".size %1$s,.-%1$s\n"
-                        ".section .text\n"
-                        ".type .%1$s,@function\n"
-                        ".align 2\n"
-                        ".%1$s:\n", symbol);
-#endif
-
-
-       fprintf (acfg->fp,
-                        "stdu 1,-128(1)\n"
-                        "mflr 0\n"
-                        "std 31,120(1)\n"
-                        "std 0,144(1)\n"
-
-                        ".Lautoreg:\n"
-                        "lis 3, .Lglobals@h\n"
-                        "ori 3, 3, .Lglobals@l\n"
-                        "bl .mono_aot_register_module\n"
-                        "ld 11,0(1)\n"
-                        "ld 0,16(11)\n"
-                        "mtlr 0\n"
-                        "ld 31,-8(11)\n"
-                        "mr 1,11\n"
-                        "blr\n"
-                        );
-#if defined(_MSC_VER) || defined(MONO_CROSS_COMPILE) 
-               fprintf (acfg->fp,
-                        ".size .%s,.-.%s\n", symbol, symbol);
-#else
-       fprintf (acfg->fp,
-                        ".size .%1$s,.-.%1$s\n", symbol);
-#endif
-#else
-#endif
-}
-
 /* END OF ARCH SPECIFIC CODE */
 
 static guint32
@@ -2632,20 +2518,9 @@ encode_klass_ref_inner (MonoAotCompile *acfg, MonoClass *klass, guint8 *buf, gui
                } else {
                        encode_value (par->gshared_constraint ? 1 : 0, p, &p);
                        if (par->gshared_constraint) {
-                               const char *name;
-
+                               MonoGSharedGenericParam *gpar = (MonoGSharedGenericParam*)par;
                                encode_type (acfg, par->gshared_constraint, p, &p);
-
-                               name = mono_generic_param_name (par);
-                               if (name) {
-                                       int len = strlen (name);
-
-                                       encode_value (len, p, &p);
-                                       memcpy (p, name, len);
-                                       p += len;
-                               } else {
-                                       encode_value (0, p, &p);
-                               }
+                               encode_klass_ref (acfg, mono_class_from_generic_parameter (gpar->parent, NULL, klass->byval_arg.type == MONO_TYPE_MVAR), p, &p);
                        }
                }
        } else if (klass->byval_arg.type == MONO_TYPE_PTR) {
@@ -3022,6 +2897,7 @@ encode_method_ref (MonoAotCompile *acfg, MonoMethod *method, guint8 *buf, guint8
 
                        g_assert (info);
                        encode_value (info->subtype, p, &p);
+                       encode_value (info->d.runtime_invoke.pass_rgctx, p, &p);
                        if (info->subtype == WRAPPER_SUBTYPE_RUNTIME_INVOKE_DIRECT || info->subtype == WRAPPER_SUBTYPE_RUNTIME_INVOKE_VIRTUAL)
                                encode_method_ref (acfg, info->d.runtime_invoke.method, p, &p);
                        else if (info->subtype == WRAPPER_SUBTYPE_RUNTIME_INVOKE_NORMAL)
@@ -3430,7 +3306,13 @@ get_runtime_invoke_sig (MonoMethodSignature *sig)
 
        mb = mono_mb_new (mono_defaults.object_class, "FOO", MONO_WRAPPER_NONE);
        m = mono_mb_create_method (mb, sig, 16);
-       return mono_marshal_get_runtime_invoke (m, FALSE);
+       return mono_marshal_get_runtime_invoke (m, FALSE, FALSE);
+}
+
+static MonoMethod*
+get_runtime_invoke (MonoAotCompile *acfg, MonoMethod *method, gboolean virtual)
+{
+       return mono_marshal_get_runtime_invoke (method, virtual, acfg->aot_opts.llvm_only && mono_method_needs_static_rgctx_invoke (method, TRUE));
 }
 
 static gboolean
@@ -3609,7 +3491,7 @@ add_wrappers (MonoAotCompile *acfg)
                                        has_nullable = TRUE;
                        }
 
-                       if (info && !has_nullable) {
+                       if (info && !has_nullable && !acfg->aot_opts.llvm_only) {
                                /* Supported by the dynamic runtime-invoke wrapper */
                                skip = TRUE;
                        }
@@ -3620,7 +3502,7 @@ add_wrappers (MonoAotCompile *acfg)
 
                if (!skip) {
                        //printf ("%s\n", mono_method_full_name (method, TRUE));
-                       add_method (acfg, mono_marshal_get_runtime_invoke (method, FALSE));
+                       add_method (acfg, get_runtime_invoke (acfg, method, FALSE));
                }
        }
 
@@ -3679,15 +3561,16 @@ add_wrappers (MonoAotCompile *acfg)
                add_method (acfg, get_runtime_invoke_sig (csig));
 
                /* runtime-invoke used by finalizers */
-               add_method (acfg, mono_marshal_get_runtime_invoke (mono_class_get_method_from_name_flags (mono_defaults.object_class, "Finalize", 0, 0), TRUE));
+               add_method (acfg, get_runtime_invoke (acfg, mono_class_get_method_from_name_flags (mono_defaults.object_class, "Finalize", 0, 0), TRUE));
 
                /* This is used by mono_runtime_capture_context () */
                method = mono_get_context_capture_method ();
                if (method)
-                       add_method (acfg, mono_marshal_get_runtime_invoke (method, FALSE));
+                       add_method (acfg, get_runtime_invoke (acfg, method, FALSE));
 
 #ifdef MONO_ARCH_DYN_CALL_SUPPORTED
-               add_method (acfg, mono_marshal_get_runtime_invoke_dynamic ());
+               if (!acfg->aot_opts.llvm_only)
+                       add_method (acfg, mono_marshal_get_runtime_invoke_dynamic ());
 #endif
 
                /* stelemref */
@@ -3883,13 +3766,13 @@ add_wrappers (MonoAotCompile *acfg)
                        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));
+                       add_extra_method (acfg, get_runtime_invoke (acfg, 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));
+                       add_extra_method (acfg, get_runtime_invoke (acfg, wrapper, FALSE));
                }
        }
 
@@ -5326,6 +5209,9 @@ encode_patch (MonoAotCompile *acfg, MonoJumpInfo *patch_info, guint8 *buf, guint
        case MONO_PATCH_INFO_METHOD_CODE_SLOT:
                encode_method_ref (acfg, patch_info->data.method, p, &p);
                break;
+       case MONO_PATCH_INFO_AOT_JIT_INFO:
+               encode_value (patch_info->data.index, p, &p);
+               break;
        case MONO_PATCH_INFO_INTERNAL_METHOD:
        case MONO_PATCH_INFO_JIT_ICALL_ADDR: {
                guint32 len = strlen (patch_info->data.name);
@@ -5386,7 +5272,7 @@ encode_patch (MonoAotCompile *acfg, MonoJumpInfo *patch_info, guint8 *buf, guint
                } else {
                        encode_value (0, p, &p);
                }
-               encode_value (patch_info->data.del_tramp->virtual, p, &p);
+               encode_value (patch_info->data.del_tramp->is_virtual, p, &p);
                break;
        case MONO_PATCH_INFO_FIELD:
        case MONO_PATCH_INFO_SFLDA:
@@ -5394,7 +5280,8 @@ encode_patch (MonoAotCompile *acfg, MonoJumpInfo *patch_info, guint8 *buf, guint
                break;
        case MONO_PATCH_INFO_INTERRUPTION_REQUEST_FLAG:
                break;
-       case MONO_PATCH_INFO_RGCTX_FETCH: {
+       case MONO_PATCH_INFO_RGCTX_FETCH:
+       case MONO_PATCH_INFO_RGCTX_SLOT_INDEX: {
                MonoJumpInfoRgctxEntry *entry = patch_info->data.rgctx_entry;
                guint32 offset;
                guint8 *buf2, *p2;
@@ -5427,6 +5314,7 @@ encode_patch (MonoAotCompile *acfg, MonoJumpInfo *patch_info, guint8 *buf, guint
                break;
        }
        case MONO_PATCH_INFO_SEQ_POINT_INFO:
+       case MONO_PATCH_INFO_AOT_MODULE:
                break;
        case MONO_PATCH_INFO_LLVM_IMT_TRAMPOLINE:
                encode_method_ref (acfg, patch_info->data.imt_tramp->method, p, &p);
@@ -5568,13 +5456,14 @@ emit_method_info (MonoAotCompile *acfg, MonoCompile *cfg)
                }
 
                if (patch_info->type == MONO_PATCH_INFO_GC_CARD_TABLE_ADDR ||
-                               patch_info->type == MONO_PATCH_INFO_GC_NURSERY_START) {
+                       patch_info->type == MONO_PATCH_INFO_GC_NURSERY_START ||
+                       patch_info->type == MONO_PATCH_INFO_AOT_MODULE) {
                        /* Stored in a GOT slot initialized at module load time */
                        patch_info->type = MONO_PATCH_INFO_NONE;
                        continue;
                }
 
-               if (is_plt_patch (patch_info)) {
+               if (is_plt_patch (patch_info) && !(cfg->compile_llvm && acfg->aot_opts.llvm_only)) {
                        /* Calls are made through the PLT */
                        patch_info->type = MONO_PATCH_INFO_NONE;
                        continue;
@@ -5717,6 +5606,12 @@ emit_exception_debug_info (MonoAotCompile *acfg, MonoCompile *cfg, gboolean stor
                                encode_value (0, p, &p);
                        }
 
+                       /* Emit the IL ranges too, since they might not be available at runtime */
+                       encode_value (clause->try_offset, p, &p);
+                       encode_value (clause->try_len, p, &p);
+                       encode_value (clause->handler_offset, p, &p);
+                       encode_value (clause->handler_len, p, &p);
+
                        /* Emit a list of nesting clauses */
                        for (i = 0; i < header->num_clauses; ++i) {
                                gint32 cindex1 = k;
@@ -6013,15 +5908,18 @@ get_plt_entry_debug_sym (MonoAotCompile *acfg, MonoJumpInfo *ji, GHashTable *cac
 static void
 emit_plt (MonoAotCompile *acfg)
 {
-       char symbol [128];
        int i;
 
+       if (acfg->aot_opts.llvm_only) {
+               g_assert (acfg->plt_offset == 1);
+               return;
+       }
+
        emit_line (acfg);
-       sprintf (symbol, "plt");
 
        emit_section_change (acfg, ".text", 0);
        emit_alignment_code (acfg, NACL_SIZE(16, kNaClAlignment));
-       emit_info_symbol (acfg, symbol);
+       emit_info_symbol (acfg, "plt");
        emit_label (acfg, acfg->plt_symbol);
 
        for (i = 0; i < acfg->plt_offset; ++i) {
@@ -6125,8 +6023,7 @@ emit_plt (MonoAotCompile *acfg)
 
        emit_symbol_size (acfg, acfg->plt_symbol, ".");
 
-       sprintf (symbol, "plt_end");
-       emit_info_symbol (acfg, symbol);
+       emit_info_symbol (acfg, "plt_end");
 }
 
 /*
@@ -6259,7 +6156,7 @@ emit_trampolines (MonoAotCompile *acfg)
        int tramp_type;
 #endif
 
-       if (!mono_aot_mode_is_full (&acfg->aot_opts))
+       if (!mono_aot_mode_is_full (&acfg->aot_opts) || acfg->aot_opts.llvm_only)
                return;
        
        g_assert (acfg->image->assembly);
@@ -6700,8 +6597,6 @@ mono_aot_parse_options (const char *aot_options, MonoAotOptions *opts)
                        opts->nimt_trampolines = atoi (arg + strlen ("nimt-trampolines="));
                } else if (str_begins_with (arg, "ngsharedvt-trampolines=")) {
                        opts->ngsharedvt_arg_trampolines = atoi (arg + strlen ("ngsharedvt-trampolines="));
-               } else if (str_begins_with (arg, "autoreg")) {
-                       opts->autoreg = TRUE;
                } else if (str_begins_with (arg, "tool-prefix=")) {
                        opts->tool_prefix = g_strdup (arg + strlen ("tool-prefix="));
                } else if (str_begins_with (arg, "ld-flags=")) {
@@ -6745,7 +6640,11 @@ mono_aot_parse_options (const char *aot_options, MonoAotOptions *opts)
                } else if (str_begins_with (arg, "gc-maps")) {
                        mini_gc_enable_gc_maps_for_aot ();
                } else if (str_begins_with (arg, "dump")) {
-                       opts->dump_json = TRUE;                 
+                       opts->dump_json = TRUE;
+               } else if (str_begins_with (arg, "llvmonly")) {
+                       opts->mode = MONO_AOT_MODE_FULL;
+                       opts->llvm = TRUE;
+                       opts->llvm_only = TRUE;
                } else if (str_begins_with (arg, "help") || str_begins_with (arg, "?")) {
                        printf ("Supported options for --aot:\n");
                        printf ("    outfile=\n");
@@ -6768,7 +6667,6 @@ mono_aot_parse_options (const char *aot_options, MonoAotOptions *opts)
                        printf ("    nrgctx-trampolines=\n");
                        printf ("    nimt-trampolines=\n");
                        printf ("    ngsharedvt-trampolines=\n");
-                       printf ("    autoreg\n");
                        printf ("    tool-prefix=\n");
                        printf ("    readonly-value=\n");
                        printf ("    soft-debug\n");
@@ -6904,7 +6802,8 @@ can_encode_patch (MonoAotCompile *acfg, MonoJumpInfo *patch_info)
                }
                break;
        }
-       case MONO_PATCH_INFO_RGCTX_FETCH: {
+       case MONO_PATCH_INFO_RGCTX_FETCH:
+       case MONO_PATCH_INFO_RGCTX_SLOT_INDEX: {
                MonoJumpInfoRgctxEntry *entry = patch_info->data.rgctx_entry;
 
                if (!can_encode_method (acfg, entry->method))
@@ -6984,6 +6883,8 @@ compile_method (MonoAotCompile *acfg, MonoMethod *method)
                flags |= JIT_FLAG_FULL_AOT;
        if (acfg->llvm)
                flags |= JIT_FLAG_LLVM;
+       if (acfg->aot_opts.llvm_only)
+               flags |= JIT_FLAG_LLVM_ONLY | JIT_FLAG_EXPLICIT_NULL_CHECKS;
        if (acfg->aot_opts.no_direct_calls)
                flags |= JIT_FLAG_NO_DIRECT_ICALLS;
        cfg = mini_method_compile (method, acfg->opts, mono_get_root_domain (), flags, 0, index);
@@ -7094,10 +6995,11 @@ compile_method (MonoAotCompile *acfg, MonoMethod *method)
                for (patch_info = cfg->patch_info; patch_info; patch_info = patch_info->next) {
                        switch (patch_info->type) {
                        case MONO_PATCH_INFO_RGCTX_FETCH:
+                       case MONO_PATCH_INFO_RGCTX_SLOT_INDEX:
                        case MONO_PATCH_INFO_METHOD: {
                                MonoMethod *m = NULL;
 
-                               if (patch_info->type == MONO_PATCH_INFO_RGCTX_FETCH) {
+                               if (patch_info->type == MONO_PATCH_INFO_RGCTX_FETCH || patch_info->type == MONO_PATCH_INFO_RGCTX_SLOT_INDEX) {
                                        MonoJumpInfoRgctxEntry *e = patch_info->data.rgctx_entry;
 
                                        if (e->info_type == MONO_RGCTX_INFO_GENERIC_METHOD_CODE)
@@ -7165,7 +7067,7 @@ compile_method (MonoAotCompile *acfg, MonoMethod *method)
                                cfg->has_got_slots = TRUE;
                        break;
                default:
-                       if (!is_plt_patch (patch_info))
+                       if (!is_plt_patch (patch_info) || (cfg->compile_llvm && acfg->aot_opts.llvm_only))
                                cfg->has_got_slots = TRUE;
                        break;
                }
@@ -7378,6 +7280,18 @@ mono_aot_get_got_offset (MonoJumpInfo *ji)
        return get_got_offset (llvm_acfg, TRUE, ji);
 }
 
+/*
+ * mono_aot_is_shared_got_offset:
+ *
+ *   Return whenever OFFSET refers to a GOT slot which is preinitialized
+ * when the AOT image is loaded.
+ */
+gboolean
+mono_aot_is_shared_got_offset (int offset)
+{
+       return offset < llvm_acfg->nshared_got_entries;
+}
+
 char*
 mono_aot_get_method_name (MonoCompile *cfg)
 {
@@ -7403,6 +7317,26 @@ mono_aot_mark_unused_llvm_plt_entry (MonoJumpInfo *patch_info)
        plt_entry->llvm_used = FALSE;
 }
 
+char*
+mono_aot_get_direct_call_symbol (MonoJumpInfoType type, gconstpointer data)
+{
+       const char *sym = NULL;
+
+       if (llvm_acfg->aot_opts.direct_icalls) {
+               if (type == MONO_PATCH_INFO_JIT_ICALL_ADDR) {
+                       /* Call to a C function implementing a jit icall */
+                       sym = mono_lookup_jit_icall_symbol (data);
+               } else if (type == MONO_PATCH_INFO_ICALL_ADDR) {
+                       MonoMethod *method = (gpointer)data;
+                       if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
+                               sym = mono_lookup_icall_symbol (method);
+               }
+               if (sym)
+                       return g_strdup (sym);
+       }
+       return NULL;
+}
+
 char*
 mono_aot_get_plt_symbol (MonoJumpInfoType type, gconstpointer data)
 {
@@ -7497,10 +7431,30 @@ emit_llvm_file (MonoAotCompile *acfg)
 {
        char *command, *opts, *tempbc, *output_fname;
 
+       /* Emit the LLVM code into a .bc file */
+       if (acfg->aot_opts.llvm_only && acfg->aot_opts.asm_only) {
+               mono_llvm_emit_aot_module (acfg->aot_opts.llvm_outfile, g_path_get_basename (acfg->image->name));
+               return TRUE;
+       }
+
        tempbc = g_strdup_printf ("%s.bc", acfg->tmpbasename);
        mono_llvm_emit_aot_module (tempbc, g_path_get_basename (acfg->image->name));
        g_free (tempbc);
 
+       if (acfg->aot_opts.llvm_only) {
+               /* Use the stock clang from xcode */
+               // FIXME: arch
+               // FIXME: -O2
+               // FIXME: llc/opt flags
+               command = g_strdup_printf ("clang -march=x86-64 -fpic -msse -msse2 -msse3 -msse4 -O0 -c -o \"%s\" \"%s.bc\"", acfg->llvm_ofile, acfg->tmpbasename);
+               //command = g_strdup_printf ("/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang  -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS8.3.sdk -Qunused-arguments -miphoneos-version-min=8.2 -arch arm64 -fpic -O0 -c -o \"%s\" \"%s.bc\"", acfg->llvm_ofile, acfg->tmpbasename);
+
+               aot_printf (acfg, "Executing clang: %s\n", command);
+               if (execute_system (command) != 0)
+                       return FALSE;
+               return TRUE;
+       }
+
        /*
         * FIXME: Experiment with adding optimizations, the -std-compile-opts set takes
         * a lot of time, and doesn't seem to save much space.
@@ -7516,7 +7470,6 @@ emit_llvm_file (MonoAotCompile *acfg)
         * 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 -domtree -verify");
        /* The dse pass is disabled because of #13734 and #17616 */
        /*
@@ -7530,6 +7483,7 @@ emit_llvm_file (MonoAotCompile *acfg)
         * 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 -inline-cost -inline -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");
+       opts = g_strdup ("");
 #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);
        aot_printf (acfg, "Executing opt: %s\n", command);
@@ -7544,11 +7498,11 @@ emit_llvm_file (MonoAotCompile *acfg)
        /* Verbose asm slows down llc greatly */
        g_string_append (acfg->llc_args, " -asm-verbose=false");
 
-       g_string_append (acfg->llc_args, " -disable-gnu-eh-frame -enable-mono-eh-frame");
-
        if (acfg->aot_opts.mtriple)
                g_string_append_printf (acfg->llc_args, " -mtriple=%s", acfg->aot_opts.mtriple);
 
+       g_string_append (acfg->llc_args, " -disable-gnu-eh-frame -enable-mono-eh-frame");
+
        g_string_append_printf (acfg->llc_args, " -mono-eh-frame-symbol=%s%s", acfg->user_symbol_prefix, acfg->llvm_eh_frame_symbol);
 
 #if defined(TARGET_MACH) && defined(TARGET_ARM)
@@ -7586,6 +7540,9 @@ emit_code (MonoAotCompile *acfg)
        gboolean saved_unbox_info = FALSE;
        char symbol [256];
 
+       if (acfg->aot_opts.llvm_only)
+               return;
+
 #if defined(TARGET_POWERPC64)
        sprintf (symbol, ".Lgot_addr");
        emit_section_change (acfg, ".text", 0);
@@ -7632,7 +7589,7 @@ emit_code (MonoAotCompile *acfg)
                method = cfg->orig_method;
 
                /* Emit unbox trampoline */
-               if (mono_aot_mode_is_full (&acfg->aot_opts) && cfg->orig_method->klass->valuetype) {
+               if (mono_aot_mode_is_full (&acfg->aot_opts) && cfg->orig_method->klass->valuetype && !(acfg->aot_opts.llvm_only && cfg->compile_llvm)) {
                        sprintf (symbol, "ut_%d", get_method_index (acfg, method));
 
                        emit_section_change (acfg, ".text", 0);
@@ -7715,10 +7672,15 @@ emit_code (MonoAotCompile *acfg)
 #ifdef MONO_ARCH_AOT_SUPPORTED
                int call_size;
 
-               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
+               if (acfg->cfgs [i]) {
+                       if (acfg->aot_opts.llvm_only && acfg->cfgs [i]->compile_llvm)
+                               /* Obtained by calling a generated function in the LLVM image */
+                               arch_emit_direct_call (acfg, "method_addresses", FALSE, FALSE, NULL, &call_size);
+                       else
+                               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
        }
 
@@ -7744,7 +7706,7 @@ emit_code (MonoAotCompile *acfg)
 
                method = cfg->orig_method;
 
-               if (mono_aot_mode_is_full (&acfg->aot_opts) && cfg->orig_method->klass->valuetype) {
+               if (mono_aot_mode_is_full (&acfg->aot_opts) && cfg->orig_method->klass->valuetype && !(acfg->aot_opts.llvm_only && cfg->compile_llvm)) {
                        index = get_method_index (acfg, method);
 
                        emit_int32 (acfg, index);
@@ -7774,7 +7736,7 @@ emit_code (MonoAotCompile *acfg)
 
                method = cfg->orig_method;
 
-               if (mono_aot_mode_is_full (&acfg->aot_opts) && cfg->orig_method->klass->valuetype) {
+               if (mono_aot_mode_is_full (&acfg->aot_opts) && cfg->orig_method->klass->valuetype && !(acfg->aot_opts.llvm_only && cfg->compile_llvm)) {
 #ifdef MONO_ARCH_AOT_SUPPORTED
                        int call_size;
 
@@ -8212,6 +8174,11 @@ emit_unwind_info (MonoAotCompile *acfg)
        int i;
        char symbol [128];
 
+       if (acfg->aot_opts.llvm_only) {
+               g_assert (acfg->unwind_ops->len == 0);
+               return;
+       }
+
        /* 
         * The unwind info contains a lot of duplicates so we emit each unique
         * entry once, and only store the offset from the start of the table in the
@@ -8474,6 +8441,9 @@ emit_got (MonoAotCompile *acfg)
 {
        char symbol [256];
 
+       if (acfg->aot_opts.llvm_only)
+               return;
+
        /* Don't make GOT global so accesses to it don't need relocations */
        sprintf (symbol, "%s", acfg->got_symbol);
 
@@ -8613,30 +8583,14 @@ emit_globals (MonoAotCompile *acfg)
        emit_int32 (acfg, 0);
 }
 
-static void
-emit_autoreg (MonoAotCompile *acfg)
-{
-       char *symbol;
-
-       /*
-        * Emit a function into the .ctor section which will be called by the ELF
-        * loader to register this module with the runtime.
-        */
-       if (! (!acfg->use_bin_writer && acfg->aot_opts.static_link && acfg->aot_opts.autoreg))
-               return;
-
-       symbol = g_strdup_printf ("_%s_autoreg", acfg->static_linking_symbol);
-
-       arch_emit_autoreg (acfg, symbol);
-
-       g_free (symbol);
-}      
-
 static void
 emit_mem_end (MonoAotCompile *acfg)
 {
        char symbol [128];
 
+       if (acfg->aot_opts.llvm_only)
+               return;
+
        sprintf (symbol, "mem_end");
        emit_section_change (acfg, ".text", 1);
        emit_alignment_code (acfg, 8);
@@ -8669,6 +8623,7 @@ init_aot_file_info (MonoAotCompile *acfg, MonoAotFileInfo *info, int gc_name_off
        info->long_align = MONO_ABI_ALIGNOF (gint64);
        info->generic_tramp_num = MONO_TRAMPOLINE_NUM;
        info->tramp_page_size = acfg->tramp_page_size;
+       info->nshared_got_entries = acfg->nshared_got_entries;
        for (i = 0; i < MONO_AOT_TRAMP_NUM; ++i)
                info->tramp_page_code_offsets [i] = acfg->tramp_page_code_offsets [i];
 }
@@ -8690,9 +8645,19 @@ emit_aot_file_info (MonoAotCompile *acfg, MonoAotFileInfo *info)
                symbols [sindex ++] = NULL;
                symbols [sindex ++] = NULL;
        }
-       symbols [sindex ++] = "jit_code_start";
-       symbols [sindex ++] = "jit_code_end";
-       symbols [sindex ++] = "method_addresses";
+       /* llvm_get_method */
+       symbols [sindex ++] = NULL;
+       /* llvm_get_unbox_tramp */
+       symbols [sindex ++] = NULL;
+       if (!acfg->aot_opts.llvm_only) {
+               symbols [sindex ++] = "jit_code_start";
+               symbols [sindex ++] = "jit_code_end";
+               symbols [sindex ++] = "method_addresses";
+       } else {
+               symbols [sindex ++] = NULL;
+               symbols [sindex ++] = NULL;
+               symbols [sindex ++] = NULL;
+       }
        symbols [sindex ++] = "blob";
        symbols [sindex ++] = "class_name_table";
        symbols [sindex ++] = "class_info_offsets";
@@ -8729,9 +8694,16 @@ emit_aot_file_info (MonoAotCompile *acfg, MonoAotFileInfo *info)
        symbols [sindex ++] = "plt";
        symbols [sindex ++] = "plt_end";
        symbols [sindex ++] = "unwind_info";
-       symbols [sindex ++] = "unbox_trampolines";
-       symbols [sindex ++] = "unbox_trampolines_end";
-       symbols [sindex ++] = "unbox_trampoline_addresses";
+       if (!acfg->aot_opts.llvm_only) {
+               symbols [sindex ++] = "unbox_trampolines";
+               symbols [sindex ++] = "unbox_trampolines_end";
+               symbols [sindex ++] = "unbox_trampoline_addresses";
+       } else {
+               symbols [sindex ++] = NULL;
+               symbols [sindex ++] = NULL;
+               symbols [sindex ++] = NULL;
+       }
+
        g_assert (sindex == MONO_AOT_FILE_INFO_NUM_SYMBOLS);
 
        sprintf (symbol, "%smono_aot_file_info", acfg->user_symbol_prefix);
@@ -8767,6 +8739,7 @@ emit_aot_file_info (MonoAotCompile *acfg, MonoAotFileInfo *info)
        emit_int32 (acfg, info->long_align);
        emit_int32 (acfg, info->generic_tramp_num);
        emit_int32 (acfg, info->tramp_page_size);
+       emit_int32 (acfg, info->nshared_got_entries);
 
        for (i = 0; i < MONO_AOT_TRAMP_NUM; ++i)
                emit_int32 (acfg, info->num_trampolines [i]);
@@ -9186,6 +9159,9 @@ compile_asm (MonoAotCompile *acfg)
        /* replace the ; flags separators with spaces */
        g_strdelimit (ld_flags, ";", ' ');
 
+       if (acfg->aot_opts.llvm_only)
+               ld_flags = g_strdup_printf ("%s %s", ld_flags, "-lstdc++");
+
 #ifdef LD_NAME
        command = g_strdup_printf ("%s -o \"%s\" %s \"%s.o\" %s", LD_NAME, tmp_outfile_name, llvm_ofile, acfg->tmpfname, ld_flags);
 #else
@@ -9507,6 +9483,68 @@ static void aot_dump (MonoAotCompile *acfg)
        mono_json_writer_destroy (&writer);
 }
 
+static const char *preinited_jit_icalls[] = {
+       "mono_aot_init_llvm_method",
+       "mono_aot_init_gshared_method_this",
+       "mono_aot_init_gshared_method_rgctx",
+       "mono_llvm_throw_corlib_exception",
+       "mono_resolve_vcall",
+       "mono_helper_ldstr_mscorlib"
+};
+
+static void
+add_preinit_got_slots (MonoAotCompile *acfg)
+{
+       MonoJumpInfo *ji;
+       int i;
+
+       /*
+        * Allocate the first few GOT entries to information which is needed frequently, or it is needed
+        * during method initialization etc.
+        */
+
+       ji = mono_mempool_alloc0 (acfg->mempool, sizeof (MonoJumpInfo));
+       ji->type = MONO_PATCH_INFO_IMAGE;
+       ji->data.image = acfg->image;
+       get_got_offset (acfg, FALSE, ji);
+       get_got_offset (acfg, TRUE, ji);
+
+       ji = mono_mempool_alloc0 (acfg->mempool, sizeof (MonoJumpInfo));
+       ji->type = MONO_PATCH_INFO_MSCORLIB_GOT_ADDR;
+       get_got_offset (acfg, FALSE, ji);
+       get_got_offset (acfg, TRUE, ji);
+
+       ji = mono_mempool_alloc0 (acfg->mempool, sizeof (MonoJumpInfo));
+       ji->type = MONO_PATCH_INFO_GC_CARD_TABLE_ADDR;
+       get_got_offset (acfg, FALSE, ji);
+       get_got_offset (acfg, TRUE, ji);
+
+       ji = mono_mempool_alloc0 (acfg->mempool, sizeof (MonoJumpInfo));
+       ji->type = MONO_PATCH_INFO_GC_NURSERY_START;
+       get_got_offset (acfg, FALSE, ji);
+       get_got_offset (acfg, TRUE, ji);
+
+       ji = mono_mempool_alloc0 (acfg->mempool, sizeof (MonoJumpInfo));
+       ji->type = MONO_PATCH_INFO_JIT_TLS_ID;
+       get_got_offset (acfg, FALSE, ji);
+       get_got_offset (acfg, TRUE, ji);
+
+       ji = mono_mempool_alloc0 (acfg->mempool, sizeof (MonoJumpInfo));
+       ji->type = MONO_PATCH_INFO_AOT_MODULE;
+       get_got_offset (acfg, FALSE, ji);
+       get_got_offset (acfg, TRUE, ji);
+
+       for (i = 0; i < sizeof (preinited_jit_icalls) / sizeof (char*); ++i) {
+               ji = mono_mempool_alloc0 (acfg->mempool, sizeof (MonoAotCompile));
+               ji->type = MONO_PATCH_INFO_INTERNAL_METHOD;
+               ji->data.name = preinited_jit_icalls [i];
+               get_got_offset (acfg, FALSE, ji);
+               get_got_offset (acfg, TRUE, ji);
+       }
+
+       acfg->nshared_got_entries = acfg->got_offset;
+}
+
 int
 mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options)
 {
@@ -9540,9 +9578,6 @@ mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options)
                acfg->logfile = fopen (acfg->aot_opts.logfile, "a+");
        }
 
-       if (acfg->aot_opts.static_link)
-               acfg->aot_opts.autoreg = TRUE;
-
        //acfg->aot_opts.print_skipped_methods = TRUE;
 
 #if !defined(MONO_ARCH_GSHAREDVT_SUPPORTED) || !defined(ENABLE_GSHAREDVT)
@@ -9616,6 +9651,9 @@ mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options)
        if (mono_aot_mode_is_full (&acfg->aot_opts))
                acfg->flags |= MONO_AOT_FILE_FLAG_FULL_AOT;
 
+       if (mono_threads_is_coop_enabled ())
+               acfg->flags |= MONO_AOT_FILE_FLAG_SAFEPOINTS;
+
        if (acfg->aot_opts.instances_logfile_path) {
                acfg->instances_logfile = fopen (acfg->aot_opts.instances_logfile_path, "w");
                if (!acfg->instances_logfile) {
@@ -9642,6 +9680,8 @@ mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options)
 
        if (acfg->llvm && acfg->thumb_mixed)
                acfg->flags |= MONO_AOT_FILE_FLAG_LLVM_THUMB;
+       if (acfg->aot_opts.llvm_only)
+               acfg->flags |= MONO_AOT_FILE_FLAG_LLVM_ONLY;
 
        acfg->assembly_name_sym = g_strdup (acfg->image->assembly->aname.name);
        /* Get rid of characters which cannot occur in symbols */
@@ -9672,48 +9712,15 @@ mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options)
 
        /* PLT offset 0 is reserved for the PLT trampoline */
        acfg->plt_offset = 1;
+       add_preinit_got_slots (acfg);
 
 #ifdef ENABLE_LLVM
        if (acfg->llvm) {
                llvm_acfg = acfg;
-               mono_llvm_create_aot_module (acfg->image->assembly, acfg->global_prefix, TRUE, acfg->aot_opts.static_link);
+               mono_llvm_create_aot_module (acfg->image->assembly, acfg->global_prefix, TRUE, acfg->aot_opts.static_link, acfg->aot_opts.llvm_only);
        }
 #endif
 
-       /* GOT offset 0 is reserved for the address of the current assembly */
-       {
-               MonoJumpInfo *ji;
-
-               ji = mono_mempool_alloc0 (acfg->mempool, sizeof (MonoJumpInfo));
-               ji->type = MONO_PATCH_INFO_IMAGE;
-               ji->data.image = acfg->image;
-
-               get_got_offset (acfg, FALSE, ji);
-               get_got_offset (acfg, TRUE, ji);
-
-               /* Slot 1 is reserved for the mscorlib got addr */
-               ji = mono_mempool_alloc0 (acfg->mempool, sizeof (MonoJumpInfo));
-               ji->type = MONO_PATCH_INFO_MSCORLIB_GOT_ADDR;
-               get_got_offset (acfg, FALSE, ji);
-               get_got_offset (acfg, TRUE, ji);
-
-               /* This is very common */
-               ji = mono_mempool_alloc0 (acfg->mempool, sizeof (MonoJumpInfo));
-               ji->type = MONO_PATCH_INFO_GC_CARD_TABLE_ADDR;
-               get_got_offset (acfg, FALSE, ji);
-               get_got_offset (acfg, TRUE, ji);
-
-               ji = mono_mempool_alloc0 (acfg->mempool, sizeof (MonoJumpInfo));
-               ji->type = MONO_PATCH_INFO_GC_NURSERY_START;
-               get_got_offset (acfg, FALSE, ji);
-               get_got_offset (acfg, TRUE, ji);
-
-               ji = mono_mempool_alloc0 (acfg->mempool, sizeof (MonoJumpInfo));
-               ji->type = MONO_PATCH_INFO_JIT_TLS_ID;
-               get_got_offset (acfg, FALSE, ji);
-               get_got_offset (acfg, TRUE, ji);
-       }
-
        TV_GETTIME (atv);
 
        compile_methods (acfg);
@@ -9752,46 +9759,24 @@ mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options)
        }
 #endif
 
-       if (!acfg->aot_opts.asm_only && !acfg->aot_opts.asm_writer && mono_bin_writer_supported ()) {
+       if (acfg->aot_opts.asm_only) {
                if (acfg->aot_opts.outfile)
-                       outfile_name = g_strdup_printf ("%s", acfg->aot_opts.outfile);
+                       acfg->tmpfname = g_strdup_printf ("%s", acfg->aot_opts.outfile);
                else
-                       outfile_name = g_strdup_printf ("%s%s", acfg->image->name, MONO_SOLIB_EXT);
-
-               /* 
-                * Can't use g_file_open_tmp () as it will be deleted at exit, and
-                * it might be in another file system so the rename () won't work.
-                */
-               tmp_outfile_name = g_strdup_printf ("%s.tmp", outfile_name);
-
-               acfg->fp = fopen (tmp_outfile_name, "w");
-               if (!acfg->fp) {
-                       aot_printf (acfg, "Unable to create temporary file '%s': %s\n", tmp_outfile_name, strerror (errno));
-                       return 1;
-               }
-
-               acfg->w = mono_img_writer_create (acfg->fp, TRUE);
-               acfg->use_bin_writer = TRUE;
+                       acfg->tmpfname = g_strdup_printf ("%s.s", acfg->image->name);
+               acfg->fp = fopen (acfg->tmpfname, "w+");
        } else {
-               if (acfg->aot_opts.asm_only) {
-                       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->fp = fopen (acfg->tmpfname, "w+");
-               } else {
-                       int i = g_file_open_tmp ("mono_aot_XXXXXX", &acfg->tmpfname, NULL);
-                       acfg->fp = fdopen (i, "w+");
-               }
-               if (acfg->fp == 0) {
-                       aot_printerrf (acfg, "Unable to open file '%s': %s\n", acfg->tmpfname, strerror (errno));
-                       return 1;
-               }
-               acfg->w = mono_img_writer_create (acfg->fp, FALSE);
-               
-               tmp_outfile_name = NULL;
-               outfile_name = NULL;
+               int i = g_file_open_tmp ("mono_aot_XXXXXX", &acfg->tmpfname, NULL);
+               acfg->fp = fdopen (i, "w+");
        }
+       if (acfg->fp == 0) {
+               aot_printerrf (acfg, "Unable to open file '%s': %s\n", acfg->tmpfname, strerror (errno));
+               return 1;
+       }
+       acfg->w = mono_img_writer_create (acfg->fp, FALSE);
+
+       tmp_outfile_name = NULL;
+       outfile_name = NULL;
 
        /* Compute symbols for methods */
        for (i = 0; i < acfg->nmethods; ++i) {
@@ -9865,8 +9850,6 @@ mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options)
 
        emit_globals (acfg);
 
-       emit_autoreg (acfg);
-
        if (acfg->dwarf) {
                emit_dwarf_info (acfg);
                mono_dwarf_writer_close (acfg->dwarf);
@@ -9877,8 +9860,7 @@ mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options)
        if (acfg->need_pt_gnu_stack) {
                /* This is required so the .so doesn't have an executable stack */
                /* The bin writer already emits this */
-               if (!acfg->use_bin_writer)
-                       fprintf (acfg->fp, "\n.section  .note.GNU-stack,\"\",@progbits\n");
+               fprintf (acfg->fp, "\n.section  .note.GNU-stack,\"\",@progbits\n");
        }
 
 #ifdef ENABLE_LLVM
@@ -9932,19 +9914,10 @@ mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options)
                acfg_free (acfg);
                return res;
        }
-       if (acfg->use_bin_writer) {
-               int err = rename (tmp_outfile_name, outfile_name);
-
-               if (err) {
-                       aot_printf (acfg, "Unable to rename '%s' to '%s': %s\n", tmp_outfile_name, outfile_name, strerror (errno));
-                       return 1;
-               }
-       } else {
-               res = compile_asm (acfg);
-               if (res != 0) {
-                       acfg_free (acfg);
-                       return res;
-               }
+       res = compile_asm (acfg);
+       if (res != 0) {
+               acfg_free (acfg);
+               return res;
        }
        TV_GETTIME (btv);
        acfg->stats.link_time = TV_ELAPSED (atv, btv);
@@ -9984,4 +9957,10 @@ mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options)
        return 0;
 }
 
+gboolean
+mono_aot_is_shared_got_offset (int offset)
+{
+       return FALSE;
+}
+
 #endif