Merge pull request #2754 from markusbeth/fix-mono-config
authormonojenkins <jo.shields+jenkins@xamarin.com>
Mon, 14 Mar 2016 04:35:14 +0000 (04:35 +0000)
committermonojenkins <jo.shields+jenkins@xamarin.com>
Mon, 14 Mar 2016 04:35:14 +0000 (04:35 +0000)
fixed replacement of $mono_libdir in config file

strncpy does not NUL-terminate the destination string in this case so one cannot use strcat to append

This fixes the error "malloc: top chunk is corrupt" as reported on mono-devel-list back in 2015-10-20 (subject: "malloc error executing OBS-built mono") at least for me.

19 files changed:
acceptance-tests/SUBMODULES.json
acceptance-tests/coreclr.mk
mono/metadata/assembly.c
mono/metadata/icall-def.h
mono/metadata/icall.c
mono/metadata/reflection-internals.h
mono/metadata/reflection.c
mono/metadata/reflection.h
mono/mini/aot-runtime.c
mono/mini/debugger-agent.c
mono/mini/llvm-jit.cpp
mono/mini/llvm-jit.h
mono/mini/mini-llvm.c
mono/mini/mini-runtime.c
mono/mini/mini.c
mono/mini/mini.h
mono/tests/Makefile.am
mono/tests/assembly-load-remap.cs
mono/utils/mono-error.c

index e0335f40f7de3e375f209b4dae3846a63965e71b..534d2729fd3910edd70689e81da14878d37795a0 100644 (file)
@@ -10,7 +10,7 @@
   {
     "name": "coreclr", 
     "url": "git://github.com/mono/coreclr.git", 
-    "rev": "96cf61f96b42cf9d013e641609cb7787f6e3a71f", 
+    "rev": "d964b6b194e508921b75194b216c315116e33fef", 
     "remote-branch": "origin/mono", 
     "branch": "mono", 
     "directory": "coreclr"
@@ -18,7 +18,7 @@
   {
     "name": "ms-test-suite", 
     "url": "git@github.com:xamarin/ms-test-suite.git", 
-    "rev": "8eb26bd72a38e2c78675db45b13e89237dbdf4f2", 
+    "rev": "1ab0d4972937bf0451fc164f39a67475776a9edf", 
     "remote-branch": "origin/master", 
     "branch": "master", 
     "directory": "ms-test-suite"
index dd141bcb194851ff1394268a8771b4b1d11aaa48..2271e371f6906a8ef575697b7ab23057ab51dd04 100644 (file)
@@ -1186,7 +1186,6 @@ CORECLR_TEST_CS_SRC=              \
        $(CORECLR_PATH)/tests/src/Regressions/coreclr/0576/test0576.cs  \
        $(CORECLR_PATH)/tests/src/Regressions/coreclr/0582/csgen.1.cs   \
        $(CORECLR_PATH)/tests/src/Regressions/coreclr/0583/test583.cs   \
-       $(CORECLR_PATH)/tests/src/Regressions/coreclr/0584/test584.cs   \
        $(CORECLR_PATH)/tests/src/Regressions/coreclr/0792/test0792.cs  \
        $(CORECLR_PATH)/tests/src/Regressions/coreclr/0828/test0828.cs  \
        $(CORECLR_PATH)/tests/src/Regressions/coreclr/0829/test0829.cs  \
@@ -4001,6 +4000,9 @@ CORECLR_DISABLED_TEST_CS_SRC +=   \
        $(CORECLR_PATH)/tests/src/hosting/samples/hosting/usercode/usercode.cs  \
        $(CORECLR_PATH)/tests/src/hosting/samples/resolveevent/usercodedependency/usercodedependency.cs
 
+# this test makes no sense, the expected pattern is the English one for all cultures
+CORECLR_DISABLED_TEST_CS_SRC += $(CORECLR_PATH)/tests/src/Regressions/coreclr/0584/test584.cs
+
 CORECLR_TEST_IL_SRC =                  \
        $(CORECLR_PATH)/tests/src/JIT/BBT/Scenario4/Not-Int32.il        \
        $(CORECLR_PATH)/tests/src/JIT/Directed/Convert/implicitConv.il  \
index f37c9acca6ea12450228dfd556204b0cdc75a95d..275bcbb234309c1498d30ac3a283022c84b8a951 100644 (file)
 #include <mach-o/dyld.h>
 #endif
 
-/* AssemblyVersionMap: an assembly name and the assembly version set on which it is based */
+/* AssemblyVersionMap: an assembly name, the assembly version set on which it is based, the assembly name it is replaced with and whether only versions lower than the current runtime version should be remapped */
 typedef struct  {
        const char* assembly_name;
        guint8 version_set_index;
+       const char* new_assembly_name;
+       gboolean only_lower_versions;
 } AssemblyVersionMap;
 
 /* the default search path is empty, the first slot is replaced with the computed value */
@@ -89,8 +91,12 @@ static const AssemblyVersionMap framework_assemblies [] = {
        {"I18N.Other", 0},
        {"I18N.Rare", 0},
        {"I18N.West", 0},
-       {"Microsoft.Build.Engine", 2},
-       {"Microsoft.Build.Framework", 2},
+       {"Microsoft.Build.Engine", 2, NULL, TRUE},
+       {"Microsoft.Build.Framework", 2, NULL, TRUE},
+       {"Microsoft.Build.Tasks", 2, "Microsoft.Build.Tasks.v4.0"},
+       {"Microsoft.Build.Tasks.v3.5", 2, "Microsoft.Build.Tasks.v4.0"},
+       {"Microsoft.Build.Utilities", 2, "Microsoft.Build.Utilities.v4.0"},
+       {"Microsoft.Build.Utilities.v3.5", 2, "Microsoft.Build.Utilities.v4.0"},
        {"Microsoft.VisualBasic", 1},
        {"Microsoft.VisualC", 1},
        {"Mono.Cairo", 0},
@@ -1016,13 +1022,10 @@ mono_assembly_remap_version (MonoAssemblyName *aname, MonoAssemblyName *dest_ana
                        if (aname->major == vset->major && aname->minor == vset->minor &&
                                aname->build == vset->build && aname->revision == vset->revision)
                                return aname;
-
-                       if (compare_versions (vset, aname) < 0) {
-                               // requested version is newer than current
-                               // runtime version, don't remap
-                               return aname;
-                       }
                
+                       if (framework_assemblies[pos].only_lower_versions && compare_versions ((AssemblyVersionSet*)vset, aname) < 0)
+                               return aname;
+
                        if ((aname->major | aname->minor | aname->build | aname->revision) != 0)
                                mono_trace (G_LOG_LEVEL_WARNING, MONO_TRACE_ASSEMBLY,
                                        "The request to load the assembly %s v%d.%d.%d.%d was remapped to v%d.%d.%d.%d",
@@ -1036,6 +1039,13 @@ mono_assembly_remap_version (MonoAssemblyName *aname, MonoAssemblyName *dest_ana
                        dest_aname->minor = vset->minor;
                        dest_aname->build = vset->build;
                        dest_aname->revision = vset->revision;
+                       if (framework_assemblies[pos].new_assembly_name != NULL) {
+                               dest_aname->name = framework_assemblies[pos].new_assembly_name;
+                               mono_trace (G_LOG_LEVEL_WARNING, MONO_TRACE_ASSEMBLY,
+                                                       "The assembly name %s was remapped to %s",
+                                                       aname->name,
+                                                       dest_aname->name);
+                       }
                        return dest_aname;
                } else if (res < 0) {
                        last = pos - 1;
index 47a02d28d68007a179db132217248ecda08d09ec..68702706b533ca9d878797a0012d0705ea485595 100644 (file)
@@ -553,7 +553,7 @@ ICALL(FILEDI_2, "get_marshal_info", ves_icall_System_Reflection_FieldInfo_get_ma
 ICALL(FILEDI_3, "internal_from_handle_type", ves_icall_System_Reflection_FieldInfo_internal_from_handle_type)
 
 ICALL_TYPE(MEMBERI, "System.Reflection.MemberInfo", MEMBERI_1)
-ICALL(MEMBERI_1, "get_MetadataToken", mono_reflection_get_token)
+ICALL(MEMBERI_1, "get_MetadataToken", ves_icall_reflection_get_token)
 
 ICALL_TYPE(MBASE, "System.Reflection.MethodBase", MBASE_1)
 ICALL(MBASE_1, "GetCurrentMethod", ves_icall_GetCurrentMethod)
@@ -574,7 +574,7 @@ ICALL(MODULE_9, "ResolveMethodToken", ves_icall_System_Reflection_Module_Resolve
 ICALL(MODULE_10, "ResolveSignature", ves_icall_System_Reflection_Module_ResolveSignature)
 ICALL(MODULE_11, "ResolveStringToken", ves_icall_System_Reflection_Module_ResolveStringToken)
 ICALL(MODULE_12, "ResolveTypeToken", ves_icall_System_Reflection_Module_ResolveTypeToken)
-ICALL(MODULE_13, "get_MetadataToken", mono_reflection_get_token)
+ICALL(MODULE_13, "get_MetadataToken", ves_icall_reflection_get_token)
 
 ICALL_TYPE(MCMETH, "System.Reflection.MonoCMethod", MCMETH_1)
 ICALL(MCMETH_1, "GetGenericMethodDefinition_impl", ves_icall_MonoMethod_GetGenericMethodDefinition)
@@ -620,7 +620,7 @@ ICALL(MPROPI_3, "get_default_value", property_info_get_default_value)
 ICALL(MPROPI_2, "get_property_info", ves_icall_MonoPropertyInfo_get_property_info)
 
 ICALL_TYPE(PARAMI, "System.Reflection.ParameterInfo", PARAMI_1)
-ICALL(PARAMI_1, "GetMetadataToken", mono_reflection_get_token)
+ICALL(PARAMI_1, "GetMetadataToken", ves_icall_reflection_get_token)
 ICALL(PARAMI_2, "GetTypeModifiers", ves_icall_ParameterInfo_GetTypeModifiers)
 
 ICALL_TYPE(RTFIELD, "System.Reflection.RtFieldInfo", RTFIELD_1)
@@ -771,7 +771,7 @@ ICALL(RTH_3, "GetAttributes", ves_icall_RuntimeTypeHandle_GetAttributes)
 ICALL(RTH_4, "GetBaseType", ves_icall_RuntimeTypeHandle_GetBaseType)
 ICALL(RTH_5, "GetElementType", ves_icall_RuntimeTypeHandle_GetElementType)
 ICALL(RTH_6, "GetGenericTypeDefinition_impl", ves_icall_RuntimeTypeHandle_GetGenericTypeDefinition_impl)
-ICALL(RTH_7, "GetMetadataToken", ves_icall_RuntimeTypeHandle_GetMetadataToken)
+ICALL(RTH_7, "GetMetadataToken", ves_icall_reflection_get_token)
 ICALL(RTH_8, "GetModule", ves_icall_RuntimeTypeHandle_GetModule)
 ICALL(RTH_9, "HasInstantiation", ves_icall_RuntimeTypeHandle_HasInstantiation)
 ICALL(RTH_10, "IsArray", ves_icall_RuntimeTypeHandle_IsArray)
index ee70870d102a934a85cb544f61aadd01310bd867..77e471bf1d00d4c07bf67b5b8c746fec8cf03524 100644 (file)
@@ -1364,15 +1364,19 @@ type_from_parsed_name (MonoTypeNameParse *info, MonoBoolean ignoreCase, MonoErro
 
        if (assembly) {
                /* When loading from the current assembly, AppDomain.TypeResolve will not be called yet */
-               type = mono_reflection_get_type (assembly->image, info, ignoreCase, &type_resolve);
+               type = mono_reflection_get_type_checked (assembly->image, info, ignoreCase, &type_resolve, error);
+               return_val_if_nok (error, NULL);
        }
 
-       if (!info->assembly.name && !type) /* try mscorlib */
-               type = mono_reflection_get_type (NULL, info, ignoreCase, &type_resolve);
-
+       if (!info->assembly.name && !type) {
+               /* try mscorlib */
+               type = mono_reflection_get_type_checked (NULL, info, ignoreCase, &type_resolve, error);
+               return_val_if_nok (error, NULL);
+       }
        if (assembly && !type && type_resolve) {
                type_resolve = FALSE; /* This will invoke TypeResolve if not done in the first 'if' */
-               type = mono_reflection_get_type (assembly->image, info, ignoreCase, &type_resolve);
+               type = mono_reflection_get_type_checked (assembly->image, info, ignoreCase, &type_resolve, error);
+               return_val_if_nok (error, NULL);
        }
 
        if (!type) 
@@ -2473,9 +2477,12 @@ ves_icall_RuntimeTypeHandle_IsComObject (MonoReflectionType *type)
 }
 
 ICALL_EXPORT guint32
-ves_icall_RuntimeTypeHandle_GetMetadataToken (MonoReflectionType *obj)
+ves_icall_reflection_get_token (MonoObject* obj)
 {
-       return mono_reflection_get_token ((MonoObject*)obj);
+       MonoError error;
+       guint32 result = mono_reflection_get_token_checked (obj, &error);
+       mono_error_set_pending_exception (&error);
+       return result;
 }
 
 ICALL_EXPORT MonoReflectionModule*
@@ -4394,9 +4401,15 @@ ves_icall_System_Reflection_Assembly_InternalGetType (MonoReflectionAssembly *as
        }
 
        if (module != NULL) {
-               if (module->image)
-                       type = mono_reflection_get_type (module->image, &info, ignoreCase, &type_resolve);
-               else
+               if (module->image) {
+                       type = mono_reflection_get_type_checked (module->image, &info, ignoreCase, &type_resolve, &error);
+                       if (!is_ok (&error)) {
+                               g_free (str);
+                               mono_reflection_free_type_info (&info);
+                               mono_error_set_pending_exception (&error);
+                               return NULL;
+                       }
+               } else
                        type = NULL;
        }
        else
@@ -4409,7 +4422,13 @@ ves_icall_System_Reflection_Assembly_InternalGetType (MonoReflectionAssembly *as
                        if (abuilder->modules) {
                                for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
                                        MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
-                                       type = mono_reflection_get_type (&mb->dynamic_image->image, &info, ignoreCase, &type_resolve);
+                                       type = mono_reflection_get_type_checked (&mb->dynamic_image->image, &info, ignoreCase, &type_resolve, &error);
+                                       if (!is_ok (&error)) {
+                                               g_free (str);
+                                               mono_reflection_free_type_info (&info);
+                                               mono_error_set_pending_exception (&error);
+                                               return NULL;
+                                       }
                                        if (type)
                                                break;
                                }
@@ -4418,14 +4437,27 @@ ves_icall_System_Reflection_Assembly_InternalGetType (MonoReflectionAssembly *as
                        if (!type && abuilder->loaded_modules) {
                                for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
                                        MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
-                                       type = mono_reflection_get_type (mod->image, &info, ignoreCase, &type_resolve);
+                                       type = mono_reflection_get_type_checked (mod->image, &info, ignoreCase, &type_resolve, &error);
+                                       if (!is_ok (&error)) {
+                                               g_free (str);
+                                               mono_reflection_free_type_info (&info);
+                                               mono_error_set_pending_exception (&error);
+                                               return NULL;
+                                       }
                                        if (type)
                                                break;
                                }
                        }
                }
-               else
-                       type = mono_reflection_get_type (assembly->assembly->image, &info, ignoreCase, &type_resolve);
+               else {
+                       type = mono_reflection_get_type_checked (assembly->assembly->image, &info, ignoreCase, &type_resolve, &error);
+                       if (!is_ok (&error)) {
+                               g_free (str);
+                               mono_reflection_free_type_info (&info);
+                               mono_error_set_pending_exception (&error);
+                               return NULL;
+                       }
+               }
        g_free (str);
        mono_reflection_free_type_info (&info);
        if (!type) {
@@ -4465,7 +4497,7 @@ ves_icall_System_Reflection_Assembly_InternalGetType (MonoReflectionAssembly *as
 
        /* g_print ("got it\n"); */
        ret = mono_type_get_object_checked (mono_object_domain (assembly), type, &error);
-       mono_error_raise_exception (&error);
+       mono_error_set_pending_exception (&error);
 
        return ret;
 }
@@ -5103,7 +5135,10 @@ ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternalType (MonoMeth
 ICALL_EXPORT MonoReflectionMethodBody*
 ves_icall_System_Reflection_MethodBase_GetMethodBodyInternal (MonoMethod *method)
 {
-       return mono_method_body_get_object (mono_domain_get (), method);
+       MonoError error;
+       MonoReflectionMethodBody *result = mono_method_body_get_object_checked (mono_domain_get (), method, &error);
+       mono_error_set_pending_exception (&error);
+       return result;
 }
 
 ICALL_EXPORT MonoReflectionAssembly*
index fad3fb214f58a00669c613ea9c70afdf469a9a61..af5ba0afdb0b0a6420e1f309712fb928d04cf811 100644 (file)
@@ -8,9 +8,16 @@
 #include <mono/utils/mono-compiler.h>
 #include <mono/utils/mono-error.h>
 
+MonoType*
+mono_reflection_get_type_checked (MonoImage* image, MonoTypeNameParse *info, mono_bool ignorecase, mono_bool *type_resolve, MonoError *error);
+
 MonoType*
 mono_reflection_type_from_name_checked (char *name, MonoImage *image, MonoError *error);
 
+guint32
+mono_reflection_get_token_checked (MonoObject *obj, MonoError *error);
+
+
 MonoObject*
 mono_custom_attrs_get_attr_checked (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass, MonoError *error);
 
@@ -68,4 +75,8 @@ mono_module_get_object_checked (MonoDomain *domain, MonoImage *image, MonoError
 MonoReflectionModule*
 mono_module_file_get_object_checked (MonoDomain *domain, MonoImage *image, int table_index, MonoError *error);
 
+MonoReflectionMethodBody*
+mono_method_body_get_object_checked (MonoDomain *domain, MonoMethod *method, MonoError *error);
+
+
 #endif /* __MONO_METADATA_REFLECTION_INTERNALS_H__ */
index 1d493102f95a40c163e123c14b31cafb4e359547..a3ea522b1cf5e1cccdccde76bbd134070ae6fe9f 100644 (file)
@@ -7772,18 +7772,39 @@ MonoReflectionMethodBody*
 mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
 {
        MonoError error;
+       MonoReflectionMethodBody *result = mono_method_body_get_object_checked (domain, method, &error);
+       mono_error_cleanup (&error); /* FIXME new API that doesn't swallow the error */
+       return result;
+}
+
+/**
+ * mono_method_body_get_object_checked:
+ * @domain: an app domain
+ * @method: a method
+ * @error: set on error
+ *
+ * Return an System.Reflection.MethodBody object representing the
+ * method @method.  On failure, returns NULL and sets @error.
+ */
+MonoReflectionMethodBody*
+mono_method_body_get_object_checked (MonoDomain *domain, MonoMethod *method, MonoError *error)
+{
        MonoReflectionMethodBody *ret;
        MonoMethodHeader *header;
        MonoImage *image;
        MonoReflectionType *rt;
        guint32 method_rva, local_var_sig_token;
-    char *ptr;
+       char *ptr;
        unsigned char format, flags;
        int i;
 
+       mono_error_init (error);
+
        /* for compatibility with .net */
-    if (method_is_dynamic (method))
-        mono_raise_exception (mono_get_exception_invalid_operation (NULL));
+       if (method_is_dynamic (method)) {
+               mono_error_set_exception_instance (error, mono_get_exception_invalid_operation (NULL));
+               return NULL;
+       }
 
        CHECK_OBJECT (MonoReflectionMethodBody *, method, NULL);
 
@@ -7795,8 +7816,8 @@ mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
                return NULL;
 
        image = method->klass->image;
-       header = mono_method_get_header_checked (method, &error);
-       mono_error_raise_exception (&error); /* FIXME don't raise here */
+       header = mono_method_get_header_checked (method, error);
+       return_val_if_nok (error, NULL);
 
        if (!image_is_dynamic (image)) {
                /* Obtain local vars signature token */
@@ -7820,8 +7841,8 @@ mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
        } else
                local_var_sig_token = 0; //FIXME
 
-       ret = (MonoReflectionMethodBody*)mono_object_new_checked (domain, mono_class_get_method_body_class (), &error);
-       mono_error_raise_exception (&error); /* FIXME don't raise here */
+       ret = (MonoReflectionMethodBody*)mono_object_new_checked (domain, mono_class_get_method_body_class (), error);
+       return_val_if_nok (error, NULL);
 
        ret->init_locals = header->init_locals;
        ret->max_stack = header->max_stack;
@@ -7832,11 +7853,11 @@ mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
        /* Locals */
        MONO_OBJECT_SETREF (ret, locals, mono_array_new_cached (domain, mono_class_get_local_variable_info_class (), header->num_locals));
        for (i = 0; i < header->num_locals; ++i) {
-               MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new_checked (domain, mono_class_get_local_variable_info_class (), &error);
-               mono_error_raise_exception (&error); /* FIXME don't raise here */
+               MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new_checked (domain, mono_class_get_local_variable_info_class (), error);
+               return_val_if_nok (error, NULL);
 
-               rt = mono_type_get_object_checked (domain, header->locals [i], &error);
-               mono_error_raise_exception (&error); /* FIXME don't raise here */
+               rt = mono_type_get_object_checked (domain, header->locals [i], error);
+               return_val_if_nok (error, NULL);
 
                MONO_OBJECT_SETREF (info, local_type, rt);
 
@@ -7848,8 +7869,8 @@ mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
        /* Exceptions */
        MONO_OBJECT_SETREF (ret, clauses, mono_array_new_cached (domain, mono_class_get_exception_handling_clause_class (), header->num_clauses));
        for (i = 0; i < header->num_clauses; ++i) {
-               MonoReflectionExceptionHandlingClause *info = (MonoReflectionExceptionHandlingClause*)mono_object_new_checked (domain, mono_class_get_exception_handling_clause_class (), &error);
-               mono_error_raise_exception (&error); /* FIXME don't raise here */
+               MonoReflectionExceptionHandlingClause *info = (MonoReflectionExceptionHandlingClause*)mono_object_new_checked (domain, mono_class_get_exception_handling_clause_class (), error);
+               return_val_if_nok (error, NULL);
                MonoExceptionClause *clause = &header->clauses [i];
 
                info->flags = clause->flags;
@@ -7860,8 +7881,8 @@ mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
                if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER)
                        info->filter_offset = clause->data.filter_offset;
                else if (clause->data.catch_class) {
-                       rt = mono_type_get_object_checked (mono_domain_get (), &clause->data.catch_class->byval_arg, &error);
-                       mono_error_raise_exception (&error); /* FIXME don't raise here */
+                       rt = mono_type_get_object_checked (mono_domain_get (), &clause->data.catch_class->byval_arg, error);
+                       return_val_if_nok (error, NULL);
 
                        MONO_OBJECT_SETREF (info, catch_type, rt);
                }
@@ -8589,11 +8610,29 @@ mono_reflection_get_type_internal (MonoImage *rootimage, MonoImage* image, MonoT
 MonoType*
 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve) {
        MonoError error;
-       MonoType *result = mono_reflection_get_type_with_rootimage(image, image, info, ignorecase, type_resolve, &error);
-       mono_error_raise_exception (&error); /* FIXME don't raise here */
+       MonoType *result = mono_reflection_get_type_with_rootimage (image, image, info, ignorecase, type_resolve, &error);
+       mono_error_cleanup (&error);
        return result;
 }
 
+/**
+ * mono_reflection_get_type_checked:
+ * @image: a metadata context
+ * @info: type description structure
+ * @ignorecase: flag for case-insensitive string compares
+ * @type_resolve: whenever type resolve was already tried
+ * @error: set on error.
+ *
+ * Build a MonoType from the type description in @info. On failure returns NULL and sets @error.
+ *
+ */
+MonoType*
+mono_reflection_get_type_checked (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve, MonoError *error) {
+       mono_error_init (error);
+       return mono_reflection_get_type_with_rootimage (image, image, info, ignorecase, type_resolve, error);
+}
+
+
 static MonoType*
 mono_reflection_get_type_internal_dynamic (MonoImage *rootimage, MonoAssembly *assembly, MonoTypeNameParse *info, gboolean ignorecase, MonoError *error)
 {
@@ -8779,9 +8818,27 @@ guint32
 mono_reflection_get_token (MonoObject *obj)
 {
        MonoError error;
+       guint32 result = mono_reflection_get_token_checked (obj, &error);
+       mono_error_assert_ok (&error);
+       return result;
+}
+
+/**
+ * mono_reflection_get_token_checked:
+ * @obj: the object
+ * @error: set on error
+ *
+ *   Return the metadata token of @obj which should be an object
+ * representing a metadata element.  On failure sets @error.
+ */
+guint32
+mono_reflection_get_token_checked (MonoObject *obj, MonoError *error)
+{
        MonoClass *klass;
        guint32 token = 0;
 
+       mono_error_init (error);
+
        klass = obj->vtable->klass;
 
        if (strcmp (klass->name, "MethodBuilder") == 0) {
@@ -8800,11 +8857,13 @@ mono_reflection_get_token (MonoObject *obj)
                MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
                token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
        } else if (strcmp (klass->name, "MonoType") == 0) {
-               MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj, &error);
-               mono_error_raise_exception (&error); /* FIXME don't raise here */
+               MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj, error);
+               return_val_if_nok (error, 0);
                MonoClass *mc = mono_class_from_mono_type (type);
-               if (!mono_class_init (mc))
-                       mono_raise_exception (mono_class_get_exception_for_failure (mc));
+               if (!mono_class_init (mc)) {
+                       mono_error_set_exception_instance (error, mono_class_get_exception_for_failure (mc));
+                       return 0;
+               }
 
                token = mc->type_token;
        } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
@@ -8830,7 +8889,7 @@ mono_reflection_get_token (MonoObject *obj)
 
                                g_assert (field_index >= 0 && field_index < dgclass->count_fields);
                                obj = dgclass->field_objects [field_index];
-                               return mono_reflection_get_token (obj);
+                               return mono_reflection_get_token_checked (obj, error);
                        }
                }
                token = mono_class_get_field_token (f->field);
@@ -8855,10 +8914,9 @@ mono_reflection_get_token (MonoObject *obj)
        } else if (strcmp (klass->name, "Assembly") == 0 || strcmp (klass->name, "MonoAssembly") == 0) {
                token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
        } else {
-               gchar *msg = g_strdup_printf ("MetadataToken is not supported for type '%s.%s'", klass->name_space, klass->name);
-               MonoException *ex = mono_get_exception_not_implemented (msg);
-               g_free (msg);
-               mono_raise_exception (ex);
+               mono_error_set_generic_error (error, "System", "NotImplementedException",
+                                             "MetadataToken is not supported for type '%s.%s'", klass->name_space, klass->name);
+               return 0;
        }
 
        return token;
index 7c03e62b597e7b1de1d77bdf97fb91d810f62466..164cc4ae87cfe996d18bbeabdea99255c6ca867c 100644 (file)
@@ -42,10 +42,12 @@ typedef enum {
 } MonoResolveTokenError;
 
 MONO_API int           mono_reflection_parse_type (char *name, MonoTypeNameParse *info);
+MONO_RT_EXTERNAL_ONLY
 MONO_API MonoType*     mono_reflection_get_type   (MonoImage* image, MonoTypeNameParse *info, mono_bool ignorecase, mono_bool *type_resolve);
 MONO_API void          mono_reflection_free_type_info (MonoTypeNameParse *info);
 MONO_RT_EXTERNAL_ONLY
 MONO_API MonoType*     mono_reflection_type_from_name (char *name, MonoImage *image);
+MONO_RT_EXTERNAL_ONLY
 MONO_API uint32_t      mono_reflection_get_token (MonoObject *obj);
 
 MONO_RT_EXTERNAL_ONLY
@@ -66,6 +68,7 @@ MONO_API MonoReflectionEvent*    mono_event_get_object    (MonoDomain *domain, M
 /* note: this one is slightly different: we keep the whole array of params in the cache */
 MONO_RT_EXTERNAL_ONLY
 MONO_API MonoArray* mono_param_get_objects  (MonoDomain *domain, MonoMethod *method);
+MONO_RT_EXTERNAL_ONLY
 MONO_API MonoReflectionMethodBody* mono_method_body_get_object (MonoDomain *domain, MonoMethod *method);
 
 MONO_API MonoObject *mono_get_dbnull_object (MonoDomain *domain);
index fe54562f57a6883a6261768783355cebc7234807..93756b108b33cb4402a0ca57601aa8b0bb9a25cc 100644 (file)
@@ -245,36 +245,36 @@ amodule_unlock (MonoAotModule *amodule)
  * load_image:
  *
  *   Load one of the images referenced by AMODULE. Returns NULL if the image is not
- * found, and sets the loader error if SET_ERROR is TRUE.
+ * found, and sets @error for what happened
  */
 static MonoImage *
-load_image (MonoAotModule *amodule, int index, gboolean set_error)
+load_image (MonoAotModule *amodule, int index, MonoError *error)
 {
        MonoAssembly *assembly;
        MonoImageOpenStatus status;
 
        g_assert (index < amodule->image_table_len);
 
+       mono_error_init (error);
+
        if (amodule->image_table [index])
                return amodule->image_table [index];
-       if (amodule->out_of_date)
+       if (amodule->out_of_date) {
+               mono_error_set_bad_image_name (error, amodule->aot_name, "Image out of date");
                return NULL;
+       }
 
        assembly = mono_assembly_load (&amodule->image_names [index], amodule->assembly->basedir, &status);
        if (!assembly) {
                mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_AOT, "AOT: module %s is unusable because dependency %s is not found.\n", amodule->aot_name, amodule->image_names [index].name);
+               mono_error_set_bad_image_name (error, amodule->aot_name, "module is unusable because dependency %s is not found (error %d).\n", amodule->image_names [index].name, status);
                amodule->out_of_date = TRUE;
-
-               if (set_error) {
-                       char *full_name = mono_stringify_assembly_name (&amodule->image_names [index]);
-                       mono_loader_set_error_assembly_load (full_name, FALSE);
-                       g_free (full_name);
-               }
                return NULL;
        }
 
        if (strcmp (assembly->image->guid, amodule->image_guids [index])) {
                mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_AOT, "AOT: module %s is unusable (GUID of dependent assembly %s doesn't match (expected '%s', got '%s').\n", amodule->aot_name, amodule->image_names [index].name, amodule->image_guids [index], assembly->image->guid);
+               mono_error_set_bad_image_name (error, amodule->aot_name, "module is unusable (GUID of dependent assembly %s doesn't match (expected '%s', got '%s').\n", amodule->image_names [index].name, amodule->image_guids [index], assembly->image->guid);
                amodule->out_of_date = TRUE;
                return NULL;
        }
@@ -356,27 +356,28 @@ mono_aot_get_offset (guint32 *table, int index)
 }
 
 static MonoMethod*
-decode_resolve_method_ref (MonoAotModule *module, guint8 *buf, guint8 **endbuf);
+decode_resolve_method_ref (MonoAotModule *module, guint8 *buf, guint8 **endbuf, MonoError *error);
 
 static MonoClass*
-decode_klass_ref (MonoAotModule *module, guint8 *buf, guint8 **endbuf);
+decode_klass_ref (MonoAotModule *module, guint8 *buf, guint8 **endbuf, MonoError *error);
 
 static MonoType*
-decode_type (MonoAotModule *module, guint8 *buf, guint8 **endbuf);
+decode_type (MonoAotModule *module, guint8 *buf, guint8 **endbuf, MonoError *error);
 
 static MonoGenericInst*
-decode_generic_inst (MonoAotModule *module, guint8 *buf, guint8 **endbuf)
+decode_generic_inst (MonoAotModule *module, guint8 *buf, guint8 **endbuf, MonoError *error)
 {
        int type_argc, i;
        MonoType **type_argv;
        MonoGenericInst *inst;
        guint8 *p = buf;
 
+       mono_error_init (error);
        type_argc = decode_value (p, &p);
        type_argv = g_new0 (MonoType*, type_argc);
 
        for (i = 0; i < type_argc; ++i) {
-               MonoClass *pclass = decode_klass_ref (module, p, &p);
+               MonoClass *pclass = decode_klass_ref (module, p, &p, error);
                if (!pclass) {
                        g_free (type_argv);
                        return NULL;
@@ -393,17 +394,18 @@ decode_generic_inst (MonoAotModule *module, guint8 *buf, guint8 **endbuf)
 }
 
 static gboolean
-decode_generic_context (MonoAotModule *module, MonoGenericContext *ctx, guint8 *buf, guint8 **endbuf)
+decode_generic_context (MonoAotModule *module, MonoGenericContext *ctx, guint8 *buf, guint8 **endbuf, MonoError *error)
 {
        guint8 *p = buf;
        guint8 *p2;
        int argc;
+       mono_error_init (error);
 
        p2 = p;
        argc = decode_value (p, &p);
        if (argc) {
                p = p2;
-               ctx->class_inst = decode_generic_inst (module, p, &p);
+               ctx->class_inst = decode_generic_inst (module, p, &p, error);
                if (!ctx->class_inst)
                        return FALSE;
        }
@@ -411,7 +413,7 @@ decode_generic_context (MonoAotModule *module, MonoGenericContext *ctx, guint8 *
        argc = decode_value (p, &p);
        if (argc) {
                p = p2;
-               ctx->method_inst = decode_generic_inst (module, p, &p);
+               ctx->method_inst = decode_generic_inst (module, p, &p, error);
                if (!ctx->method_inst)
                        return FALSE;
        }
@@ -421,63 +423,63 @@ decode_generic_context (MonoAotModule *module, MonoGenericContext *ctx, guint8 *
 }
 
 static MonoClass*
-decode_klass_ref (MonoAotModule *module, guint8 *buf, guint8 **endbuf)
+decode_klass_ref (MonoAotModule *module, guint8 *buf, guint8 **endbuf, MonoError *error)
 {
-       MonoError error;
        MonoImage *image;
        MonoClass *klass = NULL, *eklass;
        guint32 token, rank, idx;
        guint8 *p = buf;
        int reftype;
 
+       mono_error_init (error);
        reftype = decode_value (p, &p);
        if (reftype == 0) {
                *endbuf = p;
+               mono_error_set_bad_image_name (error, module->aot_name, "Decoding a null class ref");
                return NULL;
        }
 
        switch (reftype) {
        case MONO_AOT_TYPEREF_TYPEDEF_INDEX:
                idx = decode_value (p, &p);
-               image = load_image (module, 0, TRUE);
+               image = load_image (module, 0, error);
                if (!image)
                        return NULL;
-               klass = mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF + idx, &error);
-               g_assert (mono_error_ok (&error));
+               klass = mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF + idx, error);
                break;
        case MONO_AOT_TYPEREF_TYPEDEF_INDEX_IMAGE:
                idx = decode_value (p, &p);
-               image = load_image (module, decode_value (p, &p), TRUE);
+               image = load_image (module, decode_value (p, &p), error);
                if (!image)
                        return NULL;
-               klass = mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF + idx, &error);
-               g_assert (mono_error_ok (&error));
+               klass = mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF + idx, error);
                break;
        case MONO_AOT_TYPEREF_TYPESPEC_TOKEN:
                token = decode_value (p, &p);
                image = module->assembly->image;
-               if (!image)
+               if (!image) {
+                       mono_error_set_bad_image_name (error, module->aot_name, "No image associated with the aot module");
                        return NULL;
-               klass = mono_class_get_checked (image, token, &error);
-               g_assert (mono_error_ok (&error));
+               }
+               klass = mono_class_get_checked (image, token, error);
                break;
        case MONO_AOT_TYPEREF_GINST: {
-               MonoError error;
                MonoClass *gclass;
                MonoGenericContext ctx;
                MonoType *type;
 
-               gclass = decode_klass_ref (module, p, &p);
+               gclass = decode_klass_ref (module, p, &p, error);
                if (!gclass)
                        return NULL;
                g_assert (gclass->generic_container);
 
                memset (&ctx, 0, sizeof (ctx));
-               ctx.class_inst = decode_generic_inst (module, p, &p);
+               ctx.class_inst = decode_generic_inst (module, p, &p, error);
                if (!ctx.class_inst)
                        return NULL;
-               type = mono_class_inflate_generic_type_checked (&gclass->byval_arg, &ctx, &error);
-               mono_error_assert_ok (&error); /* FIXME don't swallow the error */
+               type = mono_class_inflate_generic_type_checked (&gclass->byval_arg, &ctx, error);
+               if (!type)
+                       return NULL;
                klass = mono_class_from_mono_type (type);
                mono_metadata_free_type (type);
                break;
@@ -491,11 +493,11 @@ decode_klass_ref (MonoAotModule *module, guint8 *buf, guint8 **endbuf)
                        MonoClass *par_klass;
                        MonoType *gshared_constraint;
 
-                       gshared_constraint = decode_type (module, p, &p);
+                       gshared_constraint = decode_type (module, p, &p, error);
                        if (!gshared_constraint)
                                return NULL;
 
-                       par_klass = decode_klass_ref (module, p, &p);
+                       par_klass = decode_klass_ref (module, p, &p, error);
                        if (!par_klass)
                                return NULL;
 
@@ -512,7 +514,7 @@ decode_klass_ref (MonoAotModule *module, guint8 *buf, guint8 **endbuf)
                                if (is_method) {
                                        MonoMethod *method_def;
                                        g_assert (type == MONO_TYPE_MVAR);
-                                       method_def = decode_resolve_method_ref (module, p, &p);
+                                       method_def = decode_resolve_method_ref (module, p, &p, error);
                                        if (!method_def)
                                                return NULL;
 
@@ -520,7 +522,7 @@ decode_klass_ref (MonoAotModule *module, guint8 *buf, guint8 **endbuf)
                                } else {
                                        MonoClass *class_def;
                                        g_assert (type == MONO_TYPE_VAR);
-                                       class_def = decode_klass_ref (module, p, &p);
+                                       class_def = decode_klass_ref (module, p, &p, error);
                                        if (!class_def)
                                                return NULL;
 
@@ -554,13 +556,15 @@ decode_klass_ref (MonoAotModule *module, guint8 *buf, guint8 **endbuf)
        case MONO_AOT_TYPEREF_ARRAY:
                /* Array */
                rank = decode_value (p, &p);
-               eklass = decode_klass_ref (module, p, &p);
+               eklass = decode_klass_ref (module, p, &p, error);
+               if (!eklass)
+                       return NULL;
                klass = mono_array_class_get (eklass, rank);
                break;
        case MONO_AOT_TYPEREF_PTR: {
                MonoType *t;
 
-               t = decode_type (module, p, &p);
+               t = decode_type (module, p, &p, error);
                if (!t)
                        return NULL;
                klass = mono_class_from_mono_type (t);
@@ -572,13 +576,13 @@ decode_klass_ref (MonoAotModule *module, guint8 *buf, guint8 **endbuf)
                guint8 *p2;
 
                p2 = module->blob + offset;
-               klass = decode_klass_ref (module, p2, &p2);
+               klass = decode_klass_ref (module, p2, &p2, error);
                break;
        }
        default:
-               g_assert_not_reached ();
+               mono_error_set_bad_image_name (error, module->aot_name, "Invalid klass reftype %d", reftype);
        }
-       g_assert (klass);
+       //g_assert (klass);
        //printf ("BLA: %s\n", mono_type_full_name (&klass->byval_arg));
        *endbuf = p;
        return klass;
@@ -587,12 +591,15 @@ decode_klass_ref (MonoAotModule *module, guint8 *buf, guint8 **endbuf)
 static MonoClassField*
 decode_field_info (MonoAotModule *module, guint8 *buf, guint8 **endbuf)
 {
-       MonoClass *klass = decode_klass_ref (module, buf, &buf);
+       MonoError error;
+       MonoClass *klass = decode_klass_ref (module, buf, &buf, &error);
        guint32 token;
        guint8 *p = buf;
 
-       if (!klass)
+       if (!klass) {
+               mono_error_cleanup (&error); /* FIXME don't swallow the error */
                return NULL;
+       }
 
        token = MONO_TOKEN_FIELD_DEF + decode_value (p, &p);
 
@@ -606,12 +613,13 @@ decode_field_info (MonoAotModule *module, guint8 *buf, guint8 **endbuf)
  * memory.
  */
 static MonoType*
-decode_type (MonoAotModule *module, guint8 *buf, guint8 **endbuf)
+decode_type (MonoAotModule *module, guint8 *buf, guint8 **endbuf, MonoError *error)
 {
        guint8 *p = buf;
        MonoType *t;
 
        t = (MonoType *)g_malloc0 (sizeof (MonoType));
+       mono_error_init (error);
 
        while (TRUE) {
                if (*p == MONO_TYPE_PINNED) {
@@ -650,36 +658,39 @@ decode_type (MonoAotModule *module, guint8 *buf, guint8 **endbuf)
                break;
        case MONO_TYPE_VALUETYPE:
        case MONO_TYPE_CLASS:
-               t->data.klass = decode_klass_ref (module, p, &p);
+               t->data.klass = decode_klass_ref (module, p, &p, error);
+               if (!t->data.klass)
+                       goto fail;
                break;
        case MONO_TYPE_SZARRAY:
-               t->data.klass = decode_klass_ref (module, p, &p);
+               t->data.klass = decode_klass_ref (module, p, &p, error);
 
                if (!t->data.klass)
-                       return NULL;
+                       goto fail;
                break;
        case MONO_TYPE_PTR:
-               t->data.type = decode_type (module, p, &p);
+               t->data.type = decode_type (module, p, &p, error);
+               if (!t->data.type)
+                       goto fail;
                break;
        case MONO_TYPE_GENERICINST: {
-               MonoError error;
                MonoClass *gclass;
                MonoGenericContext ctx;
                MonoType *type;
                MonoClass *klass;
 
-               gclass = decode_klass_ref (module, p, &p);
+               gclass = decode_klass_ref (module, p, &p, error);
                if (!gclass)
-                       return NULL;
+                       goto fail;
                g_assert (gclass->generic_container);
 
                memset (&ctx, 0, sizeof (ctx));
-               ctx.class_inst = decode_generic_inst (module, p, &p);
+               ctx.class_inst = decode_generic_inst (module, p, &p, error);
                if (!ctx.class_inst)
-                       return NULL;
-               type = mono_class_inflate_generic_type_checked (&gclass->byval_arg, &ctx, &error);
-               mono_error_assert_ok (&error); /* FIXME don't swallow the error */
-
+                       goto fail;
+               type = mono_class_inflate_generic_type_checked (&gclass->byval_arg, &ctx, error);
+               if (!type)
+                       goto fail;
                klass = mono_class_from_mono_type (type);
                t->data.generic_class = klass->generic_class;
                break;
@@ -690,9 +701,9 @@ decode_type (MonoAotModule *module, guint8 *buf, guint8 **endbuf)
 
                // FIXME: memory management
                array = g_new0 (MonoArrayType, 1);
-               array->eklass = decode_klass_ref (module, p, &p);
+               array->eklass = decode_klass_ref (module, p, &p, error);
                if (!array->eklass)
-                       return NULL;
+                       goto fail;
                array->rank = decode_value (p, &p);
                array->numsizes = decode_value (p, &p);
 
@@ -711,19 +722,23 @@ decode_type (MonoAotModule *module, guint8 *buf, guint8 **endbuf)
        }
        case MONO_TYPE_VAR:
        case MONO_TYPE_MVAR: {
-               MonoClass *klass = decode_klass_ref (module, p, &p);
+               MonoClass *klass = decode_klass_ref (module, p, &p, error);
                if (!klass)
-                       return NULL;
+                       goto fail;
                t->data.generic_param = klass->byval_arg.data.generic_param;
                break;
        }
        default:
-               g_assert_not_reached ();
+               mono_error_set_bad_image_name (error, module->aot_name, "Invalid encoded type %d", t->type);
+               goto fail;
        }
 
        *endbuf = p;
 
        return t;
+fail:
+       g_free (t);
+       return NULL;
 }
 
 // FIXME: Error handling, memory management
@@ -731,6 +746,7 @@ decode_type (MonoAotModule *module, guint8 *buf, guint8 **endbuf)
 static MonoMethodSignature*
 decode_signature_with_target (MonoAotModule *module, MonoMethodSignature *target, guint8 *buf, guint8 **endbuf)
 {
+       MonoError error;
        MonoMethodSignature *sig;
        guint32 flags;
        int i, gen_param_count = 0, param_count, call_conv;
@@ -756,14 +772,18 @@ decode_signature_with_target (MonoAotModule *module, MonoMethodSignature *target
        sig->explicit_this = explicit_this;
        sig->call_convention = call_conv;
        sig->generic_param_count = gen_param_count;
-       sig->ret = decode_type (module, p, &p);
+       sig->ret = decode_type (module, p, &p, &error);
+       if (!sig->ret)
+               goto fail;
        for (i = 0; i < param_count; ++i) {
                if (*p == MONO_TYPE_SENTINEL) {
                        g_assert (sig->call_convention == MONO_CALL_VARARG);
                        sig->sentinelpos = i;
                        p ++;
                }
-               sig->params [i] = decode_type (module, p, &p);
+               sig->params [i] = decode_type (module, p, &p, &error);
+               if (!sig->params [i])
+                       goto fail;
        }
 
        if (sig->call_convention == MONO_CALL_VARARG && sig->sentinelpos == -1)
@@ -772,6 +792,10 @@ decode_signature_with_target (MonoAotModule *module, MonoMethodSignature *target
        *endbuf = p;
 
        return sig;
+fail:
+       mono_error_cleanup (&error); /* FIXME don't swallow the error */
+       g_free (sig);
+       return NULL;
 }
 
 static MonoMethodSignature*
@@ -815,15 +839,18 @@ typedef struct {
  * that the method reference matches a given method. This is normally not a problem
  * as these wrappers only occur in the extra_methods table, where we already have
  * a method we want to lookup.
+ *
+ * If there was a decoding error, we return FALSE and set @error
  */
 static gboolean
-decode_method_ref_with_target (MonoAotModule *module, MethodRef *ref, MonoMethod *target, guint8 *buf, guint8 **endbuf)
+decode_method_ref_with_target (MonoAotModule *module, MethodRef *ref, MonoMethod *target, guint8 *buf, guint8 **endbuf, MonoError *error)
 {
        guint32 image_index, value;
        MonoImage *image = NULL;
        guint8 *p = buf;
 
        memset (ref, 0, sizeof (MethodRef));
+       mono_error_init (error);
 
        value = decode_value (p, &p);
        image_index = value >> 24;
@@ -835,8 +862,9 @@ decode_method_ref_with_target (MonoAotModule *module, MethodRef *ref, MonoMethod
        }
 
        if (image_index < MONO_AOT_METHODREF_MIN || image_index == MONO_AOT_METHODREF_METHODSPEC || image_index == MONO_AOT_METHODREF_GINST) {
-               if (target && target->wrapper_type)
+               if (target && target->wrapper_type) {
                        return FALSE;
+               }
        }
 
        if (image_index == MONO_AOT_METHODREF_WRAPPER) {
@@ -854,8 +882,7 @@ decode_method_ref_with_target (MonoAotModule *module, MethodRef *ref, MonoMethod
                switch (wrapper_type) {
 #ifndef DISABLE_REMOTING
                case MONO_WRAPPER_REMOTING_INVOKE_WITH_CHECK: {
-                       MonoMethod *m = decode_resolve_method_ref (module, p, &p);
-
+                       MonoMethod *m = decode_resolve_method_ref (module, p, &p, error);
                        if (!m)
                                return FALSE;
                        mono_class_init (m->klass);
@@ -866,7 +893,7 @@ decode_method_ref_with_target (MonoAotModule *module, MethodRef *ref, MonoMethod
                        break;
                }
                case MONO_WRAPPER_PROXY_ISINST: {
-                       MonoClass *klass = decode_klass_ref (module, p, &p);
+                       MonoClass *klass = decode_klass_ref (module, p, &p, error);
                        if (!klass)
                                return FALSE;
                        ref->method = mono_marshal_get_proxy_cancast (klass);
@@ -876,7 +903,7 @@ decode_method_ref_with_target (MonoAotModule *module, MethodRef *ref, MonoMethod
                case MONO_WRAPPER_LDFLDA:
                case MONO_WRAPPER_STFLD:
                case MONO_WRAPPER_ISINST: {
-                       MonoClass *klass = decode_klass_ref (module, p, &p);
+                       MonoClass *klass = decode_klass_ref (module, p, &p, error);
                        if (!klass)
                                return FALSE;
                        if (wrapper_type == MONO_WRAPPER_LDFLD)
@@ -887,8 +914,10 @@ decode_method_ref_with_target (MonoAotModule *module, MethodRef *ref, MonoMethod
                                ref->method = mono_marshal_get_stfld_wrapper (&klass->byval_arg);
                        else if (wrapper_type == MONO_WRAPPER_ISINST)
                                ref->method = mono_marshal_get_isinst (klass);
-                       else
-                               g_assert_not_reached ();
+                       else {
+                               mono_error_set_bad_image_name (error, module->aot_name, "Unknown AOT wrapper type %d", wrapper_type);
+                               return FALSE;
+                       }
                        break;
                }
                case MONO_WRAPPER_LDFLD_REMOTE:
@@ -902,8 +931,10 @@ decode_method_ref_with_target (MonoAotModule *module, MethodRef *ref, MonoMethod
                        int atype = decode_value (p, &p);
 
                        ref->method = mono_gc_get_managed_allocator_by_type (atype, !!(mono_profiler_get_events () & MONO_PROFILE_ALLOCATIONS));
-                       if (!ref->method)
-                               g_error ("Error: No managed allocator, but we need one for AOT.\nAre you using non-standard GC options?\n");
+                       if (!ref->method) {
+                               mono_error_set_bad_image_name (error, module->aot_name, "Error: No managed allocator, but we need one for AOT.\nAre you using non-standard GC options?\n");
+                               return FALSE;
+                       }
                        break;
                }
                case MONO_WRAPPER_WRITE_BARRIER: {
@@ -935,13 +966,13 @@ decode_method_ref_with_target (MonoAotModule *module, MethodRef *ref, MonoMethod
                                        return FALSE;
                                }
                        } else {
-                               g_assert_not_reached ();
+                               mono_error_set_bad_image_name (error, module->aot_name, "Invalid STELEMREF subtype %d", subtype);
+                               return FALSE;
                        }
                        break;
                }
                case MONO_WRAPPER_SYNCHRONIZED: {
-                       MonoMethod *m = decode_resolve_method_ref (module, p, &p);
-
+                       MonoMethod *m = decode_resolve_method_ref (module, p, &p, error);
                        if (!m)
                                return FALSE;
                        ref->method = mono_marshal_get_synchronized_wrapper (m);
@@ -951,8 +982,7 @@ decode_method_ref_with_target (MonoAotModule *module, MethodRef *ref, MonoMethod
                        int subtype = decode_value (p, &p);
 
                        if (subtype == WRAPPER_SUBTYPE_PTR_TO_STRUCTURE || subtype == WRAPPER_SUBTYPE_STRUCTURE_TO_PTR) {
-                               MonoClass *klass = decode_klass_ref (module, p, &p);
-                               
+                               MonoClass *klass = decode_klass_ref (module, p, &p, error);
                                if (!klass)
                                        return FALSE;
 
@@ -971,14 +1001,12 @@ decode_method_ref_with_target (MonoAotModule *module, MethodRef *ref, MonoMethod
                                        ref->method = mono_marshal_get_struct_to_ptr (klass);
                                }
                        } else if (subtype == WRAPPER_SUBTYPE_SYNCHRONIZED_INNER) {
-                               MonoMethod *m = decode_resolve_method_ref (module, p, &p);
-
+                               MonoMethod *m = decode_resolve_method_ref (module, p, &p, error);
                                if (!m)
                                        return FALSE;
                                ref->method = mono_marshal_get_synchronized_inner_wrapper (m);
                        } else if (subtype == WRAPPER_SUBTYPE_ARRAY_ACCESSOR) {
-                               MonoMethod *m = decode_resolve_method_ref (module, p, &p);
-
+                               MonoMethod *m = decode_resolve_method_ref (module, p, &p, error);
                                if (!m)
                                        return FALSE;
                                ref->method = mono_marshal_get_array_accessor_wrapper (m);
@@ -997,7 +1025,8 @@ decode_method_ref_with_target (MonoAotModule *module, MethodRef *ref, MonoMethod
                                        return FALSE;
                                ref->method = mini_get_gsharedvt_out_sig_wrapper (sig);
                        } else {
-                               g_assert_not_reached ();
+                               mono_error_set_bad_image_name (error, module->aot_name, "Invalid UNKNOWN wrapper subtype %d", subtype);
+                               return FALSE;
                        }
                        break;
                }
@@ -1012,7 +1041,7 @@ decode_method_ref_with_target (MonoAotModule *module, MethodRef *ref, MonoMethod
                        } else if (subtype == WRAPPER_SUBTYPE_STRING_CTOR) {
                                MonoMethod *m;
 
-                               m = decode_resolve_method_ref (module, p, &p);
+                               m = decode_resolve_method_ref (module, p, &p, error);
                                if (!m)
                                        return FALSE;
 
@@ -1042,8 +1071,7 @@ decode_method_ref_with_target (MonoAotModule *module, MethodRef *ref, MonoMethod
                                        return FALSE;
                                ref->method = target;
                        } else {
-                               m = decode_resolve_method_ref (module, p, &p);
-
+                               m = decode_resolve_method_ref (module, p, &p, error);
                                if (!m)
                                        return FALSE;
 
@@ -1064,8 +1092,10 @@ decode_method_ref_with_target (MonoAotModule *module, MethodRef *ref, MonoMethod
                                ref->method = mono_marshal_get_castclass_with_cache ();
                        else if (subtype == WRAPPER_SUBTYPE_ISINST_WITH_CACHE)
                                ref->method = mono_marshal_get_isinst_with_cache ();
-                       else
-                               g_assert_not_reached ();
+                       else {
+                               mono_error_set_bad_image_name (error, module->aot_name, "Invalid CASTCLASS wrapper subtype %d", subtype);
+                               return FALSE;
+                       }
                        break;
                }
                case MONO_WRAPPER_RUNTIME_INVOKE: {
@@ -1080,15 +1110,13 @@ decode_method_ref_with_target (MonoAotModule *module, MethodRef *ref, MonoMethod
                                ref->method = target;
                        } else if (subtype == WRAPPER_SUBTYPE_RUNTIME_INVOKE_DIRECT) {
                                /* Direct wrapper */
-                               MonoMethod *m = decode_resolve_method_ref (module, p, &p);
-
+                               MonoMethod *m = decode_resolve_method_ref (module, p, &p, error);
                                if (!m)
                                        return FALSE;
                                ref->method = mono_marshal_get_runtime_invoke (m, FALSE);
                        } else if (subtype == WRAPPER_SUBTYPE_RUNTIME_INVOKE_VIRTUAL) {
                                /* Virtual direct wrapper */
-                               MonoMethod *m = decode_resolve_method_ref (module, p, &p);
-
+                               MonoMethod *m = decode_resolve_method_ref (module, p, &p, error);
                                if (!m)
                                        return FALSE;
                                ref->method = mono_marshal_get_runtime_invoke (m, TRUE);
@@ -1119,7 +1147,7 @@ decode_method_ref_with_target (MonoAotModule *module, MethodRef *ref, MonoMethod
                                MonoClass *klass;
                                MonoMethod *invoke, *wrapper;
 
-                               klass = decode_klass_ref (module, p, &p);
+                               klass = decode_klass_ref (module, p, &p, error);
                                if (!klass)
                                        return FALSE;
 
@@ -1181,10 +1209,10 @@ decode_method_ref_with_target (MonoAotModule *module, MethodRef *ref, MonoMethod
                        MonoMethod *m;
                        MonoClass *klass;
 
-                       m = decode_resolve_method_ref (module, p, &p);
+                       m = decode_resolve_method_ref (module, p, &p, error);
                        if (!m)
                                return FALSE;
-                       klass = decode_klass_ref (module, p, &p);
+                       klass = decode_klass_ref (module, p, &p, error);
                        if (!klass)
                                return FALSE;
                        ref->method = mono_marshal_get_managed_wrapper (m, klass, 0);
@@ -1197,11 +1225,10 @@ decode_method_ref_with_target (MonoAotModule *module, MethodRef *ref, MonoMethod
                image_index = decode_value (p, &p);
                ref->token = decode_value (p, &p);
 
-               image = load_image (module, image_index, TRUE);
+               image = load_image (module, image_index, error);
                if (!image)
                        return FALSE;
        } else if (image_index == MONO_AOT_METHODREF_GINST) {
-               MonoError error;
                MonoClass *klass;
                MonoGenericContext ctx;
 
@@ -1209,7 +1236,7 @@ decode_method_ref_with_target (MonoAotModule *module, MethodRef *ref, MonoMethod
                 * These methods do not have a token which resolves them, so we 
                 * resolve them immediately.
                 */
-               klass = decode_klass_ref (module, p, &p);
+               klass = decode_klass_ref (module, p, &p, error);
                if (!klass)
                        return FALSE;
 
@@ -1219,15 +1246,14 @@ decode_method_ref_with_target (MonoAotModule *module, MethodRef *ref, MonoMethod
                image_index = decode_value (p, &p);
                ref->token = decode_value (p, &p);
 
-               image = load_image (module, image_index, TRUE);
+               image = load_image (module, image_index, error);
                if (!image)
                        return FALSE;
 
-               ref->method = mono_get_method_checked (image, ref->token, NULL, NULL, &error);
-               if (!ref->method) {
-                       mono_error_cleanup (&error); /* FIXME don't swallow the error */
+               ref->method = mono_get_method_checked (image, ref->token, NULL, NULL, error);
+               if (!ref->method)
                        return FALSE;
-               }
+
 
                memset (&ctx, 0, sizeof (ctx));
 
@@ -1235,25 +1261,25 @@ decode_method_ref_with_target (MonoAotModule *module, MethodRef *ref, MonoMethod
                        ctx.class_inst = klass->generic_class->context.class_inst;
                        ctx.method_inst = NULL;
  
-                       ref->method = mono_class_inflate_generic_method_full_checked (ref->method, klass, &ctx, &error);
+                       ref->method = mono_class_inflate_generic_method_full_checked (ref->method, klass, &ctx, error);
                        if (!ref->method)
-                               g_error ("AOT runtime could not load method due to %s", mono_error_get_message (&error)); /* FIXME don't swallow the error */
+                               return FALSE;
                }                       
 
                memset (&ctx, 0, sizeof (ctx));
 
-               if (!decode_generic_context (module, &ctx, p, &p))
+               if (!decode_generic_context (module, &ctx, p, &p, error))
                        return FALSE;
 
-               ref->method = mono_class_inflate_generic_method_full_checked (ref->method, klass, &ctx, &error);
+               ref->method = mono_class_inflate_generic_method_full_checked (ref->method, klass, &ctx, error);
                if (!ref->method)
-                       g_error ("AOT runtime could not load method due to %s", mono_error_get_message (&error)); /* FIXME don't swallow the error */
+                       return FALSE;
 
        } else if (image_index == MONO_AOT_METHODREF_ARRAY) {
                MonoClass *klass;
                int method_type;
 
-               klass = decode_klass_ref (module, p, &p);
+               klass = decode_klass_ref (module, p, &p, error);
                if (!klass)
                        return FALSE;
                method_type = decode_value (p, &p);
@@ -1274,7 +1300,8 @@ decode_method_ref_with_target (MonoAotModule *module, MethodRef *ref, MonoMethod
                        ref->method = mono_class_get_method_from_name (klass, "Set", -1);
                        break;
                default:
-                       g_assert_not_reached ();
+                       mono_error_set_bad_image_name (error, module->aot_name, "Invalid METHODREF_ARRAY method type %d", method_type);
+                       return FALSE;
                }
        } else {
                if (image_index == MONO_AOT_METHODREF_LARGE_IMAGE_INDEX) {
@@ -1284,7 +1311,7 @@ decode_method_ref_with_target (MonoAotModule *module, MethodRef *ref, MonoMethod
 
                ref->token = MONO_TOKEN_METHOD_DEF | (value & 0xffffff);
 
-               image = load_image (module, image_index, TRUE);
+               image = load_image (module, image_index, error);
                if (!image)
                        return FALSE;
        }
@@ -1297,9 +1324,9 @@ decode_method_ref_with_target (MonoAotModule *module, MethodRef *ref, MonoMethod
 }
 
 static gboolean
-decode_method_ref (MonoAotModule *module, MethodRef *ref, guint8 *buf, guint8 **endbuf)
+decode_method_ref (MonoAotModule *module, MethodRef *ref, guint8 *buf, guint8 **endbuf, MonoError *error)
 {
-       return decode_method_ref_with_target (module, ref, NULL, buf, endbuf);
+       return decode_method_ref_with_target (module, ref, NULL, buf, endbuf, error);
 }
 
 /*
@@ -1308,30 +1335,27 @@ decode_method_ref (MonoAotModule *module, MethodRef *ref, guint8 *buf, guint8 **
  *   Similar to decode_method_ref, but resolve and return the method itself.
  */
 static MonoMethod*
-decode_resolve_method_ref_with_target (MonoAotModule *module, MonoMethod *target, guint8 *buf, guint8 **endbuf)
+decode_resolve_method_ref_with_target (MonoAotModule *module, MonoMethod *target, guint8 *buf, guint8 **endbuf, MonoError *error)
 {
-       MonoError error;
        MethodRef ref;
-       gboolean res;
-       MonoMethod *result;
 
-       res = decode_method_ref_with_target (module, &ref, target, buf, endbuf);
-       if (!res)
+       mono_error_init (error);
+
+       if (!decode_method_ref_with_target (module, &ref, target, buf, endbuf, error))
                return NULL;
        if (ref.method)
                return ref.method;
-       if (!ref.image)
+       if (!ref.image) {
+               mono_error_set_bad_image_name (error, module->aot_name, "No image found for methodref with target");
                return NULL;
-       result = mono_get_method_checked (ref.image, ref.token, NULL, NULL, &error);
-       if (!result)
-               mono_error_cleanup (&error); /* FIXME don't swallow the error */
-       return result;
+       }
+       return mono_get_method_checked (ref.image, ref.token, NULL, NULL, error);
 }
 
 static MonoMethod*
-decode_resolve_method_ref (MonoAotModule *module, guint8 *buf, guint8 **endbuf)
+decode_resolve_method_ref (MonoAotModule *module, guint8 *buf, guint8 **endbuf, MonoError *error)
 {
-       return decode_resolve_method_ref_with_target (module, NULL, buf, endbuf);
+       return decode_resolve_method_ref_with_target (module, NULL, buf, endbuf, error);
 }
 
 #ifdef ENABLE_AOT_CACHE
@@ -2244,8 +2268,11 @@ load_aot_module (MonoAssembly *assembly, gpointer user_data)
        }
 #endif
        if (do_load_image) {
-               for (i = 0; i < amodule->image_table_len; ++i)
-                       load_image (amodule, i, FALSE);
+               for (i = 0; i < amodule->image_table_len; ++i) {
+                       MonoError error;
+                       load_image (amodule, i, &error);
+                       mono_error_cleanup (&error); /* FIXME don't swallow the error */
+               }
        }
 
        if (amodule->out_of_date) {
@@ -2322,6 +2349,7 @@ mono_aot_cleanup (void)
 static gboolean
 decode_cached_class_info (MonoAotModule *module, MonoCachedClassInfo *info, guint8 *buf, guint8 **endbuf)
 {
+       MonoError error;
        guint32 flags;
        MethodRef ref;
        gboolean res;
@@ -2342,13 +2370,15 @@ decode_cached_class_info (MonoAotModule *module, MonoCachedClassInfo *info, guin
        info->is_generic_container = (flags >> 8) & 0x1;
 
        if (info->has_cctor) {
-               res = decode_method_ref (module, &ref, buf, &buf);
+               res = decode_method_ref (module, &ref, buf, &buf, &error);
+               mono_error_assert_ok (&error); /* FIXME don't swallow the error */
                if (!res)
                        return FALSE;
                info->cctor_token = ref.token;
        }
        if (info->has_finalize) {
-               res = decode_method_ref (module, &ref, buf, &buf);
+               res = decode_method_ref (module, &ref, buf, &buf, &error);
+               mono_error_assert_ok (&error); /* FIXME don't swallow the error */
                if (!res)
                        return FALSE;
                info->finalize_image = ref.image;
@@ -2368,6 +2398,7 @@ decode_cached_class_info (MonoAotModule *module, MonoCachedClassInfo *info, guin
 gpointer
 mono_aot_get_method_from_vt_slot (MonoDomain *domain, MonoVTable *vtable, int slot)
 {
+       MonoError error;
        int i;
        MonoClass *klass = vtable->klass;
        MonoAotModule *amodule = (MonoAotModule *)klass->image->aot_module;
@@ -2387,10 +2418,13 @@ mono_aot_get_method_from_vt_slot (MonoDomain *domain, MonoVTable *vtable, int sl
        if (!err)
                return NULL;
 
-       for (i = 0; i < slot; ++i)
-               decode_method_ref (amodule, &ref, p, &p);
+       for (i = 0; i < slot; ++i) {
+               decode_method_ref (amodule, &ref, p, &p, &error);
+               mono_error_cleanup (&error); /* FIXME don't swallow the error */
+       }
 
-       res = decode_method_ref (amodule, &ref, p, &p);
+       res = decode_method_ref (amodule, &ref, p, &p, &error);
+       mono_error_cleanup (&error); /* FIXME don't swallow the error */
        if (!res)
                return NULL;
        if (ref.no_aot_trampoline)
@@ -2799,6 +2833,7 @@ decode_exception_debug_info (MonoAotModule *amodule, MonoDomain *domain,
                                                         MonoMethod *method, guint8* ex_info,
                                                         guint8 *code, guint32 code_len)
 {
+       MonoError error;
        int i, buf_len, num_clauses, len;
        MonoJitInfo *jinfo;
        MonoJitInfoFlags flags = JIT_INFO_NONE;
@@ -2872,8 +2907,10 @@ decode_exception_debug_info (MonoAotModule *amodule, MonoDomain *domain,
 
                        ei->flags = decode_value (p, &p);
 
-                       if (decode_value (p, &p))
-                               ei->data.catch_class = decode_klass_ref (amodule, p, &p);
+                       if (decode_value (p, &p)) {
+                               ei->data.catch_class = decode_klass_ref (amodule, p, &p, &error);
+                               mono_error_cleanup (&error); /* FIXME don't swallow the error */
+                       }
 
                        ei->clause_index = i;
 
@@ -2921,10 +2958,12 @@ decode_exception_debug_info (MonoAotModule *amodule, MonoDomain *domain,
                                int len = decode_value (p, &p);
 
                                if (len > 0) {
-                                       if (async)
+                                       if (async) {
                                                p += len;
-                                       else
-                                               ei->data.catch_class = decode_klass_ref (amodule, p, &p);
+                                       } else {
+                                               ei->data.catch_class = decode_klass_ref (amodule, p, &p, &error);
+                                               mono_error_cleanup (&error); /* FIXME don't swallow the error */
+                                       }
                                }
                        }
 
@@ -3010,10 +3049,12 @@ decode_exception_debug_info (MonoAotModule *amodule, MonoDomain *domain,
                }
 
                len = decode_value (p, &p);
-               if (async)
+               if (async) {
                        p += len;
-               else
-                       jinfo->d.method = decode_resolve_method_ref (amodule, p, &p);
+               } else {
+                       jinfo->d.method = decode_resolve_method_ref (amodule, p, &p, &error);
+                       mono_error_cleanup (&error); /* FIXME don't swallow the error */
+               }
 
                gi->generic_sharing_context = g_new0 (MonoGenericSharingContext, 1);
                if (decode_value (p, &p)) {
@@ -3172,6 +3213,7 @@ msort_method_addresses (gpointer *array, int *indexes, int len)
 MonoJitInfo *
 mono_aot_find_jit_info (MonoDomain *domain, MonoImage *image, gpointer addr)
 {
+       MonoError error;
        int pos, left, right, code_len;
        int method_index, table_len;
        guint32 token;
@@ -3325,7 +3367,8 @@ mono_aot_find_jit_info (MonoDomain *domain, MonoImage *image, gpointer addr)
                                }
 
                                p = amodule->blob + table [(pos * 2) + 1];
-                               method = decode_resolve_method_ref (amodule, p, &p);
+                               method = decode_resolve_method_ref (amodule, p, &p, &error);
+                               mono_error_cleanup (&error); /* FIXME don't swallow the error */
                                if (!method)
                                        /* Happens when a random address is passed in which matches a not-yey called wrapper encoded using its name */
                                        return NULL;
@@ -3388,6 +3431,7 @@ mono_aot_find_jit_info (MonoDomain *domain, MonoImage *image, gpointer addr)
 static gboolean
 decode_patch (MonoAotModule *aot_module, MonoMemPool *mp, MonoJumpInfo *ji, guint8 *buf, guint8 **endbuf)
 {
+       MonoError error;
        guint8 *p = buf;
        gpointer *table;
        MonoImage *image;
@@ -3403,7 +3447,8 @@ decode_patch (MonoAotModule *aot_module, MonoMemPool *mp, MonoJumpInfo *ji, guin
                MethodRef ref;
                gboolean res;
 
-               res = decode_method_ref (aot_module, &ref, p, &p);
+               res = decode_method_ref (aot_module, &ref, p, &p, &error);
+               mono_error_assert_ok (&error); /* FIXME don't swallow the error */
                if (!res)
                        goto cleanup;
 
@@ -3435,7 +3480,8 @@ decode_patch (MonoAotModule *aot_module, MonoMemPool *mp, MonoJumpInfo *ji, guin
        }
        case MONO_PATCH_INFO_METHODCONST:
                /* Shared */
-               ji->data.method = decode_resolve_method_ref (aot_module, p, &p);
+               ji->data.method = decode_resolve_method_ref (aot_module, p, &p, &error);
+               mono_error_cleanup (&error); /* FIXME don't swallow the error */
                if (!ji->data.method)
                        goto cleanup;
                break;
@@ -3444,24 +3490,28 @@ decode_patch (MonoAotModule *aot_module, MonoMemPool *mp, MonoJumpInfo *ji, guin
        case MONO_PATCH_INFO_IID:
        case MONO_PATCH_INFO_ADJUSTED_IID:
                /* Shared */
-               ji->data.klass = decode_klass_ref (aot_module, p, &p);
+               ji->data.klass = decode_klass_ref (aot_module, p, &p, &error);
+               mono_error_cleanup (&error); /* FIXME don't swallow the error */
                if (!ji->data.klass)
                        goto cleanup;
                break;
        case MONO_PATCH_INFO_DELEGATE_TRAMPOLINE:
                ji->data.del_tramp = (MonoDelegateClassMethodPair *)mono_mempool_alloc0 (mp, sizeof (MonoDelegateClassMethodPair));
-               ji->data.del_tramp->klass = decode_klass_ref (aot_module, p, &p);
+               ji->data.del_tramp->klass = decode_klass_ref (aot_module, p, &p, &error);
+               mono_error_cleanup (&error); /* FIXME don't swallow the error */
                if (!ji->data.del_tramp->klass)
                        goto cleanup;
                if (decode_value (p, &p)) {
-                       ji->data.del_tramp->method = decode_resolve_method_ref (aot_module, p, &p);
+                       ji->data.del_tramp->method = decode_resolve_method_ref (aot_module, p, &p, &error);
+                       mono_error_cleanup (&error); /* FIXME don't swallow the error */
                        if (!ji->data.del_tramp->method)
                                goto cleanup;
                }
                ji->data.del_tramp->is_virtual = decode_value (p, &p) ? TRUE : FALSE;
                break;
        case MONO_PATCH_INFO_IMAGE:
-               ji->data.image = load_image (aot_module, decode_value (p, &p), TRUE);
+               ji->data.image = load_image (aot_module, decode_value (p, &p), &error);
+               mono_error_cleanup (&error); /* FIXME don't swallow the error */
                if (!ji->data.image)
                        goto cleanup;
                break;
@@ -3501,7 +3551,8 @@ decode_patch (MonoAotModule *aot_module, MonoMemPool *mp, MonoJumpInfo *ji, guin
                break;
        }
        case MONO_PATCH_INFO_LDSTR:
-               image = load_image (aot_module, decode_value (p, &p), TRUE);
+               image = load_image (aot_module, decode_value (p, &p), &error);
+               mono_error_cleanup (&error); /* FIXME don't swallow the error */
                if (!image)
                        goto cleanup;
                ji->data.token = mono_jump_info_token_new (mp, image, MONO_TOKEN_STRING + decode_value (p, &p));
@@ -3511,20 +3562,23 @@ decode_patch (MonoAotModule *aot_module, MonoMemPool *mp, MonoJumpInfo *ji, guin
        case MONO_PATCH_INFO_LDTOKEN:
        case MONO_PATCH_INFO_TYPE_FROM_HANDLE:
                /* Shared */
-               image = load_image (aot_module, decode_value (p, &p), TRUE);
+               image = load_image (aot_module, decode_value (p, &p), &error);
+               mono_error_cleanup (&error); /* FIXME don't swallow the error */
                if (!image)
                        goto cleanup;
                ji->data.token = mono_jump_info_token_new (mp, image, decode_value (p, &p));
 
                ji->data.token->has_context = decode_value (p, &p);
                if (ji->data.token->has_context) {
-                       gboolean res = decode_generic_context (aot_module, &ji->data.token->context, p, &p);
+                       gboolean res = decode_generic_context (aot_module, &ji->data.token->context, p, &p, &error);
+                       mono_error_cleanup (&error); /* FIXME don't swallow the error */
                        if (!res)
                                goto cleanup;
                }
                break;
        case MONO_PATCH_INFO_EXC_NAME:
-               ji->data.klass = decode_klass_ref (aot_module, p, &p);
+               ji->data.klass = decode_klass_ref (aot_module, p, &p, &error);
+               mono_error_cleanup (&error); /* FIXME don't swallow the error */
                if (!ji->data.klass)
                        goto cleanup;
                ji->data.name = ji->data.klass->name;
@@ -3553,11 +3607,12 @@ decode_patch (MonoAotModule *aot_module, MonoMemPool *mp, MonoJumpInfo *ji, guin
 
                entry = (MonoJumpInfoRgctxEntry *)mono_mempool_alloc0 (mp, sizeof (MonoJumpInfoRgctxEntry));
                p2 = aot_module->blob + offset;
-               entry->method = decode_resolve_method_ref (aot_module, p2, &p2);
+               entry->method = decode_resolve_method_ref (aot_module, p2, &p2, &error);
                entry->in_mrgctx = ((val & 1) > 0) ? TRUE : FALSE;
                entry->info_type = (MonoRgctxInfoType)((val >> 1) & 0xff);
                entry->data = (MonoJumpInfo *)mono_mempool_alloc0 (mp, sizeof (MonoJumpInfo));
                entry->data->type = (MonoJumpInfoType)((val >> 9) & 0xff);
+               mono_error_cleanup (&error); /* FIXME don't swallow the error */
                
                res = decode_patch (aot_module, mp, entry->data, p, &p);
                if (!res)
@@ -3580,8 +3635,8 @@ decode_patch (MonoAotModule *aot_module, MonoMemPool *mp, MonoJumpInfo *ji, guin
                MonoJumpInfoGSharedVtCall *info = (MonoJumpInfoGSharedVtCall *)mono_mempool_alloc0 (mp, sizeof (MonoJumpInfoGSharedVtCall));
                info->sig = decode_signature (aot_module, p, &p);
                g_assert (info->sig);
-               info->method = decode_resolve_method_ref (aot_module, p, &p);
-               g_assert (info->method);
+               info->method = decode_resolve_method_ref (aot_module, p, &p, &error);
+               mono_error_assert_ok (&error); /* FIXME don't swallow the error */
 
                ji->data.target = info;
                break;
@@ -3590,8 +3645,9 @@ decode_patch (MonoAotModule *aot_module, MonoMemPool *mp, MonoJumpInfo *ji, guin
                MonoGSharedVtMethodInfo *info = (MonoGSharedVtMethodInfo *)mono_mempool_alloc0 (mp, sizeof (MonoGSharedVtMethodInfo));
                int i;
                
-               info->method = decode_resolve_method_ref (aot_module, p, &p);
-               g_assert (info->method);
+               info->method = decode_resolve_method_ref (aot_module, p, &p, &error);
+               mono_error_assert_ok (&error); /* FIXME don't swallow the error */
+
                info->num_entries = decode_value (p, &p);
                info->count_entries = info->num_entries;
                info->entries = (MonoRuntimeGenericContextInfoTemplate *)mono_mempool_alloc0 (mp, sizeof (MonoRuntimeGenericContextInfoTemplate) * info->num_entries);
@@ -3601,7 +3657,8 @@ decode_patch (MonoAotModule *aot_module, MonoMemPool *mp, MonoJumpInfo *ji, guin
                        template_->info_type = (MonoRgctxInfoType)decode_value (p, &p);
                        switch (mini_rgctx_info_type_to_patch_info_type (template_->info_type)) {
                        case MONO_PATCH_INFO_CLASS: {
-                               MonoClass *klass = decode_klass_ref (aot_module, p, &p);
+                               MonoClass *klass = decode_klass_ref (aot_module, p, &p, &error);
+                               mono_error_cleanup (&error); /* FIXME don't swallow the error */
                                if (!klass)
                                        goto cleanup;
                                template_->data = &klass->byval_arg;
@@ -3634,10 +3691,11 @@ decode_patch (MonoAotModule *aot_module, MonoMemPool *mp, MonoJumpInfo *ji, guin
        case MONO_PATCH_INFO_VIRT_METHOD: {
                MonoJumpInfoVirtMethod *info = (MonoJumpInfoVirtMethod *)mono_mempool_alloc0 (mp, sizeof (MonoJumpInfoVirtMethod));
 
-               info->klass = decode_klass_ref (aot_module, p, &p);
-               g_assert (info->klass);
-               info->method = decode_resolve_method_ref (aot_module, p, &p);
-               g_assert (info->method);
+               info->klass = decode_klass_ref (aot_module, p, &p, &error);
+               mono_error_assert_ok (&error); /* FIXME don't swallow the error */
+
+               info->method = decode_resolve_method_ref (aot_module, p, &p, &error);
+               mono_error_assert_ok (&error); /* FIXME don't swallow the error */
 
                ji->data.target = info;
                break;
@@ -3916,6 +3974,7 @@ load_method (MonoDomain *domain, MonoAotModule *amodule, MonoImage *image, MonoM
 static guint32
 find_aot_method_in_amodule (MonoAotModule *amodule, MonoMethod *method, guint32 hash_full)
 {
+       MonoError error;
        guint32 table_size, entry_size, hash;
        guint32 *table, *entry;
        guint32 index;
@@ -3951,7 +4010,8 @@ find_aot_method_in_amodule (MonoAotModule *amodule, MonoMethod *method, guint32
                m = (MonoMethod *)g_hash_table_lookup (amodule->method_ref_to_method, p);
                amodule_unlock (amodule);
                if (!m) {
-                       m = decode_resolve_method_ref_with_target (amodule, method, p, &p);
+                       m = decode_resolve_method_ref_with_target (amodule, method, p, &p, &error);
+                       mono_error_cleanup (&error); /* FIXME don't swallow the error */
                        /*
                         * Can't catche runtime invoke wrappers since it would break
                         * the check in decode_method_ref_with_target ().
@@ -4093,7 +4153,9 @@ init_method (MonoAotModule *amodule, guint32 method_index, MonoMethod *method, M
 
        //does the method's class has a cctor?
        if (decode_value (p, &p) == 1)
-               klass_to_run_ctor = decode_klass_ref (amodule, p, &p);
+               klass_to_run_ctor = decode_klass_ref (amodule, p, &p, error);
+       if (!is_ok (error))
+               return FALSE;
 
        //FIXME old code would use the class from @method if not null and ignore the one encoded. I don't know if we need to honor that -- @kumpera
        if (method)
index 140fbfb689b1f89ea0ef61570ed56b0c51bf9c01..4c791507cc3775777fb5e32e80d057292f1841e0 100644 (file)
@@ -7246,8 +7246,11 @@ vm_commands (int command, int id, guint8 *p, guint8 *end, Buffer *buf)
                                ass = (MonoAssembly *)tmp->data;
 
                                if (ass->image) {
+                                       MonoError error;
                                        type_resolve = TRUE;
-                                       t = mono_reflection_get_type (ass->image, &info, ignore_case, &type_resolve);
+                                       /* FIXME really okay to call while holding locks? */
+                                       t = mono_reflection_get_type_checked (ass->image, &info, ignore_case, &type_resolve, &error);
+                                       mono_error_cleanup (&error); 
                                        if (t) {
                                                g_ptr_array_add (res_classes, mono_type_get_class (t));
                                                g_ptr_array_add (res_domains, domain);
@@ -7663,6 +7666,7 @@ assembly_commands (int command, guint8 *p, guint8 *end, Buffer *buf)
                break;
        }
        case CMD_ASSEMBLY_GET_TYPE: {
+               MonoError error;
                char *s = decode_string (p, &p, end);
                gboolean ignorecase = decode_byte (p, &p, end);
                MonoTypeNameParse info;
@@ -7679,7 +7683,13 @@ assembly_commands (int command, guint8 *p, guint8 *end, Buffer *buf)
                } else {
                        if (info.assembly.name)
                                NOT_IMPLEMENTED;
-                       t = mono_reflection_get_type (ass->image, &info, ignorecase, &type_resolve);
+                       t = mono_reflection_get_type_checked (ass->image, &info, ignorecase, &type_resolve, &error);
+                       if (!is_ok (&error)) {
+                               mono_error_cleanup (&error); /* FIXME don't swallow the error */
+                               mono_reflection_free_type_info (&info);
+                               g_free (s);
+                               return ERR_INVALID_ARGUMENT;
+                       }
                }
                buffer_add_typeid (buf, domain, t ? mono_class_from_mono_type (t) : NULL);
                mono_reflection_free_type_info (&info);
index ed719f456e4156a74ee358f1d7b847a4395cfe2f..fe876b4ba30907b73c1c8ff6de883b433676c1b9 100644 (file)
 #include "mini-llvm-cpp.h"
 #include "llvm-jit.h"
 
+extern "C" {
+#include <mono/utils/mono-dl.h>
+}
+
 #if !defined(MONO_CROSS_COMPILE) && LLVM_API_VERSION > 100
 
 /*
 #include "llvm/ExecutionEngine/Orc/CompileUtils.h"
 #include "llvm/ExecutionEngine/Orc/IRCompileLayer.h"
 #include "llvm/ExecutionEngine/Orc/LambdaResolver.h"
-#include "llvm/ExecutionEngine/Orc/LazyEmittingLayer.h"
 #include "llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h"
 #include "llvm/ExecutionEngine/Orc/OrcArchitectureSupport.h"
 
 using namespace llvm;
 using namespace llvm::orc;
 
+extern cl::opt<bool> EnableMonoEH;
+extern cl::opt<std::string> MonoEHFrameSymbol;
+
 void
 mono_llvm_set_unhandled_exception_handler (void)
 {
 }
 
-static gboolean inited;
+template <typename T>
+static std::vector<T> singletonSet(T t) {
+  std::vector<T> Vec;
+  Vec.push_back(std::move(t));
+  return Vec;
+}
 
-static void
-init_llvm (void)
-{
-       if (inited)
-               return;
+#ifdef __MINGW32__
 
-       InitializeNativeTarget ();
-       InitializeNativeTargetAsmPrinter();
-}
+#include <stddef.h>
+extern void *memset(void *, int, size_t);
+void bzero (void *to, size_t count) { memset (to, 0, count); }
+
+#endif
+
+class MonoLLVMJIT {
+public:
+       /* We use our own trampoline infrastructure instead of the Orc one */
+       typedef ObjectLinkingLayer<> ObjLayerT;
+       typedef IRCompileLayer<ObjLayerT> CompileLayerT;
+       typedef CompileLayerT::ModuleSetHandleT ModuleHandleT;
+
+       MonoLLVMJIT (TargetMachine *TM)
+               : TM(TM),
+                 CompileLayer (ObjectLayer, SimpleCompiler (*TM)) {
+       }
+
+       ModuleHandleT addModule(Module *M) {
+               auto Resolver = createLambdaResolver(
+                      [&](const std::string &Name) {
+                                                 const char *name = Name.c_str ();
+                                                 if (!strcmp (name, "___bzero"))
+                                                         return RuntimeDyld::SymbolInfo((uint64_t)(gssize)(void*)bzero, (JITSymbolFlags)0);
+
+                                                 MonoDl *current;
+                                                 char *err;
+                                                 void *symbol;
+                                                 current = mono_dl_open (NULL, 0, NULL);
+                                                 g_assert (current);
+                                                 if (name [0] == '_')
+                                                         err = mono_dl_symbol (current, name + 1, &symbol);
+                                                 else
+                                                         err = mono_dl_symbol (current, name, &symbol);
+                                                 mono_dl_close (current);
+                                                 if (!symbol)
+                                                         outs () << "R: " << Name << "\n";
+                                                 assert (symbol);
+                                                 return RuntimeDyld::SymbolInfo((uint64_t)(gssize)symbol, (JITSymbolFlags)0);
+                      },
+                      [](const std::string &S) {
+                                                 outs () << "R2: " << S << "\n";
+                                                 assert (0);
+                                                 return nullptr;
+                                         } );
+
+               return CompileLayer.addModuleSet(singletonSet(M),
+                                                                                 make_unique<SectionMemoryManager>(),
+                                                                                 std::move(Resolver));
+       }
+
+       std::string mangle(const std::string &Name) {
+               std::string MangledName;
+               {
+                       raw_string_ostream MangledNameStream(MangledName);
+                       Mangler::getNameWithPrefix(MangledNameStream, Name,
+                                                                          TM->createDataLayout());
+               }
+               return MangledName;
+       }
+
+       std::string mangle(const GlobalValue *GV) {
+               std::string MangledName;
+               {
+                       Mangler Mang;
+
+                       raw_string_ostream MangledNameStream(MangledName);
+                       Mang.getNameWithPrefix(MangledNameStream, GV, false);
+               }
+               return MangledName;
+       }
+
+       gpointer compile (Function *F, int nvars, LLVMValueRef *callee_vars, gpointer *callee_addrs, gpointer *eh_frame) {
+               F->getParent ()->setDataLayout (TM->createDataLayout ());
+               auto ModuleHandle = addModule (F->getParent ());
+
+               auto BodySym = CompileLayer.findSymbolIn(ModuleHandle, mangle (F), false);
+               auto BodyAddr = BodySym.getAddress();
+               assert (BodyAddr);
+
+               for (int i = 0; i < nvars; ++i) {
+                       GlobalVariable *var = unwrap<GlobalVariable>(callee_vars [i]);
+
+                       auto sym = CompileLayer.findSymbolIn (ModuleHandle, mangle (var->getName ()), true);
+                       auto addr = sym.getAddress ();
+                       g_assert (addr);
+                       callee_addrs [i] = (gpointer)addr;
+               }
+
+               auto ehsym = CompileLayer.findSymbolIn(ModuleHandle, "mono_eh_frame", false);
+               auto ehaddr = ehsym.getAddress ();
+               g_assert (ehaddr);
+               *eh_frame = (gpointer)ehaddr;
+
+               return (gpointer)BodyAddr;
+       }
+
+private:
+       TargetMachine *TM;
+       ObjLayerT ObjectLayer;
+       CompileLayerT CompileLayer;
+};
+
+static MonoLLVMJIT *jit;
 
 MonoEERef
 mono_llvm_create_ee (LLVMModuleProviderRef MP, AllocCodeMemoryCb *alloc_cb, FunctionEmittedCb *emitted_cb, ExceptionTableCb *exception_cb, DlSymCb *dlsym_cb, LLVMExecutionEngineRef *ee)
 {
-       init_llvm ();
+       InitializeNativeTarget ();
+       InitializeNativeTargetAsmPrinter();
+
+       EnableMonoEH = true;
+       MonoEHFrameSymbol = "mono_eh_frame";
+
+       EngineBuilder EB;
+#if defined(TARGET_AMD64) || defined(TARGET_X86)
+       std::vector<std::string> attrs;
+       // FIXME: Autodetect this
+       attrs.push_back("sse3");
+       attrs.push_back("sse4.1");
+       EB.setMAttrs (attrs);
+#endif
+       auto TM = EB.selectTarget ();
+       assert (TM);
+
+       jit = new MonoLLVMJIT (TM);
 
        return NULL;
 }
 
-void
-mono_llvm_optimize_method (MonoEERef eeref, LLVMValueRef method)
+/*
+ * mono_llvm_compile_method:
+ *
+ *   Compile METHOD to native code. Compute the addresses of the variables in CALLEE_VARS and store them into
+ * CALLEE_ADDRS. Return the EH frame address in EH_FRAME.
+ */
+gpointer
+mono_llvm_compile_method (MonoEERef mono_ee, LLVMValueRef method, int nvars, LLVMValueRef *callee_vars, gpointer *callee_addrs, gpointer *eh_frame)
 {
-       g_assert_not_reached ();
+       return jit->compile (unwrap<Function> (method), nvars, callee_vars, callee_addrs, eh_frame);
 }
 
 void
@@ -75,13 +206,14 @@ mono_llvm_dispose_ee (MonoEERef *eeref)
 }
 
 void
-LLVMAddGlobalMapping (LLVMExecutionEngineRef EE, LLVMValueRef Global,
-                                         void* Addr)
+LLVMAddGlobalMapping(LLVMExecutionEngineRef EE, LLVMValueRef Global,
+                                        void* Addr)
 {
+       g_assert_not_reached ();
 }
 
 void*
-LLVMGetPointerToGlobal (LLVMExecutionEngineRef EE, LLVMValueRef Global)
+LLVMGetPointerToGlobal(LLVMExecutionEngineRef EE, LLVMValueRef Global)
 {
        g_assert_not_reached ();
        return NULL;
index fe23bff820f0733f1f93b6c97255a7186205cddc..4510b71cea6ee58689c4ce7179b1421def6ca226 100644 (file)
@@ -33,7 +33,7 @@ void
 mono_llvm_dispose_ee (MonoEERef *mono_ee);
 
 gpointer
-mono_llvm_compile_method (MonoEERef mono_ee, LLVMValueRef method);
+mono_llvm_compile_method (MonoEERef mono_ee, LLVMValueRef method, int nvars, LLVMValueRef *callee_vars, gpointer *callee_addrs, gpointer *eh_frame);
 
 void
 mono_llvm_optimize_method (MonoEERef mono_ee, LLVMValueRef method);
index 6dc95e48f1927ad5b108e2f7ae8e86f013f74657..83d9ba44dd725c7c84285a0cd56c839318a47944 100644 (file)
@@ -46,6 +46,8 @@ void bzero (void *to, size_t count) { memset (to, 0, count); }
 #error "The version of the mono llvm repository is too old."
 #endif
 
+#define ALIGN_PTR_TO(ptr,align) (gpointer)((((gssize)(ptr)) + (align - 1)) & (~(align - 1)))
+
  /*
   * Information associated by mono with LLVM modules.
   */
@@ -166,6 +168,7 @@ typedef struct {
        GPtrArray *phi_values;
        GPtrArray *bblock_list;
        char *method_name;
+       GHashTable *jit_callees;
 } EmitContext;
 
 typedef struct {
@@ -258,9 +261,9 @@ static LLVMRealPredicate fpcond_to_llvm_cond [] = {
 static MonoNativeTlsKey current_cfg_tls_id;
 
 static MonoLLVMModule aot_module;
-static int memset_param_count, memcpy_param_count;
-static const char *memset_func_name;
-static const char *memcpy_func_name;
+
+static GHashTable *intrins_id_to_name;
+static GHashTable *intrins_name_to_id;
 
 static void init_jit_module (MonoDomain *domain);
 
@@ -268,6 +271,8 @@ static void emit_dbg_loc (EmitContext *ctx, LLVMBuilderRef builder, const unsign
 static LLVMValueRef emit_dbg_subprogram (EmitContext *ctx, MonoCompile *cfg, LLVMValueRef method, const char *name);
 static void emit_dbg_info (MonoLLVMModule *module, const char *filename, const char *cu_name);
 static void emit_cond_system_exception (EmitContext *ctx, MonoBasicBlock *bb, const char *exc_type, LLVMValueRef cmp);
+static LLVMValueRef get_intrinsic (EmitContext *ctx, const char *name);
+static void decode_llvm_eh_info (EmitContext *ctx, gpointer eh_frame);
 
 static inline void
 set_failure (EmitContext *ctx, const char *message)
@@ -1697,6 +1702,22 @@ get_callee (EmitContext *ctx, LLVMTypeRef llvm_sig, MonoJumpInfoType type, gcons
        }
 }
 
+static LLVMValueRef
+emit_jit_callee (EmitContext *ctx, const char *name, LLVMTypeRef llvm_sig, gpointer target)
+{
+#if LLVM_API_VERSION > 100
+       LLVMValueRef tramp_var = LLVMAddGlobal (ctx->lmodule, LLVMPointerType (llvm_sig, 0), name);
+       LLVMSetInitializer (tramp_var, LLVMConstIntToPtr (LLVMConstInt (LLVMInt64Type (), (guint64)(size_t)target, FALSE), LLVMPointerType (llvm_sig, 0)));
+       LLVMSetLinkage (tramp_var, LLVMExternalLinkage);
+       LLVMValueRef callee = LLVMBuildLoad (ctx->builder, tramp_var, "");
+       return callee;
+#else
+       LLVMValueRef callee = LLVMAddFunction (ctx->lmodule, "", llvm_sig);
+       LLVMAddGlobalMapping (ctx->module->ee, callee, target);
+       return callee;
+#endif
+}
+
 static int
 get_handler_clause (MonoCompile *cfg, MonoBasicBlock *bb)
 {
@@ -1927,7 +1948,7 @@ emit_load_general (EmitContext *ctx, MonoBasicBlock *bb, LLVMBuilderRef *builder
                args [1] = LLVMConstInt (LLVMInt32Type (), 0, FALSE);
                args [2] = LLVMConstInt (LLVMInt1Type (), TRUE, FALSE);
                args [3] = LLVMConstInt (LLVMInt32Type (), ordering, FALSE);
-               res = emit_call (ctx, bb, builder_ref, LLVMGetNamedFunction (ctx->lmodule, intrins_name), args, 4);
+               res = emit_call (ctx, bb, builder_ref, get_intrinsic (ctx, intrins_name), args, 4);
 
                if (addr_type == LLVMPointerType (LLVMDoubleType (), 0))
                        res = LLVMBuildBitCast (*builder_ref, res, LLVMDoubleType (), "");
@@ -2023,7 +2044,7 @@ emit_store_general (EmitContext *ctx, MonoBasicBlock *bb, LLVMBuilderRef *builde
                args [2] = LLVMConstInt (LLVMInt32Type (), 0, FALSE);
                args [3] = LLVMConstInt (LLVMInt1Type (), TRUE, FALSE);
                args [4] = LLVMConstInt (LLVMInt32Type (), ordering, FALSE);
-               emit_call (ctx, bb, builder_ref, LLVMGetNamedFunction (ctx->lmodule, intrins_name), args, 5);
+               emit_call (ctx, bb, builder_ref, get_intrinsic (ctx, intrins_name), args, 5);
        } else {
                mono_llvm_build_store (*builder_ref, value, addr, is_faulting, barrier);
        }
@@ -2099,17 +2120,29 @@ emit_cond_system_exception (EmitContext *ctx, MonoBasicBlock *bb, const char *ex
                if (ctx->cfg->compile_aot) {
                        callee = get_callee (ctx, sig, MONO_PATCH_INFO_INTERNAL_METHOD, icall_name);
                } else {
-                       callee = LLVMAddFunction (ctx->lmodule, "llvm_throw_corlib_exception_trampoline", sig);
-
                        /*
                         * Differences between the LLVM/non-LLVM throw corlib exception trampoline:
                         * - On x86, LLVM generated code doesn't push the arguments
                         * - The trampoline takes the throw address as an arguments, not a pc offset.
                         */
-                       LLVMAddGlobalMapping (ctx->module->ee, callee, resolve_patch (ctx->cfg, MONO_PATCH_INFO_INTERNAL_METHOD, icall_name));
+                       gpointer target = resolve_patch (ctx->cfg, MONO_PATCH_INFO_INTERNAL_METHOD, icall_name);
+                       callee = emit_jit_callee (ctx, "llvm_throw_corlib_exception_trampoline", sig, target);
 
+#if LLVM_API_VERSION > 100
+                       /*
+                        * Make sure that ex_bb starts with the invoke, so the block address points to it, and not to the load 
+                        * added by emit_jit_callee ().
+                        */
+                       ex2_bb = gen_bb (ctx, "EX2_BB");
+                       LLVMBuildBr (builder, ex2_bb);
+                       ex_bb = ex2_bb;
+
+                       ctx->builder = builder = create_builder (ctx);
+                       LLVMPositionBuilderAtEnd (ctx->builder, ex2_bb);
+#else
                        mono_memory_barrier ();
                        ctx->module->throw_corlib_exception = callee;
+#endif
                }
        }
 
@@ -2723,7 +2756,7 @@ emit_init_method (EmitContext *ctx)
 
        args [0] = inited_var;
        args [1] = LLVMConstInt (LLVMInt8Type (), 1, FALSE);
-       inited_var = LLVMBuildCall (ctx->builder, LLVMGetNamedFunction (ctx->lmodule, "llvm.expect.i8"), args, 2, "");
+       inited_var = LLVMBuildCall (ctx->builder, get_intrinsic (ctx, "llvm.expect.i8"), args, 2, "");
 
        cmp = LLVMBuildICmp (builder, LLVMIntEQ, inited_var, LLVMConstInt (LLVMTypeOf (inited_var), 0, FALSE), "");
 
@@ -3092,7 +3125,6 @@ static void
 process_call (EmitContext *ctx, MonoBasicBlock *bb, LLVMBuilderRef *builder_ref, MonoInst *ins)
 {
        MonoCompile *cfg = ctx->cfg;
-       LLVMModuleRef lmodule = ctx->lmodule;
        LLVMValueRef *values = ctx->values;
        LLVMValueRef *addresses = ctx->addresses;
        MonoCallInst *call = (MonoCallInst*)ins;
@@ -3155,15 +3187,40 @@ process_call (EmitContext *ctx, MonoBasicBlock *bb, LLVMBuilderRef *builder_ref,
                                }
                        } else {
                                MonoError error;
+                               static int tramp_index;
+                               char *name;
+
+                               name = g_strdup_printf ("tramp_%d", tramp_index);
+                               tramp_index ++;
+
+#if LLVM_API_VERSION > 100
+                               /*
+                                * Use our trampoline infrastructure for lazy compilation instead of llvm's.
+                                * Make all calls through a global. The address of the global will be saved in
+                                * MonoJitDomainInfo.llvm_jit_callees and updated when the method it refers to is
+                                * compiled.
+                                */
+                               LLVMValueRef tramp_var = g_hash_table_lookup (ctx->jit_callees, call->method);
+                               if (!tramp_var) {
+                                       target =
+                                               mono_create_jit_trampoline (mono_domain_get (),
+                                                                                                       call->method, &error);
+                                       if (!mono_error_ok (&error))
+                                               mono_error_raise_exception (&error); /* FIXME: Don't raise here */
+                                       tramp_var = LLVMAddGlobal (ctx->lmodule, LLVMPointerType (llvm_sig, 0), name);
+                                       LLVMSetInitializer (tramp_var, LLVMConstIntToPtr (LLVMConstInt (LLVMInt64Type (), (guint64)(size_t)target, FALSE), LLVMPointerType (llvm_sig, 0)));
+                                       LLVMSetLinkage (tramp_var, LLVMExternalLinkage);
+                                       g_hash_table_insert (ctx->jit_callees, call->method, tramp_var);
+                               }
+                               callee = LLVMBuildLoad (builder, tramp_var, "");
+#else
+                               callee = LLVMAddFunction (ctx->lmodule, name, llvm_sig);
+                               g_free (name);
 
-                               callee = LLVMAddFunction (lmodule, "", llvm_sig);
-                               target =
-                                       mono_create_jit_trampoline (mono_domain_get (),
-                                                                                               call->method, &error);
                                if (!mono_error_ok (&error))
                                        mono_error_raise_exception (&error); /* FIXME: Don't raise here */
                                LLVMAddGlobalMapping (ctx->module->ee, callee, target);
+#endif
                        }
                }
 
@@ -3193,9 +3250,8 @@ process_call (EmitContext *ctx, MonoBasicBlock *bb, LLVMBuilderRef *builder_ref,
                                        return;
                                }
                        } else {
-                               callee = LLVMAddFunction (lmodule, "", llvm_sig);
                                target = (gpointer)mono_icall_get_wrapper (info);
-                               LLVMAddGlobalMapping (ctx->module->ee, callee, target);
+                               callee = emit_jit_callee (ctx, "", llvm_sig, target);
                        }
                } else {
                        if (cfg->compile_aot) {
@@ -3215,7 +3271,23 @@ process_call (EmitContext *ctx, MonoBasicBlock *bb, LLVMBuilderRef *builder_ref,
                                        return;
                                }
                        } else {
-                               callee = LLVMAddFunction (lmodule, "", llvm_sig);
+#if LLVM_API_VERSION > 100
+                               if (cfg->abs_patches) {
+                                       MonoJumpInfo *abs_ji = (MonoJumpInfo*)g_hash_table_lookup (cfg->abs_patches, call->fptr);
+                                       if (abs_ji) {
+                                               MonoError error;
+
+                                               target = mono_resolve_patch_target (cfg->method, cfg->domain, NULL, abs_ji, FALSE, &error);
+                                               mono_error_assert_ok (&error);
+                                               callee = emit_jit_callee (ctx, "", llvm_sig, target);
+                                       } else {
+                                               g_assert_not_reached ();
+                                       }
+                               } else {
+                                       g_assert_not_reached ();
+                               }
+#else
+                               callee = LLVMAddFunction (ctx->lmodule, "", llvm_sig);
                                target = NULL;
                                if (cfg->abs_patches) {
                                        MonoJumpInfo *abs_ji = (MonoJumpInfo*)g_hash_table_lookup (cfg->abs_patches, call->fptr);
@@ -3233,6 +3305,7 @@ process_call (EmitContext *ctx, MonoBasicBlock *bb, LLVMBuilderRef *builder_ref,
                                }
                                if (!target)
                                        LLVMAddGlobalMapping (ctx->module->ee, callee, (gpointer)call->fptr);
+#endif
                        }
                }
        }
@@ -3537,24 +3610,26 @@ emit_throw (EmitContext *ctx, MonoBasicBlock *bb, gboolean rethrow, LLVMValueRef
                if (ctx->cfg->compile_aot) {
                        callee = get_callee (ctx, sig_to_llvm_sig (ctx, throw_sig), MONO_PATCH_INFO_INTERNAL_METHOD, icall_name);
                } else {
-                       callee = LLVMAddFunction (ctx->lmodule, icall_name, sig_to_llvm_sig (ctx, throw_sig));
-
+                       gpointer target;
 #ifdef TARGET_X86
                        /* 
                         * LLVM doesn't push the exception argument, so we need a different
                         * trampoline.
                         */
-                       LLVMAddGlobalMapping (ctx->module->ee, callee, resolve_patch (ctx->cfg, MONO_PATCH_INFO_INTERNAL_METHOD, rethrow ? "llvm_rethrow_exception_trampoline" : "llvm_throw_exception_trampoline"));
+                       target = resolve_patch (ctx->cfg, MONO_PATCH_INFO_INTERNAL_METHOD, rethrow ? "llvm_rethrow_exception_trampoline" : "llvm_throw_exception_trampoline");
 #else
-                       LLVMAddGlobalMapping (ctx->module->ee, callee, resolve_patch (ctx->cfg, MONO_PATCH_INFO_INTERNAL_METHOD, icall_name));
+                       target = resolve_patch (ctx->cfg, MONO_PATCH_INFO_INTERNAL_METHOD, icall_name);
 #endif
+                       callee = emit_jit_callee (ctx, icall_name, sig_to_llvm_sig (ctx, throw_sig), target);
                }
 
                mono_memory_barrier ();
+#if LLVM_API_VERSION < 100
                if (rethrow)
                        ctx->module->rethrow = callee;
                else
                        ctx->module->throw_icall = callee;
+#endif
        }
        arg = convert (ctx, exc, type_to_llvm_type (ctx, &mono_get_object_class ()->byval_arg));
        emit_call (ctx, bb, &ctx->builder, callee, &arg, 1);
@@ -3717,7 +3792,7 @@ get_mono_personality (EmitContext *ctx)
 
        if (!use_debug_personality) {
                if (ctx->cfg->compile_aot) {
-                               personality = LLVMGetNamedFunction (ctx->lmodule, default_personality_name);
+                               personality = get_intrinsic (ctx, default_personality_name);
                } else if (InterlockedCompareExchange (&mapping_inited, 1, 0) == 0) {
                                personality = LLVMAddFunction (ctx->lmodule, default_personality_name, personality_type);
                                LLVMAddGlobalMapping (ctx->module->ee, personality, personality);
@@ -3865,10 +3940,8 @@ emit_handler_start (EmitContext *ctx, MonoBasicBlock *bb, LLVMBuilderRef builder
        LLVMValueRef landing_pad;
        LLVMBasicBlockRef target_bb;
        MonoInst *exvar;
-       static gint32 mapping_inited;
        static int ti_generator;
        char ti_name [128];
-       gint32 *ti;
        LLVMValueRef type_info;
        int clause_index;
        GSList *l;
@@ -3880,9 +3953,22 @@ emit_handler_start (EmitContext *ctx, MonoBasicBlock *bb, LLVMBuilderRef builder
                personality = LLVMGetNamedFunction (lmodule, "mono_personality");
                g_assert (personality);
        } else {
+#if LLVM_API_VERSION > 100
+               LLVMTypeRef personality_type = LLVMFunctionType (LLVMInt32Type (), NULL, 0, TRUE);
+               personality = LLVMAddFunction (ctx->lmodule, "mono_personality", personality_type);
+               LLVMAddFunctionAttr (personality, LLVMNoUnwindAttribute);
+               LLVMBasicBlockRef entry_bb = LLVMAppendBasicBlock (personality, "ENTRY");
+               LLVMBuilderRef builder2 = LLVMCreateBuilder ();
+               LLVMPositionBuilderAtEnd (builder2, entry_bb);
+               LLVMBuildRet (builder2, LLVMConstInt (LLVMInt32Type (), 0, FALSE));
+#else
+               static gint32 mapping_inited;
+
                personality = LLVMGetNamedFunction (lmodule, "mono_personality");
+
                if (InterlockedCompareExchange (&mapping_inited, 1, 0) == 0)
                        LLVMAddGlobalMapping (ctx->module->ee, personality, (gpointer)mono_personality);
+#endif
        }
 
        i8ptr = LLVMPointerType (LLVMInt8Type (), 0);
@@ -3905,6 +3991,12 @@ emit_handler_start (EmitContext *ctx, MonoBasicBlock *bb, LLVMBuilderRef builder
                 */
                LLVMSetLinkage (type_info, LLVMInternalLinkage);
        } else {
+#if LLVM_API_VERSION > 100
+               type_info = LLVMAddGlobal (lmodule, LLVMInt32Type (), ti_name);
+               LLVMSetInitializer (type_info, LLVMConstInt (LLVMInt32Type (), clause_index, FALSE));
+#else
+               gint32 *ti;
+
                /*
                 * After the cfg mempool is freed, the type info will point to stale memory,
                 * but this is not a problem, since we decode it once in exception_cb during
@@ -3916,6 +4008,7 @@ emit_handler_start (EmitContext *ctx, MonoBasicBlock *bb, LLVMBuilderRef builder
                type_info = LLVMAddGlobal (lmodule, i8ptr, ti_name);
 
                LLVMAddGlobalMapping (ctx->module->ee, type_info, ti);
+#endif
        }
 
        {
@@ -3993,7 +4086,6 @@ process_bb (EmitContext *ctx, MonoBasicBlock *bb)
        LLVMValueRef *values = ctx->values;
        LLVMValueRef *addresses = ctx->addresses;
        LLVMCallInfo *linfo = ctx->linfo;
-       LLVMModuleRef lmodule = ctx->lmodule;
        BBInfo *bblocks = ctx->bblocks;
        MonoInst *ins;
        LLVMBasicBlockRef cbb;
@@ -4365,7 +4457,7 @@ process_bb (EmitContext *ctx, MonoBasicBlock *bb)
                        if (likely) {
                                args [0] = cmp;
                                args [1] = LLVMConstInt (LLVMInt1Type (), 1, FALSE);
-                               cmp = LLVMBuildCall (ctx->builder, LLVMGetNamedFunction (ctx->lmodule, "llvm.expect.i1"), args, 2, "");
+                               cmp = LLVMBuildCall (ctx->builder, get_intrinsic (ctx, "llvm.expect.i1"), args, 2, "");
                        }
 
                        if (MONO_IS_COND_BRANCH_OP (ins->next)) {
@@ -4933,7 +5025,7 @@ process_bb (EmitContext *ctx, MonoBasicBlock *bb)
                                args [2] = LLVMConstInt (LLVMInt32Type (), size, FALSE);
                                args [3] = LLVMConstInt (LLVMInt32Type (), MONO_ARCH_FRAME_ALIGNMENT, FALSE);
                                args [4] = LLVMConstInt (LLVMInt1Type (), 0, FALSE);
-                               LLVMBuildCall (builder, LLVMGetNamedFunction (lmodule, memset_func_name), args, memset_param_count, "");
+                               LLVMBuildCall (builder, get_intrinsic (ctx, "llvm.memset.p0i8.i32"), args, 5, "");
                        }
 
                        values [ins->dreg] = v;
@@ -4954,7 +5046,7 @@ process_bb (EmitContext *ctx, MonoBasicBlock *bb)
                                args [2] = size;
                                args [3] = LLVMConstInt (LLVMInt32Type (), MONO_ARCH_FRAME_ALIGNMENT, FALSE);
                                args [4] = LLVMConstInt (LLVMInt1Type (), 0, FALSE);
-                               LLVMBuildCall (builder, LLVMGetNamedFunction (lmodule, memset_func_name), args, memset_param_count, "");
+                               LLVMBuildCall (builder, get_intrinsic (ctx, "llvm.memset.p0i8.i32"), args, 5, "");
                        }
                        values [ins->dreg] = v;
                        break;
@@ -5186,28 +5278,28 @@ process_bb (EmitContext *ctx, MonoBasicBlock *bb)
                        LLVMValueRef args [1];
 
                        args [0] = convert (ctx, lhs, LLVMDoubleType ());
-                       values [ins->dreg] = LLVMBuildCall (builder, LLVMGetNamedFunction (lmodule, "llvm.sin.f64"), args, 1, dname);
+                       values [ins->dreg] = LLVMBuildCall (builder, get_intrinsic (ctx, "llvm.sin.f64"), args, 1, dname);
                        break;
                }
                case OP_COS: {
                        LLVMValueRef args [1];
 
                        args [0] = convert (ctx, lhs, LLVMDoubleType ());
-                       values [ins->dreg] = LLVMBuildCall (builder, LLVMGetNamedFunction (lmodule, "llvm.cos.f64"), args, 1, dname);
+                       values [ins->dreg] = LLVMBuildCall (builder, get_intrinsic (ctx, "llvm.cos.f64"), args, 1, dname);
                        break;
                }
                case OP_SQRT: {
                        LLVMValueRef args [1];
 
                        args [0] = convert (ctx, lhs, LLVMDoubleType ());
-                       values [ins->dreg] = LLVMBuildCall (builder, LLVMGetNamedFunction (lmodule, "llvm.sqrt.f64"), args, 1, dname);
+                       values [ins->dreg] = LLVMBuildCall (builder, get_intrinsic (ctx, "llvm.sqrt.f64"), args, 1, dname);
                        break;
                }
                case OP_ABS: {
                        LLVMValueRef args [1];
 
                        args [0] = convert (ctx, lhs, LLVMDoubleType ());
-                       values [ins->dreg] = LLVMBuildCall (builder, LLVMGetNamedFunction (lmodule, "fabs"), args, 1, dname);
+                       values [ins->dreg] = LLVMBuildCall (builder, get_intrinsic (ctx, "fabs"), args, 1, dname);
                        break;
                }
 
@@ -5387,7 +5479,7 @@ process_bb (EmitContext *ctx, MonoBasicBlock *bb)
                }
                case OP_RELAXED_NOP: {
 #if defined(TARGET_AMD64) || defined(TARGET_X86)
-                       emit_call (ctx, bb, &builder, LLVMGetNamedFunction (ctx->lmodule, "llvm.x86.sse2.pause"), NULL, 0);
+                       emit_call (ctx, bb, &builder, get_intrinsic (ctx, "llvm.x86.sse2.pause"), NULL, 0);
                        break;
 #else
                        break;
@@ -5466,7 +5558,7 @@ process_bb (EmitContext *ctx, MonoBasicBlock *bb)
 
                                args [0] = convert (ctx, lhs, op_to_llvm_type (ins->opcode));
                                args [1] = convert (ctx, rhs, op_to_llvm_type (ins->opcode));
-                               func = LLVMGetNamedFunction (lmodule, ovf_op_to_intrins (ins->opcode));
+                               func = get_intrinsic (ctx, ovf_op_to_intrins (ins->opcode));
                                g_assert (func);
                                val = LLVMBuildCall (builder, func, args, 2, "");
                                values [ins->dreg] = LLVMBuildExtractValue (builder, val, 0, dname);
@@ -5503,7 +5595,7 @@ process_bb (EmitContext *ctx, MonoBasicBlock *bb)
                        // FIXME: Alignment
                        args [3] = LLVMConstInt (LLVMInt32Type (), 0, FALSE);
                        args [4] = LLVMConstInt (LLVMInt1Type (), 0, FALSE);
-                       LLVMBuildCall (builder, LLVMGetNamedFunction (lmodule, memset_func_name), args, memset_param_count, "");
+                       LLVMBuildCall (builder, get_intrinsic (ctx, "llvm.memset.p0i8.i32"), args, 5, "");
                        break;
                }
                case OP_DUMMY_VZERO:
@@ -5577,7 +5669,7 @@ process_bb (EmitContext *ctx, MonoBasicBlock *bb)
                        // FIXME: Alignment
                        args [3] = LLVMConstInt (LLVMInt32Type (), 0, FALSE);
                        args [4] = LLVMConstInt (LLVMInt1Type (), 0, FALSE);
-                       LLVMBuildCall (builder, LLVMGetNamedFunction (lmodule, memcpy_func_name), args, memcpy_param_count, "");
+                       LLVMBuildCall (builder, get_intrinsic (ctx, "llvm.memcpy.p0i8.p0i8.i32"), args, 5, "");
                        break;
                }
                case OP_LLVM_OUTARG_VT: {
@@ -5769,7 +5861,7 @@ process_bb (EmitContext *ctx, MonoBasicBlock *bb)
                        args [0] = lhs;
                        args [1] = rhs;
 
-                       values [ins->dreg] = LLVMBuildCall (builder, LLVMGetNamedFunction (lmodule, simd_op_to_intrins (ins->opcode)), args, 2, dname);
+                       values [ins->dreg] = LLVMBuildCall (builder, get_intrinsic (ctx, simd_op_to_intrins (ins->opcode)), args, 2, dname);
                        break;
                }
                case OP_PCMPEQB:
@@ -5876,7 +5968,7 @@ process_bb (EmitContext *ctx, MonoBasicBlock *bb)
 
                        v = convert (ctx, values [ins->sreg1], simd_op_to_llvm_type (ins->opcode));
 
-                       values [ins->dreg] = LLVMBuildCall (builder, LLVMGetNamedFunction (lmodule, simd_op_to_intrins (ins->opcode)), &v, 1, dname);
+                       values [ins->dreg] = LLVMBuildCall (builder, get_intrinsic (ctx, simd_op_to_intrins (ins->opcode)), &v, 1, dname);
                        break;
                }
 
@@ -5888,7 +5980,7 @@ process_bb (EmitContext *ctx, MonoBasicBlock *bb)
                        args [1] = rhs;
                        args [2] = LLVMConstInt (LLVMInt8Type (), ins->inst_c0, FALSE);
 
-                       values [ins->dreg] = LLVMBuildCall (builder, LLVMGetNamedFunction (lmodule, simd_op_to_intrins (ins->opcode)), args, 3, dname);
+                       values [ins->dreg] = LLVMBuildCall (builder, get_intrinsic (ctx, simd_op_to_intrins (ins->opcode)), args, 3, dname);
                        break;
                }
 
@@ -5910,7 +6002,7 @@ process_bb (EmitContext *ctx, MonoBasicBlock *bb)
                        args [0] = lhs;
                        args [1] = LLVMConstInt (LLVMInt32Type (), ins->inst_imm, FALSE);
 
-                       values [ins->dreg] = LLVMBuildCall (builder, LLVMGetNamedFunction (lmodule, simd_op_to_intrins (ins->opcode)), args, 2, dname);
+                       values [ins->dreg] = LLVMBuildCall (builder, get_intrinsic (ctx, simd_op_to_intrins (ins->opcode)), args, 2, dname);
                        break;
                }
 
@@ -5927,7 +6019,7 @@ process_bb (EmitContext *ctx, MonoBasicBlock *bb)
                        args [0] = lhs;
                        args [1] = values [ins->sreg2];
 
-                       values [ins->dreg] = LLVMBuildCall (builder, LLVMGetNamedFunction (lmodule, simd_op_to_intrins (ins->opcode)), args, 2, dname);
+                       values [ins->dreg] = LLVMBuildCall (builder, get_intrinsic (ctx, simd_op_to_intrins (ins->opcode)), args, 2, dname);
                        break;
                }
 
@@ -6215,7 +6307,17 @@ process_bb (EmitContext *ctx, MonoBasicBlock *bb)
                                if (ctx->cfg->compile_aot) {
                                        callee = get_callee (ctx, LLVMFunctionType (LLVMVoidType (), NULL, 0, FALSE), MONO_PATCH_INFO_INTERNAL_METHOD, "llvm_resume_unwind_trampoline");
                                } else {
+#if LLVM_API_VERSION > 100
+                                       MonoJitICallInfo *info;
+
+                                       info = mono_find_jit_icall_by_name ("llvm_resume_unwind_trampoline");
+                                       g_assert (info);
+                                       gpointer target = (void*)info->func;
+                                       LLVMTypeRef icall_sig = LLVMFunctionType (LLVMVoidType (), NULL, 0, FALSE);
+                                       callee = emit_jit_callee (ctx, "llvm_resume_unwind_trampoline", icall_sig, target);
+#else
                                        callee = LLVMGetNamedFunction (lmodule, "llvm_resume_unwind_trampoline");
+#endif
                                }
                                LLVMBuildCall (builder, callee, NULL, 0, "");
                                LLVMBuildUnreachable (builder);
@@ -6396,6 +6498,7 @@ free_ctx (EmitContext *ctx)
        g_free (ctx->bblocks);
        g_hash_table_destroy (ctx->region_to_handler);
        g_hash_table_destroy (ctx->clause_to_handler);
+       g_hash_table_destroy (ctx->jit_callees);
        g_free (ctx->method_name);
        g_ptr_array_free (ctx->bblock_list, TRUE);
 
@@ -6454,6 +6557,7 @@ mono_llvm_emit_method (MonoCompile *cfg)
        ctx->region_to_handler = g_hash_table_new (NULL, NULL);
        ctx->clause_to_handler = g_hash_table_new (NULL, NULL);
        ctx->method_to_callers = g_hash_table_new (NULL, NULL);
+       ctx->jit_callees = g_hash_table_new (NULL, NULL);
        if (cfg->compile_aot) {
                ctx->module = &aot_module;
 
@@ -6487,7 +6591,11 @@ mono_llvm_emit_method (MonoCompile *cfg)
        ctx->method_name = method_name;
        ctx->is_linkonce = is_linkonce;
 
+#if LLVM_API_VERSION > 100
+       ctx->lmodule = LLVMModuleCreateWithName ("jit-module");
+#else
        ctx->lmodule = ctx->module->lmodule;
+#endif
        ctx->llvm_only = ctx->module->llvm_only;
 
        emit_method_inner (ctx);
@@ -6595,7 +6703,11 @@ emit_method_inner (EmitContext *ctx)
                        LLVMSetVisibility (method, LLVMDefaultVisibility);
                }
        } else {
+#if LLVM_API_VERSION > 100
+               LLVMSetLinkage (method, LLVMExternalLinkage);
+#else
                LLVMSetLinkage (method, LLVMPrivateLinkage);
+#endif
        }
 
        if (cfg->method->save_lmf && !cfg->llvm_only) {
@@ -6994,6 +7106,46 @@ emit_method_inner (EmitContext *ctx)
 #endif
        } else {
                //LLVMVerifyFunction(method, 0);
+#if LLVM_API_VERSION > 100
+               MonoDomain *domain = mono_domain_get ();
+               MonoJitDomainInfo *domain_info;
+               int nvars = g_hash_table_size (ctx->jit_callees);
+               LLVMValueRef *callee_vars = g_new0 (LLVMValueRef, nvars); 
+               gpointer *callee_addrs = g_new0 (gpointer, nvars);
+               GHashTableIter iter;
+               LLVMValueRef var;
+               MonoMethod *callee;
+               gpointer eh_frame;
+
+               /*
+                * Compute the addresses of the LLVM globals pointing to the
+                * methods called by the current method. Pass it to the trampoline
+                * code so it can update them after their corresponding method was
+                * compiled.
+                */
+               g_hash_table_iter_init (&iter, ctx->jit_callees);
+               i = 0;
+               while (g_hash_table_iter_next (&iter, NULL, (void**)&var))
+                       callee_vars [i ++] = var;
+
+               cfg->native_code = mono_llvm_compile_method (ctx->module->mono_ee, ctx->lmethod, nvars, callee_vars, callee_addrs, &eh_frame);
+
+               decode_llvm_eh_info (ctx, eh_frame);
+
+               mono_domain_lock (domain);
+               domain_info = domain_jit_info (domain);
+               if (!domain_info->llvm_jit_callees)
+                       domain_info->llvm_jit_callees = g_hash_table_new (NULL, NULL);
+               g_hash_table_iter_init (&iter, ctx->jit_callees);
+               i = 0;
+               while (g_hash_table_iter_next (&iter, (void**)&callee, (void**)&var)) {
+                       GSList *addrs = g_hash_table_lookup (domain_info->llvm_jit_callees, callee);
+                       addrs = g_slist_prepend (addrs, callee_addrs [i]);
+                       g_hash_table_insert (domain_info->llvm_jit_callees, callee, addrs);
+                       i ++;
+               }
+               mono_domain_unlock (domain);
+#else
                mono_llvm_optimize_method (ctx->module->mono_ee, ctx->lmethod);
 
                if (cfg->verbose_level > 1)
@@ -7003,6 +7155,7 @@ emit_method_inner (EmitContext *ctx)
 
                /* Set by emit_cb */
                g_assert (cfg->code_len);
+#endif
        }
 
        if (ctx->module->method_to_lmethod)
@@ -7242,6 +7395,90 @@ exception_cb (void *data)
        g_free (type_info);
 }
 
+#if LLVM_API_VERSION > 100
+/*
+ * decode_llvm_eh_info:
+ *
+ *   Decode the EH table emitted by llvm in jit mode, and store
+ * the result into cfg.
+ */
+static void
+decode_llvm_eh_info (EmitContext *ctx, gpointer eh_frame)
+{
+       MonoCompile *cfg = ctx->cfg;
+       guint8 *cie, *fde;
+       int fde_len;
+       MonoLLVMFDEInfo info;
+       MonoJitExceptionInfo *ei;
+       guint8 *p = eh_frame;
+       int version, fde_count, fde_offset;
+       guint32 ei_len, i, nested_len;
+       gpointer *type_info;
+       gint32 *table;
+
+       /*
+        * Decode the one element EH table emitted by the MonoException class
+        * in llvm.
+        */
+
+       /* Similar to decode_llvm_mono_eh_frame () in aot-runtime.c */
+
+       version = *p;
+       g_assert (version == 3);
+       p ++;
+       p ++;
+       p = (guint8 *)ALIGN_PTR_TO (p, 4);
+
+       fde_count = *(guint32*)p;
+       p += 4;
+       table = (gint32*)p;
+
+       g_assert (fde_count == 1);
+
+       /* The only table entry */
+       fde_offset = table [1];
+       table += 2;
+       /* Extra entry */
+       cfg->code_len = table [0];
+       fde_len = table [1] - fde_offset;
+       table += 2;
+
+       fde = (guint8*)eh_frame + fde_offset;
+       cie = (guint8*)table;
+
+       mono_unwind_decode_llvm_mono_fde (fde, fde_len, cie, cfg->native_code, &info);
+
+       cfg->encoded_unwind_ops = info.unw_info;
+       cfg->encoded_unwind_ops_len = info.unw_info_len;
+       if (cfg->verbose_level > 1)
+               mono_print_unwind_info (cfg->encoded_unwind_ops, cfg->encoded_unwind_ops_len);
+       if (info.this_reg != -1) {
+               cfg->llvm_this_reg = info.this_reg;
+               cfg->llvm_this_offset = info.this_offset;
+       }
+
+       ei = info.ex_info;
+       ei_len = info.ex_info_len;
+       type_info = info.type_info;
+
+       // Nested clauses are currently disabled
+       nested_len = 0;
+
+       cfg->llvm_ex_info = (MonoJitExceptionInfo*)mono_mempool_alloc0 (cfg->mempool, (ei_len + nested_len) * sizeof (MonoJitExceptionInfo));
+       cfg->llvm_ex_info_len = ei_len + nested_len;
+       memcpy (cfg->llvm_ex_info, ei, ei_len * sizeof (MonoJitExceptionInfo));
+       /* Fill the rest of the information from the type info */
+       for (i = 0; i < ei_len; ++i) {
+               gint32 clause_index = *(gint32*)type_info [i];
+               MonoExceptionClause *clause = &cfg->header->clauses [clause_index];
+
+               cfg->llvm_ex_info [i].flags = clause->flags;
+               cfg->llvm_ex_info [i].data.catch_class = clause->data.catch_class;
+               cfg->llvm_ex_info [i].clause_index = clause_index;
+       }
+}
+#endif
+
 static char*
 dlsym_cb (const char *name, void **symbol)
 {
@@ -7282,226 +7519,478 @@ AddFunc2 (LLVMModuleRef module, const char *name, LLVMTypeRef ret_type, LLVMType
        AddFunc (module, name, ret_type, param_types, 2);
 }
 
+typedef enum {
+       INTRINS_MEMSET,
+       INTRINS_MEMCPY,
+       INTRINS_SADD_OVF_I32,
+       INTRINS_UADD_OVF_I32,
+       INTRINS_SSUB_OVF_I32,
+       INTRINS_USUB_OVF_I32,
+       INTRINS_SMUL_OVF_I32,
+       INTRINS_UMUL_OVF_I32,
+       INTRINS_SADD_OVF_I64,
+       INTRINS_UADD_OVF_I64,
+       INTRINS_SSUB_OVF_I64,
+       INTRINS_USUB_OVF_I64,
+       INTRINS_SMUL_OVF_I64,
+       INTRINS_UMUL_OVF_I64,
+       INTRINS_SIN,
+       INTRINS_COS,
+       INTRINS_SQRT,
+       INTRINS_FABS,
+       INTRINS_EXPECT_I8,
+       INTRINS_EXPECT_I1,
+#if defined(TARGET_AMD64) || defined(TARGET_X86)
+       INTRINS_SSE_PMOVMSKB,
+       INTRINS_SSE_PSRLI_W,
+       INTRINS_SSE_PSRAI_W,
+       INTRINS_SSE_PSLLI_W,
+       INTRINS_SSE_PSRLI_D,
+       INTRINS_SSE_PSRAI_D,
+       INTRINS_SSE_PSLLI_D,
+       INTRINS_SSE_PSRLI_Q,
+       INTRINS_SSE_PSLLI_Q,
+       INTRINS_SSE_SQRT_PD,
+       INTRINS_SSE_SQRT_PS,
+       INTRINS_SSE_RSQRT_PS,
+       INTRINS_SSE_RCP_PS,
+       INTRINS_SSE_CVTTPD2DQ,
+       INTRINS_SSE_CVTTPS2DQ,
+       INTRINS_SSE_CVTDQ2PD,
+       INTRINS_SSE_CVTDQ2PS,
+       INTRINS_SSE_CVTPD2DQ,
+       INTRINS_SSE_CVTPS2DQ,
+       INTRINS_SSE_CVTPD2PS,
+       INTRINS_SSE_CVTPS2PD,
+       INTRINS_SSE_CMPPD,
+       INTRINS_SSE_CMPPS,
+       INTRINS_SSE_PACKSSWB,
+       INTRINS_SSE_PACKUSWB,
+       INTRINS_SSE_PACKSSDW,
+       INTRINS_SSE_PACKUSDW,
+       INTRINS_SSE_MINPS,
+       INTRINS_SSE_MAXPS,
+       INTRINS_SSE_HADDPS,
+       INTRINS_SSE_HSUBPS,
+       INTRINS_SSE_ADDSUBPS,
+       INTRINS_SSE_MINPD,
+       INTRINS_SSE_MAXPD,
+       INTRINS_SSE_HADDPD,
+       INTRINS_SSE_HSUBPD,
+       INTRINS_SSE_ADDSUBPD,
+       INTRINS_SSE_PMINUD,
+       INTRINS_SSE_PMAXUD,
+       INTRINS_SSE_PMINUW,
+       INTRINS_SSE_PMINSW,
+       INTRINS_SSE_PMAXUW,
+       INTRINS_SSE_PADDSW,
+       INTRINS_SSE_PSUBSW,
+       INTRINS_SSE_PADDUSW,
+       INTRINS_SSE_PSUBUSW,
+       INTRINS_SSE_PAVGW,
+       INTRINS_SSE_PMULHW,
+       INTRINS_SSE_PMULHU,
+       INTRINS_SSE_PMINUB,
+       INTRINS_SSE_PMAXUB,
+       INTRINS_SE_PADDSB,
+       INTRINS_SSE_PSUBSB,
+       INTRINS_SSE_PADDUSB,
+       INTRINS_SSE_PSUBUSB,
+       INTRINS_SSE_PAVGB,
+       INTRINS_SSE_PAUSE,
+#endif
+       INTRINS_NUM
+} IntrinsicId;
+
+typedef struct {
+       IntrinsicId id;
+       const char *name;
+} IntrinsicDesc;
+
+static IntrinsicDesc intrinsics[] = {
+       {INTRINS_MEMSET, "llvm.memset.p0i8.i32"},
+       {INTRINS_MEMCPY, "llvm.memcpy.p0i8.p0i8.i32"},
+       {INTRINS_SADD_OVF_I32, "llvm.sadd.with.overflow.i32"},
+       {INTRINS_UADD_OVF_I32, "llvm.uadd.with.overflow.i32"},
+       {INTRINS_SSUB_OVF_I32, "llvm.ssub.with.overflow.i32"},
+       {INTRINS_USUB_OVF_I32, "llvm.usub.with.overflow.i32"},
+       {INTRINS_SMUL_OVF_I32, "llvm.smul.with.overflow.i32"},
+       {INTRINS_UMUL_OVF_I32, "llvm.umul.with.overflow.i32"},
+       {INTRINS_SADD_OVF_I64, "llvm.sadd.with.overflow.i64"},
+       {INTRINS_UADD_OVF_I64, "llvm.uadd.with.overflow.i64"},
+       {INTRINS_SSUB_OVF_I64, "llvm.ssub.with.overflow.i64"},
+       {INTRINS_USUB_OVF_I64, "llvm.usub.with.overflow.i64"},
+       {INTRINS_SMUL_OVF_I64, "llvm.smul.with.overflow.i64"},
+       {INTRINS_UMUL_OVF_I64, "llvm.umul.with.overflow.i64"},
+       {INTRINS_SIN, "llvm.sin.f64"},
+       {INTRINS_COS, "llvm.cos.f64"},
+       {INTRINS_SQRT, "llvm.sqrt.f64"},
+       /* This isn't an intrinsic, instead llvm seems to special case it by name */
+       {INTRINS_FABS, "fabs"},
+       {INTRINS_EXPECT_I8, "llvm.expect.i8"},
+       {INTRINS_EXPECT_I1, "llvm.expect.i1"},
+#if defined(TARGET_AMD64) || defined(TARGET_X86)
+       {INTRINS_SSE_PMOVMSKB, "llvm.x86.sse2.pmovmskb.128"},
+       {INTRINS_SSE_PSRLI_W, "llvm.x86.sse2.psrli.w"},
+       {INTRINS_SSE_PSRAI_W, "llvm.x86.sse2.psrai.w"},
+       {INTRINS_SSE_PSLLI_W, "llvm.x86.sse2.pslli.w"},
+       {INTRINS_SSE_PSRLI_D, "llvm.x86.sse2.psrli.d"},
+       {INTRINS_SSE_PSRAI_D, "llvm.x86.sse2.psrai.d"},
+       {INTRINS_SSE_PSLLI_D, "llvm.x86.sse2.pslli.d"},
+       {INTRINS_SSE_PSRLI_Q, "llvm.x86.sse2.psrli.q"},
+       {INTRINS_SSE_PSLLI_Q, "llvm.x86.sse2.pslli.q"},
+       {INTRINS_SSE_SQRT_PD, "llvm.x86.sse2.sqrt.pd"},
+       {INTRINS_SSE_SQRT_PS, "llvm.x86.sse.sqrt.ps"},
+       {INTRINS_SSE_RSQRT_PS, "llvm.x86.sse.rsqrt.ps"},
+       {INTRINS_SSE_RCP_PS, "llvm.x86.sse.rcp.ps"},
+       {INTRINS_SSE_CVTTPD2DQ, "llvm.x86.sse2.cvttpd2dq"},
+       {INTRINS_SSE_CVTTPS2DQ, "llvm.x86.sse2.cvttps2dq"},
+       {INTRINS_SSE_CVTDQ2PD, "llvm.x86.sse2.cvtdq2pd"},
+       {INTRINS_SSE_CVTDQ2PS, "llvm.x86.sse2.cvtdq2ps"},
+       {INTRINS_SSE_CVTPD2DQ, "llvm.x86.sse2.cvtpd2dq"},
+       {INTRINS_SSE_CVTPS2DQ, "llvm.x86.sse2.cvtps2dq"},
+       {INTRINS_SSE_CVTPD2PS, "llvm.x86.sse2.cvtpd2ps"},
+       {INTRINS_SSE_CVTPS2PD, "llvm.x86.sse2.cvtps2pd"},
+       {INTRINS_SSE_CMPPD, "llvm.x86.sse2.cmp.pd"},
+       {INTRINS_SSE_CMPPS, "llvm.x86.sse.cmp.ps"},
+       {INTRINS_SSE_PACKSSWB, "llvm.x86.sse2.packsswb.128"},
+       {INTRINS_SSE_PACKUSWB, "llvm.x86.sse2.packuswb.128"},
+       {INTRINS_SSE_PACKSSDW, "llvm.x86.sse2.packssdw.128"},
+       {INTRINS_SSE_PACKUSDW, "llvm.x86.sse41.packusdw"},
+       {INTRINS_SSE_MINPS, "llvm.x86.sse.min.ps"},
+       {INTRINS_SSE_MAXPS, "llvm.x86.sse.max.ps"},
+       {INTRINS_SSE_HADDPS, "llvm.x86.sse3.hadd.ps"},
+       {INTRINS_SSE_HSUBPS, "llvm.x86.sse3.hsub.ps"},
+       {INTRINS_SSE_ADDSUBPS, "llvm.x86.sse3.addsub.ps"},
+       {INTRINS_SSE_MINPD, "llvm.x86.sse2.min.pd"},
+       {INTRINS_SSE_MAXPD, "llvm.x86.sse2.max.pd"},
+       {INTRINS_SSE_HADDPD, "llvm.x86.sse3.hadd.pd"},
+       {INTRINS_SSE_HSUBPD, "llvm.x86.sse3.hsub.pd"},
+       {INTRINS_SSE_ADDSUBPD, "llvm.x86.sse3.addsub.pd"},
+       {INTRINS_SSE_PMINUD, "llvm.x86.sse41.pminud"},
+       {INTRINS_SSE_PMAXUD, "llvm.x86.sse41.pmaxud"},
+       {INTRINS_SSE_PMINUW, "llvm.x86.sse41.pminuw"},
+       {INTRINS_SSE_PMINSW, "llvm.x86.sse2.pmins.w"},
+       {INTRINS_SSE_PMAXUW, "llvm.x86.sse41.pmaxuw"},
+       {INTRINS_SSE_PADDSW, "llvm.x86.sse2.padds.w"},
+       {INTRINS_SSE_PSUBSW, "llvm.x86.sse2.psubs.w"},
+       {INTRINS_SSE_PADDUSW, "llvm.x86.sse2.paddus.w"},
+       {INTRINS_SSE_PSUBUSW, "llvm.x86.sse2.psubus.w"},
+       {INTRINS_SSE_PAVGW, "llvm.x86.sse2.pavg.w"},
+       {INTRINS_SSE_PMULHW, "llvm.x86.sse2.pmulh.w"},
+       {INTRINS_SSE_PMULHU, "llvm.x86.sse2.pmulhu.w"},
+       {INTRINS_SSE_PMINUB, "llvm.x86.sse2.pminu.b"},
+       {INTRINS_SSE_PMAXUB, "llvm.x86.sse2.pmaxu.b"},
+       {INTRINS_SE_PADDSB, "llvm.x86.sse2.padds.b"},
+       {INTRINS_SSE_PSUBSB, "llvm.x86.sse2.psubs.b"},
+       {INTRINS_SSE_PADDUSB, "llvm.x86.sse2.paddus.b"},
+       {INTRINS_SSE_PSUBUSB, "llvm.x86.sse2.psubus.b"},
+       {INTRINS_SSE_PAVGB, "llvm.x86.sse2.pavg.b"},
+       {INTRINS_SSE_PAUSE, "llvm.x86.sse2.pause"}
+#endif
+};
+
 static void
-add_intrinsics (LLVMModuleRef module)
+add_sse_binary (LLVMModuleRef module, const char *name, int type)
 {
-       /* Emit declarations of instrinsics */
-       /*
-        * It would be nicer to emit only the intrinsics actually used, but LLVM's Module
-        * type doesn't seem to do any locking.
-        */
-       {
-               LLVMTypeRef params [] = { LLVMPointerType (LLVMInt8Type (), 0), LLVMInt8Type (), LLVMInt32Type (), LLVMInt32Type (), LLVMInt1Type () };
-
-               memset_param_count = 5;
-               memset_func_name = "llvm.memset.p0i8.i32";
+       LLVMTypeRef ret_type = type_to_simd_type (type);
+       AddFunc2 (module, name, ret_type, ret_type, ret_type);
+}
 
-               AddFunc (module, memset_func_name, LLVMVoidType (), params, memset_param_count);
-       }
+static void
+add_intrinsic (LLVMModuleRef module, int id)
+{
+       const char *name;
+       LLVMTypeRef ret_type, arg_types [16];
 
-       {
-               LLVMTypeRef params [] = { LLVMPointerType (LLVMInt8Type (), 0), LLVMPointerType (LLVMInt8Type (), 0), LLVMInt32Type (), LLVMInt32Type (), LLVMInt1Type () };
+       name = g_hash_table_lookup (intrins_id_to_name, GINT_TO_POINTER (id));
+       g_assert (name);
 
-               memcpy_param_count = 5;
-               memcpy_func_name = "llvm.memcpy.p0i8.p0i8.i32";
+       switch (id) {
+       case INTRINS_MEMSET: {
+               LLVMTypeRef params [] = { LLVMPointerType (LLVMInt8Type (), 0), LLVMInt8Type (), LLVMInt32Type (), LLVMInt32Type (), LLVMInt1Type () };
 
-               AddFunc (module, memcpy_func_name, LLVMVoidType (), params, memcpy_param_count);
+               AddFunc (module, name, LLVMVoidType (), params, 5);
+               break;
        }
+       case INTRINS_MEMCPY: {
+               LLVMTypeRef params [] = { LLVMPointerType (LLVMInt8Type (), 0), LLVMPointerType (LLVMInt8Type (), 0), LLVMInt32Type (), LLVMInt32Type (), LLVMInt1Type () };
 
-       {
-               LLVMTypeRef params [] = { LLVMDoubleType () };
-
-               AddFunc (module, "llvm.sin.f64", LLVMDoubleType (), params, 1);
-               AddFunc (module, "llvm.cos.f64", LLVMDoubleType (), params, 1);
-               AddFunc (module, "llvm.sqrt.f64", LLVMDoubleType (), params, 1);
-
-               /* This isn't an intrinsic, instead llvm seems to special case it by name */
-               AddFunc (module, "fabs", LLVMDoubleType (), params, 1);
+               AddFunc (module, name, LLVMVoidType (), params, 5);
+               break;
        }
-
-       {
+       case INTRINS_SADD_OVF_I32:
+       case INTRINS_UADD_OVF_I32:
+       case INTRINS_SSUB_OVF_I32:
+       case INTRINS_USUB_OVF_I32:
+       case INTRINS_SMUL_OVF_I32:
+       case INTRINS_UMUL_OVF_I32: {
                LLVMTypeRef ovf_res_i32 [] = { LLVMInt32Type (), LLVMInt1Type () };
                LLVMTypeRef params [] = { LLVMInt32Type (), LLVMInt32Type () };
                LLVMTypeRef ret_type = LLVMStructType (ovf_res_i32, 2, FALSE);
 
-               AddFunc (module, "llvm.sadd.with.overflow.i32", ret_type, params, 2);
-               AddFunc (module, "llvm.sadd.with.overflow.i32", ret_type, params, 2);
-               AddFunc (module, "llvm.uadd.with.overflow.i32", ret_type, params, 2);
-               AddFunc (module, "llvm.ssub.with.overflow.i32", ret_type, params, 2);
-               AddFunc (module, "llvm.usub.with.overflow.i32", ret_type, params, 2);
-               AddFunc (module, "llvm.smul.with.overflow.i32", ret_type, params, 2);
-               AddFunc (module, "llvm.umul.with.overflow.i32", ret_type, params, 2);
+               AddFunc (module, name, ret_type, params, 2);
+               break;
        }
-
-       {
+       case INTRINS_SADD_OVF_I64:
+       case INTRINS_UADD_OVF_I64:
+       case INTRINS_SSUB_OVF_I64:
+       case INTRINS_USUB_OVF_I64:
+       case INTRINS_SMUL_OVF_I64:
+       case INTRINS_UMUL_OVF_I64: {
                LLVMTypeRef ovf_res_i64 [] = { LLVMInt64Type (), LLVMInt1Type () };
                LLVMTypeRef params [] = { LLVMInt64Type (), LLVMInt64Type () };
                LLVMTypeRef ret_type = LLVMStructType (ovf_res_i64, 2, FALSE);
 
-               AddFunc (module, "llvm.sadd.with.overflow.i64", ret_type, params, 2);
-               AddFunc (module, "llvm.uadd.with.overflow.i64", ret_type, params, 2);
-               AddFunc (module, "llvm.ssub.with.overflow.i64", ret_type, params, 2);
-               AddFunc (module, "llvm.usub.with.overflow.i64", ret_type, params, 2);
-               AddFunc (module, "llvm.smul.with.overflow.i64", ret_type, params, 2);
-               AddFunc (module, "llvm.umul.with.overflow.i64", ret_type, params, 2);
+               AddFunc (module, name, ret_type, params, 2);
+               break;
        }
+       case INTRINS_SIN:
+       case INTRINS_COS:
+       case INTRINS_SQRT:
+       case INTRINS_FABS: {
+               LLVMTypeRef params [] = { LLVMDoubleType () };
 
-       AddFunc2 (module, "llvm.expect.i8", LLVMInt8Type (), LLVMInt8Type (), LLVMInt8Type ());
-       AddFunc2 (module, "llvm.expect.i1", LLVMInt1Type (), LLVMInt1Type (), LLVMInt1Type ());
-
-       /* EH intrinsics */
-       {
-               AddFunc (module, "mono_personality", LLVMVoidType (), NULL, 0);
-
-               AddFunc (module, "llvm_resume_unwind_trampoline", LLVMVoidType (), NULL, 0);
+               AddFunc (module, name, LLVMDoubleType (), params, 1);
+               break;
        }
-
-       /* SSE intrinsics */
-#if defined(TARGET_X86) || defined(TARGET_AMD64)
-       {
-               LLVMTypeRef ret_type, arg_types [16];
-
-               /* Binary ops */
-               ret_type = type_to_simd_type (MONO_TYPE_I4);
-               arg_types [0] = ret_type;
-               arg_types [1] = ret_type;
-               AddFunc (module, "llvm.x86.sse41.pminud", ret_type, arg_types, 2);
-               AddFunc (module, "llvm.x86.sse41.pmaxud", ret_type, arg_types, 2);
-
+       case INTRINS_EXPECT_I8:
+               AddFunc2 (module, name, LLVMInt8Type (), LLVMInt8Type (), LLVMInt8Type ());
+               break;
+       case INTRINS_EXPECT_I1:
+               AddFunc2 (module, name, LLVMInt1Type (), LLVMInt1Type (), LLVMInt1Type ());
+               break;
+#if defined(TARGET_AMD64) || defined(TARGET_X86)
+       case INTRINS_SSE_PMOVMSKB:
+               /* pmovmskb */
+               ret_type = LLVMInt32Type ();
+               arg_types [0] = type_to_simd_type (MONO_TYPE_I1);
+               AddFunc (module, name, ret_type, arg_types, 1);
+               break;
+       case INTRINS_SSE_PSRLI_W:
+       case INTRINS_SSE_PSRAI_W:
+       case INTRINS_SSE_PSLLI_W:
+               /* shifts */
                ret_type = type_to_simd_type (MONO_TYPE_I2);
                arg_types [0] = ret_type;
-               arg_types [1] = ret_type;
-               AddFunc (module, "llvm.x86.sse41.pminuw", ret_type, arg_types, 2);
-               AddFunc (module, "llvm.x86.sse2.pmins.w", ret_type, arg_types, 2);
-               AddFunc (module, "llvm.x86.sse41.pmaxuw", ret_type, arg_types, 2);
-               AddFunc (module, "llvm.x86.sse2.padds.w", ret_type, arg_types, 2);
-               AddFunc (module, "llvm.x86.sse2.psubs.w", ret_type, arg_types, 2);
-               AddFunc (module, "llvm.x86.sse2.paddus.w", ret_type, arg_types, 2);
-               AddFunc (module, "llvm.x86.sse2.psubus.w", ret_type, arg_types, 2);
-               AddFunc (module, "llvm.x86.sse2.pavg.w", ret_type, arg_types, 2);
-               AddFunc (module, "llvm.x86.sse2.pmulh.w", ret_type, arg_types, 2);
-               AddFunc (module, "llvm.x86.sse2.pmulhu.w", ret_type, arg_types, 2);
-
-               ret_type = type_to_simd_type (MONO_TYPE_I1);
+               arg_types [1] = LLVMInt32Type ();
+               AddFunc (module, name, ret_type, arg_types, 2);
+               break;
+       case INTRINS_SSE_PSRLI_D:
+       case INTRINS_SSE_PSRAI_D:
+       case INTRINS_SSE_PSLLI_D:
+               ret_type = type_to_simd_type (MONO_TYPE_I4);
                arg_types [0] = ret_type;
-               arg_types [1] = ret_type;
-               AddFunc (module, "llvm.x86.sse2.pminu.b", ret_type, arg_types, 2);
-               AddFunc (module, "llvm.x86.sse2.pmaxu.b", ret_type, arg_types, 2);
-               AddFunc (module, "llvm.x86.sse2.padds.b", ret_type, arg_types, 2);
-               AddFunc (module, "llvm.x86.sse2.psubs.b", ret_type, arg_types, 2);
-               AddFunc (module, "llvm.x86.sse2.paddus.b", ret_type, arg_types, 2);
-               AddFunc (module, "llvm.x86.sse2.psubus.b", ret_type, arg_types, 2);
-               AddFunc (module, "llvm.x86.sse2.pavg.b", ret_type, arg_types, 2);
-
+               arg_types [1] = LLVMInt32Type ();
+               AddFunc (module, name, ret_type, arg_types, 2);
+               break;
+       case INTRINS_SSE_PSRLI_Q:
+       case INTRINS_SSE_PSLLI_Q:
+               ret_type = type_to_simd_type (MONO_TYPE_I8);
+               arg_types [0] = ret_type;
+               arg_types [1] = LLVMInt32Type ();
+               AddFunc (module, name, ret_type, arg_types, 2);
+               break;
+       case INTRINS_SSE_SQRT_PD:
+               /* Unary ops */
                ret_type = type_to_simd_type (MONO_TYPE_R8);
                arg_types [0] = ret_type;
-               arg_types [1] = ret_type;
-               AddFunc (module, "llvm.x86.sse2.min.pd", ret_type, arg_types, 2);
-               AddFunc (module, "llvm.x86.sse2.max.pd", ret_type, arg_types, 2);
-               AddFunc (module, "llvm.x86.sse3.hadd.pd", ret_type, arg_types, 2);
-               AddFunc (module, "llvm.x86.sse3.hsub.pd", ret_type, arg_types, 2);
-               AddFunc (module, "llvm.x86.sse3.addsub.pd", ret_type, arg_types, 2);
-
+               AddFunc (module, name, ret_type, arg_types, 1);
+               break;
+       case INTRINS_SSE_SQRT_PS:
                ret_type = type_to_simd_type (MONO_TYPE_R4);
                arg_types [0] = ret_type;
-               arg_types [1] = ret_type;
-               AddFunc (module, "llvm.x86.sse.min.ps", ret_type, arg_types, 2);
-               AddFunc (module, "llvm.x86.sse.max.ps", ret_type, arg_types, 2);
-               AddFunc (module, "llvm.x86.sse3.hadd.ps", ret_type, arg_types, 2);
-               AddFunc (module, "llvm.x86.sse3.hsub.ps", ret_type, arg_types, 2);
-               AddFunc (module, "llvm.x86.sse3.addsub.ps", ret_type, arg_types, 2);
-
-               /* pack */
-               ret_type = type_to_simd_type (MONO_TYPE_I1);
-               arg_types [0] = type_to_simd_type (MONO_TYPE_I2);
-               arg_types [1] = type_to_simd_type (MONO_TYPE_I2);
-               AddFunc (module, "llvm.x86.sse2.packsswb.128", ret_type, arg_types, 2);
-               AddFunc (module, "llvm.x86.sse2.packuswb.128", ret_type, arg_types, 2);
-               ret_type = type_to_simd_type (MONO_TYPE_I2);
-               arg_types [0] = type_to_simd_type (MONO_TYPE_I4);
-               arg_types [1] = type_to_simd_type (MONO_TYPE_I4);
-               AddFunc (module, "llvm.x86.sse2.packssdw.128", ret_type, arg_types, 2);
-               AddFunc (module, "llvm.x86.sse41.packusdw", ret_type, arg_types, 2);
-
-               /* cmp pd/ps */
-               ret_type = type_to_simd_type (MONO_TYPE_R8);
+               AddFunc (module, name, ret_type, arg_types, 1);
+               break;
+       case INTRINS_SSE_RSQRT_PS:
+               ret_type = type_to_simd_type (MONO_TYPE_R4);
                arg_types [0] = ret_type;
-               arg_types [1] = ret_type;
-               arg_types [2] = LLVMInt8Type ();
-               AddFunc (module, "llvm.x86.sse2.cmp.pd", ret_type, arg_types, 3);
+               AddFunc (module, name, ret_type, arg_types, 1);
+               break;
+       case INTRINS_SSE_RCP_PS:
                ret_type = type_to_simd_type (MONO_TYPE_R4);
                arg_types [0] = ret_type;
-               arg_types [1] = ret_type;
-               arg_types [2] = LLVMInt8Type ();
-               AddFunc (module, "llvm.x86.sse.cmp.ps", ret_type, arg_types, 3);
-
+               AddFunc (module, name, ret_type, arg_types, 1);
+               break;
+       case INTRINS_SSE_CVTTPD2DQ:
+               ret_type = type_to_simd_type (MONO_TYPE_I4);
+               arg_types [0] = type_to_simd_type (MONO_TYPE_R8);
+               AddFunc (module, name, ret_type, arg_types, 1);
+               break;
+       case INTRINS_SSE_CVTTPS2DQ:
+               ret_type = type_to_simd_type (MONO_TYPE_I4);
+               arg_types [0] = type_to_simd_type (MONO_TYPE_R4);
+               AddFunc (module, name, ret_type, arg_types, 1);
+               break;
+       case INTRINS_SSE_CVTDQ2PD:
                /* Conversion ops */
                ret_type = type_to_simd_type (MONO_TYPE_R8);
                arg_types [0] = type_to_simd_type (MONO_TYPE_I4);
-               AddFunc (module, "llvm.x86.sse2.cvtdq2pd", ret_type, arg_types, 1);
+               AddFunc (module, name, ret_type, arg_types, 1);
+               break;
+       case INTRINS_SSE_CVTDQ2PS:
                ret_type = type_to_simd_type (MONO_TYPE_R4);
                arg_types [0] = type_to_simd_type (MONO_TYPE_I4);
-               AddFunc (module, "llvm.x86.sse2.cvtdq2ps", ret_type, arg_types, 1);
+               AddFunc (module, name, ret_type, arg_types, 1);
+               break;
+       case INTRINS_SSE_CVTPD2DQ:
                ret_type = type_to_simd_type (MONO_TYPE_I4);
                arg_types [0] = type_to_simd_type (MONO_TYPE_R8);
-               AddFunc (module, "llvm.x86.sse2.cvtpd2dq", ret_type, arg_types, 1);
+               AddFunc (module, name, ret_type, arg_types, 1);
+               break;
+       case INTRINS_SSE_CVTPS2DQ:
                ret_type = type_to_simd_type (MONO_TYPE_I4);
                arg_types [0] = type_to_simd_type (MONO_TYPE_R4);
-               AddFunc (module, "llvm.x86.sse2.cvtps2dq", ret_type, arg_types, 1);
+               AddFunc (module, name, ret_type, arg_types, 1);
+               break;
+       case INTRINS_SSE_CVTPD2PS:
                ret_type = type_to_simd_type (MONO_TYPE_R4);
                arg_types [0] = type_to_simd_type (MONO_TYPE_R8);
-               AddFunc (module, "llvm.x86.sse2.cvtpd2ps", ret_type, arg_types, 1);
+               AddFunc (module, name, ret_type, arg_types, 1);
+               break;
+       case INTRINS_SSE_CVTPS2PD:
                ret_type = type_to_simd_type (MONO_TYPE_R8);
                arg_types [0] = type_to_simd_type (MONO_TYPE_R4);
-               AddFunc (module, "llvm.x86.sse2.cvtps2pd", ret_type, arg_types, 1);
-
-               ret_type = type_to_simd_type (MONO_TYPE_I4);
-               arg_types [0] = type_to_simd_type (MONO_TYPE_R8);
-               AddFunc (module, "llvm.x86.sse2.cvttpd2dq", ret_type, arg_types, 1);
-               ret_type = type_to_simd_type (MONO_TYPE_I4);
-               arg_types [0] = type_to_simd_type (MONO_TYPE_R4);
-               AddFunc (module, "llvm.x86.sse2.cvttps2dq", ret_type, arg_types, 1);
-
-               /* Unary ops */
+               AddFunc (module, name, ret_type, arg_types, 1);
+               break;
+       case INTRINS_SSE_CMPPD:
+               /* cmp pd/ps */
                ret_type = type_to_simd_type (MONO_TYPE_R8);
                arg_types [0] = ret_type;
-               AddFunc (module, "llvm.x86.sse2.sqrt.pd", ret_type, arg_types, 1);
-               ret_type = type_to_simd_type (MONO_TYPE_R4);
-               arg_types [0] = ret_type;
-               AddFunc (module, "llvm.x86.sse.sqrt.ps", ret_type, arg_types, 1);
-               ret_type = type_to_simd_type (MONO_TYPE_R4);
-               arg_types [0] = ret_type;
-               AddFunc (module, "llvm.x86.sse.rsqrt.ps", ret_type, arg_types, 1);
+               arg_types [1] = ret_type;
+               arg_types [2] = LLVMInt8Type ();
+               AddFunc (module, name, ret_type, arg_types, 3);
+               break;
+       case INTRINS_SSE_CMPPS:
                ret_type = type_to_simd_type (MONO_TYPE_R4);
                arg_types [0] = ret_type;
-               AddFunc (module, "llvm.x86.sse.rcp.ps", ret_type, arg_types, 1);
-
-               /* shifts */
+               arg_types [1] = ret_type;
+               arg_types [2] = LLVMInt8Type ();
+               AddFunc (module, name, ret_type, arg_types, 3);
+               break;
+       case INTRINS_SSE_PACKSSWB:
+       case INTRINS_SSE_PACKUSWB:
+       case INTRINS_SSE_PACKSSDW:
+               /* pack */
+               ret_type = type_to_simd_type (MONO_TYPE_I1);
+               arg_types [0] = type_to_simd_type (MONO_TYPE_I2);
+               arg_types [1] = type_to_simd_type (MONO_TYPE_I2);
+               AddFunc (module, name, ret_type, arg_types, 2);
+               break;
+       case INTRINS_SSE_PACKUSDW:
                ret_type = type_to_simd_type (MONO_TYPE_I2);
-               arg_types [0] = ret_type;
-               arg_types [1] = LLVMInt32Type ();
-               AddFunc (module, "llvm.x86.sse2.psrli.w", ret_type, arg_types, 2);
-               AddFunc (module, "llvm.x86.sse2.psrai.w", ret_type, arg_types, 2);
-               AddFunc (module, "llvm.x86.sse2.pslli.w", ret_type, arg_types, 2);
-               ret_type = type_to_simd_type (MONO_TYPE_I4);
-               arg_types [0] = ret_type;
-               arg_types [1] = LLVMInt32Type ();
-               AddFunc (module, "llvm.x86.sse2.psrli.d", ret_type, arg_types, 2);
-               AddFunc (module, "llvm.x86.sse2.psrai.d", ret_type, arg_types, 2);
-               AddFunc (module, "llvm.x86.sse2.pslli.d", ret_type, arg_types, 2);
-               ret_type = type_to_simd_type (MONO_TYPE_I8);
-               arg_types [0] = ret_type;
-               arg_types [1] = LLVMInt32Type ();
-               AddFunc (module, "llvm.x86.sse2.psrli.q", ret_type, arg_types, 2);
-               AddFunc (module, "llvm.x86.sse2.pslli.q", ret_type, arg_types, 2);
+               arg_types [0] = type_to_simd_type (MONO_TYPE_I4);
+               arg_types [1] = type_to_simd_type (MONO_TYPE_I4);
+               AddFunc (module, name, ret_type, arg_types, 2);
+               break;
+               /* SSE Binary ops */
+       case INTRINS_SSE_PMINUD:
+       case INTRINS_SSE_PMAXUD:
+               add_sse_binary (module, name, MONO_TYPE_I4);
+               break;
+       case INTRINS_SSE_PMINUW:
+       case INTRINS_SSE_PMINSW:
+       case INTRINS_SSE_PMAXUW:
+       case INTRINS_SSE_PADDSW:
+       case INTRINS_SSE_PSUBSW:
+       case INTRINS_SSE_PADDUSW:
+       case INTRINS_SSE_PSUBUSW:
+       case INTRINS_SSE_PAVGW:
+       case INTRINS_SSE_PMULHW:
+       case INTRINS_SSE_PMULHU:
+               add_sse_binary (module, name, MONO_TYPE_I2);
+               break;
+       case INTRINS_SSE_MINPS:
+       case INTRINS_SSE_MAXPS:
+       case INTRINS_SSE_HADDPS:
+       case INTRINS_SSE_HSUBPS:
+       case INTRINS_SSE_ADDSUBPS:
+               add_sse_binary (module, name, MONO_TYPE_R4);
+               break;
+       case INTRINS_SSE_MINPD:
+       case INTRINS_SSE_MAXPD:
+       case INTRINS_SSE_HADDPD:
+       case INTRINS_SSE_HSUBPD:
+       case INTRINS_SSE_ADDSUBPD:
+               add_sse_binary (module, name, MONO_TYPE_R8);
+               break;
+       case INTRINS_SSE_PMINUB:
+       case INTRINS_SSE_PMAXUB:
+       case INTRINS_SE_PADDSB:
+       case INTRINS_SSE_PSUBSB:
+       case INTRINS_SSE_PADDUSB:
+       case INTRINS_SSE_PSUBUSB:
+       case INTRINS_SSE_PAVGB:
+               add_sse_binary (module, name, MONO_TYPE_I1);
+               break;
+       case INTRINS_SSE_PAUSE:
+               AddFunc (module, "llvm.x86.sse2.pause", LLVMVoidType (), NULL, 0);
+               break;
+#endif
+       default:
+               g_assert_not_reached ();
+               break;
+       }
+}
 
-               /* pmovmskb */
-               ret_type = LLVMInt32Type ();
-               arg_types [0] = type_to_simd_type (MONO_TYPE_I1);
-               AddFunc (module, "llvm.x86.sse2.pmovmskb.128", ret_type, arg_types, 1);
+static LLVMValueRef
+get_intrinsic (EmitContext *ctx, const char *name)
+{
+#if LLVM_API_VERSION > 100
+       LLVMValueRef res;
+
+       /*
+        * Every method is emitted into its own module so
+        * we can add intrinsics on demand.
+        */
+       res = LLVMGetNamedFunction (ctx->lmodule, name);
+       if (!res) {
+               int id = -1;
+
+               /* No locking needed */
+               id = GPOINTER_TO_INT (g_hash_table_lookup (intrins_name_to_id, name));
+               id --;
+               if (id == -1)
+                       printf ("%s\n", name);
+               g_assert (id != -1);
+               add_intrinsic (ctx->lmodule, id);
+               res = LLVMGetNamedFunction (ctx->lmodule, name);
+               g_assert (res);
        }
 
-       AddFunc (module, "llvm.x86.sse2.pause", LLVMVoidType (), NULL, 0);
+       return res;
+#else
+       LLVMValueRef res;
+
+       res = LLVMGetNamedFunction (ctx->lmodule, name);
+       g_assert (res);
+       return res;
+#endif
+}
+
+static void
+add_intrinsics (LLVMModuleRef module)
+{
+       int i;
+
+       /* Emit declarations of instrinsics */
+       /*
+        * It would be nicer to emit only the intrinsics actually used, but LLVM's Module
+        * type doesn't seem to do any locking.
+        */
+       for (i = 0; i < INTRINS_NUM; ++i)
+               add_intrinsic (module, i);
+
+       /* EH intrinsics */
+       {
+               AddFunc (module, "mono_personality", LLVMVoidType (), NULL, 0);
+
+               AddFunc (module, "llvm_resume_unwind_trampoline", LLVMVoidType (), NULL, 0);
+       }
+
+       /* SSE intrinsics */
+#if defined(TARGET_X86) || defined(TARGET_AMD64)
+
 #endif
 
        /* Load/Store intrinsics */
@@ -7538,13 +8027,25 @@ add_types (MonoLLVMModule *module)
 void
 mono_llvm_init (void)
 {
+       GHashTable *h;
+       int i;
+
        mono_native_tls_alloc (&current_cfg_tls_id, NULL);
+
+       h = g_hash_table_new (NULL, NULL);
+       for (i = 0; i < INTRINS_NUM; ++i)
+               g_hash_table_insert (h, GINT_TO_POINTER (intrinsics [i].id), (gpointer)intrinsics [i].name);
+       intrins_id_to_name = h;
+
+       h = g_hash_table_new (g_str_hash, g_str_equal);
+       for (i = 0; i < INTRINS_NUM; ++i)
+               g_hash_table_insert (h, (gpointer)intrinsics [i].name, GINT_TO_POINTER (intrinsics [i].id + 1));
+       intrins_name_to_id = h;
 }
 
 static void
 init_jit_module (MonoDomain *domain)
 {
-       MonoJitICallInfo *info;
        MonoJitDomainInfo *dinfo;
        MonoLLVMModule *module;
        char *name;
@@ -7573,9 +8074,13 @@ init_jit_module (MonoDomain *domain)
 
        module->llvm_types = g_hash_table_new (NULL, NULL);
 
+#if LLVM_API_VERSION < 100
+       MonoJitICallInfo *info;
+
        info = mono_find_jit_icall_by_name ("llvm_resume_unwind_trampoline");
        g_assert (info);
        LLVMAddGlobalMapping (module->ee, LLVMGetNamedFunction (module->lmodule, "llvm_resume_unwind_trampoline"), (void*)info->func);
+#endif
 
        mono_memory_barrier ();
 
index 7a149b345f297d48dc3dc6c23686e83fbec2044e..cb8b970b827c2b89828f3aa6d239e0b735bad9c5 100644 (file)
@@ -2164,7 +2164,6 @@ mono_jit_free_method (MonoDomain *domain, MonoMethod *method)
                }
                g_slist_free (remove);
        }
-
        mono_domain_unlock (domain);
 
 #ifdef MONO_ARCH_HAVE_INVALIDATE_METHOD
@@ -3519,6 +3518,12 @@ runtime_invoke_info_free (gpointer value)
        g_free (info);
 }
 
+static void
+free_jit_callee_list (gpointer key, gpointer value, gpointer user_data)
+{
+       g_slist_free (value);
+}
+
 static void
 mini_free_jit_domain_info (MonoDomain *domain)
 {
@@ -3549,6 +3554,10 @@ mini_free_jit_domain_info (MonoDomain *domain)
                mono_debugger_agent_free_domain_info (domain);
        if (info->gsharedvt_arg_tramp_hash)
                g_hash_table_destroy (info->gsharedvt_arg_tramp_hash);
+       if (info->llvm_jit_callees) {
+               g_hash_table_foreach (info->llvm_jit_callees, free_jit_callee_list, NULL);
+               g_hash_table_destroy (info->llvm_jit_callees);
+       }
 #ifdef ENABLE_LLVM
        mono_llvm_free_domain_info (domain);
 #endif
index 10cb86ba1a9638a027b1caa4e1f5d5bbd1295bce..fc26dc5201de0b0c1a5fe26680ac50c9ea97594f 100644 (file)
@@ -4490,6 +4490,18 @@ mono_jit_compile_method_inner (MonoMethod *method, MonoDomain *target_domain, in
                }
        }
 
+       /* Update llvm callees */
+       if (domain_jit_info (target_domain)->llvm_jit_callees) {
+               GSList *callees = g_hash_table_lookup (domain_jit_info (target_domain)->llvm_jit_callees, method);
+               GSList *l;
+
+               for (l = callees; l; l = l->next) {
+                       gpointer *addr = (gpointer*)l->data;
+
+                       *addr = code;
+               }
+       }
+
        mono_emit_jit_map (jinfo);
 #endif
        mono_domain_unlock (target_domain);
index dcec9707567346673e0af609312eb6f5f8a3a84e..0081438d78dc428f14c21bacefa023386e57a952 100644 (file)
@@ -354,6 +354,8 @@ typedef struct
        gpointer *memcpy_addr [17];
        gpointer *bzero_addr [17];
        gpointer llvm_module;
+       /* Maps MonoMethod -> GSlist of addresses */
+       GHashTable *llvm_jit_callees;
 } MonoJitDomainInfo;
 
 typedef struct {
index 7ed3e2813040c578a03440222ff496af4bfdb7e3..4898932259a8431914d536cf941160f85585b9ce 100644 (file)
@@ -1,7 +1,7 @@
 SUBDIRS = assemblyresolve gc-descriptors
 
 check-local: assemblyresolve/test/asm.dll testjit test-generic-sharing test-type-load test-cattr-type-load test-reflection-load-with-context test_platform     \
-                test-console-output test-messages test-env-options test-unhandled-exception-2 test-appdomain-unload test-process-stress test-assembly-load-remap rm-empty-logs
+                test-console-output test-messages test-env-options test-unhandled-exception-2 test-appdomain-unload test-process-stress rm-empty-logs
 check-full: test-sgen check-local
 check-parallel: compile-tests check-full
 
@@ -61,6 +61,7 @@ BASE_TEST_CS_SRC=             \
        bug-2907.cs             \
        array-init.cs           \
        arraylist.cs            \
+       assembly-load-remap.cs  \
        assemblyresolve_event.cs        \
        assemblyresolve_event3.cs       \
        assemblyresolve_event4.cs       \
@@ -1429,13 +1430,6 @@ PROCESS_STRESS_TESTS=    \
 test-process-stress: $(PROCESS_STRESS_TESTS) test-runner.exe
        $(RUNTIME) ./test-runner.exe --testsuite-name $@ --timeout 600 $(PROCESS_STRESS_TESTS)
 
-EXTRA_DIST += assembly-load-remap.cs
-test-assembly-load-remap: assembly-load-remap.exe
-       MONO_LOG_LEVEL=warning MONO_LOG_MASK=asm $(RUNTIME) assembly-load-remap.exe "2.0.0.0" | grep "remapped to v4.0.0.0"
-       MONO_LOG_LEVEL=warning MONO_LOG_MASK=asm $(RUNTIME) assembly-load-remap.exe "4.0.0.0" | grep "remapped to" && exit 1 || exit 0
-       MONO_LOG_LEVEL=warning MONO_LOG_MASK=asm $(RUNTIME) assembly-load-remap.exe "12.0.0.0" | grep "remapped to" && exit 1 || exit 0
-       MONO_LOG_LEVEL=warning MONO_LOG_MASK=asm $(RUNTIME) assembly-load-remap.exe "14.0.0.0" | grep "remapped to" && exit 1 || exit 0
-
 coreclr-gcstress:
        $(MAKE) -C $(mono_build_root)/acceptance-tests coreclr-gcstress
 
index a206cdcd7525560a56d41544eba3956ade1b8f22..f9c93d5da88f65186082c68cd3dc8b432ff2c562 100644 (file)
@@ -6,13 +6,85 @@ public class Tests
 {
        public static void Main (string[] args)
        {
-               if (args.Length != 1)
-                       throw new Exception ("Missing commandline args.");
+               var ver40 = new Version (4, 0, 0, 0);
+               var ver140 = new Version (14, 0, 0, 0);
+               var util20 = Assembly.ReflectionOnlyLoad ("Microsoft.Build.Utilities, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a");
+               var util35 = Assembly.ReflectionOnlyLoad ("Microsoft.Build.Utilities.v3.5, Version=3.5.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a");
+               var task20 = Assembly.ReflectionOnlyLoad ("Microsoft.Build.Tasks, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a");
+               var task35 = Assembly.ReflectionOnlyLoad ("Microsoft.Build.Tasks.v3.5, Version=3.5.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a");
+               var engn20 = Assembly.ReflectionOnlyLoad ("Microsoft.Build.Engine, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a");
+               var engn35 = Assembly.ReflectionOnlyLoad ("Microsoft.Build.Engine, Version=3.5.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a");
+               var frwk20 = Assembly.ReflectionOnlyLoad ("Microsoft.Build.Framework, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a");
+               var frwk35 = Assembly.ReflectionOnlyLoad ("Microsoft.Build.Framework, Version=3.5.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a");
 
-               string versionLoad = args [0];
-               var asm = Assembly.Load ("Microsoft.Build.Framework, Version=" + versionLoad + ", Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a");
+               // when run as part of the test suite, we need to register the xbuild 14.0 path or v14 assembly lookup will fail 
+               if (!String.IsNullOrEmpty (Environment.GetEnvironmentVariable ("MONO_PATH"))) {
+                       var p = Path.Combine (new DirectoryInfo (Environment.GetEnvironmentVariable ("MONO_PATH")).Parent.FullName, "xbuild_14");
+                       Console.WriteLine("Adding private bin path " + p);
+                       AppDomain.CurrentDomain.AppendPrivatePath (p);
+               }
 
-               if (asm == null)
-                       throw new Exception ("Assembly couldn't be loaded.");
+               var engn140 = Assembly.ReflectionOnlyLoad ("Microsoft.Build.Engine, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a");
+               var frwk140 = Assembly.ReflectionOnlyLoad ("Microsoft.Build.Framework, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a");
+
+               if (util20 == null)
+                       throw new Exception ("#1 assembly couldn't be loaded.");
+
+               if (util35 == null)
+                       throw new Exception ("#2 assembly couldn't be loaded.");
+
+               if (util20.GetName ().Version != ver40)
+                       throw new Exception ("#3 expected remap to v4.0.0.0, but got " + util20);
+
+               if (util35.GetName ().Version != ver40)
+                       throw new Exception ("#4 expected remap to v4.0.0.0, but got " + util35);
+
+               if (task20 == null)
+                       throw new Exception ("#5 assembly couldn't be loaded.");
+
+               if (task35 == null)
+                       throw new Exception ("#6 assembly couldn't be loaded.");
+
+               if (task20.GetName ().Version != ver40)
+                       throw new Exception ("#7 expected remap to v4.0.0.0, but got " + task20);
+
+               if (task35.GetName ().Version != ver40)
+                       throw new Exception ("#8 expected remap to v4.0.0.0, but got " + task35);
+
+               if (engn20 == null)
+                       throw new Exception ("#9 assembly couldn't be loaded.");
+
+               if (engn35 == null)
+                       throw new Exception ("#10 assembly couldn't be loaded.");
+
+               if (engn140 == null)
+                       throw new Exception ("#11 assembly couldn't be loaded.");
+
+               if (engn20.GetName ().Version != ver40)
+                       throw new Exception ("#12 expected remap to v4.0.0.0, but got " + engn20);
+
+               if (engn35.GetName ().Version != ver40)
+                       throw new Exception ("#13 expected remap to v4.0.0.0, but got " + engn35);
+       
+               if (engn140.GetName ().Version != ver140)
+                       throw new Exception ("#14 expected v14.0.0.0, but got " + engn140);
+
+               if (frwk20 == null)
+                       throw new Exception ("#15 assembly couldn't be loaded.");
+
+               if (frwk35 == null)
+                       throw new Exception ("#16 assembly couldn't be loaded.");
+
+               if (frwk140 == null)
+                       throw new Exception ("#17 assembly couldn't be loaded.");
+
+               if (frwk20.GetName ().Version != ver40)
+                       throw new Exception ("#18 expected remap to v4.0.0.0, but got " + frwk20);
+
+               if (frwk35.GetName ().Version != ver40)
+                       throw new Exception ("#19 expected remap to v4.0.0.0, but got " + frwk35);
+
+               if (frwk140.GetName ().Version != ver140)
+                       throw new Exception ("#20 expected v14.0.0.0, but got " + frwk140);
        }
 }
index f1e1bacf6be5857c31bb05a9611ae3e0c955c1ad..b6f2ee0979524b82e12815c5bd57731c7d1886a4 100644 (file)
@@ -599,7 +599,7 @@ mono_error_prepare_exception (MonoError *oerror, MonoError *error_out)
                break;
 
        case MONO_ERROR_TYPE_LOAD:
-               if (error->type_name && error->assembly_name) {
+               if ((error->type_name && error->assembly_name) || error->exn.klass) {
                        type_name = get_type_name_as_mono_string (error, domain, error_out);
                        if (!mono_error_ok (error_out))
                                break;