Skip to content

Commit 1b99431

Browse files
Merge pull request swiftwasm#618 from PassiveLogic/kr/stack-abi-generalization
NCF: BridgeJS: Generalize Optional stack ABI for Array, Dictionary, and Struct types
2 parents dd1cb58 + bed1178 commit 1b99431

File tree

14 files changed

+127
-354
lines changed

14 files changed

+127
-354
lines changed

Benchmarks/Sources/Generated/BridgeJS.swift

Lines changed: 9 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1762,11 +1762,7 @@ public func _bjs_ArrayRoundtrip_makeOptionalPointArray(_ _self: UnsafeMutableRaw
17621762
#if arch(wasm32)
17631763
let ret = ArrayRoundtrip.bridgeJSLiftParameter(_self).makeOptionalPointArray()
17641764
for __bjs_elem_ret in ret {
1765-
let __bjs_isSome_ret_elem = __bjs_elem_ret != nil
1766-
if let __bjs_unwrapped_ret_elem = __bjs_elem_ret {
1767-
__bjs_unwrapped_ret_elem.bridgeJSLowerReturn()
1768-
}
1769-
_swift_js_push_i32(__bjs_isSome_ret_elem ? 1 : 0)
1765+
__bjs_elem_ret.bridgeJSLowerReturn()
17701766
}
17711767
_swift_js_push_i32(Int32(ret.count))
17721768
#else
@@ -1789,11 +1785,7 @@ public func _bjs_ArrayRoundtrip_roundtripOptionalPointArray(_ _self: UnsafeMutab
17891785
return __result
17901786
}())
17911787
for __bjs_elem_ret in ret {
1792-
let __bjs_isSome_ret_elem = __bjs_elem_ret != nil
1793-
if let __bjs_unwrapped_ret_elem = __bjs_elem_ret {
1794-
__bjs_unwrapped_ret_elem.bridgeJSLowerReturn()
1795-
}
1796-
_swift_js_push_i32(__bjs_isSome_ret_elem ? 1 : 0)
1788+
__bjs_elem_ret.bridgeJSLowerReturn()
17971789
}
17981790
_swift_js_push_i32(Int32(ret.count))
17991791
#else
@@ -1803,15 +1795,9 @@ public func _bjs_ArrayRoundtrip_roundtripOptionalPointArray(_ _self: UnsafeMutab
18031795

18041796
@_expose(wasm, "bjs_ArrayRoundtrip_takeOptionalArray")
18051797
@_cdecl("bjs_ArrayRoundtrip_takeOptionalArray")
1806-
public func _bjs_ArrayRoundtrip_takeOptionalArray(_ _self: UnsafeMutableRawPointer, _ values: Int32) -> Void {
1798+
public func _bjs_ArrayRoundtrip_takeOptionalArray(_ _self: UnsafeMutableRawPointer) -> Void {
18071799
#if arch(wasm32)
1808-
ArrayRoundtrip.bridgeJSLiftParameter(_self).takeOptionalArray(_: {
1809-
if values == 0 {
1810-
return Optional<[Int]>.none
1811-
} else {
1812-
return [Int].bridgeJSLiftParameter()
1813-
}
1814-
}())
1800+
ArrayRoundtrip.bridgeJSLiftParameter(_self).takeOptionalArray(_: Optional<[Int]>.bridgeJSLiftParameter())
18151801
#else
18161802
fatalError("Only available on WebAssembly")
18171803
#endif
@@ -1822,11 +1808,7 @@ public func _bjs_ArrayRoundtrip_takeOptionalArray(_ _self: UnsafeMutableRawPoint
18221808
public func _bjs_ArrayRoundtrip_makeOptionalArraySome(_ _self: UnsafeMutableRawPointer) -> Void {
18231809
#if arch(wasm32)
18241810
let ret = ArrayRoundtrip.bridgeJSLiftParameter(_self).makeOptionalArraySome()
1825-
let __bjs_isSome_ret = ret != nil
1826-
if let __bjs_unwrapped_ret = ret {
1827-
__bjs_unwrapped_ret.bridgeJSLowerReturn()
1828-
}
1829-
_swift_js_push_i32(__bjs_isSome_ret ? 1 : 0)
1811+
ret.bridgeJSLowerReturn()
18301812
#else
18311813
fatalError("Only available on WebAssembly")
18321814
#endif
@@ -1837,32 +1819,18 @@ public func _bjs_ArrayRoundtrip_makeOptionalArraySome(_ _self: UnsafeMutableRawP
18371819
public func _bjs_ArrayRoundtrip_makeOptionalArrayNone(_ _self: UnsafeMutableRawPointer) -> Void {
18381820
#if arch(wasm32)
18391821
let ret = ArrayRoundtrip.bridgeJSLiftParameter(_self).makeOptionalArrayNone()
1840-
let __bjs_isSome_ret = ret != nil
1841-
if let __bjs_unwrapped_ret = ret {
1842-
__bjs_unwrapped_ret.bridgeJSLowerReturn()
1843-
}
1844-
_swift_js_push_i32(__bjs_isSome_ret ? 1 : 0)
1822+
ret.bridgeJSLowerReturn()
18451823
#else
18461824
fatalError("Only available on WebAssembly")
18471825
#endif
18481826
}
18491827

18501828
@_expose(wasm, "bjs_ArrayRoundtrip_roundtripOptionalArray")
18511829
@_cdecl("bjs_ArrayRoundtrip_roundtripOptionalArray")
1852-
public func _bjs_ArrayRoundtrip_roundtripOptionalArray(_ _self: UnsafeMutableRawPointer, _ values: Int32) -> Void {
1830+
public func _bjs_ArrayRoundtrip_roundtripOptionalArray(_ _self: UnsafeMutableRawPointer) -> Void {
18531831
#if arch(wasm32)
1854-
let ret = ArrayRoundtrip.bridgeJSLiftParameter(_self).roundtripOptionalArray(_: {
1855-
if values == 0 {
1856-
return Optional<[Int]>.none
1857-
} else {
1858-
return [Int].bridgeJSLiftParameter()
1859-
}
1860-
}())
1861-
let __bjs_isSome_ret = ret != nil
1862-
if let __bjs_unwrapped_ret = ret {
1863-
__bjs_unwrapped_ret.bridgeJSLowerReturn()
1864-
}
1865-
_swift_js_push_i32(__bjs_isSome_ret ? 1 : 0)
1832+
let ret = ArrayRoundtrip.bridgeJSLiftParameter(_self).roundtripOptionalArray(_: Optional<[Int]>.bridgeJSLiftParameter())
1833+
ret.bridgeJSLowerReturn()
18661834
#else
18671835
fatalError("Only available on WebAssembly")
18681836
#endif

Plugins/BridgeJS/Sources/BridgeJSCore/ExportSwift.swift

Lines changed: 15 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -147,27 +147,7 @@ public class ExportSwift {
147147
} else {
148148
optionalSwiftType = "JSUndefinedOr"
149149
}
150-
if case .array(let elementType) = wrappedType {
151-
let arrayLift = StackCodegen().liftArrayExpression(elementType: elementType)
152-
let isSomeParam = argumentsToLift[0]
153-
let swiftTypeName = elementType.swiftType
154-
typeNameForIntrinsic = "\(optionalSwiftType)<[\(swiftTypeName)]>"
155-
let absentExpr =
156-
kind == .null
157-
? "\(optionalSwiftType)<[\(swiftTypeName)]>.none"
158-
: "\(optionalSwiftType)<[\(swiftTypeName)]>.undefined"
159-
liftingExpr = ExprSyntax(
160-
"""
161-
{
162-
if \(raw: isSomeParam) == 0 {
163-
return \(raw: absentExpr)
164-
} else {
165-
return \(arrayLift)
166-
}
167-
}()
168-
"""
169-
)
170-
} else if case .swiftProtocol(let protocolName) = wrappedType {
150+
if case .swiftProtocol(let protocolName) = wrappedType {
171151
let wrapperName = "Any\(protocolName)"
172152
typeNameForIntrinsic = "\(optionalSwiftType)<\(wrapperName)>"
173153
liftingExpr = ExprSyntax(
@@ -919,43 +899,11 @@ struct StackCodegen {
919899
let typeName = kind == .null ? "Optional" : "JSUndefinedOr"
920900
switch wrappedType {
921901
case .string, .int, .uint, .bool, .float, .double, .jsObject(nil), .jsValue,
922-
.swiftStruct, .swiftHeapObject, .caseEnum, .associatedValueEnum, .rawValueEnum:
902+
.swiftStruct, .swiftHeapObject, .caseEnum, .associatedValueEnum, .rawValueEnum,
903+
.array, .dictionary:
923904
return "\(raw: typeName)<\(raw: wrappedType.swiftType)>.bridgeJSLiftParameter()"
924905
case .jsObject(let className?):
925906
return "\(raw: typeName)<JSObject>.bridgeJSLiftParameter().map { \(raw: className)(unsafelyWrapping: $0) }"
926-
case .array(let elementType):
927-
let arrayLift = liftArrayExpression(elementType: elementType)
928-
let swiftTypeName = elementType.swiftType
929-
let absentExpr =
930-
kind == .null
931-
? "\(typeName)<[\(swiftTypeName)]>.none" : "\(typeName)<[\(swiftTypeName)]>.undefined"
932-
return """
933-
{
934-
let __isSome = _swift_js_pop_i32()
935-
if __isSome == 0 {
936-
return \(raw: absentExpr)
937-
} else {
938-
return \(arrayLift)
939-
}
940-
}()
941-
"""
942-
case .dictionary(let valueType):
943-
let dictionaryLift = liftDictionaryExpression(valueType: valueType)
944-
let swiftTypeName = valueType.swiftType
945-
let absentExpr =
946-
kind == .null
947-
? "\(typeName)<[String: \(swiftTypeName)]>.none"
948-
: "\(typeName)<[String: \(swiftTypeName)]>.undefined"
949-
return """
950-
{
951-
let __isSome = _swift_js_pop_i32()
952-
if __isSome == 0 {
953-
return \(raw: absentExpr)
954-
} else {
955-
return \(dictionaryLift)
956-
}
957-
}()
958-
"""
959907
case .nullable, .void, .namespaceEnum, .closure, .unsafePointer, .swiftProtocol:
960908
fatalError("Invalid nullable wrapped type: \(wrappedType)")
961909
}
@@ -1112,6 +1060,13 @@ struct StackCodegen {
11121060
accessor: String,
11131061
varPrefix: String
11141062
) -> [CodeBlockItemSyntax] {
1063+
switch wrappedType {
1064+
case .array, .dictionary, .swiftStruct:
1065+
return ["\(raw: accessor).bridgeJSLowerReturn()"]
1066+
default:
1067+
break
1068+
}
1069+
11151070
var statements: [String] = []
11161071
statements.append("let __bjs_isSome_\(varPrefix) = \(accessor) != nil")
11171072
statements.append("if let __bjs_unwrapped_\(varPrefix) = \(accessor) {")
@@ -1140,23 +1095,15 @@ struct StackCodegen {
11401095
case .string, .int, .uint, .bool, .float, .double, .jsValue:
11411096
return ["\(raw: unwrappedVar).bridgeJSLowerStackReturn()"]
11421097
case .caseEnum, .rawValueEnum:
1143-
// Enums conform to _BridgedSwiftStackType
11441098
return ["\(raw: unwrappedVar).bridgeJSLowerStackReturn()"]
1145-
case .swiftStruct:
1146-
return ["\(raw: unwrappedVar).bridgeJSLowerReturn()"]
11471099
case .swiftHeapObject:
11481100
return ["\(raw: unwrappedVar).bridgeJSLowerStackReturn()"]
11491101
case .associatedValueEnum:
1150-
// Push payloads via bridgeJSLowerParameter(), then push the returned case ID
11511102
return ["_swift_js_push_i32(\(raw: unwrappedVar).bridgeJSLowerParameter())"]
11521103
case .jsObject(nil):
11531104
return ["\(raw: unwrappedVar).bridgeJSLowerStackReturn()"]
11541105
case .jsObject(_?):
11551106
return ["\(raw: unwrappedVar).jsObject.bridgeJSLowerStackReturn()"]
1156-
case .array(let elementType):
1157-
return lowerArrayStatements(elementType: elementType, accessor: unwrappedVar, varPrefix: varPrefix)
1158-
case .dictionary(let valueType):
1159-
return lowerDictionaryStatements(valueType: valueType, accessor: unwrappedVar, varPrefix: varPrefix)
11601107
default:
11611108
return ["preconditionFailure(\"BridgeJS: unsupported optional wrapped type\")"]
11621109
}
@@ -1834,8 +1781,12 @@ extension BridgeType {
18341781
case .swiftProtocol: return .jsObject
18351782
case .void: return .void
18361783
case .nullable(let wrappedType, _):
1784+
let wrappedInfo = try wrappedType.liftParameterInfo()
1785+
if wrappedInfo.parameters.isEmpty {
1786+
return LiftingIntrinsicInfo(parameters: [])
1787+
}
18371788
var optionalParams: [(name: String, type: WasmCoreType)] = [("isSome", .i32)]
1838-
optionalParams.append(contentsOf: try wrappedType.liftParameterInfo().parameters)
1789+
optionalParams.append(contentsOf: wrappedInfo.parameters)
18391790
return LiftingIntrinsicInfo(parameters: optionalParams)
18401791
case .caseEnum: return .caseEnum
18411792
case .rawValueEnum(_, let rawType):

Plugins/BridgeJS/Sources/BridgeJSLink/JSGlueGen.swift

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -832,7 +832,8 @@ struct IntrinsicJSFragment: Sendable {
832832
}
833833
printer.write("}")
834834
cleanupCode.write("if (\(cleanupVar)) { \(cleanupVar)(); }")
835-
return ["+\(isSomeVar)"]
835+
printer.write("\(JSGlueVariableScope.reservedI32Stack).push(+\(isSomeVar));")
836+
return []
836837
case .string, .rawValueEnum(_, .string):
837838
let bytesVar = scope.variable("\(value)Bytes")
838839
let idVar = scope.variable("\(value)Id")
@@ -895,7 +896,8 @@ struct IntrinsicJSFragment: Sendable {
895896
}
896897
printer.write("}")
897898
cleanupCode.write("for (const cleanup of \(cleanupArrayVar)) { cleanup(); }")
898-
return ["+\(isSomeVar)"]
899+
printer.write("\(JSGlueVariableScope.reservedI32Stack).push(+\(isSomeVar));")
900+
return []
899901
case .dictionary(let valueType):
900902
let cleanupArrayVar = scope.variable("\(value)Cleanups")
901903
printer.write("const \(cleanupArrayVar) = [];")
@@ -915,7 +917,8 @@ struct IntrinsicJSFragment: Sendable {
915917
}
916918
printer.write("}")
917919
cleanupCode.write("for (const cleanup of \(cleanupArrayVar)) { cleanup(); }")
918-
return ["+\(isSomeVar)"]
920+
printer.write("\(JSGlueVariableScope.reservedI32Stack).push(+\(isSomeVar));")
921+
return []
919922
default:
920923
switch wrappedType {
921924
case .swiftHeapObject:

Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/ArrayTypes.swift

Lines changed: 4 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -277,20 +277,10 @@ public func _bjs_processOptionalStringArray() -> Void {
277277

278278
@_expose(wasm, "bjs_processOptionalArray")
279279
@_cdecl("bjs_processOptionalArray")
280-
public func _bjs_processOptionalArray(_ values: Int32) -> Void {
280+
public func _bjs_processOptionalArray() -> Void {
281281
#if arch(wasm32)
282-
let ret = processOptionalArray(_: {
283-
if values == 0 {
284-
return Optional<[Int]>.none
285-
} else {
286-
return [Int].bridgeJSLiftParameter()
287-
}
288-
}())
289-
let __bjs_isSome_ret = ret != nil
290-
if let __bjs_unwrapped_ret = ret {
291-
__bjs_unwrapped_ret.bridgeJSLowerReturn()
292-
}
293-
_swift_js_push_i32(__bjs_isSome_ret ? 1 : 0)
282+
let ret = processOptionalArray(_: Optional<[Int]>.bridgeJSLiftParameter())
283+
ret.bridgeJSLowerReturn()
294284
#else
295285
fatalError("Only available on WebAssembly")
296286
#endif
@@ -311,11 +301,7 @@ public func _bjs_processOptionalPointArray() -> Void {
311301
return __result
312302
}())
313303
for __bjs_elem_ret in ret {
314-
let __bjs_isSome_ret_elem = __bjs_elem_ret != nil
315-
if let __bjs_unwrapped_ret_elem = __bjs_elem_ret {
316-
__bjs_unwrapped_ret_elem.bridgeJSLowerReturn()
317-
}
318-
_swift_js_push_i32(__bjs_isSome_ret_elem ? 1 : 0)
304+
__bjs_elem_ret.bridgeJSLowerReturn()
319305
}
320306
_swift_js_push_i32(Int32(ret.count))
321307
#else

Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/DefaultParameters.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -294,9 +294,9 @@ public func _bjs_testEmptyInit(_ greeter: UnsafeMutableRawPointer) -> UnsafeMuta
294294

295295
@_expose(wasm, "bjs_testOptionalStructDefault")
296296
@_cdecl("bjs_testOptionalStructDefault")
297-
public func _bjs_testOptionalStructDefault(_ point: Int32) -> Void {
297+
public func _bjs_testOptionalStructDefault() -> Void {
298298
#if arch(wasm32)
299-
let ret = testOptionalStructDefault(point: Optional<Config>.bridgeJSLiftParameter(point))
299+
let ret = testOptionalStructDefault(point: Optional<Config>.bridgeJSLiftParameter())
300300
return ret.bridgeJSLowerReturn()
301301
#else
302302
fatalError("Only available on WebAssembly")
@@ -305,9 +305,9 @@ public func _bjs_testOptionalStructDefault(_ point: Int32) -> Void {
305305

306306
@_expose(wasm, "bjs_testOptionalStructWithValueDefault")
307307
@_cdecl("bjs_testOptionalStructWithValueDefault")
308-
public func _bjs_testOptionalStructWithValueDefault(_ point: Int32) -> Void {
308+
public func _bjs_testOptionalStructWithValueDefault() -> Void {
309309
#if arch(wasm32)
310-
let ret = testOptionalStructWithValueDefault(point: Optional<Config>.bridgeJSLiftParameter(point))
310+
let ret = testOptionalStructWithValueDefault(point: Optional<Config>.bridgeJSLiftParameter())
311311
return ret.bridgeJSLowerReturn()
312312
#else
313313
fatalError("Only available on WebAssembly")

Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/DictionaryTypes.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,9 @@ public func _bjs_mirrorDictionary() -> Void {
1111

1212
@_expose(wasm, "bjs_optionalDictionary")
1313
@_cdecl("bjs_optionalDictionary")
14-
public func _bjs_optionalDictionary(_ values: Int32) -> Void {
14+
public func _bjs_optionalDictionary() -> Void {
1515
#if arch(wasm32)
16-
let ret = optionalDictionary(_: Optional<[String: String]>.bridgeJSLiftParameter(values))
16+
let ret = optionalDictionary(_: Optional<[String: String]>.bridgeJSLiftParameter())
1717
return ret.bridgeJSLowerReturn()
1818
#else
1919
fatalError("Only available on WebAssembly")

Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/EnumAssociatedValue.swift

Lines changed: 5 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -617,14 +617,7 @@ extension OptionalAllTypesResult: _BridgedSwiftAssociatedValueEnum {
617617
case 3:
618618
return .optNestedEnum(Optional<APIResult>.bridgeJSLiftParameter())
619619
case 4:
620-
return .optArray({
621-
let __isSome = _swift_js_pop_i32()
622-
if __isSome == 0 {
623-
return Optional<[Int]>.none
624-
} else {
625-
return [Int].bridgeJSLiftParameter()
626-
}
627-
}())
620+
return .optArray(Optional<[Int]>.bridgeJSLiftParameter())
628621
case 5:
629622
return .empty
630623
default:
@@ -637,11 +630,7 @@ extension OptionalAllTypesResult: _BridgedSwiftAssociatedValueEnum {
637630
@_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerParameter() -> Int32 {
638631
switch self {
639632
case .optStruct(let param0):
640-
let __bjs_isSome_param0 = param0 != nil
641-
if let __bjs_unwrapped_param0 = param0 {
642-
__bjs_unwrapped_param0.bridgeJSLowerReturn()
643-
}
644-
_swift_js_push_i32(__bjs_isSome_param0 ? 1 : 0)
633+
param0.bridgeJSLowerReturn()
645634
return Int32(0)
646635
case .optClass(let param0):
647636
let __bjs_isSome_param0 = param0 != nil
@@ -665,11 +654,7 @@ extension OptionalAllTypesResult: _BridgedSwiftAssociatedValueEnum {
665654
_swift_js_push_i32(__bjs_isSome_param0 ? 1 : 0)
666655
return Int32(3)
667656
case .optArray(let param0):
668-
let __bjs_isSome_param0 = param0 != nil
669-
if let __bjs_unwrapped_param0 = param0 {
670-
__bjs_unwrapped_param0.bridgeJSLowerReturn()
671-
}
672-
_swift_js_push_i32(__bjs_isSome_param0 ? 1 : 0)
657+
param0.bridgeJSLowerReturn()
673658
return Int32(4)
674659
case .empty:
675660
return Int32(5)
@@ -689,11 +674,7 @@ extension OptionalAllTypesResult: _BridgedSwiftAssociatedValueEnum {
689674
@_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerReturn() {
690675
switch self {
691676
case .optStruct(let param0):
692-
let __bjs_isSome_param0 = param0 != nil
693-
if let __bjs_unwrapped_param0 = param0 {
694-
__bjs_unwrapped_param0.bridgeJSLowerReturn()
695-
}
696-
_swift_js_push_i32(__bjs_isSome_param0 ? 1 : 0)
677+
param0.bridgeJSLowerReturn()
697678
_swift_js_push_tag(Int32(0))
698679
case .optClass(let param0):
699680
let __bjs_isSome_param0 = param0 != nil
@@ -717,11 +698,7 @@ extension OptionalAllTypesResult: _BridgedSwiftAssociatedValueEnum {
717698
_swift_js_push_i32(__bjs_isSome_param0 ? 1 : 0)
718699
_swift_js_push_tag(Int32(3))
719700
case .optArray(let param0):
720-
let __bjs_isSome_param0 = param0 != nil
721-
if let __bjs_unwrapped_param0 = param0 {
722-
__bjs_unwrapped_param0.bridgeJSLowerReturn()
723-
}
724-
_swift_js_push_i32(__bjs_isSome_param0 ? 1 : 0)
701+
param0.bridgeJSLowerReturn()
725702
_swift_js_push_tag(Int32(4))
726703
case .empty:
727704
_swift_js_push_tag(Int32(5))

0 commit comments

Comments
 (0)