Analysing Statements
The PCG Analysis computes four states for each MIR statement, corresponding to the PCG evaluation phases:
PreOperands
PostOperands
PreMain
PostMain
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 theStorageLive
instruction)Unalloc
: Storage for local is not allocated (e.g. via theStorageDead
instruction)ExpandTwoPhase
: Place is the borrowed place of a two-phase borrowReturn
: TheRETURN
place 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
RemoveEdge
action is generated for each removed edge. See more details here.
TODO: Precisely define liveness.
- The place capabilities required by the
PreOperand
place 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
p
is a reference-typed value and contained in the borrows graph and the capability forp
isR
:- 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
p
are removed
- If
PostMain
- For every operand
move p
in the statement:- The analysis performs the
MakePlaceOld(p, MoveOut)
action.
- The analysis performs the
- If the statement is a function call
p = call f(..)
:- The entry for
p
in the latest map is updated to the current location - Function call abstraction edges are described using the rules defined here
- The entry for
- If the statement takes the form
Assign(p, r)
:- The entry for
p
in the latest map is updated to the current location p
is 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
Aggregate
BorrowFlow edge , with associated field index and lifetime projection index .
- Add an
- If outlives :
- For every
- If takes the form
use c
,c
is a reference-typed constant with lifetime , and is a reference-typed place with lifetime , then:- Create a new
ConstRef
borrowedge of the form
- Create a new
- If takes the form
move p_f
orcast(_, 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 location of
p_f
in the latest map - Add a
Move
edge
- Let be the i'th lifetime projection in
- For all :
- If takes the form
copy p_f
orcast(_, 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
CopyRef
edge
- Let be the i'th lifetime projection in
- For all :
- If takes the form
&p
or&mut p
:- Handle the borrow as described here
- The entry for