diff options
| author | Ralf Jung <post@ralfj.de> | 2024-11-28 08:05:16 +0000 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-11-28 08:05:16 +0000 |
| commit | 4624dadc209f595fffc87ef54a54156a5d31cec7 (patch) | |
| tree | dd441ff27ed00a8826fbb8fd042eef1a2293b260 /compiler/rustc_mir_dataflow/src/impls | |
| parent | 987d642de5bf3c8e263c477ab728db5cd88c0ec3 (diff) | |
| parent | 8e2d72bac8e29cda5b1457720dcdc66def70d9d4 (diff) | |
Merge pull request #4063 from rust-lang/rustup-2024-11-28
Automatic Rustup
Diffstat (limited to 'compiler/rustc_mir_dataflow/src/impls')
4 files changed, 36 insertions, 152 deletions
diff --git a/compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs b/compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs index 859019fd1f6..cec654cac72 100644 --- a/compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs +++ b/compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs @@ -15,7 +15,7 @@ use crate::{Analysis, GenKill}; pub struct MaybeBorrowedLocals; impl MaybeBorrowedLocals { - pub(super) fn transfer_function<'a, T>(&'a self, trans: &'a mut T) -> TransferFunction<'a, T> { + pub(super) fn transfer_function<'a, T>(trans: &'a mut T) -> TransferFunction<'a, T> { TransferFunction { trans } } } @@ -39,7 +39,7 @@ impl<'tcx> Analysis<'tcx> for MaybeBorrowedLocals { statement: &Statement<'tcx>, location: Location, ) { - self.transfer_function(trans).visit_statement(statement, location); + Self::transfer_function(trans).visit_statement(statement, location); } fn apply_terminator_effect<'mir>( @@ -48,7 +48,7 @@ impl<'tcx> Analysis<'tcx> for MaybeBorrowedLocals { terminator: &'mir Terminator<'tcx>, location: Location, ) -> TerminatorEdges<'mir, 'tcx> { - self.transfer_function(trans).visit_terminator(terminator, location); + Self::transfer_function(trans).visit_terminator(terminator, location); terminator.edges() } } diff --git a/compiler/rustc_mir_dataflow/src/impls/initialized.rs b/compiler/rustc_mir_dataflow/src/impls/initialized.rs index 9bb50d1e056..2c10d4b1cd3 100644 --- a/compiler/rustc_mir_dataflow/src/impls/initialized.rs +++ b/compiler/rustc_mir_dataflow/src/impls/initialized.rs @@ -12,7 +12,7 @@ use crate::framework::SwitchIntEdgeEffects; use crate::move_paths::{HasMoveData, InitIndex, InitKind, LookupResult, MoveData, MovePathIndex}; use crate::{ Analysis, GenKill, MaybeReachable, drop_flag_effects, drop_flag_effects_for_function_entry, - drop_flag_effects_for_location, lattice, on_all_children_bits, on_lookup_result_bits, + drop_flag_effects_for_location, on_all_children_bits, on_lookup_result_bits, }; /// `MaybeInitializedPlaces` tracks all places that might be @@ -42,10 +42,10 @@ use crate::{ /// } /// ``` /// -/// To determine whether a place *must* be initialized at a -/// particular control-flow point, one can take the set-difference -/// between this data and the data from `MaybeUninitializedPlaces` at the -/// corresponding control-flow point. +/// To determine whether a place is *definitely* initialized at a +/// particular control-flow point, one can take the set-complement +/// of the data from `MaybeUninitializedPlaces` at the corresponding +/// control-flow point. /// /// Similarly, at a given `drop` statement, the set-intersection /// between this data and `MaybeUninitializedPlaces` yields the set of @@ -117,10 +117,10 @@ impl<'a, 'tcx> HasMoveData<'tcx> for MaybeInitializedPlaces<'a, 'tcx> { /// } /// ``` /// -/// To determine whether a place *must* be uninitialized at a -/// particular control-flow point, one can take the set-difference -/// between this data and the data from `MaybeInitializedPlaces` at the -/// corresponding control-flow point. +/// To determine whether a place is *definitely* uninitialized at a +/// particular control-flow point, one can take the set-complement +/// of the data from `MaybeInitializedPlaces` at the corresponding +/// control-flow point. /// /// Similarly, at a given `drop` statement, the set-intersection /// between this data and `MaybeInitializedPlaces` yields the set of @@ -170,57 +170,6 @@ impl<'tcx> HasMoveData<'tcx> for MaybeUninitializedPlaces<'_, 'tcx> { } } -/// `DefinitelyInitializedPlaces` tracks all places that are definitely -/// initialized upon reaching a particular point in the control flow -/// for a function. -/// -/// For example, in code like the following, we have corresponding -/// dataflow information shown in the right-hand comments. -/// -/// ```rust -/// struct S; -/// fn foo(pred: bool) { // definite-init: -/// // { } -/// let a = S; let mut b = S; let c; let d; // {a, b } -/// -/// if pred { -/// drop(a); // { b, } -/// b = S; // { b, } -/// -/// } else { -/// drop(b); // {a, } -/// d = S; // {a, d} -/// -/// } // { } -/// -/// c = S; // { c } -/// } -/// ``` -/// -/// To determine whether a place *may* be uninitialized at a -/// particular control-flow point, one can take the set-complement -/// of this data. -/// -/// Similarly, at a given `drop` statement, the set-difference between -/// this data and `MaybeInitializedPlaces` yields the set of places -/// that would require a dynamic drop-flag at that statement. -pub struct DefinitelyInitializedPlaces<'a, 'tcx> { - body: &'a Body<'tcx>, - move_data: &'a MoveData<'tcx>, -} - -impl<'a, 'tcx> DefinitelyInitializedPlaces<'a, 'tcx> { - pub fn new(body: &'a Body<'tcx>, move_data: &'a MoveData<'tcx>) -> Self { - DefinitelyInitializedPlaces { body, move_data } - } -} - -impl<'a, 'tcx> HasMoveData<'tcx> for DefinitelyInitializedPlaces<'a, 'tcx> { - fn move_data(&self) -> &MoveData<'tcx> { - self.move_data - } -} - /// `EverInitializedPlaces` tracks all places that might have ever been /// initialized upon reaching a particular point in the control flow /// for a function, without an intervening `StorageDead`. @@ -293,19 +242,6 @@ impl<'tcx> MaybeUninitializedPlaces<'_, 'tcx> { } } -impl<'a, 'tcx> DefinitelyInitializedPlaces<'a, 'tcx> { - fn update_bits( - trans: &mut <Self as Analysis<'tcx>>::Domain, - path: MovePathIndex, - state: DropFlagState, - ) { - match state { - DropFlagState::Absent => trans.kill(path), - DropFlagState::Present => trans.gen_(path), - } - } -} - impl<'tcx> Analysis<'tcx> for MaybeInitializedPlaces<'_, 'tcx> { /// There can be many more `MovePathIndex` than there are locals in a MIR body. /// We use a chunked bitset to avoid paying too high a memory footprint. @@ -554,70 +490,6 @@ impl<'tcx> Analysis<'tcx> for MaybeUninitializedPlaces<'_, 'tcx> { } } -impl<'a, 'tcx> Analysis<'tcx> for DefinitelyInitializedPlaces<'a, 'tcx> { - /// Use set intersection as the join operator. - type Domain = lattice::Dual<BitSet<MovePathIndex>>; - - const NAME: &'static str = "definite_init"; - - fn bottom_value(&self, _: &mir::Body<'tcx>) -> Self::Domain { - // bottom = initialized (start_block_effect counters this at outset) - lattice::Dual(BitSet::new_filled(self.move_data().move_paths.len())) - } - - // sets on_entry bits for Arg places - fn initialize_start_block(&self, _: &mir::Body<'tcx>, state: &mut Self::Domain) { - state.0.clear(); - - drop_flag_effects_for_function_entry(self.body, self.move_data, |path, s| { - assert!(s == DropFlagState::Present); - state.0.insert(path); - }); - } - - fn apply_statement_effect( - &mut self, - trans: &mut Self::Domain, - _statement: &mir::Statement<'tcx>, - location: Location, - ) { - drop_flag_effects_for_location(self.body, self.move_data, location, |path, s| { - Self::update_bits(trans, path, s) - }) - } - - fn apply_terminator_effect<'mir>( - &mut self, - trans: &mut Self::Domain, - terminator: &'mir mir::Terminator<'tcx>, - location: Location, - ) -> TerminatorEdges<'mir, 'tcx> { - drop_flag_effects_for_location(self.body, self.move_data, location, |path, s| { - Self::update_bits(trans, path, s) - }); - terminator.edges() - } - - fn apply_call_return_effect( - &mut self, - trans: &mut Self::Domain, - _block: mir::BasicBlock, - return_places: CallReturnPlaces<'_, 'tcx>, - ) { - return_places.for_each(|place| { - // when a call returns successfully, that means we need to set - // the bits for that dest_place to 1 (initialized). - on_lookup_result_bits( - self.move_data(), - self.move_data().rev_lookup.find(place.as_ref()), - |mpi| { - trans.gen_(mpi); - }, - ); - }); - } -} - impl<'tcx> Analysis<'tcx> for EverInitializedPlaces<'_, 'tcx> { /// There can be many more `InitIndex` than there are locals in a MIR body. /// We use a chunked bitset to avoid paying too high a memory footprint. diff --git a/compiler/rustc_mir_dataflow/src/impls/mod.rs b/compiler/rustc_mir_dataflow/src/impls/mod.rs index 9b5bfa9bfa0..b9e194b00c5 100644 --- a/compiler/rustc_mir_dataflow/src/impls/mod.rs +++ b/compiler/rustc_mir_dataflow/src/impls/mod.rs @@ -9,10 +9,11 @@ mod storage_liveness; pub use self::borrowed_locals::{MaybeBorrowedLocals, borrowed_locals}; pub use self::initialized::{ - DefinitelyInitializedPlaces, EverInitializedPlaces, MaybeInitializedPlaces, - MaybeUninitializedPlaces, + EverInitializedPlaces, MaybeInitializedPlaces, MaybeUninitializedPlaces, }; pub use self::liveness::{ MaybeLiveLocals, MaybeTransitiveLiveLocals, TransferFunction as LivenessTransferFunction, }; -pub use self::storage_liveness::{MaybeRequiresStorage, MaybeStorageDead, MaybeStorageLive}; +pub use self::storage_liveness::{ + MaybeRequiresStorage, MaybeStorageDead, MaybeStorageLive, always_storage_live_locals, +}; diff --git a/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs b/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs index 576289e228a..1aae06d79d3 100644 --- a/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs +++ b/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs @@ -7,6 +7,23 @@ use rustc_middle::mir::*; use super::MaybeBorrowedLocals; use crate::{Analysis, GenKill, ResultsCursor}; +/// The set of locals in a MIR body that do not have `StorageLive`/`StorageDead` annotations. +/// +/// These locals have fixed storage for the duration of the body. +pub fn always_storage_live_locals(body: &Body<'_>) -> BitSet<Local> { + let mut always_live_locals = BitSet::new_filled(body.local_decls.len()); + + for block in &*body.basic_blocks { + for statement in &block.statements { + if let StatementKind::StorageLive(l) | StatementKind::StorageDead(l) = statement.kind { + always_live_locals.remove(l); + } + } + } + + always_live_locals +} + pub struct MaybeStorageLive<'a> { always_live_locals: Cow<'a, BitSet<Local>>, } @@ -28,10 +45,7 @@ impl<'a, 'tcx> Analysis<'tcx> for MaybeStorageLive<'a> { } fn initialize_start_block(&self, body: &Body<'tcx>, on_entry: &mut Self::Domain) { - assert_eq!(body.local_decls.len(), self.always_live_locals.domain_size()); - for local in self.always_live_locals.iter() { - on_entry.insert(local); - } + on_entry.union(&*self.always_live_locals); for arg in body.args_iter() { on_entry.insert(arg); @@ -135,7 +149,7 @@ impl<'tcx> Analysis<'tcx> for MaybeRequiresStorage<'_, 'tcx> { loc: Location, ) { // If a place is borrowed in a statement, it needs storage for that statement. - self.borrowed_locals.mut_analysis().apply_statement_effect(trans, stmt, loc); + MaybeBorrowedLocals::transfer_function(trans).visit_statement(stmt, loc); match &stmt.kind { StatementKind::StorageDead(l) => trans.kill(*l), @@ -180,10 +194,7 @@ impl<'tcx> Analysis<'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() - .transfer_function(trans) - .visit_terminator(terminator, loc); + MaybeBorrowedLocals::transfer_function(trans).visit_terminator(terminator, loc); match &terminator.kind { TerminatorKind::Call { destination, .. } => { |
