[netcore] Fix the range checks for Vector.CopyTo(). (mono/mono#16663)
authorZoltan Varga <vargaz@gmail.com>
Thu, 5 Sep 2019 11:55:53 +0000 (07:55 -0400)
committerMarek Safar <marek.safar@gmail.com>
Thu, 5 Sep 2019 11:55:53 +0000 (13:55 +0200)
* [netcore] Fix the range checks for Vector.CopyTo().

* [netcore] Fix Vector.get_Item () for u1/u2, the llvm type is a vector of i1/i2, so we need to zero extend.

Commit migrated from https://github.com/mono/mono/commit/c3541c27389846dafe731999b31e4ade5263dee5

src/mono/mono/mini/mini-llvm.c
src/mono/mono/mini/mini-ops.h
src/mono/mono/mini/simd-intrinsics-netcore.c

index b13c8b1..8d29e71 100644 (file)
@@ -7420,6 +7420,15 @@ process_bb (EmitContext *ctx, MonoBasicBlock *bb)
                        values [ins->dreg] = LLVMBuildPhi (builder, LLVMTypeOf (phi_values [0]), "");
                        LLVMAddIncoming (values [ins->dreg], phi_values, bbs, nelems);
 
+                       MonoTypeEnum type = (MonoTypeEnum)ins->inst_c0;
+                       switch (type) {
+                       case MONO_TYPE_U1:
+                       case MONO_TYPE_U2:
+                               values [ins->dreg] = LLVMBuildZExt (ctx->builder, values [ins->dreg], LLVMInt32Type (), "");
+                               break;
+                       default:
+                               break;
+                       }
                        ctx->bblocks [bb->block_num].end_bblock = cbb;
                        break;
                }
index 29643f1..8269879 100644 (file)
@@ -1389,6 +1389,7 @@ MINI_OP(OP_XBINOP, "xbinop", XREG, XREG, XREG)
 MINI_OP(OP_XCAST, "xcast", XREG, XREG, NONE)
 /* Extract element of vector */
 /* The index is assumed to be in range */
+/* inst_i0 is the element type */
 MINI_OP(OP_XEXTRACT_I32, "xextract_i32", IREG, XREG, IREG)
 MINI_OP(OP_XEXTRACT_I64, "xextract_i64", LREG, XREG, IREG)
 MINI_OP(OP_XEXTRACT_R8, "xextract_r8", FREG, XREG, IREG)
index 6c2ba1c..20146a3 100644 (file)
@@ -341,6 +341,7 @@ emit_sys_numerics_vector_t (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSig
                ins->dreg = dreg;
                ins->sreg1 = load_simd_vreg (cfg, cmethod, args [0], NULL);
                ins->sreg2 = args [1]->dreg;
+               ins->inst_c0 = etype->type;
                mini_type_to_eval_stack_type (cfg, etype, ins);
                MONO_ADD_INS (cfg->cbb, ins);
                return ins;
@@ -402,13 +403,17 @@ emit_sys_numerics_vector_t (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSig
                                EMIT_NEW_ICONST (cfg, index_ins, 0);
                        }
 
-                       /* Emit index check for the end (index + len - 1 < array length) */
+                       /* CopyTo () does complicated argument checks */
+                       mini_emit_bounds_check_offset (cfg, array_ins->dreg, MONO_STRUCT_OFFSET (MonoArray, max_length), index_ins->dreg, "ArgumentOutOfRangeException");
                        end_index_reg = alloc_ireg (cfg);
-                       EMIT_NEW_BIALU_IMM (cfg, ins, OP_IADD_IMM, end_index_reg, index_ins->dreg, len - 1);
-                       mini_emit_bounds_check_offset (cfg, array_ins->dreg, MONO_STRUCT_OFFSET (MonoArray, max_length), end_index_reg, "ArgumentOutOfRangeException");
+                       int len_reg = alloc_ireg (cfg);
+                       MONO_EMIT_NEW_LOAD_MEMBASE_OP_FLAGS (cfg, OP_LOADI4_MEMBASE, len_reg, array_ins->dreg, MONO_STRUCT_OFFSET (MonoArray, max_length), MONO_INST_INVARIANT_LOAD);
+                       EMIT_NEW_BIALU (cfg, ins, OP_ISUB, end_index_reg, len_reg, index_ins->dreg);
+                       MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, end_index_reg, len);
+                       MONO_EMIT_NEW_COND_EXC (cfg, LT, "ArgumentException");
 
                        /* Load the array slice into the simd reg */
-                       ldelema_ins = mini_emit_ldelema_1_ins (cfg, mono_class_from_mono_type_internal (etype), array_ins, index_ins, TRUE);
+                       ldelema_ins = mini_emit_ldelema_1_ins (cfg, mono_class_from_mono_type_internal (etype), array_ins, index_ins, FALSE);
                        EMIT_NEW_STORE_MEMBASE (cfg, ins, OP_STOREX_MEMBASE, ldelema_ins->dreg, 0, val_vreg);
                        ins->klass = cmethod->klass;
                        return ins;