Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 17 additions & 11 deletions compiler/rustc_mir_transform/src/coroutine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,7 @@ const SELF_ARG: Local = Local::from_u32(1);
const CTX_ARG: Local = Local::from_u32(2);

/// A `yield` point in the coroutine.
#[derive(Debug)]
struct SuspensionPoint<'tcx> {
/// State discriminant used when suspending or resuming at this point.
state: usize,
Expand Down Expand Up @@ -651,7 +652,7 @@ fn replace_resume_ty_local<'tcx>(
// We have to replace the `ResumeTy` that is used for type and borrow checking
// with `&mut Context<'_>` in MIR.
#[cfg(debug_assertions)]
{
if local_ty != context_mut_ref {
if let ty::Adt(resume_ty_adt, _) = local_ty.kind() {
let expected_adt = tcx.adt_def(tcx.require_lang_item(LangItem::ResumeTy, body.span));
assert_eq!(*resume_ty_adt, expected_adt);
Expand Down Expand Up @@ -1326,16 +1327,6 @@ fn create_coroutine_resume_function<'tcx>(
make_coroutine_state_argument_indirect(tcx, body);
}
}

// Make sure we remove dead blocks to remove
// unrelated code from the drop part of the function
simplify::remove_dead_blocks(body);

pm::run_passes_no_validate(tcx, body, &[&abort_unwinding_calls::AbortUnwindingCalls], None);

if let Some(dumper) = MirDumper::new(tcx, "coroutine_resume", body) {
dumper.dump_mir(body);
}
}

/// An operation that can be performed on a coroutine.
Expand Down Expand Up @@ -1691,6 +1682,21 @@ impl<'tcx> crate::MirPass<'tcx> for StateTransform {
// Create the Coroutine::resume / Future::poll function
create_coroutine_resume_function(tcx, transform, body, can_return, can_unwind);

if let Some(dumper) = MirDumper::new(tcx, "coroutine_resume", body) {
dumper.dump_mir(body);
}

pm::run_passes_no_validate(
tcx,
body,
&[
&crate::abort_unwinding_calls::AbortUnwindingCalls,
&crate::simplify::SimplifyCfg::PostStateTransform,
&crate::simplify::SimplifyLocals::PostStateTransform,
],
None,
);

// Run derefer to fix Derefs that are not in the first place
deref_finder(tcx, body, false);
}
Expand Down
11 changes: 8 additions & 3 deletions compiler/rustc_mir_transform/src/dataflow_const_prop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,12 @@ impl<'tcx> crate::MirPass<'tcx> for DataflowConstProp {
return;
}

// Avoid computing layout inside coroutines, since their `optimized_mir` is used for layout
// computation, which can create a cycle.
if body.coroutine.is_some() {
return;
}

// We want to have a somewhat linear runtime w.r.t. the number of statements/terminators.
// Let's call this number `n`. Dataflow analysis has `O(h*n)` transfer function
// applications, where `h` is the height of the lattice. Because the height of our lattice
Expand Down Expand Up @@ -237,9 +243,8 @@ impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> {
TerminatorKind::Drop { place, .. } => {
state.flood_with(place.as_ref(), &self.map, FlatSet::<Scalar>::BOTTOM);
}
TerminatorKind::Yield { .. } => {
// They would have an effect, but are not allowed in this phase.
bug!("encountered disallowed terminator");
TerminatorKind::Yield { resume_arg, .. } => {
state.flood_with(resume_arg.as_ref(), &self.map, FlatSet::<Scalar>::BOTTOM);
}
TerminatorKind::SwitchInt { discr, targets } => {
return self.handle_switch_int(discr, targets, state);
Expand Down
20 changes: 12 additions & 8 deletions compiler/rustc_mir_transform/src/gvn.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1912,14 +1912,18 @@ impl<'tcx> MutVisitor<'tcx> for VnState<'_, '_, 'tcx> {
}

fn visit_terminator(&mut self, terminator: &mut Terminator<'tcx>, location: Location) {
if let Terminator { kind: TerminatorKind::Call { destination, .. }, .. } = terminator {
if let Some(local) = destination.as_local()
&& self.ssa.is_ssa(local)
{
let ty = self.local_decls[local].ty;
let opaque = self.new_opaque(ty);
self.assign(local, opaque);
}
let destination = match terminator.kind {
TerminatorKind::Call { destination, .. } => Some(destination),
TerminatorKind::Yield { resume_arg, .. } => Some(resume_arg),
_ => None,
};
if let Some(destination) = destination
&& let Some(local) = destination.as_local()
&& self.ssa.is_ssa(local)
{
let ty = self.local_decls[local].ty;
let opaque = self.new_opaque(ty);
self.assign(local, opaque);
}
// Terminators that can write to memory may invalidate (nested) derefs.
if terminator.kind.can_write_to_memory() {
Expand Down
7 changes: 4 additions & 3 deletions compiler/rustc_mir_transform/src/jump_threading.rs
Original file line number Diff line number Diff line change
Expand Up @@ -610,9 +610,9 @@ impl<'a, 'tcx> TOFinder<'a, 'tcx> {
| TerminatorKind::Unreachable
| TerminatorKind::CoroutineDrop => bug!("{term:?} has no terminators"),
// Disallowed during optimizations.
TerminatorKind::FalseEdge { .. }
| TerminatorKind::FalseUnwind { .. }
| TerminatorKind::Yield { .. } => bug!("{term:?} invalid"),
TerminatorKind::FalseEdge { .. } | TerminatorKind::FalseUnwind { .. } => {
bug!("{term:?} invalid")
}
// Cannot reason about inline asm.
TerminatorKind::InlineAsm { .. } => return,
// `SwitchInt` is handled specially.
Expand All @@ -621,6 +621,7 @@ impl<'a, 'tcx> TOFinder<'a, 'tcx> {
TerminatorKind::Goto { .. } => None,
// Flood the overwritten place, and progress through.
TerminatorKind::Drop { place: destination, .. }
| TerminatorKind::Yield { resume_arg: destination, .. }
| TerminatorKind::Call { destination, .. } => Some(destination),
// Ignore, as this can be a no-op at codegen time.
TerminatorKind::Assert { .. } => None,
Expand Down
10 changes: 6 additions & 4 deletions compiler/rustc_mir_transform/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ mod ssa;
macro_rules! declare_passes {
(
$(
$vis:vis mod $mod_name:ident : $($pass_name:ident $( { $($ident:ident),* } )?),+ $(,)?;
$vis:vis mod $mod_name:ident : $($pass_name:ident $( { $($ident:ident),* $(,)? } )?),+ $(,)?;
)*
) => {
$(
Expand Down Expand Up @@ -181,12 +181,14 @@ declare_passes! {
PreOptimizations,
Final,
MakeShim,
AfterUnreachableEnumBranching
AfterUnreachableEnumBranching,
PostStateTransform,
},
SimplifyLocals {
BeforeConstProp,
AfterGVN,
Final
Final,
PostStateTransform,
};
mod simplify_branches : SimplifyConstCondition {
AfterInstSimplify,
Expand Down Expand Up @@ -627,7 +629,6 @@ fn run_runtime_lowering_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
&add_retag::AddRetag,
&erase_deref_temps::EraseDerefTemps,
&elaborate_box_derefs::ElaborateBoxDerefs,
&coroutine::StateTransform,
&Lint(known_panics_lint::KnownPanicsLint),
];
pm::run_passes_no_validate(tcx, body, passes, Some(MirPhase::Runtime(RuntimePhase::Initial)));
Expand Down Expand Up @@ -742,6 +743,7 @@ pub(crate) fn run_optimization_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'
&simplify::SimplifyLocals::Final,
&multiple_return_terminators::MultipleReturnTerminators,
&large_enums::EnumSizeOpt { discrepancy: 128 },
&coroutine::StateTransform,
// Some cleanup necessary at least for LLVM and potentially other codegen backends.
&add_call_guards::CriticalCallEdges,
// Cleanup for human readability, off by default.
Expand Down
1 change: 0 additions & 1 deletion compiler/rustc_mir_transform/src/shim.rs
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,6 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceKind<'tcx>) -> Body<
tcx,
&mut body,
&[
&mentioned_items::MentionedItems,
&abort_unwinding_calls::AbortUnwindingCalls,
&add_call_guards::CriticalCallEdges,
],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,7 @@ fn build_adrop_for_coroutine_shim<'tcx>(
body.source.instance = instance;
body.phase = MirPhase::Runtime(RuntimePhase::Initial);
body.var_debug_info.clear();
body.mentioned_items = None;
let pin_adt_ref = tcx.adt_def(tcx.require_lang_item(LangItem::Pin, span));
let args = tcx.mk_args(&[proxy_ref.into()]);
let pin_proxy_ref = Ty::new_adt(tcx, pin_adt_ref, args);
Expand Down
6 changes: 6 additions & 0 deletions compiler/rustc_mir_transform/src/simplify.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@ pub(super) enum SimplifyCfg {
Final,
MakeShim,
AfterUnreachableEnumBranching,
/// Extra run introduced by `StateTransform`.
PostStateTransform,
}

impl SimplifyCfg {
Expand All @@ -72,6 +74,7 @@ impl SimplifyCfg {
SimplifyCfg::AfterUnreachableEnumBranching => {
"SimplifyCfg-after-unreachable-enum-branching"
}
SimplifyCfg::PostStateTransform => "SimplifyCfg-post-StateTransform",
}
}
}
Expand Down Expand Up @@ -416,6 +419,8 @@ pub(super) enum SimplifyLocals {
BeforeConstProp,
AfterGVN,
Final,
/// Extra run introduced by `StateTransform`.
PostStateTransform,
}

impl<'tcx> crate::MirPass<'tcx> for SimplifyLocals {
Expand All @@ -424,6 +429,7 @@ impl<'tcx> crate::MirPass<'tcx> for SimplifyLocals {
SimplifyLocals::BeforeConstProp => "SimplifyLocals-before-const-prop",
SimplifyLocals::AfterGVN => "SimplifyLocals-after-value-numbering",
SimplifyLocals::Final => "SimplifyLocals-final",
SimplifyLocals::PostStateTransform => "SimplifyLocals-post-StateTransform",
}
}

Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_mir_transform/src/validate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -451,7 +451,7 @@ impl<'a, 'tcx> Visitor<'tcx> for CfgChecker<'a, 'tcx> {
if self.body.coroutine.is_none() {
self.fail(location, "`Yield` cannot appear outside coroutine bodies");
}
if self.body.phase >= MirPhase::Runtime(RuntimePhase::Initial) {
if self.body.phase >= MirPhase::Runtime(RuntimePhase::Optimized) {
self.fail(location, "`Yield` should have been replaced by coroutine lowering");
}
self.check_edge(location, *resume, EdgeKind::Normal);
Expand Down Expand Up @@ -489,7 +489,7 @@ impl<'a, 'tcx> Visitor<'tcx> for CfgChecker<'a, 'tcx> {
if self.body.coroutine.is_none() {
self.fail(location, "`CoroutineDrop` cannot appear outside coroutine bodies");
}
if self.body.phase >= MirPhase::Runtime(RuntimePhase::Initial) {
if self.body.phase >= MirPhase::Runtime(RuntimePhase::Optimized) {
self.fail(
location,
"`CoroutineDrop` should have been replaced by coroutine lowering",
Expand Down
22 changes: 0 additions & 22 deletions tests/crashes/140303.rs

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -29,72 +29,68 @@ fn a::{closure#0}(_1: Pin<&mut {async fn body of a<T>()}>, _2: &mut Context<'_>)
bb0: {
_20 = copy (_1.0: &mut {async fn body of a<T>()});
_19 = discriminant((*_20));
switchInt(move _19) -> [0: bb9, 3: bb12, 4: bb13, otherwise: bb14];
switchInt(move _19) -> [0: bb8, 3: bb11, 4: bb12, otherwise: bb13];
}

bb1: {
nop;
nop;
goto -> bb2;
}

bb2: {
_0 = Poll::<()>::Ready(const ());
return;
}

bb3: {
bb2: {
_0 = Poll::<()>::Pending;
discriminant((*_20)) = 4;
return;
}

bb4: {
bb3: {
StorageLive(_16);
_15 = &mut (((*_20) as variant#4).1: impl std::future::Future<Output = ()>);
_16 = Pin::<&mut impl Future<Output = ()>>::new_unchecked(move _15) -> [return: bb7, unwind unreachable];
_16 = Pin::<&mut impl Future<Output = ()>>::new_unchecked(move _15) -> [return: bb6, unwind unreachable];
}

bb5: {
bb4: {
unreachable;
}

bb6: {
bb5: {
StorageDead(_16);
_17 = discriminant(_9);
switchInt(move _17) -> [0: bb1, 1: bb3, otherwise: bb5];
switchInt(move _17) -> [0: bb1, 1: bb2, otherwise: bb4];
}

bb7: {
_9 = <impl Future<Output = ()> as Future>::poll(move _16, move _14) -> [return: bb6, unwind unreachable];
bb6: {
_9 = <impl Future<Output = ()> as Future>::poll(move _16, move _14) -> [return: bb5, unwind unreachable];
}

bb8: {
bb7: {
_0 = Poll::<()>::Ready(const ());
return;
}

bb8: {
goto -> bb10;
}

bb9: {
goto -> bb11;
goto -> bb7;
}

bb10: {
goto -> bb8;
drop(((*_20).0: T)) -> [return: bb9, unwind unreachable];
}

bb11: {
drop(((*_20).0: T)) -> [return: bb10, unwind unreachable];
goto -> bb3;
}

bb12: {
goto -> bb4;
goto -> bb3;
}

bb13: {
goto -> bb4;
}

bb14: {
_0 = Poll::<()>::Ready(const ());
return;
}
Expand Down
Loading
Loading