Skip to content

Commit e4dc996

Browse files
authored
Merge pull request #3569 from swiftwasm/main
2 parents 62ca8f3 + 22c2889 commit e4dc996

File tree

69 files changed

+2966
-2107
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

69 files changed

+2966
-2107
lines changed

benchmark/single-source/ArrayAppend.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ import TestsUtils
1616

1717
let t: [BenchmarkCategory] = [.validation, .api, .Array]
1818
public let benchmarks = [
19-
BenchmarkInfo(name: "ArrayAppend", runFunction: run_ArrayAppend, tags: t, legacyFactor: 10),
19+
BenchmarkInfo(name: "ArrayAppend", runFunction: run_ArrayAppend, tags: t + [.unstable], legacyFactor: 10),
2020
BenchmarkInfo(name: "ArrayAppendArrayOfInt", runFunction: run_ArrayAppendArrayOfInt, tags: t,
2121
setUpFunction: ones, tearDownFunction: releaseOnes, legacyFactor: 10),
2222
BenchmarkInfo(name: "ArrayAppendAscii", runFunction: run_ArrayAppendAscii, tags: t, legacyFactor: 34),

benchmark/single-source/DataBenchmarks.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -262,7 +262,7 @@ public let benchmarks = [
262262
runFunction: { append($0*50, data: large, to: medium) }, tags: d,
263263
legacyFactor: 200),
264264
BenchmarkInfo(name: "DataAppendDataLargeToLarge",
265-
runFunction: { append($0*50, data: large, to: large) }, tags: d,
265+
runFunction: { append($0*50, data: large, to: large) }, tags: d + [.unstable],
266266
legacyFactor: 200),
267267

268268
BenchmarkInfo(name: "DataToStringEmpty",

benchmark/single-source/Memset.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ public let benchmarks =
1616
BenchmarkInfo(
1717
name: "Memset",
1818
runFunction: run_Memset,
19-
tags: [.validation])
19+
tags: [.validation, .unstable])
2020

2121
@inline(never)
2222
func memset(_ a: inout [Int], _ c: Int) {

benchmark/single-source/SubstringTest.swift

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ public let benchmarks = [
2727
setUpFunction: { blackHole(_comparison) }),
2828
BenchmarkInfo(name: "SubstringEqualString", runFunction: run_SubstringEqualString, tags: [.validation, .api, .String]),
2929
BenchmarkInfo(name: "SubstringEquatable", runFunction: run_SubstringEquatable, tags: [.validation, .api, .String]),
30-
BenchmarkInfo(name: "SubstringFromLongString", runFunction: run_SubstringFromLongString, tags: [.validation, .api, .String]),
30+
BenchmarkInfo(name: "SubstringFromLongString2", runFunction: run_SubstringFromLongString, tags: [.validation, .api, .String]),
3131
BenchmarkInfo(name: "SubstringFromLongStringGeneric", runFunction: run_SubstringFromLongStringGeneric, tags: [.validation, .api, .String]),
3232
BenchmarkInfo(name: "SubstringTrimmingASCIIWhitespace", runFunction: run_SubstringTrimmingASCIIWhitespace, tags: [.validation, .api, .String]),
3333
]
@@ -43,7 +43,7 @@ let quiteLong = String(repeating: "0", count: 10_000)[...]
4343
public func run_SubstringFromLongString(_ n: Int) {
4444
var s = longWide
4545
s += "!" // ensure the string has a real buffer
46-
for _ in 1...n*500 {
46+
for _ in 1...n*5000 {
4747
blackHole(Substring(s))
4848
}
4949
}
@@ -292,7 +292,6 @@ let _trimmableSubstrings = "pineapple,🍍, pineapple\t,\r\n\r\n\r\n, 🍍 ,".s
292292
@inline(never)
293293
public func run_SubstringTrimmingASCIIWhitespace(_ n: Int) {
294294
let substrings = _trimmableSubstrings // bringing this alias from above
295-
var count = 0
296295
for _ in 1...n*100 {
297296
for substring in substrings {
298297
blackHole(substring.trimWhitespace())

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)