Interface IDataFlowState<Self>
- Namespace
- ICSharpCode.Decompiler.FlowAnalysis
- Assembly
- ICSharpCode.Decompiler.dll
Interface for use with DataFlowVisitor.
A mutable container for the state tracked by the data flow analysis.
public interface IDataFlowState<Self> where Self : IDataFlowState<Self>
Type Parameters
Self
Remarks
States must form a join-semilattice: https://en.wikipedia.org/wiki/Semilattice
To handle try{} finally{}
properly, states should implement MeetWith()
as well,
and thus should form a lattice.
DataFlowVisitor
expects the state to behave like a mutable reference type.
It might still be a good idea to use a struct to implement it so that .NET uses static dispatch for
method calls on the type parameter, but that struct must consist only of a readonly
field
referencing some mutable object, to ensure the type parameter behaves as it if was a mutable reference type.
Properties
IsBottom
Gets whether this is the bottom state.
The bottom state represents that the data flow analysis has not yet found a code path from the entry point to this state's position. It thus contains no information, and is "less than" all other states.
bool IsBottom { get; }
Property Value
Examples
The simple state "bool isReachable
", would implement IsBottom
as:
return !this.isReachable;
Remarks
The bottom state is the bottom element in the semi-lattice.
Initially, all code blocks not yet visited by the analysis will be in the bottom state.
Unreachable code will always remain in the bottom state.
Some analyses may also use the bottom state for reachable code after it was processed by the analysis.
For example, in DefiniteAssignmentVisitor
the bottom states means
"either this code is unreachable, or all variables are definitely initialized".
Methods
Clone()
Creates a new object with a copy of the state.
Self Clone()
Returns
- Self
Examples
The simple state "bool isReachable
", would implement Clone
as:
return new MyState(this.isReachable);
Remarks
Mutating methods such as ReplaceWith
or JoinWith
modify the contents of a state object.
Cloning the object allows the analysis to track multiple independent states,
such as the
JoinWith(Self)
Join the incomingState into this state.
void JoinWith(Self incomingState)
Parameters
incomingState
Self
Examples
The simple state "bool isReachable
", would implement JoinWith
as:
this.isReachable |= incomingState.isReachable;
Remarks
Postcondition: old(this).LessThanOrEqual(this) && incomingState.LessThanOrEqual(this)
This method should set this
to the smallest state that is greater than (or equal to)
both input states.
JoinWith()
is used when multiple control flow paths are joined together.
For example, it is used to combine the thenState
with the elseState
at the end of a if-else construct.
LessThanOrEqual(Self)
Gets whether this state is "less than" (or equal to) another state. This is the partial order of the semi-lattice.
bool LessThanOrEqual(Self otherState)
Parameters
otherState
Self
Returns
Examples
The simplest possible non-trivial state, bool isReachable
, would implement LessThanOrEqual
as:
return (this.isReachable ? 1 : 0) <= (otherState.isReachable ? 1 : 0);
Which can be simpified to:
return !this.isReachable || otherState.isReachable;
Remarks
The exact meaning of this relation is up to the concrete implementation, but usually "less than" means "has less information than". A given position in the code starts at the "bottom state" (=no information) and then adds more information as the analysis progresses. After each change to the state, the old state must be less than the new state, so that the analysis does not run into an infinite loop. The partially ordered set must also have finite height (no infinite ascending chains s1 < s2 < ...), to ensure the analysis terminates.
ReplaceWith(Self)
Replace the contents of this state object with a copy of those in newContent
.
void ReplaceWith(Self newContent)
Parameters
newContent
Self
Examples
The simple state "bool isReachable
", would implement ReplaceWith
as:
this.isReachable = newContent.isReachable;
Remarks
x = x.Clone(); x.ReplaceWith(newContent);
is equivalent to
x = newContent.Clone();
ReplaceWith() is used to avoid allocating new state objects where possible.
ReplaceWithBottom()
Equivalent to this.ReplaceWith(bottomState)
, but may be implemented more efficiently.
void ReplaceWithBottom()
Examples
The simple state "bool isReachable
", would implement ReplaceWithBottom
as:
this.isReachable = false;
Remarks
Since the DataFlowVisitor
can only create states by cloning from the initial state,
this method is necessary for the DataFlowVisitor
to gain access to the bottom element in
the first place.
TriggerFinally(Self)
A special operation to merge the end-state of the finally-block with the end state of a branch leaving the try-block.
If either input state is unreachable, this call must result in an unreachable state.
void TriggerFinally(Self finallyState)
Parameters
finallyState
Self
Examples
The simple state "bool isReachable
", would implement TriggerFinally
as:
this.isReachable &= finallyState.isReachable;