From 3c069a066e50598ef230ba71ed5c5bcf596beb90 Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Sat, 25 Jan 2020 02:31:32 +0100 Subject: [PATCH] Change MIR building to fill in the resume place This changes `Yield` from `as_rvalue` to `into` lowering, which could have a possible performance impact. I could imagine special-casing some resume types here to use a simpler lowering for them, but it's unclear if that makes sense at this stage. --- .../build/expr/as_rvalue.rs | 14 ++------- src/librustc_mir_build/build/expr/category.rs | 2 +- src/librustc_mir_build/build/expr/into.rs | 21 ++++++++++++-- src/librustc_mir_build/build/mod.rs | 29 ++++++++++++------- 4 files changed, 40 insertions(+), 26 deletions(-) diff --git a/src/librustc_mir_build/build/expr/as_rvalue.rs b/src/librustc_mir_build/build/expr/as_rvalue.rs index 16795b459b6..6f5c5f0dd4c 100644 --- a/src/librustc_mir_build/build/expr/as_rvalue.rs +++ b/src/librustc_mir_build/build/expr/as_rvalue.rs @@ -230,18 +230,8 @@ fn expr_as_rvalue( block = unpack!(this.stmt_expr(block, expr, None)); block.and(this.unit_rvalue()) } - ExprKind::Yield { value } => { - let value = unpack!(block = this.as_operand(block, scope, value)); - let resume = this.cfg.start_new_block(); - let cleanup = this.generator_drop_cleanup(); - this.cfg.terminate( - block, - source_info, - TerminatorKind::Yield { value: value, resume: resume, drop: cleanup }, - ); - resume.and(this.unit_rvalue()) - } - ExprKind::Literal { .. } + ExprKind::Yield { .. } + | ExprKind::Literal { .. } | ExprKind::StaticRef { .. } | ExprKind::Block { .. } | ExprKind::Match { .. } diff --git a/src/librustc_mir_build/build/expr/category.rs b/src/librustc_mir_build/build/expr/category.rs index c4d340953c9..cc139dee63f 100644 --- a/src/librustc_mir_build/build/expr/category.rs +++ b/src/librustc_mir_build/build/expr/category.rs @@ -50,6 +50,7 @@ impl Category { | ExprKind::Adt { .. } | ExprKind::Borrow { .. } | ExprKind::AddressOf { .. } + | ExprKind::Yield { .. } | ExprKind::Call { .. } => Some(Category::Rvalue(RvalueFunc::Into)), ExprKind::Array { .. } @@ -63,7 +64,6 @@ impl Category { | ExprKind::Repeat { .. } | ExprKind::Assign { .. } | ExprKind::AssignOp { .. } - | ExprKind::Yield { .. } | ExprKind::InlineAsm { .. } => Some(Category::Rvalue(RvalueFunc::AsRvalue)), ExprKind::Literal { .. } | ExprKind::StaticRef { .. } => Some(Category::Constant), diff --git a/src/librustc_mir_build/build/expr/into.rs b/src/librustc_mir_build/build/expr/into.rs index 5ef338c624d..51b0b5bc7cb 100644 --- a/src/librustc_mir_build/build/expr/into.rs +++ b/src/librustc_mir_build/build/expr/into.rs @@ -365,6 +365,24 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { block.unit() } + ExprKind::Yield { value } => { + let scope = this.local_scope(); + let value = unpack!(block = this.as_operand(block, scope, value)); + let resume = this.cfg.start_new_block(); + let cleanup = this.generator_drop_cleanup(); + this.cfg.terminate( + block, + source_info, + TerminatorKind::Yield { + value, + resume, + resume_arg: destination.clone(), + drop: cleanup, + }, + ); + resume.unit() + } + // these are the cases that are more naturally handled by some other mode ExprKind::Unary { .. } | ExprKind::Binary { .. } @@ -376,8 +394,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { | ExprKind::Tuple { .. } | ExprKind::Closure { .. } | ExprKind::Literal { .. } - | ExprKind::StaticRef { .. } - | ExprKind::Yield { .. } => { + | ExprKind::StaticRef { .. } => { debug_assert!(match Category::of(&expr.kind).unwrap() { // should be handled above Category::Rvalue(RvalueFunc::Into) => false, diff --git a/src/librustc_mir_build/build/mod.rs b/src/librustc_mir_build/build/mod.rs index ab539e6179e..4c8d8e3a0ea 100644 --- a/src/librustc_mir_build/build/mod.rs +++ b/src/librustc_mir_build/build/mod.rs @@ -68,6 +68,12 @@ fn mir_build(tcx: TyCtxt<'_>, def_id: DefId) -> BodyAndCache<'_> { let fn_sig = cx.tables().liberated_fn_sigs()[id]; let fn_def_id = tcx.hir().local_def_id(id); + let safety = match fn_sig.unsafety { + hir::Unsafety::Normal => Safety::Safe, + hir::Unsafety::Unsafe => Safety::FnUnsafe, + }; + + let body = tcx.hir().body(body_id); let ty = tcx.type_of(fn_def_id); let mut abi = fn_sig.abi; let implicit_argument = match ty.kind { @@ -77,22 +83,23 @@ fn mir_build(tcx: TyCtxt<'_>, def_id: DefId) -> BodyAndCache<'_> { abi = Abi::Rust; vec![ArgInfo(liberated_closure_env_ty(tcx, id, body_id), None, None, None)] } - ty::Generator(..) => { + ty::Generator(def_id, substs, _) => { let gen_ty = tcx.body_tables(body_id).node_type(id); - vec![ - ArgInfo(gen_ty, None, None, None), - ArgInfo(tcx.mk_unit(), None, None, None), - ] + let resume_ty = substs.as_generator().resume_ty(def_id, tcx); + + // The resume argument may be missing, in that case we need to provide it here. + if body.params.is_empty() { + vec![ + ArgInfo(gen_ty, None, None, None), + ArgInfo(resume_ty, None, None, None), + ] + } else { + vec![ArgInfo(gen_ty, None, None, None)] + } } _ => vec![], }; - let safety = match fn_sig.unsafety { - hir::Unsafety::Normal => Safety::Safe, - hir::Unsafety::Unsafe => Safety::FnUnsafe, - }; - - let body = tcx.hir().body(body_id); let explicit_arguments = body.params.iter().enumerate().map(|(index, arg)| { let owner_id = tcx.hir().body_owner(body_id); let opt_ty_info; -- 2.44.0