Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support P/Invoke to Variadic Functions on Apple Silicon #48752

Closed
k15tfu opened this issue Feb 25, 2021 · 10 comments
Closed

Support P/Invoke to Variadic Functions on Apple Silicon #48752

k15tfu opened this issue Feb 25, 2021 · 10 comments

Comments

@k15tfu
Copy link
Contributor

k15tfu commented Feb 25, 2021

Hi!

What is the best way to pass arguments to variadic functions (sem_open, open, etc) from C# on macOS ARM64?

There were no problems for the first few arguments for x86_64abi (specifically we used public static extern IntPtr sem_open(string name, int oflag, ushort mode, uint value)) because they are also passed via registers (as per https://refspecs.linuxbase.org/elf/x86_64-abi-0.21.pdf), but on Apple Silicon variadic arguments are passed on the stack (https://developer.apple.com/documentation/xcode/writing_arm64_code_for_apple_platforms#3671957). Does CLR support such calling conventions?

Linked issue: #9702

@dotnet-issue-labeler dotnet-issue-labeler bot added the untriaged New issue has not been triaged by the area owner label Feb 25, 2021
@dotnet-issue-labeler
Copy link

I couldn't figure out the best area label to add to this issue. If you have write-permissions please help me learn by adding exactly one area label.

@filipnavara
Copy link
Member

filipnavara commented Feb 25, 2021

I've had the same problem on iOS before. I suppose the __arglist C# keyword may work but I'd welcome a second opinion on it.

Nevermind, I see it was discussed in the linked issue. There is another workaround with generating the prototype with fixed number of arguments that go to registers (8 iirc) and then the ones after that are pushed to stack thanks to the way the ABI is defined. That's not really portable though and just exploits an implementation detail.

@k15tfu
Copy link
Contributor Author

k15tfu commented Feb 25, 2021

@filipnavara Yep, we already do this: public static extern IntPtr sem_open_CharPtrVaList(string name, int oflag, ulong __x2, ulong __x3, ulong __x4, ulong __x5, ulong __x6, ulong __x7, ulong mode, uint value) as per https://developer.apple.com/documentation/xcode/writing_arm64_code_for_apple_platforms#3671957, but I'm looking for the official way. Thanks for suggestion.

@filipnavara
Copy link
Member

I agree this is a valid concern that has to be addressed, thanks for rising it. We are hitting this problem with SQLitePCL.raw and SQLite. It has several methods that accept varargs and it breaks horribly on ARM64 ABI on iOS/macOS.

@jkotas
Copy link
Member

jkotas commented Feb 25, 2021

@AaronRobinsonMSFT AaronRobinsonMSFT removed the untriaged New issue has not been triaged by the area owner label Feb 25, 2021
@AaronRobinsonMSFT AaronRobinsonMSFT added this to the 6.0.0 milestone Feb 25, 2021
@AaronRobinsonMSFT
Copy link
Member

@k15tfu Thanks for bringing this up. Support for this has been discussed and is on our backlog. The "official way" is it is not supported. However, @filipnavara's suggestion is the best workaround at present. This is something we are looking at for .NET 6 though and will prioritize this accordingly.

@AaronRobinsonMSFT AaronRobinsonMSFT changed the title Question: P/Invoke to Variadic Functions on Apple Silicon Support P/Invoke to Variadic Functions on Apple Silicon Feb 25, 2021
@AaronRobinsonMSFT
Copy link
Member

AaronRobinsonMSFT commented Feb 25, 2021

@k15tfu and @filipnavara I see the links above and will get to them eventually. Can one of you provide a blocked scenario without this support? I want to understand the following options:

  1. We need to support a complete __arglist style interop scenario - akin to C++/CLI.
  2. We can officially document the workaround that is already commonly used (e.g. Declare specific P/Invokes with the desired overrides).
  3. Create native shim libraries that forward to the varargs method. This is what the runtime does.
  4. Similar to (2) but create a new attribute or calling convention indicator for the P/Invoke indicating the types should be marshalled as native varargs. See Introduce mechanism to indicate arguments are to be marshalled as native varargs #48796.
  5. Other options?

Edit: After conferring with the JIT team (2) isn't guaranteed to work in all cases. For example, HFA arguments will fail if a specialized P/Invoke signature is written to dispatch to a varargs function. This means that (2) works for some cases but not all. Currently the only correct way to do this on non-Windows is (3).

@filipnavara
Copy link
Member

Scenario:

Suppose I want to bind the sqlite3_config API (https://sqlite.org/c3ref/config.html) and that the SQLite library is shipped with the operating system (e.g. macOS). The workaround requires me to ship different managed binding based on RID (ABI distinction) I am targeting. Traditionally I'd use the one overload per vararg variation to implement it. That works on x86 and x64 but due to the ABI difference it breaks on Apple Silicon.

Using the workaround above is possible, of course, but it requires me to either
a) do RID multi-targeting and shipping two separate managed libraries which is largely unsupported by tooling and may require going through NuGets
b) ship both versions of the P/Invoke within one library and do a runtime check (possibly eliminated by the linker or JIT)

@AaronRobinsonMSFT
Copy link
Member

@filipnavara Thanks for the example - it helps. I've updated my comment above (#48752 (comment)) and for right now the officially supported work around is to use shim libraries and P/Invoke into them. The approach for declaring P/Invoke signatures to varargs functions with specialized signatures works in some cases but not all so that is user discretion.

Additional details on native varargs support - #10478.

@AaronRobinsonMSFT
Copy link
Member

I believe this is a duplicate of the general native varargs issue at #48796. Please let me know if there is something specific in this issue that #48796 doesn't contain.

@ghost ghost locked as resolved and limited conversation to collaborators Sep 7, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

4 participants