flowistry_pdg_construction::local_analysis

Struct LocalAnalysis

Source
pub(crate) struct LocalAnalysis<'tcx, 'a> {
    pub(crate) memo: &'a MemoPdgConstructor<'tcx>,
    pub(crate) root: Instance<'tcx>,
    body_with_facts: &'tcx CachedBody<'tcx>,
    pub(crate) mono_body: Body<'tcx>,
    pub(crate) def_id: DefId,
    pub(crate) place_info: PlaceInfo<'tcx>,
    control_dependencies: ControlDependencies<BasicBlock>,
    pub(crate) body_assignments: BodyAssignments,
    start_loc: FxHashSet<RichLocation>,
}

Fields§

§memo: &'a MemoPdgConstructor<'tcx>§root: Instance<'tcx>§body_with_facts: &'tcx CachedBody<'tcx>§mono_body: Body<'tcx>§def_id: DefId§place_info: PlaceInfo<'tcx>§control_dependencies: ControlDependencies<BasicBlock>§body_assignments: BodyAssignments§start_loc: FxHashSet<RichLocation>

Implementations§

Source§

impl<'tcx, 'a> LocalAnalysis<'tcx, 'a>

Source

pub(crate) fn can_approximate_async_functions( &self, def_id: DefId, ) -> Option<fn(_: &LocalAnalysis<'tcx, 'a>, _: &mut dyn Visitor<'tcx>, _: ArgSlice<'a, 'tcx>, _: Place<'tcx>, _: Location)>

Special case behavior for calls to functions used in desugaring async functions.

Ensures that functions like Pin::new_unchecked are not modularly-approximated.

Source

fn approximate_into_future( &self, vis: &mut dyn Visitor<'tcx>, args: ArgSlice<'_, 'tcx>, destination: Place<'tcx>, location: Location, )

Source

fn approximate_new_unchecked( &self, vis: &mut dyn Visitor<'tcx>, args: ArgSlice<'_, 'tcx>, destination: Place<'tcx>, location: Location, )

Source§

impl<'tcx> LocalAnalysis<'tcx, '_>

Source

pub(crate) fn try_poll_call_kind<'a>( &'a self, def_id: DefId, resolved_fn: Instance<'tcx>, original_args: ArgSlice<'a, 'tcx>, ) -> AsyncDeterminationResult<CallKind<'tcx>>

Checks whether the function call, described by the unresolved def_id and the resolved instance resolved_fn is a call to <T as Future>::poll where T is the type of an async fn or async {} created generator.

Resolves the original arguments that constituted the generator.

Source

fn find_async_args<'a>( &'a self, args: ArgSlice<'a, 'tcx>, ) -> Result<AsyncFnPollEnv<'tcx>, String>

Given the arguments to a Future::poll call, walk back through the body to find the original future being polled, and get the arguments to the future.

Source§

impl<'tcx, 'a> LocalAnalysis<'tcx, 'a>

Source

pub(crate) fn new( memo: &'a MemoPdgConstructor<'tcx>, root: Instance<'tcx>, ) -> LocalAnalysis<'tcx, 'a>

Creates [GraphConstructor] for a function resolved as fn_resolution in a given calling_context.

Returns None, if we were unable to load the body.

Source

fn make_dep_node( &self, place: Place<'tcx>, location: impl Into<RichLocation>, ) -> DepNode<'tcx>

Source

pub(crate) fn find_control_inputs( &self, location: Location, ) -> Vec<(DepNode<'tcx>, DepEdge)>

Returns all pairs of (src, edge)`` such that the given locationis control-dependent onedgewith inputsrc`.

Source

fn call_change_callback(&self) -> Option<&dyn CallChangeCallback<'tcx>>

Source

pub(crate) fn async_info(&self) -> &AsyncInfo

Source

pub(crate) fn make_call_string( &self, location: impl Into<RichLocation>, ) -> CallString

Source

pub(crate) fn aliases( &'a self, place: Place<'tcx>, ) -> impl Iterator<Item = Place<'tcx>> + 'a

Returns the aliases of place. See PlaceInfo::aliases for details.

Source

pub(crate) fn tcx(&self) -> TyCtxt<'tcx>

Source

pub(crate) fn dcx(&self) -> DiagCtxtHandle<'tcx>

Source

pub(crate) fn find_data_inputs( &self, state: &InstructionState<'tcx>, input: Place<'tcx>, ) -> Vec<DepNode<'tcx>>

Returns all nodes src such that src is:

  1. Part of the value of input
  2. The most-recently modified location for src
Source

pub(crate) fn find_outputs( &self, mutated: Place<'tcx>, location: Location, ) -> Vec<(Place<'tcx>, DepNode<'tcx>)>

Source

fn apply_mutation( &self, state: &mut InstructionState<'tcx>, location: Location, mutated: Place<'tcx>, )

Updates the last-mutated location for dst to the given location.

Source

pub(crate) fn operand_to_def_id( &self, func: &Operand<'tcx>, ) -> Option<(DefId, GenericArgsRef<'tcx>)>

Resolve a function Operand to a specific DefId and generic arguments if possible.

Source

fn fmt_fn(&self, def_id: DefId) -> String

Source

pub(crate) fn determine_call_handling<'b>( &'b self, location: Location, func: Cow<'_, Operand<'tcx>>, args: Cow<'b, [Spanned<Operand<'tcx>>]>, span: Span, ) -> Option<CallHandling<'tcx, 'b>>

Source

fn handle_call( &self, state: &mut InstructionState<'tcx>, location: Location, func: &Operand<'tcx>, args: &[Spanned<Operand<'tcx>>], destination: Place<'tcx>, span: Span, ) -> bool

Attempt to inline a call to a function.

The return indicates whether we were successfully able to perform the inlining.

Source

fn modular_mutation_visitor<'b: 'a>( &'b self, state: &'a mut InstructionState<'tcx>, ) -> ModularMutationVisitor<'b, 'tcx, impl FnMut(Location, Mutation<'tcx>) + 'b>

Source

pub(crate) fn generic_args(&self) -> GenericArgsRef<'tcx>

Source

pub(crate) fn construct_partial(&'a self) -> PartialGraph<'tcx>

Source

fn classify_call_kind<'b>( &'b self, def_id: DefId, resolved_fn: Instance<'tcx>, original_args: &'b [Spanned<Operand<'tcx>>], span: Span, ) -> CallKind<'tcx>

Determine the type of call-site.

The error case is if we tried to resolve this as async and failed. We know it is async but we couldn’t determine the information needed to analyze the function, therefore we will have to approximate it.

Source

fn try_indirect_call_kind(&self, def_id: DefId) -> Option<CallKind<'tcx>>

Source

fn terminator_visitor<'b: 'a>( &'b self, state: &'b mut InstructionState<'tcx>, time: Time, ) -> ModularMutationVisitor<'b, 'tcx, impl FnMut(Location, Mutation<'tcx>) + 'b>

Source§

impl<'tcx> LocalAnalysis<'tcx, '_>

Source

fn handle_terminator( &self, terminator: &Terminator<'tcx>, state: &mut InstructionState<'tcx>, location: Location, time: Time, )

Trait Implementations§

Source§

impl<'a, 'tcx> Analysis<'tcx> for &'a LocalAnalysis<'tcx, 'a>

Source§

const NAME: &'static str = "LocalPdgConstruction"

A descriptive name for this analysis. Used only for debugging. Read more
Source§

type Domain = InstructionState<'tcx>

The type that holds the dataflow state at any given point in the program.
Source§

fn bottom_value(&self, _body: &Body<'tcx>) -> Self::Domain

Returns the initial value of the dataflow state upon entry to each basic block.
Source§

fn initialize_start_block(&self, _body: &Body<'tcx>, _state: &mut Self::Domain)

Mutates the initial value of the dataflow state upon entry to the START_BLOCK. Read more
Source§

fn apply_primary_statement_effect( &mut self, state: &mut Self::Domain, statement: &Statement<'tcx>, location: Location, )

Updates the current dataflow state with the effect of evaluating a statement.
Source§

fn apply_primary_terminator_effect<'mir>( &mut self, state: &mut Self::Domain, terminator: &'mir Terminator<'tcx>, location: Location, ) -> TerminatorEdges<'mir, 'tcx>

Updates the current dataflow state with the effect of evaluating a terminator. Read more
Source§

fn apply_call_return_effect( &mut self, _state: &mut Self::Domain, _block: BasicBlock, _return_places: CallReturnPlaces<'_, 'tcx>, )

Updates the current dataflow state with the effect of a successful return from a Call terminator. Read more
§

type Direction = Forward

The direction of this analysis. Either Forward or Backward.
§

fn apply_early_statement_effect( &mut self, _state: &mut Self::Domain, _statement: &Statement<'tcx>, _location: Location, )

Updates the current dataflow state with an “early” effect, i.e. one that occurs immediately before the given statement. Read more
§

fn apply_early_terminator_effect( &mut self, _state: &mut Self::Domain, _terminator: &Terminator<'tcx>, _location: Location, )

Updates the current dataflow state with an effect that occurs immediately before the given terminator. Read more
§

fn apply_switch_int_edge_effects( &mut self, _block: BasicBlock, _discr: &Operand<'tcx>, _apply_edge_effects: &mut impl SwitchIntEdgeEffects<Self::Domain>, )

Updates the current dataflow state with the effect of taking a particular branch in a SwitchInt terminator. Read more
§

fn iterate_to_fixpoint<'mir>( self, tcx: TyCtxt<'tcx>, body: &'mir Body<'tcx>, pass_name: Option<&'static str>, ) -> Results<'tcx, Self>
where Self: Sized, Self::Domain: DebugWithContext<Self>,

Finds the fixpoint for this dataflow problem. Read more
Source§

impl<'mir, 'tcx> ResultsVisitor<'mir, 'tcx, &'mir LocalAnalysis<'tcx, 'mir>> for PartialGraph<'tcx>

Source§

fn visit_after_early_terminator_effect( &mut self, results: &mut Results<'tcx, &'mir LocalAnalysis<'tcx, 'mir>>, state: &InstructionState<'tcx>, terminator: &'mir Terminator<'tcx>, location: Location, )

We handle terminators during graph construction generally in the before state, because we’re interested in what the dependencies of our read places are before the modification pass overwrites the read places from any mutable arguments.

There is one exception which is that non-inlined function calls are handled in two steps. Before the primary effects we generate edges from the dependencies to the input arguments. After the primary effect we insert edges from each argument to each modified location. It is cleaner to do this afterwards, because the logic that resolves a place to a graph node assumes that you are reading all of your inputs from the “last_modification”. In the “before” state that map contains the “original” dependencies of each argument, e.g. we haven’t combined them with the reachable places yet. So this ordering means we can reuse the same logic but just have to run it twice for every non-inlined function call site.

Source§

fn visit_after_early_statement_effect( &mut self, results: &mut Results<'tcx, &'mir LocalAnalysis<'tcx, 'mir>>, state: &InstructionState<'tcx>, statement: &'mir Statement<'tcx>, location: Location, )

// njn: grep for “before”, “primary”, etc. Called after the “early” effect of the given statement is applied to state.
Source§

fn visit_after_primary_terminator_effect( &mut self, results: &mut Results<'tcx, &'mir LocalAnalysis<'tcx, 'mir>>, state: &InstructionState<'tcx>, terminator: &'mir Terminator<'tcx>, location: Location, )

Called after the “primary” effect of the given terminator is applied to state. Read more
§

fn visit_block_start(&mut self, _state: &<A as Analysis<'tcx>>::Domain)

§

fn visit_after_primary_statement_effect( &mut self, _results: &mut Results<'tcx, A>, _state: &<A as Analysis<'tcx>>::Domain, _statement: &'mir Statement<'tcx>, _location: Location, )

Called after the “primary” effect of the given statement is applied to state.
§

fn visit_block_end(&mut self, _state: &<A as Analysis<'tcx>>::Domain)

Auto Trait Implementations§

§

impl<'tcx, 'a> !Freeze for LocalAnalysis<'tcx, 'a>

§

impl<'tcx, 'a> !RefUnwindSafe for LocalAnalysis<'tcx, 'a>

§

impl<'tcx, 'a> !Send for LocalAnalysis<'tcx, 'a>

§

impl<'tcx, 'a> !Sync for LocalAnalysis<'tcx, 'a>

§

impl<'tcx, 'a> Unpin for LocalAnalysis<'tcx, 'a>

§

impl<'tcx, 'a> !UnwindSafe for LocalAnalysis<'tcx, 'a>

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> Captures<'_> for T
where T: ?Sized,