Skip to content
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

Implement variant translation in fused adapters #4534

Merged
merged 3 commits into from
Jul 27, 2022

Conversation

alexcrichton
Copy link
Member

This commit implements the most general case of variants for fused
adapter trampolines. Additionally a number of other primitive types are
filled out here to assist with testing variants. The implementation
internally was relatively straightforward given the shape of variants,
but there's room for future optimization as necessary especially around
converting locals to various types.

This commit also introduces a "one off" fuzzer for adapters to ensure
that the generated adapter is valid. I hope to extend this fuzz
generator as more types are implemented to assist in various corner
cases that might arise. For now the fuzzer simply tests that the output
wasm module is valid, not that it actually executes correctly. I hope to
integrate with a fuzzer along the lines of #4307 one day to test the
run-time-correctness of the generated adapters as well, at which point
this fuzzer would become obsolete.

Finally this commit also fixes an issue with u8 translation where
upper bits weren't zero'd out and were passed raw across modules.
Instead smaller-than-32 types now all mask out their upper bits and do
sign-extension as appropriate for unsigned/signed variants.

This commit implements the most general case of variants for fused
adapter trampolines. Additionally a number of other primitive types are
filled out here to assist with testing variants. The implementation
internally was relatively straightforward given the shape of variants,
but there's room for future optimization as necessary especially around
converting locals to various types.

This commit also introduces a "one off" fuzzer for adapters to ensure
that the generated adapter is valid. I hope to extend this fuzz
generator as more types are implemented to assist in various corner
cases that might arise. For now the fuzzer simply tests that the output
wasm module is valid, not that it actually executes correctly. I hope to
integrate with a fuzzer along the lines of bytecodealliance#4307 one day to test the
run-time-correctness of the generated adapters as well, at which point
this fuzzer would become obsolete.

Finally this commit also fixes an issue with `u8` translation where
upper bits weren't zero'd out and were passed raw across modules.
Instead smaller-than-32 types now all mask out their upper bits and do
sign-extension as appropriate for unsigned/signed variants.
@alexcrichton alexcrichton marked this pull request as ready for review July 26, 2022 18:39
Currently memory64 isn't supported elsewhere in the component model
implementation of Wasmtime but the trampoline compiler seems as good a
place as any to ensure that it at least works in isolation. This plumbs
through fuzz input into a `memory64` boolean which gets fed into
compilation. Some miscellaneous bugs were fixed as a result to ensure
that memory64 trampolines all validate correctly.
Comment on lines +1 to +8
//! A simple fuzzer for FACT
//!
//! This is an intentionally small fuzzer which is intended to only really be
//! used during the development of FACT itself when generating adapter modules.
//! This creates arbitrary adapter signatures and then generates the required
//! trampoline for that adapter ensuring that the final output wasm module is a
//! valid wasm module. This doesn't actually validate anything about the
//! correctness of the trampoline, only that it's valid wasm.
Copy link
Member

Choose a reason for hiding this comment

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

Why not add this to the top level wasmtime/fuzz/* fuzz targets? You don't think it is worth spending oss-fuzz time on until we get the full blown value round tripping stuff working?

Copy link
Member Author

Choose a reason for hiding this comment

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

Yeah I don't think this really all that high value of a fuzz target since it's purely "is it a valid wasm module" which is a much weaker claim than "hey it actually works". Eventually when we're actually running these I think it makes sense to run on oss-fuzz but for now this is mostly just a development aide which is intended to help suss out corner cases (worked really well for a memory64 patch I'll post after this)


#[derive(Arbitrary, Debug)]
struct FuncType {
params: Vec<ValType>,
Copy link
Member

Choose a reason for hiding this comment

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

Might not want to derive(Arbitary) for FuncType as the params are potentially unbounded in length here, and I assume we have an implementation limit we want to stay below, right?

Copy link
Member

Choose a reason for hiding this comment

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

Alternatively, you could add a wrapper type for bounding Vec lengths similar to what you did for NonZeroLenVec.

Copy link
Member Author

Choose a reason for hiding this comment

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

While we do have limits in the system they're generally elsewhere at the wasmparser validation layer or the runtime implementation layer. Here in this specific compiler there are few limits imposed and at least so far nothing has blown up. If I run into issues locally with this though running the fuzzer I'll probably do the newtype trick.

Comment on lines +433 to +435
self.stack_get(stack, ValType::I32);
self.instruction(I32Const(0xffff));
self.instruction(I32And);
Copy link
Member

Choose a reason for hiding this comment

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

Huh. I didn't realize there wasn't an i32.extend8_u instruction. Strange there are signed extension instructions where there aren't corresponding unsigned variants. Yeah you can just do the masking, but also you can do the signed version via signed shifting back and forth. So why not omit or include both?

@sunfishcode do you happen to know the answer to the above, out of curiosity?

Copy link
Member Author

Choose a reason for hiding this comment

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

Double-checking again to make sure I didn't miss something, apparently there's i64.extend32_u but that's the only one.

@alexcrichton alexcrichton merged commit 285bc5c into bytecodealliance:main Jul 27, 2022
@alexcrichton alexcrichton deleted the translate-variant branch July 27, 2022 14:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants