immunant / c2rust

Migrate C code to Rust
https://c2rust.com/
Other
4.03k stars 244 forks source link

Rely on `libc` crate to further reduce imports? #20

Open anp opened 6 years ago

anp commented 6 years ago

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?

glguy commented 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.

samuela commented 5 years ago

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.

ahomescu commented 5 years ago

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.

samuela commented 5 years ago

@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).