#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>
static MonoMethodSignature *helper_sig_rgctx_lazy_fetch_trampoline;
static MonoMethodSignature *helper_sig_llvmonly_imt_thunk;
+
+/* type loading helpers */
+static GENERATE_GET_CLASS_WITH_CACHE (runtime_helpers, System.Runtime.CompilerServices, RuntimeHelpers)
+static GENERATE_TRY_GET_CLASS_WITH_CACHE (debuggable_attribute, System.Diagnostics, DebuggableAttribute)
+
/*
* Instruction metadata
*/
} else {
MonoJumpInfo ji;
gpointer target;
+ MonoError error;
ji.type = patch_type;
ji.data.target = data;
- target = mono_resolve_patch_target (NULL, cfg->domain, NULL, &ji, FALSE);
+ target = mono_resolve_patch_target (NULL, cfg->domain, NULL, &ji, FALSE, &error);
+ mono_error_assert_ok (&error);
EMIT_NEW_PCONST (cfg, ins, target);
}
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;
vtable = mono_class_vtable (cfg->domain, method->klass);
if (!vtable)
return FALSE;
- if (!cfg->compile_aot)
- mono_runtime_class_init (vtable);
+ if (!cfg->compile_aot) {
+ MonoError error;
+ if (!mono_runtime_class_init_full (vtable, &error))
+ mono_error_raise_exception (&error); /* FIXME don't raise here */
+ }
} else if (method->klass->flags & TYPE_ATTRIBUTE_BEFORE_FIELD_INIT) {
if (cfg->run_cctors && method->klass->has_cctor) {
/*FIXME it would easier and lazier to just use mono_class_try_get_vtable */
/* running with a specific order... */
if (! vtable->initialized)
return FALSE;
- mono_runtime_class_init (vtable);
+ MonoError error;
+ if (!mono_runtime_class_init_full (vtable, &error))
+ mono_error_raise_exception (&error); /* FIXME don't raise here */
}
} else if (mono_class_needs_cctor_run (method->klass, NULL)) {
if (!method->klass->runtime_info)
{
MonoInst *ins = NULL;
- static MonoClass *runtime_helpers_class = NULL;
- if (! runtime_helpers_class)
- runtime_helpers_class = mono_class_from_name (mono_defaults.corlib,
- "System.Runtime.CompilerServices", "RuntimeHelpers");
+ MonoClass *runtime_helpers_class = mono_class_get_runtime_helpers_class ();
if (cmethod->klass == mono_defaults.string_class) {
if (strcmp (cmethod->name, "get_Chars") == 0 && fsig->param_count + fsig->hasthis == 2) {
inline_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig, MonoInst **sp,
guchar *ip, guint real_offset, gboolean inline_always)
{
+ MonoError error;
MonoInst *ins, *rvar = NULL;
MonoMethodHeader *cheader;
MonoBasicBlock *ebblock, *sbblock;
}
/* allocate local variables */
- cheader = mono_method_get_header (cmethod);
-
- if (cheader == NULL || mono_loader_get_last_error ()) {
- if (cheader)
- mono_metadata_free_mh (cheader);
- if (inline_always && mono_loader_get_last_error ()) {
+ cheader = mono_method_get_header_checked (cmethod, &error);
+ if (!cheader) {
+ if (inline_always) {
mono_cfg_set_exception (cfg, MONO_EXCEPTION_MONO_ERROR);
- mono_error_set_from_loader_error (&cfg->error);
+ mono_error_move (&cfg->error, &error);
+ } else {
+ mono_error_cleanup (&error);
}
-
- mono_loader_clear_error ();
return 0;
}
#define CHECK_LOCAL(num) if ((unsigned)(num) >= (unsigned)header->num_locals) UNVERIFIED
#define CHECK_OPSIZE(size) if (ip + size > end) UNVERIFIED
#define CHECK_UNVERIFIABLE(cfg) if (cfg->unverifiable) UNVERIFIED
-#define CHECK_TYPELOAD(klass) if (!(klass) || (klass)->exception_type) TYPE_LOAD_ERROR ((klass))
+#define CHECK_TYPELOAD(klass) if (!(klass) || mono_class_has_failure (klass)) TYPE_LOAD_ERROR ((klass))
/* offset from br.s -> br like opcodes */
#define BIG_BRANCH_OFFSET 13
if (method->wrapper_type != MONO_WRAPPER_NONE) {
klass = (MonoClass *)mono_method_get_wrapper_data (method, token);
- if (context)
- klass = mono_class_inflate_generic_class (klass, context);
+ if (context) {
+ klass = mono_class_inflate_generic_class_checked (klass, context, &error);
+ mono_error_cleanup (&error); /* FIXME don't swallow the error */
+ }
} else {
klass = mono_class_get_and_inflate_typespec_checked (method->klass->image, token, context, &error);
mono_error_cleanup (&error); /* FIXME don't swallow the error */
static void
set_exception_type_from_invalid_il (MonoCompile *cfg, MonoMethod *method, unsigned char *ip)
{
+ MonoError error;
char *method_fname = mono_method_full_name (method, TRUE);
char *method_code;
- MonoMethodHeader *header = mono_method_get_header (method);
+ MonoMethodHeader *header = mono_method_get_header_checked (method, &error);
- if (header->code_size == 0)
+ if (!header) {
+ method_code = g_strdup_printf ("could not parse method body due to %s", mono_error_get_message (&error));
+ mono_error_cleanup (&error);
+ } else if (header->code_size == 0)
method_code = g_strdup ("method body is empty.");
else
method_code = mono_disasm_code_one (NULL, method, ip, NULL);
static gboolean
is_jit_optimizer_disabled (MonoMethod *m)
{
+ MonoError error;
MonoAssembly *ass = m->klass->image->assembly;
MonoCustomAttrInfo* attrs;
- static MonoClass *klass;
+ MonoClass *klass;
int i;
gboolean val = FALSE;
if (ass->jit_optimizer_disabled_inited)
return ass->jit_optimizer_disabled;
- if (!klass)
- klass = mono_class_from_name (mono_defaults.corlib, "System.Diagnostics", "DebuggableAttribute");
+ klass = mono_class_try_get_debuggable_attribute_class ();
+
if (!klass) {
/* Linked away */
ass->jit_optimizer_disabled = FALSE;
return FALSE;
}
- attrs = mono_custom_attrs_from_assembly (ass);
+ attrs = mono_custom_attrs_from_assembly_checked (ass, &error);
+ mono_error_cleanup (&error); /* FIXME don't swallow the error */
if (attrs) {
for (i = 0; i < attrs->num_attrs; ++i) {
MonoCustomAttrEntry *attr = &attrs->attrs [i];
dont_verify_stloc |= method->wrapper_type == MONO_WRAPPER_STELEMREF;
image = method->klass->image;
- header = mono_method_get_header (method);
+ header = mono_method_get_header_checked (method, &cfg->error);
if (!header) {
- if (mono_loader_get_last_error ()) {
- mono_cfg_set_exception (cfg, MONO_EXCEPTION_MONO_ERROR);
- mono_error_set_from_loader_error (&cfg->error);
- } else {
- mono_cfg_set_exception_invalid_program (cfg, g_strdup_printf ("Missing or incorrect header for method %s", cfg->method->name));
- }
+ mono_cfg_set_exception (cfg, MONO_EXCEPTION_MONO_ERROR);
goto exception_exit;
}
generic_container = mono_method_get_generic_container (method);
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.
}
} else {
if (cfg->run_cctors) {
- MonoException *ex;
/* This makes so that inline cannot trigger */
/* .cctors: too many apps depend on them */
/* running with a specific order... */
g_assert (vtable);
if (! vtable->initialized)
INLINE_FAILURE ("class init");
- ex = mono_runtime_class_init_full (vtable, FALSE);
- if (ex) {
+ if (!mono_runtime_class_init_full (vtable, &cfg->error)) {
mono_cfg_set_exception (cfg, MONO_EXCEPTION_MONO_ERROR);
- mono_error_set_exception_instance (&cfg->error, ex);
- g_assert_not_reached ();
goto exception_exit;
}
}
EMIT_NEW_TYPE_FROM_HANDLE_CONST (cfg, ins, image, n, generic_context);
}
} else {
- MonoError error;
- MonoReflectionType *rt = mono_type_get_object_checked (cfg->domain, (MonoType *)handle, &error);
- mono_error_raise_exception (&error); /* FIXME don't raise here */
-
+ MonoReflectionType *rt = mono_type_get_object_checked (cfg->domain, (MonoType *)handle, &cfg->error);
+ CHECK_CFG_ERROR;
EMIT_NEW_PCONST (cfg, ins, rt);
}
ins->type = STACK_OBJ;
MonoInst *ad_ins, *jit_tls_ins;
MonoBasicBlock *next_bb = NULL, *call_bb = NULL;
- cfg->orig_domain_var = mono_compile_create_var (cfg, &mono_defaults.int_class->byval_arg, OP_LOCAL);
+ cfg->attach_cookie = mono_compile_create_var (cfg, &mono_defaults.int_class->byval_arg, OP_LOCAL);
+ cfg->attach_dummy = mono_compile_create_var (cfg, &mono_defaults.int_class->byval_arg, OP_LOCAL);
- EMIT_NEW_PCONST (cfg, ins, NULL);
- MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, cfg->orig_domain_var->dreg, ins->dreg);
+ if (mono_threads_is_coop_enabled ()) {
+ /* AOT code is only used in the root domain */
+ EMIT_NEW_PCONST (cfg, args [0], cfg->compile_aot ? NULL : cfg->domain);
+ EMIT_NEW_VARLOADA (cfg, args [1], cfg->attach_dummy, cfg->attach_dummy->inst_vtype);
+ ins = mono_emit_jit_icall (cfg, mono_jit_thread_attach, args);
+ MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, cfg->attach_cookie->dreg, ins->dreg);
+ } else {
+ EMIT_NEW_PCONST (cfg, ins, NULL);
+ MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, cfg->attach_cookie->dreg, ins->dreg);
- ad_ins = mono_get_domain_intrinsic (cfg);
- jit_tls_ins = mono_get_jit_tls_intrinsic (cfg);
+ ad_ins = mono_get_domain_intrinsic (cfg);
+ jit_tls_ins = mono_get_jit_tls_intrinsic (cfg);
- if (cfg->backend->have_tls_get && ad_ins && jit_tls_ins) {
- NEW_BBLOCK (cfg, next_bb);
- NEW_BBLOCK (cfg, call_bb);
+ if (cfg->backend->have_tls_get && ad_ins && jit_tls_ins) {
+ NEW_BBLOCK (cfg, next_bb);
+ NEW_BBLOCK (cfg, call_bb);
- if (cfg->compile_aot) {
- /* AOT code is only used in the root domain */
- EMIT_NEW_PCONST (cfg, domain_ins, NULL);
- } else {
- EMIT_NEW_PCONST (cfg, domain_ins, cfg->domain);
- }
- MONO_ADD_INS (cfg->cbb, ad_ins);
- MONO_EMIT_NEW_BIALU (cfg, OP_COMPARE, -1, ad_ins->dreg, domain_ins->dreg);
- MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_PBNE_UN, call_bb);
+ if (cfg->compile_aot) {
+ /* AOT code is only used in the root domain */
+ EMIT_NEW_PCONST (cfg, domain_ins, NULL);
+ } else {
+ EMIT_NEW_PCONST (cfg, domain_ins, cfg->domain);
+ }
+ MONO_ADD_INS (cfg->cbb, ad_ins);
+ MONO_EMIT_NEW_BIALU (cfg, OP_COMPARE, -1, ad_ins->dreg, domain_ins->dreg);
+ MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_PBNE_UN, call_bb);
- MONO_ADD_INS (cfg->cbb, jit_tls_ins);
- MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, jit_tls_ins->dreg, 0);
- MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_PBEQ, call_bb);
+ MONO_ADD_INS (cfg->cbb, jit_tls_ins);
+ MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, jit_tls_ins->dreg, 0);
+ MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_PBEQ, call_bb);
- MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_BR, next_bb);
- MONO_START_BB (cfg, call_bb);
- }
+ MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_BR, next_bb);
+ MONO_START_BB (cfg, call_bb);
+ }
- if (cfg->compile_aot) {
/* AOT code is only used in the root domain */
- EMIT_NEW_PCONST (cfg, args [0], NULL);
- } else {
- EMIT_NEW_PCONST (cfg, args [0], cfg->domain);
+ EMIT_NEW_PCONST (cfg, args [0], cfg->compile_aot ? NULL : cfg->domain);
+ EMIT_NEW_PCONST (cfg, args [1], NULL);
+ ins = mono_emit_jit_icall (cfg, mono_jit_thread_attach, args);
+ MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, cfg->attach_cookie->dreg, ins->dreg);
+
+ if (next_bb)
+ MONO_START_BB (cfg, next_bb);
}
- ins = mono_emit_jit_icall (cfg, mono_jit_thread_attach, args);
- MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, cfg->orig_domain_var->dreg, ins->dreg);
- if (next_bb)
- MONO_START_BB (cfg, next_bb);
ip += 2;
break;
}
/* Restore the original domain */
dreg = alloc_ireg (cfg);
- EMIT_NEW_UNALU (cfg, args [0], OP_MOVE, dreg, cfg->orig_domain_var->dreg);
- mono_emit_jit_icall (cfg, mono_jit_set_domain, args);
+ EMIT_NEW_UNALU (cfg, args [0], OP_MOVE, dreg, cfg->attach_cookie->dreg);
+ EMIT_NEW_VARLOADA (cfg, args [1], cfg->attach_dummy, cfg->attach_dummy->inst_vtype);
+ mono_emit_jit_icall (cfg, mono_jit_thread_detach, args);
ip += 2;
break;
}