Table of Contents

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

bool

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

bool

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;