-
Notifications
You must be signed in to change notification settings - Fork 1.4k
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
cranelift: Validate iconst
ranges
#6850
cranelift: Validate iconst
ranges
#6850
Conversation
iconst
rangesiconst
ranges
I think it's a good sign that the verifier is rejecting those tests. It's nice to confirm that it's detecting the problem that it was supposed to check for! That said, I think the way we should fix these tests is by changing the parser for the textual CLIF representation, in The first thing to note is that I believe So when parsing operands for that format, we can report a syntax error if that argument is Does that make sense? Feel free to do that in this PR, or make a separate PR for that change which we'll merge first, either way. |
After looking at the CLIF parser, it does make total sense. Thanks for the detailed explanation. 🙂 I have a somewhat working patch, I need to fix a few things and it should be good! |
Hi @jameysharp 👋 please see the message of my last commit: I'm facing some test breakage, I fixed a few ones, but many others seem to be related to the conversion from signed to unsigned integers. Maybe I should adapt the ranges in the verifier to allow both signed and unsigned use (-128 .. 255 instead of 0 .. 255 for i8) as initially proposed by @afonso360? 🙂 |
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 still don't think that we want to allow sign-extended values in iconst
instructions, and I don't think we need to.
Most of the remaining test failures are in the precise-output tests for the riscv64 backend, so I hope @afonso360 has time to take a look. There is one similar failure in each of x64 and s390x, and none in aarch64.
In all the failing precise-output tests, I think the backend is emitting constants where the upper bits are subsequently ignored so it doesn't matter what value they have, and this has changed only those upper bits. We need to verify that though. And it looks like riscv64 is missing an opportunity to use shorter sequences of instructions when those high bits don't matter.
cranelift/codegen/src/write.rs
Outdated
UnaryImm { imm, .. } => write!(w, " {}", imm), | ||
UnaryImm { imm, .. } => write!( | ||
w, | ||
" {}", | ||
Imm64::new(match dfg.ctrl_typevar(inst) { | ||
types::I8 => imm.bits() as i8 as i64, | ||
types::I16 => imm.bits() as i16 as i64, | ||
types::I32 => imm.bits() as i32 as i64, | ||
types::I64 => imm.bits(), | ||
_ => unreachable!(), | ||
}) | ||
), |
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.
The handful of test failures on your branch that are in filetests/filetests/egraph/
are because of this change: constants which were narrower than 64 bits were previously printed as unsigned, and are now printed as signed, but these tests expect the printed text to match what's in the test.
This change is harmless and I kind of like having these values printed the way you've done it, so you can fix the egraph tests by updating them to match the new format.
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.
OK! 🙂 The change in write.rs
was needed to fix a test case, but ended up breaking some others, as you said. I'll update those outputs.
One more thought: The fact that these backends produce different code based on the supposedly-ignored high bits of |
Hey, Just wanted to say that this is awesome work! Thanks for working on it. I'm going to look into the RISC-V failures, but It might take a bit. |
Would it make sense to store Uimm64 instead of Imm64 in |
Yes, I think so—but I think that's a much bigger change and we shouldn't try to do it in this PR. |
Alright! I'm waiting for a greenlight (or a fix) before updating the outputs of the tests, since I'm a total ISAs / assembly / compiler noob. After this PR is merged, I would be happy to work on replacing |
Now that #6915 is merged (thanks @afonso360!), hopefully most of the test failures will disappear in this PR. Are you comfortable rebasing on main and taking another look at which tests fail now? |
f1d2996
to
78a91bc
Compare
I updated the egraphs file-tests. There are 2 remaining failures: FAIL filetests/filetests/isa/x64/simd-lane-access-compile.clif: compile
FAIL filetests/filetests/isa/s390x/constants.clif: compile
|
@@ -206,7 +206,7 @@ block0(v0: i32): | |||
|
|||
; function %icmp_eq_smin(i32) -> i8 fast { | |||
; block0(v0: i32): | |||
; v1 = iconst.i32 0x8000_0000 | |||
; v1 = iconst.i32 0xffff_ffff_8000_0000 |
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.
@jameysharp this is not super clean, the parser could not re-parse this output, I don't know if it's a big deal
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, something's a little off about these tests, which appear to be sign-extending 32-bit constants to 64-bit when printing them. I think there's a bug in the writer but I haven't looked closely at it to figure out what that might be.
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 didn't check but most probably the Display instance for Imm64 is falling back to hex representation for big values. This particular example is a valid negative i32 value, but a big one, so maybe the Display implementation is falling back to unsigned 64-bit hexadecimal as it can't know it's a 32-bit value. We could add range checks in this Display instance and emit the right amount of hex digits; or I could remove my changes in the CLIF writer altogether and figure out another way of fixing the tests it solved.
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 see now. Before this PR, for constants narrower than 64 bits we were preserving whether the input was written as a negative number or not based on whether the Imm64 was sign-extended or zero-extended. So some of the egraph tests used small negative numbers on input and got negative numbers in the test expectations output; others used large enough positive numbers to have the high bit set, which were printed as positive hex numbers before but get sign-extended by your change to the writer now.
I think we should revert your change to the writer so it doesn't try to sign-extend constants, and then we'll probably just need to update the test expectations to reflect that some negative constants are printed as large positive hex values now.
This feels very close! @abrown and @uweigand, could you take a look at the test failures happening on this PR and check my reasoning about them? The diffs in the precise-output compile tests are in a comment above. For s390x, the failing test is: wasmtime/cranelift/filetests/filetests/isa/s390x/constants.clif Lines 4 to 18 in 62fdafa
I think the lowering rule in question is this one: wasmtime/cranelift/codegen/src/isa/s390x/inst.isle Lines 2985 to 2989 in 62fdafa
I'm guessing that callers are expected to ignore all but the least-significant 8 bits of That said, my guess is that we can just update this test expectation from "-1" to "255"/"0xff" and everything else will be good enough as-is. For x64, this is the failing test: wasmtime/cranelift/filetests/filetests/isa/x64/simd-lane-access-compile.clif Lines 185 to 215 in 62fdafa
When the x64 backend lowers wasmtime/cranelift/codegen/src/isa/x64/lower.isle Lines 4433 to 4434 in 62fdafa
I believe this is harmless because the value is used by |
The general assumption in the s390x back-end is that when holding an As to the caller's expectations, the platform ABI does indeed require all scalar integer types to be zero- or sign-extended to the full register width when passed in registers. However, this is implemented at the cranelift IR level by using
Agreed. |
|
Awesome: besides sorting out the writer change that's affecting the egraph tests, the last step for this PR is to update these two test expectations to match what the new parser implementation does.
I see it's the same opcode, but the immediate operand is only two bytes instead of four, right? Looking more carefully, I'm confused by the use of wasmtime/cranelift/codegen/src/isa/x64/inst.isle Lines 2568 to 2572 in 62fdafa
|
Add the following checks: `iconst.i8` immediate must be within 0 .. 2^8-1 `iconst.i16` immediate must be within 0 .. 2^16-1 `iconst.i32` immediate must be within 0 .. 2^32-1 Resolves bytecodealliance#3059
Modifies the parser for textual CLIF so that V in `iconst.T V` is parsed according to T. Before this commit, something like `iconst.i32 0xffff_ffff_ffff` was valid because all `iconst` were parsed the same as an `iconst.i64`. Now the above example will throw an error. Also, a negative immediate as in `iconst.iN -X` is now converted to `2^N - X`. This commit also fixes some broken tests.
78a91bc
to
3b5d25c
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.
Looks great to me! Let's see if this all passes CI and go ahead and merge it if so. Nice work!
Oh, though you still have it marked as a draft PR. Do you feel it's ready to merge? You should click the "Ready for review" button if so. |
@@ -189,11 +189,11 @@ block0: | |||
|
|||
; VCode: | |||
; block0: | |||
; lhi %r2, -1 | |||
; iilf %r2, 4294967295 |
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.
The instructions are different. Is this expected?
; br %r14 | ||
; | ||
; Disassembled: | ||
; block0: ; offset 0x0 | ||
; lhi %r2, -1 | ||
; iilf %r2, 0xffffffff |
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.
Same as above.
@jameysharp I think it's OK except for the 2 comments I made above. 🙂 |
Those two diffs are the same s390x instruction printed by two different disassemblers, so it's actually only one change. I looked at it before approving the PR earlier and decided that, although I don't know what the |
Nice to see this PR merged! Thanks for all your detailed explanations and guidance. This project is definitely beginner-friendly! 🚀 |
After bytecodealliance#6850 was merged, the s390x back-end now always uses iilf instead of lhi to load negative constants, which is a small code size regression. Fix the isle predicate to get back lhi whenever possible.
…6950) * Enhance `async` configuration of `bindgen!` macro (#6942) This commit takes a leaf out of `wiggle`'s book to enable bindings generation for async host functions where only some host functions are async instead of all of them. This enhances the `async` key with a few more options: async: { except_imports: ["foo"], only_imports: ["bar"], } This is beyond what `wiggle` supports where either an allow-list or deny-list can be specified (although only one can be specified). This can be useful if either the list of sync imports or the list of async imports is small. * cranelift-interpreter: Fix SIMD shifts and rotates (#6939) * cranelift-interpreter: Fix SIMD `ishl`/`{s,u}`shr * fuzzgen: Enable a few more ops * cranelift: Fix tests for {u,s}shr * fuzzgen: Change pattern matching arms for shifts Co-Authored-By: Jamey Sharp <[email protected]> --------- Co-authored-by: Jamey Sharp <[email protected]> * Partially revert CLI argument changes from #6737 (#6944) * Partially revert CLI argument changes from #6737 This commit is a partial revert of #6737. That change was reverted in #6830 for the 12.0.0 release of Wasmtime and otherwise it's currently slated to get released with the 13.0.0 release of Wasmtime. Discussion at today's Wasmtime meeting concluded that it's best to couple this change with #6925 as a single release rather than spread out across multiple releases. This commit is thus the revert of #6737, although it's a partial revert in that I've kept many of the new tests added to showcase the differences before/after when the change lands. This means that Wasmtime 13.0.0 will exhibit the same CLI behavior as 12.0.0 and all prior releases. The 14.0.0 release will have both a new CLI and new argument passing semantics. I'll revert this revert (aka re-land #6737) once the 13.0.0 release branch is created and `main` becomes 14.0.0. * Update release notes * riscv64: Use `PCRelLo12I` relocation on Loads (#6938) * riscv64: Use `PCRelLo12I` relocation on Loads * riscv64: Strenghten pattern matching when emitting Load's * riscv64: Clarify some of the load address logic * riscv64: Even stronger matching * Update Rust in CI to 1.72.0, clarify Wasmtime's MSRV (#6900) * Update Rust in CI to 1.72.0 * Update CI, tooling, and docs for MSRV This commit codifies an MSRV policy for Wasmtime at "stable minus two" meaning that the latest three releases of Rust will be supported. This is enforced on CI with a full test suite job running on Linux x86_64 with the minimum supported Rust version. The full test suite will use the latest stable version. A downside of this approach is that new changes may break MSRV support on non-Linux or non-x86_64 platforms and we won't know about it, but that's deemed a minor enough risk at this time. A minor fix is applied to Wasmtime's `Cargo.toml` to support Rust 1.70.0 instead of requiring Rust 1.71.0 * Fix installation of rust * Scrape MSRV from Cargo.toml * Cranelift is the same as Wasmtime's MSRV now, more words too * Fix a typo * aarch64: Use `RegScaled*` addressing modes (#6945) This commit adds a few cases to `amode` construction on AArch64 for using the `RegScaled*` variants of `AMode`. This won't affect wasm due to this only matching the sign-extension happening before the shift, but it should otherwise help non-wasm Cranelift use cases. Closes #6742 * cranelift: Validate `iconst` ranges (#6850) * cranelift: Validate `iconst` ranges Add the following checks: `iconst.i8` immediate must be within 0 .. 2^8-1 `iconst.i16` immediate must be within 0 .. 2^16-1 `iconst.i32` immediate must be within 0 .. 2^32-1 Resolves #3059 * cranelift: Parse `iconst` according to its type Modifies the parser for textual CLIF so that V in `iconst.T V` is parsed according to T. Before this commit, something like `iconst.i32 0xffff_ffff_ffff` was valid because all `iconst` were parsed the same as an `iconst.i64`. Now the above example will throw an error. Also, a negative immediate as in `iconst.iN -X` is now converted to `2^N - X`. This commit also fixes some broken tests. * cranelift: Update tests to match new CLIF parser * Some minor fixes and features for WASI and sockets (#6948) * Use `command::add_to_linker` in tests to reduce the number of times all the `add_to_linker` are listed. * Add all `wasi:sockets` interfaces currently implemented to both the sync and async `command` functions (this enables all the interfaces in the CLI for example). * Use `tokio::net::TcpStream::try_io` whenever I/O is performed on a socket, ensuring that readable/writable flags are set/cleared appropriately (otherwise once readable a socket is infinitely readable). * Add a `with_ambient_tokio_runtime` helper function to use when creating a `tokio::net::TcpStream` since otherwise it panics due to a lack of active runtime in a synchronous context. * Add `WouldBlock` handling to return a 0-length read. * Add an `--inherit-network` CLI flag to enable basic usage of sockets in the CLI. This will conflict a small amount with #6877 but should be easy to resolve, and otherwise this targets different usability points/issues than that PR. --------- Co-authored-by: Afonso Bordado <[email protected]> Co-authored-by: Jamey Sharp <[email protected]> Co-authored-by: Timothée Jourde <[email protected]>
This is now #6952 |
After #6850 was merged, the s390x back-end now always uses iilf instead of lhi to load negative constants, which is a small code size regression. Fix the isle predicate to get back lhi whenever possible.
This is a follow up to bytecodealliance#6850.
Resolves bytecodealliance#6965 Linked to bytecodealliance#3059 bytecodealliance#6850 bytecodealliance#6958 Co-authored-by: Afonso Bordado <[email protected]>
Resolves #6965 Linked to #3059 #6850 #6958 Co-authored-by: Afonso Bordado <[email protected]>
* cranelift: Validate `iconst` ranges Add the following checks: `iconst.i8` immediate must be within 0 .. 2^8-1 `iconst.i16` immediate must be within 0 .. 2^16-1 `iconst.i32` immediate must be within 0 .. 2^32-1 Resolves bytecodealliance#3059 * cranelift: Parse `iconst` according to its type Modifies the parser for textual CLIF so that V in `iconst.T V` is parsed according to T. Before this commit, something like `iconst.i32 0xffff_ffff_ffff` was valid because all `iconst` were parsed the same as an `iconst.i64`. Now the above example will throw an error. Also, a negative immediate as in `iconst.iN -X` is now converted to `2^N - X`. This commit also fixes some broken tests. * cranelift: Update tests to match new CLIF parser
…6952) After bytecodealliance#6850 was merged, the s390x back-end now always uses iilf instead of lhi to load negative constants, which is a small code size regression. Fix the isle predicate to get back lhi whenever possible.
Resolves bytecodealliance#6965 Linked to bytecodealliance#3059 bytecodealliance#6850 bytecodealliance#6958 Co-authored-by: Afonso Bordado <[email protected]>
Since bytecodealliance#6850, we've been able to rely on `iconst` instructions having their immediate operands' high bits zeroed before lowering. So a couple of places in `x64/lower.rs` can be expressed more simply now as a result. Out of an abundance of caution, I added a debug-assertion when constants are looked up during lowering, to check that earlier phases really did ensure the high bits are zero. I also got rid of an `expect` where a simple pattern-match will do.
Since bytecodealliance#6850, we've been able to rely on `iconst` instructions having their immediate operands' high bits zeroed before lowering. So a couple of places in `x64/lower.rs` can be expressed more simply now as a result. Out of an abundance of caution, I added a debug-assertion when constants are looked up during lowering, to check that earlier phases really did ensure the high bits are zero. I also got rid of an `expect` where a simple pattern-match will do.
Since #6850, we've been able to rely on `iconst` instructions having their immediate operands' high bits zeroed before lowering. So a couple of places in `x64/lower.rs` can be expressed more simply now as a result. Out of an abundance of caution, I added a debug-assertion when constants are looked up during lowering, to check that earlier phases really did ensure the high bits are zero. I also got rid of an `expect` where a simple pattern-match will do.
Add the following checks:
iconst.i8
immediate must be within 0 .. 2^8-1iconst.i16
immediate must be within 0 .. 2^16-1iconst.i32
immediate must be within 0 .. 2^32-1Resolves #3059
Explain why this change is needed:
As mentioned in #3059,
iconst
currently allows any immediate within the range of ani64
, even foriconst.i8
,iconst.i16
oriconst.i32
.This breaks some tests!
Running
cargo test
in/cranelift/codegen
returns successfully. I also added a few tests concerning the new checks.Running
cargo test
in/cranelift
returns some failures. For example:Which is expected if we forbid negative immediates, @jameysharp could you please confirm?
Running
cargo test
at the root of this repo returns a lot of failures, possibly related to negative immediates.This is my first contribution so this patch is probably broken.