]> git.lizzy.rs Git - rust.git/commitdiff
[ci skip] Generate false edges from loop_block
authorbobtwinkles <srkoser+GitHub@gmail.com>
Wed, 7 Feb 2018 19:25:08 +0000 (14:25 -0500)
committerbobtwinkles <srkoser+GitHub@gmail.com>
Wed, 7 Feb 2018 19:25:08 +0000 (14:25 -0500)
As opposed to using weirdness involving pretending the body block
is the loop block. This does not pass tests

This commit is [ci skip] because I know it doesn't pass tests yet.
Somehow this commit introduces nondeterminism into the handling of
loops.

src/librustc_mir/build/expr/into.rs
src/test/mir-opt/end_region_2.rs
src/test/mir-opt/end_region_3.rs
src/test/mir-opt/end_region_9.rs
src/test/mir-opt/end_region_cyclic.rs
src/test/mir-opt/issue-38669.rs
src/test/mir-opt/nll/liveness-drop-intra-block.rs

index 089ce3f71a5baef569e8e690800a534c4c527170..28dc329e4fe7cd48ab8b77a906fbb49ef0e3a1c7 100644 (file)
@@ -147,24 +147,24 @@ pub fn into_expr(&mut self,
                 join_block.unit()
             }
             ExprKind::Loop { condition: opt_cond_expr, body } => {
-                // [block] --> [loop_block] ~~> [loop_block_end] -1-> [exit_block]
-                //                  ^                  |
-                //                  |                  0
-                //                  |                  |
-                //                  |                  v
-                //           [body_block_end] <~~~ [body_block]
+                // [block] --> [loop_block] -/eval. cond./-> [loop_block_end] -1-> [exit_block]
+                //                  ^                               |
+                //                  |                               0
+                //                  |                               |
+                //                  |                               v
+                //           [body_block_end] <-/eval. body/-- [body_block]
                 //
                 // If `opt_cond_expr` is `None`, then the graph is somewhat simplified:
                 //
-                // [block] --> [loop_block] ~~> [loop_block_end]
-                //               |  ^                   |
-                //      false link  |                   |
-                //               |  +-------------------+
-                //               v
-                //        [cleanup_block]
-                //
-                // The false link is required in case something results in
-                // unwinding through the body.
+                // [block]
+                //    |
+                //   [loop_block] -> [body_block] -/eval. body/-> [body_block_end]
+                //    |        ^                                         |
+                // false link  |                                         |
+                //    |        +-----------------------------------------+
+                //    +-> [diverge_cleanup]
+                // The false link is required to make sure borrowck considers unwinds through the
+                // body, even when the exact code in the body cannot unwind
 
                 let loop_block = this.cfg.start_new_block();
                 let exit_block = this.cfg.start_new_block();
@@ -178,7 +178,6 @@ pub fn into_expr(&mut self,
                     move |this| {
                         // conduct the test, if necessary
                         let body_block;
-                        let out_terminator;
                         if let Some(cond_expr) = opt_cond_expr {
                             let loop_block_end;
                             let cond = unpack!(
@@ -192,15 +191,14 @@ pub fn into_expr(&mut self,
                             // we have to do it; this overwrites any `break`-assigned value but it's
                             // always `()` anyway
                             this.cfg.push_assign_unit(exit_block, source_info, destination);
-
-                            out_terminator = TerminatorKind::Goto { target: loop_block };
                         } else {
-                            body_block = loop_block;
+                            body_block = this.cfg.start_new_block();
                             let diverge_cleanup = this.diverge_cleanup();
-                            out_terminator = TerminatorKind::FalseUnwind {
-                                real_target: loop_block,
-                                unwind: Some(diverge_cleanup)
-                            }
+                            this.cfg.terminate(loop_block, source_info,
+                                               TerminatorKind::FalseUnwind {
+                                                   real_target: body_block,
+                                                   unwind: Some(diverge_cleanup)
+                                               })
                         }
 
                         // The “return” value of the loop body must always be an unit. We therefore
@@ -209,7 +207,7 @@ pub fn into_expr(&mut self,
                         // Execute the body, branching back to the test.
                         let body_block_end = unpack!(this.into(&tmp, body_block, body));
                         this.cfg.terminate(body_block_end, source_info,
-                                           out_terminator);
+                                           TerminatorKind::Goto { target: loop_block });
                     }
                 );
                 exit_block.unit()
index 958e9364c8fa854ec822f221b2363a54cfce3ece..d6084d5a6da9237878cddb9d955f7d86736fbad7 100644 (file)
@@ -40,18 +40,21 @@ fn main() {
 //         goto -> bb1;
 //     }
 //     bb1: {
+//          falseUnwind -> [real: bb2, cleanup: bb3];
+//     }
+//     bb2: {
 //         StorageLive(_2);
 //         _2 = const true;
 //         StorageLive(_3);
 //         _3 = &'23_1rs _2;
 //         StorageLive(_5);
 //         _5 = _2;
-//         switchInt(move _5) -> [0u8: bb4, otherwise: bb3];
+//         switchInt(move _5) -> [0u8: bb5, otherwise: bb4];
 //     }
-//     bb2: {
+//     bb3: {
 //         ...
 //     }
-//     bb3: {
+//     bb4: {
 //         _0 = ();
 //         StorageDead(_5);
 //         EndRegion('23_1rs);
@@ -59,7 +62,7 @@ fn main() {
 //         StorageDead(_2);
 //         return;
 //     }
-//     bb4: {
+//     bb5: {
 //         _4 = ();
 //         StorageDead(_5);
 //         StorageLive(_7);
@@ -70,6 +73,6 @@ fn main() {
 //         EndRegion('23_1rs);
 //         StorageDead(_3);
 //         StorageDead(_2);
-//         falseUnwind -> [real: bb1, cleanup: bb2];
+//         goto -> bb1;
 //     }
 // END rustc.main.SimplifyCfg-qualify-consts.after.mir
index c1ebc525e88ed59f7eba208456a51c0283de6093..46548f1cce97868213d29f08a931a696dc33289a 100644 (file)
@@ -43,17 +43,20 @@ fn main() {
 //         goto -> bb1;
 //     }
 //     bb1: {
+//         falseUnwind -> [real: bb2, cleanup: bb3];
+//     }
+//     bb2: {
 //         _1 = const true;
 //         StorageLive(_3);
 //         _3 = &'26_1rs _1;
 //         StorageLive(_5);
 //         _5 = _1;
-//         switchInt(move _5) -> [0u8: bb4, otherwise: bb3];
+//         switchInt(move _5) -> [0u8: bb5, otherwise: bb4];
 //     }
-//     bb2: {
+//     bb3: {
 //         ...
 //     }
-//     bb3: {
+//     bb4: {
 //         _0 = ();
 //         StorageDead(_5);
 //         EndRegion('26_1rs);
@@ -61,7 +64,7 @@ fn main() {
 //         StorageDead(_1);
 //         return;
 //     }
-//     bb4: {
+//     bb5: {
 //         _4 = ();
 //         StorageDead(_5);
 //         StorageLive(_7);
@@ -71,6 +74,6 @@ fn main() {
 //         StorageDead(_7);
 //         EndRegion('26_1rs);
 //         StorageDead(_3);
-//         falseUnwind -> [real: bb1, cleanup: bb2];
+//         goto -> bb1;
 //     }
 // END rustc.main.SimplifyCfg-qualify-consts.after.mir
index 70611306fd328f02ad7062ba3fd466ddc41e7896..0f1d714cc6fd2ec68758f34ed0edba7da810d13f 100644 (file)
@@ -57,18 +57,24 @@ fn main() {
 //        _1 = const false;
 //        StorageLive(_2);
 //        _2 = const 3i32;
-//        StorageLive(_4);
-//        goto -> bb2;
+//        falseUnwind -> [real: bb2, cleanup: bb1];
 //    }
 //    bb1: {
 //        ...
 //    }
 //    bb2: {
+//        StorageLive(_4);
+//        goto -> bb3;
+//    }
+//    bb3: {
+//        falseUnwind -> [real: bb4, cleanup: bb1];
+//    }
+//    bb4: {
 //        StorageLive(_7);
 //        _7 = _1;
-//        switchInt(move _7) -> [0u8: bb4, otherwise: bb3];
+//        switchInt(move _7) -> [0u8: bb6, otherwise: bb5];
 //    }
-//    bb3: {
+//    bb5: {
 //        _0 = ();
 //        StorageDead(_7);
 //        EndRegion('33_0rs);
@@ -77,13 +83,13 @@ fn main() {
 //        StorageDead(_1);
 //        return;
 //    }
-//    bb4: {
+//    bb6: {
 //        _4 = &'33_0rs _2;
 //        _6 = ();
 //        StorageDead(_7);
 //        _1 = const true;
 //        _3 = ();
-//        falseUnwind -> [real: bb2, cleanup: bb1];
+//        goto -> bb3;
 //    }
 // }
 // END rustc.main.SimplifyCfg-qualify-consts.after.mir
index 801c4eed4d20b1ec5eb8eb585b5d7d0cab511611..2a82e2675b67dafe59c8e1dfb0f28631826f85dd 100644 (file)
@@ -67,16 +67,19 @@ fn query() -> bool { true }
 //         goto -> bb1;
 //     }
 //     bb1: {
+//         falseUnwind -> [real: bb2, cleanup: bb3];
+//     }
+//     bb2: {
 //         StorageLive(_2);
 //         StorageLive(_3);
 //         StorageLive(_4);
 //         _4 = std::option::Option<&'35_0rs S<'35_0rs>>::None;
-//         _3 = const <std::cell::Cell<T>>::new(move _4) -> [return: bb3, unwind: bb2];
+//         _3 = const <std::cell::Cell<T>>::new(move _4) -> [return: bb4, unwind: bb3];
 //     }
-//     bb2: {
+//     bb3: {
 //         resume;
 //     }
-//     bb3: {
+//     bb4: {
 //         StorageDead(_4);
 //         _2 = S<'35_0rs> { r: move _3 };
 //         StorageDead(_3);
@@ -89,27 +92,27 @@ fn query() -> bool { true }
 //         _8 = &'35_0rs (*_9);
 //         _7 = std::option::Option<&'35_0rs S<'35_0rs>>::Some(move _8,);
 //         StorageDead(_8);
-//         _5 = const <std::cell::Cell<T>>::set(move _6, move _7) -> [return: bb4, unwind: bb2];
+//         _5 = const <std::cell::Cell<T>>::set(move _6, move _7) -> [return: bb5, unwind: bb3];
 //     }
-//     bb4: {
+//     bb5: {
 //         EndRegion('16s);
 //         StorageDead(_7);
 //         StorageDead(_6);
 //         StorageDead(_9);
 //         StorageLive(_11);
-//         _11 = const query() -> [return: bb5, unwind: bb2];
-//     }
-//     bb5: {
-//         switchInt(move _11) -> [0u8: bb7, otherwise: bb6];
+//         _11 = const query() -> [return: bb6, unwind: bb3];
 //     }
 //     bb6: {
+//         switchInt(move _11) -> [0u8: bb8, otherwise: bb7];
+//     }
+//     bb7: {
 //         _0 = ();
 //         StorageDead(_11);
 //         EndRegion('35_0rs);
 //         StorageDead(_2);
 //         return;
 //     }
-//     bb7: {
+//     bb8: {
 //         _10 = ();
 //         StorageDead(_11);
 //         StorageLive(_14);
@@ -121,9 +124,9 @@ fn query() -> bool { true }
 //         _16 = &'35_0rs (*_17);
 //         _15 = std::option::Option<&'35_0rs S<'35_0rs>>::Some(move _16,);
 //         StorageDead(_16);
-//         _13 = const <std::cell::Cell<T>>::set(move _14, move _15) -> [return: bb8, unwind: bb2];
+//         _13 = const <std::cell::Cell<T>>::set(move _14, move _15) -> [return: bb9, unwind: bb3];
 //     }
-//     bb8: {
+//     bb9: {
 //         EndRegion('33s);
 //         StorageDead(_15);
 //         StorageDead(_14);
@@ -131,7 +134,7 @@ fn query() -> bool { true }
 //         _1 = ();
 //         EndRegion('35_0rs);
 //         StorageDead(_2);
-//         falseUnwind -> [real: bb1, cleanup: bb2];
+//         goto -> bb1;
 //     }
 // }
 // END rustc.main.SimplifyCfg-qualify-consts.after.mir
index 4444d96798fcf2295c5df6233e585064ea2f87eb..3151c0643079c175bc4c4744760bb201cdc63f27 100644 (file)
@@ -27,27 +27,28 @@ fn main() {
 //         _1 = const false;
 //         goto -> bb2;
 //     }
-//
 //     bb1: {
 //         resume;
 //     }
 //     bb2: {
+//         falseUnwind -> [real: bb3, cleanup: bb1];
+//     }
+//     bb3: {
 //         StorageLive(_4);
 //         _4 = _1;
-//         switchInt(move _4) -> [0u8: bb4, otherwise: bb3];
+//         switchInt(move _4) -> [0u8: bb5, otherwise: bb4];
 //     }
-//     bb3: {
+//     bb4: {
 //         _0 = ();
 //         StorageDead(_4);
 //         StorageDead(_1);
 //         return;
 //     }
-//
-//     bb4: {
+//     bb5: {
 //         _3 = ();
 //         StorageDead(_4);
 //         _1 = const true;
 //         _2 = ();
-//         falseUnwind -> [real: bb2, cleanup: bb1];
+//         goto -> bb2;
 //     }
 // END rustc.main.SimplifyCfg-initial.after.mir
index b060222a95f1701ea42b1c9a5c7ec44b91db1556..64ffc7446062cb171b7ced9ca4e792e0e16ce304 100644 (file)
@@ -25,17 +25,17 @@ fn main() {
 
 // END RUST SOURCE
 // START rustc.main.nll.0.mir
-//    | Live variables on entry to bb2: []
-//    bb2: {
-//            | Live variables on entry to bb2[0]: []
+//    | Live variables on entry to bb3: []
+//    bb3: {
+//            | Live variables on entry to bb3[0]: []
 //        _1 = const 55usize;
-//            | Live variables on entry to bb2[1]: [_1]
+//            | Live variables on entry to bb3[1]: [_1]
 //        StorageLive(_3);
-//            | Live variables on entry to bb2[2]: [_1]
+//            | Live variables on entry to bb3[2]: [_1]
 //        StorageLive(_4);
-//            | Live variables on entry to bb2[3]: [_1]
+//            | Live variables on entry to bb3[3]: [_1]
 //        _4 = _1;
-//            | Live variables on entry to bb2[4]: [_4]
-//        _3 = const use_x(move _4) -> [return: bb3, unwind: bb1];
+//            | Live variables on entry to bb3[4]: [_4]
+//        _3 = const use_x(move _4) -> [return: bb4, unwind: bb1];
 //    }
 // END rustc.main.nll.0.mir