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.
This commit is contained in:
Jonas Schievink 2020-01-25 02:31:32 +01:00
parent f2c1468965
commit 3c069a066e
4 changed files with 40 additions and 26 deletions

View file

@ -230,18 +230,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
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 { .. }

View file

@ -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),

View file

@ -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,

View file

@ -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;