[llvm] Zero extend array indexes when targeting llvm, this seems to work around a...
authorZoltan Varga <vargaz@gmail.com>
Tue, 1 Dec 2015 23:50:31 +0000 (18:50 -0500)
committerZoltan Varga <vargaz@gmail.com>
Tue, 1 Dec 2015 23:51:21 +0000 (18:51 -0500)
mono/mini/exceptions.cs
mono/mini/method-to-ir.c

index 0148488dee3a3ab0ca92865eaf656c14f4a0fb93..e84abc68b019d0994e72115d53373ee2097a8f99 100644 (file)
@@ -2816,6 +2816,34 @@ class Tests
                }
                return finally_called ? 0 : 1;
        }
+
+       static int array_len_1 = 1;
+
+       public static int test_0_bounds_check_negative_constant () {
+               try {
+                       byte[] arr = new byte [array_len_1];
+                       byte b = arr [-1];
+                       return 1;
+               } catch {
+               }
+               try {
+                       byte[] arr = new byte [array_len_1];
+                       arr [-1] = 1;
+                       return 2;
+               } catch {
+               }
+               return 0;
+       }
+
+       public static int test_0_string_bounds_check_negative_constant () {
+               try {
+                       string s = "A";
+                       char c = s [-1];
+                       return 1;
+               } catch {
+               }
+               return 0;
+       }
 }
 
 #if !__MOBILE__
index 26536d45eff761c95cdb856c2b39fea390e401b1..1f7a6299738f5214fb57c5b066196c3fdb531b9d 100644 (file)
@@ -5638,6 +5638,9 @@ emit_array_store (MonoCompile *cfg, MonoClass *klass, MonoInst **sp, gboolean sa
                        int index_reg = sp [1]->dreg;
                        int offset = (mono_class_array_element_size (klass) * sp [1]->inst_c0) + MONO_STRUCT_OFFSET (MonoArray, vector);
 
+                       if (SIZEOF_REGISTER == 8 && COMPILE_LLVM (cfg))
+                               MONO_EMIT_NEW_UNALU (cfg, OP_ZEXT_I4, index_reg, index_reg);
+
                        if (safety_checks)
                                MONO_EMIT_BOUNDS_CHECK (cfg, array_reg, MonoArray, max_length, index_reg);
                        EMIT_NEW_STORE_MEMBASE_TYPE (cfg, ins, &klass->byval_arg, array_reg, offset, sp [2]->dreg);
@@ -5889,8 +5892,12 @@ mini_emit_inst_for_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSign
                        int add_reg = alloc_preg (cfg);
 
 #if SIZEOF_REGISTER == 8
-                       /* The array reg is 64 bits but the index reg is only 32 */
-                       MONO_EMIT_NEW_UNALU (cfg, OP_SEXT_I4, index_reg, args [1]->dreg);
+                       if (COMPILE_LLVM (cfg)) {
+                               MONO_EMIT_NEW_UNALU (cfg, OP_ZEXT_I4, index_reg, args [1]->dreg);
+                       } else {
+                               /* The array reg is 64 bits but the index reg is only 32 */
+                               MONO_EMIT_NEW_UNALU (cfg, OP_SEXT_I4, index_reg, args [1]->dreg);
+                       }
 #else
                        index_reg = args [1]->dreg;
 #endif 
@@ -11716,6 +11723,9 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                int index_reg = sp [1]->dreg;
                                int offset = (mono_class_array_element_size (klass) * sp [1]->inst_c0) + MONO_STRUCT_OFFSET (MonoArray, vector);
 
+                               if (SIZEOF_REGISTER == 8 && COMPILE_LLVM (cfg))
+                                       MONO_EMIT_NEW_UNALU (cfg, OP_ZEXT_I4, index_reg, index_reg);
+
                                MONO_EMIT_BOUNDS_CHECK (cfg, array_reg, MonoArray, max_length, index_reg);
                                EMIT_NEW_LOAD_MEMBASE_TYPE (cfg, ins, &klass->byval_arg, array_reg, offset);
                        } else {