Merge pull request #2333 from joelmartinez/docs-classic-fix
[mono.git] / mono / mini / mini-trampolines.c
index d4af8df57a08e4065f746f834cfc369e426a6a9c..116d97782807134fd85cfcd7add1473b1753657d 100644 (file)
@@ -27,8 +27,8 @@ static GHashTable *rgctx_lazy_fetch_trampoline_hash;
 static GHashTable *rgctx_lazy_fetch_trampoline_hash_addr;
 static guint32 trampoline_calls, jit_trampolines, unbox_trampolines, static_rgctx_trampolines;
 
-#define mono_trampolines_lock() mono_mutex_lock (&trampolines_mutex)
-#define mono_trampolines_unlock() mono_mutex_unlock (&trampolines_mutex)
+#define mono_trampolines_lock() mono_os_mutex_lock (&trampolines_mutex)
+#define mono_trampolines_unlock() mono_os_mutex_unlock (&trampolines_mutex)
 static mono_mutex_t trampolines_mutex;
 
 #ifdef MONO_ARCH_GSHARED_SUPPORTED
@@ -41,8 +41,8 @@ typedef struct {
 static gint
 rgctx_tramp_info_equal (gconstpointer ka, gconstpointer kb)
 {
-       const RgctxTrampInfo *i1 = ka;
-       const RgctxTrampInfo *i2 = kb;
+       const RgctxTrampInfo *i1 = (const RgctxTrampInfo *)ka;
+       const RgctxTrampInfo *i2 = (const RgctxTrampInfo *)kb;
 
        if (i1->m == i2->m && i1->addr == i2->addr)
                return 1;
@@ -53,7 +53,7 @@ rgctx_tramp_info_equal (gconstpointer ka, gconstpointer kb)
 static guint
 rgctx_tramp_info_hash (gconstpointer data)
 {
-       const RgctxTrampInfo *info = data;
+       const RgctxTrampInfo *info = (const RgctxTrampInfo *)data;
 
        return GPOINTER_TO_UINT (info->m) ^ GPOINTER_TO_UINT (info->addr);
 }
@@ -112,11 +112,11 @@ mono_create_static_rgctx_trampoline (MonoMethod *m, gpointer addr)
        if (mono_aot_only)
                res = mono_aot_get_static_rgctx_trampoline (ctx, addr);
        else
-               res = mono_arch_get_static_rgctx_trampoline (m, ctx, addr);
+               res = mono_arch_get_static_rgctx_trampoline (m, (MonoMethodRuntimeGenericContext *)ctx, addr);
 
        mono_domain_lock (domain);
        /* Duplicates inserted while we didn't hold the lock are OK */
-       info = mono_domain_alloc (domain, sizeof (RgctxTrampInfo));
+       info = (RgctxTrampInfo *)mono_domain_alloc (domain, sizeof (RgctxTrampInfo));
        info->m = m;
        info->addr = addr;
        g_hash_table_insert (domain_jit_info (domain)->static_rgctx_trampoline_hash, info, res);
@@ -167,7 +167,7 @@ mini_resolve_imt_method (MonoVTable *vt, gpointer *vtable_slot, MonoMethod *imt_
        /* This has to be variance aware since imt_method can be from an interface that vt->klass doesn't directly implement */
        interface_offset = mono_class_interface_offset_with_variance (vt->klass, imt_method->klass, &variance_used);
        if (interface_offset < 0)
-               g_error ("%s doesn't implement interface %s\n", mono_type_get_name_full (&vt->klass->byval_arg, 0), mono_type_get_name_full (&imt_method->klass->byval_arg, 0));
+               g_error ("%s doesn't implement interface %s\n", mono_type_get_name_full (&vt->klass->byval_arg, MONO_TYPE_NAME_FORMAT_IL), mono_type_get_name_full (&imt_method->klass->byval_arg, MONO_TYPE_NAME_FORMAT_IL));
 
        *variant_iface = NULL;
        if (imt_method->is_inflated && ((MonoMethodInflated*)imt_method)->context.method_inst) {
@@ -182,7 +182,8 @@ mini_resolve_imt_method (MonoVTable *vt, gpointer *vtable_slot, MonoMethod *imt_
        /* We can only use the AOT compiled code if we don't require further processing */
        lookup_aot = !generic_virtual & !variant_iface;
 
-       mono_vtable_build_imt_slot (vt, mono_method_get_imt_slot (imt_method));
+       if (!mono_llvm_only)
+               mono_vtable_build_imt_slot (vt, mono_method_get_imt_slot (imt_method));
 
        if (imt_method->is_inflated && ((MonoMethodInflated*)imt_method)->context.method_inst) {
                MonoError error;
@@ -203,7 +204,7 @@ mini_resolve_imt_method (MonoVTable *vt, gpointer *vtable_slot, MonoMethod *imt_
        } else {
                /* Avoid loading metadata or creating a generic vtable if possible */
                if (lookup_aot && !vt->klass->valuetype)
-                       aot_addr = mono_aot_get_method_from_vt_slot (mono_domain_get (), vt, interface_offset + mono_method_get_vtable_slot (imt_method));
+                       aot_addr = (guint8 *)mono_aot_get_method_from_vt_slot (mono_domain_get (), vt, interface_offset + mono_method_get_vtable_slot (imt_method));
                else
                        aot_addr = NULL;
                if (aot_addr)
@@ -298,7 +299,7 @@ mini_add_method_trampoline (MonoMethod *m, gpointer compiled_method, gboolean ad
        MonoJitInfo *ji;
 
        // FIXME: This loads information from AOT (perf problem)
-       ji = mini_jit_info_table_find (mono_domain_get (), mono_get_addr_from_ftnptr (compiled_method), NULL);
+       ji = mini_jit_info_table_find (mono_domain_get (), (char *)mono_get_addr_from_ftnptr (compiled_method), NULL);
        callee_gsharedvt = mini_jit_info_is_gsharedvt (ji);
 
        callee_array_helper = FALSE;
@@ -328,7 +329,7 @@ mini_add_method_trampoline (MonoMethod *m, gpointer compiled_method, gboolean ad
        addr = compiled_method;
 
        if (add_unbox_tramp) {
-               /* 
+               /*
                 * The unbox trampolines call the method directly, so need to add
                 * an rgctx tramp before them.
                 */
@@ -353,6 +354,8 @@ mini_add_method_trampoline (MonoMethod *m, gpointer compiled_method, gboolean ad
 
                addr = mini_get_gsharedvt_wrapper (TRUE, addr, sig, gsig, -1, FALSE);
 
+               if (mono_llvm_only)
+                       g_assert_not_reached ();
                //printf ("IN: %s\n", mono_method_full_name (m, TRUE));
        }
 
@@ -361,17 +364,140 @@ mini_add_method_trampoline (MonoMethod *m, gpointer compiled_method, gboolean ad
                /* FIXME: ji->from_aot is not set for llvm methods */
                if (ji && (ji->from_aot || mono_aot_only)) {
                        /* In AOT mode, compiled_method points to one of the InternalArray methods in Array. */
-                       if (mono_method_needs_static_rgctx_invoke (jinfo_get_method (ji), TRUE))
+                       if (!mono_llvm_only && mono_method_needs_static_rgctx_invoke (jinfo_get_method (ji), TRUE))
                                add_static_rgctx_tramp = TRUE;
                }
        }
 
+       if (mono_llvm_only)
+               add_static_rgctx_tramp = FALSE;
+
        if (add_static_rgctx_tramp)
                addr = mono_create_static_rgctx_trampoline (m, addr);
 
        return addr;
 }
 
+/*
+ * mini_create_llvmonly_ftndesc:
+ *
+ *   Create a function descriptor of the form <addr, arg>, which
+ * represents a callee ADDR with ARG as the last argument.
+ * This is used for:
+ * - generic sharing (ARG is the rgctx)
+ * - gsharedvt signature wrappers (ARG is a function descriptor)
+ */
+MonoFtnDesc*
+mini_create_llvmonly_ftndesc (MonoDomain *domain, gpointer addr, gpointer arg)
+{
+       MonoFtnDesc *ftndesc = (MonoFtnDesc*)mono_domain_alloc0 (mono_domain_get (), 2 * sizeof (gpointer));
+       ftndesc->addr = addr;
+       ftndesc->arg = arg;
+
+       return ftndesc;
+}
+
+/**
+ * mini_add_method_wrappers_llvmonly:
+ *
+ *   Add unbox/gsharedvt wrappers around COMPILED_METHOD if needed. Return the wrapper address or COMPILED_METHOD
+ * if no wrapper is needed. Set OUT_ARG to the rgctx/extra argument needed to be passed to the returned method.
+ */
+gpointer
+mini_add_method_wrappers_llvmonly (MonoMethod *m, gpointer compiled_method, gboolean caller_gsharedvt, gboolean add_unbox_tramp, gpointer *out_arg)
+{
+       gpointer addr = compiled_method;
+       gboolean callee_gsharedvt, callee_array_helper;
+       MonoMethod *jmethod = NULL;
+       MonoJitInfo *ji;
+
+       // FIXME: This loads information from AOT (perf problem)
+       ji = mini_jit_info_table_find (mono_domain_get (), (char *)mono_get_addr_from_ftnptr (compiled_method), NULL);
+       callee_gsharedvt = mini_jit_info_is_gsharedvt (ji);
+
+       callee_array_helper = FALSE;
+       if (m->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
+               WrapperInfo *info = mono_marshal_get_wrapper_info (m);
+
+               /*
+                * generic array helpers.
+                * Have to replace the wrappers with the original generic instances.
+                */
+               if (info && info->subtype == WRAPPER_SUBTYPE_GENERIC_ARRAY_HELPER) {
+                       callee_array_helper = TRUE;
+                       m = info->d.generic_array_helper.method;
+               }
+       } else if (m->wrapper_type == MONO_WRAPPER_UNKNOWN) {
+               WrapperInfo *info = mono_marshal_get_wrapper_info (m);
+
+               /* Same for synchronized inner wrappers */
+               if (info && info->subtype == WRAPPER_SUBTYPE_SYNCHRONIZED_INNER) {
+                       m = info->d.synchronized_inner.method;
+               }
+       }
+
+       if (callee_gsharedvt)
+               g_assert (m->is_inflated);
+
+       addr = compiled_method;
+
+       if (add_unbox_tramp) {
+               /* 
+                * The unbox trampolines call the method directly, so need to add
+                * an rgctx tramp before them.
+                */
+               if (mono_aot_only) {
+                       addr = mono_aot_get_unbox_trampoline (m);
+               } else {
+                       unbox_trampolines ++;
+                       addr = mono_arch_get_unbox_trampoline (m, addr);
+               }
+       }
+
+       g_assert (mono_llvm_only);
+       g_assert (out_arg);
+
+       if (ji && !ji->is_trampoline)
+               jmethod = jinfo_get_method (ji);
+
+       if (callee_gsharedvt)
+               callee_gsharedvt = mini_is_gsharedvt_variable_signature (mono_method_signature (jmethod));
+
+       if (!caller_gsharedvt && callee_gsharedvt) {
+               MonoMethodSignature *sig, *gsig;
+
+               /* Here m is a generic instance, while ji->method is the gsharedvt method implementing it */
+
+               /* Call from normal/gshared code to gsharedvt code with variable signature */
+               sig = mono_method_signature (m);
+               gsig = mono_method_signature (jmethod);
+
+               addr = mini_get_gsharedvt_wrapper (TRUE, addr, sig, gsig, -1, FALSE);
+
+               /*
+                * This is a gsharedvt in wrapper, it gets passed a ftndesc for the gsharedvt method as an argument.
+                */
+               *out_arg = mini_create_llvmonly_ftndesc (mono_domain_get (), compiled_method, mini_method_get_rgctx (m));
+               //printf ("IN: %s\n", mono_method_full_name (m, TRUE));
+       }
+
+       if (!(*out_arg) && mono_method_needs_static_rgctx_invoke (m, FALSE))
+               *out_arg = mini_method_get_rgctx (m);
+
+       if (caller_gsharedvt && !callee_gsharedvt) {
+               /*
+                * The callee uses the gsharedvt calling convention, have to add an out wrapper.
+                */
+               gpointer out_wrapper = mini_get_gsharedvt_wrapper (FALSE, NULL, mono_method_signature (m), NULL, -1, FALSE);
+               MonoFtnDesc *out_wrapper_arg = mini_create_llvmonly_ftndesc (mono_domain_get (), addr, *out_arg);
+
+               addr = out_wrapper;
+               *out_arg = out_wrapper_arg;
+       }
+
+       return addr;
+}
+
 /**
  * common_call_trampoline:
  *
@@ -388,18 +514,18 @@ common_call_trampoline_inner (mgreg_t *regs, guint8 *code, MonoMethod *m, MonoVT
        MonoMethod *declaring = NULL;
        MonoMethod *generic_virtual = NULL, *variant_iface = NULL;
        int context_used;
-       gboolean imt_call, virtual;
+       gboolean imt_call, virtual_;
        gpointer *orig_vtable_slot, *vtable_slot_to_patch = NULL;
        MonoJitInfo *ji = NULL;
 
-       virtual = vt && (gpointer)vtable_slot > (gpointer)vt;
+       virtual_ = vt && (gpointer)vtable_slot > (gpointer)vt;
        imt_call = vt && (gpointer)vtable_slot < (gpointer)vt;
 
        /*
         * rgctx trampolines are needed when the call is indirect so the caller can't pass
         * the rgctx argument needed by the callee.
         */
-       if (virtual && m)
+       if (virtual_ && m)
                need_rgctx_tramp = mono_method_needs_static_rgctx_invoke (m, FALSE);
 
        orig_vtable_slot = vtable_slot;
@@ -413,7 +539,7 @@ common_call_trampoline_inner (mgreg_t *regs, guint8 *code, MonoMethod *m, MonoVT
                g_assert (vtable_slot);
 
                imt_method = mono_arch_find_imt_method (regs, code);
-               this_arg = mono_arch_get_this_arg_from_call (regs, code);
+               this_arg = (MonoObject *)mono_arch_get_this_arg_from_call (regs, code);
 
                if (mono_object_is_transparent_proxy (this_arg)) {
                        /* Use the slow path for now */
@@ -448,7 +574,7 @@ common_call_trampoline_inner (mgreg_t *regs, guint8 *code, MonoMethod *m, MonoVT
         * The virtual check is needed because is_generic_method_definition (m) could
         * return TRUE for methods used in IMT calls too.
         */
-       if (virtual && is_generic_method_definition (m)) {
+       if (virtual_ && is_generic_method_definition (m)) {
                MonoError error;
                MonoGenericContext context = { NULL, NULL };
                MonoMethod *declaring;
@@ -496,7 +622,7 @@ common_call_trampoline_inner (mgreg_t *regs, guint8 *code, MonoMethod *m, MonoVT
 
                        klass = vtable->klass;
                } else {
-                       MonoObject *this_argument = mono_arch_get_this_arg_from_call (regs, code);
+                       MonoObject *this_argument = (MonoObject *)mono_arch_get_this_arg_from_call (regs, code);
 
                        vt = this_argument->vtable;
                        vtable_slot = orig_vtable_slot;
@@ -602,10 +728,10 @@ common_call_trampoline_inner (mgreg_t *regs, guint8 *code, MonoMethod *m, MonoVT
                        GSList *list, *tmp;
 
                        mono_domain_lock (domain);
-                       list = g_hash_table_lookup (domain_jit_info (domain)->jump_target_got_slot_hash, m);
+                       list = (GSList *)g_hash_table_lookup (domain_jit_info (domain)->jump_target_got_slot_hash, m);
                        if (list) {
                                for (tmp = list; tmp; tmp = tmp->next) {
-                                       gpointer *got_slot = tmp->data;
+                                       gpointer *got_slot = (gpointer *)tmp->data;
                                        *got_slot = addr;
                                }
                                g_hash_table_remove (domain_jit_info (domain)->jump_target_got_slot_hash, m);
@@ -632,7 +758,7 @@ common_call_trampoline_inner (mgreg_t *regs, guint8 *code, MonoMethod *m, MonoVT
                if (plt_entry) {
                        if (generic_shared) {
                                target_ji =
-                                       mini_jit_info_table_find (mono_domain_get (), mono_get_addr_from_ftnptr (compiled_method), NULL);
+                                       mini_jit_info_table_find (mono_domain_get (), (char *)mono_get_addr_from_ftnptr (compiled_method), NULL);
                                if (!ji)
                                        ji = mini_jit_info_table_find (mono_domain_get (), (char*)code, NULL);
 
@@ -641,7 +767,7 @@ common_call_trampoline_inner (mgreg_t *regs, guint8 *code, MonoMethod *m, MonoVT
                                }
                        }
                        if (!no_patch)
-                               mono_aot_patch_plt_entry (code, plt_entry, NULL, regs, addr);
+                               mono_aot_patch_plt_entry (code, plt_entry, NULL, regs, (guint8 *)addr);
                } else {
                        if (generic_shared) {
                                if (m->wrapper_type != MONO_WRAPPER_NONE)
@@ -651,7 +777,7 @@ common_call_trampoline_inner (mgreg_t *regs, guint8 *code, MonoMethod *m, MonoVT
 
                        /* Patch calling code */
                        target_ji =
-                               mini_jit_info_table_find (mono_domain_get (), mono_get_addr_from_ftnptr (compiled_method), NULL);
+                               mini_jit_info_table_find (mono_domain_get (), (char *)mono_get_addr_from_ftnptr (compiled_method), NULL);
                        if (!ji)
                                ji = mini_jit_info_table_find (mono_domain_get (), (char*)code, NULL);
 
@@ -665,7 +791,7 @@ common_call_trampoline_inner (mgreg_t *regs, guint8 *code, MonoMethod *m, MonoVT
                        }
 
                        if (!no_patch && mono_method_same_domain (ji, target_ji))
-                               mono_arch_patch_callsite (ji->code_start, code, addr);
+                               mono_arch_patch_callsite ((guint8 *)ji->code_start, code, (guint8 *)addr);
                }
        }
 
@@ -692,7 +818,7 @@ mono_magic_trampoline (mgreg_t *regs, guint8 *code, gpointer arg, guint8* tramp)
 {
        trampoline_calls ++;
 
-       return common_call_trampoline (regs, code, arg, NULL, NULL);
+       return common_call_trampoline (regs, code, (MonoMethod *)arg, NULL, NULL);
 }
 
 /**
@@ -722,7 +848,7 @@ mono_vcall_trampoline (mgreg_t *regs, guint8 *code, int slot, guint8 *tramp)
        /*
         * Obtain the vtable from the 'this' arg.
         */
-       this_arg = mono_arch_get_this_arg_from_call (regs, code);
+       this_arg = (MonoObject *)mono_arch_get_this_arg_from_call (regs, code);
        g_assert (this_arg);
 
        vt = this_arg->vtable;
@@ -820,7 +946,7 @@ mono_aot_trampoline (mgreg_t *regs, guint8 *code, guint8 *token_info,
 
        trampoline_calls ++;
 
-       image = *(gpointer*)(gpointer)token_info;
+       image = (MonoImage *)*(gpointer*)(gpointer)token_info;
        token_info += sizeof (gpointer);
        token = *(guint32*)(gpointer)token_info;
 
@@ -839,7 +965,7 @@ mono_aot_trampoline (mgreg_t *regs, guint8 *code, guint8 *token_info,
        plt_entry = mono_aot_get_plt_entry (code);
        g_assert (plt_entry);
 
-       mono_aot_patch_plt_entry (code, plt_entry, NULL, regs, addr);
+       mono_aot_patch_plt_entry (code, plt_entry, NULL, regs, (guint8 *)addr);
 
        return addr;
 }
@@ -891,9 +1017,9 @@ mono_rgctx_lazy_fetch_trampoline (mgreg_t *regs, guint8 *code, gpointer data, gu
        num_lookups++;
 
        if (mrgctx)
-               return mono_method_fill_runtime_generic_context (arg, index);
+               return mono_method_fill_runtime_generic_context ((MonoMethodRuntimeGenericContext *)arg, index);
        else
-               return mono_class_fill_runtime_generic_context (arg, index);
+               return mono_class_fill_runtime_generic_context ((MonoVTable *)arg, index);
 }
 
 /*
@@ -911,7 +1037,7 @@ create_delegate_trampoline_data (MonoDomain *domain, MonoClass *klass, MonoMetho
        invoke = mono_get_delegate_invoke (klass);
        g_assert (invoke);
 
-       tramp_data = mono_domain_alloc0 (domain, sizeof (MonoDelegateTrampInfo));
+       tramp_data = (MonoDelegateTrampInfo *)mono_domain_alloc0 (domain, sizeof (MonoDelegateTrampInfo));
        tramp_data->invoke = invoke;
        tramp_data->invoke_sig = mono_method_signature (invoke);
        tramp_data->impl_this = mono_arch_get_delegate_invoke_impl (mono_method_signature (invoke), TRUE);
@@ -946,8 +1072,8 @@ mono_delegate_trampoline (mgreg_t *regs, guint8 *code, gpointer *arg, guint8* tr
        gboolean enable_caching = TRUE;
        MonoDelegateTrampInfo *tramp_info = (MonoDelegateTrampInfo*)arg;
        MonoMethod *invoke = tramp_info->invoke;
-       guint8 *impl_this = tramp_info->impl_this;
-       guint8 *impl_nothis = tramp_info->impl_nothis;
+       guint8 *impl_this = (guint8 *)tramp_info->impl_this;
+       guint8 *impl_nothis = (guint8 *)tramp_info->impl_nothis;
        MonoError err;
        MonoMethodSignature *sig;
        gpointer addr, compiled_method;
@@ -956,7 +1082,7 @@ mono_delegate_trampoline (mgreg_t *regs, guint8 *code, gpointer *arg, guint8* tr
        trampoline_calls ++;
 
        /* Obtain the delegate object according to the calling convention */
-       delegate = mono_arch_get_this_arg_from_call (regs, code);
+       delegate = (MonoDelegate *)mono_arch_get_this_arg_from_call (regs, code);
        g_assert (mono_class_has_parent (mono_object_class (delegate), mono_defaults.multicastdelegate_class));
 
        if (delegate->method) {
@@ -1006,7 +1132,7 @@ mono_delegate_trampoline (mgreg_t *regs, guint8 *code, gpointer *arg, guint8* tr
        // ftnptrs are being used.  "method" would end up null on archtitectures without
        // ftnptrs so we can just skip this.
        } else if (delegate->method_ptr) {
-               ji = mono_jit_info_table_find (domain, mono_get_addr_from_ftnptr (delegate->method_ptr));
+               ji = mono_jit_info_table_find (domain, (char *)mono_get_addr_from_ftnptr (delegate->method_ptr));
                if (ji)
                        method = jinfo_get_method (ji);
        }
@@ -1070,7 +1196,7 @@ mono_delegate_trampoline (mgreg_t *regs, guint8 *code, gpointer *arg, guint8* tr
                        addr = mini_add_method_trampoline (method, compiled_method, need_rgctx_tramp, need_unbox_tramp);
                        delegate->method_ptr = addr;
                        if (enable_caching && delegate->method_code)
-                               *delegate->method_code = delegate->method_ptr;
+                               *delegate->method_code = (guint8 *)delegate->method_ptr;
                }
        } else {
                if (need_rgctx_tramp)
@@ -1092,8 +1218,8 @@ mono_delegate_trampoline (mgreg_t *regs, guint8 *code, gpointer *arg, guint8* tr
        if (!code) {
                /* The general, unoptimized case */
                m = mono_marshal_get_delegate_invoke (invoke, delegate);
-               code = mono_compile_method (m);
-               code = mini_add_method_trampoline (m, code, mono_method_needs_static_rgctx_invoke (m, FALSE), FALSE);
+               code = (guint8 *)mono_compile_method (m);
+               code = (guint8 *)mini_add_method_trampoline (m, code, mono_method_needs_static_rgctx_invoke (m, FALSE), FALSE);
        }
 
        delegate->invoke_impl = mono_get_addr_from_ftnptr (code);
@@ -1111,7 +1237,7 @@ mono_handler_block_guard_trampoline (mgreg_t *regs, guint8 *code, gpointer *tram
 {
        MonoContext ctx;
        MonoException *exc;
-       MonoJitTlsData *jit_tls = mono_native_tls_get_value (mono_jit_tls_id);
+       MonoJitTlsData *jit_tls = (MonoJitTlsData *)mono_native_tls_get_value (mono_jit_tls_id);
        gpointer resume_ip = jit_tls->handler_block_return_address;
 
        memcpy (&ctx, &jit_tls->handler_block_context, sizeof (MonoContext));
@@ -1126,7 +1252,7 @@ mono_handler_block_guard_trampoline (mgreg_t *regs, guint8 *code, gpointer *tram
                exc = mono_thread_resume_interruption ();
 
        if (exc) {
-               mono_handle_exception (&ctx, exc);
+               mono_handle_exception (&ctx, (MonoObject *)exc);
                mono_restore_context (&ctx);
        }
 
@@ -1217,7 +1343,7 @@ create_trampoline_code (MonoTrampolineType tramp_type)
 void
 mono_trampolines_init (void)
 {
-       mono_mutex_init_recursive (&trampolines_mutex);
+       mono_os_mutex_init_recursive (&trampolines_mutex);
 
        if (mono_aot_only)
                return;
@@ -1254,7 +1380,7 @@ mono_trampolines_cleanup (void)
        if (rgctx_lazy_fetch_trampoline_hash_addr)
                g_hash_table_destroy (rgctx_lazy_fetch_trampoline_hash_addr);
 
-       mono_mutex_destroy (&trampolines_mutex);
+       mono_os_mutex_destroy (&trampolines_mutex);
 }
 
 guint8 *
@@ -1291,6 +1417,9 @@ mono_create_jump_trampoline (MonoDomain *domain, MonoMethod *method, gboolean ad
        if (code && !ji->has_generic_jit_info && !(method->iflags & METHOD_IMPL_ATTRIBUTE_SYNCHRONIZED))
                return code;
 
+       if (mono_llvm_only)
+               return mono_jit_compile_method (method);
+
        mono_domain_lock (domain);
        code = g_hash_table_lookup (domain_jit_info (domain)->jump_trampoline_hash, method);
        mono_domain_unlock (domain);
@@ -1300,7 +1429,7 @@ mono_create_jump_trampoline (MonoDomain *domain, MonoMethod *method, gboolean ad
        code = mono_create_specific_trampoline (method, MONO_TRAMPOLINE_JUMP, mono_domain_get (), &code_size);
        g_assert (code_size);
 
-       ji = mono_domain_alloc0 (domain, MONO_SIZEOF_JIT_INFO);
+       ji = (MonoJitInfo *)mono_domain_alloc0 (domain, MONO_SIZEOF_JIT_INFO);
        ji->code_start = code;
        ji->code_size = code_size;
        ji->d.method = method;
@@ -1319,6 +1448,12 @@ mono_create_jump_trampoline (MonoDomain *domain, MonoMethod *method, gboolean ad
        return ji->code_start;
 }
 
+static void
+method_not_found (void)
+{
+       g_assert_not_reached ();
+}
+
 gpointer
 mono_create_jit_trampoline_in_domain (MonoDomain *domain, MonoMethod *method)
 {
@@ -1330,6 +1465,14 @@ mono_create_jit_trampoline_in_domain (MonoDomain *domain, MonoMethod *method)
                
                if (code)
                        return code;
+               if (mono_llvm_only) {
+                       if (method->wrapper_type == MONO_WRAPPER_PROXY_ISINST || method->wrapper_type == MONO_WRAPPER_LDFLD_REMOTE ||
+                               method->wrapper_type == MONO_WRAPPER_STFLD_REMOTE)
+                               /* These wrappers are not generated */
+                               return method_not_found;
+                       /* Methods are lazily initialized on first call, so this can't lead recursion */
+                       return mono_compile_method (method);
+               }
        }
 
        mono_domain_lock (domain);
@@ -1363,7 +1506,7 @@ mono_create_jit_trampoline_from_token (MonoImage *image, guint32 token)
        MonoDomain *domain = mono_domain_get ();
        guint8 *buf, *start;
 
-       buf = start = mono_domain_alloc0 (domain, 2 * sizeof (gpointer));
+       buf = start = (guint8 *)mono_domain_alloc0 (domain, 2 * sizeof (gpointer));
 
        *(gpointer*)(gpointer)buf = image;
        buf += sizeof (gpointer);
@@ -1392,7 +1535,7 @@ mono_create_delegate_trampoline_info (MonoDomain *domain, MonoClass *klass, Mono
        pair.klass = klass;
        pair.method = method;
        mono_domain_lock (domain);
-       tramp_info = g_hash_table_lookup (domain_jit_info (domain)->delegate_trampoline_hash, &pair);
+       tramp_info = (MonoDelegateTrampInfo *)g_hash_table_lookup (domain_jit_info (domain)->delegate_trampoline_hash, &pair);
        mono_domain_unlock (domain);
        if (tramp_info)
                return tramp_info;
@@ -1402,7 +1545,7 @@ mono_create_delegate_trampoline_info (MonoDomain *domain, MonoClass *klass, Mono
        tramp_info->invoke_impl = mono_create_specific_trampoline (tramp_info, MONO_TRAMPOLINE_DELEGATE, domain, &code_size);
        g_assert (code_size);
 
-       dpair = mono_domain_alloc0 (domain, sizeof (MonoClassMethodPair));
+       dpair = (MonoClassMethodPair *)mono_domain_alloc0 (domain, sizeof (MonoClassMethodPair));
        memcpy (dpair, &pair, sizeof (MonoClassMethodPair));
 
        /* store trampoline address */
@@ -1413,9 +1556,18 @@ mono_create_delegate_trampoline_info (MonoDomain *domain, MonoClass *klass, Mono
        return tramp_info;
 }
 
+static void
+no_delegate_trampoline (void)
+{
+       g_assert_not_reached ();
+}
+
 gpointer
 mono_create_delegate_trampoline (MonoDomain *domain, MonoClass *klass)
 {
+       if (mono_llvm_only)
+               return no_delegate_trampoline;
+
        return mono_create_delegate_trampoline_info (domain, klass, NULL)->invoke_impl;
 }
 
@@ -1473,26 +1625,6 @@ mono_create_rgctx_lazy_fetch_trampoline (guint32 offset)
 
        return ptr;
 }
-#ifdef MONO_ARCH_LLVM_SUPPORTED
-/*
- * mono_create_llvm_imt_trampoline:
- *
- *   LLVM compiled code can't pass in the IMT argument, so we use this trampoline, which
- * sets the IMT argument, then branches to the contents of the vtable slot given by
- * vt_offset in the vtable which is obtained from the argument list.
- */
-gpointer
-mono_create_llvm_imt_trampoline (MonoDomain *domain, MonoMethod *m, int vt_offset)
-{
-#ifdef MONO_ARCH_HAVE_LLVM_IMT_TRAMPOLINE
-       return mono_arch_get_llvm_imt_trampoline (domain, m, vt_offset);
-#else
-       g_assert_not_reached ();
-       return NULL;
-#endif
-}
-#endif
 
 guint32
 mono_find_rgctx_lazy_fetch_trampoline_by_addr (gconstpointer addr)