@@ -780,6 +780,178 @@ _lexical_ in order to specify this property for all contributing lifetimes.
780
780
For details see [ Variable Lifetimes] ( Ownership.md#variable-lifetimes ) in the
781
781
Ownership document.
782
782
783
+ # Dominance
784
+
785
+ ## Value and instruction 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
+ - An instruction result ` R ` dominates an instruction ` I ` if the
796
+ instruction that defines ` R ` dominates ` I ` .
797
+
798
+ - An argument of a basic block ` B ` dominates an instruction ` I ` if all
799
+ initial paths passing through ` I ` must also pass through the start
800
+ of ` B ` .
801
+
802
+ An instruction ` D ` dominates another instruction ` I ` if they are
803
+ different instructions and all initial paths passing through ` I `
804
+ must also pass through ` D ` .
805
+
806
+ See [ below] ( #definition-of-a-path ) for the formal definition of an
807
+ initial path.
808
+
809
+ ## Basic block dominance
810
+
811
+ A basic block ` B1 ` dominates a basic block ` B2 ` if they are different
812
+ blocks and if all initial paths passing through the start of ` B2 ` must
813
+ also pass through through the start of ` B1 ` .
814
+
815
+ This relationship between blocks can be thought of as creating a
816
+ directed acyclic graph of basic blocks, called the * dominance tree* .
817
+ The dominance tree is not directly represented in SIL; it is just
818
+ an emergent property of the dominance requirement on SIL functions.
819
+
820
+ ## Joint post-dominance
821
+
822
+ Certain instructions are required to have a * joint post-dominance*
823
+ relationship with certain other instructions. Informally, this means
824
+ that all terminating paths through the first instruction must
825
+ eventually pass through one of the others. This is common for
826
+ instructions that define a scope in the SIL function, such as
827
+ ` alloc_stack ` and ` begin_access ` .
828
+
829
+ The dominating instruction is called the * scope instruction* ,
830
+ and the post-dominating instructions are called the * scope-ending
831
+ instructions* . The specific joint post-dominance requirement
832
+ defines the set of instructions that count as scope-ending
833
+ instructions for the begin instruction.
834
+
835
+ For example, an ` alloc_stack ` instruction must be jointly
836
+ post-dominated by the set of ` dealloc_stack ` instructions
837
+ whose operand is the result of the ` alloc_stack ` . The
838
+ ` alloc_stack ` is the scope instruction, and the ` dealloc_stack ` s
839
+ are the scope-ending instructions.
840
+
841
+ The * scope* of a joint post-dominance relationship is the set
842
+ of all points in the function following the scope instruction
843
+ but prior to a scope-ending instruction. Making this precisely
844
+ defined is part of the point of the joint post-dominance rules.
845
+ A formal definition is given later.
846
+
847
+ In SIL, if an instruction acts as a scope instruction, it always
848
+ has exactly one set of scope-ending instructions associated
849
+ with it, and so it forms exactly one scope. People will therefore
850
+ often talk about, e.g., the scope of an ` alloc_stack ` , meaning
851
+ the scope between it and its ` dealloc_stack ` s. Furthermore,
852
+ there are no instructions in SIL which act as scope-ending
853
+ instructions for multiple scopes.
854
+
855
+ A scope instruction ` I ` is jointly post-dominated by its
856
+ scope-ending instructions if:
857
+
858
+ - All initial paths that pass through a scope-ending instruction
859
+ of ` I ` must also pass through ` I ` . (This is just the normal
860
+ dominance rule, and it is typically already required by the
861
+ definition of the joint post-dominance relationship. For example,
862
+ a ` dealloc_stack ` must be dominated by its associated
863
+ ` alloc_stack ` because it uses its result as an operand.)
864
+
865
+ - All initial paths that pass through ` I ` twice must also pass
866
+ through a scope-ending instruction of ` I ` in between.
867
+
868
+ - All initial paths that pass through a scope-ending instruction
869
+ of ` I ` twice must also pass through ` I ` in between.
870
+
871
+ - All terminating initial paths that pass through ` I ` must also
872
+ pass through a scope-ending instruction of ` I ` .
873
+
874
+ In other words, all paths must strictly alternate between ` I `
875
+ and its scope-ending instructions, starting with ` I ` and (if
876
+ the path exits) ending with a scope-ending instruction.
877
+
878
+ Note that a scope-ending instruction does not need to appear on
879
+ a path following a scope instruction if the path doesn't exit
880
+ the function. In fact, a function needn't include any scope-ending
881
+ instructions for a particular scope instruction if all paths from
882
+ that point are non-terminating, such as by ending in ` unreachable `
883
+ or containing an infinite loop.
884
+
885
+ The scope defined by a joint post-dominance relationship for
886
+ a scope instruction ` I ` is the set of points in the function for
887
+ which there exists an initial path that visits that point and
888
+ which passes through ` I ` but which does not pass through a
889
+ scope-ending instruction of ` I ` under that relationship. Note
890
+ that the point before a scope-ending instruction is always within
891
+ the scope.
892
+
893
+ ## Definition of a path
894
+
895
+ A * point* in a SIL function is the moment before an instruction.
896
+ Every basic block has an entry point, which is the point before
897
+ its first instruction. The entry point of the entry block is also
898
+ called the entry point of the function.
899
+
900
+ A path through a SIL function is a path (in the usual graph-theory
901
+ sense) in the underlying directed graph of points, in which:
902
+
903
+ - every point in the SIL function is a vertex in the graph,
904
+
905
+ - each non-terminator instruction creates an edge from the point
906
+ before it to the point after it, and
907
+
908
+ - each terminator instruction creates edges from the point before
909
+ the terminator to the initial point of each its successor blocks.
910
+
911
+ A path is said to pass through an instruction if it includes
912
+ any of the edges created by that instruction. A path is said to
913
+ pass through the start of a basic block if it visits the entry
914
+ point of that block.
915
+
916
+ An * initial path* is a path which begins at the entry point of the
917
+ function. A * terminating path* is a path which ends at the point
918
+ before an exiting instruction, such as ` return ` or ` throw ` .
919
+
920
+ Note that the dominance rules generally require only an initial path,
921
+ not a terminating path. A path that simply stops in the middle of a
922
+ block still counts for dominance. Among other things, this ensures that
923
+ dominance holds in blocks that are part of an infinite loop.
924
+
925
+ Note also that paths consider successors without regard to the
926
+ nature of the terminator. Paths that are provably impossible because
927
+ of value relationships still count for dominance. For example,
928
+ consider the following function:
929
+
930
+ ```
931
+ bb0(%cond : $Builtin.Int1):
932
+ cond_br %cond, bb1, b22
933
+ bb1:
934
+ %value = integer_literal $Builtin.Int32, 0
935
+ br bb3
936
+ bb2:
937
+ br bb3
938
+ bb3:
939
+ cond_br %cond, bb4, bb5
940
+ bb4:
941
+ %twice_value = builtin "add_Int32"(%value, %value) : $Builtin.Int32
942
+ br bb6
943
+ bb5:
944
+ br bb6
945
+ bb6:
946
+ ret %cond
947
+ ```
948
+
949
+ Dynamically, it is impossible to reach the ` builtin ` instruction
950
+ without passing through the definition of ` %value ` : to reach
951
+ the ` builtin ` , ` %cond ` must be ` true ` , and so the first ` cond_br `
952
+ must have branched to ` bb1 ` . This is not taken into consideration
953
+ by dominance, and so this function is ill-formed.
954
+
783
955
# Debug Information
784
956
785
957
Each instruction may have a debug location and a SIL scope reference at
@@ -1364,48 +1536,39 @@ stack deallocation instructions. It can even be paired with no
1364
1536
instructions at all; by the rules below, this can only happen in
1365
1537
non-terminating functions.
1366
1538
1367
- - At any point in a SIL function, there is an ordered list of stack
1368
- allocation instructions called the * active allocations list * .
1539
+ - All stack allocation instructions must be jointly post-dominated
1540
+ by stack deallocation instructions paired with them .
1369
1541
1370
- - The active allocations list is defined to be empty at the initial
1371
- point of the entry block of the function.
1542
+ - No path through the function that passes through a stack allocation
1543
+ instruction ` B ` , having already passed a stack allocation
1544
+ instruction ` A ` , may subsequently pass through a stack deallocation
1545
+ instruction paired with ` A ` without first passing through a stack
1546
+ deallocation instruction paired with ` B ` .
1372
1547
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.
1548
+ These two rules statically enforce that all stack allocations are
1549
+ properly nested. In simpler terms:
1378
1550
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 .
1551
+ - At every point in a SIL function, there is an ordered list of stack
1552
+ allocation instructions called the * active allocations list * .
1381
1553
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.
1554
+ - The active allocations list is empty at the start of the entry block
1555
+ of the function, and it must be empty again whenever an instruction
1556
+ that exits the function is reached, like ` return ` or ` throw ` .
1386
1557
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.
1558
+ - Whenever a stack allocation instruction is reached, it is added to
1559
+ the end of the list.
1393
1560
1394
- In other words, all stack allocations must be deallocated in
1395
- last-in, first-out order, aka stack order.
1561
+ - Whenever a stack deallocation instruction is reached, its paired
1562
+ stack allocation instruction must be at the end of the list, which it
1563
+ is then removed from.
1396
1564
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.
1565
+ - The active allocations list always be the same on both sides of a
1566
+ control flow edge. This implies both that all successors of a block
1567
+ must start with the same list and that all predecessors of a block
1568
+ must end with the same list.
1400
1569
1401
- - The active allocations list is required to be empty prior to
1402
- ` return ` or ` throw ` instructions.
1403
-
1404
- In other words, all stack allocations must be deallocated prior to
1405
- exiting the function.
1406
-
1407
- Note that these rules implicitly prevent an allocation instruction from
1408
- still being active when it is reached.
1570
+ Note that these rules implicitly prevent stack allocations from leaking
1571
+ or being double-freed.
1409
1572
1410
1573
The control-flow rule forbids certain patterns that would theoretically
1411
1574
be useful, such as conditionally performing an allocation around an
@@ -1414,6 +1577,13 @@ to use, however, as it is illegal to locally abstract over addresses,
1414
1577
and therefore a conditional allocation cannot be used in the
1415
1578
intermediate operation anyway.
1416
1579
1580
+ There is currently an exception to the stack discipline rules which
1581
+ allows the predecessors of a dead-end block (a block from which no
1582
+ exit is reachable) to disagree about the state of the stack.
1583
+ The current exception is unsound and permits manipulation of the
1584
+ stack in ways that may not be valid in all predecessor states. We
1585
+ are exploring ways to improve this situation.
1586
+
1417
1587
# Structural type matching for pack indices
1418
1588
1419
1589
In order to catch type errors in applying pack indices, SIL requires the
0 commit comments