Skip to content

Commit b29add2

Browse files
committed
Document SIL's dominance rules, which apparently we've never done.
1 parent 2710f20 commit b29add2

File tree

1 file changed

+126
-34
lines changed

1 file changed

+126
-34
lines changed

docs/SIL/SIL.md

Lines changed: 126 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -780,6 +780,107 @@ _lexical_ in order to specify this property for all contributing lifetimes.
780780
For details see [Variable Lifetimes](Ownership.md#variable-lifetimes) in the
781781
Ownership document.
782782

783+
# Dominance
784+
785+
## Value dominance
786+
787+
Whenever an instruction uses a [value](#values-and-operands) as an
788+
operand, the definition of the value must dominate the instruction.
789+
This is a common concept across all SSA-like representations. SIL
790+
uses a standard definition of dominance, modified slightly to account
791+
for SIL's use of basic block arguments rather than phi instructions:
792+
793+
- The value `undef` always dominates an instruction.
794+
795+
- A result of an instruction `R` dominates an instruction `I` if all paths
796+
to `I` from the start of the entry block must pass through `R`.
797+
798+
- An argument of a basic block `B` dominates an instruction `I` if all
799+
paths to `I` from the start of the entry block must pass through the
800+
start of `B`.
801+
802+
A basic block `B1` is said to dominate a basic block `B2` if they are
803+
different blocks and if all paths to the start of `B2` must pass
804+
through `B1`. This relationship can be thought of as creating a
805+
directed acyclic graph of basic blocks, called the *dominance tree*.
806+
The dominance tree is not directly represented in SIL; it is just
807+
a requirement that SIL functions must obey.
808+
809+
When enumerating the paths through a function, the dominance rules
810+
always consider all successors of a basic block to be reachable.
811+
For example, consider the following function:
812+
813+
```
814+
bb0(%cond : $Builtin.Int1):
815+
cond_br %cond, bb1, b22
816+
bb1:
817+
%value = integer_literal $Builtin.Int32, 0
818+
br bb3
819+
bb2:
820+
br bb3
821+
bb3:
822+
cond_br %cond, bb4, bb5
823+
bb4:
824+
%twice_value = builtin "add_Int32"(%value, %value) : $Builtin.Int32
825+
br bb6
826+
bb5:
827+
br bb6
828+
bb6:
829+
ret %cond
830+
```
831+
832+
The definition of `%value` in this function is not considered to
833+
dominate its use by the `builtin` instruction in `bb4` because
834+
there is a path to that instruction from the start of `bb0` that
835+
does not pass through the definition of `%value` in `bb1`. This
836+
is true even though that path would require `cond_br` to make
837+
opposite choices about the value of `%cond`, because dominance
838+
considers all successors to be reachable, regardless of the path
839+
taken to reach that point.
840+
841+
## Joint post-dominance
842+
843+
Certain instructions are required to have a *joint post-dominance*
844+
relationship with certain other instructions. The dominating
845+
instruction is called the *begin instruction*. Other instructions
846+
may have the property of being an *end instruction* for that
847+
instruction.
848+
849+
For example, an instruction `D` is an end instruction for
850+
an `alloc_stack` instruction `A` if `D` is a `dealloc_stack`
851+
instruction whose operand is the result of `A`.
852+
853+
End instructions are always dominated by their begin instructions,
854+
generally because a result of the begin instruction is required to
855+
be an operand of the end instruction in order for the relationship
856+
to hold at all.
857+
858+
A begin instruction `I` is jointly post-dominated by its end
859+
instructions if:
860+
861+
- No path through the function that passes through `I` may pass
862+
through `I` again without first passing through an end
863+
instruction of `I`.
864+
865+
- No path through the function that passes through `I` and an
866+
end instruction of `I` may pass through another end instruction
867+
of `I` without having first passed through `I` again.
868+
869+
- No path through the function that passes through `I` may reach
870+
an instruction that exits the function (such as `return`)
871+
without having passed through an end instruction of `I`.
872+
873+
That is, for every possible path through the function, consider
874+
the sequence of instances of `I` and its end instructions on that
875+
path. `I` and its end instructions must perfectly alternate, and
876+
if the path ends in an exit, the sequence must end in an end
877+
instruction.
878+
879+
Note that a begin instruction need not have any end instructions
880+
in the function if no paths through the begin instruction lead to
881+
an exit (for example, if they lead to `unreachable` or an infinite
882+
loop).
883+
783884
# Debug Information
784885

785886
Each instruction may have a debug location and a SIL scope reference at
@@ -1364,48 +1465,39 @@ stack deallocation instructions. It can even be paired with no
13641465
instructions at all; by the rules below, this can only happen in
13651466
non-terminating functions.
13661467

1367-
- At any point in a SIL function, there is an ordered list of stack
1368-
allocation instructions called the *active allocations list*.
1369-
1370-
- The active allocations list is defined to be empty at the initial
1371-
point of the entry block of the function.
1372-
1373-
- The active allocations list is required to be the same at the
1374-
initial point of any successor block as it is at the final point of
1375-
any predecessor block. Note that this also requires all
1376-
predecessors/successors of a given block to have the same
1377-
final/initial active allocations lists.
1468+
- All stack allocation instructions must be jointly post-dominated
1469+
by stack deallocation instructions paired with them.
13781470

1379-
In other words, the set of active stack allocations must be the same
1380-
at a given place in the function no matter how it was reached.
1471+
- No path through the function that passes through a stack allocation
1472+
instruction `B`, having already passed a stack allocation
1473+
instruction `A`, may subsequently pass through a stack deallocation
1474+
instruction paired with `A` without first passing through a stack
1475+
deallocation instruction paired with `B`.
13811476

1382-
- The active allocations list for the point following a stack
1383-
allocation instruction is defined to be the result of adding that
1384-
instruction to the end of the active allocations list for the point
1385-
preceding the instruction.
1477+
These two rules statically enforce that all stack allocations are
1478+
properly nested. In simpler terms:
13861479

1387-
- The active allocations list for the point following a stack
1388-
deallocation instruction is defined to be the result of removing the
1389-
instruction from the end of the active allocations list for the
1390-
point preceding the instruction. The active allocations list for the
1391-
preceding point is required to be non-empty, and the last
1392-
instruction in it must be paired with the deallocation instruction.
1480+
- At every point in a SIL function, there is an ordered list of stack
1481+
allocation instructions called the *active allocations list*.
13931482

1394-
In other words, all stack allocations must be deallocated in
1395-
last-in, first-out order, aka stack order.
1483+
- The active allocations list is empty at the start of the entry block
1484+
of the function, and it must be empty again whenever an instruction
1485+
that exits the function is reached, like `return` or `throw`.
13961486

1397-
- The active allocations list for the point following any other
1398-
instruction is defined to be the same as the active allocations list
1399-
for the point preceding the instruction.
1487+
- Whenever a stack allocation instruction is reached, it is added to
1488+
the end of the list.
14001489

1401-
- The active allocations list is required to be empty prior to
1402-
`return` or `throw` instructions.
1490+
- Whenever a stack deallocation instruction is reached, its paired
1491+
stack allocation instruction must be at the end of the list, which it
1492+
is then removed from.
14031493

1404-
In other words, all stack allocations must be deallocated prior to
1405-
exiting the function.
1494+
- The active allocations list always be the same on both sides of a
1495+
control flow edge. This implies both that all successors of a block
1496+
must start with the same list and that all predecessors of a block
1497+
must end with the same list.
14061498

1407-
Note that these rules implicitly prevent an allocation instruction from
1408-
still being active when it is reached.
1499+
Note that these rules implicitly prevent stack allocations from leaking
1500+
or being double-freed.
14091501

14101502
The control-flow rule forbids certain patterns that would theoretically
14111503
be useful, such as conditionally performing an allocation around an

0 commit comments

Comments
 (0)