{
"name": "coreclr",
"url": "git://github.com/mono/coreclr.git",
- "rev": "96cf61f96b42cf9d013e641609cb7787f6e3a71f",
+ "rev": "d964b6b194e508921b75194b216c315116e33fef",
"remote-branch": "origin/mono",
"branch": "mono",
"directory": "coreclr"
{
"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"
$(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 \
$(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 \
#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 */
{"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},
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",
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;
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)
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)
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)
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)
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)
}
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*
}
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
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;
}
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) {
/* 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;
}
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*
#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);
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__ */
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);
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 */
} 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;
/* 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);
/* 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;
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);
}
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)
{
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) {
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 ||
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);
} 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;
} 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
/* 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);
* 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;
}
}
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;
}
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;
}
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;
}
}
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;
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;
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;
} 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;
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);
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;
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);
* 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) {
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;
// 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);
}
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
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;
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)
*endbuf = p;
return sig;
+fail:
+ mono_error_cleanup (&error); /* FIXME don't swallow the error */
+ g_free (sig);
+ return NULL;
}
static MonoMethodSignature*
* 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;
}
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) {
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);
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);
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)
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:
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: {
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);
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;
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);
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;
}
} 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;
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;
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: {
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);
MonoClass *klass;
MonoMethod *invoke, *wrapper;
- klass = decode_klass_ref (module, p, &p);
+ klass = decode_klass_ref (module, p, &p, error);
if (!klass)
return FALSE;
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);
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;
* 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;
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));
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);
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) {
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;
}
}
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);
}
/*
* 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
}
#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) {
static gboolean
decode_cached_class_info (MonoAotModule *module, MonoCachedClassInfo *info, guint8 *buf, guint8 **endbuf)
{
+ MonoError error;
guint32 flags;
MethodRef ref;
gboolean res;
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;
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;
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)
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;
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;
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 */
+ }
}
}
}
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)) {
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;
}
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;
static gboolean
decode_patch (MonoAotModule *aot_module, MonoMemPool *mp, MonoJumpInfo *ji, guint8 *buf, guint8 **endbuf)
{
+ MonoError error;
guint8 *p = buf;
gpointer *table;
MonoImage *image;
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;
}
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;
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;
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));
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;
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)
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;
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);
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;
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;
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;
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 ().
//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)
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);
break;
}
case CMD_ASSEMBLY_GET_TYPE: {
+ MonoError error;
char *s = decode_string (p, &p, end);
gboolean ignorecase = decode_byte (p, &p, end);
MonoTypeNameParse info;
} 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);
#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
}
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;
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);
#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.
*/
GPtrArray *phi_values;
GPtrArray *bblock_list;
char *method_name;
+ GHashTable *jit_callees;
} EmitContext;
typedef struct {
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);
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)
}
}
+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)
{
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 (), "");
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);
}
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
}
}
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), "");
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;
}
} 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
}
}
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) {
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);
}
if (!target)
LLVMAddGlobalMapping (ctx->module->ee, callee, (gpointer)call->fptr);
+#endif
}
}
}
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);
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);
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;
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);
*/
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
type_info = LLVMAddGlobal (lmodule, i8ptr, ti_name);
LLVMAddGlobalMapping (ctx->module->ee, type_info, ti);
+#endif
}
{
LLVMValueRef *values = ctx->values;
LLVMValueRef *addresses = ctx->addresses;
LLVMCallInfo *linfo = ctx->linfo;
- LLVMModuleRef lmodule = ctx->lmodule;
BBInfo *bblocks = ctx->bblocks;
MonoInst *ins;
LLVMBasicBlockRef cbb;
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)) {
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;
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;
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;
}
}
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;
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);
// 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:
// 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: {
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:
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;
}
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;
}
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;
}
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;
}
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);
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);
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;
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);
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) {
#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)
/* Set by emit_cb */
g_assert (cfg->code_len);
+#endif
}
if (ctx->module->method_to_lmethod)
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)
{
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 */
void
mono_llvm_init (void)
{
+ GHashTable *h;
+ int i;
+
mono_native_tls_alloc (¤t_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;
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 ();
}
g_slist_free (remove);
}
-
mono_domain_unlock (domain);
#ifdef MONO_ARCH_HAVE_INVALIDATE_METHOD
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)
{
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
}
}
+ /* 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);
gpointer *memcpy_addr [17];
gpointer *bzero_addr [17];
gpointer llvm_module;
+ /* Maps MonoMethod -> GSlist of addresses */
+ GHashTable *llvm_jit_callees;
} MonoJitDomainInfo;
typedef struct {
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
bug-2907.cs \
array-init.cs \
arraylist.cs \
+ assembly-load-remap.cs \
assemblyresolve_event.cs \
assemblyresolve_event3.cs \
assemblyresolve_event4.cs \
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
{
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);
}
}
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;