summaryrefslogtreecommitdiff
path: root/src/tools
Commit message (Collapse)AuthorAgeFilesLines
* [NFC] Add a helper to get function DCE names in wasm-metadce (#5793)Alon Zakai2023-06-301-30/+15
|
* [wasm-metadce] Note ref.func connections + fix rooting of segment offsets ↵Jérôme Vouillon2023-06-291-13/+28
| | | | (#5791)
* Fix opt/shrink levels when running the optimizer multiple times, Part 2 (#5787)Alon Zakai2023-06-271-19/+39
| | | | | | | | | | | This is a followup to #5333 . That fixed the selection of which passes to run, but forgot to also fix the global state of the current optimize/shrink levels. This PR fixes that. As a result, running -O3 -Oz will now work as expected: the first -O3 will run the right passes (as #5333 fixed) and while running them, the global optimize/shrinkLevels will be -O3 (and not -Oz), which this PR fixes. A specific result of this is that -O3 -Oz used to inline less, since the invocation of inlining during -O3 thought we were optimizing for size. The new test verifies that we do fully inline in the first -O3 now.
* Fuzzing for Try and Throw (#5776)Alon Zakai2023-06-213-3/+79
|
* Fuzzer: Limit ArrayNew sizes most of the time (#5738)Alon Zakai2023-05-221-2/+11
|
* Reintroduce wasm-merge (#5709)Alon Zakai2023-05-162-0/+589
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | We used to have a wasm-merge tool but removed it for a lack of use cases. Recently use cases have been showing up in the wasm GC space and elsewhere, as people are using more diverse toolchains together, for example a project might build some C++ code alongside some wasm GC code. Merging those wasm files together can allow for nice optimizations like inlining and better DCE etc., so it makes sense to have a tool for merging. Background: * Removal: #1969 * Requests: * wasm-merge - why it has been deleted #2174 * Compiling and linking wat files #2276 * wasm-link? #2767 This PR is a compete rewrite of wasm-merge, not a restoration of the original codebase. The original code was quite messy (my fault), and also, since then we've added multi-memory and multi-table which makes things a lot simpler. The linking semantics are as described in the "wasm-link" issue #2767 : all we do is merge normal wasm files together and connect imports and export. That is, we have a graph of modules and their names, and each import to a module name can be resolved to that module. Basically, like a JS bundler would do for JS, or, in other words, we do the same operations as JS code would do to glue wasm modules together at runtime, but at compile time. See the README update in this PR for a concrete example. There are no plans to do more than that simple bundling, so this should not really overlap with wasm-ld's use cases. This should be fairly fast as it works in linear time on the total input code. However, it won't be as fast as wasm-ld, of course, as it does build Binaryen IR for each module. An advantage to working on Binaryen IR is that we can easily do some global DCE after merging, and further optimizations are possible later.
* [Wasm GC] wasm-ctor-eval: Handle cycles of data (#5685)Alon Zakai2023-05-051-57/+376
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | A cycle of data is something we can't just naively emit as wasm globals. If at runtime we end up, for example, with an object A that refers to itself, then we can't just emit (global $A (struct.new $A (global.get $A))) The struct.get is of this very global, and such a self-reference is invalid. So we need to break such cycles as we emit them. The simple idea used here is to find paths in the cycle that are nullable and mutable, and replace the initial value with a null that is fixed up later in the start function: (global $A (struct.new $A (ref.null $A))) (func $start (struct.set (global.get $A) (global.get $A))) ) This is not optimal in terms of breaking cycles, but it is fast (linear time) and simple, and does well in practice on j2wasm (where cycles in fact occur).
* [EH] Support assert_exception (#5684)Heejin Ahn2023-04-231-3/+19
| | | | | | | | `assert_exception` is similar to `assert_trap` but for exceptions, which is supported in the interpreter of the EH proposal (https://github.com/WebAssembly/exception-handling/tree/main/interpreter). We've been using `assert_trap` for both traps and exceptions, but this PR distinguishes them.
* Remove the ability to construct basic types in a TypeBuilder (#5678)Thomas Lively2023-04-192-113/+26
| | | | | | | | | | | This capability was originally introduced to support calculating LUBs in the equirecursive type system, but has not been needed for anything except tests since the equirecursive type system was removed. Since building basic heap types is no longer useful and was a source of significant complexity, remove the APIs that allowed it and the tests that used those APIs. Also remove test/example/type-builder.cpp, since a significant portion of it tested the removed APIs and the rest is already better tested in test/gtest/type-builder.cpp.
* Fuzzer: Use subtype consistently in make() (#5674)Alon Zakai2023-04-191-4/+4
|
* [Wasm GC] Fuzz array.copy and array.fill (#5663)Alon Zakai2023-04-172-4/+88
|
* Remove the nominal type system (#5672)Thomas Lively2023-04-173-62/+37
| | | | | And since the only type system left is the standard isorecursive type system, remove `TypeSystem` and its associated APIs entirely. Delete a few tests that only made sense under the isorecursive type system.
* [Wasm GC] Improve GC operation coverage by using locals more (#5661)Alon Zakai2023-04-172-19/+60
| | | | | | | | | | | | When we emit e.g. a struct.get's reference, this PR makes us prefer a non-nullable value, and even to reuse an existing local if possible. By doing that we reduce the risk of a trap, and also by using locals we end up testing operations on the same data, like this: x = new A(); x.a = .. foo(x.a) In contrast, without this PR each of those x. uses might be new A().
* Remove the --hybrid and --nominal command line options (#5669)Thomas Lively2023-04-144-47/+2
| | | | | After this change, the only type system usable from the tools will be the standard isorecursive type system. The nominal type system is still usable via the API, but it will be removed entirely in a follow-on PR.
* wasm-reduce: Add more passes (#5667)Alon Zakai2023-04-141-0/+6
|
* [Wasm GC] Casts of a non-nullable bottom type to non-null fail (#5645)Alon Zakai2023-04-121-6/+4
| | | | | | | | | | | Casting (ref nofunc) to (ref func) seems like it can succeed based on the rule of "if it's a subtype, it can cast ok." But the fuzzer found a corner case where that leads to a validation error (see testcase). Refactor the cast evaluation logic to handle uninhabitable refs directly, and return Unreachable for them (since the cast cannot even be reached). Also reorder the rule checks there to always check for a non-nullable cast of a bottom type (which always fails).
* [NFC] Refactor some old fuzzer code (#5658)Alon Zakai2023-04-121-13/+8
| | | | A return value was unused, and we have BranchUtils::operateOnScopeNameDefs now which can replace old manual code.
* [NFC] Refactor fuzzer array check logic (#5659)Alon Zakai2023-04-121-20/+30
|
* Fuzzer: When nested under makeTrivial(), avoid normal make() (#5657)Alon Zakai2023-04-122-0/+16
| | | | | | | | Without this, in certain complex operations we could end up calling a nested make() operation that included nontrivial things, which could cause problems. The specific problem I encountered was in fixAfterChanges() we tried to fix up a duplicate label, but calling makeTrivial() emitted something very large that happened to include a new block with a new label nested under a struct.get, and that block's label conflicted with a label we'd already processed.
* [Wasm GC] Fuzz struct.set and array.set (#5655)Alon Zakai2023-04-122-1/+73
|
* [Wasm GC] Fuzz struct.get and array.get (#5651)Alon Zakai2023-04-102-0/+71
|
* [NFC] Use the new getField() in the heap type fuzzer (#5643)Alon Zakai2023-04-071-17/+10
|
* Fuzzer: Improve mutate() (#5631)Alon Zakai2023-04-051-9/+33
| | | Don't use a fixed 10% chance to mutate, but pick a mutation rate in each function.
* Avoid imported memories in the fuzzer (#5626)Alon Zakai2023-04-051-12/+15
| | | | | | | We already did this for the first memory, and just needed to loop to handle initial content in the test suite that has multiple memories. Also clean up that code while I'm around, to avoid repeating wasm.memories[0] all the time.
* [Wasm GC] Fuzz struct.new and array.new (#5622)Alon Zakai2023-04-042-29/+48
| | | | | | | | | Repurpose makeBasicRef, makeCompoundRef to generate not just "constant" refs but any reference, and use those to create StructNew/ArrayNew. The key changes are to add makeCompoundRef to make(), and to make the function call make() for children, where possible, instead of just makeTrivial(). We also replace the i31-specific path with a call to makeBasicRef which handles i31 among other things.
* Use Names instead of indices to identify segments (#5618)Thomas Lively2023-04-041-5/+9
| | | | | | | | | | All top-level Module elements are identified and referred to by Name, but for historical reasons element and data segments were referred to by index instead. Fix this inconsistency by using Names to refer to segments from expressions that use them. Also parse and print segment names like we do for other elements. The C API is partially converted to use names instead of indices, but there are still many functions that refer to data segments by index. Finishing the conversion can be done in the future once it becomes necessary.
* [Wasm GC] Fuzz RefCast (#5617)Alon Zakai2023-04-032-7/+86
|
* [NFC] Remove our bespoke `make_unique` implementation (#5613)Thomas Lively2023-03-312-5/+5
| | | | This code predates our adoption of C++14 and can now be removed in favor of `std::make_unique`, which should be more efficient.
* Ensure a deterministic order in the type names section (#5590)Alon Zakai2023-03-201-0/+5
| | | | | | | | | Before this PR we iterated over an unordered set. Replace that with an iteration on a vector. (Also, the value in the set was not even used, so this should even be faster.) Add random names in the fuzzer to types, the lack of which is I believe the reason this was not detected before.
* [Wasm GC] Allow extern.externalize in globals (#5585)Alon Zakai2023-03-171-0/+5
| | | | | | | | | | This fixes wasm-ctor-eval on evalling a GC data structure that contains a field initialized with an externalized value. Per the spec this is a constant instruction and I verified that V8 allows this. Also add missing validation in wasm-ctor-eval of the output (which makes debugging this kind of thing a little easier).
* [Wasm GC] wasm-ctor-eval: Handle externalized data (#5582)Alon Zakai2023-03-161-4/+25
|
* [Wasm GC] Fuzz ref.test (#5577)Alon Zakai2023-03-162-0/+38
|
* Fuzzer: Generate both immutable and mutable globals (#5575)Alon Zakai2023-03-152-3/+8
|
* Fuzzer: Pick interesting subtypes in getSubType(HeapType) (#5573)Alon Zakai2023-03-152-7/+38
|
* Fix fuzzer emitting invalid constant expressions (#5571)Thomas Lively2023-03-131-19/+21
| | | | | | | | | | The fuzzer had code to avoid emitting `global.get` of locally defined (i.e. non-imported) globals in global initializers and data segment offsets, but that code only handled top-level `global.get` because it predated the extended-const proposal. Unfortunately this bug went undetected until #5557, which fixed the validator to make it reject invalid uses of `global.get` in constant expressions. Fix the bug so the validator no longer produces invalid modules.
* Fuzzer: Avoid emitting massive nested structs (#5564)Alon Zakai2023-03-131-7/+26
| | | | | | | | | | | The nesting limit of around 20 was enough to cause exponential blowup. A 20K input file lead to a 2GB wasm in one case I saw (!) which takes many seconds to fuzz. Instead, reduce the limit, and also check if random tells us that the random input is done; when that's done we should stop, which limits us to O(input size). Also do this for non-nullable types, and handle that in globals (we cannot emit a RefAsNulNull there, so switch the global type if necessary).
* Fuzzer: Limit array sizes (#5569)Alon Zakai2023-03-132-10/+4
| | | | | | Even with a 1% chance of a huge array, there is a second problem aside from hitting an allocation failure, which is DoS - building such a huge array of Literals takes noticeable time in the fuzzer. Instead, just limit array max sizes, which is consistent with what we do for struct sizes etc.
* Fuzzer: Emit fewer uninhabitable types in getSubType (#5563)Alon Zakai2023-03-101-0/+9
| | | | Only rarely return an uninhabitable subtype of an inhabitable one. This avoids a major source of uninhabitability and immediate traps.
* Fuzzer: Emit nulls with low probability in makeConstCompoundRef (#5559)Alon Zakai2023-03-102-18/+28
| | | | In particular, the removed code path here that did a RefAsNonNull of a null was causing a lot of code to just trap.
* Emit the fuzzer hashMemory function after modifications (#5558)Alon Zakai2023-03-092-47/+54
| | | | | | | | | | Previously we emitted it early, and would then modify it in random ways like other initial content. But this function is called frequently during execution, so if we were unlucky and modded that function to trap then basically all other functions would trap as well. After fixing this, some places assert on not having any functions or types to pick a random one from, so fix those places too.
* Integrate the heap type fuzzer into the main fuzzer (#5555)Alon Zakai2023-03-093-4/+36
| | | | | | | | | | | | | With this we generate random GC types that may be used in creating instructions later. We don't create many instructions yet, which will be the next step after this. Also add some trivial assertions in some places, that have helped debugging in the past. Stop fuzzing TypeMerging for now due to #5556 , which this PR uncovers.
* Fuzzer: Pick from existing heap types in the module (#5539)Alon Zakai2023-03-082-5/+46
|
* Refactor type fuzzer to expose `getInhabitable` API (#5552)Thomas Lively2023-03-083-76/+88
| | | | | The main fuzzer needs to be able to filter out uninhabitable types and the type fuzzer has code for finding uninhabitable types. Move and refactor the code to expose a `getInhabitable` function that can be used for both purposes.
* Skip function references when detecting uninhabitable types (#5545)Thomas Lively2023-03-032-25/+28
| | | | | | Function references are always inhabitable because functions can be created with any function type, even types that refer to uninhabitable types. Take advantage of this by skipping function references when finding non-nullable reference cycles that cause uninhabitability.
* Fix type printing in the type fuzzer (#5543)Thomas Lively2023-03-031-4/+3
| | | | | | In #5437 we updated type printing so that printing a heap type would print its name in addition to its contents. We had already been separately printing type names in the type fuzzer, so after that change we were printing each type name twice. Remove the redundant printing in the fuzzer to fix the error.
* Add a fuzzer utility for ensuring types are inhabitable (#5541)Thomas Lively2023-03-033-3/+482
| | | | | | | | | | | | | | Some valid GC types, such as non-nullable references to bottom heap types and types that contain non-nullable references to themselves, are uninhabitable, meaning it is not possible to construct values of those types. This can cause problems for the fuzzer, which generally needs to be able to construct values of arbitrary types. To simplify things for the fuzzer, introduce a utility for transforming type graphs such that all their types are inhabitable. The utility performs a DFS to find cycles of non-nullable references and breaks those cycles by introducing nullability. The new utility is itself fuzzed in the type fuzzer.
* Fuzzer: Be careful with ArrayNew sizes (#5537)Alon Zakai2023-03-011-1/+11
| | | | Only very rarely ask to create a huge array, as that can easily hit a host size limit and cause a run to be ignored.
* Fuzzer: Ignore host limits (#5536)Alon Zakai2023-03-011-4/+10
| | | | | We can't just skip host limits (#5534) but must also ignore execution at that point, as optimizations can change the results if they change whether we reach a host limit.
* Fuzzer: Handle HostLimitException during instance creation (#5534)Alon Zakai2023-03-011-0/+5
| | | | We handle this like the existing handling of TrapException: we skip running this module (since we can't even instantiate it, so there is nothing to run).
* Fuzzer: Only use RefAs in a function context (#5533)Alon Zakai2023-03-011-1/+4
| | | It is not a constant instruction and cannot be used in globals.