Skip to content
This repository was archived by the owner on Jun 26, 2020. It is now read-only.

Add ability to run CLIF IR using clif-util run [-v] {file}*#872

Closed
abrown wants to merge 1 commit intobytecodealliance:masterfrom
abrown:clif-util-run
Closed

Add ability to run CLIF IR using clif-util run [-v] {file}*#872
abrown wants to merge 1 commit intobytecodealliance:masterfrom
abrown:clif-util-run

Conversation

@abrown
Copy link
Copy Markdown
Member

@abrown abrown commented Jul 26, 2019

This PR allows users to execute CLIF functions from the command line by running clif-util run [-v] {file}*. It will look for functions with a signature like () -> bool that have a run: comment after them, compile them with the host machine's TargetIsa, and succeed if the function returns true. If the function returns false this utility keeps track of the number of failures much like clif-util test. I hoped to use this utility to verify that sequences of instructions (e.g. my SIMD changes) actually execute correctly on a host machine.

Copy link
Copy Markdown
Contributor

@bjorn3 bjorn3 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1000 This was on my own todo list :)

@abrown abrown force-pushed the clif-util-run branch 4 times, most recently from b1798da to 647f256 Compare July 29, 2019 23:12
@bnjbvr
Copy link
Copy Markdown
Member

bnjbvr commented Jul 31, 2019

Interesting idea. I remember @sunfishcode was saying we should use SimpleJIT for testing the runtime behavior and correctness of Cranelift in the past; we just never got to it. I think doing it directly with clif-util makes sense. I've made a list of things that came to mind while reading this code, and could be addressed either in this PR or in subsequent ones.

I'd be worried that testing only specific signatures could mean a lot of missing test coverage for calls to functions with other signatures; but then having to deal with the Rust ABI is a bit unfortunate. Having functions that return only booleans, means that we can use a helper function to test that a call works, but we stay in Cranelift jit territory (and if there are consistent errors within Cranelift, they couldn't be caught). Which might be good enough for a start.

  • I wonder if we could return more complicated types, like i64 or a simd 128-bit vector type, that would be used in assertions in comments; we'd have comments like assert_returns i64 42.

This would be good to have in automation too, but we'd need to limit running the runtime tests to automation host architectures that are supported by Cranelift. And by not having much control over Travis CI, not sure we can run on e.g. ARM64 in the future. Worth nothing at least.

  • Use this in automation.

Also to be entirely useful, I wonder if this shouldn't run the function in another process, in case the called function causes a segfault / other kind of hard crash. Otherwise, this means the first function that crashes causes the rest of the functions to not run, which is unfortunate.

  • Handle segfaults one way or another.

@bjorn3
Copy link
Copy Markdown
Contributor

bjorn3 commented Jul 31, 2019

I wonder if this shouldn't run the function in another process, in case the called function causes a segfault / other kind of hard crash.

fork() should work on *nix, though it should be called as close to the call of the codegened function as possible. Also after returning from the codegened function, you should immediately call std::process::exit(0). This is to avoid weird stuff. fork makes the new process single threaded for example, and also forbids calling certain libc functions (calling those is UB).

@nbp
Copy link
Copy Markdown
Collaborator

nbp commented Jul 31, 2019

For your information, I have been discussing this approach with @abrown over IRC, and suggested to use a single and only signature for function calls as a feature.

If you want to check the generated code for making a function call with a given ABI, this can already be done without the need for executing the code, with ordinary tests using ; check: and ; nextln: and even ; bin:.

So executing the code is just a matter of being able to call a single function. What I initially suggested was to have a ; run: %foo(1, 2, 3) == 51 which would generate a tiny function, compiled with Cranelift, with the signature () -> bool and which calls %foo with the expected argument and ABI.

I think the approach taken here goes in the right direction. So, even if it feels incomplete on many aspects, we should probably not block this work with too many wishes.

  • About checking complex type content, this is something which we can add vocabulary for as we improve this system. With this patch we are able to call a () -> bool function. Generating such a function for calling other signature and asserting other properties sounds like incremental future work.
  • About running other architecture, this is something we have done for SpiderMonkey testing already, by importing the simulators of other architectures (arm32, arm64, mips*). Another approach would be to rely on qemu and generate binaries.
  • About running in different processes, I think this would be premature at the moment, but a nice to have feature that I would probably not implement my-self until it pains me enough. Thus we should not block this feature on it.

@nbp nbp requested a review from sunfishcode July 31, 2019 12:33
@bnjbvr
Copy link
Copy Markdown
Member

bnjbvr commented Jul 31, 2019

Yeah yeah, I wasn't suggesting to mandate all of this before merging. More thinking about the running in different processes part had me realize that it'd be nice to have this, in two modes: 1. for running the tests in CI where each test is run in its own process (to not crash the test process itself), 2. for debugging tests, we would probably prefer something as is right now, that is, a test (or collection of tests) running in the test process itself, so it's easier to run within gdb/rr etc.

@abrown
Copy link
Copy Markdown
Member Author

abrown commented Jul 31, 2019

I'm all for fork-ing to avoid crashes, the run: %foo(...) == ... syntax @nbp is talking about, and wiring this up to the automation so that we always know that some CLIF actually runs (especially the x86 SIMD stuff 😄)--I do think all of those could be future PRs, though.

I am interested in using SimpleJIT here but someone will have to help me out. I looked at it for a moment but how to use it was obscured by the module-level stuff--I really just needed Context::compile and Context::emit_to_memory (https://github.com/CraneStation/cranelift/pull/872/files#diff-8643ebb587e63cc619cd28e00be6a7e5R127-R131).

@bnjbvr
Copy link
Copy Markdown
Member

bnjbvr commented Jul 31, 2019

The more I think about it, the more unclear it is that we can actually use SimpleJIT for this, especially considering how simple the code in the run pass is, so this looks fine as is to me in the current state. Thanks for doing this!

@abrown
Copy link
Copy Markdown
Member Author

abrown commented Aug 19, 2019

@sunfishcode rebased this on current master; should be ready to review.

Copy link
Copy Markdown
Member

@bnjbvr bnjbvr left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed having a first form of this would be quite useful actually. Some small suggestions here, let me know what you think about these, and then let's merge it. Thanks for doing this!

fn iterate_files(files: Vec<String>) -> impl Iterator<Item = PathBuf> {
files
.into_iter()
.flat_map(WalkDir::new)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is lovely. (Could require uniquing the names, if some path trees actually intersect.)

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To avoid running twice? Or we could just run things twice... 😄

@bnjbvr bnjbvr removed the request for review from sunfishcode August 20, 2019 12:56
@abrown
Copy link
Copy Markdown
Member Author

abrown commented Aug 20, 2019

@bnjbvr, I've resolved the issues above and pushed to https://github.com/abrown/cranelift/tree/clif-filetests-test-run so that we can merge as a part of #890.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants