[interp] support non-empty stack in switch branches
authorBernhard Urban <bernhard.urban@xamarin.com>
Tue, 7 Mar 2017 09:47:00 +0000 (10:47 +0100)
committerBernhard Urban <bernhard.urban@xamarin.com>
Wed, 8 Mar 2017 22:02:51 +0000 (23:02 +0100)
mono/mini/iltests.il
mono/mini/interp/transform.c

index aa594838a3bb5361531f0e2bb45f91318da8c79e..d1b03b3931b21e42e60353b4c0dbab3051983496 100644 (file)
@@ -640,7 +640,6 @@ COND:   ldloc.0
        }
 
        .method static public int32 test_11_switch_with_nonempty_stack () il managed {
-               .custom instance void [TestDriver]CategoryAttribute::.ctor(string) = ( 01 00 0C 21 49 4E 54 45 52 50 52 45 54 45 52 00 00 )   // ...!INTERPRETER.
                .maxstack 16
 
                ldc.i4.5
index 31f4e0a0d0705db70ac9cc32c0e1ded4aec471ec..e4cb8c8c20ac4c66166b752fc87146f9b80eaaa3 100644 (file)
@@ -1363,28 +1363,35 @@ generate (MonoMethod *method, RuntimeMethod *rtm, unsigned char *is_bb_start, Mo
                        unsigned short *next_new_ip;
                        ++td.ip;
                        n = read32 (td.ip);
-                       ADD_CODE(&td, MINT_SWITCH);
-                       ADD_CODE(&td, * (unsigned short *)(&n));
-                       ADD_CODE(&td, * ((unsigned short *)&n + 1));
+                       ADD_CODE (&td, MINT_SWITCH);
+                       WRITE32 (&td, &n);
                        td.ip += 4;
                        next_ip = td.ip + n * 4;
                        next_new_ip = td.new_ip + n * 2;
+                       --td.sp;
+                       int stack_height = td.sp - td.stack;
                        for (i = 0; i < n; i++) {
                                offset = read32 (td.ip);
                                target = next_ip - td.il_code + offset;
-                               if (offset < 0)
+                               if (offset < 0) {
+#if DEBUG_INTERP
+                                       if (stack_height > 0 && stack_height != td.stack_height [target])
+                                               g_warning ("SWITCH with back branch and non-empty stack");
+#endif
                                        target = td.in_offsets [target] - (next_new_ip - td.new_code);
-                               else {
+                               } else {
+                                       td.stack_height [target] = stack_height;
+                                       td.vt_stack_size [target] = td.vt_sp;
+                                       if (stack_height > 0)
+                                               td.stack_state [target] = g_memdup (td.stack, stack_height * sizeof (td.stack [0]));
                                        int prev = td.forward_refs [target];
                                        td.forward_refs [td.ip - td.il_code] = prev;
                                        td.forward_refs [target] = td.ip - td.il_code;
                                        td.in_offsets [td.ip - td.il_code] = - (base_ip - td.il_code);
                                }
-                               ADD_CODE(&td, * (unsigned short *)(&target));
-                               ADD_CODE(&td, * ((unsigned short *)&target + 1));
+                               WRITE32 (&td, &target);
                                td.ip += 4;
                        }
-                       --td.sp;
                        break;
                }
                case CEE_LDIND_I1: