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

Fuzzer: Generate TryTables #6987

Merged
merged 11 commits into from
Oct 7, 2024
Merged

Fuzzer: Generate TryTables #6987

merged 11 commits into from
Oct 7, 2024

Conversation

kripken
Copy link
Member

@kripken kripken commented Oct 4, 2024

Also make Try/TryTables with type none, and not just concrete types as before.

@kripken kripken requested a review from aheejin October 4, 2024 20:24
Comment on lines 1695 to 1699
if (funcContext->breakableStack.empty()) {
// Nothing to break to.
// TODO: Perhaps generate a block wrapping us?
return makeTrivial(type);
}
Copy link
Member

Choose a reason for hiding this comment

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

We can actually make a trivial try_table that doesn't need branches (not sure how much it would help fuzzing though)

try_table (result type)
  ...
end_try_table

Copy link
Member Author

Choose a reason for hiding this comment

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

Oh, good point. I think that is better, as it could catch something. It also makes the code simpler. I updated to do that now.


// If we found nothing, give up.
if (catchTags.empty()) {
return makeTrivial(type);
Copy link
Member

Choose a reason for hiding this comment

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

Here too we can make a trivial try_table

std::vector<Name> catchTags;
std::vector<Name> catchDests;
std::vector<bool> catchRefs;
auto numTags = upTo(MAX_TRY_CATCHES);
Copy link
Member

Choose a reason for hiding this comment

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

How about numCatches, given that some catches don't have tags?

Copy link
Member Author

Choose a reason for hiding this comment

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

Good idea, renamed.

tagName = tag->name;
tagType = tag->sig.params;
} else {
// Look for a catch_all at the end, some of the time (but all of the time
Copy link
Member

Choose a reason for hiding this comment

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

What do you mean "Look for"? Aren't we generating a catch_all here, not looking for (an already existing) one?

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, that was written poorly, thanks. Fixed.

auto valueType = getTargetType(target);
if (valueType == tagType || valueType == tagTypeWithExn) {
catchTags.push_back(tagName);
catchDests.push_back(name);
Copy link
Member

Choose a reason for hiding this comment

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

Maybe destName or dest or something to be distinguished from tagName?

Copy link
Member Author

Choose a reason for hiding this comment

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

Renamed.

for (auto t : tagType) {
vec.push_back(t);
}
vec.push_back(Type(HeapType::exn, Nullable)); // TODO: NonNullable?
Copy link
Member

Choose a reason for hiding this comment

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

Isn't exnref ref null exn? Why would we need a nonnullable exnref?

Copy link
Member Author

Choose a reason for hiding this comment

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

I wasn't sure what the spec allows. Don't we always send a non-nullable exnref, if an exception is thrown? If so then the target block could be non-nullable too, like this?

(block $block (ref exn) ;; non-nullable
  (try_table (catch_all $block)
    ..
  )
)

Or does the spec say to use a nullable value for some reason?

Copy link
Member

Choose a reason for hiding this comment

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

I'm not sure. Given that exnref values generated from try_table will never be null, I think allowing the non-nullable type makes sense though. I asked the question in the EH repo: WebAssembly/exception-handling#336

Copy link
Member

Choose a reason for hiding this comment

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

It looks the non-nullable version is allowed:
WebAssembly/exception-handling#336 (comment)

Copy link
Member Author

Choose a reason for hiding this comment

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

Oh cool, thanks. I added support for that now.

Copy link
Member

@aheejin aheejin left a comment

Choose a reason for hiding this comment

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

We are not sure whether the non-nullable exnref type is allowed, but I don't think that's necessarily a blocker anyway. Thanks!

@kripken kripken merged commit 1eb0126 into WebAssembly:main Oct 7, 2024
13 checks passed
@kripken kripken deleted the fuzz.exn.gen branch October 7, 2024 23:57
kripken added a commit that referenced this pull request Oct 17, 2024
When EH+GC are enabled then wasm has non-nullable types, and the
sent exnref should be non-nullable. In BinaryenIR we use the non-
nullable type all the time, which we also do for function references
and other things; we lower it if GC is not enabled to a nullable type
for the binary format (see `WasmBinaryWriter::writeType`, to which
comments were added in this PR). That is, this PR makes us handle
exnref the same as those other types.

A new test verifies that behavior. Various existing tests are updated
because ReFinalize will now use the more refined type, so this is
an optimization. It is also a bugfix as in #6987 we started to emit
the refined form in the fuzzer, and this PR makes us handle it
properly in validation and ReFinalization.
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