-
-
Notifications
You must be signed in to change notification settings - Fork 14.4k
support c-variadic functions in rustc_const_eval
#150601
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
This comment has been minimized.
This comment has been minimized.
d30044f to
5f98625
Compare
This comment has been minimized.
This comment has been minimized.
5f98625 to
3368321
Compare
This comment has been minimized.
This comment has been minimized.
3368321 to
41a34bc
Compare
This comment has been minimized.
This comment has been minimized.
41a34bc to
8608ba7
Compare
This comment has been minimized.
This comment has been minimized.
8608ba7 to
207b032
Compare
|
☔ The latest upstream changes made this pull request unmergeable. Please resolve the merge conflicts. |
207b032 to
1794556
Compare
This comment has been minimized.
This comment has been minimized.
b297adc to
c081ba3
Compare
This comment has been minimized.
This comment has been minimized.
c081ba3 to
293ba18
Compare
|
This PR changes rustc_public cc @oli-obk, @celinval, @ouz-a, @makai410 Some changes occurred to the CTFE machinery Some changes occurred in compiler/rustc_codegen_cranelift cc @bjorn3 Some changes occurred to the CTFE / Miri interpreter cc @rust-lang/miri Some changes occurred to the CTFE / Miri interpreter cc @rust-lang/miri, @RalfJung, @oli-obk, @lcnr The Miri subtree was changed cc @rust-lang/miri Some changes occurred to the intrinsics. Make sure the CTFE / Miri interpreter cc @rust-lang/miri, @RalfJung, @oli-obk, @lcnr Some changes occurred in compiler/rustc_codegen_gcc |
|
☔ The latest upstream changes (presumably #146923) made this pull request unmergeable. Please resolve the merge conflicts. |
Co-authored-by: Ralf Jung <post@ralfj.de>
e4bc4f9 to
8634e40
Compare
|
This PR was rebased onto a different main 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. |
This comment has been minimized.
This comment has been minimized.
8634e40 to
03543fb
Compare
This comment has been minimized.
This comment has been minimized.
|
I believe I got everything @rustbot ready |
This comment has been minimized.
This comment has been minimized.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Next round of comments. Also, CI seems unhappy?
| // The check for the DefKind is so that we don't request the fn_sig of a closure. | ||
| // Otherwise, we hit: | ||
| // | ||
| // DefId(1:180 ~ std[269c]::rt::lang_start_internal::{closure#0}) does not have a "fn_sig" | ||
| let (fixed_count, callee_c_variadic_args) = | ||
| if matches!(self.tcx.def_kind(instance.def_id()), DefKind::Fn) | ||
| && let callee_fn_sig = self.tcx.fn_sig(instance.def_id()).skip_binder() | ||
| && callee_fn_sig.c_variadic() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is very odd and seems to break our usual abstractions. How does codegen deal with this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure, I asked in #t-compiler/help > no `fn_sig`for `lang_start_internal` closure. My impression is that those functions just never get fn_sig called on them, but maybe there is some logic that I'm missing somewhere.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Apparently checking for the DefKind is fairly standard
| // NOTE: this handles the extra caller location argument | ||
| // when `#[track_caller]` is used. This attribute is only allowed on `extern "Rust"` | ||
| // functions, so the c-variadic case does not need to handle the extra argument. | ||
| callee_fn_abi.args.iter().enumerate() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't understand this comment. How does this line do anything wrt track_caller?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this additional argument is not reflected in fixed_count
| pub(crate) fn allocate_varargs<I>( | ||
| &mut self, | ||
| caller_args: &mut I, | ||
| ) -> InterpResult<'tcx, VecDeque<MPlaceTy<'tcx, M::Provenance>>> | ||
| where | ||
| I: Iterator<Item = (&'a FnArg<'tcx, M::Provenance>, &'a ArgAbi<'tcx, Ty<'tcx>>)>, | ||
| { | ||
| // Consume the remaining arguments and store them in fresh allocations. | ||
| let mut varargs = Vec::new(); | ||
| for (fn_arg, abi) in caller_args { | ||
| // FIXME: do we have to worry about in-place argument passing? | ||
| let op = self.copy_fn_arg(fn_arg); | ||
| let mplace = self.allocate(abi.layout, MemoryKind::Stack)?; | ||
| self.copy_op(&op, &mplace)?; | ||
|
|
||
| varargs.push(mplace); | ||
| } | ||
|
|
||
| // When the frame is dropped, these variable arguments are deallocated. | ||
| self.frame_mut().va_list = varargs.clone(); | ||
|
|
||
| interp_ok(varargs.into()) | ||
| } | ||
|
|
||
| fn deallocate_varargs( | ||
| &mut self, | ||
| varargs: &[MPlaceTy<'tcx, M::Provenance>], | ||
| ) -> InterpResult<'tcx> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These two functions look symmetric, but they are very different: one implicitly works on the current frame, the other takes the vararg list as argument. Such a false symmetry is quite confusing.
Any ideas how to avoid that?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I moved the self.frame_mut().va_list = varargs.clone(); line out, so now the one allocates, the other deallocates. They both receive the variadic arguments as an argument actually.
| let f = helper as *const (); | ||
| let f = std::mem::transmute::<_, unsafe extern "C" fn(...)>(f); | ||
|
|
||
| f(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please pass an argument here so that the code looks more legit (it does pass the required number of arguments, just not in the right way)
| } else { | ||
| // NOTE: this handles the extra caller location argument | ||
| // when `#[track_caller]` is used. This attribute is only allowed on `extern "Rust"` | ||
| // functions, so the c-variadic case does not need to handle the extra argument. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If this is relevant, it seems good to have an assertion double-checking this property.
|
@rustbot author |
39af72b to
49ba67a
Compare
|
@rustbot ready |
tracking issue: #44930
The new
GlobalAlloc::VaListis used to create anAllocIdthat represents the variable argument list of a frame. The allocation itself does not store any data, all we need is the unique identifier.The actual variable argument list is stored in
Memory, and keyed by theAllocId. TheFramealso stores thisAllocId, so that when a frame is popped, it can deallocate the variable arguments.At "runtime" a
VaListvalue stores a pointer to the global allocation in its first bytes. The provenance on this pointer can be used to retrieve itsAllocId, and the offset of the pointer is used to store the index of the next argument to read from the variable argument list.Miri does not yet support
va_arg, but I think that can be done separetely?r? @RalfJung
cc @workingjubilee