Open anp opened 6 years ago
This is a good idea when the types match. In many cases, however, the libc
crate uses usize
which is a distinct type from what C uses. We're interested in doing this conversion but it's a tricky question to decide exactly when to do the casts.
A viable solution might be to continue doing computation at the C types but casting into usize
just before calling libc
functions.
I've started translating a rather large C project and this is my main pain point. Each generated file has an extensive amount of boilerplate that is identical across files and seems identical to what libc offers.
A viable solution might be to continue doing computation at the C types but casting into usize just before calling libc functions.
I attempted a u64 -> usize
refactor but it produced thousands of compiler errors. It would be great if c2rust handled this automatically. Even without that refactor I've been able to replace just about all of the other boilerplate with libc stuff.
I've started translating a rather large C project and this is my main pain point. Each generated file has an extensive amount of boilerplate that is identical across files and seems identical to what libc offers.
This is something that we plan to do in the near future, but it's non-trivial because we have to take a conservative approach and make sure to replace header functions and types only when it's 100% correct, e.g., the signature of the transpiled function perfectly matches the one in the libc
crate.
That means we would have to write a type- and signature-matching algorithm between the C2Rust versions of the functions and the libc
ones, which we'd have to parse from that crate's sources.
I think the best approach is for us to write either a new refactoring command or maybe a Lua script, and that is something I was considering recently.
I attempted a u64 -> usize refactor but it produced thousands of compiler errors.
You can mostly fix that with a few refactoring commands:
rewrite_ty 'u64' 'usize' ;
type_fix_rules '*, u64, usize => __old as usize' '*, usize, u64 => __old as u64' ;
but type_fix_rules
currently has some bugs I'm still working through. We'll consolidate these into a single easy-to-use command once they're correct.
The big issue with changing libc
types to usize
/isize
by default is that there are corner cases where the change is not sound.
For example, C long
generally matches isize
on Linux but not on Windows, where long
is always i32
. There are a few C types that we can always convert, like size_t
and intptr_t
.
Edit: shortened the refactoring snippet.
@ahomescu Yeah, I understand the burden that is maintaining semantics! It's a tall order.
The refactoring tool looks very cool! But unfortunately I haven't been able to really find any documentation on it (eg https://github.com/immunant/c2rust/issues/41 and the docs.rs builds https://docs.rs/crate/c2rust-refactor/0.13.0 haven't gone through).
I'm not sure to what extent this is feasible in practice, but all of the files I'm getting out of c2rust have very large blocks of extern items that could mostly be elided by relying on the libc crate's definition for those type signatures. Would that tactic cause issues for the semantics-preserving approach you've taken?