The current Swift implementation has 4 types of calling-convention mismatch in runtime, stdlib, and code emitted by the compiler.
These violations are one of the blockers of porting to WebAssembly because swiftcc and C-cc are not compatible on WebAssembly.
In our SwiftWasm fork, we applied a hacky patch to use the same calling convention for each function. However, it may break ABI on Darwin, so I want to ask compiler folks before submitting patches to the upstream.
I'll describe the 4 issues in this post.
swift_retainCount is declared and defined in runtime without explicit cc, so it's defined as a C-cc function. But it's published as a Swift-cc public API here in stdlib.
This means some external users can call the function assuming Swift-cc, but the actual implementation in runtime uses C-cc.
The decl of the function in runtime: https://github.com/apple/swift/blob/6e3548797503b4a2bbabcebf7ffd156bc1cac245/stdlib/public/SwiftShims/HeapObject.h#L89-L90
The decl of the public API in stdlib: https://github.com/apple/swift/blob/6e3548797503b4a2bbabcebf7ffd156bc1cac245/stdlib/public/core/DebuggerSupport.swift#L268-L269
The other violating functions in the same way are:
- swift_retainCount, swift_unownedRetainCount, swift_weakRetainCount, _swift_getObjectRuntimeFunctionCounters, _swift_getGlobalRuntimeFunctionCounters, and other RuntimeInvocationsTracking things
keypath_get_arg_layout are emitted as a C-cc function by the compiler, but it's called as a Swift-cc function in the stdlib.
- Compiler emits the function here: https://github.com/apple/swift/blob/6e3548797503b4a2bbabcebf7ffd156bc1cac245/lib/IRGen/GenKeyPath.cpp#L281-L283
- stdlib calls the function here: https://github.com/apple/swift/blob/6e3548797503b4a2bbabcebf7ffd156bc1cac245/stdlib/public/core/KeyPath.swift#L863-L864
Other same cases:
- keypath_get_arg_layout, keypath_destroy, keypath_copy, keypath_arg_init
_isClassType is mainly called by compiler-emitted code and defined as a C-cc function. But it's also called by stdlib.
The call-site of stdlib uses @_silgen_name to link the function, so it's called through swiftcc.
Fortunately, the API is not exposed from Swift stdlib, so no external user calls it as a Swift-cc.
swift_demangle is defined as a C-cc function in runtime, but called as a Swift-cc function from test case.
For case 1, we can add explicit
SWIFT_CC(swift) at the definition in runtime because there is no caller that expects it to be C-cc.
For case 2, I don't know which side, runtime or compiler-generated function, should be fixed.
For case 3, the function should be called though C-cc consistently to avoid breaking ABI between generated code which expects it to be C-cc.
This case can be fixed by https://github.com/apple/swift/pull/39119
For case 4, this can be resolved by fixing the test case without any effect on ABI.
Do you have any idea about this issue or good solution of case 2?
And also is there any concern around ABI stability?