[runtime] Move MonoClass::flags to MonoClassDef.
[mono.git] / mono / mini / aot-compiler.c
index 34614773907bd8c6818564cc7b2d2aead45f5cf3..50676f5600286adcf021c783f37104589a9b8d85 100644 (file)
@@ -219,6 +219,7 @@ typedef struct MonoAotCompile {
        gboolean gas_line_numbers;
        /* Whenever to emit an object file directly from llc */
        gboolean llvm_owriter;
+       gboolean llvm_owriter_supported;
        MonoImageWriter *w;
        MonoDwarfWriter *dwarf;
        FILE *fp;
@@ -325,6 +326,9 @@ get_unwind_info_offset (MonoAotCompile *acfg, guint8 *encoded, guint32 encoded_l
 static char*
 get_plt_entry_debug_sym (MonoAotCompile *acfg, MonoJumpInfo *ji, GHashTable *cache);
 
+static void
+add_gsharedvt_wrappers (MonoAotCompile *acfg, MonoMethodSignature *sig, gboolean gsharedvt_in, gboolean gsharedvt_out);
+
 static void
 aot_printf (MonoAotCompile *acfg, const gchar *format, ...)
 {
@@ -879,6 +883,7 @@ arch_init (MonoAotCompile *acfg)
 {
        acfg->llc_args = g_string_new ("");
        acfg->as_args = g_string_new ("");
+       acfg->llvm_owriter_supported = TRUE;
 
        /*
         * The prefix LLVM likes to put in front of symbol names on darwin.
@@ -941,6 +946,10 @@ arch_init (MonoAotCompile *acfg)
 #ifdef MONOTOUCH
        acfg->global_symbols = TRUE;
 #endif
+
+#ifdef TARGET_ANDROID
+       acfg->llvm_owriter_supported = FALSE;
+#endif
 }
 
 #ifdef TARGET_ARM64
@@ -1145,7 +1154,7 @@ arm64_emit_specific_trampoline_pages (MonoAotCompile *acfg)
        /* Trampoline argument */
        arm_ldrx (code, ARMREG_IP1, ARMREG_IP0, 0);
 
-       /* Same as arch_emit_imt_thunk () */
+       /* Same as arch_emit_imt_trampoline () */
        labels [0] = code;
        arm_ldrx (code, ARMREG_IP0, ARMREG_IP1, 0);
        arm_cmpx (code, ARMREG_IP0, MONO_ARCH_RGCTX_REG);
@@ -1177,7 +1186,7 @@ arm64_emit_specific_trampoline_pages (MonoAotCompile *acfg)
        emit_code_bytes (acfg, buf, code - buf);
 
        common_tramp_size = code - buf;
-       acfg->tramp_page_code_offsets [MONO_AOT_TRAMP_IMT_THUNK] = common_tramp_size;
+       acfg->tramp_page_code_offsets [MONO_AOT_TRAMP_IMT] = common_tramp_size;
 
        arm64_emit_tramp_page_specific_code (acfg, pagesize, common_tramp_size, specific_tramp_size);
 }
@@ -1215,7 +1224,7 @@ arm64_emit_static_rgctx_trampoline (MonoAotCompile *acfg, int offset, int *tramp
 }
 
 static void
-arm64_emit_imt_thunk (MonoAotCompile *acfg, int offset, int *tramp_size)
+arm64_emit_imt_trampoline (MonoAotCompile *acfg, int offset, int *tramp_size)
 {
        guint8 buf [128];
        guint8 *code, *labels [16];
@@ -1758,7 +1767,7 @@ arch_emit_specific_trampoline_pages (MonoAotCompile *acfg)
 
        acfg->tramp_page_code_offsets [MONO_AOT_TRAMP_SPECIFIC] = 16;
        acfg->tramp_page_code_offsets [MONO_AOT_TRAMP_STATIC_RGCTX] = 16;
-       acfg->tramp_page_code_offsets [MONO_AOT_TRAMP_IMT_THUNK] = 72;
+       acfg->tramp_page_code_offsets [MONO_AOT_TRAMP_IMT] = 72;
        acfg->tramp_page_code_offsets [MONO_AOT_TRAMP_GSHAREDVT_ARG] = 16;
 
        /* Unwind info for specifc trampolines */
@@ -2133,9 +2142,9 @@ arch_emit_static_rgctx_trampoline (MonoAotCompile *acfg, int offset, int *tramp_
 }      
 
 /*
- * arch_emit_imt_thunk:
+ * arch_emit_imt_trampoline:
  *
- *   Emit an IMT thunk usable in full-aot mode. The thunk uses 1 got slot which
+ *   Emit an IMT trampoline usable in full-aot mode. The trampoline uses 1 got slot which
  * points to an array of pointer pairs. The pairs of the form [key, ptr], where
  * key is the IMT key, and ptr holds the address of a memory location holding
  * the address to branch to if the IMT arg matches the key. The array is 
@@ -2144,7 +2153,7 @@ arch_emit_static_rgctx_trampoline (MonoAotCompile *acfg, int offset, int *tramp_
  * TRAMP_SIZE is set to the size of the emitted trampoline.
  */
 static void
-arch_emit_imt_thunk (MonoAotCompile *acfg, int offset, int *tramp_size)
+arch_emit_imt_trampoline (MonoAotCompile *acfg, int offset, int *tramp_size)
 {
 #if defined(TARGET_AMD64)
        guint8 *buf, *code;
@@ -2333,7 +2342,7 @@ arch_emit_imt_thunk (MonoAotCompile *acfg, int offset, int *tramp_size)
 
        *tramp_size = code - buf + 4;
 #elif defined(TARGET_ARM64)
-       arm64_emit_imt_thunk (acfg, offset, tramp_size);
+       arm64_emit_imt_trampoline (acfg, offset, tramp_size);
 #elif defined(TARGET_POWERPC)
        guint8 buf [128];
        guint8 *code, *labels [16];
@@ -2761,7 +2770,7 @@ encode_klass_ref_inner (MonoAotCompile *acfg, MonoClass *klass, guint8 *buf, gui
         * information.
         */
 
-       if (klass->generic_class) {
+       if (mono_class_is_ginst (klass)) {
                guint32 token;
                g_assert (klass->type_token);
 
@@ -2771,8 +2780,8 @@ encode_klass_ref_inner (MonoAotCompile *acfg, MonoClass *klass, guint8 *buf, gui
                        encode_value (MONO_AOT_TYPEREF_TYPESPEC_TOKEN, p, &p);
                        encode_value (token, p, &p);
                } else {
-                       MonoClass *gclass = klass->generic_class->container_class;
-                       MonoGenericInst *inst = klass->generic_class->context.class_inst;
+                       MonoClass *gclass = mono_class_get_generic_class (klass)->container_class;
+                       MonoGenericInst *inst = mono_class_get_generic_class (klass)->context.class_inst;
                        static int count = 0;
                        guint8 *p1 = p;
 
@@ -2846,7 +2855,7 @@ encode_klass_ref (MonoAotCompile *acfg, MonoClass *klass, guint8 *buf, guint8 **
        /* 
         * The encoding of generic instances is large so emit them only once.
         */
-       if (klass->generic_class) {
+       if (mono_class_is_ginst (klass)) {
                guint32 token;
                g_assert (klass->type_token);
 
@@ -3607,7 +3616,7 @@ can_marshal_struct (MonoClass *klass)
        MonoMarshalType *info;
        int i;
 
-       if ((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_AUTO_LAYOUT)
+       if ((mono_class_get_flags (klass) & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_AUTO_LAYOUT)
                return FALSE;
 
        info = mono_marshal_load_type_info (klass);
@@ -3838,13 +3847,14 @@ add_wrappers (MonoAotCompile *acfg)
                csig->params [1] = &mono_defaults.exception_class->byval_arg;
                add_method (acfg, get_runtime_invoke_sig (csig));
 
-               /* Assembly runtime-invoke (string, bool) [DoAssemblyResolve] */
-               csig = mono_metadata_signature_alloc (mono_defaults.corlib, 2);
+               /* Assembly runtime-invoke (string, Assembly, bool) [DoAssemblyResolve] */
+               csig = mono_metadata_signature_alloc (mono_defaults.corlib, 3);
                csig->hasthis = 1;
                csig->ret = &(mono_class_load_from_name (
                                                                                        mono_defaults.corlib, "System.Reflection", "Assembly"))->byval_arg;
                csig->params [0] = &mono_defaults.string_class->byval_arg;
-               csig->params [1] = &mono_defaults.boolean_class->byval_arg;
+               csig->params [1] = &(mono_class_load_from_name (mono_defaults.corlib, "System.Reflection", "Assembly"))->byval_arg;
+               csig->params [2] = &mono_defaults.boolean_class->byval_arg;
                add_method (acfg, get_runtime_invoke_sig (csig));
 
                /* runtime-invoke used by finalizers */
@@ -4126,6 +4136,13 @@ add_wrappers (MonoAotCompile *acfg)
                        (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL)) {
                        add_method (acfg, mono_marshal_get_native_wrapper (method, TRUE, TRUE));
                }
+
+               if (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
+                       if (acfg->aot_opts.llvm_only) {
+                               /* The wrappers have a different signature (hasthis is not set) so need to add this too */
+                               add_gsharedvt_wrappers (acfg, mono_method_signature (method), FALSE, TRUE);
+                       }
+               }
        }
  
        /* native-to-managed wrappers */
@@ -4274,8 +4291,8 @@ has_type_vars (MonoClass *klass)
                return TRUE;
        if (klass->rank)
                return has_type_vars (klass->element_class);
-       if (klass->generic_class) {
-               MonoGenericContext *context = &klass->generic_class->context;
+       if (mono_class_is_ginst (klass)) {
+               MonoGenericContext *context = &mono_class_get_generic_class (klass)->context;
                if (context->class_inst) {
                        int i;
 
@@ -4327,13 +4344,19 @@ gboolean mono_aot_mode_is_full (MonoAotOptions *opts)
        return opts->mode == MONO_AOT_MODE_FULL;
 }
 
+static
+gboolean mono_aot_mode_is_hybrid (MonoAotOptions *opts)
+{
+       return opts->mode == MONO_AOT_MODE_HYBRID;
+}
+
 static void add_generic_class_with_depth (MonoAotCompile *acfg, MonoClass *klass, int depth, const char *ref);
 
 static void
 add_generic_class (MonoAotCompile *acfg, MonoClass *klass, gboolean force, const char *ref)
 {
        /* This might lead to a huge code blowup so only do it if neccesary */
-       if (!mono_aot_mode_is_full (&acfg->aot_opts) && !force)
+       if (!mono_aot_mode_is_full (&acfg->aot_opts) && !mono_aot_mode_is_hybrid (&acfg->aot_opts) && !force)
                return;
 
        add_generic_class_with_depth (acfg, klass, 0, ref);
@@ -4388,13 +4411,13 @@ add_generic_class_with_depth (MonoAotCompile *acfg, MonoClass *klass, int depth,
 
        mono_class_init (klass);
 
-       if (klass->generic_class && klass->generic_class->context.class_inst->is_open)
+       if (mono_class_is_ginst (klass) && mono_class_get_generic_class (klass)->context.class_inst->is_open)
                return;
 
        if (has_type_vars (klass))
                return;
 
-       if (!klass->generic_class && !klass->rank)
+       if (!mono_class_is_ginst (klass) && !klass->rank)
                return;
 
        if (mono_class_has_failure (klass))
@@ -4418,7 +4441,7 @@ add_generic_class_with_depth (MonoAotCompile *acfg, MonoClass *klass, int depth,
         * Use gsharedvt for generic collections with vtype arguments to avoid code blowup.
         * Enable this only for some classes since gsharedvt might not support all methods.
         */
-       if ((acfg->opts & MONO_OPT_GSHAREDVT) && klass->image == mono_defaults.corlib && klass->generic_class && klass->generic_class->context.class_inst && is_vt_inst (klass->generic_class->context.class_inst) &&
+       if ((acfg->opts & MONO_OPT_GSHAREDVT) && klass->image == mono_defaults.corlib && mono_class_is_ginst (klass) && mono_class_get_generic_class (klass)->context.class_inst && is_vt_inst (mono_class_get_generic_class (klass)->context.class_inst) &&
                (!strcmp (klass->name, "Dictionary`2") || !strcmp (klass->name, "List`1") || !strcmp (klass->name, "ReadOnlyCollection`1")))
                use_gsharedvt = TRUE;
 
@@ -4475,7 +4498,7 @@ add_generic_class_with_depth (MonoAotCompile *acfg, MonoClass *klass, int depth,
         */
        if (klass->image == mono_defaults.corlib && !strcmp (klass->name_space, "System.Collections.Generic") &&
                (!strcmp(klass->name, "ICollection`1") || !strcmp (klass->name, "IEnumerable`1") || !strcmp (klass->name, "IList`1") || !strcmp (klass->name, "IEnumerator`1") || !strcmp (klass->name, "IReadOnlyList`1"))) {
-               MonoClass *tclass = mono_class_from_mono_type (klass->generic_class->context.class_inst->type_argv [0]);
+               MonoClass *tclass = mono_class_from_mono_type (mono_class_get_generic_class (klass)->context.class_inst->type_argv [0]);
                MonoClass *array_class = mono_bounded_array_class_get (tclass, 1, FALSE);
                gpointer iter;
                char *name_prefix;
@@ -4496,7 +4519,7 @@ add_generic_class_with_depth (MonoAotCompile *acfg, MonoClass *klass, int depth,
                                        break;
                        }
                        g_assert (nclass);
-                       nclass = mono_class_inflate_generic_class_checked (nclass, mono_generic_class_get_context (klass->generic_class), &error);
+                       nclass = mono_class_inflate_generic_class_checked (nclass, mono_generic_class_get_context (mono_class_get_generic_class (klass)), &error);
                        mono_error_assert_ok (&error); /* FIXME don't swallow the error */
                        add_generic_class (acfg, nclass, FALSE, "ICollection<T>");
                }
@@ -4516,7 +4539,7 @@ add_generic_class_with_depth (MonoAotCompile *acfg, MonoClass *klass, int depth,
        /* Add an instance of GenericComparer<T> which is created dynamically by Comparer<T> */
        if (klass->image == mono_defaults.corlib && !strcmp (klass->name_space, "System.Collections.Generic") && !strcmp (klass->name, "Comparer`1")) {
                MonoError error;
-               MonoClass *tclass = mono_class_from_mono_type (klass->generic_class->context.class_inst->type_argv [0]);
+               MonoClass *tclass = mono_class_from_mono_type (mono_class_get_generic_class (klass)->context.class_inst->type_argv [0]);
                MonoClass *icomparable, *gcomparer, *icomparable_inst;
                MonoGenericContext ctx;
                MonoType *args [16];
@@ -4544,7 +4567,7 @@ add_generic_class_with_depth (MonoAotCompile *acfg, MonoClass *klass, int depth,
        /* Add an instance of GenericEqualityComparer<T> which is created dynamically by EqualityComparer<T> */
        if (klass->image == mono_defaults.corlib && !strcmp (klass->name_space, "System.Collections.Generic") && !strcmp (klass->name, "EqualityComparer`1")) {
                MonoError error;
-               MonoClass *tclass = mono_class_from_mono_type (klass->generic_class->context.class_inst->type_argv [0]);
+               MonoClass *tclass = mono_class_from_mono_type (mono_class_get_generic_class (klass)->context.class_inst->type_argv [0]);
                MonoClass *iface, *gcomparer, *iface_inst;
                MonoGenericContext ctx;
                MonoType *args [16];
@@ -4573,7 +4596,7 @@ add_generic_class_with_depth (MonoAotCompile *acfg, MonoClass *klass, int depth,
        /* Add an instance of EnumComparer<T> which is created dynamically by EqualityComparer<T> for enums */
        if (klass->image == mono_defaults.corlib && !strcmp (klass->name_space, "System.Collections.Generic") && !strcmp (klass->name, "EqualityComparer`1")) {
                MonoClass *enum_comparer;
-               MonoClass *tclass = mono_class_from_mono_type (klass->generic_class->context.class_inst->type_argv [0]);
+               MonoClass *tclass = mono_class_from_mono_type (mono_class_get_generic_class (klass)->context.class_inst->type_argv [0]);
                MonoGenericContext ctx;
                MonoType *args [16];
 
@@ -4595,7 +4618,7 @@ add_generic_class_with_depth (MonoAotCompile *acfg, MonoClass *klass, int depth,
        /* Add an instance of ObjectComparer<T> which is created dynamically by Comparer<T> for enums */
        if (klass->image == mono_defaults.corlib && !strcmp (klass->name_space, "System.Collections.Generic") && !strcmp (klass->name, "Comparer`1")) {
                MonoClass *comparer;
-               MonoClass *tclass = mono_class_from_mono_type (klass->generic_class->context.class_inst->type_argv [0]);
+               MonoClass *tclass = mono_class_from_mono_type (mono_class_get_generic_class (klass)->context.class_inst->type_argv [0]);
                MonoGenericContext ctx;
                MonoType *args [16];
 
@@ -4990,7 +5013,7 @@ is_direct_callable (MonoAotCompile *acfg, MonoMethod *method, MonoJumpInfo *patc
                if (callee_cfg) {
                        gboolean direct_callable = TRUE;
 
-                       if (direct_callable && !(!callee_cfg->has_got_slots && (callee_cfg->method->klass->flags & TYPE_ATTRIBUTE_BEFORE_FIELD_INIT)))
+                       if (direct_callable && !(!callee_cfg->has_got_slots && (mono_class_get_flags (callee_cfg->method->klass) & TYPE_ATTRIBUTE_BEFORE_FIELD_INIT)))
                                direct_callable = FALSE;
                        if ((callee_cfg->method->iflags & METHOD_IMPL_ATTRIBUTE_SYNCHRONIZED) && (!method || method->wrapper_type != MONO_WRAPPER_SYNCHRONIZED))
                                // FIXME: Maybe call the wrapper directly ?
@@ -6704,7 +6727,7 @@ emit_trampolines (MonoAotCompile *acfg)
                 * These include the following:
                 * - specific trampolines
                 * - static rgctx invoke trampolines
-                * - imt thunks
+                * - imt trampolines
                 * These trampolines have the same code, they are parameterized by GOT 
                 * slots. 
                 * They are defined in this file, in the arch_... routines instead of
@@ -6740,8 +6763,8 @@ emit_trampolines (MonoAotCompile *acfg)
                        case MONO_AOT_TRAMP_STATIC_RGCTX:
                                sprintf (symbol, "static_rgctx_trampolines");
                                break;
-                       case MONO_AOT_TRAMP_IMT_THUNK:
-                               sprintf (symbol, "imt_thunks");
+                       case MONO_AOT_TRAMP_IMT:
+                               sprintf (symbol, "imt_trampolines");
                                break;
                        case MONO_AOT_TRAMP_GSHAREDVT_ARG:
                                sprintf (symbol, "gsharedvt_arg_trampolines");
@@ -6772,8 +6795,8 @@ emit_trampolines (MonoAotCompile *acfg)
                                        arch_emit_static_rgctx_trampoline (acfg, tramp_got_offset, &tramp_size);                                
                                        tramp_got_offset += 2;
                                        break;
-                               case MONO_AOT_TRAMP_IMT_THUNK:
-                                       arch_emit_imt_thunk (acfg, tramp_got_offset, &tramp_size);
+                               case MONO_AOT_TRAMP_IMT:
+                                       arch_emit_imt_trampoline (acfg, tramp_got_offset, &tramp_size);
                                        tramp_got_offset += 1;
                                        break;
                                case MONO_AOT_TRAMP_GSHAREDVT_ARG:
@@ -7306,7 +7329,7 @@ is_concrete_type (MonoType *t)
                if (!MONO_TYPE_ISSTRUCT (t))
                        return TRUE;
                klass = mono_class_from_mono_type (t);
-               orig_ctx = &klass->generic_class->context;
+               orig_ctx = &mono_class_get_generic_class (klass)->context;
 
                inst = orig_ctx->class_inst;
                if (inst) {
@@ -7622,7 +7645,7 @@ compile_method (MonoAotCompile *acfg, MonoMethod *method)
                        case MONO_PATCH_INFO_VTABLE: {
                                MonoClass *klass = patch_info->data.klass;
 
-                               if (klass->generic_class && !mini_class_is_generic_sharable (klass))
+                               if (mono_class_is_ginst (klass) && !mini_class_is_generic_sharable (klass))
                                        add_generic_class_with_depth (acfg, klass, depth + 5, "vtable");
                                break;
                        }
@@ -7630,7 +7653,7 @@ compile_method (MonoAotCompile *acfg, MonoMethod *method)
                                MonoClass *klass = patch_info->data.field->parent;
 
                                /* The .cctor needs to run at runtime. */
-                               if (klass->generic_class && !mono_generic_context_is_sharable_full (&klass->generic_class->context, FALSE, FALSE) && mono_class_get_cctor (klass))
+                               if (mono_class_is_ginst (klass) && !mono_generic_context_is_sharable_full (&mono_class_get_generic_class (klass)->context, FALSE, FALSE) && mono_class_get_cctor (klass))
                                        add_extra_method_with_depth (acfg, mono_class_get_cctor (klass), depth + 1);
                                break;
                        }
@@ -8363,7 +8386,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 && !(acfg->aot_opts.llvm_only && cfg->compile_llvm)) {
+               if (mono_aot_mode_is_full (&acfg->aot_opts) && cfg->orig_method->klass->valuetype) {
                        sprintf (symbol, "ut_%d", get_method_index (acfg, method));
 
                        emit_section_change (acfg, ".text", 0);
@@ -8445,11 +8468,7 @@ emit_code (MonoAotCompile *acfg)
                int call_size;
 
                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, symbol, 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);
+                       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, symbol, FALSE, FALSE, NULL, &call_size);
                }
@@ -8478,7 +8497,7 @@ emit_code (MonoAotCompile *acfg)
 
                method = cfg->orig_method;
 
-               if (mono_aot_mode_is_full (&acfg->aot_opts) && cfg->orig_method->klass->valuetype && !(acfg->aot_opts.llvm_only && cfg->compile_llvm)) {
+               if (mono_aot_mode_is_full (&acfg->aot_opts) && cfg->orig_method->klass->valuetype) {
                        index = get_method_index (acfg, method);
 
                        emit_int32 (acfg, index);
@@ -8508,7 +8527,7 @@ emit_code (MonoAotCompile *acfg)
 
                method = cfg->orig_method;
 
-               if (mono_aot_mode_is_full (&acfg->aot_opts) && cfg->orig_method->klass->valuetype && !(acfg->aot_opts.llvm_only && cfg->compile_llvm)) {
+               if (mono_aot_mode_is_full (&acfg->aot_opts) && cfg->orig_method->klass->valuetype) {
 #ifdef MONO_ARCH_AOT_SUPPORTED
                        int call_size;
 
@@ -8611,8 +8630,8 @@ mono_aot_method_hash (MonoMethod *method)
 
        sig = mono_method_signature (method);
 
-       if (method->klass->generic_class)
-               class_ginst = method->klass->generic_class->context.class_inst;
+       if (mono_class_is_ginst (method->klass))
+               class_ginst = mono_class_get_generic_class (method->klass)->context.class_inst;
        if (method->is_inflated)
                ginst = ((MonoMethodInflated*)method)->context.method_inst;
 
@@ -8629,8 +8648,8 @@ mono_aot_method_hash (MonoMethod *method)
        if (!method->wrapper_type) {
                char *full_name;
 
-               if (klass->generic_class)
-                       full_name = mono_type_full_name (&klass->generic_class->container_class->byval_arg);
+               if (mono_class_is_ginst (klass))
+                       full_name = mono_type_full_name (&mono_class_get_generic_class (klass)->container_class->byval_arg);
                else
                        full_name = mono_type_full_name (&klass->byval_arg);
 
@@ -8685,7 +8704,7 @@ mono_aot_method_hash (MonoMethod *method)
                break;
        }
        
-       free (hashes_start);
+       g_free (hashes_start);
        
        return c;
 }
@@ -8887,13 +8906,13 @@ emit_extra_methods (MonoAotCompile *acfg)
 static void
 generate_aotid (guint8* aotid)
 {
-       gpointer *rand_handle;
+       gpointer rand_handle;
        MonoError error;
 
        mono_rand_open ();
        rand_handle = mono_rand_init (NULL, 0);
 
-       mono_rand_try_get_bytes (rand_handle, aotid, 16, &error);
+       mono_rand_try_get_bytes (&rand_handle, aotid, 16, &error);
        mono_error_assert_ok (&error);
 
        mono_rand_close (rand_handle);
@@ -9468,7 +9487,7 @@ emit_aot_file_info (MonoAotCompile *acfg, MonoAotFileInfo *info)
        if (acfg->num_trampoline_got_entries) {
                symbols [sindex ++] = "specific_trampolines";
                symbols [sindex ++] = "static_rgctx_trampolines";
-               symbols [sindex ++] = "imt_thunks";
+               symbols [sindex ++] = "imt_trampolines";
                symbols [sindex ++] = "gsharedvt_arg_trampolines";
        } else {
                symbols [sindex ++] = NULL;
@@ -9772,10 +9791,9 @@ compile_methods (MonoAotCompile *acfg)
                GPtrArray *frag;
                int len, j;
                GPtrArray *threads;
-               HANDLE handle;
+               MonoThreadHandle *thread_handle;
                gpointer *user_data;
                MonoMethod **methods;
-               MonoThreadParm tp;
 
                methods_len = acfg->methods->len;
 
@@ -9806,16 +9824,14 @@ compile_methods (MonoAotCompile *acfg)
                        user_data [1] = acfg;
                        user_data [2] = frag;
                        
-                       tp.priority = MONO_THREAD_PRIORITY_NORMAL;
-                       tp.stack_size = 0;
-                       tp.creation_flags = 0;
-                       handle = mono_threads_create_thread (compile_thread_main, (gpointer) user_data, &tp, NULL);
-                       g_ptr_array_add (threads, handle);
+                       thread_handle = mono_threads_create_thread (compile_thread_main, (gpointer) user_data, NULL, NULL);
+                       g_ptr_array_add (threads, thread_handle);
                }
                g_free (methods);
 
                for (i = 0; i < threads->len; ++i) {
-                       WaitForSingleObjectEx (g_ptr_array_index (threads, i), INFINITE, FALSE);
+                       mono_thread_info_wait_one_handle (g_ptr_array_index (threads, i), INFINITE, FALSE);
+                       mono_threads_close_thread_handle (g_ptr_array_index (threads, i));
                }
        } else {
                methods_len = 0;
@@ -9964,16 +9980,23 @@ compile_asm (MonoAotCompile *acfg)
                wrap_path (g_strdup_printf ("%s.o", acfg->tmpfname)), ld_flags);
 #else
        // Default (linux)
-       char *args = g_strdup_printf ("%s -shared -o %s %s %s %s", LD_OPTIONS,
-               wrap_path (tmp_outfile_name), wrap_path (llvm_ofile),
-               wrap_path (g_strdup_printf ("%s.o", acfg->tmpfname)), ld_flags);
-
-       if (acfg->llvm) {
-               command = g_strdup_printf ("clang++ %s", args);
+       if (acfg->aot_opts.tool_prefix) {
+               /* Cross compiling */
+               command = g_strdup_printf ("\"%sld\" %s -shared -o %s %s %s %s", tool_prefix, LD_OPTIONS,
+                                                                  wrap_path (tmp_outfile_name), wrap_path (llvm_ofile),
+                                                                  wrap_path (g_strdup_printf ("%s.o", acfg->tmpfname)), ld_flags);
        } else {
-               command = g_strdup_printf ("\"%sld\" %s", tool_prefix, args);
+               char *args = g_strdup_printf ("%s -shared -o %s %s %s %s", LD_OPTIONS,
+                                                                         wrap_path (tmp_outfile_name), wrap_path (llvm_ofile),
+                                                                         wrap_path (g_strdup_printf ("%s.o", acfg->tmpfname)), ld_flags);
+
+               if (acfg->llvm) {
+                       command = g_strdup_printf ("clang++ %s", args);
+               } else {
+                       command = g_strdup_printf ("\"%sld\" %s", tool_prefix, args);
+               }
+               g_free (args);
        }
-       g_free (args);
 
 #endif
        aot_printf (acfg, "Executing the native linker: %s\n", command);
@@ -10415,38 +10438,27 @@ mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options)
        //acfg->aot_opts.print_skipped_methods = TRUE;
 
 #if !defined(MONO_ARCH_GSHAREDVT_SUPPORTED)
-       if (opts & MONO_OPT_GSHAREDVT) {
+       if (acfg->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");
+       if (acfg->aot_opts.llvm_only) {
+               aot_printerrf (acfg, "--aot=llvmonly requires a runtime that supports gsharedvt.\n");
                return 1;
        }
+#else
+       if (acfg->aot_opts.llvm_only || mono_aot_mode_is_full (&acfg->aot_opts) || mono_aot_mode_is_hybrid (&acfg->aot_opts))
+               acfg->opts |= MONO_OPT_GSHAREDVT;
 #endif
 
+#if !defined(ENABLE_LLVM)
        if (acfg->aot_opts.llvm_only) {
-#ifndef MONO_ARCH_GSHAREDVT_SUPPORTED
-               aot_printerrf (acfg, "--aot=llvmonly requires a runtime that supports gsharedvt.\n");
-               return 1;
-#endif
-#ifndef ENABLE_LLVM
                aot_printerrf (acfg, "--aot=llvmonly requires a runtime compiled with llvm support.\n");
                return 1;
-#endif
-       }
-
-#if defined(MONO_ARCH_GSHAREDVT_SUPPORTED)
-       if (acfg->aot_opts.llvm_only || mono_aot_mode_is_full (&acfg->aot_opts)) {
-               acfg->opts |= MONO_OPT_GSHAREDVT;
-               opts |= MONO_OPT_GSHAREDVT;
        }
 #endif
 
-       if (opts & MONO_OPT_GSHAREDVT)
+       if (acfg->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);
@@ -10498,22 +10510,9 @@ mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options)
                mini_llvm_init ();
 
                if (acfg->aot_opts.asm_only && !acfg->aot_opts.llvm_outfile) {
-                       aot_printerrf (acfg, "Compiling with LLVM and the asm-only option requires the llvm-outputfile= option.");
+                       aot_printerrf (acfg, "Compiling with LLVM and the asm-only option requires the llvm-outfile= option.\n");
                        return 1;
                }
-
-               /*
-                * Emit all LLVM code into a separate assembly/object file and link with it
-                * normally.
-                */
-               if (!acfg->aot_opts.asm_only) {
-                       acfg->llvm_owriter = TRUE;
-               } else if (acfg->aot_opts.llvm_outfile) {
-                       int len = strlen (acfg->aot_opts.llvm_outfile);
-
-                       if (len >= 2 && acfg->aot_opts.llvm_outfile [len - 2] == '.' && acfg->aot_opts.llvm_outfile [len - 1] == 'o')
-                               acfg->llvm_owriter = TRUE;
-               }
        }
 
        if (mono_aot_mode_is_full (&acfg->aot_opts))
@@ -10536,7 +10535,7 @@ mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options)
 #ifdef MONO_ARCH_GSHARED_SUPPORTED
        acfg->num_trampolines [MONO_AOT_TRAMP_STATIC_RGCTX] = mono_aot_mode_is_full (&acfg->aot_opts) ? acfg->aot_opts.nrgctx_trampolines : 0;
 #endif
-       acfg->num_trampolines [MONO_AOT_TRAMP_IMT_THUNK] = mono_aot_mode_is_full (&acfg->aot_opts) ? acfg->aot_opts.nimt_trampolines : 0;
+       acfg->num_trampolines [MONO_AOT_TRAMP_IMT] = mono_aot_mode_is_full (&acfg->aot_opts) ? acfg->aot_opts.nimt_trampolines : 0;
 #ifdef MONO_ARCH_GSHAREDVT_SUPPORTED
        if (acfg->opts & MONO_OPT_GSHAREDVT)
                acfg->num_trampolines [MONO_AOT_TRAMP_GSHAREDVT_ARG] = mono_aot_mode_is_full (&acfg->aot_opts) ? acfg->aot_opts.ngsharedvt_arg_trampolines : 0;
@@ -10546,6 +10545,22 @@ mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options)
 
        arch_init (acfg);
 
+       if (mono_use_llvm || acfg->aot_opts.llvm) {
+
+               /*
+                * Emit all LLVM code into a separate assembly/object file and link with it
+                * normally.
+                */
+               if (!acfg->aot_opts.asm_only && acfg->llvm_owriter_supported) {
+                       acfg->llvm_owriter = TRUE;
+               } else if (acfg->aot_opts.llvm_outfile) {
+                       int len = strlen (acfg->aot_opts.llvm_outfile);
+
+                       if (len >= 2 && acfg->aot_opts.llvm_outfile [len - 2] == '.' && acfg->aot_opts.llvm_outfile [len - 1] == 'o')
+                               acfg->llvm_owriter = TRUE;
+               }
+       }
+
        if (acfg->llvm && acfg->thumb_mixed)
                acfg->flags = (MonoAotFileFlags)(acfg->flags | MONO_AOT_FILE_FLAG_LLVM_THUMB);
        if (acfg->aot_opts.llvm_only)
@@ -10568,7 +10583,7 @@ mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options)
 
        acfg->method_index = 1;
 
-       if (mono_aot_mode_is_full (&acfg->aot_opts))
+       if (mono_aot_mode_is_full (&acfg->aot_opts) || mono_aot_mode_is_hybrid (&acfg->aot_opts))
                mono_set_partial_sharing_supported (TRUE);
 
        res = collect_methods (acfg);