pub struct ElaborateDrops;
impl MirPass for ElaborateDrops {
- fn run_pass<'a, 'tcx>(&self,
- tcx: TyCtxt<'a, 'tcx, 'tcx>,
- src: MirSource<'tcx>,
- mir: &mut Mir<'tcx>)
- {
- debug!("elaborate_drops({:?} @ {:?})", src, mir.span);
+ fn run_pass<'tcx>(&self, tcx: TyCtxt<'tcx, 'tcx>, src: MirSource<'tcx>, body: &mut Body<'tcx>) {
+ debug!("elaborate_drops({:?} @ {:?})", src, body.span);
let def_id = src.def_id();
let param_env = tcx.param_env(src.def_id()).with_reveal_all();
- let move_data = match MoveData::gather_moves(mir, tcx) {
+ let move_data = match MoveData::gather_moves(body, tcx) {
Ok(move_data) => move_data,
Err((move_data, _move_errors)) => {
// The only way we should be allowing any move_errors
}
};
let elaborate_patch = {
- let mir = &*mir;
+ let body = &*body;
let env = MoveDataParamEnv {
move_data,
param_env,
};
- let dead_unwinds = find_dead_unwinds(tcx, mir, def_id, &env);
+ let dead_unwinds = find_dead_unwinds(tcx, body, def_id, &env);
let flow_inits =
- do_dataflow(tcx, mir, def_id, &[], &dead_unwinds,
- MaybeInitializedPlaces::new(tcx, mir, &env),
+ do_dataflow(tcx, body, def_id, &[], &dead_unwinds,
+ MaybeInitializedPlaces::new(tcx, body, &env),
|bd, p| DebugFormatted::new(&bd.move_data().move_paths[p]));
let flow_uninits =
- do_dataflow(tcx, mir, def_id, &[], &dead_unwinds,
- MaybeUninitializedPlaces::new(tcx, mir, &env),
+ do_dataflow(tcx, body, def_id, &[], &dead_unwinds,
+ MaybeUninitializedPlaces::new(tcx, body, &env),
|bd, p| DebugFormatted::new(&bd.move_data().move_paths[p]));
ElaborateDropsCtxt {
tcx,
- mir,
+ body,
env: &env,
flow_inits,
flow_uninits,
drop_flags: Default::default(),
- patch: MirPatch::new(mir),
+ patch: MirPatch::new(body),
}.elaborate()
};
- elaborate_patch.apply(mir);
+ elaborate_patch.apply(body);
}
}
/// Returns the set of basic blocks whose unwind edges are known
/// to not be reachable, because they are `drop` terminators
/// that can't drop anything.
-fn find_dead_unwinds<'a, 'tcx>(
- tcx: TyCtxt<'a, 'tcx, 'tcx>,
- mir: &Mir<'tcx>,
+fn find_dead_unwinds<'tcx>(
+ tcx: TyCtxt<'tcx, 'tcx>,
+ body: &Body<'tcx>,
def_id: hir::def_id::DefId,
- env: &MoveDataParamEnv<'tcx, 'tcx>)
- -> BitSet<BasicBlock>
-{
- debug!("find_dead_unwinds({:?})", mir.span);
+ env: &MoveDataParamEnv<'tcx, 'tcx>,
+) -> BitSet<BasicBlock> {
+ debug!("find_dead_unwinds({:?})", body.span);
// We only need to do this pass once, because unwind edges can only
// reach cleanup blocks, which can't have unwind edges themselves.
- let mut dead_unwinds = BitSet::new_empty(mir.basic_blocks().len());
+ let mut dead_unwinds = BitSet::new_empty(body.basic_blocks().len());
let flow_inits =
- do_dataflow(tcx, mir, def_id, &[], &dead_unwinds,
- MaybeInitializedPlaces::new(tcx, mir, &env),
+ do_dataflow(tcx, body, def_id, &[], &dead_unwinds,
+ MaybeInitializedPlaces::new(tcx, body, &env),
|bd, p| DebugFormatted::new(&bd.move_data().move_paths[p]));
- for (bb, bb_data) in mir.basic_blocks().iter_enumerated() {
+ for (bb, bb_data) in body.basic_blocks().iter_enumerated() {
let location = match bb_data.terminator().kind {
TerminatorKind::Drop { ref location, unwind: Some(_), .. } |
TerminatorKind::DropAndReplace { ref location, unwind: Some(_), .. } => location,
bb, bb_data, init_data.live);
for stmt in 0..bb_data.statements.len() {
let loc = Location { block: bb, statement_index: stmt };
- init_data.apply_location(tcx, mir, env, loc);
+ init_data.apply_location(tcx, body, env, loc);
}
let path = match env.move_data.rev_lookup.find(location) {
debug!("find_dead_unwinds @ {:?}: path({:?})={:?}", bb, location, path);
let mut maybe_live = false;
- on_all_drop_children_bits(tcx, mir, &env, path, |child| {
+ on_all_drop_children_bits(tcx, body, &env, path, |child| {
let (child_maybe_live, _) = init_data.state(child);
maybe_live |= child_maybe_live;
});
}
impl InitializationData {
- fn apply_location<'a,'tcx>(&mut self,
- tcx: TyCtxt<'a, 'tcx, 'tcx>,
- mir: &Mir<'tcx>,
- env: &MoveDataParamEnv<'tcx, 'tcx>,
- loc: Location)
- {
- drop_flag_effects_for_location(tcx, mir, env, loc, |path, df| {
+ fn apply_location<'tcx>(
+ &mut self,
+ tcx: TyCtxt<'tcx, 'tcx>,
+ body: &Body<'tcx>,
+ env: &MoveDataParamEnv<'tcx, 'tcx>,
+ loc: Location,
+ ) {
+ drop_flag_effects_for_location(tcx, body, env, loc, |path, df| {
debug!("at location {:?}: setting {:?} to {:?}",
loc, path, df);
match df {
&mut self.ctxt.patch
}
- fn mir(&self) -> &'a Mir<'tcx> {
- self.ctxt.mir
+ fn body(&self) -> &'a Body<'tcx> {
+ self.ctxt.body
}
- fn tcx(&self) -> TyCtxt<'a, 'tcx, 'tcx> {
+ fn tcx(&self) -> TyCtxt<'tcx, 'tcx> {
self.ctxt.tcx
}
let mut some_dead = false;
let mut children_count = 0;
on_all_drop_children_bits(
- self.tcx(), self.mir(), self.ctxt.env, path, |child| {
+ self.tcx(), self.body(), self.ctxt.env, path, |child| {
let (live, dead) = self.init_data.state(child);
debug!("elaborate_drop: state({:?}) = {:?}",
child, (live, dead));
}
DropFlagMode::Deep => {
on_all_children_bits(
- self.tcx(), self.mir(), self.ctxt.move_data(), path,
+ self.tcx(), self.body(), self.ctxt.move_data(), path,
|child| self.ctxt.set_drop_flag(loc, child, DropFlagState::Absent)
);
}
}
struct ElaborateDropsCtxt<'a, 'tcx: 'a> {
- tcx: TyCtxt<'a, 'tcx, 'tcx>,
- mir: &'a Mir<'tcx>,
+ tcx: TyCtxt<'tcx, 'tcx>,
+ body: &'a Body<'tcx>,
env: &'a MoveDataParamEnv<'tcx, 'tcx>,
flow_inits: DataflowResults<'tcx, MaybeInitializedPlaces<'a, 'tcx, 'tcx>>,
- flow_uninits: DataflowResults<'tcx, MaybeUninitializedPlaces<'a, 'tcx, 'tcx>>,
+ flow_uninits: DataflowResults<'tcx, MaybeUninitializedPlaces<'a, 'tcx, 'tcx>>,
drop_flags: FxHashMap<MovePathIndex, Local>,
patch: MirPatch<'tcx>,
}
.to_owned(),
};
for stmt in 0..loc.statement_index {
- data.apply_location(self.tcx, self.mir, self.env,
+ data.apply_location(self.tcx, self.body, self.env,
Location { block: loc.block, statement_index: stmt });
}
data
fn create_drop_flag(&mut self, index: MovePathIndex, span: Span) {
let tcx = self.tcx;
let patch = &mut self.patch;
- debug!("create_drop_flag({:?})", self.mir.span);
+ debug!("create_drop_flag({:?})", self.body.span);
self.drop_flags.entry(index).or_insert_with(|| {
patch.new_internal(tcx.types.bool, span)
});
fn collect_drop_flags(&mut self)
{
- for (bb, data) in self.mir.basic_blocks().iter_enumerated() {
+ for (bb, data) in self.body.basic_blocks().iter_enumerated() {
let terminator = data.terminator();
let location = match terminator.kind {
TerminatorKind::Drop { ref location, .. } |
}
};
- on_all_drop_children_bits(self.tcx, self.mir, self.env, path, |child| {
+ on_all_drop_children_bits(self.tcx, self.body, self.env, path, |child| {
let (maybe_live, maybe_dead) = init_data.state(child);
debug!("collect_drop_flags: collecting {:?} from {:?}@{:?} - {:?}",
child, location, path, (maybe_live, maybe_dead));
fn elaborate_drops(&mut self)
{
- for (bb, data) in self.mir.basic_blocks().iter_enumerated() {
+ for (bb, data) in self.body.basic_blocks().iter_enumerated() {
let loc = Location { block: bb, statement_index: data.statements.len() };
let terminator = data.terminator();
unwind: Option<BasicBlock>)
{
let bb = loc.block;
- let data = &self.mir[bb];
+ let data = &self.body[bb];
let terminator = data.terminator();
assert!(!data.is_cleanup, "DropAndReplace in unwind path not supported");
target,
Unwind::To(unwind),
bb);
- on_all_children_bits(self.tcx, self.mir, self.move_data(), path, |child| {
+ on_all_children_bits(self.tcx, self.body, self.move_data(), path, |child| {
self.set_drop_flag(Location { block: target, statement_index: 0 },
child, DropFlagState::Present);
self.set_drop_flag(Location { block: unwind, statement_index: 0 },
fn set_drop_flag(&mut self, loc: Location, path: MovePathIndex, val: DropFlagState) {
if let Some(&flag) = self.drop_flags.get(&path) {
- let span = self.patch.source_info_for_location(self.mir, loc).span;
+ let span = self.patch.source_info_for_location(self.body, loc).span;
let val = self.constant_bool(span, val.value());
self.patch.add_assign(loc, Place::Base(PlaceBase::Local(flag)), val);
}
fn drop_flags_on_init(&mut self) {
let loc = Location::START;
- let span = self.patch.source_info_for_location(self.mir, loc).span;
+ let span = self.patch.source_info_for_location(self.body, loc).span;
let false_ = self.constant_bool(span, false);
for flag in self.drop_flags.values() {
self.patch.add_assign(loc, Place::Base(PlaceBase::Local(*flag)), false_.clone());
}
fn drop_flags_for_fn_rets(&mut self) {
- for (bb, data) in self.mir.basic_blocks().iter_enumerated() {
+ for (bb, data) in self.body.basic_blocks().iter_enumerated() {
if let TerminatorKind::Call {
destination: Some((ref place, tgt)), cleanup: Some(_), ..
} = data.terminator().kind {
let loc = Location { block: tgt, statement_index: 0 };
let path = self.move_data().rev_lookup.find(place);
on_lookup_result_bits(
- self.tcx, self.mir, self.move_data(), path,
+ self.tcx, self.body, self.move_data(), path,
|child| self.set_drop_flag(loc, child, DropFlagState::Present)
);
}
fn drop_flags_for_args(&mut self) {
let loc = Location::START;
dataflow::drop_flag_effects_for_function_entry(
- self.tcx, self.mir, self.env, |path, ds| {
+ self.tcx, self.body, self.env, |path, ds| {
self.set_drop_flag(loc, path, ds);
}
)
// drop flags by themselves, to avoid the drop flags being
// clobbered before they are read.
- for (bb, data) in self.mir.basic_blocks().iter_enumerated() {
+ for (bb, data) in self.body.basic_blocks().iter_enumerated() {
debug!("drop_flags_for_locs({:?})", data);
for i in 0..(data.statements.len()+1) {
debug!("drop_flag_for_locs: stmt {}", i);
}
let loc = Location { block: bb, statement_index: i };
dataflow::drop_flag_effects_for_location(
- self.tcx, self.mir, self.env, loc, |path, ds| {
+ self.tcx, self.body, self.env, loc, |path, ds| {
if ds == DropFlagState::Absent || allow_initializations {
self.set_drop_flag(loc, path, ds)
}
let loc = Location { block: bb, statement_index: data.statements.len() };
let path = self.move_data().rev_lookup.find(place);
on_lookup_result_bits(
- self.tcx, self.mir, self.move_data(), path,
+ self.tcx, self.body, self.move_data(), path,
|child| self.set_drop_flag(loc, child, DropFlagState::Present)
);
}