summaryrefslogtreecommitdiff
path: root/src/tools/execution-results.h
Commit message (Collapse)AuthorAgeFilesLines
* Fuzz JSPI (#7148)Alon Zakai2024-12-161-0/+3
| | | | | | | | | | * Add a new "sleep" fuzzer import, that does a sleep for some ms. * Add JSPI support in fuzz_shell.js. This is in the form of commented-out async/await keywords - commented out so that normal fuzzing is not impacted. When we want to fuzz JSPI, we uncomment them. We also apply the JSPI operations of marking imports and exports as suspending/promising. JSPI fuzzing is added to both fuzz_opt.py and ClusterFuzz's run.py.
* Execution results: JS traps on exnref on the boundary (#7147)Alon Zakai2024-12-121-5/+5
| | | Fixes #7145
* Fuzzer: Add call-ref, call-ref-catch imports (#7137)Alon Zakai2024-12-091-8/+47
| | | | | | | | | | | | | | | Similar to call-export*, these imports call a wasm function from outside the module. The difference is that we send a function reference for them to call (rather than an export index). This gives more coverage, first by sending a ref from wasm to JS, and also since we will now try to call anything that is sent. Exports, in comparison, are filtered by the fuzzer to things that JS can handle, so this may lead to more traps, but maybe also some new situations. This also leads to adding more logic to execution-results.h to model JS trapping properly. fuzz_shell.js is refactored to allow sharing code between call-export* and call-ref*.
* [EH] Fuzz calls from JS by calling wasm exports, sometimes catching (#7067)Alon Zakai2024-11-081-1/+49
| | | | | | | | | | | | | | | | This adds two new imports to fuzzer modules: * call-export, which gets an export index and calls it. * call-export-catch, which does the call in a try-catch, swallowing any error, and returning 1 if it saw an error. The former gives us calls back into the wasm, possibly making various trips between wasm and JS in interesting ways. The latter adds a try-catch which helps fuzz wasm EH. We do these calls using a wasm export index, i.e., the index in the list of exports. This is simple, but it does have the downside that it makes executing the wasm sensitive to changes in exports (e.g. wasm-merge adds more), which requires some handling in the fuzzer.
* [wasm64] Make interpreter table methods operate on Address, not Index (#7062)Alon Zakai2024-11-071-2/+2
| | | This allows 64-bit bounds checking to work properly.
* Fuzz the Table from JS (#7042)Alon Zakai2024-10-311-6/+42
| | | | | Continues the work from #7027 which added throwing from JS, this adds table get/set operations from JS, to further increase our coverage of Wasm/JS interactions (the table can be used from both sides).
* [EH] Fuzz throws from JS (#7027)Alon Zakai2024-10-231-18/+29
| | | | | | | | | | | We already generated (throw ..) instructions in wasm, but it makes sense to model throws from outside as well, as they cross the module boundary. This adds a new fuzzer import to the generated modules, "throw", that just does a throw from JS etc. Also be more precise about handling fuzzing-support imports in fuzz-exec: we now check that logging functions start with "log*" and error otherwise (this check is now needed given we have "throw", which is not logging). Also fix a minor issue with name conflicts for logging functions by using getValidFunctionName for them, both for logging and for throw.
* Restore isString type methods (#6815)Thomas Lively2024-08-061-4/+2
| | | | | | | | | PR ##6803 proposed removing Type::isString and HeapType::isString in favor of more explicit, verbose callsites. There was no consensus to make this change, but it was accidentally committed as part of #6804. Revert the accidental change, except for the useful, noncontroversial parts, such as fixing the `isString` implementation and a few other locations to correctly handle shared types.
* [NFC] Add HeapType::getKind returning a new HeapTypeKind enum (#6804)Thomas Lively2024-08-061-2/+5
| | | | | | | | | | | | | | | | | The HeapType API has functions like `isBasic()`, `isStruct()`, `isSignature()`, etc. to test the classification of a heap type. Many users have to call these functions in sequence and handle all or most of the possible classifications. When we add a new kind of heap type, finding and updating all these sites is a manual and error-prone process. To make adding new heap type kinds easier, introduce a new API that returns an enum classifying the heap type. The enum can be used in switch statements and the compiler's exhaustiveness checker will flag use sites that need to be updated when we add a new kind of heap type. This commit uses the new enum internally in the type system, but follow-on commits will add new uses and convert uses of the existing APIs to use `getKind` instead.
* Fuzzer: Compare strings (#6530)Alon Zakai2024-04-241-11/+15
|
* Fuzzer: Match the logging of i31ref between JS and C++ (#6335)Alon Zakai2024-02-221-21/+35
| | | | | | | | | | | | | JS engines print i31ref as just a number, so we need a small regex to standardize the representation (similar to what we do for funcrefs on the code above). On the C++ side, make it actually print the i31ref rather than treat it like a generic reference (for whom we only print "object"). To do that we must unwrap an externalized i31 as necessary, and add a case for i31 in the printing logic. Also move that printing logic to its own function, as it was starting to get quite long.
* Fuzzer: Remove --emit-js-shell logic and reuse fuzz_shell.js instead (#6310)Alon Zakai2024-02-201-2/+12
| | | | | | | | | | | | | | | | | | | | | | | | | We had two JS files that could run a wasm file for fuzzing purposes: * --emit-js-shell, which emitted a custom JS file that runs the wasm. * scripts/fuzz_shell.js, which was a generic file that did the same. Both of those load the wasm and then call the exports in order and print out logging as it goes of their return values (if any), exceptions, etc. Then the fuzzer compares that output to running the same wasm in another VM, etc. The difference is that one was custom for the wasm file, and one was generic. Aside from that they are similar and duplicated a bunch of code. This PR improves things by removing 1 and using 2 in all places, that is, we now use the generic file everywhere. I believe we added 1 because we thought a generic file can't do all the things we need, like know the order of exports and the types of return values, but in practice there are ways to do those things: The exports are in fact in the proper order (JS order of iteration is deterministic, thankfully), and for the type we don't want to print type internals anyhow since that would limit fuzzing --closed-world. We do need to be careful with types in JS (see notes in the PR about the type of null) but it's not too bad. As for the types of params, it's fine to pass in null for them all anyhow (null converts to a number or a reference without error).
* Fix handling of exported imported functions (#6044)Alon Zakai2023-10-241-1/+1
| | | | | | | | Two trivial places did not handle that case, and assumed an exported function was actually defined (and not imported). Also add some const stuff to fix compilation after this change. This was discovered by #6026
* 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] Simplify the hang limit mechanism (#5513)Alon Zakai2023-02-231-5/+1
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | Previously the idea was that we started with HANG_LIMIT = 10 or so, and we'd decrement it by one in each potentially-recursive call and loop entry. When we reached 0 we'd start to unwind the stack. Then, after we unwound it all the way, we'd reset HANG_LIMIT before calling the next export. That approach adds complexity that each "execution wrapper", like for JS or for --fuzz-exec, had to manually reset HANG_LIMIT. That was done by calling an export. Calls to those exports had to appear in various places, which is sort of a hack. The new approach here does the following when the hang limit reaches zero: It resets HANG_LIMIT, and it traps. The trap unwinds the call stack all the way out. When the next export is called, it will have a fresh hang limit since we reset it before the trap. This does have downsides. Before, we did not always trap when we hit the hang limit but rather we'd emit something unreachable, like a return. The idea was that we'd leave the current function scope at least, so we don't hang forever. That let us still execute a small amount of code "on the way out" as we unwind the stack. I'm not sure it's worth the complexity for that. The advantages of this PR are to simplify the code, and also it makes more fuzzing approaches easy to implement. I'd like to add a wasm-ctor-eval fuzzer, and having to add hacks to call the hang limit init export in it would be tricky. With this PR, the execution model is simple in the fuzzer: The exports are called one by one, in order, and that's it - no extra magic execution needs to be done. Also bump the hang limit from 10 to 100, just to give some more chance for code to run.
* [Strings] Initial string execution support (#5491)Alon Zakai2023-02-151-1/+4
| | | | | | | | | | Store string data as GC data. Inefficient (one Const per char), but ok for now. Implement string.new_wtf16 and string.const, enough for basic testing. Create strings in makeConstantExpression, which enables ctor-eval support. Print strings in fuzz-exec which makes testing easier.
* Do not compare reference values across executions (#5276)Thomas Lively2022-11-171-18/+10
| | | | | | | Since we optimize assuming a closed world, optimizations can change the types and structure of GC data even in externally-visible ways. Because differences are expected, the fuzzer already did not compare reference-typed values from before and after optimizations when running with nominal typing. Update it to not compare these values under any type system.
* Switch from `typedef` to `using` in C++ code. NFC (#5258)Sam Clegg2022-11-151-1/+1
| | | | This is more modern and (IMHO) easier to read than that old C typedef syntax.
* Fuzzer simplification: Remove trap-ignoring logic (#4958)Alon Zakai2022-08-241-15/+2
| | | | | | | | | | | | | The "ignore trap" logic there is not close to enough for what we'd need to actually fuzz in a way that ignores traps, so this removes it. Atm that logic just allows a trap to happen without causing an error (that is, when comparing two results, one might trap and the other not, but they'd still be considered "equal"). But due to how we optimize traps in TrapsNeverHappens mode, the optimizer is free to assume the trap never occurs, which might remove side effects that are noticeable later. To actually handle that, we'd need to refactor the code to retain results per function (including the Loggings) and then to ignore everything from the very first trapping function. That is somewhat complicated to do, and a simpler thing is done in #4936, so we won't need it here.
* [NominalFuzzing] Don't compare nominal types in the fuzzer (#4603)Alon Zakai2022-04-211-3/+8
| | | | | The same module will have a different type after some transformations, even though that is not observable, like --roundtrip. Basically, we should not be comparing types between separate modules, which is what the fuzzer does.
* [NFC] Refactor ModuleInstanceBase+RuntimeExpressionRunner into a single ↵Alon Zakai2022-01-281-3/+3
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | class (#4479) As recently discussed, the interpreter code is way too complex. Trying to add ctor-eval stuff I need, I got stuck and ended up spending some time to get rid of some of the complexity. We had a ModuleInstanceBase class which was basically an instance of a module, that is, an execution of it. And internally we have RuntimeExpressionRunner which is a runner that integrates with the ModuleInstanceBase - basically, it uses the runtime info to execute code. For example, the MIB has globals info, and the RER would read it from there. But these two classes are really just one functionality - an execution of a module. We get rid of some complexity by removing the separation between them, ending up with a class that can run a module. One set of problems we avoid is that we can now extend the single class in a simple way. Before, we would need to extend both - and inform each other of those changes. That gets "fun" with CRTP which we use everywhere. In other words, each of the two classes depended on the other / would need to be templated on the other. Specifically, MIB.callFunction would need to be given the RER to run with, and so that would need to be templated on it. This ends up leading to a bunch more templating all around - all complexity that we just don't need. See the simplification to the wasm-ctor-eval for some of that (and even worse complexity would have been needed without this PR in the next steps for that tool to eval GC stuff). The final single class is now called ModuleRunner. Also fixes a pre-existing issue uncovered by this PR. We had the delegate target on the runner, but it should be tied to a function scope. This happened to not be a problem if one always created a new runner for each scope, but this PR makes the runner longer-lived, so the stale data ended up mattering. The PR moves that data to the proper place. Note: Diff without whitespace is far, far smaller.
* Fuzzer: Fix a missing return of a trap (#4485)Alon Zakai2022-01-281-0/+1
| | | | | We emitted the right text to stdout to indicate a trap in one code path, but did not return a Trap from the function. As a result, we'd continue and hit the assert on the next line.
* LiteralList => Literals (#4451)Alon Zakai2022-01-131-2/+2
| | | | | | | LiteralList overlaps with Literals, but is less efficient as it is not a SmallVector. Add reserve/capacity methods to SmallVector which are now necessary to compile.
* Compare traps in ExecutionResults (#4405)Heejin Ahn2021-12-291-22/+38
| | | | | | | | We used to only compare return values, and in #4369 we started comparing whether an uncaught exception was thrown. This also adds whether a trap occurred to `ExecutionResults`. So in `--fuzz-exec`, if a program with a trap loses the trap or vice versa, it will error out saying the result has changed, unless either of `--ignore-implicit-traps` or `--trans-never-happen` is set.
* [EH] Make interpreter handle uncaught exceptions (#4369)Heejin Ahn2021-12-061-24/+28
| | | | | | | | | When a wasm exception is thrown and uncaught in the interpreter, it caused the whole interpreter to crash, rather than gracefully reporting it. This fixes the problem, and also compares whether an uncaught exception happened when comparing the results before and after optimizations in `--fuzz-exec`. To do that, when `--fuzz-exec` is given, we now compare results even when the function does not have return values. Logs for some existing test have changed because of this.
* Modernize code to C++17 (#3104)Max Graey2021-11-221-2/+1
|
* [Wasm GC] Handle uses of default values in LocalSubtyping (#4024)Alon Zakai2021-07-281-1/+3
| | | | | | It is ok to use the default value of a reference even if we refine the type, as it would be a more specifically-typed null, and all nulls compare the same. However, if the default is used then we *cannot* alter the type to be non-nullable, as then we'd use a null where that is not allowed.
* Preserve Function HeapTypes (#3952)Thomas Lively2021-06-301-3/+3
| | | | | | | | | When using nominal types, func.ref of two functions with identical signatures but different HeapTypes will yield different types. To preserve these semantics, Functions need to track their HeapTypes, not just their Signatures. This PR replaces the Signature field in Function with a HeapType field and adds new utility methods to make it almost as simple to update and query the function HeapType as it was to update and query the Function Signature.
* Fuzzer: Distinguish traps from host limitations (#3801)Alon Zakai2021-04-121-0/+12
| | | | | | | | | Host limitations are arbitrary and can be modified by optimizations, so ignore them. For example, if the optimizer removes allocations then a host limit on an allocation error may vanish. Or, an optimization that removes recursion and replaces it with a loop may avoid a host limit on call depth (that is not done currently, but might some day). This removes a class of annoying false positives in the fuzzer.
* Fuzzing: Minor execution-results.h fixes (#3747)Alon Zakai2021-03-301-4/+28
| | | | | | | | | | | | Log out an i64 as two i32s. That keeps the output consistent regardless of whether we legalize. Do not print a reference result. The printed value cannot be compared, as funcref(10) (where 10 is the index of the function) is not guaranteed to be the same after opts. Trap when trying to call an export with a nondefaultable type (instead of asserting when trying to create zeros for it).
* [Fuzzer] Don't compare references, just their types (#3384)Alon Zakai2020-11-171-14/+44
| | | | | | | There are several issues here that we can't fully handle, see #3378, but basically we are comparing results between two separate wasm modules (and a separate instance of each) - we can't really identify an identical reference between such things. We can only compare things structurally, for which we compare the types.
* Handle get/setTempRet0 in fuzzer support (#3279)Alon Zakai2020-10-231-0/+13
| | | | | | | | This avoids it printing a warning and doing nothing for them. It also increases coverage, for checking 64-bit return values, but any such bug would have already been found already, I think (as we ignored the high bits), so likely the fuzzer is not emitting such things when running JS at least.
* Fuzzer: Handle log_execution instrumentation, and warn on unknown imports ↵Alon Zakai2020-10-211-0/+12
| | | | | | | | | | | | | | | | | | | | | | (#3271) log_execution can be useful to run on a fuzz testcase for debugging purposes. This adds support to --fuzz-exec for printing out those values. IOW, this PR allows the following debugging flow: you run wasm-opt --log-execution on the wasm, then run it in the fuzzer, wasm-opt --fuzz-exec[-before] and you get that logging printed out (showing where we enter functions, exit them, etc.). Also, in general --fuzz-exec ignores unknown imports (so that it can be run on more wasm files, for at least some fuzz testing there). This also adds a warning in that case, so it is less surprising (the behavior does not change in this PR).
* Refactor naming convention for functions handling tuples (#3196)Max Graey2020-10-091-1/+1
| | | When there are two versions of a function, one handling tuples and the other handling non-tuple values, the previous naming convention was to have "Single" in the name of the non-tuple handling function. This PR simplifies the convention and shortens function names by making the names plural for the tuple-handling version and singular for the non-tuple-handling version.
* Improve testing on Windows (#3142)Wouter van Oortmerssen2020-09-171-1/+1
| | | | | | This PR contains: - Changes that enable/disable tests on Windows to allow for better local testing. - Also changes many abort() into Fatal() when it is really just exiting on error. This is because abort() generates a dialog window on Windows which is not great in automated scripts. - Improvements to CMake to better work with the project in IDEs (VS).
* Fix RefNull issues (#3123)Daniel Wirtz2020-09-131-2/+3
| | | | | | | | | * ExpressionAnalyzer: Fix `ref.null ht` equality check to include `ht`. * Precompute: Fix `ref.null ht` expression reuse to also update `ht`. * Fuzzing: Fix `ref.null func` becoming canonicalized to `ref.func $funcref` when evaluating execution results, by adding a check for `isNull`. * Fuzzing: Print actual and expected execution results when aborting. * Tests: Update `if-arms-subtype` test in `optimize-instructions` to check that identical `if` arms become folded while not identical arms are kept.
* Update reference types (#3084)Daniel Wirtz2020-09-091-1/+1
| | | | | | | Align with the current state of the reference types proposal: * Remove `nullref` * Remove `externref` and `funcref` subtyping * A `Literal` of a nullable reference type can now represent `null` (previously was type `nullref`) * Update the tests and temporarily comment out those tests relying on subtyping
* Use const modifier when dealing with types (#3064)Daniel Wirtz2020-08-201-1/+1
| | | Since they make the code clearer and more self-documenting.
* Replace Type::expand() with an iterator-based approach (#3061)Daniel Wirtz2020-08-191-1/+1
| | | This leads to simpler code and is a prerequisite for #3012, which makes it so that not all `Type`s are backed by vectors that `expand` could return.
* [fuzzing] wasm2c integration (#2772)Alon Zakai2020-04-221-1/+0
| | | | | | | | | | | | | | | | | | | | | | | | | This adds support for fuzzing with wabt's wasm2c that @binji wrote. Basically we compile the wasm to C, then compile the C to a native executable with a custom main() to wrap around it. The executable should then print exactly the same as that wasm when run in either the binaryen interpreter or in a JS VM with our wrapper JS for that wasm. In other words, compiling the wasm to C is another way to run that wasm. The main reasons I want this are to fuzz wasm2c itself, and to have another option for fuzzing emcc. For the latter, we do fuzz wasm-opt quite a lot, but that doesn't fuzz the non-wasm-opt parts of emcc. And using wasm2c for that is nice since the starting point is always a wasm file, which means we can use tools like wasm-reduce and so forth, which can be integrated with this fuzzer. This also: Refactors the fuzzer harness a little to make it easier to add more "VMs" to run wasms in. Do not autoreduce when re-running a testcase, which I hit while developing this.
* Update Precompute to handle tuples (#2687)Thomas Lively2020-03-101-1/+1
| | | | | | This involves replacing `Literal::makeZero` with `Literal::makeZeroes` and `Literal::makeSingleZero` and updating `isConstantExpression` to handle constant tuples as well. Also makes `Literals` its own struct and adds convenience methods on it.
* Handle multivalue returns in the interpreter (#2684)Thomas Lively2020-03-101-14/+17
| | | | Updates the interpreter to properly flow vectors of values, including at function boundaries. Adds a small spec test for multivalue return.
* Add support for reference types proposal (#2451)Heejin Ahn2019-12-301-9/+15
| | | | | | | | | | | | This adds support for the reference type proposal. This includes support for all reference types (`anyref`, `funcref`(=`anyfunc`), and `nullref`) and four new instructions: `ref.null`, `ref.is_null`, `ref.func`, and new typed `select`. This also adds subtype relationship support between reference types. This does not include table instructions yet. This also does not include wasm2js support. Fixes #2444 and fixes #2447.
* Remove FunctionType (#2510)Thomas Lively2019-12-111-2/+2
| | | | | | | | | | | | | | | | | Function signatures were previously redundantly stored on Function objects as well as on FunctionType objects. These two signature representations had to always be kept in sync, which was error-prone and needlessly complex. This PR takes advantage of the new ability of Type to represent multiple value types by consolidating function signatures as a pair of Types (params and results) stored on the Function object. Since there are no longer module-global named function types, significant changes had to be made to the printing and emitting of function types, as well as their parsing and manipulation in various passes. The C and JS APIs and their tests also had to be updated to remove named function types.
* Multivalue type creation and inspection (#2459)Thomas Lively2019-11-221-1/+1
| | | | | | | | | | | | | Adds the ability to create multivalue types from vectors of concrete value types. All types are transparently interned, so their representation is still a single uint32_t. Types can be extracted into vectors of their component parts, and all the single value types expand into vectors containing themselves. Multivalue types are not yet used in the IR, but their creation and inspection functionality is exposed and tested in the C and JS APIs. Also makes common type predicates methods of Type and improves the ergonomics of type printing.
* clang-tidy braces changes (#2075)Alon Zakai2019-05-011-1/+2
| | | Applies the changes in #2065, and temprarily disables the hook since it's too slow to run on a change this large. We should re-enable it in a later commit.
* Apply format changes from #2048 (#2059)Alon Zakai2019-04-261-8/+9
| | | Mass change to apply clang-format to everything. We are applying this in a PR by me so the (git) blame is all mine ;) but @aheejin did all the work to get clang-format set up and all the manual work to tidy up some things to make the output nicer in #2048
* Compare binaryen fuzz-exec to JS VMs (#1856)Alon Zakai2019-01-101-13/+16
| | | | | | | | | | | The main fuzz_opt.py script compares JS VMs, and separately runs binaryen's fuzz-exec that compares the binaryen interpreter to itself (before and after opts). This PR lets us directly compare binaryen's interpreter output to JS VMs. This found a bunch of minor things we can do better on both sides, giving more fuzz coverage. To enable this, a bunch of tiny fixes were needed: * Add --fuzz-exec-before which is like --fuzz-exec but just runs the code before opts are run, instead of before and after. * Normalize double printing (so JS and C++ print comparable things). This includes negative zero in JS, which we never printed properly til now. * Various improvements to how we print fuzz-exec logging - remove unuseful things, and normalize the others across JS and C++. * Properly legalize the wasm when --emit-js-wrapper (i.e., we will run the code from JS), and use that in the JS wrapper code.
* Fuzzing v128 and associated bug fixes (#1827)Thomas Lively2018-12-141-1/+0
| | | | * Fuzzing v128 and associated bug fixes