[ci skip] Generate false edges from loop_block
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.
This commit is contained in:
parent
eae1a35f55
commit
8e0c3f5c46
7 changed files with 86 additions and 72 deletions
|
@ -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();
|
||||
|
@ -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!(
|
||||
|
@ -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
|
||||
|
@ -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()
|
||||
|
|
|
@ -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];
|
||||
// }
|
||||
// bb2: {
|
||||
// ...
|
||||
// switchInt(move _5) -> [0u8: bb5, otherwise: bb4];
|
||||
// }
|
||||
// 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
|
||||
|
|
|
@ -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];
|
||||
// }
|
||||
// bb2: {
|
||||
// ...
|
||||
// switchInt(move _5) -> [0u8: bb5, otherwise: bb4];
|
||||
// }
|
||||
// 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
|
||||
|
|
|
@ -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(_7);
|
||||
// _7 = _1;
|
||||
// switchInt(move _7) -> [0u8: bb4, otherwise: bb3];
|
||||
// StorageLive(_4);
|
||||
// goto -> bb3;
|
||||
// }
|
||||
// bb3: {
|
||||
// falseUnwind -> [real: bb4, cleanup: bb1];
|
||||
// }
|
||||
// bb4: {
|
||||
// StorageLive(_7);
|
||||
// _7 = _1;
|
||||
// switchInt(move _7) -> [0u8: bb6, otherwise: bb5];
|
||||
// }
|
||||
// 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
|
||||
|
|
|
@ -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];
|
||||
// }
|
||||
// bb2: {
|
||||
// resume;
|
||||
// _3 = const <std::cell::Cell<T>>::new(move _4) -> [return: bb4, unwind: bb3];
|
||||
// }
|
||||
// bb3: {
|
||||
// resume;
|
||||
// }
|
||||
// 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
|
||||
|
|
|
@ -27,27 +27,28 @@ fn main() {
|
|||
// _1 = const false;
|
||||
// goto -> bb2;
|
||||
// }
|
||||
//
|
||||
// bb1: {
|
||||
// resume;
|
||||
// }
|
||||
// bb2: {
|
||||
// StorageLive(_4);
|
||||
// _4 = _1;
|
||||
// switchInt(move _4) -> [0u8: bb4, otherwise: bb3];
|
||||
// falseUnwind -> [real: bb3, cleanup: bb1];
|
||||
// }
|
||||
// bb3: {
|
||||
// StorageLive(_4);
|
||||
// _4 = _1;
|
||||
// switchInt(move _4) -> [0u8: bb5, otherwise: bb4];
|
||||
// }
|
||||
// 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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Add table
Reference in a new issue