Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/mono/mono/metadata/jit-icall-reg.h
Original file line number Diff line number Diff line change
Expand Up @@ -312,6 +312,7 @@ MONO_JIT_ICALL (mono_throw_bad_image) \
MONO_JIT_ICALL (mono_throw_not_supported) \
MONO_JIT_ICALL (mono_throw_platform_not_supported) \
MONO_JIT_ICALL (mono_throw_invalid_program) \
MONO_JIT_ICALL (mono_throw_type_load) \
MONO_JIT_ICALL (mono_trace_enter_method) \
MONO_JIT_ICALL (mono_trace_leave_method) \
MONO_JIT_ICALL (mono_trace_tail_method) \
Expand Down
1 change: 1 addition & 0 deletions src/mono/mono/mini/aot-compiler.c
Original file line number Diff line number Diff line change
Expand Up @@ -9580,6 +9580,7 @@ compile_method (MonoAotCompile *acfg, MonoMethod *method)
mono_atomic_inc_i32 (&acfg->stats.genericcount);
return;
}

Comment thread
jandupej marked this conversation as resolved.
Outdated
if (cfg->exception_type != MONO_EXCEPTION_NONE) {
/* Some instances cannot be JITted due to constraints etc. */
if (!method->is_inflated)
Expand Down
8 changes: 8 additions & 0 deletions src/mono/mono/mini/jit-icalls.c
Original file line number Diff line number Diff line change
Expand Up @@ -1688,6 +1688,14 @@ mono_throw_invalid_program (const char *msg)
mono_error_set_pending_exception (error);
}

void
mono_throw_type_load (const char* msg)
{
ERROR_DECL (error);
mono_error_set_generic_error (error, "System", "TypeLoadException", "Attempting to load invalid type '%s'.", msg);
mono_error_set_pending_exception (error);
}

void
mono_dummy_jit_icall (void)
{
Expand Down
2 changes: 2 additions & 0 deletions src/mono/mono/mini/jit-icalls.h
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,8 @@ ICALL_EXPORT void mono_throw_platform_not_supported (void);

ICALL_EXPORT void mono_throw_invalid_program (const char *msg);

ICALL_EXPORT void mono_throw_type_load (const char* msg);

ICALL_EXPORT void mono_dummy_jit_icall (void);

ICALL_EXPORT void mono_dummy_jit_icall_val (gpointer ptr);
Expand Down
102 changes: 85 additions & 17 deletions src/mono/mono/mini/method-to-ir.c
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ mono_tailcall_print (const char *format, ...)

#define TYPE_LOAD_ERROR(klass) do { \
cfg->exception_ptr = klass; \
LOAD_ERROR; \
LOAD_ERROR; \
} while (0)

#define CHECK_CFG_ERROR do {\
Expand Down Expand Up @@ -2303,6 +2303,20 @@ emit_not_supported_failure (MonoCompile *cfg)
mono_emit_jit_icall (cfg, mono_throw_not_supported, NULL);
}

static void
emit_type_load_failure (MonoCompile* cfg, MonoClass* klass)
{
char* class_name;
if (G_UNLIKELY (!klass))
class_name = mono_mem_manager_strdup (cfg->mem_manager, "Unknown class" );
else
class_name = mono_mem_manager_strdup (cfg->mem_manager, mono_class_full_name (klass));

MonoInst* iargs[1];
EMIT_NEW_LDSTRLITCONST (cfg, iargs [0], class_name);
Comment thread
jandupej marked this conversation as resolved.
Outdated
mono_emit_jit_icall (cfg, mono_throw_type_load, iargs);
}

static void
emit_invalid_program_with_msg (MonoCompile *cfg, MonoError *error_msg, MonoMethod *caller, MonoMethod *callee)
{
Expand Down Expand Up @@ -4963,6 +4977,11 @@ inline_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig,
#define CHECK_UNVERIFIABLE(cfg) if (cfg->unverifiable) UNVERIFIED
#define CHECK_TYPELOAD(klass) if (!(klass) || mono_class_has_failure (klass)) TYPE_LOAD_ERROR ((klass))

#define CLEAR_TYPELOAD_EXCEPTION(cfg) if (cfg->exception_type == MONO_EXCEPTION_TYPE_LOAD) { clear_cfg_error (cfg); cfg->exception_type = MONO_EXCEPTION_NONE; }
#define IF_TYPELOAD_ERROR(klass) if (!(klass) || mono_class_has_failure (klass))
Comment thread
jandupej marked this conversation as resolved.
Outdated
#define HANDLE_TYPELOAD_ERROR(cfg,klass) if (!cfg->compile_aot) TYPE_LOAD_ERROR ((klass)); emit_type_load_failure (cfg, klass); CLEAR_TYPELOAD_EXCEPTION (cfg);

Comment thread
jandupej marked this conversation as resolved.
Outdated

/* offset from br.s -> br like opcodes */
#define BIG_BRANCH_OFFSET 13

Expand Down Expand Up @@ -5438,7 +5457,10 @@ emit_optimized_ldloca_ir (MonoCompile *cfg, guchar *ip, guchar *end, int local)
if ((ip = il_read_initobj (ip, end, &token)) && ip_in_bb (cfg, cfg->cbb, start + 1)) {
/* From the INITOBJ case */
klass = mini_get_class (cfg->current_method, token, cfg->generic_context);
CHECK_TYPELOAD (klass);
IF_TYPELOAD_ERROR (klass) {
HANDLE_TYPELOAD_ERROR (cfg, klass);
return ip;
}
type = mini_get_underlying_type (m_class_get_byval_arg (klass));
emit_init_local (cfg, local, type, TRUE);
return ip;
Expand Down Expand Up @@ -9383,7 +9405,10 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
case MONO_CEE_ISINST: {
--sp;
klass = mini_get_class (method, token, generic_context);
CHECK_TYPELOAD (klass);
IF_TYPELOAD_ERROR (klass) {
HANDLE_TYPELOAD_ERROR (cfg, klass);
break; // reached only in AOT
}
if (sp [0]->type != STACK_OBJ)
UNVERIFIED;

Expand All @@ -9405,7 +9430,10 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b

--sp;
klass = mini_get_class (method, token, generic_context);
CHECK_TYPELOAD (klass);
IF_TYPELOAD_ERROR (klass) {
HANDLE_TYPELOAD_ERROR (cfg, klass);
break; // reached in AOT only
}

mono_save_token_info (cfg, image, token, klass);

Expand Down Expand Up @@ -9837,7 +9865,10 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
case MONO_CEE_UNBOX: {
--sp;
klass = mini_get_class (method, token, generic_context);
CHECK_TYPELOAD (klass);
IF_TYPELOAD_ERROR (klass) {
HANDLE_TYPELOAD_ERROR (cfg, klass);
break; // reached in AOT only
}

mono_save_token_info (cfg, image, token, klass);

Expand Down Expand Up @@ -9898,8 +9929,12 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
else {
klass = NULL;
field = mono_field_from_token_checked (image, token, &klass, generic_context, cfg->error);
if (!field)
CHECK_TYPELOAD (klass);
if (!field) {
IF_TYPELOAD_ERROR (klass) {
HANDLE_TYPELOAD_ERROR (cfg, klass);
break; // reached only in AOT
}
}
CHECK_CFG_ERROR;
}
if (!dont_verify && !cfg->skip_visibility && !mono_method_can_access_field (method, field))
Expand Down Expand Up @@ -10385,7 +10420,10 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
case MONO_CEE_STOBJ:
sp -= 2;
klass = mini_get_class (method, token, generic_context);
CHECK_TYPELOAD (klass);
IF_TYPELOAD_ERROR (klass) {
HANDLE_TYPELOAD_ERROR (cfg, klass);
break;
}

/* FIXME: should check item at sp [1] is compatible with the type of the store. */
mini_emit_memory_store (cfg, m_class_get_byval_arg (klass), sp [0], sp [1], ins_flag);
Expand All @@ -10405,7 +10443,10 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
--sp;

klass = mini_get_class (method, token, generic_context);
CHECK_TYPELOAD (klass);
IF_TYPELOAD_ERROR (klass) {
HANDLE_TYPELOAD_ERROR (cfg, klass);
break;
}
if (m_class_get_byval_arg (klass)->type == MONO_TYPE_VOID)
UNVERIFIED;

Expand Down Expand Up @@ -10531,7 +10572,10 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
cfg->flags |= MONO_CFG_HAS_LDELEMA;

klass = mini_get_class (method, token, generic_context);
CHECK_TYPELOAD (klass);
IF_TYPELOAD_ERROR (klass) {
HANDLE_TYPELOAD_ERROR (cfg, klass);
break; // reached only in AOT
}
/* we need to make sure that this array is exactly the type it needs
* to be for correctness. the wrappers are lax with their usage
* so we need to ignore them here
Expand Down Expand Up @@ -10564,7 +10608,10 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b

if (il_op == MONO_CEE_LDELEM) {
klass = mini_get_class (method, token, generic_context);
CHECK_TYPELOAD (klass);
IF_TYPELOAD_ERROR (klass) {
HANDLE_TYPELOAD_ERROR (cfg, klass);
break; // reached only in AOT
}
mono_class_init_internal (klass);
}
else
Expand Down Expand Up @@ -10612,7 +10659,10 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b

if (il_op == MONO_CEE_STELEM) {
klass = mini_get_class (method, token, generic_context);
CHECK_TYPELOAD (klass);
IF_TYPELOAD_ERROR (klass) {
HANDLE_TYPELOAD_ERROR (cfg, klass);
break; // reached only in AOT
}
mono_class_init_internal (klass);
}
else
Expand Down Expand Up @@ -10659,7 +10709,10 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
MONO_INST_NEW (cfg, ins, il_op);
--sp;
klass = mini_get_class (method, token, generic_context);
CHECK_TYPELOAD (klass);
IF_TYPELOAD_ERROR (klass) {
HANDLE_TYPELOAD_ERROR (cfg, klass);
break; // reached only in AOT
}

context_used = mini_class_check_context_used (cfg, klass);

Expand Down Expand Up @@ -10696,7 +10749,10 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
MONO_INST_NEW (cfg, ins, il_op);
--sp;
klass = mini_get_class (method, token, generic_context);
CHECK_TYPELOAD (klass);
IF_TYPELOAD_ERROR (klass) {
HANDLE_TYPELOAD_ERROR (cfg, klass);
break; // reached only in AOT
}

context_used = mini_class_check_context_used (cfg, klass);

Expand Down Expand Up @@ -11855,16 +11911,25 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
case MONO_CEE_INITOBJ:
--sp;
klass = mini_get_class (method, token, generic_context);
CHECK_TYPELOAD (klass);

IF_TYPELOAD_ERROR (klass) {
HANDLE_TYPELOAD_ERROR (cfg, klass);
inline_costs += 10;
break; // reached only in AOT
}

if (mini_class_is_reference (klass))
MONO_EMIT_NEW_STORE_MEMBASE_IMM (cfg, OP_STORE_MEMBASE_IMM, sp [0]->dreg, 0, 0);
else
mini_emit_initobj (cfg, *sp, NULL, klass);

inline_costs += 1;
break;
case MONO_CEE_CONSTRAINED_:
constrained_class = mini_get_class (method, token, generic_context);
CHECK_TYPELOAD (constrained_class);
IF_TYPELOAD_ERROR (constrained_class) {
HANDLE_TYPELOAD_ERROR (cfg, constrained_class);
}
ins_has_side_effect = FALSE;
break;
case MONO_CEE_CPBLK:
Expand Down Expand Up @@ -11949,7 +12014,10 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
EMIT_NEW_ICONST (cfg, ins, val);
} else {
klass = mini_get_class (method, token, generic_context);
CHECK_TYPELOAD (klass);
IF_TYPELOAD_ERROR (klass) {
HANDLE_TYPELOAD_ERROR (cfg, klass);
break;
}

if (mini_is_gsharedvt_klass (klass)) {
ins = mini_emit_get_gsharedvt_info_klass (cfg, klass, MONO_RGCTX_INFO_CLASS_SIZEOF);
Expand Down
1 change: 1 addition & 0 deletions src/mono/mono/mini/mini-runtime.c
Original file line number Diff line number Diff line change
Expand Up @@ -5139,6 +5139,7 @@ register_icalls (void)
register_icall (mono_throw_not_supported, mono_icall_sig_void, FALSE);
register_icall (mono_throw_platform_not_supported, mono_icall_sig_void, FALSE);
register_icall (mono_throw_invalid_program, mono_icall_sig_void_ptr, FALSE);
register_icall (mono_throw_type_load, mono_icall_sig_void_ptr, FALSE);
register_icall_no_wrapper (mono_dummy_jit_icall, mono_icall_sig_void);
//register_icall_no_wrapper (mono_dummy_jit_icall_val, mono_icall_sig_void_ptr);
register_icall_no_wrapper (mini_init_method_rgctx, mono_icall_sig_void_ptr_ptr);
Expand Down
9 changes: 7 additions & 2 deletions src/mono/mono/mini/mini.c
Original file line number Diff line number Diff line change
Expand Up @@ -660,7 +660,9 @@ mono_compile_create_var_for_vreg (MonoCompile *cfg, MonoType *type, int opcode,
inst->backend.is_pinvoke = 0;
inst->dreg = vreg;

if (mono_class_has_failure (inst->klass))
// In AOT, we do not set the exception so that the compilation can succeed. To indicate
// the error, an exception is thrown in run-time.
if (!cfg->compile_aot && mono_class_has_failure (inst->klass))
mono_cfg_set_exception (cfg, MONO_EXCEPTION_TYPE_LOAD);

if (cfg->compute_gc_maps) {
Expand Down Expand Up @@ -1351,7 +1353,10 @@ mono_allocate_stack_slots (MonoCompile *cfg, gboolean backward, guint32 *stack_s
size = mini_type_stack_size (t, &ialign);
align = ialign;

if (mono_class_has_failure (mono_class_from_mono_type_internal (t)))
// In AOT, we do not set the exception but allow the compilation to succeed. The error will be
// indicated in runtime by throwing an exception when an operation with the invalid object is
// attempted.
if (!cfg->compile_aot && mono_class_has_failure (mono_class_from_mono_type_internal (t)))
mono_cfg_set_exception (cfg, MONO_EXCEPTION_TYPE_LOAD);

if (mini_class_is_simd (cfg, mono_class_from_mono_type_internal (t)))
Expand Down
9 changes: 0 additions & 9 deletions src/tests/issues.targets
Original file line number Diff line number Diff line change
Expand Up @@ -2405,15 +2405,6 @@
<ExcludeList Include="$(XunitTestBinBase)/Loader/classloader/explicitlayout/objrefandnonobjrefoverlap/case9/**">
<Issue>expected failure: overlapped structs fail at AOT compile time, not runtime</Issue>
</ExcludeList>
<ExcludeList Include = "$(XunitTestBinBase)/Loader/classloader/explicitlayout/NestedStructs/case03/**">
<Issue>expected failure: overlapped structs fail at AOT compile time, not runtime</Issue>
</ExcludeList>
<ExcludeList Include = "$(XunitTestBinBase)/Loader/classloader/explicitlayout/NestedStructs/case04/**">
<Issue>expected failure: overlapped structs fail at AOT compile time, not runtime</Issue>
</ExcludeList>
<ExcludeList Include = "$(XunitTestBinBase)/Loader/classloader/explicitlayout/NestedStructs/case05/**">
<Issue>expected failure: overlapped structs fail at AOT compile time, not runtime</Issue>
</ExcludeList>
<ExcludeList Include = "$(XunitTestBinBase)/Loader/classloader/RefFields/Validate/**">
<Issue>expected failure: unsupported type with ref field fails at AOT compile time, not runtime</Issue>
</ExcludeList>
Expand Down