* (C) 2002 Ximian, Inc.
* Copyright 2003-2010 Novell, Inc (http://www.novell.com)
* Copyright 2011 Xamarin, Inc (http://www.xamarin.com)
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
*/
#include <config.h>
#include <mono/metadata/debug-mono-symfile.h>
#include <mono/utils/mono-compiler.h>
#include <mono/utils/mono-memory-model.h>
+#include <mono/utils/mono-error-internals.h>
#include <mono/metadata/mono-basic-block.h>
#include <mono/metadata/reflection-internals.h>
return -1;
}
+//XXX this ignores if t is byref
+#define MONO_TYPE_IS_PRIMITIVE_SCALAR(t) ((((((t)->type >= MONO_TYPE_BOOLEAN && (t)->type <= MONO_TYPE_U8) || ((t)->type >= MONO_TYPE_I && (t)->type <= MONO_TYPE_U)))))
+
/*
* target_type_is_incompatible:
* @cfg: MonoCompile context
if (target->byref) {
/* FIXME: check that the pointed to types match */
if (arg->type == STACK_MP) {
- MonoClass *base_class = mono_class_from_mono_type (target);
- /* This is needed to handle gshared types + ldaddr */
- simple_type = mini_get_underlying_type (&base_class->byval_arg);
- return target->type != MONO_TYPE_I && arg->klass != base_class && arg->klass != mono_class_from_mono_type (simple_type);
+ if (cfg->verbose_level) printf ("ok\n");
+ /* This is needed to handle gshared types + ldaddr. We lower the types so we can handle enums and other typedef-like types. */
+ MonoClass *target_class_lowered = mono_class_from_mono_type (mini_get_underlying_type (&mono_class_from_mono_type (target)->byval_arg));
+ MonoClass *source_class_lowered = mono_class_from_mono_type (mini_get_underlying_type (&arg->klass->byval_arg));
+
+ /* if the target is native int& or same type */
+ if (target->type == MONO_TYPE_I || target_class_lowered == source_class_lowered)
+ return 0;
+
+ /* Both are primitive type byrefs and the source points to a larger type that the destination */
+ if (MONO_TYPE_IS_PRIMITIVE_SCALAR (&target_class_lowered->byval_arg) && MONO_TYPE_IS_PRIMITIVE_SCALAR (&source_class_lowered->byval_arg) &&
+ mono_class_instance_size (target_class_lowered) <= mono_class_instance_size (source_class_lowered))
+ return 0;
+ return 1;
}
if (arg->type == STACK_PTR)
return 0;
if (cfg->verbose_level > 2)
printf ("INLINE ABORTED %s (cost %d)\n", mono_method_full_name (cmethod, TRUE), costs);
cfg->exception_type = MONO_EXCEPTION_NONE;
- mono_loader_clear_error ();
/* This gets rid of the newly added bblocks */
cfg->cbb = prev_cbb;
skip_dead_blocks = !dont_verify;
if (skip_dead_blocks) {
- original_bb = bb = mono_basic_block_split (method, &cfg->error);
+ original_bb = bb = mono_basic_block_split (method, &cfg->error, header);
CHECK_CFG_ERROR;
g_assert (bb);
}
info_data = addr->inst_right->inst_left;
}
- if (info_type == MONO_PATCH_INFO_ICALL_ADDR || info_type == MONO_PATCH_INFO_JIT_ICALL_ADDR) {
+ if (info_type == MONO_PATCH_INFO_ICALL_ADDR) {
+ ins = (MonoInst*)mono_emit_abs_call (cfg, MONO_PATCH_INFO_ICALL_ADDR_CALL, info_data, fsig, sp);
+ NULLIFY_INS (addr);
+ goto calli_end;
+ } else if (info_type == MONO_PATCH_INFO_JIT_ICALL_ADDR) {
ins = (MonoInst*)mono_emit_abs_call (cfg, info_type, info_data, fsig, sp);
NULLIFY_INS (addr);
goto calli_end;
}
}
- if (!cmethod || mono_loader_get_last_error ()) {
- if (mono_loader_get_last_error ()) {
- mono_cfg_set_exception (cfg, MONO_EXCEPTION_MONO_ERROR);
- mono_error_set_from_loader_error (&cfg->error);
- CHECK_CFG_ERROR;
- } else {
- LOAD_ERROR;
- }
- }
if (!dont_verify && !cfg->skip_visibility) {
MonoMethod *target_method = cil_method;
if (method->is_inflated) {
/* STATIC CASE */
context_used = mini_class_check_context_used (cfg, klass);
- if (ftype->attrs & FIELD_ATTRIBUTE_LITERAL)
- UNVERIFIED;
+ if (ftype->attrs & FIELD_ATTRIBUTE_LITERAL) {
+ mono_error_set_field_load (&cfg->error, field->parent, field->name, "Using static instructions with literal field");
+ CHECK_CFG_ERROR;
+ }
/* The special_static_fields field is init'd in mono_class_vtable, so it needs
* to be called here.
INLINE_FAILURE ("class init");
if (!mono_runtime_class_init_full (vtable, &cfg->error)) {
mono_cfg_set_exception (cfg, MONO_EXCEPTION_MONO_ERROR);
- g_assert_not_reached ();
goto exception_exit;
}
}