mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Update documentation.
This commit is contained in:
parent
c7bb117d50
commit
90a147d371
@ -62,28 +62,34 @@ struct Dialect;
|
||||
* Detailed rules:
|
||||
*
|
||||
* The AST is traversed twice: in an information gathering step and in the
|
||||
* actual removal step. During information gathering, we maintain a
|
||||
* mapping from assignment statements to the three states
|
||||
* "unused", "undecided" and "used".
|
||||
* When an assignment is visited, it is added to the mapping in the "undecided" state
|
||||
* (see remark about for loops below) and every other assignment to the same variable
|
||||
* that is still in the "undecided" state is changed to "unused".
|
||||
* When a variable is referenced, the state of any assignment to that variable still
|
||||
* in the "undecided" state is changed to "used".
|
||||
* At points where control flow splits, a copy
|
||||
* of the mapping is handed over to each branch. At points where control flow
|
||||
* joins, the two mappings coming from the two branches are combined in the following way:
|
||||
* Statements that are only in one mapping or have the same state are used unchanged.
|
||||
* Conflicting values are resolved in the following way:
|
||||
* "unused", "undecided" -> "undecided"
|
||||
* "unused", "used" -> "used"
|
||||
* "undecided, "used" -> "used".
|
||||
* actual removal step. During information gathering, assignment statements
|
||||
* can be marked as "potentially unused" or as "used".
|
||||
*
|
||||
* When an assignment is visited, it is stored in the "set of all stores" and
|
||||
* added to the branch-dependent "active" sets for the assigned variables. This active
|
||||
* set for a variable contains all statements where that variable was last assigned to, i.e.
|
||||
* where a read from that variable could read from.
|
||||
* Furthermore, all other active sets for the assigned variables are cleared.
|
||||
*
|
||||
* When a reference to a variable is visited, the active assignments to that variable
|
||||
* in the current branch are marked as "used". This mark is permanent.
|
||||
* Also, the active set for this variable in the current branch is cleared.
|
||||
*
|
||||
* At points where control-flow splits, we maintain a copy of the active set
|
||||
* (all other data structures are shared across branches).
|
||||
*
|
||||
* At control-flow joins, we combine the sets of active stores for each variable.
|
||||
*
|
||||
* In the example above, the active set right after the assignment "b := mload(a)" (but before
|
||||
* the control-flow join) is "b := mload(a)"; the assignment "b := 2" was removed.
|
||||
* After the control-flow join it will contain both "b := mload(a)" and "b := 2", coming from
|
||||
* the two branches.
|
||||
*
|
||||
* For for-loops, the condition, body and post-part are visited twice, taking
|
||||
* the joining control-flow at the condition into account.
|
||||
* In other words, we create three control flow paths: Zero runs of the loop,
|
||||
* one run and two runs and then combine them at the end.
|
||||
* Running at most twice is enough because there are only three different states.
|
||||
* Running at most twice is enough because this takes into account all possible control-flow connections.
|
||||
*
|
||||
* Since this algorithm has exponential runtime in the nesting depth of for loops,
|
||||
* a shortcut is taken at a certain nesting level: We only use the zero- and
|
||||
@ -95,12 +101,7 @@ struct Dialect;
|
||||
*
|
||||
* At ``leave`` statements, all return variables are set to "used".
|
||||
*
|
||||
* When a variable goes out of scope, all statements still in the "undecided"
|
||||
* state are changed to "unused", unless the variable is the return
|
||||
* parameter of a function - there, the state changes to "used".
|
||||
*
|
||||
* In the second traversal, all assignments that are in the "unused" state are removed.
|
||||
*
|
||||
* In the second traversal, all assignments that are not marked as "used" are removed.
|
||||
*
|
||||
* This step is usually run right after the SSA transform to complete
|
||||
* the generation of the pseudo-SSA.
|
||||
|
@ -38,8 +38,11 @@ struct Dialect;
|
||||
*
|
||||
* The class tracks the state of abstract "stores" (assignments or mstore/sstore
|
||||
* statements) across the control-flow. It is the job of the derived class to create
|
||||
* the stores and track references, but the base class adjusts their "used state" at
|
||||
* control-flow splits and joins.
|
||||
* the stores and track references, but the base class manages control-flow splits and joins.
|
||||
*
|
||||
* In general, active stores are those where it has not yet been determined if they are used
|
||||
* or not. Those are split and joined at control-flow forks. Once a store has been deemed
|
||||
* used, it is removed from the active set and marked as used and this will never change.
|
||||
*
|
||||
* Prerequisite: Disambiguator, ForLoopInitRewriter.
|
||||
*/
|
||||
|
Loading…
Reference in New Issue
Block a user