Skip to content

Wasm: fix async typed throws arguments mismatch trap - #89416

Merged
MaxDesiatov merged 2 commits into
swiftlang:mainfrom
MaxDesiatov:maxd/wasm-async-typed-throws
May 28, 2026
Merged

Wasm: fix async typed throws arguments mismatch trap#89416
MaxDesiatov merged 2 commits into
swiftlang:mainfrom
MaxDesiatov:maxd/wasm-async-typed-throws

Conversation

@MaxDesiatov

@MaxDesiatov MaxDesiatov commented May 26, 2026

Copy link
Copy Markdown
Contributor

Workaround for issue #89320: a Wasm runtime trap when async typed-throws closures are coerced via thin_to_thick_function. The WebAssembly backend pads swiftcc signatures with trailing swiftself/swifterror placeholders to align call_indirect. On thin async typed-throws callees the padding collides positionally with the trailing ind_error_ptr, miscompiling calls from thick callers.

This PR adds a mandatory SIL pass WasmAsyncT2TLowering (gated on Triple::isWasm(), runs after OwnershipModelEliminator) that rewrites the narrow bug shape (isAsync, hasIndirectErrorResult, non-polymorphic operand/result, FunctionRefBaseInst operand, single-BB uses) into a zero-capture partial_apply [callee_guaranteed] [on_stack] bracketed by dealloc_stack. The partial_apply lowering emits matching caller and callee arg layouts at the LLVM level, sidestepping the backend padding mismatch.

Resolves #89320
rdar://177615931

@MaxDesiatov
MaxDesiatov requested a review from rjmccall as a code owner May 26, 2026 12:44
@MaxDesiatov
MaxDesiatov requested a review from eeckstein as a code owner May 26, 2026 12:44
@MaxDesiatov MaxDesiatov added the WebAssembly Platform: WebAssembly label May 26, 2026
@MaxDesiatov

Copy link
Copy Markdown
Contributor Author

@swift-ci smoke test

Comment thread test/IRGen/async_typed_throws_nonwasm.swift Outdated
Co-authored-by: Max Desiatov <m_desiatov@apple.com>
@MaxDesiatov

Copy link
Copy Markdown
Contributor Author

@swift-ci smoke test

@kateinoigakukun

Copy link
Copy Markdown
Member

Let me put my thoughts on this: This is very unfortunate and strictly speaking the problem is not specific to wasm but any target that doesn't support putting swiftself on a register (effectively wasm only today though). Having said that, the temporal workaround is valid and worth landing as a band-aid for now. We should consider placing ind_error param before the swiftself param in the mid-term.

@MaxDesiatov
MaxDesiatov enabled auto-merge (squash) May 27, 2026 15:25
@MaxDesiatov

Copy link
Copy Markdown
Contributor Author

@swift-ci test windows

@MaxDesiatov
MaxDesiatov merged commit 879ec06 into swiftlang:main May 28, 2026
3 checks passed
@MaxDesiatov
MaxDesiatov deleted the maxd/wasm-async-typed-throws branch May 28, 2026 06:03
@github-project-automation github-project-automation Bot moved this from In Progress to Done in Swift for Wasm May 28, 2026
ktoso added a commit to mattmassicotte/swift that referenced this pull request May 28, 2026
swiftlang#89416 was merged, so this should work now
Teemperor pushed a commit to Teemperor/swift-mono that referenced this pull request May 29, 2026
MaxDesiatov added a commit that referenced this pull request Jul 14, 2026
Follow up to currently-reverted #89416.

On wasm32 the WebAssembly backend pads the `swiftself` and `swifterror` parameters, which left the indirect typed-error pointer and the `swiftself`/context slot at different LLVM-IR positions for Thin versus Thick async callers; caller and callee then disagreed on which trailing pointer held the typed-error slot and miscompiled async typed-throws calls (#89155: `Result.init(catching:) async` trapped in a value-witness copy on Wasm).

With this change `SignatureExpansion::expandAsyncEntryType` now emits `addIndirectThrowingResult` before the `swiftself`/context slot, so the trailing pair is always `[ind_error, swiftself]` and Thin and Thick agree on the position regardless of parameter padding. The result-shape decision moves behind one gate, `hasTrailingAsyncErrorContextPair` (`GenCall.h`), consumed by the three sites that read these slots positionally: `AsyncCallEmission::setFromCallee`, `AsyncPartialApplicationForwarderEmission`, and `AsyncNativeCCEntryPointArgumentEmission::mapAsyncParameters` (the last also pre-extracts the witness-method Self/witness-table that trail the pair).

Each consumer carries an assertion that fires if the gate ever diverges from the slots actually filled.

Fixes #89320.
Teemperor pushed a commit to Teemperor/swift-mono that referenced this pull request Jul 14, 2026
…R 89715)

Follow up to currently-reverted swiftlang/swift#89416.

On wasm32 the WebAssembly backend pads the `swiftself` and `swifterror` parameters, which left the indirect typed-error pointer and the `swiftself`/context slot at different LLVM-IR positions for Thin versus Thick async callers; caller and callee then disagreed on which trailing pointer held the typed-error slot and miscompiled async typed-throws calls (Issue/PR 89155: `Result.init(catching:) async` trapped in a value-witness copy on Wasm).

With this change `SignatureExpansion::expandAsyncEntryType` now emits `addIndirectThrowingResult` before the `swiftself`/context slot, so the trailing pair is always `[ind_error, swiftself]` and Thin and Thick agree on the position regardless of parameter padding. The result-shape decision moves behind one gate, `hasTrailingAsyncErrorContextPair` (`GenCall.h`), consumed by the three sites that read these slots positionally: `AsyncCallEmission::setFromCallee`, `AsyncPartialApplicationForwarderEmission`, and `AsyncNativeCCEntryPointArgumentEmission::mapAsyncParameters` (the last also pre-extracts the witness-method Self/witness-table that trail the pair).

Each consumer carries an assertion that fires if the gate ever diverges from the slots actually filled.

Fixes Issue/PR 89320.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

SIL WebAssembly Platform: WebAssembly

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

Crash with typed/untyped throwing async functions on Wasm

2 participants