@@ -179,7 +179,6 @@ public class ExportSwift {
179179
180180 class ExportedThunkBuilder {
181181 var body : [ CodeBlockItemSyntax ] = [ ]
182- var liftedParameterExprs : [ ExprSyntax ] = [ ]
183182 var parameters : [ Parameter ] = [ ]
184183 var abiParameterSignatures : [ ( name: String , type: WasmCoreType ) ] = [ ]
185184 var abiReturnType : WasmCoreType ?
@@ -190,8 +189,7 @@ public class ExportSwift {
190189 /// helper. Set for every `async` thunk.
191190 var asyncResolveReturnType : BridgeType ?
192191
193- /// Stack-using parameter lifts hoisted ahead of the deferred async closure.
194- var asyncHoistedBindings : [ CodeBlockItemSyntax ] = [ ]
192+ var parameterBindings : [ CodeBlockItemSyntax ] = [ ]
195193
196194 init ( effects: Effects , returnType: BridgeType ) throws {
197195 self . effects = effects
@@ -254,7 +252,7 @@ public class ExportSwift {
254252 )
255253 }
256254
257- liftedParameterExprs . append ( liftingExpr)
255+ parameterBindings . insert ( " let \( raw : param . name ) = \( liftingExpr) " , at : 0 )
258256 for (name, type) in zip ( argumentsToLift, liftingInfo. parameters. map { $0. type } ) {
259257 abiParameterSignatures. append ( ( name, type) )
260258 }
@@ -269,15 +267,16 @@ public class ExportSwift {
269267 }
270268 }
271269
272- private func removeFirstLiftedParameter( ) -> ( parameter: Parameter , expr: ExprSyntax ) {
273- let parameter = parameters. removeFirst ( )
274- let expr = liftedParameterExprs. removeFirst ( )
275- return ( parameter, expr)
270+ private func removeFirstLiftedParameter( ) -> String {
271+ return parameters. removeFirst ( ) . name
276272 }
277273
278274 private func renderCallStatement( callee: ExprSyntax , returnType: BridgeType ) -> CodeBlockItemSyntax {
279- let labeledParams = zip ( parameters, liftedParameterExprs) . map { param, expr in
280- LabeledExprSyntax ( label: param. label, expression: expr)
275+ let labeledParams = parameters. map { param in
276+ LabeledExprSyntax (
277+ label: param. label,
278+ expression: DeclReferenceExprSyntax ( baseName: . identifier( param. name) )
279+ )
281280 }
282281 var callExpr : ExprSyntax =
283282 " \( raw: callee) ( \( raw: labeledParams. map { $0. description } . joined ( separator: " , " ) ) ) "
@@ -310,7 +309,6 @@ public class ExportSwift {
310309 }
311310
312311 func call( name: String , returnType: BridgeType ) {
313- generateParameterLifting ( )
314312 let item = renderCallStatement ( callee: " \( raw: name) " , returnType: returnType)
315313 append ( item)
316314 }
@@ -325,51 +323,16 @@ public class ExportSwift {
325323 }
326324
327325 func callMethod( methodName: String , returnType: BridgeType ) {
328- let ( _, selfExpr) = removeFirstLiftedParameter ( )
329- generateParameterLifting ( )
326+ let selfExpr = removeFirstLiftedParameter ( )
330327 let item = renderCallStatement (
331328 callee: " \( raw: selfExpr) . \( raw: methodName) " ,
332329 returnType: returnType
333330 )
334331 append ( item)
335332 }
336333
337- /// Generates intermediate variables for stack-using parameters if needed for LIFO compatibility
338- private func generateParameterLifting( ) {
339- let stackParamIndices = parameters. enumerated ( ) . compactMap { index, param -> Int ? in
340- param. type. isStackUsingParameter ? index : nil
341- }
342-
343- if effects. isAsync {
344- // Drain stack parameters before the deferred `Task` or the shared stack is corrupted.
345- for index in stackParamIndices. reversed ( ) {
346- let param = parameters [ index]
347- let expr = liftedParameterExprs [ index]
348- let varName = " _tmp_ \( param. name) "
349- var binding : CodeBlockItemSyntax = " let \( raw: varName) = \( expr) "
350- if !asyncHoistedBindings. isEmpty {
351- binding = binding. with ( \. leadingTrivia, . newline)
352- }
353- asyncHoistedBindings. append ( binding)
354- liftedParameterExprs [ index] = ExprSyntax ( DeclReferenceExprSyntax ( baseName: . identifier( varName) ) )
355- }
356- return
357- }
358-
359- guard stackParamIndices. count > 1 else { return }
360-
361- for index in stackParamIndices. reversed ( ) {
362- let param = parameters [ index]
363- let expr = liftedParameterExprs [ index]
364- let varName = " _tmp_ \( param. name) "
365-
366- append ( " let \( raw: varName) = \( expr) " )
367- liftedParameterExprs [ index] = ExprSyntax ( DeclReferenceExprSyntax ( baseName: . identifier( varName) ) )
368- }
369- }
370-
371334 func callPropertyGetter( propertyName: String , returnType: BridgeType ) {
372- let ( _ , selfExpr) = removeFirstLiftedParameter ( )
335+ let selfExpr = removeFirstLiftedParameter ( )
373336 if returnType == . void {
374337 append ( " \( raw: selfExpr) . \( raw: propertyName) " )
375338 } else {
@@ -379,13 +342,13 @@ public class ExportSwift {
379342 }
380343
381344 func callPropertySetter( propertyName: String ) {
382- let ( _ , selfExpr) = removeFirstLiftedParameter ( )
383- let ( _ , newValueExpr) = removeFirstLiftedParameter ( )
345+ let selfExpr = removeFirstLiftedParameter ( )
346+ let newValueExpr = removeFirstLiftedParameter ( )
384347 append ( " \( raw: selfExpr) . \( raw: propertyName) = \( raw: newValueExpr) " )
385348 }
386349
387350 func callStaticPropertySetter( klassName: String , propertyName: String ) {
388- let ( _ , newValueExpr) = removeFirstLiftedParameter ( )
351+ let newValueExpr = removeFirstLiftedParameter ( )
389352 append ( " \( raw: klassName) . \( raw: propertyName) = \( raw: newValueExpr) " )
390353 }
391354
@@ -456,10 +419,11 @@ public class ExportSwift {
456419 /// so the body must also read the captured value.
457420 /// See: https://github.com/swiftlang/swift/issues/89320
458421 private var asyncThrowsBodyForcesCapture : Bool {
459- effects. isThrows && abiParameterSignatures . isEmpty && asyncHoistedBindings . isEmpty
422+ effects. isThrows && parameterBindings . isEmpty
460423 }
461424
462425 func render( abiName: String ) -> DeclSyntax {
426+ var bindings = parameterBindings
463427 let body : CodeBlockItemListSyntax
464428 if effects. isAsync, let resolveType = asyncResolveReturnType {
465429 let resolveName = " Promise_resolve_ \( resolveType. mangleTypeName) "
@@ -468,17 +432,15 @@ public class ExportSwift {
468432 returnSpelling: resolveType. swiftType,
469433 forcesCapture: forcesCapture
470434 )
471- var hoistedBindings = asyncHoistedBindings
472435 var bodyItems = self . body
473436 if forcesCapture {
474- hoistedBindings . append ( " let __bjs_capture = 0 " )
437+ bindings . append ( " let __bjs_capture = 0 " )
475438 if !bodyItems. isEmpty {
476439 bodyItems [ 0 ] = bodyItems [ 0 ] . with ( \. leadingTrivia, . newline)
477440 }
478441 bodyItems. insert ( " _ = __bjs_capture " , at: 0 )
479442 }
480443 body = """
481- \( CodeBlockItemListSyntax ( hoistedBindings) )
482444 return _bjs_makePromise(resolve: \( raw: resolveName) , reject: Promise_reject) { \( raw: closureHead)
483445 \( CodeBlockItemListSyntax ( bodyItems) )
484446 }
@@ -504,6 +466,10 @@ public class ExportSwift {
504466 } else {
505467 body = CodeBlockItemListSyntax ( self . body)
506468 }
469+ let preparedBody : CodeBlockItemListSyntax = """
470+ \( CodeBlockItemListSyntax ( bindings. map { $0. with ( \. leadingTrivia, . newline) } ) )
471+ \( body)
472+ """
507473 // Build function signature using SwiftSignatureBuilder
508474 let signature = SwiftSignatureBuilder . buildABIFunctionSignature (
509475 abiParameters: abiParameterSignatures,
@@ -515,7 +481,7 @@ public class ExportSwift {
515481 abiName: abiName,
516482 signature: signature
517483 ) { printer in
518- printer. write ( multilineString: body . description)
484+ printer. write ( multilineString: preparedBody . description)
519485 }
520486
521487 return DeclSyntax ( funcDecl)
@@ -1744,19 +1710,6 @@ extension BridgeType {
17441710 return false
17451711 }
17461712
1747- var isStackUsingParameter : Bool {
1748- switch self {
1749- case . swiftStruct, . array, . dictionary, . associatedValueEnum:
1750- return true
1751- case . nullable( let wrapped, _) :
1752- return wrapped. isStackUsingParameter
1753- case . alias( _, let underlying) :
1754- return underlying. isStackUsingParameter
1755- default :
1756- return false
1757- }
1758- }
1759-
17601713 struct LiftingIntrinsicInfo : Sendable {
17611714 let parameters : [ ( name: String , type: WasmCoreType ) ]
17621715
0 commit comments