Skip to content

Commit

Permalink
[ci skip] Generate false edges from loop_block
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
sapphire-arches committed Feb 7, 2018
1 parent eae1a35 commit 8e0c3f5
Show file tree
Hide file tree
Showing 7 changed files with 81 additions and 67 deletions.
46 changes: 22 additions & 24 deletions src/librustc_mir/build/expr/into.rs
Original file line number Diff line number Diff line change
Expand Up @@ -147,24 +147,24 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
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();
Expand All @@ -178,7 +178,6 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
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!(
Expand All @@ -192,15 +191,14 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
// 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
Expand All @@ -209,7 +207,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
// 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()
Expand Down
13 changes: 8 additions & 5 deletions src/test/mir-opt/end_region_2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,26 +40,29 @@ 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);
// StorageDead(_3);
// StorageDead(_2);
// return;
// }
// bb4: {
// bb5: {
// _4 = ();
// StorageDead(_5);
// StorageLive(_7);
Expand All @@ -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
13 changes: 8 additions & 5 deletions src/test/mir-opt/end_region_3.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,25 +43,28 @@ 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);
// StorageDead(_3);
// StorageDead(_1);
// return;
// }
// bb4: {
// bb5: {
// _4 = ();
// StorageDead(_5);
// StorageLive(_7);
Expand All @@ -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
18 changes: 12 additions & 6 deletions src/test/mir-opt/end_region_9.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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
29 changes: 16 additions & 13 deletions src/test/mir-opt/end_region_cyclic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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);
Expand All @@ -121,17 +124,17 @@ 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);
// StorageDead(_17);
// _1 = ();
// EndRegion('35_0rs);
// StorageDead(_2);
// falseUnwind -> [real: bb1, cleanup: bb2];
// goto -> bb1;
// }
// }
// END rustc.main.SimplifyCfg-qualify-consts.after.mir
13 changes: 7 additions & 6 deletions src/test/mir-opt/issue-38669.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
16 changes: 8 additions & 8 deletions src/test/mir-opt/nll/liveness-drop-intra-block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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

0 comments on commit 8e0c3f5

Please sign in to comment.