From 40478709a9d3f536f0269d992953a2c40d005cef Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Tue, 16 Sep 2025 20:23:04 -0700 Subject: [PATCH 1/6] Rework the definitions of the extern ABIs 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. --- src/items/external-blocks.md | 46 +++++++++++++++++++++++++++++------- 1 file changed, 37 insertions(+), 9 deletions(-) diff --git a/src/items/external-blocks.md b/src/items/external-blocks.md index 25a265350..4ec8b15de 100644 --- a/src/items/external-blocks.md +++ b/src/items/external-blocks.md @@ -118,13 +118,16 @@ r[items.extern.abi.standard] The following ABI strings are supported on all platforms: r[items.extern.abi.rust] -* `unsafe extern "Rust"` --- The default ABI when you write a normal `fn foo()` in any Rust code. +* `unsafe extern "Rust"` --- The native calling convention for Rust functions and closures. This is the default when the function's ABI is not specified. The Rust ABI offers no stability guarantees. 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. r[items.extern.abi.system] -* `unsafe extern "system"` --- Usually the same as `extern "C"`, except on Win32, in which case it's `"stdcall"`, or what you should use to link to the Windows API itself. +* `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 attempting to link Windows API functions that don't otherwise use a different ABI. r[items.extern.abi.unwind] * `extern "C-unwind"` and `extern "system-unwind"` --- Identical to `"C"` and `"system"`, respectively, but with [different behavior][unwind-behavior] when the callee unwinds (by panicking or throwing a C++ style exception). @@ -133,33 +136,57 @@ r[items.extern.abi.platform] There are also some platform-specific ABI strings: 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. * Only available on x86_32 targets. + > [!NOTE] + > See and for more information. + 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. * Only available on x86_32 targets. + > [!NOTE] + > See and for more information. + r[items.extern.abi.win64] -* `unsafe extern "win64"` --- The default for C code on x86_64 Windows. +* `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 and 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. + * "sysv64" is the same as the "C" ABI on non-Windows x86_64 targets. + + > [!NOTE] + > See or for more information. r[items.extern.abi.aapcs] -* `unsafe extern "aapcs"` --- The default for ARM. +* `unsafe extern "aapcs"` --- The soft-float ABI for ARM. * Only available on ARM32 targets. + * "aapcs" is the same as the "C" ABI on soft-float ARM32. + + > [!NOTE] + > See [Arm Procedure Call Standard](https://developer.arm.com/documentation/107656/0101/Getting-started-with-Armv8-M-based-systems/Procedure-Call-Standard-for-Arm-Architecture--AAPCS-) for more information. r[items.extern.abi.fastcall] * `unsafe extern "fastcall"` --- The `fastcall` ABI --- corresponds to MSVC's `__fastcall` and GCC and clang's `__attribute__((fastcall))`. * Only available on x86_32 targets. + > [!NOTE] + > See and for more information. + r[items.extern.abi.thiscall] -* `unsafe extern "thiscall"` --- The default for C++ member functions on x86_32 MSVC --- corresponds to MSVC's `__thiscall` and GCC and clang's `__attribute__((thiscall))`. +* `unsafe extern "thiscall"` --- The calling convention typically used on C++ class member functions on x86_32 MSVC --- corresponds to MSVC's `__thiscall` and GCC and clang's `__attribute__((thiscall))`. * Only available on x86_32 targets. + > [!NOTE] + > See and for more information. + r[items.extern.abi.efiapi] * `unsafe extern "efiapi"` --- The ABI used for [UEFI] functions. * Only available on x86 and ARM targets (32bit and 64bit). @@ -494,4 +521,5 @@ restrictions as [regular function parameters]. [statics]: static-items.md [unwind-behavior]: functions.md#unwinding [value namespace]: ../names/namespaces.md +[win32 api]: https://learn.microsoft.com/en-us/windows/win32/api/ [`link_ordinal`]: items.extern.attributes.link_ordinal From e8969f768ad908bfe34f3c316f6f1207f0723b22 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Mon, 29 Sep 2025 13:15:01 -0700 Subject: [PATCH 2/6] Add more ABI correspondence with other compilers --- src/items/external-blocks.md | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/items/external-blocks.md b/src/items/external-blocks.md index 4ec8b15de..3a7317b1d 100644 --- a/src/items/external-blocks.md +++ b/src/items/external-blocks.md @@ -138,6 +138,7 @@ There are also some platform-specific ABI strings: r[items.extern.abi.cdecl] * `unsafe extern "cdecl"` --- The calling convention typically used with x86_32 C code. * Only available on x86_32 targets. + * Corresponds to MSVC's `__cdecl` and GCC and clang's `__attribute__((cdecl))`. > [!NOTE] > See and for more information. @@ -145,6 +146,7 @@ r[items.extern.abi.cdecl] r[items.extern.abi.stdcall] * `unsafe extern "stdcall"` --- The calling convention typically used by the [Win32 API] on x86_32. * Only available on x86_32 targets. + * Corresponds to MSVC's `__stdcall` and GCC and clang's `__attribute__((stdcall))`. > [!NOTE] > See and for more information. @@ -153,6 +155,7 @@ r[items.extern.abi.win64] * `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. + * Corresponds to GCC and clang's `__attribute__((ms_abi))`. > [!NOTE] > See and for more information. @@ -161,6 +164,7 @@ r[items.extern.abi.sysv64] * `unsafe extern "sysv64"` --- The System V ABI. * Only available on x86_64 targets. * "sysv64" is the same as the "C" ABI on non-Windows x86_64 targets. + * Corresponds to GCC and clang's `__attribute__((sysv_abi))`. > [!NOTE] > See or for more information. @@ -169,20 +173,23 @@ r[items.extern.abi.aapcs] * `unsafe extern "aapcs"` --- The soft-float ABI for ARM. * Only available on ARM32 targets. * "aapcs" is the same as the "C" ABI on soft-float ARM32. + * Corresponds to clang's `__attribute__((pcs("aapcs")))`. > [!NOTE] > See [Arm Procedure Call Standard](https://developer.arm.com/documentation/107656/0101/Getting-started-with-Armv8-M-based-systems/Procedure-Call-Standard-for-Arm-Architecture--AAPCS-) for more information. r[items.extern.abi.fastcall] -* `unsafe extern "fastcall"` --- The `fastcall` ABI --- corresponds to MSVC's `__fastcall` and GCC and clang's `__attribute__((fastcall))`. +* `unsafe extern "fastcall"` --- A "fast" variant of stdcall that passes some arguments in registers. * Only available on x86_32 targets. + * Corresponds to MSVC's `__fastcall` and GCC and clang's `__attribute__((fastcall))`. > [!NOTE] > See and for more information. r[items.extern.abi.thiscall] -* `unsafe extern "thiscall"` --- The calling convention typically used on C++ class member functions on x86_32 MSVC --- corresponds to MSVC's `__thiscall` and GCC and clang's `__attribute__((thiscall))`. +* `unsafe extern "thiscall"` --- The calling convention typically used on C++ class member functions on x86_32 MSVC. * Only available on x86_32 targets. + * Corresponds to MSVC's `__thiscall` and GCC and clang's `__attribute__((thiscall))`. > [!NOTE] > See and for more information. From a78b6c2158bbe220958aa6b775213c289d44ba10 Mon Sep 17 00:00:00 2001 From: Travis Cross Date: Wed, 8 Oct 2025 00:18:25 +0000 Subject: [PATCH 3/6] Clarify default when not using `extern fn` 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. --- src/items/external-blocks.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/items/external-blocks.md b/src/items/external-blocks.md index 3a7317b1d..7c58707ae 100644 --- a/src/items/external-blocks.md +++ b/src/items/external-blocks.md @@ -118,7 +118,7 @@ r[items.extern.abi.standard] The following ABI strings are supported on all platforms: r[items.extern.abi.rust] -* `unsafe extern "Rust"` --- The native calling convention for Rust functions and closures. This is the default when the function's ABI is not specified. The Rust ABI offers no stability guarantees. +* `unsafe extern "Rust"` --- The native calling convention for Rust functions and closures. This is the default when a function is declared without using [`extern fn`]. The Rust ABI offers no stability guarantees. r[items.extern.abi.c] * `unsafe extern "C"` --- The "C" ABI attempts to match the default ABI chosen by the dominant C compiler for the target. @@ -519,6 +519,7 @@ restrictions as [regular function parameters]. [WebAssembly module]: https://webassembly.github.io/spec/core/syntax/modules.html [`bundle` documentation for rustc]: ../../rustc/command-line-arguments.html#linking-modifiers-bundle [`dylib` versus `raw-dylib`]: #dylib-versus-raw-dylib +[`extern fn`]: items.fn.extern [`unsafe` context]: ../unsafe-keyword.md [`verbatim` documentation for rustc]: ../../rustc/command-line-arguments.html#linking-modifiers-verbatim [`whole-archive` documentation for rustc]: ../../rustc/command-line-arguments.html#linking-modifiers-whole-archive From 5ef9f4f4f7cea61981383be824e423c97a469e55 Mon Sep 17 00:00:00 2001 From: Travis Cross Date: Wed, 8 Oct 2025 00:25:37 +0000 Subject: [PATCH 4/6] Clarify about Windows functions with explicit ABI 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. --- src/items/external-blocks.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/items/external-blocks.md b/src/items/external-blocks.md index 7c58707ae..2fb035be6 100644 --- a/src/items/external-blocks.md +++ b/src/items/external-blocks.md @@ -127,7 +127,7 @@ r[items.extern.abi.system] * `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 attempting to link Windows API functions that don't otherwise use a different ABI. + > As the correct underlying ABI on Windows is target-specific, it's best to use `extern "system"` when attempting to link Windows API functions that don't use an explicitly defined ABI. r[items.extern.abi.unwind] * `extern "C-unwind"` and `extern "system-unwind"` --- Identical to `"C"` and `"system"`, respectively, but with [different behavior][unwind-behavior] when the callee unwinds (by panicking or throwing a C++ style exception). From 45de0c51bc76792436f9d7322f3077ca73e85eef Mon Sep 17 00:00:00 2001 From: Travis Cross Date: Wed, 8 Oct 2025 00:34:55 +0000 Subject: [PATCH 5/6] Convert ABI "details" links to lists 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. --- src/items/external-blocks.md | 34 +++++++++++++++++++++++++++------- 1 file changed, 27 insertions(+), 7 deletions(-) diff --git a/src/items/external-blocks.md b/src/items/external-blocks.md index 2fb035be6..5be564946 100644 --- a/src/items/external-blocks.md +++ b/src/items/external-blocks.md @@ -141,7 +141,10 @@ r[items.extern.abi.cdecl] * Corresponds to MSVC's `__cdecl` and GCC and clang's `__attribute__((cdecl))`. > [!NOTE] - > See and for more information. + > For details, see: + > + > - + > - r[items.extern.abi.stdcall] * `unsafe extern "stdcall"` --- The calling convention typically used by the [Win32 API] on x86_32. @@ -149,7 +152,10 @@ r[items.extern.abi.stdcall] * Corresponds to MSVC's `__stdcall` and GCC and clang's `__attribute__((stdcall))`. > [!NOTE] - > See and for more information. + > For details, see: + > + > - + > - r[items.extern.abi.win64] * `unsafe extern "win64"` --- The Windows x64 ABI. @@ -158,7 +164,10 @@ r[items.extern.abi.win64] * Corresponds to GCC and clang's `__attribute__((ms_abi))`. > [!NOTE] - > See and for more information. + > For details, see: + > + > - + > - r[items.extern.abi.sysv64] * `unsafe extern "sysv64"` --- The System V ABI. @@ -167,7 +176,10 @@ r[items.extern.abi.sysv64] * Corresponds to GCC and clang's `__attribute__((sysv_abi))`. > [!NOTE] - > See or for more information. + > For details, see: + > + > - + > - r[items.extern.abi.aapcs] * `unsafe extern "aapcs"` --- The soft-float ABI for ARM. @@ -176,7 +188,9 @@ r[items.extern.abi.aapcs] * Corresponds to clang's `__attribute__((pcs("aapcs")))`. > [!NOTE] - > See [Arm Procedure Call Standard](https://developer.arm.com/documentation/107656/0101/Getting-started-with-Armv8-M-based-systems/Procedure-Call-Standard-for-Arm-Architecture--AAPCS-) for more information. + > For details, see: + > + > - [Arm Procedure Call Standard](https://developer.arm.com/documentation/107656/0101/Getting-started-with-Armv8-M-based-systems/Procedure-Call-Standard-for-Arm-Architecture--AAPCS-) r[items.extern.abi.fastcall] * `unsafe extern "fastcall"` --- A "fast" variant of stdcall that passes some arguments in registers. @@ -184,7 +198,10 @@ r[items.extern.abi.fastcall] * Corresponds to MSVC's `__fastcall` and GCC and clang's `__attribute__((fastcall))`. > [!NOTE] - > See and for more information. + > For details, see: + > + > - + > - r[items.extern.abi.thiscall] * `unsafe extern "thiscall"` --- The calling convention typically used on C++ class member functions on x86_32 MSVC. @@ -192,7 +209,10 @@ r[items.extern.abi.thiscall] * Corresponds to MSVC's `__thiscall` and GCC and clang's `__attribute__((thiscall))`. > [!NOTE] - > See and for more information. + > For details, see: + > + > - + > - r[items.extern.abi.efiapi] * `unsafe extern "efiapi"` --- The ABI used for [UEFI] functions. From cc463db8aa2b19cef0a040da37e41634a3b1148f Mon Sep 17 00:00:00 2001 From: Travis Cross Date: Wed, 8 Oct 2025 01:34:14 +0000 Subject: [PATCH 6/6] Strengthen wording on "C" ABI 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. --- src/items/external-blocks.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/items/external-blocks.md b/src/items/external-blocks.md index 5be564946..c360189ba 100644 --- a/src/items/external-blocks.md +++ b/src/items/external-blocks.md @@ -121,7 +121,7 @@ r[items.extern.abi.rust] * `unsafe extern "Rust"` --- The native calling convention for Rust functions and closures. This is the default when a function is declared without using [`extern fn`]. The Rust ABI offers no stability guarantees. r[items.extern.abi.c] -* `unsafe extern "C"` --- The "C" ABI attempts to match the default ABI chosen by the dominant C compiler for the target. +* `unsafe extern "C"` --- The "C" ABI matches the default ABI chosen by the dominant C compiler for the target. r[items.extern.abi.system] * `unsafe extern "system"` --- This is equivalent to `extern "C"` except on Windows x86_32 where it is equivalent to `"stdcall"`.