@@ -15,6 +15,45 @@ private import SsaInternals as Ssa
15
15
16
16
cached
17
17
private module Cached {
18
+ /**
19
+ * The IR dataflow graph consists of the following nodes:
20
+ * - `InstructionNode`, which represents an `Instruction` in the graph.
21
+ * - `OperandNode`, which represents an `Operand` in the graph.
22
+ * - `VariableNode`, which is used to model global variables.
23
+ * - Two kinds of `StoreNode`s:
24
+ * 1. `StoreNodeInstr`, which represents the value of an address computed by an `Instruction` that
25
+ * has been updated by a write operation.
26
+ * 2. `StoreNodeOperand`, which represents the value of an address in an `ArgumentOperand` after a
27
+ * function call that may have changed the value.
28
+ * - `ReadNode`, which represents the result of reading a field of an object.
29
+ * - `SsaPhiNode`, which represents phi nodes as computed by the shared SSA library.
30
+ *
31
+ * The following section describes how flow is generally transferred between these nodes:
32
+ * - Flow between `InstructionNode`s and `OperandNode`s follow the def-use information as computed by
33
+ * the IR. Because the IR compute must-alias information for memory operands, we only follow def-use
34
+ * flow for register operands.
35
+ * - Flow can enter a `StoreNode` in two ways (both done in `StoreNode.flowInto`):
36
+ * 1. Flow is transferred from a `StoreValueOperand` to a `StoreNodeInstr`. Flow will then proceed
37
+ * along the chain of addresses computed by `StoreNodeInstr.getInner` to identify field writes
38
+ * and call `storeStep` accordingly (i.e., for an expression like `a.b.c = x`, we visit `c`, then
39
+ * `b`, then `a`).
40
+ * 2. Flow is transfered from a `WriteSideEffectInstruction` to a `StoreNodeOperand` after flow
41
+ * returns to a caller. Flow will then proceed to the defining instruction of the operand (because
42
+ * the `StoreNodeInstr` computed by `StoreNodeOperand.getInner()` is the `StoreNode` containing
43
+ * the defining instruction), and then along the chain computed by `StoreNodeInstr.getInner` like
44
+ * above.
45
+ * In both cases, flow leaves a `StoreNode` once the entire chain has been traversed, and the shared
46
+ * SSA library is used to find the next use of the variable at the end of the chain.
47
+ * - Flow can enter a `ReadNode` through an `OperandNode` that represents an address of some variable.
48
+ * Flow will then proceed along the chain of addresses computed by `ReadNode.getOuter` (i.e., for an
49
+ * expression like `use(a.b.c)` we visit `a`, then `b`, then `c`) and call `readStep` accordingly.
50
+ * Once the entire chain has been traversed, flow is transferred to the load instruction that reads
51
+ * the final address of the chain.
52
+ * - Flow can enter a `SsaPhiNode` from an `InstructionNode`, a `StoreNode` or another `SsaPhiNode`
53
+ * (in `toPhiNode`), depending on which node provided the previous definition of the underlying
54
+ * variable. Flow leaves a `SsaPhiNode` (in `fromPhiNode`) by using the shared SSA library to
55
+ * determine the next use of the variable.
56
+ */
18
57
cached
19
58
newtype TIRDataFlowNode =
20
59
TInstructionNode ( Instruction i ) or
0 commit comments