Repository navigation
Description
This is a tracking issue for the RFC "Support defining C-compatible variadic functions in Rust" (rust-lang/rfcs#2137).
Steps:
- Implement the RFC (PR Support defining C compatible variadic functions #57760)
- Adjust documentation (see instructions on forge)
- In particular, ensure we have all the UB documented. This includes the one for ABI compatibility: in particular, caller and callee must agree on whether the function is variadic and on the number of fixed arguments.
- Stabilization PR (see instructions on forge) Stabilize c-variadic function definitions #155697
- Reference PR add c-variadic function definitions reference#2177
Unresolved questions
passing VaList to extern functions
On linux calling foo will pass a sysv64 VaList to an extern "win64" function, which might be confusing.
extern "win64" {
fn foo(_: VaList);
}
Resolved questions
Miri support
Has been added in #150601.
Continuing bikeshed on the ... syntax
There has been no discussion of a different syntax in recent years.
When implementing this feature, we will need to determine whether the compiler can provide an appropriate lifetime that prevents a VaList from outliving its corresponding variadic function.
The compiler internally determines that lifetime, to make sure that a VaList<'_> does not outlive the function that created it.
Ensure that even when this gets stabilized for regular functions, it is still rejected on const fn.
This is tested in https://github.com/rust-lang/rust/blob/main/tests/ui/parser/variadic-ffi-semantic-restrictions.rs and gives the following error:
error: functions cannot be both `const` and C-variadic
--> $DIR/variadic-ffi-semantic-restrictions.rs:33:1
|
LL | const unsafe extern "C" fn f4_1(x: isize, _: ...) {}
| ^^^^^ `const` because of this ^^^^^^ C-variadic because of this
We reject c-variadic async functions in a similar way.
Issue #125431
The VaList definition introduced in #141980 circumvents this issue.
Issue #61275
This is an issue with c-variadic calls, not with c-variadic definitons.
Issue #141618
We have some forwards-compatible ideas for how to potentially add the ABI to the type in the future. That is only required if we want to allow calling c-variadic functions with a non-system ABI. Because C only allows using the system ABI for c-variadic calls, that is unlikely to come up in practice.
What exactly are the ABI requirements around variadic calls? What are the ABI compatibility rules? Do we have to be concerned about LLVM target features affecting variadic ABI?
Variadic calls using the system ABI do not impose any additional constraints. We already handle some ABI compatibility issues using target modifiers.
Implementation history
va_arg codegen
- codegen: Fix va_list - aarch64 iOS/Windows #56599
- Properly define va_arg and va_list for aarch64-apple-darwin #78126
- implement
va_argfor x86_64 systemv #141538 - implement
va_argforpowerpc#141622 - use custom types to clarify arguments to
emit_ptr_va_arg#141623 - match clang's
va_argassembly on arm targets #144549
VaList and its layout
- libcore: Add VaList and variadic arg handling intrinsics #49878
- tests: Simplify VaList run-make test #56396
- VaList::copy should not require a mutable ref #57311
- Support defining C compatible variadic functions #57760
- core: ensure VaList passes improper_ctypes lint #58938
- Fix segfaults in release build C-variadic fns #58985
- ffi: rename VaList::copy to VaList::with_copy #59371
- Refactor C FFI variadics to more closely match their C counterparts, and add Clone implementation #59625
- Make VaListImpl<'f> invariant over the 'f lifetime #62639
- Fix intra-docs link in core::ffi::VaList #77784
- Give VaList its own home #126921
c_variadic: makeVaListabi-compatible with C #141980
other
- Allow "C-unwind" fn to have C variadics #126843
- core: VaArgSafe is an unsafe trait #126927
- use
cfg_select!to select the rightVaListImpldefinition #141361 c_variadic: Add future-incompatibility warning for...arguments without a pattern outside ofexternblocks #143619- Add
#[rustc_pass_indirectly_in_non_rustic_abis]#144529 - improve c-variadic error reporting #146165
- Improve C-variadic error messages: part 2 #146342
- c-variadic: allow c-variadic inherent and trait methods #146434
- document
core::ffi::VaArgSafe#146521 - implement
feature(c_variadic_naked_functions)#148770 - c-variadic: bpf and spirv do not support c-variadic definitions #149557
c-variadic adjacent
Activity
plietar commentedon Sep 29, 2017
I'd like to work on this, I already have some prototype
aturon commentedon Sep 29, 2017
Awesome @plietar! It'd probably be good to bring this up in the "middle-end" compiler working group channel, which would also be a good place to get any help you might need.
joshtriplett commentedon Nov 23, 2017
@plietar How goes the implementation? I remember you showing a mostly complete prototype on IRC.
thedataking commentedon Feb 14, 2018
@plietar any news to share? This is a blocker for teams working on C to Rust transpilers, so this addition would be very welcome. (I'm part of one such team).
plietar commentedon Feb 22, 2018
Hey,
Sorry I've been busy and then forgot about this. I'll get my prototype back in shape, hopefully by this weekend.
harpocrates commentedon Mar 16, 2018
@plietar Any update on this? Do you have a WIP branch I can check out to try / fiddle with this?
dlrobertson commentedon Mar 20, 2018
Looks like I'm a little late to the party 😄 ... sorry about that
A few questions:
How would functions that use a
va_listmultiple times work without the ability to explicitly useva_startandva_end? Are they expected to use copy? E.g.execltypically loops through the arguments to to getargc, creats a arrayargvof sizeargc, loops through the list again populatingargv, and finally callexecv.The structure of a
va_listvaries greatly between the architectures. The intrinsic functions work with the architecture specific structure bitcast to ani8*, but AFAIK we'll still need to define the structure. Which architectures will be expected to be supported in the first iteration? Or am I mistaken that we'll have to define the structure?@plietar if you don't have the time to work on this any more or if there is any way I could help out, I'd be more than happy to do so. I haven't worked on rustc much, but I'd be happy to help however I can with the implementation of this.
nikomatsakis commentedon Mar 20, 2018
@dlrobertson
Seems likely that @plietar doesn't have much time, though they can speak for themselves.
I've not really looked closely at what would be needed to implement this, but if you need any help, please ping me, or reach out on gitter/IRC.
dlrobertson commentedon Apr 4, 2018
I've been working on this for the past two week and have
va_list_kindto the target specification which closely mirrors clangs TargetInfo::BuiltinVaListKindType::va_listwhich builds the correct structure based on the targetsva_list_kindI'm struggling a bit with understanding how to write something in
libcoreand link that toType::va_listin trans. I'm currently attempting to add#[lang = "va_list"]so that I can check thedef.didagainst thelang_items().va_list_impl()id. Does this seem correct?Also how would you like me to break this up into PRs? My current plan was to submit a PR once I got
VaListimplemented (meaning functions likevprintfcould be defined and tested). Then submit a second PR for implementing support for functions likeprintf.399 remaining items
Rollup merge of rust-lang#160165 - folkertdev:reject-dotdotdot-post-e…
Rollup merge of rust-lang#160165 - folkertdev:reject-dotdotdot-post-e…
Rollup merge of rust-lang#160165 - folkertdev:reject-dotdotdot-post-e…
authz: FULL Rust flip — 3 TUs, 29 functions, $0.23, and no shim
Unrolled build for #160165
Rollup merge of #160165 - folkertdev:reject-dotdotdot-post-expansion,…
Auto merge of #141980 - beetrees:va-list-proposal, r=workingjubilee
Rollup merge of #158039 - folkertdev:c-variadic-lifetimes, r=RalfJung
feat(core): retro_environment command dispatch (P1.5)
Rollup merge of rust-lang#162905 - folkertdev:variadic-x86-windows-lo…
Rollup merge of rust-lang#162905 - folkertdev:variadic-x86-windows-lo…
Rollup merge of rust-lang#162905 - folkertdev:variadic-x86-windows-lo…
Unrolled build for #162905 in rollup 162989
Rollup merge of #162905 - folkertdev:variadic-x86-windows-lock-in, r=…
Rollup merge of #162905 - folkertdev:variadic-x86-windows-lock-in, r=…