[aot] Fix emission of external aot data by aligning tables in the file.
[mono.git] / mono / mini / aot-compiler.c
index ca329edf7d5395d1050df3239ee6c1aa2e1a4b9a..b066a590993d1e9232d9a40b50ef299cd8d06744 100644 (file)
@@ -95,6 +95,7 @@ static ReadOnlyValue *readonly_values;
 typedef struct MonoAotOptions {
        char *outfile;
        char *llvm_outfile;
+       char *data_outfile;
        gboolean save_temps;
        gboolean write_symbols;
        gboolean metadata_only;
@@ -178,12 +179,15 @@ typedef struct MonoAotCompile {
        GHashTable *klass_blob_hash;
        /* Maps MonoMethod* -> blob offset */
        GHashTable *method_blob_hash;
+       GHashTable *gsharedvt_in_signatures;
+       GHashTable *gsharedvt_out_signatures;
        guint32 *plt_got_info_offsets;
        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;
 
+       guint32 table_offsets [MONO_AOT_TABLE_NUM];
        guint32 num_trampolines [MONO_AOT_TRAMP_NUM];
        guint32 trampoline_got_offset_base [MONO_AOT_TRAMP_NUM];
        guint32 trampoline_size [MONO_AOT_TRAMP_NUM];
@@ -228,6 +232,7 @@ typedef struct MonoAotCompile {
        gboolean has_jitted_code;
        MonoAotFileFlags flags;
        MonoDynamicStream blob;
+       gboolean blob_closed;
        MonoClass **typespec_classes;
        GString *llc_args;
        GString *as_args;
@@ -242,6 +247,9 @@ typedef struct MonoAotCompile {
        GHashTable *objc_selector_to_index;
        FILE *logfile;
        FILE *instances_logfile;
+       FILE *data_outfile;
+       int datafile_offset;
+       int gc_name_offset;
 } MonoAotCompile;
 
 typedef struct {
@@ -251,8 +259,8 @@ typedef struct {
        gboolean jit_used, llvm_used;
 } MonoPltEntry;
 
-#define mono_acfg_lock(acfg) mono_mutex_lock (&((acfg)->mutex))
-#define mono_acfg_unlock(acfg) mono_mutex_unlock (&((acfg)->mutex))
+#define mono_acfg_lock(acfg) mono_os_mutex_lock (&((acfg)->mutex))
+#define mono_acfg_unlock(acfg) mono_os_mutex_unlock (&((acfg)->mutex))
 
 /* This points to the current acfg in LLVM mode */
 static MonoAotCompile *llvm_acfg;
@@ -1858,7 +1866,7 @@ arch_emit_imt_thunk (MonoAotCompile *acfg, int offset, int *tramp_size)
 
        const int kSizeOfMove = 7;
 #if defined(__default_codegen__)
-       code = buf = g_malloc (256);
+       code = buf = (guint8 *)g_malloc (256);
 #elif defined(__native_client_codegen__)
        buf_alloc = g_malloc (256 + kNaClAlignment + kSizeOfMove);
        buf = ((guint)buf_alloc + kNaClAlignment) & ~kNaClAlignmentMask;
@@ -2252,7 +2260,7 @@ stream_init (MonoDynamicStream *sh)
 {
        sh->index = 0;
        sh->alloc_size = 4096;
-       sh->data = g_malloc (4096);
+       sh->data = (char *)g_malloc (4096);
 
        /* So offsets are > 0 */
        sh->data [0] = 0;
@@ -2272,7 +2280,7 @@ make_room_in_stream (MonoDynamicStream *stream, int size)
                        stream->alloc_size *= 2;
        }
        
-       stream->data = g_realloc (stream->data, stream->alloc_size);
+       stream->data = (char *)g_realloc (stream->data, stream->alloc_size);
 }
 
 static guint32
@@ -2296,6 +2304,8 @@ add_stream_data (MonoDynamicStream *stream, const char *data, guint32 len)
 static guint32
 add_to_blob (MonoAotCompile *acfg, const guint8 *data, guint32 data_len)
 {
+       g_assert (!acfg->blob_closed);
+
        if (acfg->blob.alloc_size == 0)
                stream_init (&acfg->blob);
 
@@ -2320,6 +2330,30 @@ add_to_blob_aligned (MonoAotCompile *acfg, const guint8 *data, guint32 data_len,
        return add_stream_data (&acfg->blob, (char*)data, data_len);
 }
 
+/* Emit a table of data into the aot image */
+static void
+emit_aot_data (MonoAotCompile *acfg, MonoAotFileTable table, const char *symbol, guint8 *data, int size)
+{
+       if (acfg->data_outfile) {
+               acfg->table_offsets [(int)table] = acfg->datafile_offset;
+               fwrite (data,1, size, acfg->data_outfile);
+               acfg->datafile_offset += size;
+               // align the data to 8 bytes. Put zeros in the file (so that every build results in consistent output).
+               int align = 8 - size % 8;
+               acfg->datafile_offset += align;
+               guint8 align_buf [16];
+               memset (&align_buf, 0, sizeof (align_buf));
+               fwrite (align_buf, align, 1, acfg->data_outfile);
+       } else if (acfg->llvm) {
+               mono_llvm_emit_aot_data (symbol, data, size);
+       } else {
+               emit_section_change (acfg, RODATA_SECT, 0);
+               emit_alignment (acfg, 8);
+               emit_label (acfg, symbol);
+               emit_bytes (acfg, data, size);
+       }
+}
+
 /*
  * emit_offset_table:
  *
@@ -2329,7 +2363,7 @@ add_to_blob_aligned (MonoAotCompile *acfg, const guint8 *data, guint32 data_len,
  * a given entry. Returns the size of the table.
  */
 static guint32
-emit_offset_table (MonoAotCompile *acfg, const char *symbol, int noffsets, int group_size, gint32 *offsets)
+emit_offset_table (MonoAotCompile *acfg, const char *symbol, MonoAotFileTable table, int noffsets, int group_size, gint32 *offsets)
 {
        gint32 current_offset;
        int i, buf_size, ngroups, index_entry_size;
@@ -2342,7 +2376,7 @@ emit_offset_table (MonoAotCompile *acfg, const char *symbol, int noffsets, int g
        index_offsets = g_new0 (guint32, ngroups);
 
        buf_size = noffsets * 4;
-       p = buf = g_malloc0 (buf_size);
+       p = buf = (guint8 *)g_malloc0 (buf_size);
 
        current_offset = 0;
        for (i = 0; i < noffsets; ++i) {
@@ -2367,7 +2401,7 @@ emit_offset_table (MonoAotCompile *acfg, const char *symbol, int noffsets, int g
                index_entry_size = 4;
 
        buf_size = (data_p - data_buf) + (ngroups * 4) + 16;
-       p = buf = g_malloc0 (buf_size);
+       p = buf = (guint8 *)g_malloc0 (buf_size);
 
        /* Emit the header */
        encode_int (noffsets, p, &p);
@@ -2388,14 +2422,7 @@ emit_offset_table (MonoAotCompile *acfg, const char *symbol, int noffsets, int g
 
        g_assert (p - buf <= buf_size);
 
-       if (acfg->llvm) {
-               mono_llvm_emit_aot_data (symbol, buf, p - buf);
-       } else {
-               emit_section_change (acfg, RODATA_SECT, 1);
-               emit_alignment (acfg, 8);
-               emit_label (acfg, symbol);
-               emit_bytes (acfg, buf, p - buf);
-       }
+       emit_aot_data (acfg, table, symbol, buf, p - buf);
 
        g_free (buf);
        g_free (data_buf);
@@ -2427,7 +2454,7 @@ find_typespec_for_class (MonoAotCompile *acfg, MonoClass *klass)
 
        /* FIXME: Search referenced images as well */
        if (!acfg->typespec_classes) {
-               acfg->typespec_classes = mono_mempool_alloc0 (acfg->mempool, sizeof (MonoClass*) * len);
+               acfg->typespec_classes = (MonoClass **)mono_mempool_alloc0 (acfg->mempool, sizeof (MonoClass*) * len);
                for (i = 0; i < len; ++i) {
                        MonoError error;
                        acfg->typespec_classes [i] = mono_class_get_and_inflate_typespec_checked (acfg->image, MONO_TOKEN_TYPE_SPEC | (i + 1), NULL, &error);
@@ -2505,23 +2532,24 @@ encode_klass_ref_inner (MonoAotCompile *acfg, MonoClass *klass, guint8 *buf, gui
                MonoGenericParam *par = klass->byval_arg.data.generic_param;
 
                encode_value (MONO_AOT_TYPEREF_VAR, p, &p);
-               encode_value (klass->byval_arg.type, p, &p);
-               encode_value (mono_type_get_generic_param_num (&klass->byval_arg), p, &p);
-
-               encode_value (container ? 1 : 0, p, &p);
-               if (container) {
-                       encode_value (container->is_method, p, &p);
-                       g_assert (!par->gshared_constraint);
-                       if (container->is_method)
-                               encode_method_ref (acfg, container->owner.method, p, &p);
-                       else
-                               encode_klass_ref (acfg, container->owner.klass, p, &p);
+
+               encode_value (par->gshared_constraint ? 1 : 0, p, &p);
+               if (par->gshared_constraint) {
+                       MonoGSharedGenericParam *gpar = (MonoGSharedGenericParam*)par;
+                       encode_type (acfg, par->gshared_constraint, p, &p);
+                       encode_klass_ref (acfg, mono_class_from_generic_parameter (gpar->parent, NULL, klass->byval_arg.type == MONO_TYPE_MVAR), p, &p);
                } else {
-                       encode_value (par->gshared_constraint ? 1 : 0, p, &p);
-                       if (par->gshared_constraint) {
-                               MonoGSharedGenericParam *gpar = (MonoGSharedGenericParam*)par;
-                               encode_type (acfg, par->gshared_constraint, p, &p);
-                               encode_klass_ref (acfg, mono_class_from_generic_parameter (gpar->parent, NULL, klass->byval_arg.type == MONO_TYPE_MVAR), p, &p);
+                       encode_value (klass->byval_arg.type, p, &p);
+                       encode_value (mono_type_get_generic_param_num (&klass->byval_arg), p, &p);
+
+                       encode_value (container->is_anonymous ? 0 : 1, p, &p);
+
+                       if (!container->is_anonymous) {
+                               encode_value (container->is_method, p, &p);
+                               if (container->is_method)
+                                       encode_method_ref (acfg, container->owner.method, p, &p);
+                               else
+                                       encode_klass_ref (acfg, container->owner.klass, p, &p);
                        }
                }
        } else if (klass->byval_arg.type == MONO_TYPE_PTR) {
@@ -2568,7 +2596,7 @@ encode_klass_ref (MonoAotCompile *acfg, MonoClass *klass, guint8 *buf, guint8 **
                guint8 *buf2, *p;
 
                if (!offset) {
-                       buf2 = g_malloc (1024);
+                       buf2 = (guint8 *)g_malloc (1024);
                        p = buf2;
 
                        encode_klass_ref_inner (acfg, klass, p, &p);
@@ -2839,6 +2867,10 @@ encode_method_ref (MonoAotCompile *acfg, MonoMethod *method, guint8 *buf, guint8
                                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);
+                       else if (info->subtype == WRAPPER_SUBTYPE_GSHAREDVT_IN_SIG)
+                               encode_signature (acfg, info->d.gsharedvt.sig, p, &p);
+                       else if (info->subtype == WRAPPER_SUBTYPE_GSHAREDVT_OUT_SIG)
+                               encode_signature (acfg, info->d.gsharedvt.sig, p, &p);
                        break;
                }
                case MONO_WRAPPER_MANAGED_TO_NATIVE: {
@@ -2926,7 +2958,7 @@ encode_method_ref (MonoAotCompile *acfg, MonoMethod *method, guint8 *buf, guint8
                 * encode that.
                 * Obtain the token from information recorded by the JIT.
                 */
-               ji = g_hash_table_lookup (acfg->token_info_hash, method);
+               ji = (MonoJumpInfoToken *)g_hash_table_lookup (acfg->token_info_hash, method);
                if (ji) {
                        image_index = get_image_index (acfg, ji->image);
                        g_assert (image_index < MAX_IMAGE_INDEX);
@@ -2963,7 +2995,7 @@ encode_method_ref (MonoAotCompile *acfg, MonoMethod *method, guint8 *buf, guint8
        } else if (token == 0) {
                /* This might be a method of a constructed type like int[,].Set */
                /* Obtain the token from information recorded by the JIT */
-               ji = g_hash_table_lookup (acfg->token_info_hash, method);
+               ji = (MonoJumpInfoToken *)g_hash_table_lookup (acfg->token_info_hash, method);
                if (ji) {
                        image_index = get_image_index (acfg, ji->image);
                        g_assert (image_index < MAX_IMAGE_INDEX);
@@ -3058,7 +3090,6 @@ is_plt_patch (MonoJumpInfo *patch_info)
        case MONO_PATCH_INFO_JIT_ICALL_ADDR:
        case MONO_PATCH_INFO_ICALL_ADDR:
        case MONO_PATCH_INFO_RGCTX_FETCH:
-       case MONO_PATCH_INFO_LLVM_IMT_TRAMPOLINE:
                return TRUE;
        default:
                return FALSE;
@@ -3101,7 +3132,7 @@ get_plt_entry (MonoAotCompile *acfg, MonoJumpInfo *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);
+       res = (MonoPltEntry *)g_hash_table_lookup (acfg->patch_to_plt_entry [patch_info->type], patch_info);
 
        if (!acfg->llvm && patch_info->type == MONO_PATCH_INFO_METHOD && (patch_info->data.method->iflags & METHOD_IMPL_ATTRIBUTE_SYNCHRONIZED)) {
                /* 
@@ -3118,7 +3149,7 @@ get_plt_entry (MonoAotCompile *acfg, MonoJumpInfo *patch_info)
 
                new_ji = mono_patch_info_dup_mp (acfg->mempool, patch_info);
 
-               res = mono_mempool_alloc0 (acfg->mempool, sizeof (MonoPltEntry));
+               res = (MonoPltEntry *)mono_mempool_alloc0 (acfg->mempool, sizeof (MonoPltEntry));
                res->plt_offset = acfg->plt_offset;
                res->ji = new_ji;
                res->symbol = get_plt_symbol (acfg, res->plt_offset, patch_info);
@@ -3270,8 +3301,8 @@ add_extra_method (MonoAotCompile *acfg, MonoMethod *method)
 static void
 add_jit_icall_wrapper (gpointer key, gpointer value, gpointer user_data)
 {
-       MonoAotCompile *acfg = user_data;
-       MonoJitICallInfo *callinfo = value;
+       MonoAotCompile *acfg = (MonoAotCompile *)user_data;
+       MonoJitICallInfo *callinfo = (MonoJitICallInfo *)value;
        MonoMethod *wrapper;
        char *name;
 
@@ -3297,9 +3328,9 @@ get_runtime_invoke_sig (MonoMethodSignature *sig)
 }
 
 static MonoMethod*
-get_runtime_invoke (MonoAotCompile *acfg, MonoMethod *method, gboolean virtual)
+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));
+       return mono_marshal_get_runtime_invoke (method, virtual_, acfg->aot_opts.llvm_only && mono_method_needs_static_rgctx_invoke (method, TRUE));
 }
 
 static gboolean
@@ -3487,6 +3518,10 @@ add_wrappers (MonoAotCompile *acfg)
                }
 #endif
 
+               if (!skip && acfg->aot_opts.llvm_only && (acfg->opts & MONO_OPT_GSHAREDVT) && mini_gsharedvt_runtime_invoke_supported (sig))
+                       /* Supported by the gsharedvt based runtime-invoke wrapper */
+                       skip = TRUE;
+
                if (!skip) {
                        //printf ("%s\n", mono_method_full_name (method, TRUE));
                        add_method (acfg, get_runtime_invoke (acfg, method, FALSE));
@@ -3560,6 +3595,21 @@ add_wrappers (MonoAotCompile *acfg)
                        add_method (acfg, mono_marshal_get_runtime_invoke_dynamic ());
 #endif
 
+               /* These are used by mono_jit_runtime_invoke () to calls gsharedvt out wrappers */
+               if (acfg->aot_opts.llvm_only) {
+                       int variants;
+
+                       /* Create simplified signatures which match the signature used by the gsharedvt out wrappers */
+                       for (variants = 0; variants < 4; ++variants) {
+                               for (i = 0; i < 16; ++i) {
+                                       sig = mini_get_gsharedvt_out_sig_wrapper_signature ((variants & 1) > 0, (variants & 2) > 0, i);
+                                       add_extra_method (acfg, mono_marshal_get_runtime_invoke_for_sig (sig));
+
+                                       g_free (sig);
+                               }
+                       }
+               }
+
                /* stelemref */
                add_method (acfg, mono_marshal_get_stelemref ());
 
@@ -3863,7 +3913,7 @@ add_wrappers (MonoAotCompile *acfg)
 
                                /* From load_cattr_value () in reflection.c */
                                slen = mono_metadata_decode_value (p, &p);
-                               n = g_memdup (p, slen + 1);
+                               n = (char *)g_memdup (p, slen + 1);
                                n [slen] = 0;
                                t = mono_reflection_type_from_name (n, acfg->image);
                                g_assert (t);
@@ -3890,7 +3940,7 @@ add_wrappers (MonoAotCompile *acfg)
                                        named += 1;
 
                                        name_len = mono_metadata_decode_blob_size (named, &named);
-                                       name = g_malloc (name_len + 1);
+                                       name = (char *)g_malloc (name_len + 1);
                                        memcpy (name, named, name_len);
                                        name [name_len] = 0;
                                        named += name_len;
@@ -3901,7 +3951,7 @@ add_wrappers (MonoAotCompile *acfg)
                                        /* load_cattr_value (), string case */
                                        g_assert (*named != (char)0xff);
                                        slen = mono_metadata_decode_value (named, &named);
-                                       export_name = g_malloc (slen + 1);
+                                       export_name = (char *)g_malloc (slen + 1);
                                        memcpy (export_name, named, slen);
                                        export_name [slen] = 0;
                                        named += slen;
@@ -4453,7 +4503,7 @@ add_generic_instances (MonoAotCompile *acfg)
 
        /* Add types of args/locals */
        for (i = 0; i < acfg->methods->len; ++i) {
-               method = g_ptr_array_index (acfg->methods, i);
+               method = (MonoMethod *)g_ptr_array_index (acfg->methods, i);
                add_types_from_method_header (acfg, method);
        }
 
@@ -4483,44 +4533,39 @@ add_generic_instances (MonoAotCompile *acfg)
                if (klass)
                        add_instances_of (acfg, klass, insts, ninsts, TRUE);
 
-               /* Add an instance of EnumEqualityComparer<int/uint> which is created by EqualityComparer<T> for enums */
+               /* Add instances of EnumEqualityComparer which are created by EqualityComparer<T> for enums */
                {
                        MonoClass *enum_comparer;
-                       MonoGenericContext ctx;
-                       MonoType *args [16];
-
+                       MonoType *insts [16];
+                       int ninsts;
+
+                       ninsts = 0;
+                       insts [ninsts ++] = &mono_defaults.int32_class->byval_arg;
+                       insts [ninsts ++] = &mono_defaults.uint32_class->byval_arg;
+                       insts [ninsts ++] = &mono_defaults.uint16_class->byval_arg;
+                       insts [ninsts ++] = &mono_defaults.byte_class->byval_arg;
                        enum_comparer = mono_class_from_name (mono_defaults.corlib, "System.Collections.Generic", "EnumEqualityComparer`1");
                        g_assert (enum_comparer);
+                       add_instances_of (acfg, enum_comparer, insts, ninsts, FALSE);
 
-                       memset (&ctx, 0, sizeof (ctx));
-                       args [0] = &mono_defaults.int32_class->byval_arg;
-                       ctx.class_inst = mono_metadata_get_generic_inst (1, args);
-                       add_generic_class (acfg, mono_class_inflate_generic_class (enum_comparer, &ctx), FALSE, "EqualityComparer<T>");
-
-                       memset (&ctx, 0, sizeof (ctx));
-                       args [0] = &mono_defaults.uint32_class->byval_arg;
-                       ctx.class_inst = mono_metadata_get_generic_inst (1, args);
-                       add_generic_class (acfg, mono_class_inflate_generic_class (enum_comparer, &ctx), FALSE, "EqualityComparer<T>");
-               }
+                       ninsts = 0;
+                       insts [ninsts ++] = &mono_defaults.int16_class->byval_arg;
+                       enum_comparer = mono_class_from_name (mono_defaults.corlib, "System.Collections.Generic", "ShortEnumEqualityComparer`1");
+                       g_assert (enum_comparer);
+                       add_instances_of (acfg, enum_comparer, insts, ninsts, FALSE);
 
-               /* Add an instance of LongEnumEqualityComparer<long/ulong> which is created by EqualityComparer<T> for enums */
-               {
-                       MonoClass *enum_comparer;
-                       MonoGenericContext ctx;
-                       MonoType *args [16];
+                       ninsts = 0;
+                       insts [ninsts ++] = &mono_defaults.sbyte_class->byval_arg;
+                       enum_comparer = mono_class_from_name (mono_defaults.corlib, "System.Collections.Generic", "SByteEnumEqualityComparer`1");
+                       g_assert (enum_comparer);
+                       add_instances_of (acfg, enum_comparer, insts, ninsts, FALSE);
 
                        enum_comparer = mono_class_from_name (mono_defaults.corlib, "System.Collections.Generic", "LongEnumEqualityComparer`1");
                        g_assert (enum_comparer);
-
-                       memset (&ctx, 0, sizeof (ctx));
-                       args [0] = &mono_defaults.int64_class->byval_arg;
-                       ctx.class_inst = mono_metadata_get_generic_inst (1, args);
-                       add_generic_class (acfg, mono_class_inflate_generic_class (enum_comparer, &ctx), FALSE, "EqualityComparer<T>");
-
-                       memset (&ctx, 0, sizeof (ctx));
-                       args [0] = &mono_defaults.uint64_class->byval_arg;
-                       ctx.class_inst = mono_metadata_get_generic_inst (1, args);
-                       add_generic_class (acfg, mono_class_inflate_generic_class (enum_comparer, &ctx), FALSE, "EqualityComparer<T>");
+                       ninsts = 0;
+                       insts [ninsts ++] = &mono_defaults.int64_class->byval_arg;
+                       insts [ninsts ++] = &mono_defaults.uint64_class->byval_arg;
+                       add_instances_of (acfg, enum_comparer, insts, ninsts, FALSE);
                }
 
                /* Add instances of the array generic interfaces for primitive types */
@@ -4635,7 +4680,7 @@ static gboolean
 is_direct_callable (MonoAotCompile *acfg, MonoMethod *method, MonoJumpInfo *patch_info)
 {
        if ((patch_info->type == MONO_PATCH_INFO_METHOD) && (patch_info->data.method->klass->image == acfg->image)) {
-               MonoCompile *callee_cfg = g_hash_table_lookup (acfg->method_to_cfg, patch_info->data.method);
+               MonoCompile *callee_cfg = (MonoCompile *)g_hash_table_lookup (acfg->method_to_cfg, patch_info->data.method);
                if (callee_cfg) {
                        gboolean direct_callable = TRUE;
 
@@ -4687,7 +4732,7 @@ get_pinvoke_import (MonoAotCompile *acfg, MonoMethod *method)
        guint32 im_cols [MONO_IMPLMAP_SIZE];
        char *import;
 
-       import = g_hash_table_lookup (acfg->method_to_pinvoke_import, method);
+       import = (char *)g_hash_table_lookup (acfg->method_to_pinvoke_import, method);
        if (import != NULL)
                return import;
 
@@ -4747,7 +4792,7 @@ compute_line_numbers (MonoMethod *method, int code_size, MonoDebugMethodJitInfo
        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);
+       qsort (ln_array, debug_info->num_line_numbers, sizeof (MonoDebugLineNumberEntry), (int (*)(const void *, const void *))compare_lne);
 
        native_to_il_offset = g_new0 (int, code_size + 1);
 
@@ -4868,7 +4913,7 @@ emit_and_reloc_code (MonoAotCompile *acfg, MonoMethod *method, guint8 *code, gui
        for (i = 0; i < code_len; i += INST_LEN) {
                patch_info = NULL;
                for (pindex = start_index; pindex < patches->len; ++pindex) {
-                       patch_info = g_ptr_array_index (patches, pindex);
+                       patch_info = (MonoJumpInfo *)g_ptr_array_index (patches, pindex);
                        if (patch_info->ip.i >= i)
                                break;
                }
@@ -4902,7 +4947,7 @@ emit_and_reloc_code (MonoAotCompile *acfg, MonoMethod *method, guint8 *code, gui
                        }
                        case MONO_PATCH_INFO_OBJC_SELECTOR_REF: {
                                int code_size, index;
-                               char *selector = (void*)patch_info->data.target;
+                               char *selector = (char *)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);
@@ -4934,7 +4979,7 @@ emit_and_reloc_code (MonoAotCompile *acfg, MonoMethod *method, guint8 *code, gui
                                external_call = FALSE;
                                if ((patch_info->type == MONO_PATCH_INFO_METHOD) && (patch_info->data.method->klass->image == acfg->image)) {
                                        if (!got_only && is_direct_callable (acfg, method, patch_info)) {
-                                               MonoCompile *callee_cfg = g_hash_table_lookup (acfg->method_to_cfg, patch_info->data.method);
+                                               MonoCompile *callee_cfg = (MonoCompile *)g_hash_table_lookup (acfg->method_to_cfg, patch_info->data.method);
                                                //printf ("DIRECT: %s %s\n", method ? mono_method_full_name (method, TRUE) : "", mono_method_full_name (callee_cfg->method, TRUE));
                                                direct_call = TRUE;
                                                direct_call_target = callee_cfg->asm_symbol;
@@ -5017,7 +5062,7 @@ emit_and_reloc_code (MonoAotCompile *acfg, MonoMethod *method, guint8 *code, gui
                        /* Find next patch */
                        patch_info = NULL;
                        for (pindex = start_index; pindex < patches->len; ++pindex) {
-                               patch_info = g_ptr_array_index (patches, pindex);
+                               patch_info = (MonoJumpInfo *)g_ptr_array_index (patches, pindex);
                                if (patch_info->ip.i >= i)
                                        break;
                        }
@@ -5108,7 +5153,7 @@ get_debug_sym (MonoMethod *method, const char *prefix, GHashTable *cache)
 #endif
 
        len = strlen (name1);
-       name2 = malloc (strlen (prefix) + len + 16);
+       name2 = (char *)malloc (strlen (prefix) + len + 16);
        memcpy (name2, prefix, strlen (prefix));
        j = strlen (prefix);
        for (i = 0; i < len; ++i) {
@@ -5131,7 +5176,7 @@ get_debug_sym (MonoMethod *method, const char *prefix, GHashTable *cache)
 
        count = 0;
        while (TRUE) {
-               cached_method = g_hash_table_lookup (cache, name2);
+               cached_method = (MonoMethod *)g_hash_table_lookup (cache, name2);
                if (!(cached_method && cached_method != method))
                        break;
                sprintf (name2 + j, "_%d", count);
@@ -5186,7 +5231,7 @@ emit_method_code (MonoAotCompile *acfg, MonoCompile *cfg)
                emit_label (acfg, debug_sym);
        }
 
-       export_name = g_hash_table_lookup (acfg->export_names, method);
+       export_name = (char *)g_hash_table_lookup (acfg->export_names, method);
        if (export_name) {
                /* Emit a global symbol for the method */
                emit_global_inner (acfg, export_name, TRUE);
@@ -5298,7 +5343,7 @@ encode_patch (MonoAotCompile *acfg, MonoJumpInfo *patch_info, guint8 *buf, guint
 
                ex_class =
                        mono_class_from_name (mono_defaults.exception_class->image,
-                                                                 "System", patch_info->data.target);
+                                                                 "System", (const char *)patch_info->data.target);
                g_assert (ex_class);
                encode_klass_ref (acfg, ex_class, p, &p);
                break;
@@ -5344,7 +5389,7 @@ encode_patch (MonoAotCompile *acfg, MonoJumpInfo *patch_info, guint8 *buf, guint
                 */
                offset = GPOINTER_TO_UINT (g_hash_table_lookup (acfg->method_blob_hash, entry->method));
                if (!offset) {
-                       buf2 = g_malloc (1024);
+                       buf2 = (guint8 *)g_malloc (1024);
                        p2 = buf2;
 
                        encode_method_ref (acfg, entry->method, p2, &p2);
@@ -5368,10 +5413,6 @@ encode_patch (MonoAotCompile *acfg, MonoJumpInfo *patch_info, guint8 *buf, guint
        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);
-               encode_value (patch_info->data.imt_tramp->vt_offset, p, &p);
-               break;
        case MONO_PATCH_INFO_SIGNATURE:
                encode_signature (acfg, (MonoMethodSignature*)patch_info->data.target, p, &p);
                break;
@@ -5389,15 +5430,15 @@ encode_patch (MonoAotCompile *acfg, MonoJumpInfo *patch_info, guint8 *buf, guint
                encode_method_ref (acfg, info->method, p, &p);
                encode_value (info->num_entries, p, &p);
                for (i = 0; i < info->num_entries; ++i) {
-                       MonoRuntimeGenericContextInfoTemplate *template = &info->entries [i];
+                       MonoRuntimeGenericContextInfoTemplate *template_ = &info->entries [i];
 
-                       encode_value (template->info_type, p, &p);
-                       switch (mini_rgctx_info_type_to_patch_info_type (template->info_type)) {
+                       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);
+                               encode_klass_ref (acfg, mono_class_from_mono_type ((MonoType *)template_->data), p, &p);
                                break;
                        case MONO_PATCH_INFO_FIELD:
-                               encode_field_info (acfg, template->data, p, &p);
+                               encode_field_info (acfg, (MonoClassField *)template_->data, p, &p);
                                break;
                        default:
                                g_assert_not_reached ();
@@ -5407,7 +5448,7 @@ encode_patch (MonoAotCompile *acfg, MonoJumpInfo *patch_info, guint8 *buf, guint
                break;
        }
        case MONO_PATCH_INFO_LDSTR_LIT: {
-               const char *s = patch_info->data.target;
+               const char *s = (const char *)patch_info->data.target;
                int len = strlen (s);
 
                encode_value (len, p, &p);
@@ -5439,7 +5480,7 @@ encode_patch_list (MonoAotCompile *acfg, GPtrArray *patches, int n_patches, gboo
        encode_value (n_patches, p, &p);
 
        for (pindex = 0; pindex < patches->len; ++pindex) {
-               patch_info = g_ptr_array_index (patches, pindex);
+               patch_info = (MonoJumpInfo *)g_ptr_array_index (patches, pindex);
 
                if (patch_info->type == MONO_PATCH_INFO_NONE || patch_info->type == MONO_PATCH_INFO_BB)
                        /* Nothing to do */
@@ -5480,7 +5521,7 @@ emit_method_info (MonoAotCompile *acfg, MonoCompile *cfg)
        /**********************/
 
        buf_size = (patches->len < 1000) ? 40960 : 40960 + (patches->len * 64);
-       p = buf = g_malloc (buf_size);
+       p = buf = (guint8 *)g_malloc (buf_size);
 
        if (mono_class_get_cctor (method->klass))
                encode_klass_ref (acfg, method->klass, p, &p);
@@ -5492,7 +5533,7 @@ emit_method_info (MonoAotCompile *acfg, MonoCompile *cfg)
 
        n_patches = 0;
        for (pindex = 0; pindex < patches->len; ++pindex) {
-               patch_info = g_ptr_array_index (patches, pindex);
+               patch_info = (MonoJumpInfo *)g_ptr_array_index (patches, pindex);
                
                if ((patch_info->type == MONO_PATCH_INFO_GOT_OFFSET) ||
                        (patch_info->type == MONO_PATCH_INFO_NONE)) {
@@ -5599,7 +5640,7 @@ emit_exception_debug_info (MonoAotCompile *acfg, MonoCompile *cfg, gboolean stor
 
        buf_size = header->num_clauses * 256 + debug_info_size + 2048 + seq_points_size + cfg->gc_map_size;
 
-       p = buf = g_malloc (buf_size);
+       p = buf = (guint8 *)g_malloc (buf_size);
 
        use_unwind_ops = cfg->unwind_ops != NULL;
 
@@ -5700,7 +5741,7 @@ emit_exception_debug_info (MonoAotCompile *acfg, MonoCompile *cfg, gboolean stor
                                        guint8 *buf2, *p2;
                                        int len;
 
-                                       buf2 = g_malloc (4096);
+                                       buf2 = (guint8 *)g_malloc (4096);
                                        p2 = buf2;
                                        encode_klass_ref (acfg, ei->data.catch_class, p2, &p2);
                                        len = p2 - buf2;
@@ -5771,7 +5812,7 @@ emit_exception_debug_info (MonoAotCompile *acfg, MonoCompile *cfg, gboolean stor
                 * Need to encode jinfo->method too, since it is not equal to 'method'
                 * when using generic sharing.
                 */
-               buf2 = g_malloc (4096);
+               buf2 = (guint8 *)g_malloc (4096);
                p2 = buf2;
                encode_method_ref (acfg, jinfo->d.method, p2, &p2);
                len = p2 - buf2;
@@ -5835,7 +5876,7 @@ emit_klass_info (MonoAotCompile *acfg, guint32 token)
 
                buf_size = 16;
 
-               p = buf = g_malloc (buf_size);
+               p = buf = (guint8 *)g_malloc (buf_size);
 
                /* Mark as unusable */
                encode_value (-1, p, &p);
@@ -5847,7 +5888,7 @@ emit_klass_info (MonoAotCompile *acfg, guint32 token)
        }
                
        buf_size = 10240 + (klass->vtable_size * 16);
-       p = buf = g_malloc (buf_size);
+       p = buf = (guint8 *)g_malloc (buf_size);
 
        g_assert (klass);
 
@@ -5985,7 +6026,7 @@ emit_plt (MonoAotCompile *acfg)
                         */
                        continue;
 
-               plt_entry = g_hash_table_lookup (acfg->plt_offset_to_entry, GUINT_TO_POINTER (i));
+               plt_entry = (MonoPltEntry *)g_hash_table_lookup (acfg->plt_offset_to_entry, GUINT_TO_POINTER (i));
 
                debug_sym = plt_entry->debug_sym;
 
@@ -6039,7 +6080,7 @@ emit_plt (MonoAotCompile *acfg)
                        if (i == 0)
                                continue;
 
-                       plt_entry = g_hash_table_lookup (acfg->plt_offset_to_entry, GUINT_TO_POINTER (i));
+                       plt_entry = (MonoPltEntry *)g_hash_table_lookup (acfg->plt_offset_to_entry, GUINT_TO_POINTER (i));
 
                        /* Skip plt entries not actually called by LLVM code */
                        if (!plt_entry->llvm_used)
@@ -6148,7 +6189,7 @@ emit_trampoline_full (MonoAotCompile *acfg, int got_offset, MonoTrampInfo *info,
        g_ptr_array_sort (patches, compare_patches);
 
        buf_size = patches->len * 128 + 128;
-       buf = g_malloc (buf_size);
+       buf = (guint8 *)g_malloc (buf_size);
        p = buf;
 
        encode_patch_list (acfg, patches, patches->len, FALSE, got_offset, p, &p);
@@ -6204,7 +6245,7 @@ emit_trampolines (MonoAotCompile *acfg)
        char symbol [256];
        char end_symbol [256];
        int i, tramp_got_offset;
-       MonoAotTrampoline ntype;
+       int ntype;
 #ifdef MONO_ARCH_HAVE_FULL_AOT_TRAMPOLINES
        int tramp_type;
 #endif
@@ -6236,7 +6277,7 @@ emit_trampolines (MonoAotCompile *acfg)
                        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);
+                       mono_arch_create_generic_trampoline ((MonoTrampolineType)tramp_type, &info, acfg->aot_opts.use_trampolines_page? 2: TRUE);
                        emit_trampoline (acfg, acfg->got_offset, info);
                }
 
@@ -6275,7 +6316,7 @@ emit_trampolines (MonoAotCompile *acfg)
                        GSList *l = mono_arch_get_trampolines (TRUE);
 
                        while (l) {
-                               MonoTrampInfo *info = l->data;
+                               MonoTrampInfo *info = (MonoTrampInfo *)l->data;
 
                                emit_trampoline (acfg, acfg->got_offset, info);
                                l = l->next;
@@ -6306,7 +6347,7 @@ emit_trampolines (MonoAotCompile *acfg)
                        /* delegate_invoke_impl trampolines */
                        l = mono_arch_get_delegate_invoke_impls ();
                        while (l) {
-                               MonoTrampInfo *info = l->data;
+                               MonoTrampInfo *info = (MonoTrampInfo *)l->data;
 
                                emit_trampoline (acfg, acfg->got_offset, info);
                                l = l->next;
@@ -6487,7 +6528,7 @@ add_readonly_value (MonoAotOptions *opts, const char *val)
                exit (1);
        }
        rdv = g_new0 (ReadOnlyValue, 1);
-       rdv->name = g_malloc0 (tval - val + 1);
+       rdv->name = (char *)g_malloc0 (tval - val + 1);
        memcpy (rdv->name, val, tval - val);
        tval++;
        fval++;
@@ -6603,7 +6644,7 @@ mono_aot_parse_options (const char *aot_options, MonoAotOptions *opts)
 
        args = mono_aot_split_options (aot_options ? aot_options : "");
        for (int i = 0; i < args->len; ++i) {
-               const char *arg = g_ptr_array_index (args, i);
+               const char *arg = (const char *)g_ptr_array_index (args, i);
 
                if (str_begins_with (arg, "outfile=")) {
                        opts->outfile = g_strdup (arg + strlen ("outfile="));
@@ -6698,6 +6739,8 @@ mono_aot_parse_options (const char *aot_options, MonoAotOptions *opts)
                        opts->mode = MONO_AOT_MODE_FULL;
                        opts->llvm = TRUE;
                        opts->llvm_only = TRUE;
+               } else if (str_begins_with (arg, "data-outfile=")) {
+                       opts->data_outfile = g_strdup (arg + strlen ("data-outfile="));
                } else if (str_begins_with (arg, "help") || str_begins_with (arg, "?")) {
                        printf ("Supported options for --aot:\n");
                        printf ("    outfile=\n");
@@ -6755,10 +6798,10 @@ add_token_info_hash (gpointer key, gpointer value, gpointer user_data)
 {
        MonoMethod *method = (MonoMethod*)key;
        MonoJumpInfoToken *ji = (MonoJumpInfoToken*)value;
-       MonoAotCompile *acfg = user_data;
+       MonoAotCompile *acfg = (MonoAotCompile *)user_data;
        MonoJumpInfoToken *new_ji;
 
-       new_ji = mono_mempool_alloc0 (acfg->mempool, sizeof (MonoJumpInfoToken));
+       new_ji = (MonoJumpInfoToken *)mono_mempool_alloc0 (acfg->mempool, sizeof (MonoJumpInfoToken));
        new_ji->image = ji->image;
        new_ji->token = ji->token;
        g_hash_table_insert (acfg->token_info_hash, method, new_ji);
@@ -6872,6 +6915,100 @@ can_encode_patch (MonoAotCompile *acfg, MonoJumpInfo *patch_info)
        return TRUE;
 }
 
+/* LOCKING: Assumes the loader lock is held */
+static void
+add_gsharedvt_wrappers (MonoAotCompile *acfg, MonoMethodSignature *sig, gboolean gsharedvt_in, gboolean gsharedvt_out)
+{
+       MonoMethod *wrapper;
+       gboolean concrete = TRUE;
+       gboolean add_in = gsharedvt_in;
+       gboolean add_out = gsharedvt_out;
+
+       if (gsharedvt_in && g_hash_table_lookup (acfg->gsharedvt_in_signatures, sig))
+               add_in = FALSE;
+       if (gsharedvt_out && g_hash_table_lookup (acfg->gsharedvt_out_signatures, sig))
+               add_out = FALSE;
+
+       if (!add_in && !add_out)
+               return;
+
+       if (mini_is_gsharedvt_variable_signature (sig))
+               return;
+
+       if (add_in)
+               g_hash_table_insert (acfg->gsharedvt_in_signatures, sig, sig);
+       if (add_out)
+               g_hash_table_insert (acfg->gsharedvt_out_signatures, sig, sig);
+
+       if (!sig->has_type_parameters) {
+               //printf ("%s\n", mono_signature_full_name (sig));
+
+               if (gsharedvt_in) {
+                       wrapper = mini_get_gsharedvt_in_sig_wrapper (sig);
+                       add_extra_method (acfg, wrapper);
+               }
+               if (gsharedvt_out) {
+                       wrapper = mini_get_gsharedvt_out_sig_wrapper (sig);
+                       add_extra_method (acfg, wrapper);
+               }
+       } else {
+               /* For signatures creared during generic sharing, convert them to a concrete signature if possible */
+               MonoMethodSignature *copy = mono_metadata_signature_dup (sig);
+               int i;
+
+               //printf ("%s\n", mono_signature_full_name (sig));
+
+               copy->ret = mini_get_underlying_type (sig->ret);
+               // FIXME: Add more cases
+               if (copy->ret->type == MONO_TYPE_VAR || copy->ret->type == MONO_TYPE_MVAR || copy->ret->type == MONO_TYPE_GENERICINST)
+                       concrete = FALSE;
+               for (i = 0; i < sig->param_count; ++i) {
+                       MonoType *t = mini_get_underlying_type (sig->params [i]);
+                       /*
+                        * Create a concrete type for Nullable<T_REF> etc.
+                        * FIXME: Generalize this
+                        */
+                       if (t->type == MONO_TYPE_GENERICINST && mono_class_is_nullable (mono_class_from_mono_type (t))) {
+                               MonoType *arg = mono_class_from_mono_type (t)->generic_class->context.class_inst->type_argv[0];
+                               arg = mini_get_underlying_type (arg);
+                               if (arg->type == MONO_TYPE_VAR || arg->type == MONO_TYPE_MVAR || arg->type == MONO_TYPE_GENERICINST) {
+                                       concrete = FALSE;
+                               } else {
+                                       MonoGenericContext ctx;
+                                       MonoClass *klass;
+                                       MonoType *args [16];
+
+                                       memset (&ctx, 0, sizeof (MonoGenericContext));
+                                       args [0] = arg;
+                                       ctx.class_inst = mono_metadata_get_generic_inst (1, args);
+
+                                       klass = mono_class_inflate_generic_class (mono_defaults.generic_nullable_class, &ctx);
+                                       t = &klass->byval_arg;
+                               }
+                       } else {
+                               if (t->type == MONO_TYPE_VAR || t->type == MONO_TYPE_MVAR || t->type == MONO_TYPE_GENERICINST)
+                                       concrete = FALSE;
+                       }
+                       copy->params [i] = t;
+               }
+               if (concrete) {
+                       copy->has_type_parameters = 0;
+
+                       if (gsharedvt_in) {
+                               wrapper = mini_get_gsharedvt_in_sig_wrapper (copy);
+                               add_extra_method (acfg, wrapper);
+                       }
+
+                       if (gsharedvt_out) {
+                               wrapper = mini_get_gsharedvt_out_sig_wrapper (copy);
+                               add_extra_method (acfg, wrapper);
+                       }
+
+                       //printf ("%s\n", mono_method_full_name (wrapper, 1));
+               }
+       }
+}
+
 /*
  * compile_method:
  *
@@ -6933,13 +7070,13 @@ compile_method (MonoAotCompile *acfg, MonoMethod *method)
         */
        flags = JIT_FLAG_AOT;
        if (mono_aot_mode_is_full (&acfg->aot_opts))
-               flags |= JIT_FLAG_FULL_AOT;
+               flags = (JitFlags)(flags | JIT_FLAG_FULL_AOT);
        if (acfg->llvm)
-               flags |= JIT_FLAG_LLVM;
+               flags = (JitFlags)(flags | JIT_FLAG_LLVM);
        if (acfg->aot_opts.llvm_only)
-               flags |= JIT_FLAG_LLVM_ONLY | JIT_FLAG_EXPLICIT_NULL_CHECKS;
+               flags = (JitFlags)(flags | JIT_FLAG_LLVM_ONLY | JIT_FLAG_EXPLICIT_NULL_CHECKS);
        if (acfg->aot_opts.no_direct_calls)
-               flags |= JIT_FLAG_NO_DIRECT_ICALLS;
+               flags = (JitFlags)(flags | JIT_FLAG_NO_DIRECT_ICALLS);
        cfg = mini_method_compile (method, acfg->opts, mono_get_root_domain (), flags, 0, index);
        mono_loader_clear_error ();
 
@@ -7130,6 +7267,22 @@ compile_method (MonoAotCompile *acfg, MonoMethod *method)
        if (!cfg->has_got_slots)
                InterlockedIncrement (&acfg->stats.methods_without_got_slots);
 
+       if (!cfg->method->wrapper_type)
+               /* These only need out wrappers */
+               add_gsharedvt_wrappers (acfg, mono_method_signature (cfg->method), FALSE, TRUE);
+
+       /* Add gsharedvt wrappers for signatures used by the method */
+       if (acfg->aot_opts.llvm_only && (acfg->opts & MONO_OPT_GSHAREDVT)) {
+               GSList *l;
+
+               for (l = cfg->signatures; l; l = l->next) {
+                       MonoMethodSignature *sig = mono_metadata_signature_dup ((MonoMethodSignature*)l->data);
+
+                       /* These only need in wrappers */
+                       add_gsharedvt_wrappers (acfg, sig, TRUE, FALSE);
+               }
+       }
+
        /* 
         * FIXME: Instead of this mess, allocate the patches from the aot mempool.
         */
@@ -7155,7 +7308,7 @@ compile_method (MonoAotCompile *acfg, MonoMethod *method)
 
                unwind_ops = NULL;
                for (l = cfg->unwind_ops; l; l = l->next) {
-                       op = mono_mempool_alloc (acfg->mempool, sizeof (MonoUnwindOp));
+                       op = (MonoUnwindOp *)mono_mempool_alloc (acfg->mempool, sizeof (MonoUnwindOp));
                        memcpy (op, l->data, sizeof (MonoUnwindOp));
                        unwind_ops = g_slist_prepend_mempool (acfg->mempool, unwind_ops, op);
                }
@@ -7169,17 +7322,17 @@ compile_method (MonoAotCompile *acfg, MonoMethod *method)
                int i;
                
                sig = mono_method_signature (method);
-               args = mono_mempool_alloc (acfg->mempool, sizeof (MonoInst*) * (sig->param_count + sig->hasthis));
+               args = (MonoInst **)mono_mempool_alloc (acfg->mempool, sizeof (MonoInst*) * (sig->param_count + sig->hasthis));
                for (i = 0; i < sig->param_count + sig->hasthis; ++i) {
-                       args [i] = mono_mempool_alloc (acfg->mempool, sizeof (MonoInst));
+                       args [i] = (MonoInst *)mono_mempool_alloc (acfg->mempool, sizeof (MonoInst));
                        memcpy (args [i], cfg->args [i], sizeof (MonoInst));
                }
                cfg->args = args;
 
                header = mono_method_get_header (method);
-               locals = mono_mempool_alloc (acfg->mempool, sizeof (MonoInst*) * header->num_locals);
+               locals = (MonoInst **)mono_mempool_alloc (acfg->mempool, sizeof (MonoInst*) * header->num_locals);
                for (i = 0; i < header->num_locals; ++i) {
-                       locals [i] = mono_mempool_alloc (acfg->mempool, sizeof (MonoInst));
+                       locals [i] = (MonoInst *)mono_mempool_alloc (acfg->mempool, sizeof (MonoInst));
                        memcpy (locals [i], cfg->locals [i], sizeof (MonoInst));
                }
                cfg->locals = locals;
@@ -7227,15 +7380,15 @@ compile_method (MonoAotCompile *acfg, MonoMethod *method)
 static void
 compile_thread_main (gpointer *user_data)
 {
-       MonoDomain *domain = user_data [0];
-       MonoAotCompile *acfg = user_data [1];
-       GPtrArray *methods = user_data [2];
+       MonoDomain *domain = (MonoDomain *)user_data [0];
+       MonoAotCompile *acfg = (MonoAotCompile *)user_data [1];
+       GPtrArray *methods = (GPtrArray *)user_data [2];
        int i;
 
        mono_thread_attach (domain);
 
        for (i = 0; i < methods->len; ++i)
-               compile_method (acfg, g_ptr_array_index (methods, i));
+               compile_method (acfg, (MonoMethod *)g_ptr_array_index (methods, i));
 }
 
 static void
@@ -7379,9 +7532,9 @@ mono_aot_get_direct_call_symbol (MonoJumpInfoType type, gconstpointer data)
        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);
+                       sym = mono_lookup_jit_icall_symbol ((const char *)data);
                } else if (type == MONO_PATCH_INFO_ICALL_ADDR) {
-                       MonoMethod *method = (gpointer)data;
+                       MonoMethod *method = (MonoMethod *)data;
                        if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
                                sym = mono_lookup_icall_symbol (method);
                }
@@ -7394,7 +7547,7 @@ mono_aot_get_direct_call_symbol (MonoJumpInfoType type, gconstpointer data)
 char*
 mono_aot_get_plt_symbol (MonoJumpInfoType type, gconstpointer data)
 {
-       MonoJumpInfo *ji = mono_mempool_alloc (llvm_acfg->mempool, sizeof (MonoJumpInfo));
+       MonoJumpInfo *ji = (MonoJumpInfo *)mono_mempool_alloc (llvm_acfg->mempool, sizeof (MonoJumpInfo));
        MonoPltEntry *plt_entry;
        const char *sym = NULL;
 
@@ -7407,9 +7560,9 @@ mono_aot_get_plt_symbol (MonoJumpInfoType type, gconstpointer data)
        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);
+                       sym = mono_lookup_jit_icall_symbol ((const char *)data);
                } else if (type == MONO_PATCH_INFO_ICALL_ADDR) {
-                       MonoMethod *method = (gpointer)data;
+                       MonoMethod *method = (MonoMethod *)data;
                        if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
                                sym = mono_lookup_icall_symbol (method);
                }
@@ -7823,7 +7976,7 @@ emit_info (MonoAotCompile *acfg)
                }
        }
 
-       acfg->stats.offsets_size += emit_offset_table (acfg, "method_info_offsets", acfg->nmethods, 10, offsets);
+       acfg->stats.offsets_size += emit_offset_table (acfg, "method_info_offsets", MONO_AOT_TABLE_METHOD_INFO_OFFSETS, acfg->nmethods, 10, offsets);
 
        g_free (offsets);
 }
@@ -7899,7 +8052,7 @@ mono_aot_method_hash (MonoMethod *method)
                ginst = ((MonoMethodInflated*)method)->context.method_inst;
 
        hashes_count = sig->param_count + 5 + (class_ginst ? class_ginst->type_argc : 0) + (ginst ? ginst->type_argc : 0);
-       hashes_start = g_malloc0 (hashes_count * sizeof (guint32));
+       hashes_start = (guint32 *)g_malloc0 (hashes_count * sizeof (guint32));
        hashes = hashes_start;
 
        /* Some wrappers are assigned to random classes */
@@ -8036,7 +8189,6 @@ static void
 emit_extra_methods (MonoAotCompile *acfg)
 {
        int i, table_size, buf_size;
-       char symbol [256];
        guint8 *p, *buf;
        guint32 *info_offsets;
        guint32 hash;
@@ -8050,14 +8202,14 @@ emit_extra_methods (MonoAotCompile *acfg)
        /* Emit method info */
        nmethods = 0;
        for (i = 0; i < acfg->extra_methods->len; ++i) {
-               MonoMethod *method = g_ptr_array_index (acfg->extra_methods, i);
-               MonoCompile *cfg = g_hash_table_lookup (acfg->method_to_cfg, method);
+               MonoMethod *method = (MonoMethod *)g_ptr_array_index (acfg->extra_methods, i);
+               MonoCompile *cfg = (MonoCompile *)g_hash_table_lookup (acfg->method_to_cfg, method);
 
                if (!cfg)
                        continue;
 
                buf_size = 10240;
-               p = buf = g_malloc (buf_size);
+               p = buf = (guint8 *)g_malloc (buf_size);
 
                nmethods ++;
 
@@ -8082,8 +8234,8 @@ emit_extra_methods (MonoAotCompile *acfg)
        chain_lengths = g_new0 (int, table_size);
        max_chain_length = 0;
        for (i = 0; i < acfg->extra_methods->len; ++i) {
-               MonoMethod *method = g_ptr_array_index (acfg->extra_methods, i);
-               MonoCompile *cfg = g_hash_table_lookup (acfg->method_to_cfg, method);
+               MonoMethod *method = (MonoMethod *)g_ptr_array_index (acfg->extra_methods, i);
+               MonoCompile *cfg = (MonoCompile *)g_hash_table_lookup (acfg->method_to_cfg, method);
                guint32 key, value;
 
                if (!cfg)
@@ -8098,11 +8250,11 @@ emit_extra_methods (MonoAotCompile *acfg)
                chain_lengths [hash] ++;
                max_chain_length = MAX (max_chain_length, chain_lengths [hash]);
 
-               new_entry = mono_mempool_alloc0 (acfg->mempool, sizeof (HashEntry));
+               new_entry = (HashEntry *)mono_mempool_alloc0 (acfg->mempool, sizeof (HashEntry));
                new_entry->key = key;
                new_entry->value = value;
 
-               entry = g_ptr_array_index (table, hash);
+               entry = (HashEntry *)g_ptr_array_index (table, hash);
                if (entry == NULL) {
                        new_entry->index = hash;
                        g_ptr_array_index (table, hash) = new_entry;
@@ -8119,11 +8271,11 @@ emit_extra_methods (MonoAotCompile *acfg)
        //printf ("MAX: %d\n", max_chain_length);
 
        buf_size = table->len * 12 + 4;
-       p = buf = g_malloc (buf_size);
+       p = buf = (guint8 *)g_malloc (buf_size);
        encode_int (table_size, p, &p);
 
        for (i = 0; i < table->len; ++i) {
-               HashEntry *entry = g_ptr_array_index (table, i);
+               HashEntry *entry = (HashEntry *)g_ptr_array_index (table, i);
 
                if (entry == NULL) {
                        encode_int (0, p, &p);
@@ -8142,38 +8294,22 @@ emit_extra_methods (MonoAotCompile *acfg)
        g_assert (p - buf <= buf_size);
 
        /* Emit the table */
-       if (acfg->llvm) {
-               mono_llvm_emit_aot_data ("extra_method_table", buf, p - buf);
-       } else {
-               sprintf (symbol, "extra_method_table");
-               emit_section_change (acfg, RODATA_SECT, 0);
-               emit_alignment (acfg, 8);
-               emit_label (acfg, symbol);
-               emit_bytes (acfg, buf, p - buf);
-       }
+       emit_aot_data (acfg, MONO_AOT_TABLE_EXTRA_METHOD_TABLE, "extra_method_table", buf, p - buf);
 
        /* 
         * Emit a table reverse mapping method indexes to their index in extra_method_info.
         * This is used by mono_aot_find_jit_info ().
         */
        buf_size = acfg->extra_methods->len * 8 + 4;
-       p = buf = g_malloc (buf_size);
+       p = buf = (guint8 *)g_malloc (buf_size);
        encode_int (acfg->extra_methods->len, p, &p);
        for (i = 0; i < acfg->extra_methods->len; ++i) {
-               MonoMethod *method = g_ptr_array_index (acfg->extra_methods, i);
+               MonoMethod *method = (MonoMethod *)g_ptr_array_index (acfg->extra_methods, i);
 
                encode_int (get_method_index (acfg, method), p, &p);
                encode_int (info_offsets [i], p, &p);
        }
-       if (acfg->llvm) {
-               mono_llvm_emit_aot_data ("extra_method_info_offsets", buf, p - buf);
-       } else {
-               sprintf (symbol, "extra_method_info_offsets");
-               emit_section_change (acfg, RODATA_SECT, 0);
-               emit_alignment (acfg, 8);
-               emit_label (acfg, symbol);
-               emit_bytes (acfg, buf, p - buf);
-       }
+       emit_aot_data (acfg, MONO_AOT_TABLE_EXTRA_METHOD_INFO_OFFSETS, "extra_method_info_offsets", buf, p - buf);
 }      
 
 static void
@@ -8218,7 +8354,7 @@ emit_exception_info (MonoAotCompile *acfg)
                g_free (seq_points_aot_file);
        }
 
-       acfg->stats.offsets_size += emit_offset_table (acfg, "ex_info_offsets", acfg->nmethods, 10, offsets);
+       acfg->stats.offsets_size += emit_offset_table (acfg, "ex_info_offsets", MONO_AOT_TABLE_EX_INFO_OFFSETS, acfg->nmethods, 10, offsets);
        g_free (offsets);
 }
 
@@ -8272,7 +8408,7 @@ emit_class_info (MonoAotCompile *acfg)
        for (i = 0; i < acfg->image->tables [MONO_TABLE_TYPEDEF].rows; ++i)
                offsets [i] = emit_klass_info (acfg, MONO_TOKEN_TYPE_DEF | (i + 1));
 
-       acfg->stats.offsets_size += emit_offset_table (acfg, "class_info_offsets", acfg->image->tables [MONO_TABLE_TYPEDEF].rows, 10, offsets);
+       acfg->stats.offsets_size += emit_offset_table (acfg, "class_info_offsets", MONO_AOT_TABLE_CLASS_INFO_OFFSETS, acfg->image->tables [MONO_TABLE_TYPEDEF].rows, 10, offsets);
        g_free (offsets);
 }
 
@@ -8290,7 +8426,6 @@ emit_class_name_table (MonoAotCompile *acfg)
        GPtrArray *table;
        char *full_name;
        guint8 *buf, *p;
-       char symbol [256];
        ClassNameTableEntry *entry, *new_entry;
 
        /*
@@ -8316,7 +8451,7 @@ emit_class_name_table (MonoAotCompile *acfg)
                new_entry = g_new0 (ClassNameTableEntry, 1);
                new_entry->token = token;
 
-               entry = g_ptr_array_index (table, hash);
+               entry = (ClassNameTableEntry *)g_ptr_array_index (table, hash);
                if (entry == NULL) {
                        new_entry->index = hash;
                        g_ptr_array_index (table, hash) = new_entry;
@@ -8332,14 +8467,14 @@ emit_class_name_table (MonoAotCompile *acfg)
 
        /* Emit the table */
        buf_size = table->len * 4 + 4;
-       p = buf = g_malloc0 (buf_size);
+       p = buf = (guint8 *)g_malloc0 (buf_size);
 
        /* FIXME: Optimize memory usage */
        g_assert (table_size < 65000);
        encode_int16 (table_size, p, &p);
        g_assert (table->len < 65000);
        for (i = 0; i < table->len; ++i) {
-               ClassNameTableEntry *entry = g_ptr_array_index (table, i);
+               ClassNameTableEntry *entry = (ClassNameTableEntry *)g_ptr_array_index (table, i);
 
                if (entry == NULL) {
                        encode_int16 (0, p, &p);
@@ -8354,22 +8489,13 @@ emit_class_name_table (MonoAotCompile *acfg)
        }
        g_assert (p - buf <= buf_size);
 
-       if (acfg->llvm) {
-               mono_llvm_emit_aot_data ("class_name_table", buf, p - buf);
-       } else {
-               sprintf (symbol, "class_name_table");
-               emit_section_change (acfg, RODATA_SECT, 0);
-               emit_alignment (acfg, 8);
-               emit_label (acfg, symbol);
-               emit_bytes (acfg, buf, p - buf);
-       }
+       emit_aot_data (acfg, MONO_AOT_TABLE_CLASS_NAME, "class_name_table", buf, p - buf);
 }
 
 static void
 emit_image_table (MonoAotCompile *acfg)
 {
        int i, buf_size;
-       char symbol [256];
        guint8 *buf, *p;
 
        /*
@@ -8384,7 +8510,7 @@ emit_image_table (MonoAotCompile *acfg)
                buf_size += strlen (image->assembly_name) + strlen (image->guid) + (aname->culture ? strlen (aname->culture) : 1) + strlen ((char*)aname->public_key_token) + 4;
        }
 
-       buf = p = g_malloc0 (buf_size);
+       buf = p = (guint8 *)g_malloc0 (buf_size);
        encode_int (acfg->image_table->len, p, &p);
        for (i = 0; i < acfg->image_table->len; i++) {
                MonoImage *image = (MonoImage*)g_ptr_array_index (acfg->image_table, i);
@@ -8409,15 +8535,7 @@ emit_image_table (MonoAotCompile *acfg)
        }
        g_assert (p - buf <= buf_size);
 
-       if (acfg->llvm) {
-               mono_llvm_emit_aot_data ("image_table", buf, p - buf);
-       } else {
-               sprintf (symbol, "image_table");
-               emit_section_change (acfg, RODATA_SECT, 1);
-               emit_alignment (acfg, 8);
-               emit_label (acfg, symbol);
-               emit_bytes (acfg, buf, p - buf);
-       }
+       emit_aot_data (acfg, MONO_AOT_TABLE_IMAGE_TABLE, "image_table", buf, p - buf);
 
        g_free (buf);
 }
@@ -8435,7 +8553,7 @@ emit_got_info (MonoAotCompile *acfg, gboolean llvm)
                acfg->plt_got_offset_base = acfg->got_offset;
                first_plt_got_patch = info->got_patches->len;
                for (i = 1; i < acfg->plt_offset; ++i) {
-                       MonoPltEntry *plt_entry = g_hash_table_lookup (acfg->plt_offset_to_entry, GUINT_TO_POINTER (i));
+                       MonoPltEntry *plt_entry = (MonoPltEntry *)g_hash_table_lookup (acfg->plt_offset_to_entry, GUINT_TO_POINTER (i));
 
                        g_ptr_array_add (info->got_patches, plt_entry->ji);
 
@@ -8458,16 +8576,16 @@ emit_got_info (MonoAotCompile *acfg, gboolean llvm)
 
        /* Encode info required to decode shared GOT entries */
        buf_size = info->got_patches->len * 128;
-       p = buf = mono_mempool_alloc (acfg->mempool, buf_size);
-       got_info_offsets = mono_mempool_alloc (acfg->mempool, info->got_patches->len * sizeof (guint32));
+       p = buf = (guint8 *)mono_mempool_alloc (acfg->mempool, buf_size);
+       got_info_offsets = (guint32 *)mono_mempool_alloc (acfg->mempool, info->got_patches->len * sizeof (guint32));
        if (!llvm) {
-               acfg->plt_got_info_offsets = mono_mempool_alloc (acfg->mempool, acfg->plt_offset * sizeof (guint32));
+               acfg->plt_got_info_offsets = (guint32 *)mono_mempool_alloc (acfg->mempool, acfg->plt_offset * sizeof (guint32));
                /* Unused */
                if (acfg->plt_offset)
                        acfg->plt_got_info_offsets [0] = 0;
        }
        for (i = 0; i < info->got_patches->len; ++i) {
-               MonoJumpInfo *ji = g_ptr_array_index (info->got_patches, i);
+               MonoJumpInfo *ji = (MonoJumpInfo *)g_ptr_array_index (info->got_patches, i);
                guint8 *p2;
 
                p = buf;
@@ -8487,7 +8605,7 @@ emit_got_info (MonoAotCompile *acfg, gboolean llvm)
        /* Emit got_info_offsets table */
 
        /* No need to emit offsets for the got plt entries, the plt embeds them directly */
-       acfg->stats.offsets_size += emit_offset_table (acfg, llvm ? "llvm_got_info_offsets" : "got_info_offsets", llvm ? acfg->llvm_got_offset : first_plt_got_patch, 10, (gint32*)got_info_offsets);
+       acfg->stats.offsets_size += emit_offset_table (acfg, llvm ? "llvm_got_info_offsets" : "got_info_offsets", llvm ? MONO_AOT_TABLE_LLVM_GOT_INFO_OFFSETS : MONO_AOT_TABLE_GOT_INFO_OFFSETS, llvm ? acfg->llvm_got_offset : first_plt_got_patch, 10, (gint32*)got_info_offsets);
 }
 
 static void
@@ -8553,7 +8671,7 @@ emit_globals (MonoAotCompile *acfg)
        for (i = 0; i < table_size; ++i)
                g_ptr_array_add (table, NULL);
        for (i = 0; i < acfg->globals->len; ++i) {
-               char *name = g_ptr_array_index (acfg->globals, i);
+               char *name = (char *)g_ptr_array_index (acfg->globals, i);
 
                hash = mono_metadata_str_hash (name) % table_size;
 
@@ -8561,7 +8679,7 @@ emit_globals (MonoAotCompile *acfg)
                new_entry = g_new0 (GlobalsTableEntry, 1);
                new_entry->value = i;
 
-               entry = g_ptr_array_index (table, hash);
+               entry = (GlobalsTableEntry *)g_ptr_array_index (table, hash);
                if (entry == NULL) {
                        new_entry->index = hash;
                        g_ptr_array_index (table, hash) = new_entry;
@@ -8585,7 +8703,7 @@ emit_globals (MonoAotCompile *acfg)
        g_assert (table_size < 65000);
        emit_int16 (acfg, table_size);
        for (i = 0; i < table->len; ++i) {
-               GlobalsTableEntry *entry = g_ptr_array_index (table, i);
+               GlobalsTableEntry *entry = (GlobalsTableEntry *)g_ptr_array_index (table, i);
 
                if (entry == NULL) {
                        emit_int16 (acfg, 0);
@@ -8601,7 +8719,7 @@ emit_globals (MonoAotCompile *acfg)
 
        /* Emit the names */
        for (i = 0; i < acfg->globals->len; ++i) {
-               char *name = g_ptr_array_index (acfg->globals, i);
+               char *name = (char *)g_ptr_array_index (acfg->globals, i);
 
                sprintf (symbol, "name_%d", i);
                emit_section_change (acfg, RODATA_SECT, 1);
@@ -8623,7 +8741,7 @@ emit_globals (MonoAotCompile *acfg)
        emit_pointer (acfg, symbol);
 
        for (i = 0; i < acfg->globals->len; ++i) {
-               char *name = g_ptr_array_index (acfg->globals, i);
+               char *name = (char *)g_ptr_array_index (acfg->globals, i);
 
                sprintf (symbol, "name_%d", i);
                emit_pointer (acfg, symbol);
@@ -8652,7 +8770,7 @@ emit_mem_end (MonoAotCompile *acfg)
 }
 
 static void
-init_aot_file_info (MonoAotCompile *acfg, MonoAotFileInfo *info, int gc_name_offset)
+init_aot_file_info (MonoAotCompile *acfg, MonoAotFileInfo *info)
 {
        int i;
 
@@ -8664,7 +8782,10 @@ init_aot_file_info (MonoAotCompile *acfg, MonoAotFileInfo *info, int gc_name_off
        info->flags = acfg->flags;
        info->opts = acfg->opts;
        info->simd_opts = acfg->simd_opts;
-       info->gc_name_index = gc_name_offset;
+       info->gc_name_index = acfg->gc_name_offset;
+       info->datafile_size = acfg->datafile_offset;
+       for (i = 0; i < MONO_AOT_TABLE_NUM; ++i)
+               info->table_offsets [i] = acfg->table_offsets [i];
        for (i = 0; i < MONO_AOT_TRAMP_NUM; ++i)
                info->num_trampolines [i] = acfg->num_trampolines [i];
        for (i = 0; i < MONO_AOT_TRAMP_NUM; ++i)
@@ -8712,20 +8833,25 @@ emit_aot_file_info (MonoAotCompile *acfg, MonoAotFileInfo *info)
                symbols [sindex ++] = NULL;
                symbols [sindex ++] = NULL;
        }
-       symbols [sindex ++] = "blob";
-       symbols [sindex ++] = "class_name_table";
-       symbols [sindex ++] = "class_info_offsets";
-       symbols [sindex ++] = "method_info_offsets";
-       symbols [sindex ++] = "ex_info_offsets";
-       symbols [sindex ++] = "extra_method_info_offsets";
-       symbols [sindex ++] = "extra_method_table";
-       symbols [sindex ++] = "got_info_offsets";
-       if (acfg->llvm)
-               symbols [sindex ++] = "llvm_got_info_offsets";
-       else
-               symbols [sindex ++] = NULL;
+       if (acfg->data_outfile) {
+               for (i = 0; i < MONO_AOT_TABLE_NUM; ++i)
+                       symbols [sindex ++] = NULL;
+       } else {
+               symbols [sindex ++] = "blob";
+               symbols [sindex ++] = "class_name_table";
+               symbols [sindex ++] = "class_info_offsets";
+               symbols [sindex ++] = "method_info_offsets";
+               symbols [sindex ++] = "ex_info_offsets";
+               symbols [sindex ++] = "extra_method_info_offsets";
+               symbols [sindex ++] = "extra_method_table";
+               symbols [sindex ++] = "got_info_offsets";
+               if (acfg->llvm)
+                       symbols [sindex ++] = "llvm_got_info_offsets";
+               else
+                       symbols [sindex ++] = NULL;
+               symbols [sindex ++] = "image_table";
+       }
        symbols [sindex ++] = "mem_end";
-       symbols [sindex ++] = "image_table";
        symbols [sindex ++] = "assembly_guid";
        symbols [sindex ++] = "runtime_version";
        if (acfg->num_trampoline_got_entries) {
@@ -8794,7 +8920,10 @@ emit_aot_file_info (MonoAotCompile *acfg, MonoAotFileInfo *info)
        emit_int32 (acfg, info->generic_tramp_num);
        emit_int32 (acfg, info->tramp_page_size);
        emit_int32 (acfg, info->nshared_got_entries);
+       emit_int32 (acfg, info->datafile_size);
 
+       for (i = 0; i < MONO_AOT_TABLE_NUM; ++i)
+               emit_int32 (acfg, info->table_offsets [i]);
        for (i = 0; i < MONO_AOT_TRAMP_NUM; ++i)
                emit_int32 (acfg, info->num_trampolines [i]);
        for (i = 0; i < MONO_AOT_TRAMP_NUM; ++i)
@@ -8834,8 +8963,6 @@ emit_aot_file_info (MonoAotCompile *acfg, MonoAotFileInfo *info)
 static void
 emit_file_info (MonoAotCompile *acfg)
 {
-       int gc_name_offset;
-       const char *gc_name;
        char *build_info;
        MonoAotFileInfo *info;
 
@@ -8852,15 +8979,8 @@ emit_file_info (MonoAotCompile *acfg)
        /* Emit a string holding the assembly name */
        emit_string_symbol (acfg, "assembly_name", acfg->image->assembly->aname.name);
 
-       /*
-        * The managed allocators are GC specific, so can't use an AOT image created by one GC
-        * in another.
-        */
-       gc_name = mono_gc_get_gc_name ();
-       gc_name_offset = add_to_blob (acfg, (guint8*)gc_name, strlen (gc_name) + 1);
-
        info = g_new0 (MonoAotFileInfo, 1);
-       init_aot_file_info (acfg, info, gc_name_offset);
+       init_aot_file_info (acfg, info);
 
        if (acfg->llvm)
                mono_llvm_emit_aot_file_info (info, acfg->has_jitted_code);
@@ -8871,19 +8991,9 @@ emit_file_info (MonoAotCompile *acfg)
 static void
 emit_blob (MonoAotCompile *acfg)
 {
-       char symbol [128];
-
-       if (acfg->llvm) {
-               mono_llvm_emit_aot_data ("blob", (guint8*)acfg->blob.data, acfg->blob.index);
-               return;
-       }
+       acfg->blob_closed = TRUE;
 
-       sprintf (symbol, "blob");
-       emit_section_change (acfg, RODATA_SECT, 1);
-       emit_alignment (acfg, 8);
-       emit_label (acfg, symbol);
-
-       emit_bytes (acfg, (guint8*)acfg->blob.data, acfg->blob.index);
+       emit_aot_data (acfg, MONO_AOT_TABLE_BLOB, "blob", (guint8*)acfg->blob.data, acfg->blob.index);
 }
 
 static void
@@ -8949,7 +9059,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->asm_debug_symbol, 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 ()));
+               mono_dwarf_writer_emit_method (acfg->dwarf, cfg, cfg->method, cfg->asm_symbol, symbol2, cfg->asm_debug_symbol, (guint8 *)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
 }
@@ -9062,7 +9172,7 @@ compile_methods (MonoAotCompile *acfg)
                methods = g_new0 (MonoMethod*, methods_len);
                //memcpy (methods, g_ptr_array_index (acfg->methods, 0), sizeof (MonoMethod*) * methods_len);
                for (i = 0; i < methods_len; ++i)
-                       methods [i] = g_ptr_array_index (acfg->methods, i);
+                       methods [i] = (MonoMethod *)g_ptr_array_index (acfg->methods, i);
                i = 0;
                while (i < methods_len) {
                        frag = g_ptr_array_new ();
@@ -9078,7 +9188,7 @@ compile_methods (MonoAotCompile *acfg)
                        user_data [1] = acfg;
                        user_data [2] = frag;
                        
-                       handle = mono_threads_create_thread ((gpointer)compile_thread_main, user_data, 0, 0, NULL);
+                       handle = mono_threads_create_thread ((LPTHREAD_START_ROUTINE)compile_thread_main, user_data, 0, 0, NULL);
                        g_ptr_array_add (threads, handle);
                }
                g_free (methods);
@@ -9093,7 +9203,7 @@ compile_methods (MonoAotCompile *acfg)
        /* Compile methods added by compile_method () or all methods if nthreads == 0 */
        for (i = methods_len; i < acfg->methods->len; ++i) {
                /* This can new methods to acfg->methods */
-               compile_method (acfg, g_ptr_array_index (acfg->methods, i));
+               compile_method (acfg, (MonoMethod *)g_ptr_array_index (acfg->methods, i));
        }
 }
 
@@ -9323,7 +9433,9 @@ acfg_create (MonoAssembly *ass, guint32 opts)
        acfg->klass_blob_hash = g_hash_table_new (NULL, NULL);
        acfg->method_blob_hash = g_hash_table_new (NULL, NULL);
        acfg->plt_entry_debug_sym_cache = g_hash_table_new (g_str_hash, g_str_equal);
-       mono_mutex_init_recursive (&acfg->mutex);
+       acfg->gsharedvt_in_signatures = g_hash_table_new ((GHashFunc)mono_signature_hash, (GEqualFunc)mono_metadata_signature_equal);
+       acfg->gsharedvt_out_signatures = g_hash_table_new ((GHashFunc)mono_signature_hash, (GEqualFunc)mono_metadata_signature_equal);
+       mono_os_mutex_init_recursive (&acfg->mutex);
 
        init_got_info (&acfg->got_info);
        init_got_info (&acfg->llvm_got_info);
@@ -9542,7 +9654,7 @@ static const char *preinited_jit_icalls[] = {
        "mono_aot_init_gshared_method_this",
        "mono_aot_init_gshared_method_rgctx",
        "mono_llvm_throw_corlib_exception",
-       "mono_resolve_vcall",
+       "mono_init_vtable_slot",
        "mono_helper_ldstr_mscorlib"
 };
 
@@ -9557,44 +9669,44 @@ add_preinit_got_slots (MonoAotCompile *acfg)
         * during method initialization etc.
         */
 
-       ji = mono_mempool_alloc0 (acfg->mempool, sizeof (MonoJumpInfo));
+       ji = (MonoJumpInfo *)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 = (MonoJumpInfo *)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 = (MonoJumpInfo *)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 = (MonoJumpInfo *)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 = (MonoJumpInfo *)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 = (MonoJumpInfo *)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);
 
-       ji = mono_mempool_alloc0 (acfg->mempool, sizeof (MonoJumpInfo));
+       ji = (MonoJumpInfo *)mono_mempool_alloc0 (acfg->mempool, sizeof (MonoJumpInfo));
        ji->type = MONO_PATCH_INFO_GC_NURSERY_BITS;
        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 = (MonoJumpInfo *)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);
@@ -9637,15 +9749,41 @@ mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options)
                acfg->logfile = fopen (acfg->aot_opts.logfile, "a+");
        }
 
+       if (acfg->aot_opts.data_outfile) {
+               acfg->data_outfile = fopen (acfg->aot_opts.data_outfile, "w+");
+               if (!acfg->data_outfile) {
+                       aot_printerrf (acfg, "Unable to create file '%s': %s\n", acfg->aot_opts.data_outfile, strerror (errno));
+                       return 1;
+               }
+               acfg->flags = (MonoAotFileFlags)(acfg->flags | MONO_AOT_FILE_FLAG_SEPARATE_DATA);
+       }
+
        //acfg->aot_opts.print_skipped_methods = TRUE;
 
-#if !defined(MONO_ARCH_GSHAREDVT_SUPPORTED) || !defined(ENABLE_GSHAREDVT)
+#if !defined(ENABLE_GSHAREDVT)
        if (opts & MONO_OPT_GSHAREDVT) {
                aot_printerrf (acfg, "-O=gsharedvt not supported on this platform.\n");
                return 1;
        }
 #endif
 
+#if !defined(MONO_ARCH_GSHAREDVT_SUPPORTED)
+       if (!acfg->aot_opts.llvm_only && (opts & MONO_OPT_GSHAREDVT)) {
+               aot_printerrf (acfg, "-O=gsharedvt not supported on this platform.\n");
+               return 1;
+       }
+#endif
+
+#if defined(ENABLE_GSHAREDVT)
+       if (acfg->aot_opts.llvm_only) {
+               acfg->opts |= MONO_OPT_GSHAREDVT;
+               opts |= MONO_OPT_GSHAREDVT;
+       }
+#endif
+
+       if (opts & MONO_OPT_GSHAREDVT)
+               mono_set_generic_sharing_vt_supported (TRUE);
+
        aot_printf (acfg, "Mono Ahead of Time compiler - compiling assembly %s\n", image->name);
 
 #ifndef MONO_ARCH_HAVE_FULL_AOT_TRAMPOLINES
@@ -9673,13 +9811,13 @@ mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options)
                        aot_printerrf (acfg, "The soft-debug AOT option requires the --debug option.\n");
                        return 1;
                }
-               acfg->flags |= MONO_AOT_FILE_FLAG_DEBUG;
+               acfg->flags = (MonoAotFileFlags)(acfg->flags | MONO_AOT_FILE_FLAG_DEBUG);
        }
 
        if (mono_use_llvm || acfg->aot_opts.llvm) {
                acfg->llvm = TRUE;
                acfg->aot_opts.asm_writer = TRUE;
-               acfg->flags |= MONO_AOT_FILE_FLAG_WITH_LLVM;
+               acfg->flags = (MonoAotFileFlags)(acfg->flags | MONO_AOT_FILE_FLAG_WITH_LLVM);
 
                if (acfg->aot_opts.soft_debug) {
                        aot_printerrf (acfg, "The 'soft-debug' option is not supported when compiling with LLVM.\n");
@@ -9708,10 +9846,10 @@ 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;
+               acfg->flags = (MonoAotFileFlags)(acfg->flags | MONO_AOT_FILE_FLAG_FULL_AOT);
 
        if (mono_threads_is_coop_enabled ())
-               acfg->flags |= MONO_AOT_FILE_FLAG_SAFEPOINTS;
+               acfg->flags = (MonoAotFileFlags)(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");
@@ -9738,9 +9876,9 @@ mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options)
        arch_init (acfg);
 
        if (acfg->llvm && acfg->thumb_mixed)
-               acfg->flags |= MONO_AOT_FILE_FLAG_LLVM_THUMB;
+               acfg->flags = (MonoAotFileFlags)(acfg->flags | MONO_AOT_FILE_FLAG_LLVM_THUMB);
        if (acfg->aot_opts.llvm_only)
-               acfg->flags |= MONO_AOT_FILE_FLAG_LLVM_ONLY;
+               acfg->flags = (MonoAotFileFlags)(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 */
@@ -9901,7 +10039,14 @@ mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options)
 
        emit_got (acfg);
 
-       emit_file_info (acfg);
+       {
+               /*
+                * The managed allocators are GC specific, so can't use an AOT image created by one GC
+                * in another.
+                */
+               const char *gc_name = mono_gc_get_gc_name ();
+               acfg->gc_name_offset = add_to_blob (acfg, (guint8*)gc_name, strlen (gc_name) + 1);
+       }
 
        emit_blob (acfg);
 
@@ -9909,6 +10054,8 @@ mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options)
 
        emit_globals (acfg);
 
+       emit_file_info (acfg);
+
        if (acfg->dwarf) {
                emit_dwarf_info (acfg);
                mono_dwarf_writer_close (acfg->dwarf);
@@ -9922,6 +10069,9 @@ mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options)
                fprintf (acfg->fp, "\n.section  .note.GNU-stack,\"\",@progbits\n");
        }
 
+       if (acfg->aot_opts.data_outfile)
+               fclose (acfg->data_outfile);
+
 #ifdef ENABLE_LLVM
        if (acfg->llvm) {
                gboolean res;