-
Notifications
You must be signed in to change notification settings - Fork 13.1k
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
Use wrappers for native functions #1179
Comments
This would mean that you can't get a pointer to a C function |
Yes, that is true. I guess I can imagine that it might be useful to be able to get pointers to C functions for interop or something like that, but it's probably fairly uncommon. |
I'd like a scheme where static calls to native functions directly use (when possible) the function's calling conventions, but taking the value of such a function generates a wrapper that follows our own calling convention. This imposes minimal run-time and code-size overhead, without complicating things for language users. |
Hmm... I do not think it would be very hard to implement a scheme like Marijn's. That said, assuming native functions are called from multiple sites, wrappers would likely save code size overall because there is no need to inline the stack switching logic at each call site to a native function. I would expect performance impact to be minimal, but it is harder to predict: it depends on the target architecture and the signature of the target method. |
Allowing calls to use the native convention means we need to keep the ABI as part of the function type (or disallow calling native functions across crates), and I was hoping we could get rid of that. My reason for wanting to do that is pretty weak though - it's just because I'm making ABI an attribute of native modules, and it doesn't seem right to express type information as metadata. |
It doesn't have to be part of the type, but to do direct native calls, calling conventions do have to be associated with static function names (def ids). That's not hard to orchestrate, though. Niko may be right that, for involved calling conventions, generating a wrapper might be cheaper. |
Even on a simple calling convention, we currently generate 2 function calls: one to allocate space for the arguments on the C stack, the other to the "call on C stack" function. Actually, now that I think about it, allocating space on the C stack is not so important (currently), as we end up copying the data in the shim function. It may be better, therefore, to have LLVM allocate the argument structure on the Rust stack, where the allocation is free as part of the initial stack frame allocation. That said, we may at some point want to special case the i386 architecture, in which case allocating the structure on the C stack (as we do today) is better, since it avoids a copy of the arguments. |
It occurs to me that if LLVM inlines the calls to the wrapper functions---as it could likely be convinced to do, as they are small and statically linked most of the time---then we would have the system that Marijn wanted without having to implement it ourselves (to get the code size reduction, though, we'd have to have the linker strip functions that are neither referenced nor exported, but that's something else we should be doing anyhow, I would think) |
Implemented wrappers in @b6af844. Will open a follow-up bug to investigate inlining or other performance improvements. |
Generating wrappers for native functions would make them easier to use, and remove the calling convention from their type. Right now I believe there are a few things that are complicated by making these look different than rust functions (we can't use them across crates for one).
I know we've specifically removed the wrappers before, so I'm sure this requires further discussion.
The text was updated successfully, but these errors were encountered: