-
Notifications
You must be signed in to change notification settings - Fork 200
Print return values of run tests if type is not boolean. #1231
Conversation
|
Good idea; I've needed something like this in the past. @nbp and I had talked about extending the |
|
For context: #872 |
|
I have initially suggested adding a new opcode for printing the argument similar to what If the intention is to print results of comparisons instead of a single value, maybe the function can return a multilane value and we could print the data as two values that are half width of the return type - which would be a workaround. Extending the run comment On the other hand, one might say that a new |
Makes sense, let's just go with the simple print idea then. I suspect that implementing
What do you think of that? |
|
Would it mean that |
da67801 to
7312d56
Compare
|
Sure thing, it makes sense to modify the
I do not like my |
7312d56 to
cffae1e
Compare
|
Nice work! I'll take a closer look on Monday. |
abrown
left a comment
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.
Thanks for doing this! See my comments for some improvements but I think this approach makes sense. I will use these new features for sure 😄. If anything I said didn't make sense I'll be on the Mozilla IRC if you want to discuss.
| args: Vec<u128>, | ||
| operator: Option<Operator>, | ||
| expected: Option<u128>, | ||
| } |
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.
To be more clear about what this is used for (and to make construction simpler), we could do:
enum FunctionRunnerAction {
Print,
Test,
TestWithResult(operator: Operator, expected: ...)
}
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.
And I don't see that args is used (yet 😄) so we could leave it out for now.
| Self { | ||
| function, | ||
| isa, | ||
| options: Self::parse_options(comment), |
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.
It occurred to me that it might be better to not pass comment in through a bunch of functions: we might want to pass in an already parsed Options/FunctionRunnerAction in some cases and I see below some cases where we are forced to provide a comment string when we really don't need to. What if new just put a default value here (like the original behavior FunctionRunnerAction::Test) and then we had a function like:
fn with_action(self, action: FunctionRunnerAction) -> Self {
self.action = action;
self
}
If users, like test_run.rs, want to override the default action they could do something roughly like FunctionRunner::new(...).with_action(parse(comment)).
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 have introduced a builder FunctionRunnerBuilder to unify it with other with functions.
| "Function arguments more than supported count: {}", | ||
| self.options.args.len() | ||
| )), | ||
| }, |
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 was a bit hard to read but I think I get it now; it might be more clear with an enum like I mentioned above:
match action {
Print => println!(...),
Test => check(...),
TestWithResult => check(...),
}
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 simplified things a lot!
bnjbvr
left a comment
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.
Just wanted to add: could we keep the previous behavior that ; run is equivalent to ; run: test, so we don't have to modify all the existing test cases, and remove ; run: test too? (or find a better sub-directive name after the :, since "test" is quite overloaded in the context of testing)
730bd3d to
72f6ea8
Compare
To print the return value of a run test, use "; run print", to assert on the return value, use "; run %fn() == 42".
72f6ea8 to
18afb26
Compare
cranelift-codegen/src/result.rs
Outdated
| /// This always represents a bug, either in the code that generated IR for Cranelift, or a bug | ||
| /// in Cranelift itself. | ||
| #[error("Verifier errors")] | ||
| #[error("Verifier errors\n{0}")] |
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 don't think we want to do this (I just learned): #1240
| match s { | ||
| "==" => Ok(Operator::EQ), | ||
| "!=" => Ok(Operator::NEQ), | ||
| _ => Err(format!("Unsupported operator {}", s)), |
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.
A minor re-factoring suggestion: elsewhere in cranelift I've seen this type of thing as impl FromStr for Operator { ... } so that we can just call .parse() up on line 320. Not a big deal but it keeps the operator implementation together.
| /// Build a function runner from an action, a function and the ISA to run on. | ||
| pub fn finish(self) -> FunctionRunner { | ||
| FunctionRunner::new(self.function, self.isa.unwrap(), self.action) | ||
| } |
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.
Nit: elsewhere in the project we are calling this build.
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.
cranelift-codegen/src/isa/mod.rs calls it finish.
cranelift/cranelift-codegen/src/isa/mod.rs
Line 151 in da996fe
| pub fn finish(self, shared_flags: settings::Flags) -> Box<dyn TargetIsa> { |
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.
Yeah, in this particular case it's this file which is not consistent with the Rust style, so we should fix it (later).
| match &self.action { | ||
| FunctionRunnerAction::Test => { | ||
| if !ret_value_type.is_bool() { | ||
| return Err(String::from("Function return type is not boolean")); |
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.
Let's add the context.func.name here as well so that we can more easily find it.
| if result { | ||
| return Ok(()); | ||
| } | ||
| return Err(format!("Failed: {}", context.func.name.to_string())); |
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.
Re-factoring nit: I'm not really used to seeing return much in Rust 😄:
if Self::invoke::<bool>(&code_page) {
Ok(())
} else {
Err(format!("Failed: {}", context.func.name.to_string()))
}
| Operator::EQ, | ||
| ConstantData::default().append(1), | ||
| true, | ||
| ), |
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.
Perhaps we should not overload check; why not just invoke here and println! the returned value?
cranelift-codegen/src/ir/constant.rs
Outdated
| Ok(self.into_vec()[0] != 0) | ||
| } | ||
| } | ||
|
|
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 don't think we should modify ConstantData for what we are doing; it is designed for constant pool stuff and adding these conversions might make it harder to decouple later from test functionality. Why not build our own Value enum:
enum Value {
Bool(bool),
F32(f32),
F64(f64),
...
}
I wouldn't worry too much about 128-bit types just yet until we get the basics in place. Then I would add a way to parse into this (using Rust's FromStr/parse) from text and a type:
impl Value {
fn parse_as(text: &str, type: Type) -> Result<Self, ...> {
match type {
B8 | B16 | ... => Ok(Value::Bool(text.parse()?)),
F32 => Ok(Value::F32(text.parse()?)),
...
}
Then I would #[derive(Eq, PartialEq)] on the enum so we can compare them to each other and add some From implementations so that invoke can get the raw value (e.g. f32), wrap it in a Value with Value::from (or into), and then compare it against the parsed Values that we get from the comments. (Hopefully that explains the other comments I've made; this isn't the only way to do things but it doesn't involve touching other components like ConstantData and it seems natural to Rust--from the little I know about Rust).
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.
Let me change my tune a bit: I now see down below that you implemented some parsing logic in parser.rs; if you want to use that for the FromStr on Value instead of the built-in Rust parsing that seems OK. We could use methods like Parser::new(text).match_bool(...) instead and Value may have to use different inner types (e.g. F32(Ieee32) instead of F32(f32))--but that seems fine. The underlying thing that I'm getting at is that we likely don't want to touch ConstantData in this case.
cranelift-reader/src/parser.rs
Outdated
| }; | ||
| Ok(constant_data) | ||
| } | ||
|
|
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.
See my parsing comments about Value; we may not need to change the parser.
abrown
left a comment
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 will be out next week on vacation and it looks like @bnjbvr may be as well so it might not get merged until after Thanskgiving week). |
|
I'm back from vacation, I'll try to take a look at it this week. |
fitzgen
left a comment
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.
Hi @krk -- thanks for this PR!
I'm not super familiar with this area of code, but since Benjamin tagged me for review (I assume because he's got a lot on his plate at the moment) I've taken a look and left a few comments.
Overall, this looks good, but I think there are a few things we could clean up a bit before landing, and it seems like there are still some unresolved discussions from earlier rounds of review that we should figure out before merging this as well.
If any of my comments are unclear, please let me know! I'm happy to clarify.
Cheers!
| let mut parts: Vec<&str> = comment.split_ascii_whitespace().collect(); | ||
|
|
||
| if parts.len() < 3 { | ||
| panic!("Invalid syntax for test assertion, expected \"%fn() <operator> <value>\", found \"{}\"", comment); |
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.
We shouldn't panic on parse errors, we should return a fallible ParseResult like other parsing functions do.
Additionally, it seems a little strange that we have this parsing code in the cranelift-filetests crate, when AFAICT all the other parsing code is in the cranelift-reader crate. Unless there is a good reason not to, we should match existing conventions and keep the parsing code inside cranelift-reader.
| // Match and consume either a hexadecimal Uimm128 immediate (e.g. 0x000102...) or its literal list form (e.g. [0 1 2...]) | ||
| fn match_constant_data(&mut self, controlling_type: Type) -> ParseResult<ConstantData> { | ||
| /// Match and consume either a hexadecimal Uimm128 immediate (e.g. 0x000102...) or its literal list form (e.g. [0 1 2...]) | ||
| pub fn match_constant_data(&mut self, controlling_type: Type) -> ParseResult<ConstantData> { |
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 believe that moving that parsing code into this cranelift-reader crate would let us avoid making all these methods public as well.
| Self::I8(data.into()) | ||
| } | ||
| types::I16 => { | ||
| let data = p.match_constant_data(ty).unwrap(); |
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.
Was this still going to happen?
| types::I128 => { | ||
| let data = p.match_constant_data(ty).unwrap(); | ||
| let data = ConstantDataU128::try_into(data).unwrap(); | ||
| Self::I128(data.rotate_left(64)) |
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.
It isn't clear to me what the resolution is here, if any.
| ($type: ty, $name: ident) => { | ||
| struct $name {} | ||
| impl $name { | ||
| fn try_into(d: ConstantData) -> Result<$type, String> { |
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.
Instead of making an ad-hoc try_into method, we should follow convention and implement the TryFrom trait, which gives us a try_into via the blanket impl TryInto<T> for U where U: TryFrom<T>. For details, see: https://doc.rust-lang.org/stable/std/convert/trait.TryInto.html and https://doc.rust-lang.org/stable/std/convert/trait.TryFrom.html
If I'm reading this code right, it would be something like this:
struct $name(ConstantData);
impl TryFrom<$name> for $type {
// ...
}But this also makes me wonder why we don't implement TryFrom<ConstantData> for $type directly instead of creating all these temporary ConstantData$Type types. Is that something that you explored at all? I think it would be the best course to take, unless it doesn't work for some reason or I am overlooking something else.
|
Thanks for the PR again, and as a procedural note the Cranelift repository has now merged into the wasmtime repository. PRs are no longer landing in this repository, and unfortunately there's no "one button" solution to move a PR to the wasmtime repository. A script has been prepared, however, to assist you in transferring this PR to the wasmtime repo. Feel free to reach out on Zulip with any questions! |
|
Sorry for abandoning this PR. It seems that functionality is being added: bytecodealliance/wasmtime#1223 |
This resolves the work started in bytecodealliance/cranelift#1231 and bytecodealliance#1436. Cranelift filetests currently have the ability to run CLIF functions with a signature like `() -> b*` and check that the result is true under the `test run` directive. This PR adds the ability to call functions with arbitrary arguments and non-boolean returns and either print the result or check against a list of expected results: - `run` commands look like `; run: %add(2, 2) == 4` or `; run: %add(2, 2) != 5` and verify that the executed CLIF function returns the expected value - `print` commands look like `; print: %add(2, 2)` and print the result of the function to stdout To make this work, this PR compiles a single Cranelift `Function` into a `CompiledFunction` using a `SingleFunctionCompiler`. Because we will not know the signature of the function until runtime, we use a `Trampoline` to place the values in the appropriate location for the calling convention; this should look a lot like what @alexcrichton is doing with `VMTrampoline` in wasmtime (see https://github.com/bytecodealliance/wasmtime/blob/3b7cb6ee64469470fcdd68e185abca8eb2a1b20a/crates/api/src/func.rs#L510-L526, https://github.com/bytecodealliance/wasmtime/blob/3b7cb6ee64469470fcdd68e185abca8eb2a1b20a/crates/jit/src/compiler.rs#L260). To avoid re-compiling `Trampoline`s for the same function signatures, `Trampoline`s are cached in the `SingleFunctionCompiler`.
This resolves the work started in bytecodealliance/cranelift#1231 and bytecodealliance#1436. Cranelift filetests currently have the ability to run CLIF functions with a signature like `() -> b*` and check that the result is true under the `test run` directive. This PR adds the ability to call functions with arbitrary arguments and non-boolean returns and either print the result or check against a list of expected results: - `run` commands look like `; run: %add(2, 2) == 4` or `; run: %add(2, 2) != 5` and verify that the executed CLIF function returns the expected value - `print` commands look like `; print: %add(2, 2)` and print the result of the function to stdout To make this work, this PR compiles a single Cranelift `Function` into a `CompiledFunction` using a `SingleFunctionCompiler`. Because we will not know the signature of the function until runtime, we use a `Trampoline` to place the values in the appropriate location for the calling convention; this should look a lot like what @alexcrichton is doing with `VMTrampoline` in wasmtime (see https://github.com/bytecodealliance/wasmtime/blob/3b7cb6ee64469470fcdd68e185abca8eb2a1b20a/crates/api/src/func.rs#L510-L526, https://github.com/bytecodealliance/wasmtime/blob/3b7cb6ee64469470fcdd68e185abca8eb2a1b20a/crates/jit/src/compiler.rs#L260). To avoid re-compiling `Trampoline`s for the same function signatures, `Trampoline`s are cached in the `SingleFunctionCompiler`.
This resolves the work started in bytecodealliance/cranelift#1231 and bytecodealliance#1436. Cranelift filetests currently have the ability to run CLIF functions with a signature like `() -> b*` and check that the result is true under the `test run` directive. This PR adds the ability to call functions with arbitrary arguments and non-boolean returns and either print the result or check against a list of expected results: - `run` commands look like `; run: %add(2, 2) == 4` or `; run: %add(2, 2) != 5` and verify that the executed CLIF function returns the expected value - `print` commands look like `; print: %add(2, 2)` and print the result of the function to stdout To make this work, this PR compiles a single Cranelift `Function` into a `CompiledFunction` using a `SingleFunctionCompiler`. Because we will not know the signature of the function until runtime, we use a `Trampoline` to place the values in the appropriate location for the calling convention; this should look a lot like what @alexcrichton is doing with `VMTrampoline` in wasmtime (see https://github.com/bytecodealliance/wasmtime/blob/3b7cb6ee64469470fcdd68e185abca8eb2a1b20a/crates/api/src/func.rs#L510-L526, https://github.com/bytecodealliance/wasmtime/blob/3b7cb6ee64469470fcdd68e185abca8eb2a1b20a/crates/jit/src/compiler.rs#L260). To avoid re-compiling `Trampoline`s for the same function signatures, `Trampoline`s are cached in the `SingleFunctionCompiler`.
This resolves the work started in bytecodealliance/cranelift#1231 and bytecodealliance#1436. Cranelift filetests currently have the ability to run CLIF functions with a signature like `() -> b*` and check that the result is true under the `test run` directive. This PR adds the ability to call functions with arbitrary arguments and non-boolean returns and either print the result or check against a list of expected results: - `run` commands look like `; run: %add(2, 2) == 4` or `; run: %add(2, 2) != 5` and verify that the executed CLIF function returns the expected value - `print` commands look like `; print: %add(2, 2)` and print the result of the function to stdout To make this work, this PR compiles a single Cranelift `Function` into a `CompiledFunction` using a `SingleFunctionCompiler`. Because we will not know the signature of the function until runtime, we use a `Trampoline` to place the values in the appropriate location for the calling convention; this should look a lot like what @alexcrichton is doing with `VMTrampoline` in wasmtime (see https://github.com/bytecodealliance/wasmtime/blob/3b7cb6ee64469470fcdd68e185abca8eb2a1b20a/crates/api/src/func.rs#L510-L526, https://github.com/bytecodealliance/wasmtime/blob/3b7cb6ee64469470fcdd68e185abca8eb2a1b20a/crates/jit/src/compiler.rs#L260). To avoid re-compiling `Trampoline`s for the same function signatures, `Trampoline`s are cached in the `SingleFunctionCompiler`.
This resolves the work started in bytecodealliance/cranelift#1231 and bytecodealliance#1436. Cranelift filetests currently have the ability to run CLIF functions with a signature like `() -> b*` and check that the result is true under the `test run` directive. This PR adds the ability to call functions with arbitrary arguments and non-boolean returns and either print the result or check against a list of expected results: - `run` commands look like `; run: %add(2, 2) == 4` or `; run: %add(2, 2) != 5` and verify that the executed CLIF function returns the expected value - `print` commands look like `; print: %add(2, 2)` and print the result of the function to stdout To make this work, this PR compiles a single Cranelift `Function` into a `CompiledFunction` using a `SingleFunctionCompiler`. Because we will not know the signature of the function until runtime, we use a `Trampoline` to place the values in the appropriate location for the calling convention; this should look a lot like what @alexcrichton is doing with `VMTrampoline` in wasmtime (see https://github.com/bytecodealliance/wasmtime/blob/3b7cb6ee64469470fcdd68e185abca8eb2a1b20a/crates/api/src/func.rs#L510-L526, https://github.com/bytecodealliance/wasmtime/blob/3b7cb6ee64469470fcdd68e185abca8eb2a1b20a/crates/jit/src/compiler.rs#L260). To avoid re-compiling `Trampoline`s for the same function signatures, `Trampoline`s are cached in the `SingleFunctionCompiler`.
This resolves the work started in bytecodealliance/cranelift#1231 and bytecodealliance#1436. Cranelift filetests currently have the ability to run CLIF functions with a signature like `() -> b*` and check that the result is true under the `test run` directive. This PR adds the ability to call functions with arbitrary arguments and non-boolean returns and either print the result or check against a list of expected results: - `run` commands look like `; run: %add(2, 2) == 4` or `; run: %add(2, 2) != 5` and verify that the executed CLIF function returns the expected value - `print` commands look like `; print: %add(2, 2)` and print the result of the function to stdout To make this work, this PR compiles a single Cranelift `Function` into a `CompiledFunction` using a `SingleFunctionCompiler`. Because we will not know the signature of the function until runtime, we use a `Trampoline` to place the values in the appropriate location for the calling convention; this should look a lot like what @alexcrichton is doing with `VMTrampoline` in wasmtime (see https://github.com/bytecodealliance/wasmtime/blob/3b7cb6ee64469470fcdd68e185abca8eb2a1b20a/crates/api/src/func.rs#L510-L526, https://github.com/bytecodealliance/wasmtime/blob/3b7cb6ee64469470fcdd68e185abca8eb2a1b20a/crates/jit/src/compiler.rs#L260). To avoid re-compiling `Trampoline`s for the same function signatures, `Trampoline`s are cached in the `SingleFunctionCompiler`.
This resolves the work started in bytecodealliance/cranelift#1231 and bytecodealliance#1436. Cranelift filetests currently have the ability to run CLIF functions with a signature like `() -> b*` and check that the result is true under the `test run` directive. This PR adds the ability to call functions with arbitrary arguments and non-boolean returns and either print the result or check against a list of expected results: - `run` commands look like `; run: %add(2, 2) == 4` or `; run: %add(2, 2) != 5` and verify that the executed CLIF function returns the expected value - `print` commands look like `; print: %add(2, 2)` and print the result of the function to stdout To make this work, this PR compiles a single Cranelift `Function` into a `CompiledFunction` using a `SingleFunctionCompiler`. Because we will not know the signature of the function until runtime, we use a `Trampoline` to place the values in the appropriate location for the calling convention; this should look a lot like what @alexcrichton is doing with `VMTrampoline` in wasmtime (see https://github.com/bytecodealliance/wasmtime/blob/3b7cb6ee64469470fcdd68e185abca8eb2a1b20a/crates/api/src/func.rs#L510-L526, https://github.com/bytecodealliance/wasmtime/blob/3b7cb6ee64469470fcdd68e185abca8eb2a1b20a/crates/jit/src/compiler.rs#L260). To avoid re-compiling `Trampoline`s for the same function signatures, `Trampoline`s are cached in the `SingleFunctionCompiler`.
This resolves the work started in bytecodealliance/cranelift#1231 and bytecodealliance#1436. Cranelift filetests currently have the ability to run CLIF functions with a signature like `() -> b*` and check that the result is true under the `test run` directive. This PR adds the ability to call functions with arbitrary arguments and non-boolean returns and either print the result or check against a list of expected results: - `run` commands look like `; run: %add(2, 2) == 4` or `; run: %add(2, 2) != 5` and verify that the executed CLIF function returns the expected value - `print` commands look like `; print: %add(2, 2)` and print the result of the function to stdout To make this work, this PR compiles a single Cranelift `Function` into a `CompiledFunction` using a `SingleFunctionCompiler`. Because we will not know the signature of the function until runtime, we use a `Trampoline` to place the values in the appropriate location for the calling convention; this should look a lot like what @alexcrichton is doing with `VMTrampoline` in wasmtime (see https://github.com/bytecodealliance/wasmtime/blob/3b7cb6ee64469470fcdd68e185abca8eb2a1b20a/crates/api/src/func.rs#L510-L526, https://github.com/bytecodealliance/wasmtime/blob/3b7cb6ee64469470fcdd68e185abca8eb2a1b20a/crates/jit/src/compiler.rs#L260). To avoid re-compiling `Trampoline`s for the same function signatures, `Trampoline`s are cached in the `SingleFunctionCompiler`.
This resolves the work started in bytecodealliance/cranelift#1231 and bytecodealliance#1436. Cranelift filetests currently have the ability to run CLIF functions with a signature like `() -> b*` and check that the result is true under the `test run` directive. This PR adds the ability to call functions with arbitrary arguments and non-boolean returns and either print the result or check against a list of expected results: - `run` commands look like `; run: %add(2, 2) == 4` or `; run: %add(2, 2) != 5` and verify that the executed CLIF function returns the expected value - `print` commands look like `; print: %add(2, 2)` and print the result of the function to stdout To make this work, this PR compiles a single Cranelift `Function` into a `CompiledFunction` using a `SingleFunctionCompiler`. Because we will not know the signature of the function until runtime, we use a `Trampoline` to place the values in the appropriate location for the calling convention; this should look a lot like what @alexcrichton is doing with `VMTrampoline` in wasmtime (see https://github.com/bytecodealliance/wasmtime/blob/3b7cb6ee64469470fcdd68e185abca8eb2a1b20a/crates/api/src/func.rs#L510-L526, https://github.com/bytecodealliance/wasmtime/blob/3b7cb6ee64469470fcdd68e185abca8eb2a1b20a/crates/jit/src/compiler.rs#L260). To avoid re-compiling `Trampoline`s for the same function signatures, `Trampoline`s are cached in the `SingleFunctionCompiler`.
This resolves the work started in bytecodealliance/cranelift#1231 and bytecodealliance#1436. Cranelift filetests currently have the ability to run CLIF functions with a signature like `() -> b*` and check that the result is true under the `test run` directive. This PR adds the ability to call functions with arbitrary arguments and non-boolean returns and either print the result or check against a list of expected results: - `run` commands look like `; run: %add(2, 2) == 4` or `; run: %add(2, 2) != 5` and verify that the executed CLIF function returns the expected value - `print` commands look like `; print: %add(2, 2)` and print the result of the function to stdout To make this work, this PR compiles a single Cranelift `Function` into a `CompiledFunction` using a `SingleFunctionCompiler`. Because we will not know the signature of the function until runtime, we use a `Trampoline` to place the values in the appropriate location for the calling convention; this should look a lot like what @alexcrichton is doing with `VMTrampoline` in wasmtime (see https://github.com/bytecodealliance/wasmtime/blob/3b7cb6ee64469470fcdd68e185abca8eb2a1b20a/crates/api/src/func.rs#L510-L526, https://github.com/bytecodealliance/wasmtime/blob/3b7cb6ee64469470fcdd68e185abca8eb2a1b20a/crates/jit/src/compiler.rs#L260). To avoid re-compiling `Trampoline`s for the same function signatures, `Trampoline`s are cached in the `SingleFunctionCompiler`.
This resolves the work started in bytecodealliance/cranelift#1231 and bytecodealliance#1436. Cranelift filetests currently have the ability to run CLIF functions with a signature like `() -> b*` and check that the result is true under the `test run` directive. This PR adds the ability to call functions with arbitrary arguments and non-boolean returns and either print the result or check against a list of expected results: - `run` commands look like `; run: %add(2, 2) == 4` or `; run: %add(2, 2) != 5` and verify that the executed CLIF function returns the expected value - `print` commands look like `; print: %add(2, 2)` and print the result of the function to stdout To make this work, this PR compiles a single Cranelift `Function` into a `CompiledFunction` using a `SingleFunctionCompiler`. Because we will not know the signature of the function until runtime, we use a `Trampoline` to place the values in the appropriate location for the calling convention; this should look a lot like what @alexcrichton is doing with `VMTrampoline` in wasmtime (see https://github.com/bytecodealliance/wasmtime/blob/3b7cb6ee64469470fcdd68e185abca8eb2a1b20a/crates/api/src/func.rs#L510-L526, https://github.com/bytecodealliance/wasmtime/blob/3b7cb6ee64469470fcdd68e185abca8eb2a1b20a/crates/jit/src/compiler.rs#L260). To avoid re-compiling `Trampoline`s for the same function signatures, `Trampoline`s are cached in the `SingleFunctionCompiler`.
This resolves the work started in bytecodealliance/cranelift#1231 and bytecodealliance#1436. Cranelift filetests currently have the ability to run CLIF functions with a signature like `() -> b*` and check that the result is true under the `test run` directive. This PR adds the ability to call functions with arbitrary arguments and non-boolean returns and either print the result or check against a list of expected results: - `run` commands look like `; run: %add(2, 2) == 4` or `; run: %add(2, 2) != 5` and verify that the executed CLIF function returns the expected value - `print` commands look like `; print: %add(2, 2)` and print the result of the function to stdout To make this work, this PR compiles a single Cranelift `Function` into a `CompiledFunction` using a `SingleFunctionCompiler`. Because we will not know the signature of the function until runtime, we use a `Trampoline` to place the values in the appropriate location for the calling convention; this should look a lot like what @alexcrichton is doing with `VMTrampoline` in wasmtime (see https://github.com/bytecodealliance/wasmtime/blob/3b7cb6ee64469470fcdd68e185abca8eb2a1b20a/crates/api/src/func.rs#L510-L526, https://github.com/bytecodealliance/wasmtime/blob/3b7cb6ee64469470fcdd68e185abca8eb2a1b20a/crates/jit/src/compiler.rs#L260). To avoid re-compiling `Trampoline`s for the same function signatures, `Trampoline`s are cached in the `SingleFunctionCompiler`.
This resolves the work started in bytecodealliance/cranelift#1231 and bytecodealliance#1436. Cranelift filetests currently have the ability to run CLIF functions with a signature like `() -> b*` and check that the result is true under the `test run` directive. This PR adds the ability to call functions with arbitrary arguments and non-boolean returns and either print the result or check against a list of expected results: - `run` commands look like `; run: %add(2, 2) == 4` or `; run: %add(2, 2) != 5` and verify that the executed CLIF function returns the expected value - `print` commands look like `; print: %add(2, 2)` and print the result of the function to stdout To make this work, this PR compiles a single Cranelift `Function` into a `CompiledFunction` using a `SingleFunctionCompiler`. Because we will not know the signature of the function until runtime, we use a `Trampoline` to place the values in the appropriate location for the calling convention; this should look a lot like what @alexcrichton is doing with `VMTrampoline` in wasmtime (see https://github.com/bytecodealliance/wasmtime/blob/3b7cb6ee64469470fcdd68e185abca8eb2a1b20a/crates/api/src/func.rs#L510-L526, https://github.com/bytecodealliance/wasmtime/blob/3b7cb6ee64469470fcdd68e185abca8eb2a1b20a/crates/jit/src/compiler.rs#L260). To avoid re-compiling `Trampoline`s for the same function signatures, `Trampoline`s are cached in the `SingleFunctionCompiler`.
This resolves the work started in bytecodealliance/cranelift#1231 and bytecodealliance#1436. Cranelift filetests currently have the ability to run CLIF functions with a signature like `() -> b*` and check that the result is true under the `test run` directive. This PR adds the ability to call functions with arbitrary arguments and non-boolean returns and either print the result or check against a list of expected results: - `run` commands look like `; run: %add(2, 2) == 4` or `; run: %add(2, 2) != 5` and verify that the executed CLIF function returns the expected value - `print` commands look like `; print: %add(2, 2)` and print the result of the function to stdout To make this work, this PR compiles a single Cranelift `Function` into a `CompiledFunction` using a `SingleFunctionCompiler`. Because we will not know the signature of the function until runtime, we use a `Trampoline` to place the values in the appropriate location for the calling convention; this should look a lot like what @alexcrichton is doing with `VMTrampoline` in wasmtime (see https://github.com/bytecodealliance/wasmtime/blob/3b7cb6ee64469470fcdd68e185abca8eb2a1b20a/crates/api/src/func.rs#L510-L526, https://github.com/bytecodealliance/wasmtime/blob/3b7cb6ee64469470fcdd68e185abca8eb2a1b20a/crates/jit/src/compiler.rs#L260). To avoid re-compiling `Trampoline`s for the same function signatures, `Trampoline`s are cached in the `SingleFunctionCompiler`.
This resolves the work started in bytecodealliance/cranelift#1231 and #1436. Cranelift filetests currently have the ability to run CLIF functions with a signature like `() -> b*` and check that the result is true under the `test run` directive. This PR adds the ability to call functions with arbitrary arguments and non-boolean returns and either print the result or check against a list of expected results: - `run` commands look like `; run: %add(2, 2) == 4` or `; run: %add(2, 2) != 5` and verify that the executed CLIF function returns the expected value - `print` commands look like `; print: %add(2, 2)` and print the result of the function to stdout To make this work, this PR compiles a single Cranelift `Function` into a `CompiledFunction` using a `SingleFunctionCompiler`. Because we will not know the signature of the function until runtime, we use a `Trampoline` to place the values in the appropriate location for the calling convention; this should look a lot like what @alexcrichton is doing with `VMTrampoline` in wasmtime (see https://github.com/bytecodealliance/wasmtime/blob/3b7cb6ee64469470fcdd68e185abca8eb2a1b20a/crates/api/src/func.rs#L510-L526, https://github.com/bytecodealliance/wasmtime/blob/3b7cb6ee64469470fcdd68e185abca8eb2a1b20a/crates/jit/src/compiler.rs#L260). To avoid re-compiling `Trampoline`s for the same function signatures, `Trampoline`s are cached in the `SingleFunctionCompiler`.
If return value of a run test is not boolean, an error is created with
the message "Function return type is not boolean, return value is {}".