-
Notifications
You must be signed in to change notification settings - Fork 263
Translation of C's va_copy
into Rust's std::ffi::VaList::copy
#43
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
Comments
Sample code in the Playground here: https://play.rust-lang.org/?version=nightly&mode=debug&edition=2018&gist=1deb2470984d60fe6ecf4ea10dac17da pub unsafe extern "C" fn bar(mut ap1: VaList) {
ap1.copy(|mut ap2| {
println!("{}=={}", ap1.arg::<u32>(), ap2.arg::<u32>()); // Doesn't compile
});
} In this snippet, the closure body cannot call |
pub unsafe extern "C" fn bar(mut ap1: VaList) {
let x = ap1.arg::<u32>();
ap1.copy(|mut ap2| {
let y = ap2.arg::<u32>();
println!("{}=={}", x, y);
});
} |
Would a valid workaround be something like the following:
Note that |
In general, it is not possible to know how many times |
I can also see problems in cases where |
It seems entirely reasonable to want to iterate over two The easiest safe solution would be a Another alternative: we could expose a raw copy function as an unsafe function. I'm currently looking over the RFC thread to remember why we ended on a closure-taking function rather than a reference-returning function (e.g. |
I can't speak to all use cases here, but in the C translation case, an unsafe copy function that returns a new |
If we added |
@dlrobertson Remind me why we couldn't just have |
The user would have to use |
@dlrobertson No, the Drop implementation would call |
|
Sounds like a good idea to me.
We are certainly not in a position to make demands on your time. That said, we are very interested in this change since it is the one remaining feature that prevents us from translating large C99 projects. Let us know if we can help. |
I remembered a reason why this wasn't done. You'd be returning a reference to data owned by the |
On Wed, Mar 20, 2019 at 05:50:41PM +0000, Dan Robertson wrote:
> I'm currently looking over the RFC thread to remember why we ended on a closure-taking function rather than a reference-returning function (e.g. VaList::copy taking &self and returning a &mut with the same lifetime so that it can't outlive the VaList).
I remembered a reason why this wasn't done. You'd be returning a reference to data owned by the `copy` function. For pointer variants, I think you'd be okay, but for structure variants you have to alloc the structure.
It could still be a VaList<'a> though, right? (An owned structure that
nonetheless has a lifetime?)
|
On Wed, Mar 20, 2019 at 09:00:58AM -0700, Dan Robertson wrote:
> No, the Drop implementation would call va_end.
1) I wonder if adding `Drop` to `VaList` could complicate the current implementation of C-variadic functions since we "spoof" one in the function signature.
I don't know. I'll happily leave the approach and solution entirely up to you.
2) I wonder if the current `VaList::copy` should be be renamed `VaList::with_copy`.
That's a good idea, I like that.
3) Is there a timeline when this work should be done by (do I need to suspend work on other issues and do this now)?
In my opinion, this is less important than having VaList support
completely working, merged, and tested on all platforms. Once that's
done, this would be good to have for full C compatibility as part of the
FFI WG.
|
I don't think so. For the pointer variants it is fine, but for architectures like Aarch64 and x86_64 the reference contained by the |
@dlrobertson If you're busy with other things, we could implement this ourselves (@thedataking & myself) once we all agree on what the API is. This would also help accelerate testing with C2Rust for this feature, since we'd be doing it concurrently with development. |
I ran some tests and implementing
@ahomescu @thedataking awesome! I'm on the rustc discussion threads at |
On March 22, 2019 7:39:01 AM PDT, Dan Robertson ***@***.***> wrote:
> 1) I wonder if adding `Drop` to `VaList` could complicate the current
implementation of C-variadic functions since we "spoof" one in the
function signature.
I ran some tests and implementing `Drop` for `VaList` doesn't cause any
issues with "pure" C-variadic functions.
Awesome!
|
I haven't read the old discussions in their entirety so I'm not aware if this has already been discussed: on all of LLVM's current in-tree architectures, |
Yes
Sorry, by "hasn't caused any issues" I also mean "generates the correct LLVM IR". With the |
Closing since rust-lang/rust#59625 was merged. |
There is no good way to perform syntax-directed translation of all possible C functions using
va_list
into a corresponding Rust function usingstd::ffi::VaList::copy
.VaList
scopy
has the following signature:copy
takes a closure whose inputVaList
cannot outlive the closure (e.g. it cannot be passed back as a result of the closure). This is so thatva_end
can be called on the inputVaList
once the closure returns.Since copy takes an immutable reference to the original
va_list
andstd::ffi::VaList::arg
requires a mutable reference, it is not possible to callstd::ffi::VaList::arg
inside the closure passed tocopy
. Therefore, a C function that callsva_arg
on twova_lists
(with one being ava_copy
of the other) in the same basic block, cannot be expressed using the current Rust variadic function APIThe text was updated successfully, but these errors were encountered: