From 32c5e9f9f0519ab8bd9041914bc2f96ab72c438c Mon Sep 17 00:00:00 2001 From: Ben Maurer Date: Tue, 21 Dec 2004 17:48:29 +0000 Subject: [PATCH] * iltests.il: New test for LDELEMA on an array of ref types. * mini.c (CEE_LDELEMA): We need to emit OP_CHECK_ARRAY_TYPE for all ldelema's on reftypes. (check_call_signature): Remove the OP_CHECK_ARRAY_TYPE from here, it was the wrong place to put it. svn path=/trunk/mono/; revision=38037 --- mono/mini/ChangeLog | 7 +++++++ mono/mini/iltests.il | 28 ++++++++++++++++++++++++++++ mono/mini/mini.c | 34 +++++++++++++++------------------- 3 files changed, 50 insertions(+), 19 deletions(-) diff --git a/mono/mini/ChangeLog b/mono/mini/ChangeLog index be822191691..18495849efd 100644 --- a/mono/mini/ChangeLog +++ b/mono/mini/ChangeLog @@ -9,6 +9,13 @@ Tue Dec 21 17:43:06 CET 2004 Paolo Molaro 2004-12-21 Ben Maurer + * iltests.il: New test for LDELEMA on an array of ref types. + + * mini.c (CEE_LDELEMA): We need to emit OP_CHECK_ARRAY_TYPE for + all ldelema's on reftypes. + (check_call_signature): Remove the OP_CHECK_ARRAY_TYPE from here, + it was the wrong place to put it. + * mini-x86.c (mono_arch_output_basic_block): Just use ecx as the register to pop to make this cleaner, at the request of Paolo. diff --git a/mono/mini/iltests.il b/mono/mini/iltests.il index e99a3165bf9..b86f00f1340 100644 --- a/mono/mini/iltests.il +++ b/mono/mini/iltests.il @@ -596,4 +596,32 @@ COND: ldloc.0 ceq ret } + + .method public static int32 test_1_array_type_mismatch_ldelema () { + .locals init (int32 r) + + ldc.i4.1 + newarr string + ldc.i4.0 + ldelema string + pop + + .try { + ldc.i4.1 + newarr string + ldc.i4.0 + ldelema object + pop + + leave end + } catch [mscorlib]System.ArrayTypeMismatchException { + pop + ldc.i4.1 + stloc.0 + leave end + } + end: + ldloc.0 + ret + } } diff --git a/mono/mini/mini.c b/mono/mini/mini.c index 607c3c0c213..d07aa41935c 100644 --- a/mono/mini/mini.c +++ b/mono/mini/mini.c @@ -1889,25 +1889,6 @@ check_call_signature (MonoCompile *cfg, MonoMethodSignature *sig, MonoInst **arg } for (i = 0; i < sig->param_count; ++i) { if (sig->params [i]->byref) { - /* - * check the result of ldelema is only passed as an argument if the byref - * type matches exactly the array element type. - * FIXME: if the argument as been saved on the stack as part of the - * interface variable code (the value was on the stack at a basic block boundary) - * we need to add the check in that case, too. - */ - if (args [i]->opcode == CEE_LDELEMA) { - MonoInst *check; - MonoClass *exact_class = mono_class_from_mono_type (sig->params [i]); - if (!exact_class->valuetype) { - MONO_INST_NEW (cfg, check, OP_CHECK_ARRAY_TYPE); - check->cil_code = args [i]->cil_code; - check->klass = exact_class; - check->inst_left = args [i]->inst_left; - check->type = STACK_OBJ; - args [i]->inst_left = check; - } - } if (args [i]->type != STACK_MP && args [i]->type != STACK_PTR) return 1; continue; @@ -5067,6 +5048,21 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b klass = (MonoClass*)mono_method_get_wrapper_data (method, read32 (ip + 1)); else klass = mono_class_get_full (image, read32 (ip + 1), generic_context); + + /* we need to make sure that this array is exactly the type it needs + * to be for correctness. the stelemref wrapper is lax with its usage + * so we need to ignore it there + */ + if (!klass->valuetype && method->wrapper_type != MONO_WRAPPER_STELEMREF) { + MonoInst* check; + MONO_INST_NEW (cfg, check, OP_CHECK_ARRAY_TYPE); + check->cil_code = ip; + check->klass = klass; + check->inst_left = sp [0]; + check->type = STACK_OBJ; + sp [0] = check; + } + mono_class_init (klass); NEW_LDELEMA (cfg, ins, sp, klass); ins->cil_code = ip; -- 2.11.4.GIT