-
Notifications
You must be signed in to change notification settings - Fork 352
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
Adding support for external C functions that have integer (or empty) args and/or returns #2363
Conversation
Wow, that's amazing, thanks a ton. :) One high-level comment based just on the PR summary: I think it'd be better to put this new functionality into new file(s) dedicated to C FFI support. That should help things be more structured. |
This is awesome! It would be nice to have this support as optional / gated...similar to how miri has an option for isolation, it is useful to assert that no c code is called (if you take the extreme view that C = UB 😄 ) . |
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 really cool!
Oh definitely, this should be off-by-default. |
Hey guys, thanks for the quick and thorough review! And hello fellow Boston squad :) |
Hey all -- thanks again for the feedback! I've just pushed an updated version of the code, with the main changes being:
I did not fix Oli's comment about supporting the external C tests only on certain platforms as I'm not sure how best to do 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 think we'll limit everything to linux for now and then look into expanding the support (and CI coverage) to other platforms in separate PRs. Please set it up so that the shared object is only built on linux for now
It would be great if you could resolve those conflicts by doing a rebase over latest master, so that CI can run on this PR. |
It looks like the linux build is failing because the install is trying to download a new dependency Error message from CI build log:
|
I think it has been so long since we added a dependency to miri itself, we've since made CI broken in case we do. @RalfJung I guess we should remove the |
I think I added it because at the time I used |
Our test suite needs a new feature: |
Thank you! :) 🙏 |
@oli-obk Can you also make the |
☔ The latest upstream changes (presumably #2377) made this pull request unmergeable. Please resolve the merge conflicts. |
OK, after a rebase everything should work now |
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 rebase instead of merge
☔ The latest upstream changes (presumably #2382) made this pull request unmergeable. Please resolve the merge conflicts. |
3c8fff0
to
c5e5754
Compare
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 am quite excited by this, but do have a bunch of comments. :)
src/shims/ffi_support.rs
Outdated
// Check if host target == the session target. | ||
// This check needs to happen _after_ we check if the shared object file does not | ||
// export the function: we don't want to throw an error if we are just going to use | ||
// one of the shims. |
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 disagree. In fact I think the check should be somewhere way earlier, during initiailization. Passing this flag at all for cross-interpretation is an error.
Also throw_ub
is definitely wrong here. UB is when the Abstract Machine says you did something wrong. This here is just a misconfiguration of the user, similar to setting -Zmiri-preemption-rate=notafloat
.
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.
Ah ok, sounds good.
@@ -410,6 +413,18 @@ impl<'mir, 'tcx> Evaluator<'mir, 'tcx> { | |||
preemption_rate: config.preemption_rate, | |||
report_progress: config.report_progress, | |||
since_progress_report: 0, | |||
external_so_lib: config.external_so_file.as_ref().map(|lib_file_path| { |
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 think this is the right spot to error if host != target.
☔ The latest upstream changes (presumably #2441) made this pull request unmergeable. Please resolve the merge conflicts. |
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.
should probably squash commits again after addressing these.
I'm checking out your branch locally now to see if it actually works in x.py
|
||
#[derive(Debug, Clone)] | ||
/// Enum of supported arguments to external C functions. | ||
pub enum CArg { |
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.
Should probably document why this intermediate enum is used instead of directly invoking ffi::args
and using libffi::high::Arg
immediately
All the tests pass! So I guess after my nits, rebase to eliminate any merge commits and squash the other commits. |
☔ The latest upstream changes (presumably #2448) made this pull request unmergeable. Please resolve the merge conflicts. |
dfdb158
to
88a7882
Compare
@bors r+ |
☀️ Test successful - checks-actions |
<<<<<<< HEAD | ||
======= | ||
<<<<<<< HEAD | ||
tests/extern-so/libtestlib.so | ||
======= | ||
>>>>>>> master | ||
>>>>>>> 58ba05a0 (C FFI support for functions with int args and returns) |
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.
Is this a merge conflict issue?
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.
yea, I created a fix PR for 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.
oh no -- good catch and thanks for fixing it!
Fix merge conflict found in #2363 (comment)
@@ -412,6 +416,24 @@ impl<'mir, 'tcx> Evaluator<'mir, 'tcx> { | |||
preemption_rate: config.preemption_rate, | |||
report_progress: config.report_progress, | |||
since_progress_report: 0, | |||
external_so_lib: config.external_so_file.as_ref().map(|lib_file_path| { | |||
// Check if host target == the session target. | |||
if option_env!("TARGET") == Some(target_triple) { |
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.
So we panic if they are equal? How does that make sense?
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 hiding a bug, the comparison doesn't actually work right now.
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.
Fixed by #2511
Unless we can quickly find a solution for this licensing issue, we might have to revert this PR (or disable some of its code, at least) in order to be able to update Miri in rustc. :/ |
Oh yikes 😢 |
Have we reached out to |
Yeah I am trying that: tov/libffi-rs#58. @emarteca what alternatives to libffi are there? |
Hmm, |
Honestly it seems easier to fork libffi and remove their use of abort_on_panic. |
But I hope tov/libffi-rs#58 won't take too long so we can avoid any such drastic steps. :) |
Starts addressing @#11
Implementation
Adding support for calling external C functions that have any number of integer arguments (types of integers:
i8
,i16
,i32
,i64
,u8
,u16
,u32
,u64
) and an integer return type (orvoid
).As suggested in @#11, the
libffi
crate is used to dispatch the calls to external C functions.Modifications
Main modifications are to:
call_and_add_external_c_fct_to_context
to read the code pointer to the external C function, dispatch the call, and save the return in MIRI internal memory. Handles all conversions between MIRI and C values (using some macros, also defined in this file).call_and_add_external_c_fct_to_context
in helper.rs when a foreign item is encountered. Also adds some structs to model C representations of arguments, and the signature of the external C call.Testing
Adds tests for the following external functions which are now supported:
i16
to ani64
Code review
The code in this PR was reviewed by @maurer on another fork -- thanks!