Hi, folks
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.
1. Defined as a C-cc in runtime but published as a Swift-cc public API in stdlib.
For example, 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: swift/HeapObject.h at 6e3548797503b4a2bbabcebf7ffd156bc1cac245 · apple/swift · GitHub
-
The definition in runtime: swift/HeapObject.cpp at 6e3548797503b4a2bbabcebf7ffd156bc1cac245 · apple/swift · GitHub
-
The decl of the public API in stdlib: swift/DebuggerSupport.swift at 6e3548797503b4a2bbabcebf7ffd156bc1cac245 · apple/swift · GitHub
The other violating functions in the same way are:
- swift_retainCount, swift_unownedRetainCount, swift_weakRetainCount, _swift_getObjectRuntimeFunctionCounters, _swift_getGlobalRuntimeFunctionCounters, and other RuntimeInvocationsTracking things
2. Emitted as a C-cc from user code, but called as a Swift-cc by stdlib indirectly.
For example, 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: swift/GenKeyPath.cpp at 6e3548797503b4a2bbabcebf7ffd156bc1cac245 · apple/swift · GitHub
- stdlib calls the function here: swift/KeyPath.swift at 6e3548797503b4a2bbabcebf7ffd156bc1cac245 · apple/swift · GitHub
Other same cases:
- keypath_get_arg_layout, keypath_destroy, keypath_copy, keypath_arg_init
3. Defined as a C-cc in runtime, but called as a Swift-cc in stdlib
For example, _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.
4. Defined as a C-cc in runtime, but called as a Swift-cc by test binary
swift_demangle
is defined as a C-cc function in runtime, but called as a Swift-cc function from test case.
How to fix them?
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 [stdlib] Fix cc mismatch violation on swift_isClassType by kateinoigakukun · Pull Request #39119 · apple/swift · GitHub
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?