Skip to content

Conversation

ehuss
Copy link
Contributor

@ehuss ehuss commented Sep 17, 2025

This updates the definitions of the extern ABIs to try to make them a little clearer as to what they mean.

This also adds new statements about the equivalence of some ABIs to the "C" ABI.

Fixes #1946.

@ehuss
Copy link
Contributor Author

ehuss commented Sep 17, 2025

@ChrisDenton We rephrased the description of the "system" ABI, and were wondering if you could take a look to see if the new text was accurate and conveyed the right meaning.

@Amanieu or @ChrisDenton We made a few new claims in this edit about the "C" ABI. We were sure who to ask, but were wondering if you knew the answer. In particular it is specifying that:

  • "win64" is the same as the "C" ABI on Windows x86_64 targets
  • "sysv64" is the same as the "C" ABI on non-Windows x86_64 targets

@Amanieu
Copy link
Member

Amanieu commented Sep 17, 2025

Yes, that seems correct to me.

@ChrisDenton
Copy link
Member

ChrisDenton commented Sep 17, 2025

Should probably @workingjubilee and @RalfJung who are knowledgable in this area.

This looks good to me though rust-lang/rust#136946 will need to adjust the the Windows 32-bit documentation to note the varargs peculiarity.

Copy link
Member

@RalfJung RalfJung left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This sounds right but I don't actually know that much about all these target-specific ABIs.

Not sure how I feel about linking to the Microsoft docs for some of these (even when they are not Microsoft-defined ABIs, or are they?), but I don't know a better place to link to either.


r[items.extern.abi.c]
* `unsafe extern "C"` --- This is the same as `extern fn foo()`; whatever the default your C compiler supports.
* `unsafe extern "C"` --- The "C" ABI attempts to match the default ABI chosen by the dominant C compiler for the target.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"attempts to match" is a bit... weak?^^

* `unsafe extern "system"` --- This is equivalent to `extern "C"` except on Windows x86_32 where it is equivalent to `"stdcall"`.

> [!NOTE]
> As the correct underlying ABI on Windows is target-specific, it's best to use `extern "system"` when attemping to link to the Windows API.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This isn't true for all of the Windows API though, some of it uses "C"...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated, though I think you meant cdecl here?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No I meant "C". "cdecl" is x86-32-only.

r[items.extern.abi.stdcall]
* `unsafe extern "stdcall"` --- The default for the Win32 API on x86_32.
* `unsafe extern "stdcall"` --- The calling convention typically used by the [Win32 API] on x86_32.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this correspond to __stdcall or __attribute__((stdcall)) or anything like that on any other compiler?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe the answer is "yes". Are you suggesting this should explicitly say that like the entry for fastcall does?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems worthwhile, doesn't it?


r[items.extern.abi.cdecl]
* `unsafe extern "cdecl"` --- The default for x86_32 C code.
* `unsafe extern "cdecl"` --- The calling convention typically used with x86_32 C code.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this correspond to __scdecl or __attribute__((cdecl)) or anything like that on any other compiler?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe the answer here is also "yes" (assuming the s is a typo).

Comment on lines 146 to 165
* `unsafe extern "win64"` --- The Windows x64 ABI.
* Only available on x86_64 targets.
* "win64" is the same as the "C" ABI on Windows x86_64 targets.

> [!NOTE]
> See <https://learn.microsoft.com/en-us/cpp/build/x64-software-conventions> and <https://en.wikipedia.org/wiki/X86_calling_conventions#Microsoft_x64_calling_convention> for more information.
r[items.extern.abi.sysv64]
* `unsafe extern "sysv64"` --- The default for C code on non-Windows x86_64.
* `unsafe extern "sysv64"` --- The System V ABI.
* Only available on x86_64 targets.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do clang/gcc/MSVC have attributes that correspond to our win64/sysv64?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe the answer is "kinda".

AFAIK, Microsoft's __cdecl is the same as our "win64" or "C" (and I believe clang/gcc also do the same).

I believe for "sysv64", the answer is "no" for MSVC, you cannot explicitly specify that on MSVC. It looks like clang and gcc use the attribute sysv_abi.

Are you suggesting that we should be more explicit about these equivalences?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AFAIK, Microsoft's __cdecl is the same as our "win64" or "C"

That's just a consequence of "C" being "win64" for them, right?

Do clang/gcc support explicitly using the win64 ABI somehow? That would be the most direct equivalent.

Are you suggesting that we should be more explicit about these equivalences?

We're very explicit about it in some cases but not others. That seemed odd.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's truer to say that __cdecl, __fastcall, etc is ignored outside of x86_32. I don't believe MSVC has an explicit calling convention for arm64 or x86_64. It just ignores any calling convention other than __vector_call and thus uses the default. I guess you could claim that one of these ignored calling conventions is the "real" name for the calling convention on x64 or arm64 but I don't think it's particularly useful to do so.

@ehuss
Copy link
Contributor Author

ehuss commented Sep 29, 2025

OK, I pushed up a change that tries to be more consistent with showing the equivalent attributes.

My homework for investigating this:

Primary sources are:

For the translation in rustc to LLVM, there are multiple places to look:

  • AbiMapping -- This is a first canonicalization of ABIs. Most ABIs have a clear translation ("Rust" is "Rust"). Some are erased at this stage (efiapi gets translated to various other ABIs based on the target).
  • llvm::CallConv -- Converts rustc's call convention to LLVM's.
  • LLVM CallingConv.h -- LLVM's definition of the different calling conventions.
  • Clang CallingConv -- How attributes to mapped to a calling convention.
  • Clang ClangCallConvToLLVMCallConv -- Converts clang's calling convention to LLVM.

Generally I tried to make sure that clang translation to LLVM is the same as rustc's.

@ehuss ehuss marked this pull request as ready for review September 29, 2025 20:52
@rustbot rustbot added the S-waiting-on-review Status: The marked PR is awaiting review from a maintainer label Sep 29, 2025
@rustbot

This comment has been minimized.

@ehuss ehuss force-pushed the rewrite-abi-defs branch from 8da6ee3 to d0fce21 Compare October 7, 2025 21:17
@rustbot

This comment has been minimized.

ehuss added 2 commits October 7, 2025 23:57
This updates the definitions of the extern ABIs to try to make them a
little clearer as to what they mean.

This also adds new statements about the equivalence of some ABIs
to the "C" ABI.
@rustbot
Copy link
Collaborator

rustbot commented Oct 7, 2025

This PR was rebased onto a different master commit. Here's a range-diff highlighting what actually changed.

Rebasing is a normal part of keeping PRs up to date, so no action is needed—this note is just to help reviewers.

Due to changes we've recently merged discussing the default ABI of an
`extern` that doesn't specify one ("C"), the description of "Rust"
being the default ABI for functions that followed immediately after
this read as a bit odd.  Let's revise this to clarify that "Rust" is
the default ABI when `extern fn` is not used.
Some Windows API functions have an explicitly defined ABI.  We were
trying to suggest this with wording that was a bit subtle; let's spell
it out explicitly.
For each of the ABIs, we have outbound links to documents with more
details.  For most of these, we display the URL, since these URLs are
short and readable enough that it's probably more informative to just
show them as compared to trying to describe the document.  However,
the URLs are still long enough that they look better as list items, so
let's switch to doing it that way.
When using the "C" ABI, do we "match" the default ABI chosen by the
dominant C compiler for the target or do we "attempt" to match it?

Tough question.  There are believed to be some exceptions in current
behavior.

However, in the Reference, we generally state things in terms of what
the consensus is on how they should be and then note the bugs, so
let's do that here.  We'll just say that we "match" it.
@traviscross traviscross enabled auto-merge October 8, 2025 01:39
@traviscross traviscross added this pull request to the merge queue Oct 8, 2025
Merged via the queue into rust-lang:master with commit 053c511 Oct 8, 2025
5 checks passed
@rustbot rustbot removed the S-waiting-on-review Status: The marked PR is awaiting review from a maintainer label Oct 8, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Description of "aapcs" ABI seems wrong
6 participants