Analysing Statements
The PCG Analysis computes four states for each MIR statement, corresponding to the PCG evaluation phases:
PreOperandsPostOperandsPreMainPostMain
The analysis for each statement proceeds in two steps:
- Step 1: Place Conditions are computed for each statement phase
- Step 2: PCG Actions are performed for each statement phase
Determining Place Conditions
A place condition is a predicate on the PCG related to a particular MIR place.
We define the following place conditions:
Capability: Place must have capabilityRemoveCapability: Capability for place should be removed1AllocateOrDeallocate: Storage for local is allocated (e.g. via theStorageLiveinstruction)Unalloc: Storage for local is not allocated (e.g. via theStorageDeadinstruction)ExpandTwoPhase: Place is the borrowed place of a two-phase borrowReturn: TheRETURNplace has Exclusive capability
ExpandTwoPhase may not be necessary. AllocateOrDeallocate is a confusing
name, also it's not clear if it's any different than just having Write
permission.
During this step of the analysis, place conditions are computed for each phase. The determination of place conditions is based on the MIR statement; the state of the PCG is not relevant.
The conditions computed for each phase are as follows:
PreOperands: Pre-conditions on the PCG for the operands in the statement to be evaluatedPostOperands: Post-conditions on the PCG after the operands in the statement has been evaluatedPreMain: Pre-conditions on the PCG for the main effect of the statement to be appliedPostMain: Post-conditions on the PCG after the main effect of the statement has been applied
As an example, the MIR statement: let y = move x would have the following
place conditions:
PreOperands:{x: E}PostOperands:{x: W}PreMain:{y: W}PostMain:{y: E}
The rules describing how these place conditions are generated for a statement are described here.
Performing PCG Actions
After the place conditions for each phase are computed, the analyses proceeds by performing the actions for each phase. At a high-level, this proceeds as follows:
PreOperands
- The Borrow PCG graph is minimized by repeatedly removing every effective
leaf edge2 for which their target PCG nodes of are not live
at the current MIR location. A Borrow PCG
RemoveEdgeaction is generated for each removed edge. See more details here.
TODO: Precisely define liveness.
- The place capabilities required by the
PreOperandplace conditions are obtained.
PostOperands
No actions occur at this stage. Capabilities for every moved-out operand are set to Write.
PreMain
The place capabilities required by the PreMain place conditions are
obtained.
Then, the behaviour depends on the type of statement:
StorageDead(v)- The analysis performs the
MakePlaceOld(v, StorageDead)action.
- The analysis performs the
Assign(p r)- If
pis a reference-typed value and contained in the borrows graph and the capability forpisR:- The analysis performs the
RestoreCapability(p, E)action
- The analysis performs the
- If :
- The analysis performs the action
- All edges in the borrow PCG blocked by any of the lifetime projections in
pare removed
- If
PostMain
- For every operand
move pin the statement:- The analysis performs the
MakePlaceOld(p, MoveOut)action.
- The analysis performs the
- If the statement is a function call
p = call f(..):- Function call abstraction edges are inserted using the rules defined here
- If the statement takes the form
Assign(p, r):pis given exclusive permission- If takes the form
Aggregate(o_1, ..., o_n):- For every
- Let be the associated place of
- For all
- If outlives :
- Add an
AggregateBorrowFlow edge , with associated field index and lifetime projection index .
- Add an
- If outlives :
- For every
- If takes the form
use c,cis a reference-typed constant with lifetime , and is a reference-typed place with lifetime , then:- Create a new
ConstRefborrowedge of the form
- Create a new
- If takes the form
move p_forcast(_, move p_f):- For all :
- Let be the i'th lifetime projection in
p - Let be the i'th lifetime projection in
p_f - Let be the snapshot location
- Add a
Moveedge
- Let be the i'th lifetime projection in
- For all :
- If takes the form
copy p_forcast(_, copy p_f):- For all :
- Let be the i'th lifetime projection in
p - Let be the i'th lifetime projection in
p_f - Add a
CopyRefedge
- Let be the i'th lifetime projection in
- For all :
- If takes the form
&por&mut p:- Handle the borrow as described here