Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 6079cbe

Browse files
committed
AccessBase documentation
Split the SIL function convention and memory access documentation into separate documents. Reference them from SIL.rst.
1 parent 19cff2e commit 6079cbe

5 files changed

Lines changed: 634 additions & 632 deletions

File tree

docs/README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,8 @@ documentation, please create a thread on the Swift forums under the
123123
Describes how to maintain compatibility when changing the serialization
124124
format.
125125
- SIL and SIL Optimizations:
126+
- [SILFunctionConventions.md](/docs/SILFunctionConventions.md):
127+
- [SILMemoryAccess.md](/docs/SILMemoryAccess.md):
126128
- [SILProgrammersManual.md](/docs/SILProgrammersManual.md):
127129
Provides an overview of the implementation of SIL in the compiler.
128130
- [OptimizerDesign.md](/docs/OptimizerDesign.md):

docs/SIL.rst

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,11 @@ In contrast to LLVM IR, SIL is a generally target-independent format
2929
representation that can be used for code distribution, but it can also express
3030
target-specific concepts as well as LLVM can.
3131

32-
For more information on developing the implementation of SIL and SIL passes, see
33-
`SILProgrammersManual.md <SILProgrammersManual.md>`_.
32+
For more information on developing the implementation of SIL and SIL passes, see:
33+
34+
- `SILProgrammersManual.md <SILProgrammersManual.md>`_.
35+
- `SILFunctionConventions.md <SILFunctionConventions.md>`_.
36+
- `SILMemoryAccess.md <SILMemoryAccess.md>`_.
3437

3538
SIL in the Swift Compiler
3639
-------------------------

docs/SILFunctionConventions.md

Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
# SIL Function Conventions
2+
3+
Throughout the compiler, integer indices are used to identify argument
4+
positions in several different contexts:
5+
6+
- A `SILFunctionType` has a tuple of parameters.
7+
8+
- The SIL function definition has a list of `SILFunctionArgument`.
9+
This is the callee-side argument list. It includes indirect results.
10+
11+
- `apply`, `try_apply`, and `begin_apply` have "applied arguments":
12+
the subset of instruction operands representing the callee's
13+
`SILFunctionArgument` list.
14+
15+
- `partial_apply` has "applied arguments": the subset of instruction
16+
operands representing closure captures. Closure captures in turn map
17+
to a subset of the callee's `SILFunctionArgument` list.
18+
19+
- In the above three contexts, `SILFunctionArgument`, `apply`, and
20+
`partial_apply`, the argument indices also depend on the SIL stage:
21+
Canonical vs. Lowered.
22+
23+
Consider the example:
24+
25+
```swift
26+
func example<T>(i: Int, t: T) -> (Int, T) {
27+
let foo = { return ($0, t) }
28+
return foo(i)
29+
}
30+
```
31+
32+
The closure `foo` has the indices as numbered below in each
33+
context, ignoring the calling convention and boxing/unboxing of
34+
captures for brevity:
35+
36+
The closure's `SILFunctionType` has two direct formal parameters at
37+
indices (`#0`, `#1`) and one direct formal result of tuple type:
38+
39+
```
40+
SILFunctionType(foo): (#0: Int, #1: T) -> @out (Int, T)
41+
```
42+
43+
Canonical SIL with opaque values matches `SILFunctionType`. The
44+
definition of `foo` has two direct `SILFunctionArgument`s at (`#0`,
45+
`#1`):
46+
47+
```
48+
SILFunctionArguments: (#0: Int, #1: T) -> (Int, T)
49+
```
50+
51+
The Lowered SIL for `foo`s definition has an indirect "result
52+
argument" at index #0. The function parameter indices are now (`#1`,
53+
`#2`):
54+
55+
```
56+
SILFunctionArguments: (#0: *T, #1: Int, #2: T) -> Int
57+
```
58+
59+
Creation of the closure has one applied argument at index `#0`. Note
60+
that the first applied argument is actually the second operand (the
61+
first is the callee), and in lowered SIL, it is actually the third
62+
SILFunctionArgument (after the indirect result and first parameter):
63+
64+
```
65+
%closure = partial_apply @foo(#0: t)
66+
```
67+
68+
Application of the closure with opaque values has one applied
69+
argument:
70+
71+
```
72+
%resultTuple = apply %closure(#0: i)
73+
```
74+
75+
Lowered application of the closure has two applied arguments:
76+
77+
```
78+
%directResult = apply %closure(#0: %indirectResult: *T, #1: i)
79+
```
80+
81+
The mapping between `SILFunctionType` and `SILFunctionArgument`, which depends
82+
on the SIL stage, is managed by the
83+
[SILFunctionConventions](https://github.com/apple/swift/blob/main/include/swift/SIL/SILFunctionConventions.h)
84+
abstraction. This API follows naming conventions to communicate the meaning of the integer indices:
85+
86+
- "Parameters" refer to the function signature's tuple of arguments.
87+
88+
- "SILArguments" refer to the set of `SILFunctionArgument` in the callee's entry block, including any indirect results required by the current SIL stage.
89+
90+
These argument indices and their relative offsets should never be
91+
hardcoded. Although this is common practice in LLVM, it should be
92+
avoided in SIL: (a) the structure of SIL instructions, particularly
93+
applies, is much more nuanced than LLVM IR, (b) assumptions that may
94+
be valid at the initial point of use are often copied into parts of
95+
the code where they are no longer valid; and (c) unlike LLVM IR, SIL
96+
is not stable and will continue evolving.
97+
98+
Translation between SILArgument and parameter indices should use:
99+
`SILFunctionConventions::getSILArgIndexOfFirstParam()`.
100+
101+
Translation between SILArgument and result indices should use:
102+
`SILFunctionConventions::getSILArgIndexOfFirstIndirectResult()`.
103+
104+
Convenience methods exist for the most common uses, so there is
105+
typically no need to use the above "IndexOfFirst" methods to translate
106+
one integer index into another. The naming convention of the
107+
convenience method should clearly indicate which form of index it
108+
expects. For example, information about a parameter's type can be retrieved directly from a SILArgument index: `getParamInfoForSILArg(index)`, `getSILArgumentConvention(index)`, and `getSILArgumentType(index)`.
109+
110+
Another abstraction,
111+
[`ApplySite`](https://github.com/search?utf8=✓&q=%22class+ApplySite%22+repo%3Aapple%2Fswift+path%3Ainclude%2Fswift%2FSIL&type=Code&ref=advsearch&l=&l=),
112+
abstracts over the various kinds of `apply` instructions, including
113+
`try_apply`, `begin_apply`, and `partial_apply`.
114+
115+
`ApplySite::getSubstCalleeConv()` is commonly used to query the
116+
callee's `SILFunctionConventions` which provides information about the
117+
function's type and its definition as explained above. Information about the applied arguments can be queried directly from the `ApplySite` API.
118+
119+
For example, `ApplySite::getAppliedArgumentConvention(index)` takes an
120+
applied argument index, while
121+
`SILFunctionArguments::getSILArgumentConvention(index`) takes a
122+
`SILFunctionArgument` index. They both return the same information,
123+
but from a different viewpoint.
124+
125+
A common mistake is to directly map the ApplySite's caller-side
126+
arguments onto callee-side SILFunctionArguments. This happens to work
127+
until the same code is exposed to a `partial_apply`. Instead, use the `ApplySite` API for applied argument indices, or use
128+
`ApplySite::getCalleeArgIndexOfFirstAppliedArg()` to translate the
129+
apply's arguments into function convention arguments.
130+
131+
Consistent use of common idioms for accessing arguments should be
132+
adopted throughout the compiler. Plenty of bugs have resulted from
133+
assumptions about the form of SIL made in one area of the compiler
134+
that have been copied into other parts of the compiler. For example,
135+
knowing that a block of code is guarded by a dynamic condition that
136+
rules out PartialApplies is no excuse to conflate applied arguments
137+
with function arguments. Also, without consistent use of common
138+
idioms, it becomes overly burdensome to evolve these APIs over time.
139+

0 commit comments

Comments
 (0)