Skip to content

Commit

Permalink
Small update (return types in signatures)
Browse files Browse the repository at this point in the history
  • Loading branch information
jkoritzinsky committed Jan 19, 2024
1 parent 63b15bd commit bc35ee7
Showing 1 changed file with 2 additions and 2 deletions.
4 changes: 2 additions & 2 deletions proposed/swift-interop.md
Original file line number Diff line number Diff line change
Expand Up @@ -118,11 +118,11 @@ When calling a function that returns an opaque struct, the Swift ABI always requ

At the lowest level of the calling convention, we do not consider Library Evolution to be a different calling convention than the Swift calling convention. Library Evolution requires that some types are passed by a pointer/reference, but it does not fundamentally change the calling convention. Effectively, Library Evolution forces the least optimizable choice to be taken at every possible point. As a result, we should not handle Library Evolution as a separate calling convention and instead we can manually handle it at the projection layer.

For frozen structs and enums, Swift has a complicated lowering process where the struct or enum type's layout are recursively flattened to a sequence of primitives. If this sequence is length 4 or less, the values of this type are split into the elements of this sequence for parameter passing instead of passing the struct as a whole. Structs and enums that cannot be broken down in this way are passed by-reference to their specified frozen layout. Due to high implementation cost in the RyuJIT, in particular in the `UnmanagedCallersOnly` scenario, we should implement this first pass of lowering in the projection layer; the only types allowed for `CallConvSwift` calling convention in method or function pointer signatures are primitives, our special Swift register types, and pointer types. For reference, this lowering pass is done in the Swift compiler when lowering from Swift IL to LLVM IR. This design decision reinforces our direction of having the Runtime layer of Swift interop support similar features as the LLVM IR representation of Swift.
For frozen structs and enums, Swift has a complicated lowering process where the struct or enum type's layout are recursively flattened to a sequence of primitives. If this sequence is length 4 or less, the values of this type are split into the elements of this sequence for parameter passing instead of passing the struct as a whole. Structs and enums that cannot be broken down in this way are passed by-reference to their specified frozen layout. Due to high implementation cost in the RyuJIT, in particular in the `UnmanagedCallersOnly` scenario, we should implement this first pass of lowering in the projection layer; the only types allowed for `CallConvSwift` calling convention in method or function pointer signatures are primitives, our special Swift register types, and pointer types. We will allow struct types as the return type in a signature to support scenarios where a return value is passed in multiple registers instead of passed indirectly; this occurs in some scenarios such as some larger-than-register SIMD types. For reference, this lowering pass is done in the Swift compiler when lowering from Swift IL to LLVM IR. This design decision reinforces our direction of having the Runtime layer of Swift interop support similar features as the LLVM IR representation of Swift.

##### SIMD Types

We will pass the `System.Runtime.Intrinsics.VectorX<T>` types in SIMD registers as we do with the managed calling convention. We will treat the `Vector2/3/4` types as non-SIMD types (and block their usage directly in the `CallConvSwift` signature as is the case with other structs).
We will pass the `System.Runtime.Intrinsics.VectorX<T>` types in SIMD registers as we do with the managed calling convention. We will treat the `Vector2/3/4` types as non-SIMD types (and block their usage directly as parameters in the `CallConvSwift` signature as is the case with other structs).

CoreCLR and NativeAOT currently block the `VectorX<T>` types from P/Invokes as this behavior is currently not well-supported by RyuJIT. Depending on implementation cost and the number of APIs we wish to support, we may want to block the `VectorX<T>` types from `CallConvSwift` initially until we can implement the correct behavior. We can always add support for these types later.

Expand Down

0 comments on commit bc35ee7

Please sign in to comment.