Skip to content

Commit cd56cf3

Browse files
Merge pull request #4883 from swiftwasm/main
[pull] swiftwasm from main
2 parents 9d9ca35 + 6ed6290 commit cd56cf3

File tree

127 files changed

+6277
-785
lines changed

Some content is hidden

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

127 files changed

+6277
-785
lines changed

SwiftCompilerSources/Sources/SIL/Effects.swift

Lines changed: 79 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -16,22 +16,22 @@ public struct ArgumentEffect : CustomStringConvertible, CustomReflectable {
1616
public typealias Path = SmallProjectionPath
1717

1818
public enum Kind {
19-
/// The selected argument value does not escape.
19+
/// The argument value does not escape.
2020
///
2121
/// Syntax examples:
22-
/// !%0 // argument 0 does not escape
23-
/// !%0.** // argument 0 and all transitively contained values do not escape
22+
/// [%0: noescape] // argument 0 does not escape
23+
/// [%0: noescape **] // argument 0 and all transitively contained values do not escape
2424
///
2525
case notEscaping
2626

27-
/// The selected argument value escapes to the specified selection (= first payload).
27+
/// The argument value escapes to the function return value.
2828
///
2929
/// Syntax examples:
30-
/// %0.s1 => %r // field 2 of argument 0 exclusively escapes via return.
31-
/// %0.s1 -> %1 // field 2 of argument 0 - and other values - escape to argument 1.
30+
/// [%0: escape s1 => %r] // field 2 of argument 0 exclusively escapes via return.
31+
/// [%0: escape s1 -> %r] // field 2 of argument 0 - and other values - escape via return
3232
///
33-
/// The "exclusive" flag (= second payload) is true if only the selected argument escapes
34-
/// to the specified selection, but nothing else escapes to it.
33+
/// The "exclusive" flag (= second payload) is true if only the argument escapes,
34+
/// but nothing else escapes to the return value.
3535
/// For example, "exclusive" is true for the following function:
3636
///
3737
/// @_effect(escaping c => return)
@@ -46,6 +46,14 @@ public struct ArgumentEffect : CustomStringConvertible, CustomReflectable {
4646
///
4747
case escapingToReturn(Path, Bool) // toPath, exclusive
4848

49+
/// Like `escapingToReturn`, but the argument escapes to another argument.
50+
///
51+
/// Example: The argument effects of
52+
/// func argToArgEscape(_ r: inout Class, _ c: Class) { r = c }
53+
///
54+
/// would be
55+
/// [%1: escape => %0] // Argument 1 escapes to argument 0
56+
///
4957
case escapingToArgument(Int, Path, Bool) // toArgumentIndex, toPath, exclusive
5058
}
5159

@@ -111,21 +119,28 @@ public struct ArgumentEffect : CustomStringConvertible, CustomReflectable {
111119
return argumentIndex == rhsArgIdx && rhsPath.matches(pattern: pathPattern)
112120
}
113121

114-
public var description: String {
115-
let selectedArg = "%\(argumentIndex)" + (pathPattern.isEmpty ? "" : ".\(pathPattern)")
122+
public var headerDescription: String {
123+
"%\(argumentIndex)\(isDerived ? "" : "!"): "
124+
}
116125

126+
public var bodyDescription: String {
127+
let patternStr = pathPattern.isEmpty ? "" : " \(pathPattern)"
117128
switch kind {
118129
case .notEscaping:
119-
return "!\(selectedArg)"
130+
return "noescape\(patternStr)"
120131
case .escapingToReturn(let toPath, let exclusive):
121-
let pathStr = (toPath.isEmpty ? "" : ".\(toPath)")
122-
return "\(selectedArg) \(exclusive ? "=>" : "->") %r\(pathStr)"
132+
let toPathStr = (toPath.isEmpty ? "" : ".\(toPath)")
133+
return "escape\(patternStr) \(exclusive ? "=>" : "->") %r\(toPathStr)"
123134
case .escapingToArgument(let toArgIdx, let toPath, let exclusive):
124-
let pathStr = (toPath.isEmpty ? "" : ".\(toPath)")
125-
return "\(selectedArg) \(exclusive ? "=>" : "->") %\(toArgIdx)\(pathStr)"
135+
let toPathStr = (toPath.isEmpty ? "" : ".\(toPath)")
136+
return "escape\(patternStr) \(exclusive ? "=>" : "->") %\(toArgIdx)\(toPathStr)"
126137
}
127138
}
128139

140+
public var description: String {
141+
headerDescription + bodyDescription
142+
}
143+
129144
public var customMirror: Mirror { Mirror(self, children: []) }
130145
}
131146

@@ -164,8 +179,27 @@ public struct FunctionEffects : CustomStringConvertible, CustomReflectable {
164179
argumentEffects = argumentEffects.filter { !$0.isDerived }
165180
}
166181

182+
public var argumentEffectsDescription: String {
183+
var currentArgIdx = -1
184+
var currentIsDerived = false
185+
var result = ""
186+
for effect in argumentEffects {
187+
if effect.argumentIndex != currentArgIdx || effect.isDerived != currentIsDerived {
188+
if currentArgIdx >= 0 { result += "]\n" }
189+
result += "[\(effect.headerDescription)"
190+
currentArgIdx = effect.argumentIndex
191+
currentIsDerived = effect.isDerived
192+
} else {
193+
result += ", "
194+
}
195+
result += effect.bodyDescription
196+
}
197+
if currentArgIdx >= 0 { result += "]\n" }
198+
return result
199+
}
200+
167201
public var description: String {
168-
return "[" + argumentEffects.map { $0.description }.joined(separator: ", ") + "]"
202+
return argumentEffectsDescription
169203
}
170204

171205
public var customMirror: Mirror { Mirror(self, children: []) }
@@ -237,24 +271,37 @@ extension StringParser {
237271
return ArgumentEffect.Path()
238272
}
239273

240-
mutating func parseEffectFromSIL(for function: Function, isDerived: Bool) throws -> ArgumentEffect {
241-
if consume("!") {
242-
let argIdx = try parseArgumentIndexFromSIL()
243-
let path = try parsePathPatternFromSIL()
244-
return ArgumentEffect(.notEscaping, argumentIndex: argIdx, pathPattern: path, isDerived: isDerived)
274+
mutating func parseEffectsFromSIL(to effects: inout FunctionEffects) throws {
275+
let argumentIndex = try parseArgumentIndexFromSIL()
276+
let isDerived = !consume("!")
277+
if !consume(":") {
278+
try throwError("expected ':'")
245279
}
246-
let fromArgIdx = try parseArgumentIndexFromSIL()
247-
let fromPath = try parsePathPatternFromSIL()
248-
let exclusive = try parseEscapingArrow()
249-
if consume("%r") {
250-
let toPath = try parsePathPatternFromSIL()
251-
return ArgumentEffect(.escapingToReturn(toPath, exclusive),
252-
argumentIndex: fromArgIdx, pathPattern: fromPath, isDerived: isDerived)
280+
repeat {
281+
let effect = try parseEffectFromSIL(argumentIndex: argumentIndex, isDerived: isDerived)
282+
effects.argumentEffects.append(effect)
283+
} while consume(",")
284+
}
285+
286+
mutating func parseEffectFromSIL(argumentIndex: Int, isDerived: Bool) throws -> ArgumentEffect {
287+
if consume("noescape") {
288+
let path = try parseProjectionPathFromSIL()
289+
return ArgumentEffect(.notEscaping, argumentIndex: argumentIndex, pathPattern: path, isDerived: isDerived)
290+
}
291+
if consume("escape") {
292+
let fromPath = try parseProjectionPathFromSIL()
293+
let exclusive = try parseEscapingArrow()
294+
if consume("%r") {
295+
let toPath = consume(".") ? try parseProjectionPathFromSIL() : ArgumentEffect.Path()
296+
return ArgumentEffect(.escapingToReturn(toPath, exclusive),
297+
argumentIndex: argumentIndex, pathPattern: fromPath, isDerived: isDerived)
298+
}
299+
let toArgIdx = try parseArgumentIndexFromSIL()
300+
let toPath = consume(".") ? try parseProjectionPathFromSIL() : ArgumentEffect.Path()
301+
return ArgumentEffect(.escapingToArgument(toArgIdx, toPath, exclusive),
302+
argumentIndex: argumentIndex, pathPattern: fromPath, isDerived: isDerived)
253303
}
254-
let toArgIdx = try parseArgumentIndexFromSIL()
255-
let toPath = try parsePathPatternFromSIL()
256-
return ArgumentEffect(.escapingToArgument(toArgIdx, toPath, exclusive),
257-
argumentIndex: fromArgIdx, pathPattern: fromPath, isDerived: isDerived)
304+
try throwError("unknown effect")
258305
}
259306

260307
mutating func parseArgumentIndexFromSIL() throws -> Int {
@@ -267,13 +314,6 @@ extension StringParser {
267314
try throwError("expected parameter")
268315
}
269316

270-
mutating func parsePathPatternFromSIL() throws -> ArgumentEffect.Path {
271-
if consume(".") {
272-
return try parseProjectionPathFromSIL()
273-
}
274-
return ArgumentEffect.Path()
275-
}
276-
277317
private mutating func parseEscapingArrow() throws -> Bool {
278318
if consume("=>") { return true }
279319
if consume("->") { return false }

SwiftCompilerSources/Sources/SIL/Function.swift

Lines changed: 27 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -133,27 +133,36 @@ final public class Function : CustomStringConvertible, HasShortDescription, Hash
133133
},
134134
// writeFn
135135
{ (f: BridgedFunction, os: BridgedOStream, idx: Int) in
136-
let s = f.function.effects.argumentEffects[idx].description
136+
let s: String
137+
if idx >= 0 {
138+
s = f.function.effects.argumentEffects[idx].bodyDescription
139+
} else {
140+
s = f.function.effects.argumentEffectsDescription
141+
}
137142
s._withStringRef { OStream_write(os, $0) }
138143
},
139144
// parseFn:
140-
{ (f: BridgedFunction, str: llvm.StringRef, fromSIL: Int, isDerived: Int, paramNames: BridgedArrayRef) -> BridgedParsingError in
145+
{ (f: BridgedFunction, str: llvm.StringRef, fromSIL: Int, argumentIndex: Int, isDerived: Int, paramNames: BridgedArrayRef) -> BridgedParsingError in
141146
do {
142147
var parser = StringParser(str.string)
143-
let effect: ArgumentEffect
144-
if fromSIL != 0 {
145-
effect = try parser.parseEffectFromSIL(for: f.function, isDerived: isDerived != 0)
148+
149+
if fromSIL != 0 && argumentIndex < 0 {
150+
try parser.parseEffectsFromSIL(to: &f.function.effects)
146151
} else {
147-
let paramToIdx = paramNames.withElements(ofType: llvm.StringRef.self) {
148-
(buffer: UnsafeBufferPointer<llvm.StringRef>) -> Dictionary<String, Int> in
149-
let keyValPairs = buffer.enumerated().lazy.map { ($0.1.string, $0.0) }
150-
return Dictionary(uniqueKeysWithValues: keyValPairs)
152+
let effect: ArgumentEffect
153+
if fromSIL != 0 {
154+
effect = try parser.parseEffectFromSIL(argumentIndex: argumentIndex, isDerived: isDerived != 0)
155+
} else {
156+
let paramToIdx = paramNames.withElements(ofType: llvm.StringRef.self) {
157+
(buffer: UnsafeBufferPointer<llvm.StringRef>) -> Dictionary<String, Int> in
158+
let keyValPairs = buffer.enumerated().lazy.map { ($0.1.string, $0.0) }
159+
return Dictionary(uniqueKeysWithValues: keyValPairs)
160+
}
161+
effect = try parser.parseEffectFromSource(for: f.function, params: paramToIdx)
151162
}
152-
effect = try parser.parseEffectFromSource(for: f.function, params: paramToIdx)
163+
f.function.effects.argumentEffects.append(effect)
153164
}
154165
if !parser.isEmpty() { try parser.throwError("syntax error") }
155-
156-
f.function.effects.argumentEffects.append(effect)
157166
} catch let error as ParsingError {
158167
return BridgedParsingError(message: error.message.utf8Start, position: error.position)
159168
} catch {
@@ -179,20 +188,14 @@ final public class Function : CustomStringConvertible, HasShortDescription, Hash
179188
resultArgDelta: destResultArgs - srcResultArgs)
180189
return 1
181190
},
182-
// getEffectFlags
183-
{ (f: BridgedFunction, idx: Int) -> Int in
191+
// getEffectInfo
192+
{ (f: BridgedFunction, idx: Int) -> BridgedEffectInfo in
184193
let argEffects = f.function.effects.argumentEffects
185-
if idx >= argEffects.count { return 0 }
186-
let effect = argEffects[idx]
187-
var flags = 0
188-
switch effect.kind {
189-
case .notEscaping, .escapingToArgument, .escapingToReturn:
190-
flags |= Int(EffectsFlagEscape)
191-
}
192-
if effect.isDerived {
193-
flags |= Int(EffectsFlagDerived)
194+
if idx >= argEffects.count {
195+
return BridgedEffectInfo(argumentIndex: -1, isDerived: false)
194196
}
195-
return flags
197+
let effect = argEffects[idx]
198+
return BridgedEffectInfo(argumentIndex: effect.argumentIndex, isDerived: effect.isDerived)
196199
}
197200
)
198201
}

SwiftCompilerSources/Sources/SIL/SmallProjectionPath.swift

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -471,7 +471,7 @@ extension StringParser {
471471

472472
mutating func parseProjectionPathFromSIL() throws -> SmallProjectionPath {
473473
var entries: [(SmallProjectionPath.FieldKind, Int)] = []
474-
repeat {
474+
while true {
475475
if consume("**") {
476476
entries.append((.anything, 0))
477477
} else if consume("c*") {
@@ -497,12 +497,10 @@ extension StringParser {
497497
entries.append((.structField, idx))
498498
} else if let tupleElemIdx = consumeInt() {
499499
entries.append((.tupleField, tupleElemIdx))
500-
} else {
501-
try throwError("expected selection path component")
500+
} else if !consume(".") {
501+
return try createPath(from: entries)
502502
}
503-
} while consume(".")
504-
505-
return try createPath(from: entries)
503+
}
506504
}
507505

508506
private func createPath(from entries: [(SmallProjectionPath.FieldKind, Int)]) throws -> SmallProjectionPath {

docs/ReferenceGuides/UnderscoredAttributes.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,7 @@ that releases of the value may be hoisted without respect to deinit barriers.
159159

160160
When applied to a type, indicates that all values which are _statically_
161161
instances of that type are themselves `@_eagerMove` as above, unless overridden
162-
with `@_lexical`.
162+
with `@_noEagerMove`.
163163

164164
Aggregates all of whose fields are `@_eagerMove` or trivial are inferred to be
165165
`@_eagerMove`.
@@ -534,7 +534,7 @@ initializers from its superclass. This implies that all designated initializers
534534
overridden. This attribute is often printed alongside
535535
`@_hasMissingDesignatedInitializers` in this case.
536536

537-
## `@_lexical`
537+
## `@_noEagerMove`
538538

539539
When applied to a value, indicates that the value's lifetime is lexical, that
540540
releases of the value may not be hoisted over deinit barriers.
@@ -544,7 +544,7 @@ This is the default behavior, unless the value's type is annotated
544544
annotation.
545545

546546
When applied to a type, indicates that all values which are instances of that
547-
type are themselves `@_lexical` as above.
547+
type are themselves `@_noEagerMove` as above.
548548

549549
This is the default behavior, unless the type annotated is an aggregate that
550550
consists entirely of `@_eagerMove` or trivial values, in which case the

0 commit comments

Comments
 (0)