mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-25 16:24:46 +00:00
Allow apply_terminator_effect to customize edges.
This commit is contained in:
parent
32711b2b4e
commit
5173d85043
@ -2,12 +2,14 @@
|
||||
#![deny(rustc::diagnostic_outside_of_impl)]
|
||||
use rustc_data_structures::fx::FxIndexMap;
|
||||
use rustc_index::bit_set::BitSet;
|
||||
use rustc_middle::mir::{self, BasicBlock, Body, Location, Place};
|
||||
use rustc_middle::mir::{
|
||||
self, BasicBlock, Body, CallReturnPlaces, Location, Place, TerminatorEdge,
|
||||
};
|
||||
use rustc_middle::ty::RegionVid;
|
||||
use rustc_middle::ty::TyCtxt;
|
||||
use rustc_mir_dataflow::impls::{EverInitializedPlaces, MaybeUninitializedPlaces};
|
||||
use rustc_mir_dataflow::ResultsVisitable;
|
||||
use rustc_mir_dataflow::{self, fmt::DebugWithContext, CallReturnPlaces, GenKill};
|
||||
use rustc_mir_dataflow::{self, fmt::DebugWithContext, GenKill};
|
||||
use rustc_mir_dataflow::{Analysis, Direction, Results};
|
||||
use std::fmt;
|
||||
|
||||
@ -404,12 +406,12 @@ impl<'tcx> rustc_mir_dataflow::GenKillAnalysis<'tcx> for Borrows<'_, 'tcx> {
|
||||
self.kill_loans_out_of_scope_at_location(trans, location);
|
||||
}
|
||||
|
||||
fn terminator_effect(
|
||||
fn terminator_effect<'mir>(
|
||||
&mut self,
|
||||
trans: &mut impl GenKill<Self::Idx>,
|
||||
terminator: &mir::Terminator<'tcx>,
|
||||
trans: &mut Self::Domain,
|
||||
terminator: &'mir mir::Terminator<'tcx>,
|
||||
_location: Location,
|
||||
) {
|
||||
) -> TerminatorEdge<'mir, 'tcx> {
|
||||
if let mir::TerminatorKind::InlineAsm { operands, .. } = &terminator.kind {
|
||||
for op in operands {
|
||||
if let mir::InlineAsmOperand::Out { place: Some(place), .. }
|
||||
@ -419,6 +421,7 @@ impl<'tcx> rustc_mir_dataflow::GenKillAnalysis<'tcx> for Borrows<'_, 'tcx> {
|
||||
}
|
||||
}
|
||||
}
|
||||
terminator.edges()
|
||||
}
|
||||
|
||||
fn call_return_effect(
|
||||
|
@ -4,10 +4,12 @@
|
||||
|
||||
use rustc_index::bit_set::BitSet;
|
||||
use rustc_middle::mir::visit::Visitor;
|
||||
use rustc_middle::mir::{self, BasicBlock, Local, Location, Statement, StatementKind};
|
||||
use rustc_middle::mir::{
|
||||
self, BasicBlock, CallReturnPlaces, Local, Location, Statement, StatementKind, TerminatorEdge,
|
||||
};
|
||||
use rustc_mir_dataflow::fmt::DebugWithContext;
|
||||
use rustc_mir_dataflow::JoinSemiLattice;
|
||||
use rustc_mir_dataflow::{Analysis, AnalysisDomain, CallReturnPlaces};
|
||||
use rustc_mir_dataflow::{Analysis, AnalysisDomain};
|
||||
|
||||
use std::fmt;
|
||||
use std::marker::PhantomData;
|
||||
@ -345,13 +347,14 @@ where
|
||||
self.transfer_function(state).visit_statement(statement, location);
|
||||
}
|
||||
|
||||
fn apply_terminator_effect(
|
||||
fn apply_terminator_effect<'mir>(
|
||||
&mut self,
|
||||
state: &mut Self::Domain,
|
||||
terminator: &mir::Terminator<'tcx>,
|
||||
terminator: &'mir mir::Terminator<'tcx>,
|
||||
location: Location,
|
||||
) {
|
||||
) -> TerminatorEdge<'mir, 'tcx> {
|
||||
self.transfer_function(state).visit_terminator(terminator, location);
|
||||
terminator.edges()
|
||||
}
|
||||
|
||||
fn apply_call_return_effect(
|
||||
|
@ -10,6 +10,7 @@ use std::iter;
|
||||
use std::slice;
|
||||
|
||||
pub use super::query::*;
|
||||
use super::*;
|
||||
|
||||
#[derive(Debug, Clone, TyEncodable, TyDecodable, Hash, HashStable, PartialEq)]
|
||||
pub struct SwitchTargets {
|
||||
@ -430,3 +431,108 @@ impl<'tcx> TerminatorKind<'tcx> {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub enum TerminatorEdge<'mir, 'tcx> {
|
||||
/// For terminators that have no successor, like `return`.
|
||||
None,
|
||||
/// For terminators that a single successor, like `goto`, and `assert` without cleanup block.
|
||||
Single(BasicBlock),
|
||||
/// For terminators that two successors, `assert` with cleanup block and `falseEdge`.
|
||||
Double(BasicBlock, BasicBlock),
|
||||
/// Special action for `Yield`, `Call` and `InlineAsm` terminators.
|
||||
AssignOnReturn {
|
||||
return_: Option<BasicBlock>,
|
||||
unwind: UnwindAction,
|
||||
place: CallReturnPlaces<'mir, 'tcx>,
|
||||
},
|
||||
/// Special edge for `SwitchInt`.
|
||||
SwitchInt { targets: &'mir SwitchTargets, discr: &'mir Operand<'tcx> },
|
||||
}
|
||||
|
||||
/// List of places that are written to after a successful (non-unwind) return
|
||||
/// from a `Call` or `InlineAsm`.
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub enum CallReturnPlaces<'a, 'tcx> {
|
||||
Call(Place<'tcx>),
|
||||
Yield(Place<'tcx>),
|
||||
InlineAsm(&'a [InlineAsmOperand<'tcx>]),
|
||||
}
|
||||
|
||||
impl<'tcx> CallReturnPlaces<'_, 'tcx> {
|
||||
pub fn for_each(&self, mut f: impl FnMut(Place<'tcx>)) {
|
||||
match *self {
|
||||
Self::Call(place) | Self::Yield(place) => f(place),
|
||||
Self::InlineAsm(operands) => {
|
||||
for op in operands {
|
||||
match *op {
|
||||
InlineAsmOperand::Out { place: Some(place), .. }
|
||||
| InlineAsmOperand::InOut { out_place: Some(place), .. } => f(place),
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Terminator<'tcx> {
|
||||
pub fn edges(&self) -> TerminatorEdge<'_, 'tcx> {
|
||||
self.kind.edges()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> TerminatorKind<'tcx> {
|
||||
pub fn edges(&self) -> TerminatorEdge<'_, 'tcx> {
|
||||
use TerminatorKind::*;
|
||||
match *self {
|
||||
Return | Resume | Terminate | GeneratorDrop | Unreachable => TerminatorEdge::None,
|
||||
|
||||
Goto { target } => TerminatorEdge::Single(target),
|
||||
|
||||
Assert { target, unwind, expected: _, msg: _, cond: _ }
|
||||
| Drop { target, unwind, place: _, replace: _ }
|
||||
| FalseUnwind { real_target: target, unwind } => match unwind {
|
||||
UnwindAction::Cleanup(unwind) => TerminatorEdge::Double(target, unwind),
|
||||
UnwindAction::Continue | UnwindAction::Terminate | UnwindAction::Unreachable => {
|
||||
TerminatorEdge::Single(target)
|
||||
}
|
||||
},
|
||||
|
||||
FalseEdge { real_target, imaginary_target } => {
|
||||
TerminatorEdge::Double(real_target, imaginary_target)
|
||||
}
|
||||
|
||||
Yield { resume: target, drop, resume_arg, value: _ } => {
|
||||
TerminatorEdge::AssignOnReturn {
|
||||
return_: Some(target),
|
||||
unwind: drop.map_or(UnwindAction::Terminate, UnwindAction::Cleanup),
|
||||
place: CallReturnPlaces::Yield(resume_arg),
|
||||
}
|
||||
}
|
||||
|
||||
Call { unwind, destination, target, func: _, args: _, fn_span: _, call_source: _ } => {
|
||||
TerminatorEdge::AssignOnReturn {
|
||||
return_: target,
|
||||
unwind,
|
||||
place: CallReturnPlaces::Call(destination),
|
||||
}
|
||||
}
|
||||
|
||||
InlineAsm {
|
||||
template: _,
|
||||
ref operands,
|
||||
options: _,
|
||||
line_spans: _,
|
||||
destination,
|
||||
unwind,
|
||||
} => TerminatorEdge::AssignOnReturn {
|
||||
return_: destination,
|
||||
unwind,
|
||||
place: CallReturnPlaces::InlineAsm(operands),
|
||||
},
|
||||
|
||||
SwitchInt { ref targets, ref discr } => TerminatorEdge::SwitchInt { targets, discr },
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,11 +1,10 @@
|
||||
use rustc_middle::mir::{self, BasicBlock, Location, SwitchTargets, UnwindAction};
|
||||
use rustc_middle::ty::TyCtxt;
|
||||
use rustc_middle::mir::{
|
||||
self, BasicBlock, CallReturnPlaces, Location, SwitchTargets, TerminatorEdge, UnwindAction,
|
||||
};
|
||||
use std::ops::RangeInclusive;
|
||||
|
||||
use super::visitor::{ResultsVisitable, ResultsVisitor};
|
||||
use super::{
|
||||
Analysis, CallReturnPlaces, Effect, EffectIndex, GenKillAnalysis, GenKillSet, SwitchIntTarget,
|
||||
};
|
||||
use super::{Analysis, Effect, EffectIndex, GenKillAnalysis, GenKillSet, SwitchIntTarget};
|
||||
|
||||
pub trait Direction {
|
||||
const IS_FORWARD: bool;
|
||||
@ -24,12 +23,14 @@ pub trait Direction {
|
||||
) where
|
||||
A: Analysis<'tcx>;
|
||||
|
||||
fn apply_effects_in_block<'tcx, A>(
|
||||
fn apply_effects_in_block<'mir, 'tcx, A>(
|
||||
analysis: &mut A,
|
||||
state: &mut A::Domain,
|
||||
block: BasicBlock,
|
||||
block_data: &mir::BasicBlockData<'tcx>,
|
||||
) where
|
||||
block_data: &'mir mir::BasicBlockData<'tcx>,
|
||||
statement_effect: Option<&dyn Fn(BasicBlock, &mut A::Domain)>,
|
||||
) -> TerminatorEdge<'mir, 'tcx>
|
||||
where
|
||||
A: Analysis<'tcx>;
|
||||
|
||||
fn gen_kill_effects_in_block<'tcx, A>(
|
||||
@ -51,10 +52,10 @@ pub trait Direction {
|
||||
|
||||
fn join_state_into_successors_of<'tcx, A>(
|
||||
analysis: &mut A,
|
||||
tcx: TyCtxt<'tcx>,
|
||||
body: &mir::Body<'tcx>,
|
||||
exit_state: &mut A::Domain,
|
||||
block: (BasicBlock, &'_ mir::BasicBlockData<'tcx>),
|
||||
block: BasicBlock,
|
||||
edges: TerminatorEdge<'_, 'tcx>,
|
||||
propagate: impl FnMut(BasicBlock, &A::Domain),
|
||||
) where
|
||||
A: Analysis<'tcx>;
|
||||
@ -66,24 +67,30 @@ pub struct Backward;
|
||||
impl Direction for Backward {
|
||||
const IS_FORWARD: bool = false;
|
||||
|
||||
fn apply_effects_in_block<'tcx, A>(
|
||||
fn apply_effects_in_block<'mir, 'tcx, A>(
|
||||
analysis: &mut A,
|
||||
state: &mut A::Domain,
|
||||
block: BasicBlock,
|
||||
block_data: &mir::BasicBlockData<'tcx>,
|
||||
) where
|
||||
block_data: &'mir mir::BasicBlockData<'tcx>,
|
||||
statement_effect: Option<&dyn Fn(BasicBlock, &mut A::Domain)>,
|
||||
) -> TerminatorEdge<'mir, 'tcx>
|
||||
where
|
||||
A: Analysis<'tcx>,
|
||||
{
|
||||
let terminator = block_data.terminator();
|
||||
let location = Location { block, statement_index: block_data.statements.len() };
|
||||
analysis.apply_before_terminator_effect(state, terminator, location);
|
||||
analysis.apply_terminator_effect(state, terminator, location);
|
||||
|
||||
for (statement_index, statement) in block_data.statements.iter().enumerate().rev() {
|
||||
let location = Location { block, statement_index };
|
||||
analysis.apply_before_statement_effect(state, statement, location);
|
||||
analysis.apply_statement_effect(state, statement, location);
|
||||
let edges = analysis.apply_terminator_effect(state, terminator, location);
|
||||
if let Some(statement_effect) = statement_effect {
|
||||
statement_effect(block, state)
|
||||
} else {
|
||||
for (statement_index, statement) in block_data.statements.iter().enumerate().rev() {
|
||||
let location = Location { block, statement_index };
|
||||
analysis.apply_before_statement_effect(state, statement, location);
|
||||
analysis.apply_statement_effect(state, statement, location);
|
||||
}
|
||||
}
|
||||
edges
|
||||
}
|
||||
|
||||
fn gen_kill_effects_in_block<'tcx, A>(
|
||||
@ -94,11 +101,6 @@ impl Direction for Backward {
|
||||
) where
|
||||
A: GenKillAnalysis<'tcx>,
|
||||
{
|
||||
let terminator = block_data.terminator();
|
||||
let location = Location { block, statement_index: block_data.statements.len() };
|
||||
analysis.before_terminator_effect(trans, terminator, location);
|
||||
analysis.terminator_effect(trans, terminator, location);
|
||||
|
||||
for (statement_index, statement) in block_data.statements.iter().enumerate().rev() {
|
||||
let location = Location { block, statement_index };
|
||||
analysis.before_statement_effect(trans, statement, location);
|
||||
@ -217,10 +219,10 @@ impl Direction for Backward {
|
||||
|
||||
fn join_state_into_successors_of<'tcx, A>(
|
||||
analysis: &mut A,
|
||||
_tcx: TyCtxt<'tcx>,
|
||||
body: &mir::Body<'tcx>,
|
||||
exit_state: &mut A::Domain,
|
||||
(bb, _bb_data): (BasicBlock, &'_ mir::BasicBlockData<'tcx>),
|
||||
bb: BasicBlock,
|
||||
_edges: TerminatorEdge<'_, 'tcx>,
|
||||
mut propagate: impl FnMut(BasicBlock, &A::Domain),
|
||||
) where
|
||||
A: Analysis<'tcx>,
|
||||
@ -254,7 +256,11 @@ impl Direction for Backward {
|
||||
|
||||
mir::TerminatorKind::Yield { resume, resume_arg, .. } if resume == bb => {
|
||||
let mut tmp = exit_state.clone();
|
||||
analysis.apply_yield_resume_effect(&mut tmp, resume, resume_arg);
|
||||
analysis.apply_call_return_effect(
|
||||
&mut tmp,
|
||||
resume,
|
||||
CallReturnPlaces::Yield(resume_arg),
|
||||
);
|
||||
propagate(pred, &tmp);
|
||||
}
|
||||
|
||||
@ -318,24 +324,30 @@ pub struct Forward;
|
||||
impl Direction for Forward {
|
||||
const IS_FORWARD: bool = true;
|
||||
|
||||
fn apply_effects_in_block<'tcx, A>(
|
||||
fn apply_effects_in_block<'mir, 'tcx, A>(
|
||||
analysis: &mut A,
|
||||
state: &mut A::Domain,
|
||||
block: BasicBlock,
|
||||
block_data: &mir::BasicBlockData<'tcx>,
|
||||
) where
|
||||
block_data: &'mir mir::BasicBlockData<'tcx>,
|
||||
statement_effect: Option<&dyn Fn(BasicBlock, &mut A::Domain)>,
|
||||
) -> TerminatorEdge<'mir, 'tcx>
|
||||
where
|
||||
A: Analysis<'tcx>,
|
||||
{
|
||||
for (statement_index, statement) in block_data.statements.iter().enumerate() {
|
||||
let location = Location { block, statement_index };
|
||||
analysis.apply_before_statement_effect(state, statement, location);
|
||||
analysis.apply_statement_effect(state, statement, location);
|
||||
if let Some(statement_effect) = statement_effect {
|
||||
statement_effect(block, state)
|
||||
} else {
|
||||
for (statement_index, statement) in block_data.statements.iter().enumerate() {
|
||||
let location = Location { block, statement_index };
|
||||
analysis.apply_before_statement_effect(state, statement, location);
|
||||
analysis.apply_statement_effect(state, statement, location);
|
||||
}
|
||||
}
|
||||
|
||||
let terminator = block_data.terminator();
|
||||
let location = Location { block, statement_index: block_data.statements.len() };
|
||||
analysis.apply_before_terminator_effect(state, terminator, location);
|
||||
analysis.apply_terminator_effect(state, terminator, location);
|
||||
analysis.apply_terminator_effect(state, terminator, location)
|
||||
}
|
||||
|
||||
fn gen_kill_effects_in_block<'tcx, A>(
|
||||
@ -351,11 +363,6 @@ impl Direction for Forward {
|
||||
analysis.before_statement_effect(trans, statement, location);
|
||||
analysis.statement_effect(trans, statement, location);
|
||||
}
|
||||
|
||||
let terminator = block_data.terminator();
|
||||
let location = Location { block, statement_index: block_data.statements.len() };
|
||||
analysis.before_terminator_effect(trans, terminator, location);
|
||||
analysis.terminator_effect(trans, terminator, location);
|
||||
}
|
||||
|
||||
fn apply_effects_in_range<'tcx, A>(
|
||||
@ -464,86 +471,32 @@ impl Direction for Forward {
|
||||
|
||||
fn join_state_into_successors_of<'tcx, A>(
|
||||
analysis: &mut A,
|
||||
_tcx: TyCtxt<'tcx>,
|
||||
_body: &mir::Body<'tcx>,
|
||||
exit_state: &mut A::Domain,
|
||||
(bb, bb_data): (BasicBlock, &'_ mir::BasicBlockData<'tcx>),
|
||||
bb: BasicBlock,
|
||||
edges: TerminatorEdge<'_, 'tcx>,
|
||||
mut propagate: impl FnMut(BasicBlock, &A::Domain),
|
||||
) where
|
||||
A: Analysis<'tcx>,
|
||||
{
|
||||
use mir::TerminatorKind::*;
|
||||
match bb_data.terminator().kind {
|
||||
Return | Resume | Terminate | GeneratorDrop | Unreachable => {}
|
||||
|
||||
Goto { target } => propagate(target, exit_state),
|
||||
|
||||
Assert { target, unwind, expected: _, msg: _, cond: _ }
|
||||
| Drop { target, unwind, place: _, replace: _ }
|
||||
| FalseUnwind { real_target: target, unwind } => {
|
||||
if let UnwindAction::Cleanup(unwind) = unwind {
|
||||
propagate(unwind, exit_state);
|
||||
}
|
||||
|
||||
match edges {
|
||||
TerminatorEdge::None => {}
|
||||
TerminatorEdge::Single(target) => propagate(target, exit_state),
|
||||
TerminatorEdge::Double(target, unwind) => {
|
||||
propagate(target, exit_state);
|
||||
propagate(unwind, exit_state);
|
||||
}
|
||||
|
||||
FalseEdge { real_target, imaginary_target } => {
|
||||
propagate(real_target, exit_state);
|
||||
propagate(imaginary_target, exit_state);
|
||||
}
|
||||
|
||||
Yield { resume: target, drop, resume_arg, value: _ } => {
|
||||
if let Some(drop) = drop {
|
||||
propagate(drop, exit_state);
|
||||
}
|
||||
|
||||
analysis.apply_yield_resume_effect(exit_state, target, resume_arg);
|
||||
propagate(target, exit_state);
|
||||
}
|
||||
|
||||
Call { unwind, destination, target, func: _, args: _, call_source: _, fn_span: _ } => {
|
||||
TerminatorEdge::AssignOnReturn { return_, unwind, place } => {
|
||||
// This must be done *first*, otherwise the unwind path will see the assignments.
|
||||
if let UnwindAction::Cleanup(unwind) = unwind {
|
||||
propagate(unwind, exit_state);
|
||||
}
|
||||
|
||||
if let Some(target) = target {
|
||||
// N.B.: This must be done *last*, otherwise the unwind path will see the call
|
||||
// return effect.
|
||||
analysis.apply_call_return_effect(
|
||||
exit_state,
|
||||
bb,
|
||||
CallReturnPlaces::Call(destination),
|
||||
);
|
||||
propagate(target, exit_state);
|
||||
if let Some(return_) = return_ {
|
||||
analysis.apply_call_return_effect(exit_state, bb, place);
|
||||
propagate(return_, exit_state);
|
||||
}
|
||||
}
|
||||
|
||||
InlineAsm {
|
||||
template: _,
|
||||
ref operands,
|
||||
options: _,
|
||||
line_spans: _,
|
||||
destination,
|
||||
unwind,
|
||||
} => {
|
||||
if let UnwindAction::Cleanup(unwind) = unwind {
|
||||
propagate(unwind, exit_state);
|
||||
}
|
||||
|
||||
if let Some(target) = destination {
|
||||
// N.B.: This must be done *last*, otherwise the unwind path will see the call
|
||||
// return effect.
|
||||
analysis.apply_call_return_effect(
|
||||
exit_state,
|
||||
bb,
|
||||
CallReturnPlaces::InlineAsm(operands),
|
||||
);
|
||||
propagate(target, exit_state);
|
||||
}
|
||||
}
|
||||
|
||||
SwitchInt { ref targets, ref discr } => {
|
||||
TerminatorEdge::SwitchInt { targets, discr } => {
|
||||
let mut applier = ForwardSwitchIntEdgeEffectsApplier {
|
||||
exit_state,
|
||||
targets,
|
||||
|
@ -264,19 +264,20 @@ where
|
||||
state.clone_from(&entry_sets[bb]);
|
||||
|
||||
// Apply the block transfer function, using the cached one if it exists.
|
||||
match &apply_trans_for_block {
|
||||
Some(apply) => apply(bb, &mut state),
|
||||
None => {
|
||||
A::Direction::apply_effects_in_block(&mut analysis, &mut state, bb, bb_data)
|
||||
}
|
||||
}
|
||||
let edges = A::Direction::apply_effects_in_block(
|
||||
&mut analysis,
|
||||
&mut state,
|
||||
bb,
|
||||
bb_data,
|
||||
apply_trans_for_block.as_deref(),
|
||||
);
|
||||
|
||||
A::Direction::join_state_into_successors_of(
|
||||
&mut analysis,
|
||||
tcx,
|
||||
body,
|
||||
&mut state,
|
||||
(bb, bb_data),
|
||||
bb,
|
||||
edges,
|
||||
|target: BasicBlock, state: &A::Domain| {
|
||||
let set_changed = entry_sets[target].join(state);
|
||||
if set_changed {
|
||||
|
@ -269,7 +269,11 @@ where
|
||||
self.write_row(w, "", "(on yield resume)", |this, w, fmt| {
|
||||
let state_on_generator_drop = this.results.get().clone();
|
||||
this.results.apply_custom_effect(|analysis, state| {
|
||||
analysis.apply_yield_resume_effect(state, resume, resume_arg);
|
||||
analysis.apply_call_return_effect(
|
||||
state,
|
||||
resume,
|
||||
CallReturnPlaces::Yield(resume_arg),
|
||||
);
|
||||
});
|
||||
|
||||
write!(
|
||||
|
@ -34,7 +34,7 @@ use std::cmp::Ordering;
|
||||
|
||||
use rustc_index::bit_set::{BitSet, ChunkedBitSet, HybridBitSet};
|
||||
use rustc_index::Idx;
|
||||
use rustc_middle::mir::{self, BasicBlock, Location};
|
||||
use rustc_middle::mir::{self, BasicBlock, CallReturnPlaces, Location, TerminatorEdge};
|
||||
use rustc_middle::ty::TyCtxt;
|
||||
|
||||
mod cursor;
|
||||
@ -163,12 +163,12 @@ pub trait Analysis<'tcx>: AnalysisDomain<'tcx> {
|
||||
/// in this function. That should go in `apply_call_return_effect`. For example, in the
|
||||
/// `InitializedPlaces` analyses, the return place for a function call is not marked as
|
||||
/// initialized here.
|
||||
fn apply_terminator_effect(
|
||||
fn apply_terminator_effect<'mir>(
|
||||
&mut self,
|
||||
state: &mut Self::Domain,
|
||||
terminator: &mir::Terminator<'tcx>,
|
||||
terminator: &'mir mir::Terminator<'tcx>,
|
||||
location: Location,
|
||||
);
|
||||
) -> TerminatorEdge<'mir, 'tcx>;
|
||||
|
||||
/// Updates the current dataflow state with an effect that occurs immediately *before* the
|
||||
/// given terminator.
|
||||
@ -198,20 +198,6 @@ pub trait Analysis<'tcx>: AnalysisDomain<'tcx> {
|
||||
return_places: CallReturnPlaces<'_, 'tcx>,
|
||||
);
|
||||
|
||||
/// Updates the current dataflow state with the effect of resuming from a `Yield` terminator.
|
||||
///
|
||||
/// This is similar to `apply_call_return_effect` in that it only takes place after the
|
||||
/// generator is resumed, not when it is dropped.
|
||||
///
|
||||
/// By default, no effects happen.
|
||||
fn apply_yield_resume_effect(
|
||||
&mut self,
|
||||
_state: &mut Self::Domain,
|
||||
_resume_block: BasicBlock,
|
||||
_resume_place: mir::Place<'tcx>,
|
||||
) {
|
||||
}
|
||||
|
||||
/// Updates the current dataflow state with the effect of taking a particular branch in a
|
||||
/// `SwitchInt` terminator.
|
||||
///
|
||||
@ -306,12 +292,12 @@ pub trait GenKillAnalysis<'tcx>: Analysis<'tcx> {
|
||||
}
|
||||
|
||||
/// See `Analysis::apply_terminator_effect`.
|
||||
fn terminator_effect(
|
||||
fn terminator_effect<'mir>(
|
||||
&mut self,
|
||||
trans: &mut impl GenKill<Self::Idx>,
|
||||
terminator: &mir::Terminator<'tcx>,
|
||||
trans: &mut Self::Domain,
|
||||
terminator: &'mir mir::Terminator<'tcx>,
|
||||
location: Location,
|
||||
);
|
||||
) -> TerminatorEdge<'mir, 'tcx>;
|
||||
|
||||
/// See `Analysis::apply_before_terminator_effect`.
|
||||
fn before_terminator_effect(
|
||||
@ -332,15 +318,6 @@ pub trait GenKillAnalysis<'tcx>: Analysis<'tcx> {
|
||||
return_places: CallReturnPlaces<'_, 'tcx>,
|
||||
);
|
||||
|
||||
/// See `Analysis::apply_yield_resume_effect`.
|
||||
fn yield_resume_effect(
|
||||
&mut self,
|
||||
_trans: &mut impl GenKill<Self::Idx>,
|
||||
_resume_block: BasicBlock,
|
||||
_resume_place: mir::Place<'tcx>,
|
||||
) {
|
||||
}
|
||||
|
||||
/// See `Analysis::apply_switch_int_edge_effects`.
|
||||
fn switch_int_edge_effects<G: GenKill<Self::Idx>>(
|
||||
&mut self,
|
||||
@ -374,13 +351,13 @@ where
|
||||
self.before_statement_effect(state, statement, location);
|
||||
}
|
||||
|
||||
fn apply_terminator_effect(
|
||||
fn apply_terminator_effect<'mir>(
|
||||
&mut self,
|
||||
state: &mut A::Domain,
|
||||
terminator: &mir::Terminator<'tcx>,
|
||||
terminator: &'mir mir::Terminator<'tcx>,
|
||||
location: Location,
|
||||
) {
|
||||
self.terminator_effect(state, terminator, location);
|
||||
) -> TerminatorEdge<'mir, 'tcx> {
|
||||
self.terminator_effect(state, terminator, location)
|
||||
}
|
||||
|
||||
fn apply_before_terminator_effect(
|
||||
@ -403,15 +380,6 @@ where
|
||||
self.call_return_effect(state, block, return_places);
|
||||
}
|
||||
|
||||
fn apply_yield_resume_effect(
|
||||
&mut self,
|
||||
state: &mut A::Domain,
|
||||
resume_block: BasicBlock,
|
||||
resume_place: mir::Place<'tcx>,
|
||||
) {
|
||||
self.yield_resume_effect(state, resume_block, resume_place);
|
||||
}
|
||||
|
||||
fn apply_switch_int_edge_effects(
|
||||
&mut self,
|
||||
block: BasicBlock,
|
||||
@ -621,29 +589,5 @@ pub trait SwitchIntEdgeEffects<D> {
|
||||
fn apply(&mut self, apply_edge_effect: impl FnMut(&mut D, SwitchIntTarget));
|
||||
}
|
||||
|
||||
/// List of places that are written to after a successful (non-unwind) return
|
||||
/// from a `Call` or `InlineAsm`.
|
||||
pub enum CallReturnPlaces<'a, 'tcx> {
|
||||
Call(mir::Place<'tcx>),
|
||||
InlineAsm(&'a [mir::InlineAsmOperand<'tcx>]),
|
||||
}
|
||||
|
||||
impl<'tcx> CallReturnPlaces<'_, 'tcx> {
|
||||
pub fn for_each(&self, mut f: impl FnMut(mir::Place<'tcx>)) {
|
||||
match *self {
|
||||
Self::Call(place) => f(place),
|
||||
Self::InlineAsm(operands) => {
|
||||
for op in operands {
|
||||
match *op {
|
||||
mir::InlineAsmOperand::Out { place: Some(place), .. }
|
||||
| mir::InlineAsmOperand::InOut { out_place: Some(place), .. } => f(place),
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
@ -198,14 +198,15 @@ impl<'tcx, D: Direction> Analysis<'tcx> for MockAnalysis<'tcx, D> {
|
||||
assert!(state.insert(idx));
|
||||
}
|
||||
|
||||
fn apply_terminator_effect(
|
||||
fn apply_terminator_effect<'mir>(
|
||||
&mut self,
|
||||
state: &mut Self::Domain,
|
||||
_terminator: &mir::Terminator<'tcx>,
|
||||
terminator: &'mir mir::Terminator<'tcx>,
|
||||
location: Location,
|
||||
) {
|
||||
) -> TerminatorEdge<'mir, 'tcx> {
|
||||
let idx = self.effect(Effect::Primary.at_index(location.statement_index));
|
||||
assert!(state.insert(idx));
|
||||
terminator.edges()
|
||||
}
|
||||
|
||||
fn apply_before_terminator_effect(
|
||||
|
@ -2,7 +2,6 @@ use rustc_index::bit_set::BitSet;
|
||||
use rustc_middle::mir::visit::Visitor;
|
||||
use rustc_middle::mir::*;
|
||||
|
||||
use crate::framework::CallReturnPlaces;
|
||||
use crate::{AnalysisDomain, GenKill, GenKillAnalysis};
|
||||
|
||||
/// A dataflow analysis that tracks whether a pointer or reference could possibly exist that points
|
||||
@ -15,7 +14,7 @@ use crate::{AnalysisDomain, GenKill, GenKillAnalysis};
|
||||
pub struct MaybeBorrowedLocals;
|
||||
|
||||
impl MaybeBorrowedLocals {
|
||||
fn transfer_function<'a, T>(&'a self, trans: &'a mut T) -> TransferFunction<'a, T> {
|
||||
pub(super) fn transfer_function<'a, T>(&'a self, trans: &'a mut T) -> TransferFunction<'a, T> {
|
||||
TransferFunction { trans }
|
||||
}
|
||||
}
|
||||
@ -50,13 +49,14 @@ impl<'tcx> GenKillAnalysis<'tcx> for MaybeBorrowedLocals {
|
||||
self.transfer_function(trans).visit_statement(statement, location);
|
||||
}
|
||||
|
||||
fn terminator_effect(
|
||||
fn terminator_effect<'mir>(
|
||||
&mut self,
|
||||
trans: &mut impl GenKill<Self::Idx>,
|
||||
terminator: &Terminator<'tcx>,
|
||||
trans: &mut Self::Domain,
|
||||
terminator: &'mir Terminator<'tcx>,
|
||||
location: Location,
|
||||
) {
|
||||
) -> TerminatorEdge<'mir, 'tcx> {
|
||||
self.transfer_function(trans).visit_terminator(terminator, location);
|
||||
terminator.edges()
|
||||
}
|
||||
|
||||
fn call_return_effect(
|
||||
@ -69,7 +69,7 @@ impl<'tcx> GenKillAnalysis<'tcx> for MaybeBorrowedLocals {
|
||||
}
|
||||
|
||||
/// A `Visitor` that defines the transfer function for `MaybeBorrowedLocals`.
|
||||
struct TransferFunction<'a, T> {
|
||||
pub(super) struct TransferFunction<'a, T> {
|
||||
trans: &'a mut T,
|
||||
}
|
||||
|
||||
|
@ -1,12 +1,12 @@
|
||||
use rustc_index::bit_set::{BitSet, ChunkedBitSet};
|
||||
use rustc_index::Idx;
|
||||
use rustc_middle::mir::{self, Body, Location};
|
||||
use rustc_middle::mir::{self, Body, CallReturnPlaces, Location, TerminatorEdge};
|
||||
use rustc_middle::ty::{self, TyCtxt};
|
||||
|
||||
use crate::drop_flag_effects_for_function_entry;
|
||||
use crate::drop_flag_effects_for_location;
|
||||
use crate::elaborate_drops::DropFlagState;
|
||||
use crate::framework::{CallReturnPlaces, SwitchIntEdgeEffects};
|
||||
use crate::framework::SwitchIntEdgeEffects;
|
||||
use crate::move_paths::{HasMoveData, InitIndex, InitKind, LookupResult, MoveData, MovePathIndex};
|
||||
use crate::on_lookup_result_bits;
|
||||
use crate::MoveDataParamEnv;
|
||||
@ -318,15 +318,16 @@ impl<'tcx> GenKillAnalysis<'tcx> for MaybeInitializedPlaces<'_, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
fn terminator_effect(
|
||||
fn terminator_effect<'mir>(
|
||||
&mut self,
|
||||
trans: &mut impl GenKill<Self::Idx>,
|
||||
_: &mir::Terminator<'tcx>,
|
||||
state: &mut Self::Domain,
|
||||
terminator: &'mir mir::Terminator<'tcx>,
|
||||
location: Location,
|
||||
) {
|
||||
) -> TerminatorEdge<'mir, 'tcx> {
|
||||
drop_flag_effects_for_location(self.tcx, self.body, self.mdpe, location, |path, s| {
|
||||
Self::update_bits(trans, path, s)
|
||||
Self::update_bits(state, path, s)
|
||||
});
|
||||
terminator.edges()
|
||||
}
|
||||
|
||||
fn call_return_effect(
|
||||
@ -438,15 +439,16 @@ impl<'tcx> GenKillAnalysis<'tcx> for MaybeUninitializedPlaces<'_, 'tcx> {
|
||||
// mutable borrow occurs. Places cannot become uninitialized through a mutable reference.
|
||||
}
|
||||
|
||||
fn terminator_effect(
|
||||
fn terminator_effect<'mir>(
|
||||
&mut self,
|
||||
trans: &mut impl GenKill<Self::Idx>,
|
||||
_terminator: &mir::Terminator<'tcx>,
|
||||
trans: &mut Self::Domain,
|
||||
terminator: &'mir mir::Terminator<'tcx>,
|
||||
location: Location,
|
||||
) {
|
||||
) -> TerminatorEdge<'mir, 'tcx> {
|
||||
drop_flag_effects_for_location(self.tcx, self.body, self.mdpe, location, |path, s| {
|
||||
Self::update_bits(trans, path, s)
|
||||
});
|
||||
terminator.edges()
|
||||
}
|
||||
|
||||
fn call_return_effect(
|
||||
@ -559,15 +561,16 @@ impl<'tcx> GenKillAnalysis<'tcx> for DefinitelyInitializedPlaces<'_, 'tcx> {
|
||||
})
|
||||
}
|
||||
|
||||
fn terminator_effect(
|
||||
fn terminator_effect<'mir>(
|
||||
&mut self,
|
||||
trans: &mut impl GenKill<Self::Idx>,
|
||||
_terminator: &mir::Terminator<'tcx>,
|
||||
trans: &mut Self::Domain,
|
||||
terminator: &'mir mir::Terminator<'tcx>,
|
||||
location: Location,
|
||||
) {
|
||||
) -> TerminatorEdge<'mir, 'tcx> {
|
||||
drop_flag_effects_for_location(self.tcx, self.body, self.mdpe, location, |path, s| {
|
||||
Self::update_bits(trans, path, s)
|
||||
})
|
||||
});
|
||||
terminator.edges()
|
||||
}
|
||||
|
||||
fn call_return_effect(
|
||||
@ -640,13 +643,13 @@ impl<'tcx> GenKillAnalysis<'tcx> for EverInitializedPlaces<'_, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
#[instrument(skip(self, trans, _terminator), level = "debug")]
|
||||
fn terminator_effect(
|
||||
#[instrument(skip(self, trans, terminator), level = "debug")]
|
||||
fn terminator_effect<'mir>(
|
||||
&mut self,
|
||||
trans: &mut impl GenKill<Self::Idx>,
|
||||
_terminator: &mir::Terminator<'tcx>,
|
||||
trans: &mut Self::Domain,
|
||||
terminator: &'mir mir::Terminator<'tcx>,
|
||||
location: Location,
|
||||
) {
|
||||
) -> TerminatorEdge<'mir, 'tcx> {
|
||||
let (body, move_data) = (self.body, self.move_data());
|
||||
let term = body[location.block].terminator();
|
||||
let init_loc_map = &move_data.init_loc_map;
|
||||
@ -660,6 +663,7 @@ impl<'tcx> GenKillAnalysis<'tcx> for EverInitializedPlaces<'_, 'tcx> {
|
||||
})
|
||||
.copied(),
|
||||
);
|
||||
terminator.edges()
|
||||
}
|
||||
|
||||
fn call_return_effect(
|
||||
|
@ -1,8 +1,10 @@
|
||||
use rustc_index::bit_set::{BitSet, ChunkedBitSet};
|
||||
use rustc_middle::mir::visit::{MutatingUseContext, NonMutatingUseContext, PlaceContext, Visitor};
|
||||
use rustc_middle::mir::{self, Local, Location, Place, StatementKind};
|
||||
use rustc_middle::mir::{
|
||||
self, CallReturnPlaces, Local, Location, Place, StatementKind, TerminatorEdge,
|
||||
};
|
||||
|
||||
use crate::{Analysis, AnalysisDomain, Backward, CallReturnPlaces, GenKill, GenKillAnalysis};
|
||||
use crate::{Analysis, AnalysisDomain, Backward, GenKill, GenKillAnalysis};
|
||||
|
||||
/// A [live-variable dataflow analysis][liveness].
|
||||
///
|
||||
@ -56,13 +58,14 @@ impl<'tcx> GenKillAnalysis<'tcx> for MaybeLiveLocals {
|
||||
TransferFunction(trans).visit_statement(statement, location);
|
||||
}
|
||||
|
||||
fn terminator_effect(
|
||||
fn terminator_effect<'mir>(
|
||||
&mut self,
|
||||
trans: &mut impl GenKill<Self::Idx>,
|
||||
terminator: &mir::Terminator<'tcx>,
|
||||
trans: &mut Self::Domain,
|
||||
terminator: &'mir mir::Terminator<'tcx>,
|
||||
location: Location,
|
||||
) {
|
||||
) -> TerminatorEdge<'mir, 'tcx> {
|
||||
TransferFunction(trans).visit_terminator(terminator, location);
|
||||
terminator.edges()
|
||||
}
|
||||
|
||||
fn call_return_effect(
|
||||
@ -72,24 +75,13 @@ impl<'tcx> GenKillAnalysis<'tcx> for MaybeLiveLocals {
|
||||
return_places: CallReturnPlaces<'_, 'tcx>,
|
||||
) {
|
||||
return_places.for_each(|place| {
|
||||
if let Some(local) = place.as_local() {
|
||||
trans.kill(local);
|
||||
}
|
||||
YieldResumeEffect(trans).visit_place(
|
||||
&place,
|
||||
PlaceContext::MutatingUse(MutatingUseContext::Yield),
|
||||
Location::START,
|
||||
)
|
||||
});
|
||||
}
|
||||
|
||||
fn yield_resume_effect(
|
||||
&mut self,
|
||||
trans: &mut impl GenKill<Self::Idx>,
|
||||
_resume_block: mir::BasicBlock,
|
||||
resume_place: mir::Place<'tcx>,
|
||||
) {
|
||||
YieldResumeEffect(trans).visit_place(
|
||||
&resume_place,
|
||||
PlaceContext::MutatingUse(MutatingUseContext::Yield),
|
||||
Location::START,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct TransferFunction<'a, T>(pub &'a mut T);
|
||||
@ -99,16 +91,12 @@ where
|
||||
T: GenKill<Local>,
|
||||
{
|
||||
fn visit_place(&mut self, place: &mir::Place<'tcx>, context: PlaceContext, location: Location) {
|
||||
if let PlaceContext::MutatingUse(MutatingUseContext::Yield) = context {
|
||||
// The resume place is evaluated and assigned to only after generator resumes, so its
|
||||
// effect is handled separately in `yield_resume_effect`.
|
||||
return;
|
||||
}
|
||||
|
||||
match DefUse::for_place(*place, context) {
|
||||
Some(DefUse::Def) => {
|
||||
if let PlaceContext::MutatingUse(
|
||||
MutatingUseContext::Call | MutatingUseContext::AsmOutput,
|
||||
MutatingUseContext::Yield
|
||||
| MutatingUseContext::Call
|
||||
| MutatingUseContext::AsmOutput,
|
||||
) = context
|
||||
{
|
||||
// For the associated terminators, this is only a `Def` when the terminator returns
|
||||
@ -287,13 +275,14 @@ impl<'a, 'tcx> Analysis<'tcx> for MaybeTransitiveLiveLocals<'a> {
|
||||
TransferFunction(trans).visit_statement(statement, location);
|
||||
}
|
||||
|
||||
fn apply_terminator_effect(
|
||||
fn apply_terminator_effect<'mir>(
|
||||
&mut self,
|
||||
trans: &mut Self::Domain,
|
||||
terminator: &mir::Terminator<'tcx>,
|
||||
terminator: &'mir mir::Terminator<'tcx>,
|
||||
location: Location,
|
||||
) {
|
||||
) -> TerminatorEdge<'mir, 'tcx> {
|
||||
TransferFunction(trans).visit_terminator(terminator, location);
|
||||
TerminatorEdge::None
|
||||
}
|
||||
|
||||
fn apply_call_return_effect(
|
||||
@ -303,22 +292,11 @@ impl<'a, 'tcx> Analysis<'tcx> for MaybeTransitiveLiveLocals<'a> {
|
||||
return_places: CallReturnPlaces<'_, 'tcx>,
|
||||
) {
|
||||
return_places.for_each(|place| {
|
||||
if let Some(local) = place.as_local() {
|
||||
trans.remove(local);
|
||||
}
|
||||
YieldResumeEffect(trans).visit_place(
|
||||
&place,
|
||||
PlaceContext::MutatingUse(MutatingUseContext::Yield),
|
||||
Location::START,
|
||||
)
|
||||
});
|
||||
}
|
||||
|
||||
fn apply_yield_resume_effect(
|
||||
&mut self,
|
||||
trans: &mut Self::Domain,
|
||||
_resume_block: mir::BasicBlock,
|
||||
resume_place: mir::Place<'tcx>,
|
||||
) {
|
||||
YieldResumeEffect(trans).visit_place(
|
||||
&resume_place,
|
||||
PlaceContext::MutatingUse(MutatingUseContext::Yield),
|
||||
Location::START,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -5,7 +5,7 @@ use rustc_middle::mir::*;
|
||||
use std::borrow::Cow;
|
||||
|
||||
use super::MaybeBorrowedLocals;
|
||||
use crate::{CallReturnPlaces, GenKill, ResultsClonedCursor};
|
||||
use crate::{GenKill, ResultsClonedCursor};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct MaybeStorageLive<'a> {
|
||||
@ -66,13 +66,14 @@ impl<'tcx, 'a> crate::GenKillAnalysis<'tcx> for MaybeStorageLive<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
fn terminator_effect(
|
||||
fn terminator_effect<'mir>(
|
||||
&mut self,
|
||||
_trans: &mut impl GenKill<Self::Idx>,
|
||||
_: &Terminator<'tcx>,
|
||||
_trans: &mut Self::Domain,
|
||||
terminator: &'mir Terminator<'tcx>,
|
||||
_: Location,
|
||||
) {
|
||||
) -> TerminatorEdge<'mir, 'tcx> {
|
||||
// Terminators have no effect
|
||||
terminator.edges()
|
||||
}
|
||||
|
||||
fn call_return_effect(
|
||||
@ -137,13 +138,14 @@ impl<'tcx> crate::GenKillAnalysis<'tcx> for MaybeStorageDead {
|
||||
}
|
||||
}
|
||||
|
||||
fn terminator_effect(
|
||||
fn terminator_effect<'mir>(
|
||||
&mut self,
|
||||
_trans: &mut impl GenKill<Self::Idx>,
|
||||
_: &Terminator<'tcx>,
|
||||
_: &mut Self::Domain,
|
||||
terminator: &'mir Terminator<'tcx>,
|
||||
_: Location,
|
||||
) {
|
||||
) -> TerminatorEdge<'mir, 'tcx> {
|
||||
// Terminators have no effect
|
||||
terminator.edges()
|
||||
}
|
||||
|
||||
fn call_return_effect(
|
||||
@ -254,7 +256,10 @@ impl<'tcx> crate::GenKillAnalysis<'tcx> for MaybeRequiresStorage<'_, '_, 'tcx> {
|
||||
loc: Location,
|
||||
) {
|
||||
// If a place is borrowed in a terminator, it needs storage for that terminator.
|
||||
self.borrowed_locals.mut_analysis().terminator_effect(trans, terminator, loc);
|
||||
self.borrowed_locals
|
||||
.mut_analysis()
|
||||
.transfer_function(trans)
|
||||
.visit_terminator(terminator, loc);
|
||||
|
||||
match &terminator.kind {
|
||||
TerminatorKind::Call { destination, .. } => {
|
||||
@ -300,12 +305,12 @@ impl<'tcx> crate::GenKillAnalysis<'tcx> for MaybeRequiresStorage<'_, '_, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
fn terminator_effect(
|
||||
fn terminator_effect<'t>(
|
||||
&mut self,
|
||||
trans: &mut impl GenKill<Self::Idx>,
|
||||
terminator: &Terminator<'tcx>,
|
||||
trans: &mut Self::Domain,
|
||||
terminator: &'t Terminator<'tcx>,
|
||||
loc: Location,
|
||||
) {
|
||||
) -> TerminatorEdge<'t, 'tcx> {
|
||||
match terminator.kind {
|
||||
// For call terminators the destination requires storage for the call
|
||||
// and after the call returns successfully, but not after a panic.
|
||||
@ -337,6 +342,7 @@ impl<'tcx> crate::GenKillAnalysis<'tcx> for MaybeRequiresStorage<'_, '_, 'tcx> {
|
||||
}
|
||||
|
||||
self.check_for_move(trans, loc);
|
||||
terminator.edges()
|
||||
}
|
||||
|
||||
fn call_return_effect(
|
||||
@ -347,15 +353,6 @@ impl<'tcx> crate::GenKillAnalysis<'tcx> for MaybeRequiresStorage<'_, '_, 'tcx> {
|
||||
) {
|
||||
return_places.for_each(|place| trans.gen(place.local));
|
||||
}
|
||||
|
||||
fn yield_resume_effect(
|
||||
&mut self,
|
||||
trans: &mut impl GenKill<Self::Idx>,
|
||||
_resume_block: BasicBlock,
|
||||
resume_place: Place<'tcx>,
|
||||
) {
|
||||
trans.gen(resume_place.local);
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> MaybeRequiresStorage<'_, '_, 'tcx> {
|
||||
|
@ -28,9 +28,9 @@ pub use self::drop_flag_effects::{
|
||||
};
|
||||
pub use self::framework::{
|
||||
fmt, graphviz, lattice, visit_results, Analysis, AnalysisDomain, AnalysisResults, Backward,
|
||||
CallReturnPlaces, CloneAnalysis, Direction, Engine, Forward, GenKill, GenKillAnalysis,
|
||||
JoinSemiLattice, MaybeUnreachable, Results, ResultsCloned, ResultsClonedCursor, ResultsCursor,
|
||||
ResultsRefCursor, ResultsVisitable, ResultsVisitor, SwitchIntEdgeEffects,
|
||||
CloneAnalysis, Direction, Engine, Forward, GenKill, GenKillAnalysis, JoinSemiLattice,
|
||||
MaybeUnreachable, Results, ResultsCloned, ResultsClonedCursor, ResultsCursor, ResultsRefCursor,
|
||||
ResultsVisitable, ResultsVisitor, SwitchIntEdgeEffects,
|
||||
};
|
||||
|
||||
use self::move_paths::MoveData;
|
||||
|
@ -47,8 +47,7 @@ use rustc_target::abi::{FieldIdx, VariantIdx};
|
||||
|
||||
use crate::lattice::{HasBottom, HasTop};
|
||||
use crate::{
|
||||
fmt::DebugWithContext, Analysis, AnalysisDomain, CallReturnPlaces, JoinSemiLattice,
|
||||
SwitchIntEdgeEffects,
|
||||
fmt::DebugWithContext, Analysis, AnalysisDomain, JoinSemiLattice, SwitchIntEdgeEffects,
|
||||
};
|
||||
|
||||
pub trait ValueAnalysis<'tcx> {
|
||||
@ -353,22 +352,23 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
fn apply_terminator_effect(
|
||||
fn apply_terminator_effect<'mir>(
|
||||
&mut self,
|
||||
state: &mut Self::Domain,
|
||||
terminator: &Terminator<'tcx>,
|
||||
terminator: &'mir Terminator<'tcx>,
|
||||
_location: Location,
|
||||
) {
|
||||
) -> TerminatorEdge<'mir, 'tcx> {
|
||||
if state.is_reachable() {
|
||||
self.0.handle_terminator(terminator, state);
|
||||
}
|
||||
terminator.edges()
|
||||
}
|
||||
|
||||
fn apply_call_return_effect(
|
||||
&mut self,
|
||||
state: &mut Self::Domain,
|
||||
_block: BasicBlock,
|
||||
return_places: crate::CallReturnPlaces<'_, 'tcx>,
|
||||
return_places: CallReturnPlaces<'_, 'tcx>,
|
||||
) {
|
||||
if state.is_reachable() {
|
||||
self.0.handle_call_return(return_places, state)
|
||||
|
Loading…
Reference in New Issue
Block a user