Skip to content

Commit ff334d2

Browse files
Merge pull request #5308 from swiftwasm/katei/merge-main-2023-02-20
Merge main 2023-02-20
2 parents 5126044 + 16e10a3 commit ff334d2

File tree

396 files changed

+8836
-3443
lines changed

Some content is hidden

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

396 files changed

+8836
-3443
lines changed

CMakeLists.txt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -268,7 +268,9 @@ set(SWIFT_ANALYZE_CODE_COVERAGE FALSE CACHE STRING
268268
# SWIFT_VERSION is deliberately /not/ cached so that an existing build directory
269269
# can be reused when a new version of Swift comes out (assuming the user hasn't
270270
# manually set it as part of their own CMake configuration).
271-
set(SWIFT_VERSION "5.9")
271+
set(SWIFT_VERSION_MAJOR 5)
272+
set(SWIFT_VERSION_MINOR 9)
273+
set(SWIFT_VERSION "${SWIFT_VERSION_MAJOR}.${SWIFT_VERSION_MINOR}")
272274

273275
set(SWIFT_VENDOR "" CACHE STRING
274276
"The vendor name of the Swift compiler")

SwiftCompilerSources/CMakeLists.txt

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -176,20 +176,21 @@ function(add_swift_compiler_modules_library name)
176176
endforeach()
177177

178178
# Compile the module into an object file
179-
add_custom_command_target(dep_target OUTPUT ${module_obj_file}
179+
add_custom_command_target(dep_target
180+
COMMAND ${ALS_SWIFT_EXEC} "-c" "-o" ${module_obj_file}
181+
${sdk_option}
182+
"-target" ${target}
183+
"-module-name" ${module} "-emit-module"
184+
"-emit-module-path" "${build_dir}/${module}.swiftmodule"
185+
"-parse-as-library" ${sources}
186+
"-wmo" ${swift_compile_options}
187+
${c_include_paths_args}
188+
# Generated swift modules.
189+
"-I" "${build_dir}"
190+
OUTPUT ${module_obj_file}
180191
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
181192
DEPENDS ${sources} ${deps} ${ALS_DEPENDS}
182193
importedHeaderDependencies
183-
COMMAND ${ALS_SWIFT_EXEC} "-c" "-o" ${module_obj_file}
184-
${sdk_option}
185-
"-target" ${target}
186-
"-module-name" ${module} "-emit-module"
187-
"-emit-module-path" "${build_dir}/${module}.swiftmodule"
188-
"-parse-as-library" ${sources}
189-
"-wmo" ${swift_compile_options}
190-
${c_include_paths_args}
191-
# Generated swift modules.
192-
"-I" "${build_dir}"
193194
COMMENT "Building swift module ${module}")
194195

195196
set("${module}_dep_target" ${dep_target})

SwiftCompilerSources/Sources/Optimizer/FunctionPasses/ComputeEscapeEffects.swift

Lines changed: 103 additions & 103 deletions
Original file line numberDiff line numberDiff line change
@@ -85,61 +85,7 @@ func addArgEffects(_ arg: FunctionArgument, argPath ap: SmallProjectionPath,
8585
// containing one or more references.
8686
let argPath = arg.type.isClass ? ap : ap.push(.anyValueFields)
8787

88-
struct ArgEffectsVisitor : EscapeVisitorWithResult {
89-
enum EscapeDestination {
90-
case notSet
91-
case toReturn(SmallProjectionPath)
92-
case toArgument(Int, SmallProjectionPath) // argument index, path
93-
}
94-
var result = EscapeDestination.notSet
95-
96-
mutating func visitUse(operand: Operand, path: EscapePath) -> UseResult {
97-
if operand.instruction is ReturnInst {
98-
// The argument escapes to the function return
99-
if path.followStores {
100-
// The escaping path must not introduce a followStores.
101-
return .abort
102-
}
103-
switch result {
104-
case .notSet:
105-
result = .toReturn(path.projectionPath)
106-
case .toReturn(let oldPath):
107-
result = .toReturn(oldPath.merge(with: path.projectionPath))
108-
case .toArgument:
109-
return .abort
110-
}
111-
return .ignore
112-
}
113-
if isOperandOfRecursiveCall(operand) {
114-
return .ignore
115-
}
116-
return .continueWalk
117-
}
118-
119-
mutating func visitDef(def: Value, path: EscapePath) -> DefResult {
120-
guard let destArg = def as? FunctionArgument else {
121-
return .continueWalkUp
122-
}
123-
// The argument escapes to another argument (e.g. an out or inout argument)
124-
if path.followStores {
125-
// The escaping path must not introduce a followStores.
126-
return .abort
127-
}
128-
let argIdx = destArg.index
129-
switch result {
130-
case .notSet:
131-
result = .toArgument(argIdx, path.projectionPath)
132-
case .toArgument(let oldArgIdx, let oldPath) where oldArgIdx == argIdx:
133-
result = .toArgument(argIdx, oldPath.merge(with: path.projectionPath))
134-
default:
135-
return .abort
136-
}
137-
return .walkDown
138-
}
139-
}
140-
141-
guard let result = arg.at(argPath).visitByWalkingDown(using: ArgEffectsVisitor(),
142-
context) else {
88+
guard let result = arg.at(argPath).visitByWalkingDown(using: ArgEffectsVisitor(), context) else {
14389
return false
14490
}
14591

@@ -152,15 +98,17 @@ func addArgEffects(_ arg: FunctionArgument, argPath ap: SmallProjectionPath,
15298
switch result {
15399
case .notSet:
154100
effect = EscapeEffects.ArgumentEffect(.notEscaping, argumentIndex: arg.index, pathPattern: argPath)
101+
155102
case .toReturn(let toPath):
156-
let exclusive = isExclusiveEscapeToReturn(fromArgument: arg, fromPath: argPath,
157-
toPath: toPath, returnInst: returnInst, context)
158-
effect = EscapeEffects.ArgumentEffect(.escapingToReturn(toPath, exclusive),
103+
let visitor = IsExclusiveReturnEscapeVisitor(argument: arg, argumentPath: argPath, returnPath: toPath)
104+
let exclusive = visitor.isExclusiveEscape(returnInst: returnInst, context)
105+
effect = EscapeEffects.ArgumentEffect(.escapingToReturn(toPath: toPath, isExclusive: exclusive),
159106
argumentIndex: arg.index, pathPattern: argPath)
107+
160108
case .toArgument(let toArgIdx, let toPath):
161109
// Exclusive argument -> argument effects cannot appear because such an effect would
162110
// involve a store which is not permitted for exclusive escapes.
163-
effect = EscapeEffects.ArgumentEffect(.escapingToArgument(toArgIdx, toPath, /*exclusive*/ false),
111+
effect = EscapeEffects.ArgumentEffect(.escapingToArgument(toArgumentIndex: toArgIdx, toPath: toPath),
164112
argumentIndex: arg.index, pathPattern: argPath)
165113
}
166114
newEffects.append(effect)
@@ -176,8 +124,10 @@ private func getArgIndicesWithDefinedEscapingEffects(of function: Function) -> S
176124

177125
argsWithDefinedEffects.insert(effect.argumentIndex)
178126
switch effect.kind {
179-
case .notEscaping, .escapingToReturn: break
180-
case .escapingToArgument(let toArgIdx, _, _): argsWithDefinedEffects.insert(toArgIdx)
127+
case .notEscaping, .escapingToReturn:
128+
break
129+
case .escapingToArgument(let toArgIdx, _):
130+
argsWithDefinedEffects.insert(toArgIdx)
181131
}
182132
}
183133
return argsWithDefinedEffects
@@ -197,55 +147,105 @@ private func isOperandOfRecursiveCall(_ op: Operand) -> Bool {
197147
return false
198148
}
199149

200-
/// Returns true if when walking up from the `returnInst`, the `fromArgument` is the one
201-
/// and only argument which is reached - with a matching `fromPath`.
202-
private
203-
func isExclusiveEscapeToReturn(fromArgument: Argument, fromPath: SmallProjectionPath,
204-
toPath: SmallProjectionPath,
205-
returnInst: ReturnInst, _ context: FunctionPassContext) -> Bool {
206-
struct IsExclusiveReturnEscapeVisitor : EscapeVisitorWithResult {
207-
let fromArgument: Argument
208-
let fromPath: SmallProjectionPath
209-
let toPath: SmallProjectionPath
210-
var result = false
211-
212-
mutating func visitUse(operand: Operand, path: EscapePath) -> UseResult {
213-
switch operand.instruction {
214-
case is ReturnInst:
215-
if path.followStores { return .abort }
216-
if path.projectionPath.matches(pattern: toPath) {
217-
return .ignore
218-
}
150+
private struct ArgEffectsVisitor : EscapeVisitorWithResult {
151+
enum EscapeDestination {
152+
case notSet
153+
case toReturn(SmallProjectionPath)
154+
case toArgument(Int, SmallProjectionPath) // argument index, path
155+
}
156+
var result = EscapeDestination.notSet
157+
158+
mutating func visitUse(operand: Operand, path: EscapePath) -> UseResult {
159+
if operand.instruction is ReturnInst {
160+
// The argument escapes to the function return
161+
if path.followStores {
162+
// The escaping path must not introduce a followStores.
219163
return .abort
220-
case let si as StoringInstruction:
221-
// Don't allow store instructions because this allows the EscapeUtils to walk up
222-
// an apply result with `followStores`.
223-
if operand == si.destinationOperand {
224-
return .abort
225-
}
226-
case let ca as CopyAddrInst:
227-
// `copy_addr` is like a store.
228-
if operand == ca.destinationOperand {
164+
}
165+
switch result {
166+
case .notSet:
167+
result = .toReturn(path.projectionPath)
168+
case .toReturn(let oldPath):
169+
result = .toReturn(oldPath.merge(with: path.projectionPath))
170+
case .toArgument:
229171
return .abort
230-
}
231-
default:
232-
break
233172
}
234-
return .continueWalk
173+
return .ignore
235174
}
236-
237-
mutating func visitDef(def: Value, path: EscapePath) -> DefResult {
238-
guard let arg = def as? FunctionArgument else {
239-
return .continueWalkUp
240-
}
175+
if isOperandOfRecursiveCall(operand) {
176+
return .ignore
177+
}
178+
return .continueWalk
179+
}
180+
181+
mutating func visitDef(def: Value, path: EscapePath) -> DefResult {
182+
guard let destArg = def as? FunctionArgument else {
183+
return .continueWalkUp
184+
}
185+
// The argument escapes to another argument (e.g. an out or inout argument)
186+
if path.followStores {
187+
// The escaping path must not introduce a followStores.
188+
return .abort
189+
}
190+
let argIdx = destArg.index
191+
switch result {
192+
case .notSet:
193+
result = .toArgument(argIdx, path.projectionPath)
194+
case .toArgument(let oldArgIdx, let oldPath) where oldArgIdx == argIdx:
195+
result = .toArgument(argIdx, oldPath.merge(with: path.projectionPath))
196+
default:
197+
return .abort
198+
}
199+
return .walkDown
200+
}
201+
}
202+
203+
/// Returns true if when walking up from the return instruction, the `fromArgument`
204+
/// is the one and only argument which is reached - with a matching `fromPath`.
205+
private struct IsExclusiveReturnEscapeVisitor : EscapeVisitorWithResult {
206+
let argument: Argument
207+
let argumentPath: SmallProjectionPath
208+
let returnPath: SmallProjectionPath
209+
var result = false
210+
211+
func isExclusiveEscape(returnInst: ReturnInst, _ context: FunctionPassContext) -> Bool {
212+
return returnInst.operand.at(returnPath).visit(using: self, context) ?? false
213+
}
214+
215+
mutating func visitUse(operand: Operand, path: EscapePath) -> UseResult {
216+
switch operand.instruction {
217+
case is ReturnInst:
241218
if path.followStores { return .abort }
242-
if arg == fromArgument && path.projectionPath.matches(pattern: fromPath) {
243-
result = true
244-
return .walkDown
219+
if path.projectionPath.matches(pattern: returnPath) {
220+
return .ignore
245221
}
246222
return .abort
223+
case let si as StoringInstruction:
224+
// Don't allow store instructions because this allows the EscapeUtils to walk up
225+
// an apply result with `followStores`.
226+
if operand == si.destinationOperand {
227+
return .abort
228+
}
229+
case let ca as CopyAddrInst:
230+
// `copy_addr` is like a store.
231+
if operand == ca.destinationOperand {
232+
return .abort
233+
}
234+
default:
235+
break
236+
}
237+
return .continueWalk
238+
}
239+
240+
mutating func visitDef(def: Value, path: EscapePath) -> DefResult {
241+
guard let arg = def as? FunctionArgument else {
242+
return .continueWalkUp
243+
}
244+
if path.followStores { return .abort }
245+
if arg == argument && path.projectionPath.matches(pattern: argumentPath) {
246+
result = true
247+
return .walkDown
247248
}
249+
return .abort
248250
}
249-
let visitor = IsExclusiveReturnEscapeVisitor(fromArgument: fromArgument, fromPath: fromPath, toPath: toPath)
250-
return returnInst.operand.at(toPath).visit(using: visitor, context) ?? false
251251
}

SwiftCompilerSources/Sources/Optimizer/InstructionSimplification/SimplifyBuiltin.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ private extension BuiltinInst {
5656
let lhs = operands[0].value
5757
let rhs = operands[1].value
5858

59-
guard let equal = typesOfValuesAreEqual(lhs, rhs) else {
59+
guard let equal = typesOfValuesAreEqual(lhs, rhs, in: parentFunction) else {
6060
return
6161
}
6262
let builder = Builder(before: self, context)
@@ -66,7 +66,7 @@ private extension BuiltinInst {
6666
}
6767
}
6868

69-
private func typesOfValuesAreEqual(_ lhs: Value, _ rhs: Value) -> Bool? {
69+
private func typesOfValuesAreEqual(_ lhs: Value, _ rhs: Value, in function: Function) -> Bool? {
7070
if lhs == rhs {
7171
return true
7272
}
@@ -76,8 +76,8 @@ private func typesOfValuesAreEqual(_ lhs: Value, _ rhs: Value) -> Bool? {
7676
return nil
7777
}
7878

79-
let lhsTy = lhsExistential.operand.type.instanceTypeOfMetatype
80-
let rhsTy = rhsExistential.operand.type.instanceTypeOfMetatype
79+
let lhsTy = lhsExistential.operand.type.instanceTypeOfMetatype(in: function)
80+
let rhsTy = rhsExistential.operand.type.instanceTypeOfMetatype(in: function)
8181

8282
// Do we know the exact types? This is not the case e.g. if a type is passed as metatype
8383
// to the function.

SwiftCompilerSources/Sources/Optimizer/ModulePasses/StackProtection.swift

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -486,13 +486,23 @@ private extension Instruction {
486486
if !atp.needsStackProtection {
487487
return nil
488488
}
489+
var hasNoStores = NoStores()
490+
if hasNoStores.walkDownUses(ofValue: atp, path: SmallProjectionPath()) == .continueWalk {
491+
return nil
492+
}
493+
489494
// The result of an `address_to_pointer` may be used in any unsafe way, e.g.
490495
// passed to a C function.
491496
baseAddr = atp.operand
492497
case let ia as IndexAddrInst:
493498
if !ia.needsStackProtection {
494499
return nil
495500
}
501+
var hasNoStores = NoStores()
502+
if hasNoStores.walkDownUses(ofAddress: ia, path: SmallProjectionPath()) == .continueWalk {
503+
return nil
504+
}
505+
496506
// `index_addr` is unsafe if not used for tail-allocated elements (e.g. in Array).
497507
baseAddr = ia.base
498508
default:
@@ -509,6 +519,29 @@ private extension Instruction {
509519
}
510520
}
511521

522+
/// Checks if there are no stores to an address or raw pointer.
523+
private struct NoStores : ValueDefUseWalker, AddressDefUseWalker {
524+
var walkDownCache = WalkerCache<SmallProjectionPath>()
525+
526+
mutating func leafUse(value: Operand, path: SmallProjectionPath) -> WalkResult {
527+
if let ptai = value.instruction as? PointerToAddressInst {
528+
return walkDownUses(ofAddress: ptai, path: path)
529+
}
530+
return .abortWalk
531+
}
532+
533+
mutating func leafUse(address: Operand, path: SmallProjectionPath) -> WalkResult {
534+
switch address.instruction {
535+
case is LoadInst:
536+
return .continueWalk
537+
case let cai as CopyAddrInst:
538+
return address == cai.sourceOperand ? .continueWalk : .abortWalk
539+
default:
540+
return .abortWalk
541+
}
542+
}
543+
}
544+
512545
private extension Function {
513546
func setNeedsStackProtection(_ context: FunctionPassContext) {
514547
if !needsStackProtection {

SwiftCompilerSources/Sources/Optimizer/Utilities/EscapeUtils.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -594,7 +594,7 @@ fileprivate struct EscapeWalker<V: EscapeVisitor> : ValueDefUseWalker,
594594
var matched = false
595595
for effect in effects.escapeEffects.arguments {
596596
switch effect.kind {
597-
case .escapingToArgument(let toArgIdx, let toPath, _):
597+
case .escapingToArgument(let toArgIdx, let toPath):
598598
// Note: exclusive argument -> argument effects cannot appear, so we don't need to handle them here.
599599
if effect.matches(calleeArgIdx, argPath.projectionPath) {
600600
guard let callerToIdx = apply.callerArgIndex(calleeArgIndex: toArgIdx) else {

0 commit comments

Comments
 (0)