[llvmonly] Share more wrapper types. Avoid adding out wrappers for calls from gshared...
[mono.git] / mono / mini / mini-generic-sharing.c
index 394687186b8f5ca4ac9fcbf9649e10bbe843ebbb..7a57aad78869abff3d377a498c8d38335b68fed7 100644 (file)
@@ -11,6 +11,7 @@
 #include <config.h>
 
 #include <mono/metadata/class.h>
+#include <mono/metadata/method-builder.h>
 #include <mono/utils/mono-counters.h>
 
 #include "mini.h"
 static void
 mono_class_unregister_image_generic_subclasses (MonoImage *image, gpointer user_data);
 
+/* Counters */
+static int num_templates_allocted;
+static int num_templates_bytes;
+static int num_oti_allocted;
+static int num_oti_bytes;
+
 static gboolean partial_supported = FALSE;
 
 static inline gboolean
@@ -136,35 +143,35 @@ mono_class_check_context_used (MonoClass *klass)
  * LOCKING: loader lock
  */
 static MonoRuntimeGenericContextInfoTemplate*
-get_info_templates (MonoRuntimeGenericContextTemplate *template, int type_argc)
+get_info_templates (MonoRuntimeGenericContextTemplate *template_, int type_argc)
 {
        g_assert (type_argc >= 0);
        if (type_argc == 0)
-               return template->infos;
-       return g_slist_nth_data (template->method_templates, type_argc - 1);
+               return template_->infos;
+       return (MonoRuntimeGenericContextInfoTemplate *)g_slist_nth_data (template_->method_templates, type_argc - 1);
 }
 
 /*
  * LOCKING: loader lock
  */
 static void
-set_info_templates (MonoImage *image, MonoRuntimeGenericContextTemplate *template, int type_argc,
+set_info_templates (MonoImage *image, MonoRuntimeGenericContextTemplate *template_, int type_argc,
        MonoRuntimeGenericContextInfoTemplate *oti)
 {
        g_assert (type_argc >= 0);
        if (type_argc == 0)
-               template->infos = oti;
+               template_->infos = oti;
        else {
-               int length = g_slist_length (template->method_templates);
+               int length = g_slist_length (template_->method_templates);
                GSList *list;
 
                /* FIXME: quadratic! */
                while (length < type_argc) {
-                       template->method_templates = g_slist_append_image (image, template->method_templates, NULL);
+                       template_->method_templates = g_slist_append_image (image, template_->method_templates, NULL);
                        length++;
                }
 
-               list = g_slist_nth (template->method_templates, type_argc - 1);
+               list = g_slist_nth (template_->method_templates, type_argc - 1);
                g_assert (list);
                list->data = oti;
        }
@@ -174,23 +181,23 @@ set_info_templates (MonoImage *image, MonoRuntimeGenericContextTemplate *templat
  * LOCKING: loader lock
  */
 static int
-template_get_max_argc (MonoRuntimeGenericContextTemplate *template)
+template_get_max_argc (MonoRuntimeGenericContextTemplate *template_)
 {
-       return g_slist_length (template->method_templates);
+       return g_slist_length (template_->method_templates);
 }
 
 /*
  * LOCKING: loader lock
  */
 static MonoRuntimeGenericContextInfoTemplate*
-rgctx_template_get_other_slot (MonoRuntimeGenericContextTemplate *template, int type_argc, int slot)
+rgctx_template_get_other_slot (MonoRuntimeGenericContextTemplate *template_, int type_argc, int slot)
 {
        int i;
        MonoRuntimeGenericContextInfoTemplate *oti;
 
        g_assert (slot >= 0);
 
-       for (oti = get_info_templates (template, type_argc), i = 0; i < slot; oti = oti->next, ++i) {
+       for (oti = get_info_templates (template_, type_argc), i = 0; i < slot; oti = oti->next, ++i) {
                if (!oti)
                        return NULL;
        }
@@ -202,12 +209,12 @@ rgctx_template_get_other_slot (MonoRuntimeGenericContextTemplate *template, int
  * LOCKING: loader lock
  */
 static int
-rgctx_template_num_infos (MonoRuntimeGenericContextTemplate *template, int type_argc)
+rgctx_template_num_infos (MonoRuntimeGenericContextTemplate *template_, int type_argc)
 {
        MonoRuntimeGenericContextInfoTemplate *oti;
        int i;
 
-       for (i = 0, oti = get_info_templates (template, type_argc); oti; ++i, oti = oti->next)
+       for (i = 0, oti = get_info_templates (template_, type_argc); oti; ++i, oti = oti->next)
                ;
 
        return i;
@@ -239,14 +246,14 @@ class_set_rgctx_template (MonoClass *klass, MonoRuntimeGenericContextTemplate *r
 static MonoRuntimeGenericContextTemplate*
 class_lookup_rgctx_template (MonoClass *klass)
 {
-       MonoRuntimeGenericContextTemplate *template;
+       MonoRuntimeGenericContextTemplate *template_;
 
        if (!klass->image->rgctx_template_hash)
                return NULL;
 
-       template = g_hash_table_lookup (klass->image->rgctx_template_hash, klass);
+       template_ = (MonoRuntimeGenericContextTemplate *)g_hash_table_lookup (klass->image->rgctx_template_hash, klass);
 
-       return template;
+       return template_;
 }
 
 /*
@@ -267,7 +274,7 @@ register_generic_subclass (MonoClass *klass)
        if (!generic_subclass_hash)
                generic_subclass_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
 
-       subclass = g_hash_table_lookup (generic_subclass_hash, parent);
+       subclass = (MonoClass *)g_hash_table_lookup (generic_subclass_hash, parent);
        rgctx_template->next_subclass = subclass;
        g_hash_table_insert (generic_subclass_hash, parent, klass);
 }
@@ -340,43 +347,24 @@ mono_class_unregister_image_generic_subclasses (MonoImage *image, gpointer user_
 static MonoRuntimeGenericContextTemplate*
 alloc_template (MonoClass *klass)
 {
-       static gboolean inited = FALSE;
-       static int num_allocted = 0;
-       static int num_bytes = 0;
-
        int size = sizeof (MonoRuntimeGenericContextTemplate);
 
-       if (!inited) {
-               mono_counters_register ("RGCTX template num allocted", MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &num_allocted);
-               mono_counters_register ("RGCTX template bytes allocted", MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &num_bytes);
-               inited = TRUE;
-       }
-
-       num_allocted++;
-       num_bytes += size;
+       num_templates_allocted++;
+       num_templates_bytes += size;
 
-       return mono_image_alloc0 (klass->image, size);
+       return (MonoRuntimeGenericContextTemplate *)mono_image_alloc0 (klass->image, size);
 }
 
+/* LOCKING: Takes the loader lock */
 static MonoRuntimeGenericContextInfoTemplate*
 alloc_oti (MonoImage *image)
 {
-       static gboolean inited = FALSE;
-       static int num_allocted = 0;
-       static int num_bytes = 0;
-
        int size = sizeof (MonoRuntimeGenericContextInfoTemplate);
 
-       if (!inited) {
-               mono_counters_register ("RGCTX oti num allocted", MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &num_allocted);
-               mono_counters_register ("RGCTX oti bytes allocted", MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &num_bytes);
-               inited = TRUE;
-       }
-
-       num_allocted++;
-       num_bytes += size;
+       num_oti_allocted++;
+       num_oti_bytes += size;
 
-       return mono_image_alloc0 (image, size);
+       return (MonoRuntimeGenericContextInfoTemplate *)mono_image_alloc0 (image, size);
 }
 
 #define MONO_RGCTX_SLOT_USED_MARKER    ((gpointer)&mono_defaults.object_class->byval_arg)
@@ -396,7 +384,7 @@ info_has_identity (MonoRgctxInfoType info_type)
  * LOCKING: loader lock
  */
 static void
-rgctx_template_set_slot (MonoImage *image, MonoRuntimeGenericContextTemplate *template, int type_argc,
+rgctx_template_set_slot (MonoImage *image, MonoRuntimeGenericContextTemplate *template_, int type_argc,
        int slot, gpointer data, MonoRgctxInfoType info_type)
 {
        static gboolean inited = FALSE;
@@ -404,7 +392,7 @@ rgctx_template_set_slot (MonoImage *image, MonoRuntimeGenericContextTemplate *te
        static int num_data = 0;
 
        int i;
-       MonoRuntimeGenericContextInfoTemplate *list = get_info_templates (template, type_argc);
+       MonoRuntimeGenericContextInfoTemplate *list = get_info_templates (template_, type_argc);
        MonoRuntimeGenericContextInfoTemplate **oti = &list;
 
        if (!inited) {
@@ -429,7 +417,7 @@ rgctx_template_set_slot (MonoImage *image, MonoRuntimeGenericContextTemplate *te
        (*oti)->data = data;
        (*oti)->info_type = info_type;
 
-       set_info_templates (image, template, type_argc, list);
+       set_info_templates (image, template_, type_argc, list);
 
        if (data == MONO_RGCTX_SLOT_USED_MARKER)
                ++num_markers;
@@ -543,18 +531,20 @@ inflate_info (MonoRuntimeGenericContextInfoTemplate *oti, MonoGenericContext *co
        case MONO_RGCTX_INFO_NULLABLE_CLASS_BOX:
        case MONO_RGCTX_INFO_NULLABLE_CLASS_UNBOX: {
                gpointer result = mono_class_inflate_generic_type_with_mempool (temporary ? NULL : klass->image,
-                       data, context, &error);
-               g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
+                       (MonoType *)data, context, &error);
+               if (!mono_error_ok (&error)) /*FIXME proper error handling */
+                       g_error ("Could not inflate generic type due to %s", mono_error_get_message (&error));
                return result;
        }
 
        case MONO_RGCTX_INFO_METHOD:
        case MONO_RGCTX_INFO_GENERIC_METHOD_CODE:
+       case MONO_RGCTX_INFO_GSHAREDVT_OUT_WRAPPER:
        case MONO_RGCTX_INFO_METHOD_RGCTX:
        case MONO_RGCTX_INFO_METHOD_CONTEXT:
        case MONO_RGCTX_INFO_REMOTING_INVOKE_WITH_CHECK:
        case MONO_RGCTX_INFO_METHOD_DELEGATE_CODE: {
-               MonoMethod *method = data;
+               MonoMethod *method = (MonoMethod *)data;
                MonoMethod *inflated_method;
                MonoType *inflated_type = mono_class_inflate_generic_type (&method->klass->byval_arg, context);
                MonoClass *inflated_class = mono_class_from_mono_type (inflated_type);
@@ -579,12 +569,12 @@ inflate_info (MonoRuntimeGenericContextInfoTemplate *oti, MonoGenericContext *co
                return inflated_method;
        }
        case MONO_RGCTX_INFO_METHOD_GSHAREDVT_INFO: {
-               MonoGSharedVtMethodInfo *oinfo = data;
+               MonoGSharedVtMethodInfo *oinfo = (MonoGSharedVtMethodInfo *)data;
                MonoGSharedVtMethodInfo *res;
                MonoDomain *domain = mono_domain_get ();
                int i;
 
-               res = mono_domain_alloc0 (domain, sizeof (MonoGSharedVtMethodInfo));
+               res = (MonoGSharedVtMethodInfo *)mono_domain_alloc0 (domain, sizeof (MonoGSharedVtMethodInfo));
                /*
                res->nlocals = info->nlocals;
                res->locals_types = g_new0 (MonoType*, info->nlocals);
@@ -592,19 +582,19 @@ inflate_info (MonoRuntimeGenericContextInfoTemplate *oti, MonoGenericContext *co
                        res->locals_types [i] = mono_class_inflate_generic_type (info->locals_types [i], context);
                */
                res->num_entries = oinfo->num_entries;
-               res->entries = mono_domain_alloc0 (domain, sizeof (MonoRuntimeGenericContextInfoTemplate) * oinfo->num_entries);
+               res->entries = (MonoRuntimeGenericContextInfoTemplate *)mono_domain_alloc0 (domain, sizeof (MonoRuntimeGenericContextInfoTemplate) * oinfo->num_entries);
                for (i = 0; i < oinfo->num_entries; ++i) {
                        MonoRuntimeGenericContextInfoTemplate *otemplate = &oinfo->entries [i];
-                       MonoRuntimeGenericContextInfoTemplate *template = &res->entries [i];
+                       MonoRuntimeGenericContextInfoTemplate *template_ = &res->entries [i];
 
-                       memcpy (template, otemplate, sizeof (MonoRuntimeGenericContextInfoTemplate));
-                       template->data = inflate_info (template, context, klass, FALSE);
+                       memcpy (template_, otemplate, sizeof (MonoRuntimeGenericContextInfoTemplate));
+                       template_->data = inflate_info (template_, context, klass, FALSE);
                }
                return res;
        }
        case MONO_RGCTX_INFO_METHOD_GSHAREDVT_OUT_TRAMPOLINE:
        case MONO_RGCTX_INFO_METHOD_GSHAREDVT_OUT_TRAMPOLINE_VIRT: {
-               MonoJumpInfoGSharedVtCall *info = data;
+               MonoJumpInfoGSharedVtCall *info = (MonoJumpInfoGSharedVtCall *)data;
                MonoMethod *method = info->method;
                MonoMethod *inflated_method;
                MonoType *inflated_type = mono_class_inflate_generic_type (&method->klass->byval_arg, context);
@@ -612,7 +602,7 @@ inflate_info (MonoRuntimeGenericContextInfoTemplate *oti, MonoGenericContext *co
                MonoJumpInfoGSharedVtCall *res;
                MonoDomain *domain = mono_domain_get ();
 
-               res = mono_domain_alloc0 (domain, sizeof (MonoJumpInfoGSharedVtCall));
+               res = (MonoJumpInfoGSharedVtCall *)mono_domain_alloc0 (domain, sizeof (MonoJumpInfoGSharedVtCall));
                /* Keep the original signature */
                res->sig = info->sig;
 
@@ -640,7 +630,7 @@ inflate_info (MonoRuntimeGenericContextInfoTemplate *oti, MonoGenericContext *co
 
        case MONO_RGCTX_INFO_CLASS_FIELD:
        case MONO_RGCTX_INFO_FIELD_OFFSET: {
-               MonoClassField *field = data;
+               MonoClassField *field = (MonoClassField *)data;
                MonoType *inflated_type = mono_class_inflate_generic_type (&field->parent->byval_arg, context);
                MonoClass *inflated_class = mono_class_from_mono_type (inflated_type);
                int i = field - field->parent->fields;
@@ -653,8 +643,9 @@ inflate_info (MonoRuntimeGenericContextInfoTemplate *oti, MonoGenericContext *co
 
                return &inflated_class->fields [i];
        }
+       case MONO_RGCTX_INFO_SIG_GSHAREDVT_IN_TRAMPOLINE_CALLI:
        case MONO_RGCTX_INFO_SIG_GSHAREDVT_OUT_TRAMPOLINE_CALLI: {
-               MonoMethodSignature *sig = data;
+               MonoMethodSignature *sig = (MonoMethodSignature *)data;
                MonoMethodSignature *isig;
                MonoError error;
 
@@ -664,14 +655,14 @@ inflate_info (MonoRuntimeGenericContextInfoTemplate *oti, MonoGenericContext *co
        }
        case MONO_RGCTX_INFO_VIRT_METHOD_CODE:
        case MONO_RGCTX_INFO_VIRT_METHOD_BOX_TYPE: {
-               MonoJumpInfoVirtMethod *info = data;
+               MonoJumpInfoVirtMethod *info = (MonoJumpInfoVirtMethod *)data;
                MonoJumpInfoVirtMethod *res;
                MonoType *t;
                MonoDomain *domain = mono_domain_get ();
                MonoError error;
 
                // FIXME: Temporary
-               res = mono_domain_alloc0 (domain, sizeof (MonoJumpInfoVirtMethod));
+               res = (MonoJumpInfoVirtMethod *)mono_domain_alloc0 (domain, sizeof (MonoJumpInfoVirtMethod));
                t = mono_class_inflate_generic_type (&info->klass->byval_arg, context);
                res->klass = mono_class_from_mono_type (t);
                mono_metadata_free_type (t);
@@ -702,7 +693,7 @@ free_inflated_info (MonoRgctxInfoType info_type, gpointer info)
        case MONO_RGCTX_INFO_TYPE:
        case MONO_RGCTX_INFO_REFLECTION_TYPE:
        case MONO_RGCTX_INFO_CAST_CACHE:
-               mono_metadata_free_type (info);
+               mono_metadata_free_type ((MonoType *)info);
                break;
        default:
                break;
@@ -741,21 +732,21 @@ get_shared_class (MonoClass *klass)
 static MonoRuntimeGenericContextTemplate*
 mono_class_get_runtime_generic_context_template (MonoClass *klass)
 {
-       MonoRuntimeGenericContextTemplate *parent_template, *template;
+       MonoRuntimeGenericContextTemplate *parent_template, *template_;
        guint32 i;
 
        klass = get_shared_class (klass);
 
        mono_loader_lock ();
-       template = class_lookup_rgctx_template (klass);
+       template_ = class_lookup_rgctx_template (klass);
        mono_loader_unlock ();
 
-       if (template)
-               return template;
+       if (template_)
+               return template_;
 
        //g_assert (get_shared_class (class) == class);
 
-       template = alloc_template (klass);
+       template_ = alloc_template (klass);
 
        mono_loader_lock ();
 
@@ -775,7 +766,7 @@ mono_class_get_runtime_generic_context_template (MonoClass *klass)
 
                                oti = class_get_rgctx_template_oti (klass->parent, type_argc, i, FALSE, FALSE, NULL);
                                if (oti.data && oti.data != MONO_RGCTX_SLOT_USED_MARKER) {
-                                       rgctx_template_set_slot (klass->image, template, type_argc, i,
+                                       rgctx_template_set_slot (klass->image, template_, type_argc, i,
                                                                                         oti.data, oti.info_type);
                                }
                        }
@@ -784,9 +775,9 @@ mono_class_get_runtime_generic_context_template (MonoClass *klass)
 
        if (class_lookup_rgctx_template (klass)) {
                /* some other thread already set the template */
-               template = class_lookup_rgctx_template (klass);
+               template_ = class_lookup_rgctx_template (klass);
        } else {
-               class_set_rgctx_template (klass, template);
+               class_set_rgctx_template (klass, template_);
 
                if (klass->parent)
                        register_generic_subclass (klass);
@@ -794,7 +785,7 @@ mono_class_get_runtime_generic_context_template (MonoClass *klass)
 
        mono_loader_unlock ();
 
-       return template;
+       return template_;
 }
 
 /*
@@ -833,11 +824,11 @@ class_get_rgctx_template_oti (MonoClass *klass, int type_argc, guint32 slot, gbo
 
                return oti;
        } else {
-               MonoRuntimeGenericContextTemplate *template;
+               MonoRuntimeGenericContextTemplate *template_;
                MonoRuntimeGenericContextInfoTemplate *oti;
 
-               template = mono_class_get_runtime_generic_context_template (klass);
-               oti = rgctx_template_get_other_slot (template, type_argc, slot);
+               template_ = mono_class_get_runtime_generic_context_template (klass);
+               oti = rgctx_template_get_other_slot (template_, type_argc, slot);
                g_assert (oti);
 
                if (temporary)
@@ -869,8 +860,8 @@ class_type_info (MonoDomain *domain, MonoClass *klass, MonoRgctxInfoType info_ty
        }
        case MONO_RGCTX_INFO_CAST_CACHE: {
                /*First slot is the cache itself, the second the vtable.*/
-               gpointer **cache_data = mono_domain_alloc0 (domain, sizeof (gpointer) * 2);
-               cache_data [1] = (gpointer)klass;
+               gpointer **cache_data = (gpointer **)mono_domain_alloc0 (domain, sizeof (gpointer) * 2);
+               cache_data [1] = (gpointer *)klass;
                return cache_data;
        }
        case MONO_RGCTX_INFO_ARRAY_ELEMENT_SIZE:
@@ -882,11 +873,11 @@ class_type_info (MonoDomain *domain, MonoClass *klass, MonoRgctxInfoType info_ty
                        return GUINT_TO_POINTER (mono_class_value_size (klass, NULL));
        case MONO_RGCTX_INFO_CLASS_BOX_TYPE:
                if (MONO_TYPE_IS_REFERENCE (&klass->byval_arg))
-                       return GUINT_TO_POINTER (1);
+                       return GUINT_TO_POINTER (MONO_GSHAREDVT_BOX_TYPE_REF);
                else if (mono_class_is_nullable (klass))
-                       return GUINT_TO_POINTER (2);
+                       return GUINT_TO_POINTER (MONO_GSHAREDVT_BOX_TYPE_NULLABLE);
                else
-                       return GUINT_TO_POINTER (0);
+                       return GUINT_TO_POINTER (MONO_GSHAREDVT_BOX_TYPE_VTYPE);
        case MONO_RGCTX_INFO_MEMCPY:
        case MONO_RGCTX_INFO_BZERO: {
                static MonoMethod *memcpy_method [17];
@@ -926,7 +917,7 @@ class_type_info (MonoDomain *domain, MonoClass *klass, MonoRgctxInfoType info_ty
                        if (!domain_info->memcpy_addr [size]) {
                                gpointer addr = mono_compile_method (memcpy_method [size]);
                                mono_memory_barrier ();
-                               domain_info->memcpy_addr [size] = addr;
+                               domain_info->memcpy_addr [size] = (gpointer *)addr;
                        }
                        return domain_info->memcpy_addr [size];
                } else {
@@ -946,7 +937,7 @@ class_type_info (MonoDomain *domain, MonoClass *klass, MonoRgctxInfoType info_ty
                        if (!domain_info->bzero_addr [size]) {
                                gpointer addr = mono_compile_method (bzero_method [size]);
                                mono_memory_barrier ();
-                               domain_info->bzero_addr [size] = addr;
+                               domain_info->bzero_addr [size] = (gpointer *)addr;
                        }
                        return domain_info->bzero_addr [size];
                }
@@ -954,8 +945,10 @@ class_type_info (MonoDomain *domain, MonoClass *klass, MonoRgctxInfoType info_ty
        case MONO_RGCTX_INFO_NULLABLE_CLASS_BOX:
        case MONO_RGCTX_INFO_NULLABLE_CLASS_UNBOX: {
                MonoMethod *method;
-               gpointer addr;
+               gpointer addr, arg;
                MonoJitInfo *ji;
+               MonoMethodSignature *sig, *gsig;
+               MonoMethod *gmethod;
 
                if (!mono_class_is_nullable (klass))
                        /* This can happen since all the entries in MonoGSharedVtMethodInfo are inflated, even those which are not used */
@@ -967,15 +960,24 @@ class_type_info (MonoDomain *domain, MonoClass *klass, MonoRgctxInfoType info_ty
                        method = mono_class_get_method_from_name (klass, "Unbox", 1);
 
                addr = mono_compile_method (method);
+
                // The caller uses the gsharedvt call signature
-               ji = mini_jit_info_table_find (mono_domain_get (), mono_get_addr_from_ftnptr (addr), NULL);
+
+               if (mono_llvm_only) {
+                       /* FIXME: We have no access to the gsharedvt signature/gsctx used by the caller, so have to construct it ourselves */
+                       gmethod = mini_get_shared_method_full (method, FALSE, TRUE);
+                       sig = mono_method_signature (method);
+                       gsig = mono_method_signature (gmethod);
+
+                       addr = mini_add_method_wrappers_llvmonly (method, addr, TRUE, FALSE, &arg);
+                       return mini_create_llvmonly_ftndesc (domain, addr, arg);
+               }
+
+               ji = mini_jit_info_table_find (mono_domain_get (), (char *)mono_get_addr_from_ftnptr (addr), NULL);
                g_assert (ji);
                if (mini_jit_info_is_gsharedvt (ji))
                        return mono_create_static_rgctx_trampoline (method, addr);
                else {
-                       MonoMethodSignature *sig, *gsig;
-                       MonoMethod *gmethod;
-
                        /* Need to add an out wrapper */
 
                        /* FIXME: We have no access to the gsharedvt signature/gsctx used by the caller, so have to construct it ourselves */
@@ -1018,7 +1020,7 @@ typedef struct {
 static guint
 tramp_info_hash (gconstpointer key)
 {
-       GSharedVtTrampInfo *tramp = (gpointer)key;
+       GSharedVtTrampInfo *tramp = (GSharedVtTrampInfo *)key;
 
        return (gsize)tramp->addr;
 }
@@ -1026,14 +1028,344 @@ tramp_info_hash (gconstpointer key)
 static gboolean
 tramp_info_equal (gconstpointer a, gconstpointer b)
 {
-       GSharedVtTrampInfo *tramp1 = (gpointer)a;
-       GSharedVtTrampInfo *tramp2 = (gpointer)b;
+       GSharedVtTrampInfo *tramp1 = (GSharedVtTrampInfo *)a;
+       GSharedVtTrampInfo *tramp2 = (GSharedVtTrampInfo *)b;
 
        /* The signatures should be internalized */
        return tramp1->is_in == tramp2->is_in && tramp1->calli == tramp2->calli && tramp1->vcall_offset == tramp2->vcall_offset &&
                tramp1->addr == tramp2->addr && tramp1->sig == tramp2->sig && tramp1->gsig == tramp2->gsig;
 }
 
+static MonoType*
+get_wrapper_shared_type (MonoType *t)
+{
+       if (t->byref)
+               return &mono_defaults.int_class->this_arg;
+       t = mini_get_underlying_type (t);
+
+       switch (t->type) {
+       case MONO_TYPE_I1:
+               /* This removes any attributes etc. */
+               return &mono_defaults.sbyte_class->byval_arg;
+       case MONO_TYPE_U1:
+               return &mono_defaults.byte_class->byval_arg;
+       case MONO_TYPE_I2:
+               return &mono_defaults.int16_class->byval_arg;
+       case MONO_TYPE_U2:
+               return &mono_defaults.uint16_class->byval_arg;
+       case MONO_TYPE_I4:
+               return &mono_defaults.int32_class->byval_arg;
+       case MONO_TYPE_U4:
+               return &mono_defaults.uint32_class->byval_arg;
+       case MONO_TYPE_OBJECT:
+       case MONO_TYPE_CLASS:
+       case MONO_TYPE_SZARRAY:
+       case MONO_TYPE_ARRAY:
+       case MONO_TYPE_PTR:
+               return &mono_defaults.int_class->byval_arg;
+       case MONO_TYPE_GENERICINST: {
+               MonoClass *klass;
+               MonoGenericContext ctx;
+               MonoGenericContext *orig_ctx;
+               MonoGenericInst *inst;
+               MonoType *args [16];
+               int i;
+
+               if (!MONO_TYPE_ISSTRUCT (t))
+                       return &mono_defaults.int_class->byval_arg;
+
+               klass = mono_class_from_mono_type (t);
+               orig_ctx = &klass->generic_class->context;
+
+               memset (&ctx, 0, sizeof (MonoGenericContext));
+
+               inst = orig_ctx->class_inst;
+               if (inst) {
+                       g_assert (inst->type_argc < 16);
+                       for (i = 0; i < inst->type_argc; ++i)
+                               args [i] = get_wrapper_shared_type (inst->type_argv [i]);
+                       ctx.class_inst = mono_metadata_get_generic_inst (inst->type_argc, args);
+               }
+               inst = orig_ctx->method_inst;
+               if (inst) {
+                       g_assert (inst->type_argc < 16);
+                       for (i = 0; i < inst->type_argc; ++i)
+                               args [i] = get_wrapper_shared_type (inst->type_argv [i]);
+                       ctx.method_inst = mono_metadata_get_generic_inst (inst->type_argc, args);
+               }
+               klass = mono_class_inflate_generic_class (klass->generic_class->container_class, &ctx);
+               return &klass->byval_arg;
+       }
+#if SIZEOF_VOID_P == 8
+       case MONO_TYPE_I8:
+               return &mono_defaults.int_class->byval_arg;
+#endif
+       default:
+               break;
+       }
+
+       //printf ("%s\n", mono_type_full_name (t));
+
+       return t;
+}
+
+static MonoMethodSignature*
+mini_get_underlying_signature (MonoMethodSignature *sig)
+{
+       MonoMethodSignature *res = mono_metadata_signature_dup (sig);
+       int i;
+
+       res->ret = get_wrapper_shared_type (sig->ret);
+       for (i = 0; i < sig->param_count; ++i)
+               res->params [i] = get_wrapper_shared_type (sig->params [i]);
+       res->generic_param_count = 0;
+       res->is_inflated = 0;
+
+       return res;
+}
+
+/*
+ * mini_get_gsharedvt_in_sig_wrapper:
+ *
+ *   Return a wrapper to translate between the normal and gsharedvt calling conventions of SIG.
+ * The returned wrapper has a signature of SIG, plus one extra argument, which is an <addr, rgctx> pair.
+ * The extra argument is passed the same way as an rgctx to shared methods.
+ * It calls <addr> using the gsharedvt version of SIG, passing in <rgctx> as an extra argument.
+ */
+MonoMethod*
+mini_get_gsharedvt_in_sig_wrapper (MonoMethodSignature *sig)
+{
+       MonoMethodBuilder *mb;
+       MonoMethod *res;
+       WrapperInfo *info;
+       MonoMethodSignature *csig, *gsharedvt_sig;
+       int i, pindex, retval_var;
+       static GHashTable *cache;
+
+       // FIXME: Memory management
+       sig = mini_get_underlying_signature (sig);
+
+       // FIXME: Normal cache
+       if (!cache)
+               cache = g_hash_table_new_full ((GHashFunc)mono_signature_hash, (GEqualFunc)mono_metadata_signature_equal, NULL, NULL);
+       // FIXME: Locking
+       res = g_hash_table_lookup (cache, sig);
+       if (res) {
+               g_free (sig);
+               return res;
+       }
+
+       /* Create the signature for the wrapper */
+       // FIXME:
+       csig = g_malloc0 (MONO_SIZEOF_METHOD_SIGNATURE + ((sig->param_count + 1) * sizeof (MonoType*)));
+       memcpy (csig, sig, mono_metadata_signature_size (sig));
+       csig->param_count ++;
+       csig->params [sig->param_count] = &mono_defaults.int_class->byval_arg;
+
+       /* Create the signature for the gsharedvt callconv */
+       gsharedvt_sig = g_malloc0 (MONO_SIZEOF_METHOD_SIGNATURE + ((sig->param_count + 2) * sizeof (MonoType*)));
+       memcpy (gsharedvt_sig, sig, mono_metadata_signature_size (sig));
+       pindex = 0;
+       /* The return value is returned using an explicit vret argument */
+       if (sig->ret->type != MONO_TYPE_VOID) {
+               gsharedvt_sig->params [pindex ++] = &mono_defaults.int_class->byval_arg;
+               gsharedvt_sig->ret = &mono_defaults.void_class->byval_arg;
+       }
+       for (i = 0; i < sig->param_count; i++) {
+               gsharedvt_sig->params [pindex] = sig->params [i];
+               if (!sig->params [i]->byref) {
+                       gsharedvt_sig->params [pindex] = mono_metadata_type_dup (NULL, gsharedvt_sig->params [pindex]);
+                       gsharedvt_sig->params [pindex]->byref = 1;
+               }
+               pindex ++;
+       }
+       /* Rgctx arg */
+       gsharedvt_sig->params [pindex ++] = &mono_defaults.int_class->byval_arg;
+       gsharedvt_sig->param_count = pindex;
+
+       // FIXME: Use shared signatures
+       mb = mono_mb_new (mono_defaults.object_class, sig->hasthis ? "gsharedvt_in_sig" : "gsharedvt_in_sig_static", MONO_WRAPPER_UNKNOWN);
+
+#ifndef DISABLE_JIT
+       if (sig->ret->type != MONO_TYPE_VOID)
+               retval_var = mono_mb_add_local (mb, sig->ret);
+
+       /* Make the call */
+       if (sig->hasthis)
+               mono_mb_emit_ldarg (mb, 0);
+       if (sig->ret->type != MONO_TYPE_VOID)
+               mono_mb_emit_ldloc_addr (mb, retval_var);
+       for (i = 0; i < sig->param_count; i++) {
+               if (sig->params [i]->byref)
+                       mono_mb_emit_ldarg (mb, i + (sig->hasthis == TRUE));
+               else
+                       mono_mb_emit_ldarg_addr (mb, i + (sig->hasthis == TRUE));
+       }
+       /* Rgctx arg */
+       mono_mb_emit_ldarg (mb, sig->param_count + (sig->hasthis ? 1 : 0));
+       mono_mb_emit_icon (mb, sizeof (gpointer));
+       mono_mb_emit_byte (mb, CEE_ADD);
+       mono_mb_emit_byte (mb, CEE_LDIND_I);
+       /* Method to call */
+       mono_mb_emit_ldarg (mb, sig->param_count + (sig->hasthis ? 1 : 0));
+       mono_mb_emit_byte (mb, CEE_LDIND_I);
+       mono_mb_emit_calli (mb, gsharedvt_sig);
+       if (sig->ret->type != MONO_TYPE_VOID)
+               mono_mb_emit_ldloc (mb, retval_var);
+       mono_mb_emit_byte (mb, CEE_RET);
+#endif
+
+       info = mono_wrapper_info_create (mb, WRAPPER_SUBTYPE_GSHAREDVT_IN_SIG);
+       info->d.gsharedvt.sig = sig;
+
+       res = mono_mb_create (mb, csig, sig->param_count + 16, info);
+
+       // FIXME: Locking
+       g_hash_table_insert (cache, sig, res);
+
+       return res;
+}
+
+/*
+ * mini_get_gsharedvt_out_sig_wrapper:
+ *
+ *   Same as in_sig_wrapper, but translate between the gsharedvt and normal signatures.
+ */
+MonoMethod*
+mini_get_gsharedvt_out_sig_wrapper (MonoMethodSignature *sig)
+{
+       MonoMethodBuilder *mb;
+       MonoMethod *res;
+       WrapperInfo *info;
+       MonoMethodSignature *normal_sig, *csig;
+       int i, pindex, args_start, ldind_op, stind_op;
+       static GHashTable *cache;
+
+       // FIXME: Memory management
+       sig = mini_get_underlying_signature (sig);
+
+       // FIXME: Normal cache
+       if (!cache)
+               cache = g_hash_table_new_full ((GHashFunc)mono_signature_hash, (GEqualFunc)mono_metadata_signature_equal, NULL, NULL);
+       // FIXME: Locking
+       res = g_hash_table_lookup (cache, sig);
+       if (res) {
+               g_free (sig);
+               return res;
+       }
+
+       /* Create the signature for the wrapper */
+       // FIXME:
+       csig = g_malloc0 (MONO_SIZEOF_METHOD_SIGNATURE + ((sig->param_count + 2) * sizeof (MonoType*)));
+       memcpy (csig, sig, mono_metadata_signature_size (sig));
+       pindex = 0;
+       /* The return value is returned using an explicit vret argument */
+       if (sig->ret->type != MONO_TYPE_VOID) {
+               csig->params [pindex ++] = &mono_defaults.int_class->byval_arg;
+               csig->ret = &mono_defaults.void_class->byval_arg;
+       }
+       args_start = pindex;
+       if (sig->hasthis)
+               args_start ++;
+       for (i = 0; i < sig->param_count; i++) {
+               csig->params [pindex] = sig->params [i];
+               if (!sig->params [i]->byref) {
+                       csig->params [pindex] = mono_metadata_type_dup (NULL, csig->params [pindex]);
+                       csig->params [pindex]->byref = 1;
+               }
+               pindex ++;
+       }
+       /* Rgctx arg */
+       csig->params [pindex ++] = &mono_defaults.int_class->byval_arg;
+       csig->param_count = pindex;
+
+       /* Create the signature for the normal callconv */
+       normal_sig = g_malloc0 (MONO_SIZEOF_METHOD_SIGNATURE + ((sig->param_count + 2) * sizeof (MonoType*)));
+       memcpy (normal_sig, sig, mono_metadata_signature_size (sig));
+       normal_sig->param_count ++;
+       normal_sig->params [sig->param_count] = &mono_defaults.int_class->byval_arg;
+
+       // FIXME: Use shared signatures
+       mb = mono_mb_new (mono_defaults.object_class, "gsharedvt_out_sig", MONO_WRAPPER_UNKNOWN);
+
+#ifndef DISABLE_JIT
+       if (sig->ret->type != MONO_TYPE_VOID)
+               /* Load return address */
+               mono_mb_emit_ldarg (mb, sig->hasthis ? 1 : 0);
+
+       /* Make the call */
+       if (sig->hasthis)
+               mono_mb_emit_ldarg (mb, 0);
+       for (i = 0; i < sig->param_count; i++) {
+               if (sig->params [i]->byref) {
+                       mono_mb_emit_ldarg (mb, args_start + i);
+               } else {
+                       ldind_op = mono_type_to_ldind (sig->params [i]);
+                       mono_mb_emit_ldarg (mb, args_start + i);
+                       // FIXME:
+                       if (ldind_op == CEE_LDOBJ)
+                               mono_mb_emit_op (mb, CEE_LDOBJ, mono_class_from_mono_type (sig->params [i]));
+                       else
+                               mono_mb_emit_byte (mb, ldind_op);
+               }
+       }
+       /* Rgctx arg */
+       mono_mb_emit_ldarg (mb, args_start + sig->param_count);
+       mono_mb_emit_icon (mb, sizeof (gpointer));
+       mono_mb_emit_byte (mb, CEE_ADD);
+       mono_mb_emit_byte (mb, CEE_LDIND_I);
+       /* Method to call */
+       mono_mb_emit_ldarg (mb, args_start + sig->param_count);
+       mono_mb_emit_byte (mb, CEE_LDIND_I);
+       mono_mb_emit_calli (mb, normal_sig);
+       if (sig->ret->type != MONO_TYPE_VOID) {
+               /* Store return value */
+               stind_op = mono_type_to_stind (sig->ret);
+               // FIXME:
+               if (stind_op == CEE_STOBJ)
+                       mono_mb_emit_op (mb, CEE_STOBJ, mono_class_from_mono_type (sig->ret));
+               else
+                       mono_mb_emit_byte (mb, stind_op);
+       }
+       mono_mb_emit_byte (mb, CEE_RET);
+#endif
+
+       info = mono_wrapper_info_create (mb, WRAPPER_SUBTYPE_GSHAREDVT_OUT_SIG);
+       info->d.gsharedvt.sig = sig;
+
+       res = mono_mb_create (mb, csig, sig->param_count + 16, info);
+
+       // FIXME: Locking
+       g_hash_table_insert (cache, sig, res);
+
+       return res;
+}
+
+MonoMethodSignature*
+mini_get_gsharedvt_out_sig_wrapper_signature (gboolean has_this, gboolean has_ret, int param_count)
+{
+       MonoMethodSignature *sig = g_malloc0 (sizeof (MonoMethodSignature) + (32 * sizeof (MonoType*)));
+       int i, pindex;
+
+       sig->ret = &mono_defaults.void_class->byval_arg;
+       sig->sentinelpos = -1;
+       pindex = 0;
+       if (has_this)
+               /* this */
+               sig->params [pindex ++] = &mono_defaults.int_class->byval_arg;
+       if (has_ret)
+               /* vret */
+               sig->params [pindex ++] = &mono_defaults.int_class->byval_arg;
+       for (i = 0; i < param_count; ++i)
+               /* byref arguments */
+               sig->params [pindex ++] = &mono_defaults.int_class->byval_arg;
+       /* extra arg */
+       sig->params [pindex ++] = &mono_defaults.int_class->byval_arg;
+       sig->param_count = pindex;
+
+       return sig;
+}
+
 /*
  * mini_get_gsharedvt_wrapper:
  *
@@ -1055,6 +1387,17 @@ mini_get_gsharedvt_wrapper (gboolean gsharedvt_in, gpointer addr, MonoMethodSign
                inited = TRUE;
        }
 
+       if (mono_llvm_only) {
+               MonoMethod *wrapper;
+
+               if (gsharedvt_in)
+                       wrapper = mini_get_gsharedvt_in_sig_wrapper (normal_sig);
+               else
+                       wrapper = mini_get_gsharedvt_out_sig_wrapper (normal_sig);
+               res = mono_compile_method (wrapper);
+               return res;
+       }
+
        memset (&tinfo, 0, sizeof (tinfo));
        tinfo.is_in = gsharedvt_in;
        tinfo.calli = calli;
@@ -1110,7 +1453,7 @@ mini_get_gsharedvt_wrapper (gboolean gsharedvt_in, gpointer addr, MonoMethodSign
        num_trampolines ++;
 
        /* Cache it */
-       tramp_info = mono_domain_alloc0 (domain, sizeof (GSharedVtTrampInfo));
+       tramp_info = (GSharedVtTrampInfo *)mono_domain_alloc0 (domain, sizeof (GSharedVtTrampInfo));
        memcpy (tramp_info, &tinfo, sizeof (GSharedVtTrampInfo));
 
        mono_domain_lock (domain);
@@ -1158,7 +1501,7 @@ instantiate_info (MonoDomain *domain, MonoRuntimeGenericContextInfoTemplate *oti
        case MONO_RGCTX_INFO_BZERO:
        case MONO_RGCTX_INFO_NULLABLE_CLASS_BOX:
        case MONO_RGCTX_INFO_NULLABLE_CLASS_UNBOX: {
-               MonoClass *arg_class = mono_class_from_mono_type (data);
+               MonoClass *arg_class = mono_class_from_mono_type ((MonoType *)data);
 
                free_inflated_info (oti->info_type, data);
                g_assert (arg_class);
@@ -1174,17 +1517,54 @@ instantiate_info (MonoDomain *domain, MonoRuntimeGenericContextInfoTemplate *oti
        case MONO_RGCTX_INFO_TYPE:
                return data;
        case MONO_RGCTX_INFO_REFLECTION_TYPE:
-               return mono_type_get_object (domain, data);
+               return mono_type_get_object (domain, (MonoType *)data);
        case MONO_RGCTX_INFO_METHOD:
                return data;
        case MONO_RGCTX_INFO_GENERIC_METHOD_CODE: {
+               MonoMethod *m = (MonoMethod*)data;
                gpointer addr;
+               gpointer arg = NULL;
+
+               if (mono_llvm_only) {
+                       addr = mono_compile_method (m);
+                       addr = mini_add_method_wrappers_llvmonly (m, addr, FALSE, FALSE, &arg);
 
-               addr = mono_compile_method (data);
-               return mini_add_method_trampoline (data, addr, mono_method_needs_static_rgctx_invoke (data, FALSE), FALSE);
+                       /* Returns an ftndesc */
+                       return mini_create_llvmonly_ftndesc (domain, addr, arg);
+               } else {
+                       addr = mono_compile_method ((MonoMethod *)data);
+                       return mini_add_method_trampoline ((MonoMethod *)data, addr, mono_method_needs_static_rgctx_invoke ((MonoMethod *)data, FALSE), FALSE);
+               }
+       }
+       case MONO_RGCTX_INFO_GSHAREDVT_OUT_WRAPPER: {
+               MonoMethod *m = (MonoMethod*)data;
+               gpointer addr;
+               gpointer arg = NULL;
+
+               g_assert (mono_llvm_only);
+
+               addr = mono_compile_method (m);
+
+               MonoJitInfo *ji;
+               gboolean callee_gsharedvt;
+
+               ji = mini_jit_info_table_find (mono_domain_get (), (char *)mono_get_addr_from_ftnptr (addr), NULL);
+               g_assert (ji);
+               callee_gsharedvt = mini_jit_info_is_gsharedvt (ji);
+               if (callee_gsharedvt)
+                       callee_gsharedvt = mini_is_gsharedvt_variable_signature (mono_method_signature (jinfo_get_method (ji)));
+               if (callee_gsharedvt) {
+                       /* No need for a wrapper */
+                       return mini_create_llvmonly_ftndesc (domain, addr, mini_method_get_rgctx (m));
+               } else {
+                       addr = mini_add_method_wrappers_llvmonly (m, addr, FALSE, FALSE, &arg);
+
+                       /* Returns an ftndesc */
+                       return mini_create_llvmonly_ftndesc (domain, addr, arg);
+               }
        }
        case MONO_RGCTX_INFO_VIRT_METHOD_CODE: {
-               MonoJumpInfoVirtMethod *info = data;
+               MonoJumpInfoVirtMethod *info = (MonoJumpInfoVirtMethod *)data;
                MonoClass *iface_class = info->method->klass;
                MonoMethod *method;
                MonoError error;
@@ -1210,7 +1590,7 @@ instantiate_info (MonoDomain *domain, MonoRuntimeGenericContextInfoTemplate *oti
                return mini_add_method_trampoline (method, addr, mono_method_needs_static_rgctx_invoke (method, FALSE), FALSE);
        }
        case MONO_RGCTX_INFO_VIRT_METHOD_BOX_TYPE: {
-               MonoJumpInfoVirtMethod *info = data;
+               MonoJumpInfoVirtMethod *info = (MonoJumpInfoVirtMethod *)data;
                MonoClass *iface_class = info->method->klass;
                MonoMethod *method;
                MonoClass *impl_class;
@@ -1231,30 +1611,31 @@ instantiate_info (MonoDomain *domain, MonoRuntimeGenericContextInfoTemplate *oti
 
                impl_class = method->klass;
                if (MONO_TYPE_IS_REFERENCE (&impl_class->byval_arg))
-                       return GUINT_TO_POINTER (1);
+                       return GUINT_TO_POINTER (MONO_GSHAREDVT_BOX_TYPE_REF);
                else if (mono_class_is_nullable (impl_class))
-                       return GUINT_TO_POINTER (2);
+                       return GUINT_TO_POINTER (MONO_GSHAREDVT_BOX_TYPE_NULLABLE);
                else
-                       return GUINT_TO_POINTER (0);
+                       return GUINT_TO_POINTER (MONO_GSHAREDVT_BOX_TYPE_VTYPE);
        }
 #ifndef DISABLE_REMOTING
        case MONO_RGCTX_INFO_REMOTING_INVOKE_WITH_CHECK:
-               return mono_compile_method (mono_marshal_get_remoting_invoke_with_check (data));
+               return mono_compile_method (mono_marshal_get_remoting_invoke_with_check ((MonoMethod *)data));
 #endif
        case MONO_RGCTX_INFO_METHOD_DELEGATE_CODE:
                return mono_domain_alloc0 (domain, sizeof (gpointer));
        case MONO_RGCTX_INFO_CLASS_FIELD:
                return data;
        case MONO_RGCTX_INFO_FIELD_OFFSET: {
-               MonoClassField *field = data;
+               MonoClassField *field = (MonoClassField *)data;
 
+               /* The value is offset by 1 */
                if (field->parent->valuetype && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
-                       return GUINT_TO_POINTER (field->offset - sizeof (MonoObject));
+                       return GUINT_TO_POINTER (field->offset - sizeof (MonoObject) + 1);
                else
-                       return GUINT_TO_POINTER (field->offset);
+                       return GUINT_TO_POINTER (field->offset + 1);
        }
        case MONO_RGCTX_INFO_METHOD_RGCTX: {
-               MonoMethodInflated *method = data;
+               MonoMethodInflated *method = (MonoMethodInflated *)data;
                MonoVTable *vtable;
 
                g_assert (method->method.method.is_inflated);
@@ -1267,16 +1648,27 @@ instantiate_info (MonoDomain *domain, MonoRuntimeGenericContextInfoTemplate *oti
                return mono_method_lookup_rgctx (vtable, method->context.method_inst);
        }
        case MONO_RGCTX_INFO_METHOD_CONTEXT: {
-               MonoMethodInflated *method = data;
+               MonoMethodInflated *method = (MonoMethodInflated *)data;
 
                g_assert (method->method.method.is_inflated);
                g_assert (method->context.method_inst);
 
                return method->context.method_inst;
        }
+       case MONO_RGCTX_INFO_SIG_GSHAREDVT_IN_TRAMPOLINE_CALLI: {
+               MonoMethodSignature *gsig = (MonoMethodSignature *)oti->data;
+               MonoMethodSignature *sig = (MonoMethodSignature *)data;
+               gpointer addr;
+
+               /*
+                * This is an indirect call to the address passed by the caller in the rgctx reg.
+                */
+               addr = mini_get_gsharedvt_wrapper (TRUE, NULL, sig, gsig, -1, TRUE);
+               return addr;
+       }
        case MONO_RGCTX_INFO_SIG_GSHAREDVT_OUT_TRAMPOLINE_CALLI: {
-               MonoMethodSignature *gsig = oti->data;
-               MonoMethodSignature *sig = data;
+               MonoMethodSignature *gsig = (MonoMethodSignature *)oti->data;
+               MonoMethodSignature *sig = (MonoMethodSignature *)data;
                gpointer addr;
 
                /*
@@ -1287,12 +1679,12 @@ instantiate_info (MonoDomain *domain, MonoRuntimeGenericContextInfoTemplate *oti
        }
        case MONO_RGCTX_INFO_METHOD_GSHAREDVT_OUT_TRAMPOLINE:
        case MONO_RGCTX_INFO_METHOD_GSHAREDVT_OUT_TRAMPOLINE_VIRT: {
-               MonoJumpInfoGSharedVtCall *call_info = data;
+               MonoJumpInfoGSharedVtCall *call_info = (MonoJumpInfoGSharedVtCall *)data;
                MonoMethodSignature *call_sig;
                MonoMethod *method;
                gpointer addr;
                MonoJitInfo *callee_ji;
-               gboolean virtual = oti->info_type == MONO_RGCTX_INFO_METHOD_GSHAREDVT_OUT_TRAMPOLINE_VIRT;
+               gboolean virtual_ = oti->info_type == MONO_RGCTX_INFO_METHOD_GSHAREDVT_OUT_TRAMPOLINE_VIRT;
                gint32 vcall_offset;
                gboolean callee_gsharedvt;
 
@@ -1303,12 +1695,12 @@ instantiate_info (MonoDomain *domain, MonoRuntimeGenericContextInfoTemplate *oti
 
                g_assert (method->is_inflated);
 
-               if (!virtual)
+               if (!virtual_)
                        addr = mono_compile_method (method);
                else
                        addr = NULL;
 
-               if (virtual) {
+               if (virtual_) {
                        /* Same as in mono_emit_method_call_full () */
                        if ((method->klass->parent == mono_defaults.multicastdelegate_class) && (!strcmp (method->name, "Invoke"))) {
                                /* See mono_emit_method_call_full () */
@@ -1326,7 +1718,7 @@ instantiate_info (MonoDomain *domain, MonoRuntimeGenericContextInfoTemplate *oti
                }
 
                // FIXME: This loads information in the AOT case
-               callee_ji = mini_jit_info_table_find (mono_domain_get (), mono_get_addr_from_ftnptr (addr), NULL);
+               callee_ji = mini_jit_info_table_find (mono_domain_get (), (char *)mono_get_addr_from_ftnptr (addr), NULL);
                callee_gsharedvt = ji_is_gsharedvt (callee_ji);
 
                /*
@@ -1340,7 +1732,7 @@ instantiate_info (MonoDomain *domain, MonoRuntimeGenericContextInfoTemplate *oti
                 * caller -> out trampoline -> in trampoline -> callee
                 * This is not very efficient, but it is easy to implement.
                 */
-               if (virtual || !callee_gsharedvt) {
+               if (virtual_ || !callee_gsharedvt) {
                        MonoMethodSignature *sig, *gsig;
 
                        g_assert (method->is_inflated);
@@ -1348,14 +1740,29 @@ instantiate_info (MonoDomain *domain, MonoRuntimeGenericContextInfoTemplate *oti
                        sig = mono_method_signature (method);
                        gsig = call_sig;
 
-                       addr = mini_get_gsharedvt_wrapper (FALSE, addr, sig, gsig, vcall_offset, FALSE);
+                       if (mono_llvm_only) {
+                               if (mini_is_gsharedvt_variable_signature (call_sig)) {
+                                       /* The virtual case doesn't go through this code */
+                                       g_assert (!virtual_);
+
+                                       sig = mono_method_signature (jinfo_get_method (callee_ji));
+                                       gpointer out_wrapper = mini_get_gsharedvt_wrapper (FALSE, NULL, sig, gsig, -1, FALSE);
+                                       MonoFtnDesc *out_wrapper_arg = mini_create_llvmonly_ftndesc (domain, callee_ji->code_start, mini_method_get_rgctx (method));
+
+                                       /* Returns an ftndesc */
+                                       addr = mini_create_llvmonly_ftndesc (domain, out_wrapper, out_wrapper_arg);
+                               } else {
+                                       addr = mini_create_llvmonly_ftndesc (domain, addr, mini_method_get_rgctx (method));
+                               }
+                       } else {
+                               addr = mini_get_gsharedvt_wrapper (FALSE, addr, sig, gsig, vcall_offset, FALSE);
+                       }
 #if 0
                        if (virtual)
                                printf ("OUT-VCALL: %s\n", mono_method_full_name (method, TRUE));
                        else
                                printf ("OUT: %s\n", mono_method_full_name (method, TRUE));
 #endif
-                       //              } else if (!mini_is_gsharedvt_variable_signature (mono_method_signature (caller_method)) && callee_gsharedvt) {
                } else if (callee_gsharedvt) {
                        MonoMethodSignature *sig, *gsig;
 
@@ -1375,7 +1782,30 @@ instantiate_info (MonoDomain *domain, MonoRuntimeGenericContextInfoTemplate *oti
                         * FIXME: Optimize this.
                         */
 
-                       if (call_sig == mono_method_signature (method)) {
+                       if (mono_llvm_only) {
+                               /* Both wrappers receive an extra <addr, rgctx> argument */
+                               sig = mono_method_signature (method);
+                               gsig = mono_method_signature (jinfo_get_method (callee_ji));
+
+                               /* Return a function descriptor */
+
+                               if (mini_is_gsharedvt_variable_signature (call_sig)) {
+                                       /*
+                                        * This is not an optimization, but its needed, since the concrete signature 'sig'
+                                        * might not exist at all in IL, so the AOT compiler cannot generate the wrappers
+                                        * for it.
+                                        */
+                                       addr = mini_create_llvmonly_ftndesc (domain, callee_ji->code_start, mini_method_get_rgctx (method));
+                               } else if (mini_is_gsharedvt_variable_signature (gsig)) {
+                                       gpointer in_wrapper = mini_get_gsharedvt_wrapper (TRUE, callee_ji->code_start, sig, gsig, -1, FALSE);
+
+                                       gpointer in_wrapper_arg = mini_create_llvmonly_ftndesc (domain, callee_ji->code_start, mini_method_get_rgctx (method));
+
+                                       addr = mini_create_llvmonly_ftndesc (domain, in_wrapper, in_wrapper_arg);
+                               } else {
+                                       addr = mini_create_llvmonly_ftndesc (domain, addr, mini_method_get_rgctx (method));
+                               }
+                       } else if (call_sig == mono_method_signature (method)) {
                        } else {
                                sig = mono_method_signature (method);
                                gsig = mono_method_signature (jinfo_get_method (callee_ji)); 
@@ -1394,21 +1824,21 @@ instantiate_info (MonoDomain *domain, MonoRuntimeGenericContextInfoTemplate *oti
                return addr;
        }
        case MONO_RGCTX_INFO_METHOD_GSHAREDVT_INFO: {
-               MonoGSharedVtMethodInfo *info = data;
+               MonoGSharedVtMethodInfo *info = (MonoGSharedVtMethodInfo *)data;
                MonoGSharedVtMethodRuntimeInfo *res;
                MonoType *t;
                int i, offset, align, size;
 
                // FIXME:
-               res = g_malloc0 (sizeof (MonoGSharedVtMethodRuntimeInfo) + (info->num_entries * sizeof (gpointer)));
+               res = (MonoGSharedVtMethodRuntimeInfo *)g_malloc0 (sizeof (MonoGSharedVtMethodRuntimeInfo) + (info->num_entries * sizeof (gpointer)));
 
                offset = 0;
                for (i = 0; i < info->num_entries; ++i) {
-                       MonoRuntimeGenericContextInfoTemplate *template = &info->entries [i];
+                       MonoRuntimeGenericContextInfoTemplate *template_ = &info->entries [i];
 
-                       switch (template->info_type) {
+                       switch (template_->info_type) {
                        case MONO_RGCTX_INFO_LOCAL_OFFSET:
-                               t = template->data;
+                               t = (MonoType *)template_->data;
 
                                size = mono_type_size (t, &align);
 
@@ -1424,7 +1854,7 @@ instantiate_info (MonoDomain *domain, MonoRuntimeGenericContextInfoTemplate *oti
                                offset += size;
                                break;
                        default:
-                               res->entries [i] = instantiate_info (domain, template, context, klass);
+                               res->entries [i] = instantiate_info (domain, template_, context, klass);
                                break;
                        }
                }
@@ -1445,14 +1875,14 @@ instantiate_info (MonoDomain *domain, MonoRuntimeGenericContextInfoTemplate *oti
 static void
 fill_in_rgctx_template_slot (MonoClass *klass, int type_argc, int index, gpointer data, MonoRgctxInfoType info_type)
 {
-       MonoRuntimeGenericContextTemplate *template = mono_class_get_runtime_generic_context_template (klass);
+       MonoRuntimeGenericContextTemplate *template_ = mono_class_get_runtime_generic_context_template (klass);
        MonoClass *subclass;
 
-       rgctx_template_set_slot (klass->image, template, type_argc, index, data, info_type);
+       rgctx_template_set_slot (klass->image, template_, type_argc, index, data, info_type);
 
        /* Recurse for all subclasses */
        if (generic_subclass_hash)
-               subclass = g_hash_table_lookup (generic_subclass_hash, klass);
+               subclass = (MonoClass *)g_hash_table_lookup (generic_subclass_hash, klass);
        else
                subclass = NULL;
 
@@ -1484,6 +1914,7 @@ mono_rgctx_info_type_to_str (MonoRgctxInfoType type)
        case MONO_RGCTX_INFO_METHOD: return "METHOD";
        case MONO_RGCTX_INFO_METHOD_GSHAREDVT_INFO: return "GSHAREDVT_INFO";
        case MONO_RGCTX_INFO_GENERIC_METHOD_CODE: return "GENERIC_METHOD_CODE";
+       case MONO_RGCTX_INFO_GSHAREDVT_OUT_WRAPPER: return "GSHAREDVT_OUT_WRAPPER";
        case MONO_RGCTX_INFO_CLASS_FIELD: return "CLASS_FIELD";
        case MONO_RGCTX_INFO_METHOD_RGCTX: return "METHOD_RGCTX";
        case MONO_RGCTX_INFO_METHOD_CONTEXT: return "METHOD_CONTEXT";
@@ -1496,6 +1927,7 @@ mono_rgctx_info_type_to_str (MonoRgctxInfoType type)
        case MONO_RGCTX_INFO_FIELD_OFFSET: return "FIELD_OFFSET";
        case MONO_RGCTX_INFO_METHOD_GSHAREDVT_OUT_TRAMPOLINE: return "METHOD_GSHAREDVT_OUT_TRAMPOLINE";
        case MONO_RGCTX_INFO_METHOD_GSHAREDVT_OUT_TRAMPOLINE_VIRT: return "METHOD_GSHAREDVT_OUT_TRAMPOLINE_VIRT";
+       case MONO_RGCTX_INFO_SIG_GSHAREDVT_IN_TRAMPOLINE_CALLI: return "SIG_GSHAREDVT_IN_TRAMPOLINE_CALLI";
        case MONO_RGCTX_INFO_SIG_GSHAREDVT_OUT_TRAMPOLINE_CALLI: return "SIG_GSHAREDVT_OUT_TRAMPOLINE_CALLI";
        case MONO_RGCTX_INFO_MEMCPY: return "MEMCPY";
        case MONO_RGCTX_INFO_BZERO: return "BZERO";
@@ -1526,11 +1958,11 @@ static int
 register_info (MonoClass *klass, int type_argc, gpointer data, MonoRgctxInfoType info_type)
 {
        int i;
-       MonoRuntimeGenericContextTemplate *template = mono_class_get_runtime_generic_context_template (klass);
+       MonoRuntimeGenericContextTemplate *template_ = mono_class_get_runtime_generic_context_template (klass);
        MonoClass *parent;
        MonoRuntimeGenericContextInfoTemplate *oti;
 
-       for (i = 0, oti = get_info_templates (template, type_argc); oti; ++i, oti = oti->next) {
+       for (i = 0, oti = get_info_templates (template_, type_argc); oti; ++i, oti = oti->next) {
                if (!oti->data)
                        break;
        }
@@ -1554,7 +1986,7 @@ register_info (MonoClass *klass, int type_argc, gpointer data, MonoRgctxInfoType
                        break;
 
                rgctx_template_set_slot (parent->image, parent_template, type_argc, i,
-                                                                MONO_RGCTX_SLOT_USED_MARKER, 0);
+                                                                MONO_RGCTX_SLOT_USED_MARKER, (MonoRgctxInfoType)0);
 
                parent = parent->parent;
        }
@@ -1584,10 +2016,11 @@ info_equal (gpointer data1, gpointer data2, MonoRgctxInfoType info_type)
        case MONO_RGCTX_INFO_BZERO:
        case MONO_RGCTX_INFO_NULLABLE_CLASS_BOX:
        case MONO_RGCTX_INFO_NULLABLE_CLASS_UNBOX:
-               return mono_class_from_mono_type (data1) == mono_class_from_mono_type (data2);
+               return mono_class_from_mono_type ((MonoType *)data1) == mono_class_from_mono_type ((MonoType *)data2);
        case MONO_RGCTX_INFO_METHOD:
        case MONO_RGCTX_INFO_METHOD_GSHAREDVT_INFO:
        case MONO_RGCTX_INFO_GENERIC_METHOD_CODE:
+       case MONO_RGCTX_INFO_GSHAREDVT_OUT_WRAPPER:
        case MONO_RGCTX_INFO_CLASS_FIELD:
        case MONO_RGCTX_INFO_FIELD_OFFSET:
        case MONO_RGCTX_INFO_METHOD_RGCTX:
@@ -1596,12 +2029,13 @@ info_equal (gpointer data1, gpointer data2, MonoRgctxInfoType info_type)
        case MONO_RGCTX_INFO_METHOD_DELEGATE_CODE:
        case MONO_RGCTX_INFO_METHOD_GSHAREDVT_OUT_TRAMPOLINE:
        case MONO_RGCTX_INFO_METHOD_GSHAREDVT_OUT_TRAMPOLINE_VIRT:
+       case MONO_RGCTX_INFO_SIG_GSHAREDVT_IN_TRAMPOLINE_CALLI:
        case MONO_RGCTX_INFO_SIG_GSHAREDVT_OUT_TRAMPOLINE_CALLI:
                return data1 == data2;
        case MONO_RGCTX_INFO_VIRT_METHOD_CODE:
        case MONO_RGCTX_INFO_VIRT_METHOD_BOX_TYPE: {
-               MonoJumpInfoVirtMethod *info1 = data1;
-               MonoJumpInfoVirtMethod *info2 = data2;
+               MonoJumpInfoVirtMethod *info1 = (MonoJumpInfoVirtMethod *)data1;
+               MonoJumpInfoVirtMethod *info2 = (MonoJumpInfoVirtMethod *)data2;
 
                return info1->klass == info2->klass && info1->method == info2->method;
        }
@@ -1641,7 +2075,7 @@ mini_rgctx_info_type_to_patch_info_type (MonoRgctxInfoType info_type)
                return MONO_PATCH_INFO_FIELD;
        default:
                g_assert_not_reached ();
-               return -1;
+               return (MonoJumpInfoType)-1;
        }
 }
 
@@ -1768,7 +2202,7 @@ alloc_rgctx_array (MonoDomain *domain, int n, gboolean is_mrgctx)
        static int mrgctx_bytes_alloced = 0;
 
        int size = mono_class_rgctx_get_array_size (n, is_mrgctx) * sizeof (gpointer);
-       gpointer array = mono_domain_alloc0 (domain, size);
+       gpointer *array = (gpointer *)mono_domain_alloc0 (domain, size);
 
        if (!inited) {
                mono_counters_register ("RGCTX num arrays alloced", MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &rgctx_num_alloced);
@@ -1833,7 +2267,7 @@ fill_runtime_generic_context (MonoVTable *class_vtable, MonoRuntimeGenericContex
                }
                if (!rgctx [offset + 0])
                        rgctx [offset + 0] = alloc_rgctx_array (domain, i + 1, method_inst != NULL);
-               rgctx = rgctx [offset + 0];
+               rgctx = (void **)rgctx [offset + 0];
                first_slot += size - 1;
                size = mono_class_rgctx_get_array_size (i + 1, method_inst != NULL);
        }
@@ -1846,6 +2280,7 @@ fill_runtime_generic_context (MonoVTable *class_vtable, MonoRuntimeGenericContex
                                                                                method_inst ? method_inst->type_argc : 0, slot, TRUE, TRUE, &do_free);
        /* This might take the loader lock */
        info = instantiate_info (domain, &oti, &context, klass);
+       g_assert (info);
 
        /*
        if (method_inst)
@@ -1930,7 +2365,7 @@ mono_method_fill_runtime_generic_context (MonoMethodRuntimeGenericContext *mrgct
 static guint
 mrgctx_hash_func (gconstpointer key)
 {
-       const MonoMethodRuntimeGenericContext *mrgctx = key;
+       const MonoMethodRuntimeGenericContext *mrgctx = (const MonoMethodRuntimeGenericContext *)key;
 
        return mono_aligned_addr_hash (mrgctx->class_vtable) ^ mono_metadata_generic_inst_hash (mrgctx->method_inst);
 }
@@ -1938,8 +2373,8 @@ mrgctx_hash_func (gconstpointer key)
 static gboolean
 mrgctx_equal_func (gconstpointer a, gconstpointer b)
 {
-       const MonoMethodRuntimeGenericContext *mrgctx1 = a;
-       const MonoMethodRuntimeGenericContext *mrgctx2 = b;
+       const MonoMethodRuntimeGenericContext *mrgctx1 = (const MonoMethodRuntimeGenericContext *)a;
+       const MonoMethodRuntimeGenericContext *mrgctx2 = (const MonoMethodRuntimeGenericContext *)b;
 
        return mrgctx1->class_vtable == mrgctx2->class_vtable &&
                mono_metadata_generic_inst_equal (mrgctx1->method_inst, mrgctx2->method_inst);
@@ -1972,7 +2407,7 @@ mono_method_lookup_rgctx (MonoVTable *class_vtable, MonoGenericInst *method_inst
        key.class_vtable = class_vtable;
        key.method_inst = method_inst;
 
-       mrgctx = g_hash_table_lookup (domain->method_rgctx_hash, &key);
+       mrgctx = (MonoMethodRuntimeGenericContext *)g_hash_table_lookup (domain->method_rgctx_hash, &key);
 
        if (!mrgctx) {
                //int i;
@@ -2333,7 +2768,7 @@ get_object_generic_inst (int type_argc)
        MonoType **type_argv;
        int i;
 
-       type_argv = alloca (sizeof (MonoType*) * type_argc);
+       type_argv = (MonoType **)alloca (sizeof (MonoType*) * type_argc);
 
        for (i = 0; i < type_argc; ++i)
                type_argv [i] = &mono_defaults.object_class->byval_arg;
@@ -2568,6 +3003,8 @@ mini_type_get_underlying_type (MonoType *type)
                return &mono_defaults.byte_class->byval_arg;
        case MONO_TYPE_CHAR:
                return &mono_defaults.uint16_class->byval_arg;
+       case MONO_TYPE_STRING:
+               return &mono_defaults.object_class->byval_arg;
        default:
                return type;
        }
@@ -2622,6 +3059,11 @@ mini_type_stack_size_full (MonoType *t, guint32 *align, gboolean pinvoke)
 void
 mono_generic_sharing_init (void)
 {
+       mono_counters_register ("RGCTX template num allocted", MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &num_templates_allocted);
+       mono_counters_register ("RGCTX template bytes allocted", MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &num_templates_bytes);
+       mono_counters_register ("RGCTX oti num allocted", MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &num_oti_allocted);
+       mono_counters_register ("RGCTX oti bytes allocted", MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &num_oti_bytes);
+
        mono_install_image_unload_hook (mono_class_unregister_image_generic_subclasses, NULL);
 }
 
@@ -2643,7 +3085,7 @@ gboolean
 mini_type_var_is_vt (MonoType *type)
 {
        if (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR) {
-               return type->data.generic_param->gshared_constraint && type->data.generic_param->gshared_constraint->type == MONO_TYPE_VALUETYPE;
+               return type->data.generic_param->gshared_constraint && (type->data.generic_param->gshared_constraint->type == MONO_TYPE_VALUETYPE || type->data.generic_param->gshared_constraint->type == MONO_TYPE_GENERICINST);
        } else {
                g_assert_not_reached ();
                return FALSE;
@@ -2777,38 +3219,31 @@ mini_get_shared_gparam (MonoType *t, MonoType *constraint)
        key.param.param.gshared_constraint = constraint;
 
        g_assert (mono_generic_param_info (par));
-       /* image might not be set for sre */
-       if (par->owner && par->owner->image) {
-               image = par->owner->image;
+       image = get_image_for_generic_param(par);
 
-               /*
-                * Need a cache to ensure the newly created gparam
-                * is unique wrt T/CONSTRAINT.
-                */
-               mono_image_lock (image);
-               if (!image->gshared_types) {
-                       image->gshared_types_len = MONO_TYPE_INTERNAL;
-                       image->gshared_types = g_new0 (GHashTable*, image->gshared_types_len);
-               }
-               if (!image->gshared_types [constraint->type])
-                       image->gshared_types [constraint->type] = g_hash_table_new (shared_gparam_hash, shared_gparam_equal);
-               res = g_hash_table_lookup (image->gshared_types [constraint->type], &key);
-               mono_image_unlock (image);
-               if (res)
-                       return res;
-               copy = mono_image_alloc0 (image, sizeof (MonoGSharedGenericParam));
-               memcpy (&copy->param, par, sizeof (MonoGenericParamFull));
-               name = get_shared_gparam_name (constraint->type, ((MonoGenericParamFull*)copy)->info.name);
-               copy->param.info.name = mono_image_strdup (image, name);
-               g_free (name);
-       } else {
-               /* mono_generic_param_name () expects this to be a MonoGenericParamFull */
-               copy = g_new0 (MonoGSharedGenericParam, 1);
-               memcpy (&copy->param, par, sizeof (MonoGenericParam));
-       }
-       copy->param.param.owner = NULL;
-       // FIXME:
-       copy->param.param.image = image ? image : mono_defaults.corlib;
+       /*
+        * Need a cache to ensure the newly created gparam
+        * is unique wrt T/CONSTRAINT.
+        */
+       mono_image_lock (image);
+       if (!image->gshared_types) {
+               image->gshared_types_len = MONO_TYPE_INTERNAL;
+               image->gshared_types = g_new0 (GHashTable*, image->gshared_types_len);
+       }
+       if (!image->gshared_types [constraint->type])
+               image->gshared_types [constraint->type] = g_hash_table_new (shared_gparam_hash, shared_gparam_equal);
+       res = (MonoType *)g_hash_table_lookup (image->gshared_types [constraint->type], &key);
+       mono_image_unlock (image);
+       if (res)
+               return res;
+       copy = (MonoGSharedGenericParam *)mono_image_alloc0 (image, sizeof (MonoGSharedGenericParam));
+       memcpy (&copy->param, par, sizeof (MonoGenericParamFull));
+       copy->param.info.pklass = NULL;
+       name = get_shared_gparam_name (constraint->type, ((MonoGenericParamFull*)copy)->info.name);
+       copy->param.info.name = mono_image_strdup (image, name);
+       g_free (name);
+
+       copy->param.param.owner = par->owner;
 
        copy->param.param.gshared_constraint = constraint;
        copy->parent = par;
@@ -2996,7 +3431,7 @@ mini_get_rgctx_entry_slot (MonoJumpInfoRgctxEntry *entry)
                slot = mono_method_lookup_or_register_info (entry->method, entry->in_mrgctx, entry->data->data.sig, entry->info_type, mono_method_get_context (entry->method));
                break;
        case MONO_PATCH_INFO_GSHAREDVT_CALL: {
-               MonoJumpInfoGSharedVtCall *call_info = g_malloc0 (sizeof (MonoJumpInfoGSharedVtCall)); //mono_domain_alloc0 (domain, sizeof (MonoJumpInfoGSharedVtCall));
+               MonoJumpInfoGSharedVtCall *call_info = (MonoJumpInfoGSharedVtCall *)g_malloc0 (sizeof (MonoJumpInfoGSharedVtCall)); //mono_domain_alloc0 (domain, sizeof (MonoJumpInfoGSharedVtCall));
 
                memcpy (call_info, entry->data->data.gsharedvt, sizeof (MonoJumpInfoGSharedVtCall));
                slot = mono_method_lookup_or_register_info (entry->method, entry->in_mrgctx, call_info, entry->info_type, mono_method_get_context (entry->method));
@@ -3008,15 +3443,15 @@ mini_get_rgctx_entry_slot (MonoJumpInfoRgctxEntry *entry)
                int i;
 
                /* Make a copy into the domain mempool */
-               info = g_malloc0 (sizeof (MonoGSharedVtMethodInfo)); //mono_domain_alloc0 (domain, sizeof (MonoGSharedVtMethodInfo));
+               info = (MonoGSharedVtMethodInfo *)g_malloc0 (sizeof (MonoGSharedVtMethodInfo)); //mono_domain_alloc0 (domain, sizeof (MonoGSharedVtMethodInfo));
                info->method = oinfo->method;
                info->num_entries = oinfo->num_entries;
-               info->entries = g_malloc0 (sizeof (MonoRuntimeGenericContextInfoTemplate) * info->num_entries);
+               info->entries = (MonoRuntimeGenericContextInfoTemplate *)g_malloc0 (sizeof (MonoRuntimeGenericContextInfoTemplate) * info->num_entries);
                for (i = 0; i < oinfo->num_entries; ++i) {
                        MonoRuntimeGenericContextInfoTemplate *otemplate = &oinfo->entries [i];
-                       MonoRuntimeGenericContextInfoTemplate *template = &info->entries [i];
+                       MonoRuntimeGenericContextInfoTemplate *template_ = &info->entries [i];
 
-                       memcpy (template, otemplate, sizeof (MonoRuntimeGenericContextInfoTemplate));
+                       memcpy (template_, otemplate, sizeof (MonoRuntimeGenericContextInfoTemplate));
                }
                slot = mono_method_lookup_or_register_info (entry->method, entry->in_mrgctx, info, entry->info_type, mono_method_get_context (entry->method));
                break;
@@ -3025,7 +3460,7 @@ mini_get_rgctx_entry_slot (MonoJumpInfoRgctxEntry *entry)
                MonoJumpInfoVirtMethod *info;
                MonoJumpInfoVirtMethod *oinfo = entry->data->data.virt_method;
 
-               info = g_malloc0 (sizeof (MonoJumpInfoVirtMethod));
+               info = (MonoJumpInfoVirtMethod *)g_malloc0 (sizeof (MonoJumpInfoVirtMethod));
                memcpy (info, oinfo, sizeof (MonoJumpInfoVirtMethod));
                slot = mono_method_lookup_or_register_info (entry->method, entry->in_mrgctx, info, entry->info_type, mono_method_get_context (entry->method));
                break;