rust icon indicating copy to clipboard operation
rust copied to clipboard

Enable varargs support for calling conventions other than C or cdecl

Open Soveu opened this issue 2 years ago • 12 comments

This patch makes it possible to use varargs for calling conventions, which are either based on C (efiapi) or C is based on them (sysv64 and win64).

Also pinging @phlopsi, because he noticed first this oversight when writing a library for UEFI.

Soveu avatar Jun 10 '22 20:06 Soveu

Some changes occured to rustc_codegen_cranelift

cc @bjorn3

rust-highfive avatar Jun 10 '22 20:06 rust-highfive

r? @jackh726

(rust-highfive has picked a reviewer for you, use r? to override)

rust-highfive avatar Jun 10 '22 20:06 rust-highfive

:warning: Warning :warning:

rust-highfive avatar Jun 10 '22 20:06 rust-highfive

The job mingw-check failed! Check out the build log: (web) (plain)

Click to see the possible cause of the failure (guessed by this bot)
    Checking cranelift-frontend v0.83.0
    Checking cranelift-native v0.83.0
    Checking cranelift-object v0.83.0
    Checking rustc_codegen_cranelift v0.1.0 (/checkout/compiler/rustc_codegen_cranelift)
error[E0599]: no method named `support_varargs` found for enum `rustc_target::spec::abi::Abi` in the current scope
   --> src/abi/mod.rs:490:28
    |
490 |             if !fn_sig.abi.support_varargs() {
    |                            ^^^^^^^^^^^^^^^ help: there is an associated function with a similar name: `supports_varargs`
For more information about this error, try `rustc --explain E0599`.
error: could not compile `rustc_codegen_cranelift` due to previous error
Build completed unsuccessfully in 0:03:59

rust-log-analyzer avatar Jun 10 '22 21:06 rust-log-analyzer

I'm going to ping @rust-lang/lang and @rust-lang/compiler for this, since it's technically an insta-stable language feature.

jackh726 avatar Jun 26 '22 19:06 jackh726

I think this needs lang FCP, maybe compiler FCP too.

jackh726 avatar Jun 26 '22 19:06 jackh726

Does this need to go in insta-stable?

My default lang-hat answer for these things is that it should go in feature-gated first, so it just needs a compiler r+ right now and stabilization is a question for later.

scottmcm avatar Jun 26 '22 20:06 scottmcm

@Soveu I think at this point we want this change to be guarded by a feature gate.

You can see documentation in the rustc-dev-guide on how to introduce and use such guards in the rustc source code. Specifically:

  • https://rustc-dev-guide.rust-lang.org/feature-gates.html
  • https://rustc-dev-guide.rust-lang.org/implementing_new_features.html#stability-in-code

@jackh726 has agreed to help mentor with whatever help you need to make the necessary changes here.

pnkfelix avatar Jun 30 '22 14:06 pnkfelix

While I have still access to my laptop that can definitely build rustc, I think I made most of the changes required for proper feature gating.

A tracking issue still has to be created, at least that can be done from any device. Is a full RFC needed for this change though?

Soveu avatar Jun 30 '22 19:06 Soveu

Doesn't need an RFC (certainly not for unstable - someone might ask for it for stabilization, but I doubt it)

From quickly skimming, I think I'd like to see each of the new abis in a test under the feature and without the feature.

jackh726 avatar Jul 01 '22 00:07 jackh726

This PR has been discussed by T-compiler on Zulip (meetings' notes). I think I can switch the labels. Please feel free to switch back when a new review is needed, thanks.

@rustbot author

apiraino avatar Jul 06 '22 08:07 apiraino

Soooo, I was pretty busy last week or two, but I should have some time this weekend.

Soveu avatar Jul 10 '22 20:07 Soveu

@rustbot review

Soveu avatar Aug 07 '22 08:08 Soveu

@jackh726 Isn't squash done on merge or something like that? @rustbot review

Soveu avatar Aug 08 '22 05:08 Soveu

Isn't squash done on merge or something like that?

We don't squash on merge.

estebank avatar Aug 08 '22 09:08 estebank

Is that kind of squash what was expected? It had to be force-pushed, because, well, it overwrites the history. Creating another branch would mean creating another PR.

Soveu avatar Aug 08 '22 13:08 Soveu

Yes, squashing and force pushing as the last step of a PR review that might have had some "unnecessary" history is best practice. We don't auto-squash because in some cases the PR will contain commits that tell a story, and we want to keep those (but that's more around independent feature work that needs to land together, not the back and forth with the reviewer).

estebank avatar Aug 08 '22 15:08 estebank

@jackh726 ?

Soveu avatar Aug 16 '22 16:08 Soveu

@bors r+

jackh726 avatar Aug 16 '22 18:08 jackh726

:pushpin: Commit c451c9faf43a43c08469db546ee4ced5799c2ec1 has been approved by jackh726

It is now in the queue for this repository.

bors avatar Aug 16 '22 18:08 bors

If you changed the content of the message in compiler code, it also should be changed in .stderr I think.

Soveu avatar Aug 16 '22 18:08 Soveu

Gah you're right. I'll have to bless it later.

@bors r-

jackh726 avatar Aug 16 '22 18:08 jackh726

The job x86_64-gnu-llvm-13 failed! Check out the build log: (web) (plain)

Click to see the possible cause of the failure (guessed by this bot)
........................................................................................ 1056/13392
........................................................................................ 1144/13392
........................................................................................ 1232/13392
..................................................i..................................... 1320/13392
...........................................F......FF.................................... 1408/13392
........................................................................................ 1584/13392
........................................................................................ 1672/13392
...........................................................i......ii.................... 1760/13392
........................................................................................ 1848/13392
---
........................................................................................ 13376/13392
................
failures:

---- [ui] src/test/ui/c-variadic/feature-gate-extended_varargs_abi_support.rs stdout ----


- error[E0658]: using different calling convention than C or cdecl for varargs functions is unstable
+ error[E0658]: using different calling convention than `C` or `cdecl` for varargs functions is unstable
2   --> $DIR/feature-gate-extended_varargs_abi_support.rs:3:14
3    |
4 LL | fn efiapi(f: extern "efiapi" fn(usize, ...)) {
7    = note: see issue #100189 <https://github.com/rust-lang/rust/issues/100189> for more information
7    = note: see issue #100189 <https://github.com/rust-lang/rust/issues/100189> for more information
8    = help: add `#![feature(extended_varargs_abi_support)]` to the crate attributes to enable
9 
- error[E0045]: C-variadic function must have a compatible calling convention, like C or cdecl
Some tests failed in compiletest suite=ui mode=ui host=x86_64-unknown-linux-gnu target=x86_64-unknown-linux-gnu
+ error[E0045]: C-variadic function must have a compatible calling convention, like `C` or `cdecl`
11   --> $DIR/feature-gate-extended_varargs_abi_support.rs:3:14
12    |
13 LL | fn efiapi(f: extern "efiapi" fn(usize, ...)) {
14    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ C-variadic function must have a compatible calling convention
15 
15 
- error[E0658]: using different calling convention than C or cdecl for varargs functions is unstable
+ error[E0658]: using different calling convention than `C` or `cdecl` for varargs functions is unstable
17   --> $DIR/feature-gate-extended_varargs_abi_support.rs:8:12
18    |
19 LL | fn sysv(f: extern "sysv64" fn(usize, ...)) {
22    = note: see issue #100189 <https://github.com/rust-lang/rust/issues/100189> for more information
22    = note: see issue #100189 <https://github.com/rust-lang/rust/issues/100189> for more information
23    = help: add `#![feature(extended_varargs_abi_support)]` to the crate attributes to enable
24 
- error[E0045]: C-variadic function must have a compatible calling convention, like C or cdecl
+ error[E0045]: C-variadic function must have a compatible calling convention, like `C` or `cdecl`
26   --> $DIR/feature-gate-extended_varargs_abi_support.rs:8:12
27    |
28 LL | fn sysv(f: extern "sysv64" fn(usize, ...)) {
29    |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ C-variadic function must have a compatible calling convention
30 
30 
- error[E0658]: using different calling convention than C or cdecl for varargs functions is unstable
+ error[E0658]: using different calling convention than `C` or `cdecl` for varargs functions is unstable
32   --> $DIR/feature-gate-extended_varargs_abi_support.rs:13:11
33    |
34 LL | fn win(f: extern "win64" fn(usize, ...)) {
37    = note: see issue #100189 <https://github.com/rust-lang/rust/issues/100189> for more information
37    = note: see issue #100189 <https://github.com/rust-lang/rust/issues/100189> for more information
38    = help: add `#![feature(extended_varargs_abi_support)]` to the crate attributes to enable
39 
- error[E0045]: C-variadic function must have a compatible calling convention, like C or cdecl
+ error[E0045]: C-variadic function must have a compatible calling convention, like `C` or `cdecl`
41   --> $DIR/feature-gate-extended_varargs_abi_support.rs:13:11
42    |
43 LL | fn win(f: extern "win64" fn(usize, ...)) {

The actual stderr differed from the expected stderr.
The actual stderr differed from the expected stderr.
Actual stderr saved to /checkout/obj/build/x86_64-unknown-linux-gnu/test/ui/c-variadic/feature-gate-extended_varargs_abi_support/feature-gate-extended_varargs_abi_support.stderr
To update references, rerun the tests and pass the `--bless` flag
To only update this specific test, also pass `--test-args c-variadic/feature-gate-extended_varargs_abi_support.rs`
error: 1 errors occurred comparing output.
status: exit status: 1
status: exit status: 1
command: "/checkout/obj/build/x86_64-unknown-linux-gnu/stage2/bin/rustc" "/checkout/src/test/ui/c-variadic/feature-gate-extended_varargs_abi_support.rs" "-Zthreads=1" "--target=x86_64-unknown-linux-gnu" "--error-format" "json" "--json" "future-incompat" "-Ccodegen-units=1" "-Zui-testing" "-Zdeduplicate-diagnostics=no" "-Cstrip=debuginfo" "--emit" "metadata" "-C" "prefer-dynamic" "--out-dir" "/checkout/obj/build/x86_64-unknown-linux-gnu/test/ui/c-variadic/feature-gate-extended_varargs_abi_support" "-A" "unused" "-Crpath" "-Cdebuginfo=0" "-Lnative=/checkout/obj/build/x86_64-unknown-linux-gnu/native/rust-test-helpers" "-L" "/checkout/obj/build/x86_64-unknown-linux-gnu/test/ui/c-variadic/feature-gate-extended_varargs_abi_support/auxiliary"
stdout: none
--- stderr -------------------------------
error[E0658]: using different calling convention than `C` or `cdecl` for varargs functions is unstable
  --> /checkout/src/test/ui/c-variadic/feature-gate-extended_varargs_abi_support.rs:3:14
   |
LL | fn efiapi(f: extern "efiapi" fn(usize, ...)) {
   |
   = note: see issue #100189 <https://github.com/rust-lang/rust/issues/100189> for more information
   = note: see issue #100189 <https://github.com/rust-lang/rust/issues/100189> for more information
   = help: add `#![feature(extended_varargs_abi_support)]` to the crate attributes to enable

error[E0045]: C-variadic function must have a compatible calling convention, like `C` or `cdecl`
  --> /checkout/src/test/ui/c-variadic/feature-gate-extended_varargs_abi_support.rs:3:14
   |
LL | fn efiapi(f: extern "efiapi" fn(usize, ...)) {
   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ C-variadic function must have a compatible calling convention

error[E0658]: using different calling convention than `C` or `cdecl` for varargs functions is unstable
  --> /checkout/src/test/ui/c-variadic/feature-gate-extended_varargs_abi_support.rs:8:12
   |
LL | fn sysv(f: extern "sysv64" fn(usize, ...)) {
   |
   = note: see issue #100189 <https://github.com/rust-lang/rust/issues/100189> for more information
   = note: see issue #100189 <https://github.com/rust-lang/rust/issues/100189> for more information
   = help: add `#![feature(extended_varargs_abi_support)]` to the crate attributes to enable

error[E0045]: C-variadic function must have a compatible calling convention, like `C` or `cdecl`
  --> /checkout/src/test/ui/c-variadic/feature-gate-extended_varargs_abi_support.rs:8:12
   |
LL | fn sysv(f: extern "sysv64" fn(usize, ...)) {
   |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ C-variadic function must have a compatible calling convention

error[E0658]: using different calling convention than `C` or `cdecl` for varargs functions is unstable
  --> /checkout/src/test/ui/c-variadic/feature-gate-extended_varargs_abi_support.rs:13:11
   |
LL | fn win(f: extern "win64" fn(usize, ...)) {
   |
   = note: see issue #100189 <https://github.com/rust-lang/rust/issues/100189> for more information
   = note: see issue #100189 <https://github.com/rust-lang/rust/issues/100189> for more information
   = help: add `#![feature(extended_varargs_abi_support)]` to the crate attributes to enable

error[E0045]: C-variadic function must have a compatible calling convention, like `C` or `cdecl`
  --> /checkout/src/test/ui/c-variadic/feature-gate-extended_varargs_abi_support.rs:13:11
   |
LL | fn win(f: extern "win64" fn(usize, ...)) {
   |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ C-variadic function must have a compatible calling convention
error: aborting due to 6 previous errors

Some errors have detailed explanations: E0045, E0658.
For more information about an error, try `rustc --explain E0045`.
For more information about an error, try `rustc --explain E0045`.
------------------------------------------


---- [ui] src/test/ui/c-variadic/variadic-ffi-1.rs stdout ----
diff of stderr:

- error[E0045]: C-variadic function must have a compatible calling convention, like C or cdecl
+ error[E0045]: C-variadic function must have a compatible calling convention, like `C` or `cdecl`
3    |
3    |
4 LL |     fn printf(_: *const u8, ...);

The actual stderr differed from the expected stderr.
The actual stderr differed from the expected stderr.
Actual stderr saved to /checkout/obj/build/x86_64-unknown-linux-gnu/test/ui/c-variadic/variadic-ffi-1/variadic-ffi-1.stderr
To only update this specific test, also pass `--test-args c-variadic/variadic-ffi-1.rs`

error: 1 errors occurred comparing output.
status: exit status: 1
status: exit status: 1
command: "/checkout/obj/build/x86_64-unknown-linux-gnu/stage2/bin/rustc" "/checkout/src/test/ui/c-variadic/variadic-ffi-1.rs" "-Zthreads=1" "--error-format" "json" "--json" "future-incompat" "-Ccodegen-units=1" "-Zui-testing" "-Zdeduplicate-diagnostics=no" "-Cstrip=debuginfo" "--emit" "metadata" "-C" "prefer-dynamic" "--out-dir" "/checkout/obj/build/x86_64-unknown-linux-gnu/test/ui/c-variadic/variadic-ffi-1" "-A" "unused" "-Crpath" "-Cdebuginfo=0" "-Lnative=/checkout/obj/build/x86_64-unknown-linux-gnu/native/rust-test-helpers" "--target=i686-pc-windows-msvc" "--crate-type=rlib" "-L" "/checkout/obj/build/x86_64-unknown-linux-gnu/test/ui/c-variadic/variadic-ffi-1/auxiliary"
stdout: none
--- stderr -------------------------------
error[E0045]: C-variadic function must have a compatible calling convention, like `C` or `cdecl`
   |
   |
LL |     fn printf(_: *const u8, ...);
   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ C-variadic function must have a compatible calling convention
error[E0060]: this function takes at least 2 arguments but 0 arguments were supplied
  --> /checkout/src/test/ui/c-variadic/variadic-ffi-1.rs:22:9
   |
   |
LL |         foo(); //~ ERROR this function takes at least 2 arguments but 0 arguments were supplied
   |         ^^^-- two arguments of type `isize` and `u8` are missing
note: function defined here
  --> /checkout/src/test/ui/c-variadic/variadic-ffi-1.rs:15:8
   |
   |
LL |     fn foo(f: isize, x: u8, ...);
help: provide the arguments
   |
   |
LL |         foo(/* isize */, /* u8 */); //~ ERROR this function takes at least 2 arguments but 0 arguments were supplied

error[E0060]: this function takes at least 2 arguments but 1 argument was supplied
  --> /checkout/src/test/ui/c-variadic/variadic-ffi-1.rs:23:9
   |
   |
LL |         foo(1); //~ ERROR this function takes at least 2 arguments but 1 argument was supplied
   |         ^^^--- an argument of type `u8` is missing
note: function defined here
  --> /checkout/src/test/ui/c-variadic/variadic-ffi-1.rs:15:8
   |
   |
LL |     fn foo(f: isize, x: u8, ...);
help: provide the argument
   |
   |
LL |         foo(1, /* u8 */); //~ ERROR this function takes at least 2 arguments but 1 argument was supplied

error[E0308]: mismatched types
  --> /checkout/src/test/ui/c-variadic/variadic-ffi-1.rs:25:56
   |
   |
LL |         let x: unsafe extern "C" fn(f: isize, x: u8) = foo; //~ ERROR mismatched types
   |                -------------------------------------   ^^^ expected non-variadic fn, found variadic function
   |                expected due to this
   |
   |
   = note: expected fn pointer `unsafe extern "C" fn(_, _)`
                 found fn item `unsafe extern "C" fn(_, _, ...) {foo}`
error[E0308]: mismatched types
  --> /checkout/src/test/ui/c-variadic/variadic-ffi-1.rs:26:54
   |
   |
LL |         let y: extern "C" fn(f: isize, x: u8, ...) = bar; //~ ERROR mismatched types
   |                -----------------------------------   ^^^ expected variadic fn, found non-variadic function
   |                expected due to this
   |
   = note: expected fn pointer `extern "C" fn(_, _, ...)`
   = note: expected fn pointer `extern "C" fn(_, _, ...)`
                 found fn item `extern "C" fn(_, _) {bar}`

error[E0617]: can't pass `f32` to variadic function
   |
   |
LL |         foo(1, 2, 3f32); //~ ERROR can't pass
   |                   ^^^^ help: cast the value to `c_double`: `3f32 as c_double`

error[E0617]: can't pass `bool` to variadic function
   |
   |
LL |         foo(1, 2, true); //~ ERROR can't pass
   |                   ^^^^ help: cast the value to `c_int`: `true as c_int`

error[E0617]: can't pass `i8` to variadic function
   |
   |
LL |         foo(1, 2, 1i8); //~ ERROR can't pass
   |                   ^^^ help: cast the value to `c_int`: `1i8 as c_int`

error[E0617]: can't pass `u8` to variadic function
   |
   |
LL |         foo(1, 2, 1u8); //~ ERROR can't pass
   |                   ^^^ help: cast the value to `c_uint`: `1u8 as c_uint`

error[E0617]: can't pass `i16` to variadic function
   |
   |
LL |         foo(1, 2, 1i16); //~ ERROR can't pass
   |                   ^^^^ help: cast the value to `c_int`: `1i16 as c_int`

error[E0617]: can't pass `u16` to variadic function
   |
   |
LL |         foo(1, 2, 1u16); //~ ERROR can't pass
   |                   ^^^^ help: cast the value to `c_uint`: `1u16 as c_uint`
error: aborting due to 11 previous errors

Some errors have detailed explanations: E0045, E0060, E0308, E0617.
For more information about an error, try `rustc --explain E0045`.
For more information about an error, try `rustc --explain E0045`.
------------------------------------------


---- [ui] src/test/ui/c-variadic/variadic-ffi-2.rs stdout ----
diff of stderr:

- error[E0045]: C-variadic function must have a compatible calling convention, like C, cdecl, win64, sysv64 or efiapi
+ error[E0045]: C-variadic function must have a compatible calling convention, like `C`, `cdecl`, `win64`, `sysv64` or `efiapi`
3    |
3    |
4 LL | fn baz(f: extern "stdcall" fn(usize, ...)) {

The actual stderr differed from the expected stderr.
The actual stderr differed from the expected stderr.
Actual stderr saved to /checkout/obj/build/x86_64-unknown-linux-gnu/test/ui/c-variadic/variadic-ffi-2/variadic-ffi-2.stderr
To only update this specific test, also pass `--test-args c-variadic/variadic-ffi-2.rs`

error: 1 errors occurred comparing output.
status: exit status: 1
status: exit status: 1
command: "/checkout/obj/build/x86_64-unknown-linux-gnu/stage2/bin/rustc" "/checkout/src/test/ui/c-variadic/variadic-ffi-2.rs" "-Zthreads=1" "--target=x86_64-unknown-linux-gnu" "--error-format" "json" "--json" "future-incompat" "-Ccodegen-units=1" "-Zui-testing" "-Zdeduplicate-diagnostics=no" "-Cstrip=debuginfo" "--emit" "metadata" "-C" "prefer-dynamic" "--out-dir" "/checkout/obj/build/x86_64-unknown-linux-gnu/test/ui/c-variadic/variadic-ffi-2" "-A" "unused" "-Crpath" "-Cdebuginfo=0" "-Lnative=/checkout/obj/build/x86_64-unknown-linux-gnu/native/rust-test-helpers" "-L" "/checkout/obj/build/x86_64-unknown-linux-gnu/test/ui/c-variadic/variadic-ffi-2/auxiliary"
stdout: none
--- stderr -------------------------------
error[E0045]: C-variadic function must have a compatible calling convention, like `C`, `cdecl`, `win64`, `sysv64` or `efiapi`
   |
   |
LL | fn baz(f: extern "stdcall" fn(usize, ...)) {
   |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ C-variadic function must have a compatible calling convention
error: aborting due to previous error

For more information about this error, try `rustc --explain E0045`.
------------------------------------------
------------------------------------------


---- [ui] src/test/ui/error-codes/E0045.rs stdout ----
diff of stderr:

- error[E0045]: C-variadic function must have a compatible calling convention, like C or cdecl
+ error[E0045]: C-variadic function must have a compatible calling convention, like `C` or `cdecl`
2   --> $DIR/E0045.rs:1:17
3    |
4 LL | extern "Rust" { fn foo(x: u8, ...); }

The actual stderr differed from the expected stderr.
Actual stderr saved to /checkout/obj/build/x86_64-unknown-linux-gnu/test/ui/error-codes/E0045/E0045.stderr
To update references, rerun the tests and pass the `--bless` flag
To update references, rerun the tests and pass the `--bless` flag
To only update this specific test, also pass `--test-args error-codes/E0045.rs`

error: 1 errors occurred comparing output.
status: exit status: 1
command: "/checkout/obj/build/x86_64-unknown-linux-gnu/stage2/bin/rustc" "/checkout/src/test/ui/error-codes/E0045.rs" "-Zthreads=1" "--target=x86_64-unknown-linux-gnu" "--error-format" "json" "--json" "future-incompat" "-Ccodegen-units=1" "-Zui-testing" "-Zdeduplicate-diagnostics=no" "-Cstrip=debuginfo" "--emit" "metadata" "-C" "prefer-dynamic" "--out-dir" "/checkout/obj/build/x86_64-unknown-linux-gnu/test/ui/error-codes/E0045" "-A" "unused" "-Crpath" "-Cdebuginfo=0" "-Lnative=/checkout/obj/build/x86_64-unknown-linux-gnu/native/rust-test-helpers" "-L" "/checkout/obj/build/x86_64-unknown-linux-gnu/test/ui/error-codes/E0045/auxiliary"
stdout: none
--- stderr -------------------------------
error[E0045]: C-variadic function must have a compatible calling convention, like `C` or `cdecl`
   |
   |
LL | extern "Rust" { fn foo(x: u8, ...); }   //~ ERROR E0045
   |                 ^^^^^^^^^^^^^^^^^^^ C-variadic function must have a compatible calling convention
error: aborting due to previous error

For more information about this error, try `rustc --explain E0045`.
------------------------------------------

rust-log-analyzer avatar Aug 16 '22 19:08 rust-log-analyzer

:umbrella: The latest upstream changes (presumably #102306) made this pull request unmergeable. Please resolve the merge conflicts.

bors avatar Sep 27 '22 13:09 bors

Updated message and rebased.

@bors r+

jackh726 avatar Oct 23 '22 23:10 jackh726

:pushpin: Commit de78c32b854d6f76167bb6fcf76fc2760c8b7d2a has been approved by jackh726

It is now in the queue for this repository.

bors avatar Oct 23 '22 23:10 bors