-
Notifications
You must be signed in to change notification settings - Fork 13.3k
Lang proposal: extern "unspecified"
for naked functions with arbitrary ABI
#140566
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
Comments
I really like this idea. I suspect there is also some embedded code that would make use of this, e.g. (this example came up here #140279 (comment))
I think this is the right call, because of documentation and tooling. |
Reading through it, this all sounds reasonable and right to me. Maybe another name to consider for this ABI would be |
I'll take assignment and "champion" this, as I seem to have been taking the asm ones recently. Under our process, with a champion, this can be implemented experimentally (and a tracking issue should be filed, etc.). Of course, I'd first like to hear confirmation from @Amanieu that this seems reasonable. Also cc @RalfJung. And I'd like to hear from my fellow @rust-lang/lang members if anyone thinks this needs an RFC. My estimate is that it probably does not -- that this is a straightforward extension -- and that having a good stabilization report and the updated Reference documentation for this will be sufficient. |
There are other uses of an "uncallable-by-Rust-code" ABI that suggest considering a broader perspective. |
So, if the primary reason is to prevent Rust code from calling functions with that ABI, then there are already ~2 ABIs which need to have that implemented for them, and currently do not:
|
Personally I am in favor of the name However, I think that a more refined solution for "this is a well defined ABI but must not be called by rust, it must be called by the GPU" would improve upon this. Regarding processes, I think this is really only relevant to t-compiler, and maybe lang (it's technically syntax i guess?) and doesn't have any semantics, so I would expect this to just need an FCP to stabilize eventually. |
Thanks for pointing these out, agreed that it makes sense to share the checking/error mechanisms. It seems like ABIs could be grouped something like the following:
"unspecified" (or whatever name we land on) would be for the fourth category where rustc has no idea about either side, so has to treat it more or less as an opaque symbol. I think that any of the first three categories require a known ABI name because rustc/LLVM has to be made aware of how to call or create it, depending on category. Based on the description it seems The GPU case I am less certain about. If (1) there isn't anything unique about these functions that Rust needs to know about, (2) these functions can't be written in Rust (excluding asm), and (3) rustc only needs to know the symbols exist somewhere, then I think grouping it into "unspecified" seems reasonable. |
For naming, I suggested “unspecified” because it is true to both rustc (which can’t do much with the ABI because it is not provided) and to the author (who didn’t specify a specific ABI). I think “custom” works here as well. “unknown”, “any”, and “uncallable” on the other hand are true to rustc, but presumably the author knows what the specific ABI is and how to call it. Just clarifying rationale, I don’t have a strong preference or think that’s the most solid reasoning. |
Do we allow arguments/return types on naked functions? What do they do? |
What is the point of having an |
Presumably one could use a |
Yes, they are both documentation and for naked functions that can be called from Rust they define how you can call it. |
Exactly,
We do, because you can totally write something like this #[unsafe(naked)]
extern "C" fn (a: u64, b: u64) -> u64 {
core::arch::naked_asm!(
"lea rax, [rdi + rsi]",
"ret",
)
} So here, the |
Adding to the above, also it's the only way to export a function with a potentially funny calling convention (other than to use an uncallable signature, such as one that accepts an uninhabited type) from a cdylib. Functions written in C or assembly and linked into Rust are hidden when building a cdylib due to how rustc hides Rust symbols. |
|
Yes, this is a feature that I would very much like to see. I don't have a specific preference for the exact name of the ABI though. |
I would like to throw
I like the rationale, but I feel that the "unspecified" ABI is actually defined to the author. The author did actually specify the calling convention - in the comments. The ABI is only just not formalized, but it's still "specified" to humans. That said, even though I feel that "manual" captures the intent more precisely, it is also a very common and loaded word, so it's less obvious for the first time readers what it means exactly. "unspecified" is much more pedagogic in this regard. (FTR, I don't have a strong opinion on this) |
Yes, this is why I think I prefer "custom". Another possibility, that just came to mind, is calling the ABI "asm". |
Background
One of the uses of naked functions is to implement custom calling conventions. We have some code in compiler-builtins like this:
The ABI needs to be specified, so
extern "C"
is used. However, this is misleading as the function does not actually use the C calling convention.Correct ABI would be considered part of the preconditions for this function and it would only be callable inside an
unsafe
block, but Rust has no way to call the function correctly so it seems like we should prevent this.Proposal
Add a new "unspecified" ABI that may be used with naked functions. Rust will error on attempts to call them.
Proposed rules:
extern "unspecified"
can only be used with naked functions orextern
blocksextern "unspecified"
. It can still be passed as a function pointer, and it can be asym
in an asm block.extern "unspecified"
functions must be markedunsafe
, and cannot besafe fn
with anextern
block. This is a hard error. (I'm less certain about this rule since unsafety doesn't mean much if you can't call it. Proposed because it seems consistent with how it must be used, given the function still has preconditions, and it's probably makes sense to treat them asunsafe
in the compiler.)Questions:
cc @rust-lang/lang, @folkertdev, @Amanieu
(currently empty) thread for discussion on Zulip: https://rust-lang.zulipchat.com/#narrow/channel/216763-project-inline-asm/topic/.60extern.20.22unspecified.22.60.20for.20naked.20functions/with/515596073
The text was updated successfully, but these errors were encountered: