use crate::dataflow::{self, Analysis};
use crate::transform::no_landing_pads::no_landing_pads;
use crate::transform::simplify;
-use crate::transform::{MirPass, MirSource};
+use crate::transform::MirPass;
use crate::util::dump_mir;
use crate::util::expand_aggregate;
use crate::util::storage;
use rustc_data_structures::fx::FxHashMap;
use rustc_hir as hir;
-use rustc_hir::def_id::DefId;
use rustc_hir::lang_items::LangItem;
use rustc_index::bit_set::{BitMatrix, BitSet};
use rustc_index::vec::{Idx, IndexVec};
use rustc_middle::ty::{self, AdtDef, Ty, TyCtxt};
use rustc_target::abi::VariantIdx;
use rustc_target::spec::PanicStrategy;
-use std::borrow::Cow;
use std::{iter, ops};
pub struct StateTransform;
fn locals_live_across_suspend_points(
tcx: TyCtxt<'tcx>,
body: &Body<'tcx>,
- source: MirSource<'tcx>,
always_live_locals: &storage::AlwaysLiveLocals,
movable: bool,
) -> LivenessInfo {
- let def_id = source.def_id();
let body_ref: &Body<'_> = &body;
// Calculate when MIR locals have live storage. This gives us an upper bound of their
// lifetimes.
let mut storage_live = MaybeStorageLive::new(always_live_locals.clone())
- .into_engine(tcx, body_ref, def_id)
+ .into_engine(tcx, body_ref)
.iterate_to_fixpoint()
.into_results_cursor(body_ref);
// Calculate the MIR locals which have been previously
// borrowed (even if they are still active).
let borrowed_locals_results = MaybeBorrowedLocals::all_borrows()
- .into_engine(tcx, body_ref, def_id)
+ .into_engine(tcx, body_ref)
.pass_name("generator")
.iterate_to_fixpoint();
// Calculate the MIR locals that we actually need to keep storage around
// for.
let requires_storage_results = MaybeRequiresStorage::new(body, &borrowed_locals_results)
- .into_engine(tcx, body_ref, def_id)
+ .into_engine(tcx, body_ref)
.iterate_to_fixpoint();
let mut requires_storage_cursor =
dataflow::ResultsCursor::new(body_ref, &requires_storage_results);
// Calculate the liveness of MIR locals ignoring borrows.
let mut liveness = MaybeLiveLocals
- .into_engine(tcx, body_ref, def_id)
+ .into_engine(tcx, body_ref)
.pass_name("generator")
.iterate_to_fixpoint()
.into_results_cursor(body_ref);
fn sanitize_witness<'tcx>(
tcx: TyCtxt<'tcx>,
body: &Body<'tcx>,
- did: DefId,
witness: Ty<'tcx>,
upvars: &Vec<Ty<'tcx>>,
saved_locals: &GeneratorSavedLocals,
) {
+ let did = body.source.def_id();
let allowed_upvars = tcx.erase_regions(upvars);
let allowed = match witness.kind() {
ty::GeneratorWitness(s) => tcx.erase_late_bound_regions(&s),
) {
let default_block = insert_term_block(body, default);
let (assign, discr) = transform.get_discr(body);
+ let switch_targets =
+ SwitchTargets::new(cases.iter().map(|(i, bb)| ((*i) as u128, *bb)), default_block);
let switch = TerminatorKind::SwitchInt {
discr: Operand::Move(discr),
switch_ty: transform.discr_ty,
- values: Cow::from(cases.iter().map(|&(i, _)| i as u128).collect::<Vec<_>>()),
- targets: cases.iter().map(|&(_, d)| d).chain(iter::once(default_block)).collect(),
+ targets: switch_targets,
};
let source_info = SourceInfo::outermost(body.span);
}
}
-fn elaborate_generator_drops<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, body: &mut Body<'tcx>) {
+fn elaborate_generator_drops<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
use crate::shim::DropShimElaborator;
use crate::util::elaborate_drops::{elaborate_drop, Unwind};
use crate::util::patch::MirPatch;
// this is ok because `open_drop` can only be reached within that own
// generator's resume function.
+ let def_id = body.source.def_id();
let param_env = tcx.param_env(def_id);
let mut elaborator = DropShimElaborator { body, patch: MirPatch::new(body), tcx, param_env };
fn create_generator_drop_shim<'tcx>(
tcx: TyCtxt<'tcx>,
transform: &TransformVisitor<'tcx>,
- source: MirSource<'tcx>,
gen_ty: Ty<'tcx>,
body: &mut Body<'tcx>,
drop_clean: BasicBlock,
// unrelated code from the resume part of the function
simplify::remove_dead_blocks(&mut body);
- dump_mir(tcx, None, "generator_drop", &0, source, &body, |_, _| Ok(()));
+ dump_mir(tcx, None, "generator_drop", &0, &body, |_, _| Ok(()));
body
}
fn create_generator_resume_function<'tcx>(
tcx: TyCtxt<'tcx>,
transform: TransformVisitor<'tcx>,
- source: MirSource<'tcx>,
body: &mut Body<'tcx>,
can_return: bool,
) {
// unrelated code from the drop part of the function
simplify::remove_dead_blocks(body);
- dump_mir(tcx, None, "generator_resume", &0, source, body, |_, _| Ok(()));
+ dump_mir(tcx, None, "generator_resume", &0, body, |_, _| Ok(()));
}
fn insert_clean_drop(body: &mut Body<'_>) -> BasicBlock {
}
impl<'tcx> MirPass<'tcx> for StateTransform {
- fn run_pass(&self, tcx: TyCtxt<'tcx>, source: MirSource<'tcx>, body: &mut Body<'tcx>) {
+ fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
let yield_ty = if let Some(yield_ty) = body.yield_ty {
yield_ty
} else {
assert!(body.generator_drop.is_none());
- let def_id = source.def_id();
-
// The first argument is the generator type passed by value
let gen_ty = body.local_decls.raw[1].ty;
let always_live_locals = storage::AlwaysLiveLocals::new(&body);
let liveness_info =
- locals_live_across_suspend_points(tcx, body, source, &always_live_locals, movable);
+ locals_live_across_suspend_points(tcx, body, &always_live_locals, movable);
- sanitize_witness(tcx, body, def_id, interior, &upvars, &liveness_info.saved_locals);
+ sanitize_witness(tcx, body, interior, &upvars, &liveness_info.saved_locals);
if tcx.sess.opts.debugging_opts.validate_mir {
let mut vis = EnsureGeneratorFieldAssignmentsNeverAlias {
// This is expanded to a drop ladder in `elaborate_generator_drops`.
let drop_clean = insert_clean_drop(body);
- dump_mir(tcx, None, "generator_pre-elab", &0, source, body, |_, _| Ok(()));
+ dump_mir(tcx, None, "generator_pre-elab", &0, body, |_, _| Ok(()));
// Expand `drop(generator_struct)` to a drop ladder which destroys upvars.
// If any upvars are moved out of, drop elaboration will handle upvar destruction.
// However we need to also elaborate the code generated by `insert_clean_drop`.
- elaborate_generator_drops(tcx, def_id, body);
+ elaborate_generator_drops(tcx, body);
- dump_mir(tcx, None, "generator_post-transform", &0, source, body, |_, _| Ok(()));
+ dump_mir(tcx, None, "generator_post-transform", &0, body, |_, _| Ok(()));
// Create a copy of our MIR and use it to create the drop shim for the generator
- let drop_shim =
- create_generator_drop_shim(tcx, &transform, source, gen_ty, body, drop_clean);
+ let drop_shim = create_generator_drop_shim(tcx, &transform, gen_ty, body, drop_clean);
body.generator_drop = Some(box drop_shim);
// Create the Generator::resume function
- create_generator_resume_function(tcx, transform, source, body, can_return);
+ create_generator_resume_function(tcx, transform, body, can_return);
}
}