Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Stack types#12015

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 ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Open
khagankhan wants to merge3 commits intobytecodealliance:main
base:main
Choose a base branch
Loading
fromkhagankhan:stack-types
Open

Conversation

@khagankhan
Copy link
Contributor

Stack fixup

We currently have every instruction balanced itself (for example, if an op leaves a struct onto the stack it immediately calls a function that consumes that struct) like we did for our generative fuzzer. However, for mutation based fuzzers this may have some bias.

This PR removes that and fixes the stack in the end. It keeps abstract stack types and check the required types then fixes the actual stack.

+cc@fitzgen@eeide

@khagankhankhagankhan requested a review froma team as acode ownerNovember 11, 2025 01:24
@khagankhankhagankhan requested review fromalexcrichton and removed request fora teamNovember 11, 2025 01:24
pub(crate)fn operand_types(&self) ->Vec<StackType>{
matchself{
// special-cases
Self::TakeTypedStructCall(t) => vec![StackType::Struct(Some(*t))],
Copy link
ContributorAuthor

Choose a reason for hiding this comment

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

I’d like to remove these “special cases” that require an index. The macro expansion doesn’t accept it and I’d rather not complicate the macro further. If you know a clean way to handle this, please share it with me. I’ll address it in the next PR anyway.

pub(crate)fn result_types(&self) ->Vec<StackType>{
matchself{
// special-cases
Self::StructNew(t) => vec![StackType::Struct(Some(*t))],
Copy link
ContributorAuthor

Choose a reason for hiding this comment

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

Same "special case" here

@khagankhan
Copy link
ContributorAuthor

@fitzgen Ready for review!

@github-actionsgithub-actionsbot added the fuzzingIssues related to our fuzzing infrastructure labelNov 11, 2025
@github-actions
Copy link

Subscribe to Label Action

cc@fitzgen

DetailsThis issue or pull request has been labeled: "fuzzing"

Thus the following users have been cc'd because of the following labels:

  • fitzgen: fuzzing

To subscribe or unsubscribe from this label, edit the.github/subscribe-to-label.json configuration file.

Learn more.

@alexcrichton
Copy link
Member

Thanks! Nick's out this week and I so far haven't had a chance to look at this. I may end up deferring this to Nick when he gets back as I'll otherwise have to boot back up on a lot of context here, but do you have other subsequent PRs ready to go which are built on this and so it'd be good to get this in sooner rather than later?

khagankhan reacted with heart emoji

@khagankhan
Copy link
ContributorAuthor

Hey Alex! I am mostly working on a repo on GitLab where I am ahead. The Wasmtime PRs tend to lag behind my current work because I address comments, failed tests etc. Since Nick and I meet weekly (except this week) and go over everything, I think it makes sense to defer this to him. Thank you for the comment!

alexcrichton reacted with thumbs up emoji

@alexcrichtonalexcrichton requested review fromfitzgen and removed request foralexcrichtonNovember 14, 2025 03:00
Copy link
Member

@fitzgenfitzgen left a comment

Choose a reason for hiding this comment

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

I'm back now, thanks for your patience!

khagankhan reacted with heart emoji
Comment on lines +272 to +276
match&mut op{
GcOp::StructNew(t) |GcOp::TakeStructCall(t) |GcOp::TakeTypedStructCall(t) =>{
if num_types >0{
*t =*t % num_types;
}
Copy link
Member

Choose a reason for hiding this comment

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

I think this fixing-up of ops should go inGcOp::fixup. We can addnum_types as a parameter there. And ifnum_types == 0, we should probably just remove this op, no? How do westruct.new or call a function that takes a concrete struct reference if we don't define any types?

/// The operations for the `gc` operations.
#[derive(Copy,Clone,Debug,Serialize,Deserialize)]
pub(crate)enumGcOp{
/// The operations that can be performed by the `gc` function.
Copy link
Member

Choose a reason for hiding this comment

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

Stylistically, it is quite rare to have the doc comment below the#[...] attributes. Mind reverting this code motion?


pubfn results_len(&self) ->usize{
#[allow(unreachable_patterns, reason ="macro-generated code")]
pub(crate)fn operand_types(&self) ->Vec<StackType>{
Copy link
Member

Choose a reason for hiding this comment

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

To avoid a ton of temporary allocations, and reuse a single allocation instead, let's have this method take a mutable vector as an out parameter:

Suggested change
pub(crate)fn operand_types(&self) ->Vec<StackType>{
pub(crate)fn operand_types(&self,types:&mutVec<StackType>){

let new_stack = stack - $params + $results;
Ok((op, new_stack))
#[allow(unreachable_patterns, reason ="macro-generated code")]
pub(crate)fn result_types(&self) ->Vec<StackType>{
Copy link
Member

Choose a reason for hiding this comment

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

And let's also do an out parameter here as well.

Comment on lines +414 to +418
fn $op(
_ctx:&mut mutatis::Context,
_limits:&GcOpsLimits,
stack:usize,
) -> mutatis::Result<(GcOp,usize)>{
Copy link
Member

Choose a reason for hiding this comment

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

Should this still be taking astack: usize and returning a newusize? Shouldn't it be taking astack: &mut Vec<StackType> now instead?

Copy link
ContributorAuthor

@khagankhankhagankhanDec 1, 2025
edited
Loading

Choose a reason for hiding this comment

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

I am back!!!

Does this also mean that when we generate a new op, we should also be checking type compatibility, not just maintaining stack depth?

@fitzgen

Copy link
Member

Choose a reason for hiding this comment

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

Does this also mean that when we generate a new op, we should also be checking type compatibility, not just maintaining stack depth?

Yes, we either have to do that (if we continue the existing approach) or else we switch to a new approach and instead just generate a random sequence of arbitrary ops and then rely on the fixup pass to make it valid. The latter might be easier long term, so that there is only one code path we have to maintain.

But also, backing up, we shouldn't really need togenerate op sequences from scratch. The whole point of using a mutation-based paradigm is that we can generate arbitrary inputs via a series of mutations over time. So, instead of generating whole op sequences, weshould be able to get away with something like

implGenerate<GcOps>forGcOpsMutator{fngenerate(&mutself,ctx:&mutContext) -> mutatis::Result<GcOps>{letmut ops =GcOps::default();for _in0..N{self.mutate(ctx,&mut ops)?;}Ok(ops)}}

(And we should probably build the generic version of this intomutatis directly eventually)

Copy link
ContributorAuthor

Choose a reason for hiding this comment

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

Awesome! That was the answer I needed. After addressing this I will push

Thanks a lot

Comment on lines +96 to +97
/// Any value is used for reauested operand not a type left on stack (only for Drop and specially handled ops)
Anything,
Copy link
Member

Choose a reason for hiding this comment

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

Let's align with the Wasm spec and call thisAnyRef.

We will eventually want to differentiate between(ref struct) and(ref any) and(ref eq) as well.

Aside: we will need to track nullability for all our different ref types eventually as well.

Comment on lines +114 to +120
// Anything can accept any type - just pop if available
// If stack is empty, synthesize null (anyref compatible)
if stack.pop().is_none(){
// Create a null externref
Self::emit(GcOp::Null(), stack, out, num_types);
stack.pop();// consume just-synthesized externref
}
Copy link
Member

Choose a reason for hiding this comment

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

(ref extern) is a different type hierarchy from(ref any), that is there is no single top type of everything, so there is no function that can takeanything and I want to make sure we don't build that assumption in here.

Backing up a bit: I am a bit confused about this function's purpose and why it is necessary. It seems like we shouldn't ever be changing the stack types, we should be only be doing the opposite: fixing up our ops given the types that are actually on the stack. The former doesn't make sense (we can't change what types are on the stack at this point without changing what instructions we emitted earlier).

Sign up for freeto join this conversation on GitHub. Already have an account?Sign in to comment

Reviewers

@fitzgenfitzgenfitzgen left review comments

At least 1 approving review is required to merge this pull request.

Assignees

No one assigned

Labels

fuzzingIssues related to our fuzzing infrastructure

Projects

None yet

Milestone

No milestone

Development

Successfully merging this pull request may close these issues.

3 participants

@khagankhan@alexcrichton@fitzgen

[8]ページ先頭

©2009-2025 Movatter.jp