c-variadic: error when we can't guarantee that the backend does the right thing#152935
c-variadic: error when we can't guarantee that the backend does the right thing#152935folkertdev wants to merge 1 commit intorust-lang:mainfrom
Conversation
|
|
This comment has been minimized.
This comment has been minimized.
93d17a2 to
3b96e18
Compare
| @@ -1186,9 +1186,10 @@ pub(super) fn emit_va_arg<'ll, 'tcx>( | |||
| // Clang uses the LLVM implementation for these architectures. | |||
There was a problem hiding this comment.
Is this "clang does it so it's probably fine" or "people familiar with the target have confirmed it's fine"?
There was a problem hiding this comment.
It is "clang does this so we're matching the de-facto standard C compiler that rust code would interact with". We could pull that implementation into rustc as well if you prefer. I've traced how this implementation is picked here https://github.com/rust-lang/rust/pull/150831/changes#r2673777819.
The mips case right above will be handled by #152576.
There was a problem hiding this comment.
We could pull that implementation into rustc as well if you prefer.
Happy to leave that choice to you.^^ It is very strange to me that clang mostly does not use the LLVM impl here, given that they are part of the same project, so this is all a bit confusing.
There was a problem hiding this comment.
Pinging some target maintainers:
@jonathanpallant @Patryk27 @glaubitz @ricky26
apparently msp430-none-elf does not have a target maintainer. For m68k I can't get programs to link (some incorrect relocation issue, might be an LLVM problem).
Can you confirm that this test (with your target) works?
./x test tests/run-make/c-link-to-rust-va-list-fn --target mipsel-unknown-linux-gnu
this likely needs some sort of config in bootstrap.toml, I have some variations on
[target.mips64-unknown-linux-gnuabi64]
runner = "qemu-mips64 -L /usr/mips64-linux-gnuabi64"
[target.mipsel-unknown-linux-gnu]
runner = "qemu-mipsel -cpu 24Kf -L /usr/mipsel-linux-gnu"
[target.mips-unknown-linux-gnu]
runner = "qemu-mips -L /usr/mips-linux-gnu"If we don't get any response here, it's probably safer to exclude these targets from stabilization for now, because looking at it again, I think this implementation is also a fallback in clang/llvm so there is a good chance that it's actually untested.
There was a problem hiding this comment.
For m68k I can't get programs to link (some incorrect relocation issue, might be an LLVM problem).
Yes, it's a known bug, see: llvm/llvm-project#181481
There was a problem hiding this comment.
It seems that that test is not applicable to AVR (it's a non-std target), but in general the AVR backend for LLVM implements variadics:
... and we strive to be compatible with avr-gcc, so I'd expect things to just-work.
There was a problem hiding this comment.
We're hesitant with accepting targets because the LLVM va_arg implementation is known to miscompile programs on many platforms. In large part that is because a correct implementation would require layout information that LLVM just won't have. Hence, for many targets the actual logic is implemented in clang and we replicate that logic in rustc.
I just tried this locally, compilation still fails but it gets far enough along to emit these errors:
error[E0277]: the trait bound `i16: VaArgSafe` is not satisfied
--> checkrust.rs:123:27
|
123 | continue_if!(ap.arg::<c_int>() == 4);
| --- ^^^^^ the nightly-only, unstable trait `VaArgSafe` is not implemented for `i16`
| |
| required by a bound introduced by this call
|
= help: the following other types implement trait `VaArgSafe`:
f64
i32
i64
isize
u32
u64
usize
I suppose this really should work, and we're currently implicitly assuming that c_int is i32.
What types implement VaArgSafe is based on section 7.16.1 of the C23 spec
If type is not compatible with the type of the actual next argument (as promoted according to the default argument promotions), the behavior is undefined
Our reading is that, on most targets, it is UB to read an i16 because it is incompatible with what was passed (even if an i16 was passed, it has been promoted to c_int (we implicitly assume this is i32) through the default argument promotions).
I'll make a separate PR to fix that and hopefully we can figure out some approach to testing avr-none there too.
| // > 2×XLEN-bit alignment and size at most 2×XLEN bits like `long long`, | ||
| // > `unsigned long long` and `double` to have 4-byte alignment. This | ||
| // > behavior may be changed when RV32E/ILP32E is ratified. | ||
| RiscV32 if *abi == Abi::Ilp32e => false, |
There was a problem hiding this comment.
It's concerning to use the target.abi field here which is usually just informational -- it controls cfg(target_abi), it doesn't control how we configure LLVM.
3b96e18 to
b29e566
Compare
tracking issue: #44930
r? workingjubilee
as discussed in #t-lang > stabilizing `c_variadic`, display an error when we can't guarantee that the codegen backend (only LLVM is supported at the moment) does the right thing.