summaryrefslogtreecommitdiff
path: root/src/wasm/wasm-validator.cpp
Commit message (Collapse)AuthorAgeFilesLines
* Preserve Function HeapTypes (#3952)Thomas Lively2021-06-301-14/+14
| | | | | | | | | 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.
* [EH] Make tag's attribute encoding detail (#3947)Heejin Ahn2021-06-211-4/+0
| | | | | | | | | This removes `attribute` field from `Tag` class, making the reserved and unused field known only to binary encoder and decoder. This also removes the `attribute` parameter from `makeTag` and `addTag` methods in wasm-builder.h, C API, and Binaryen JS API. Suggested in https://github.com/WebAssembly/binaryen/pull/3946#pullrequestreview-687756523.
* [EH] Replace event with tag (#3937)Heejin Ahn2021-06-181-21/+20
| | | | | | | | | | | We recently decided to change 'event' to 'tag', and to 'event section' to 'tag section', out of the rationale that the section contains a generalized tag that references a type, which may be used for something other than exceptions, and the name 'event' can be confusing in the web context. See - https://github.com/WebAssembly/exception-handling/issues/159#issuecomment-857910130 - https://github.com/WebAssembly/exception-handling/pull/161
* [Wasm GC] Add experimental support for non-nullable locals (#3932)Alon Zakai2021-06-151-0/+3
| | | | | | | | | | | | | | This adds a new feature flag, GCNNLocals that enables support for non-nullable locals. No validation is applied to check that they are actually assigned before their use yet - this just allows experimentation to begin. This feature is not enabled by default even with -all. If we enabled it, then it would take effect in most of our tests and likely confuse current users as well. Instead, the flag must be opted in explicitly using --enable-gc-nn-locals. That is, this is an experimental feature flag, and as such must be explicitly enabled. (Once the spec stabilizes, we will remove the feature anyhow when we implement the final status of non-nullability. )
* [EH] Allow catch/delegate-less trys (#3924)Heejin Ahn2021-06-101-3/+0
| | | | This removes the restriction that `try` should have at least one `catch`/`catch_all`/`delegate`. See WebAssembly/exception-handling#157.
* [Wasm GC] Properly validate BrOn* (#3928)Alon Zakai2021-06-081-1/+1
| | | | | | The noteBreak call was in the wrong place, causing us to not note breaks from BrOnNull for example, which could make validation miss errors. Noticed in #3926
* [Wasm GC] Add negated BrOn* operations (#3913)Alon Zakai2021-06-021-2/+2
| | | | | | They are basically the flip versions. The only interesting part in the impl is that their returned typed and sent types are different. Spec: https://docs.google.com/document/d/1DklC3qVuOdLHSXB5UXghM_syCh-4cMinQ50ICiXnK3Q/edit
* [Wasm GC] Add experimental array.copy (#3911)Alon Zakai2021-05-271-0/+26
| | | | | | | | Spec for it is here: https://docs.google.com/document/d/1DklC3qVuOdLHSXB5UXghM_syCh-4cMinQ50ICiXnK3Q/edit# Also reorder some things in wasm.h that were not in the canonical order (that has no effect, but it is confusing to read).
* Remove Type ordering (#3793)Thomas Lively2021-05-181-1/+1
| | | | | | | | | As found in #3682, the current implementation of type ordering is not correct, and although the immediate issue would be easy to fix, I don't think the current intended comparison algorithm is correct in the first place. Rather than try to switch to using a correct algorithm (which I am not sure I know how to implement, although I have an idea) this PR removes Type ordering entirely. In places that used Type ordering with std::set or std::map because they require deterministic iteration order, this PR uses InsertOrdered{Set,Map} instead.
* Rename SIMD extending load instructions (#3798)Daniel Wirtz2021-04-121-6/+6
| | | | | | | | | Renames the SIMD instructions * LoadExtSVec8x8ToVecI16x8 -> Load8x8SVec128 * LoadExtUVec8x8ToVecI16x8 -> Load8x8UVec128 * LoadExtSVec16x4ToVecI32x4 -> Load16x4SVec128 * LoadExtUVec16x4ToVecI32x4 -> Load16x4UVec128 * LoadExtSVec32x2ToVecI64x2 -> Load32x2SVec128 * LoadExtUVec32x2ToVecI64x2 -> Load32x2UVec128
* Rename various SIMD load instructions (#3795)Daniel Wirtz2021-04-111-6/+6
| | | | | | | | | Renames the SIMD instructions * LoadSplatVec8x16 -> Load8SplatVec128 * LoadSplatVec16x8 -> Load16SplatVec128 * LoadSplatVec32x4 -> Load32SplatVec128 * LoadSplatVec64x2 -> Load64SplatVec128 * Load32Zero -> Load32ZeroVec128 * Load64Zero -> Load64ZeroVec128
* RefFunc: Validate that the type is non-nullable, and avoid possible bugs in ↵Alon Zakai2021-04-081-0/+2
| | | | | | | | the builder (#3790) The builder can receive a HeapType so that callers don't need to set non-nullability themselves. Not NFC as some of the callers were in fact still making it nullable.
* Add v128.load/storeN_lane SIMD instructions to C/JS API (#3784)Daniel Wirtz2021-04-081-8/+8
| | | | | | | | | | | Adds C/JS APIs for the SIMD instructions * Load8LaneVec128 (was LoadLaneVec8x16) * Load16LaneVec128 (was LoadLaneVec16x8) * Load32LaneVec128 (was LoadLaneVec32x4) * Load64LaneVec128 (was LoadLaneVec64x2) * Store8LaneVec128 (was StoreLaneVec8x16) * Store16LaneVec128 (was StoreLaneVec16x8) * Store32LaneVec128 (was StoreLaneVec32x4) * Store64LaneVec128 (was StoreLaneVec64x2)
* [RT] Add type to tables and element segments (#3763)Abbas Mashayekh2021-04-061-7/+76
|
* Update SIMD names and opcodes (#3771)Thomas Lively2021-04-051-21/+21
| | | | Also removes experimental SIMD instructions that were not included in the final spec proposal.
* Scan module-level code in necessary places (#3744)Alon Zakai2021-03-291-0/+14
| | | | | | | | | | | | | | | | | | Several old passes like DeadArgumentElimination and DuplicateFunctionElimination need to look at all ref.funcs, and they scanned functions for that, but that is not enough as such an instruction might appear in a global initializer. To fix this, add a walkModuleCode method. walkModuleCode is useful when doing the pattern of creating a function-parallel pass to scan functions quickly, but we also want to do the same scanning of code at the module level. This allows doing so in a single line. (It is also possible to just do walk() on the entire module, which will find all code, but that is not function-parallel. Perhaps we should have a walkParallel() option to simplify this further in a followup, and that would call walkModuleCode afterwards etc.) Also add some missing validation and comments in the validator about issues that I noticed in relation to the new testcases here.
* [Wasm GC] Properly validate struct.new number of operands (#3726)Alon Zakai2021-03-251-9/+10
|
* Validator: Pass the module along when printing errors, so type names are ↵Alon Zakai2021-03-241-7/+10
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | used (#3727) For example, on this invalid wat: (module (type $vec (struct (field i64))) (func $test (drop (struct.new_with_rtt $vec (i32.const 1) (rtt.canon $vec)) ) ) ) We used to print: [wasm-validator error in function test] struct.new operand must have proper type, on (struct.new_with_rtt ${i64} (i32.const 1) (rtt.canon ${i64}) ) We will now print: [wasm-validator error in function test] struct.new operand must have proper type, on (struct.new_with_rtt $vec (i32.const 1) (rtt.canon $vec) ) Note that $vec is used. In real-world examples the autogenerated structural name can be huge, which this avoids.
* [Wasm GC] Validate the number of arguments in struct.new (#3723)Alon Zakai2021-03-241-0/+4
|
* [RT] Support expressions in element segments (#3666)Abbas Mashayekh2021-03-241-7/+37
| | | | | | This PR adds support for `ref.null t` as a valid element segment item. The abbreviated format of `(elem ... func $f $g...)` is kept in both printing and binary emitting if all items are `ref.func`s. Public APIs aren't updated in this PR.
* [Wasm GC] Add support for non-nullable types, all except for locals (#3710)Alon Zakai2021-03-231-3/+1
| | | | | | | | | | | | | | | | | | | | | | After this PR we still do not support non-nullable locals. But we no longer turn all types into nullable upon load. In particular, we support non-nullable types on function parameters and struct fields, etc. This should be enough to experiment with optimizations in both binaryen and in VMs regarding non- nullability (since we expect that optimizing VMs can do well inside functions anyhow; it's non-nullability across calls and from data that the VM can't be expected to think about). Let is handled as before, by lowering it into gets and sets. In addition, we turn non-nullable locals into nullable ones, and add a ref.as_non_null on all their gets (to keep the type identical there). This is used not just for loading code with a let but also is needed after inlining. Most of the code changes here are removing FIXMEs for allowing non-nullable types. But there is also code to handle the issues mentioned above. Most of the test updates are removing extra nulls that we added before when we turned all types nullable. A few tests had actual issues, though, and also some new tests are added to cover the code changes here.
* [Wasm GC] Validate static subtyping in rtt.sub (#3696)Alon Zakai2021-03-161-0/+3
| | | | Also add more spec tests, including one that verifies we validate rtt.sub and on a global location as fixed by #3694
* Validate code in global data structures (#3694)Alon Zakai2021-03-161-3/+14
| | | | | | This validation is almost never needed, but it starts to get interesting with GC, where a global initializer can be an rtt.sub which must be valid. No tests here as testing requires a further GC fix in a later PR.
* Remove LUB calculation (#3669)Thomas Lively2021-03-111-80/+23
| | | | | | | | Since correct LUB calculation for recursive types is complicated, stop depending on LUBs throughout the code base. This also fixes a validation bug in which the validator required blocks to be typed with the LUB of all the branch types, when in fact any upper bound should have been valid. In addition to fixing that bug, this PR simplifies the code for break handling by not storing redundant information about the arity of types.
* Make unreachable a subtype of everything (#3673)Thomas Lively2021-03-111-87/+56
| | | | | | | Since in principle an unreachable expression can be used in any position. An exception to this rule is in OptimizeInstructions, which avoids replacing concrete expressions with unreachable expressions so that it doesn't need to refinalize any expressions. Notably, Type::getLeastUpperBound was already treating unreachable as the bottom type.
* [Wasm GC] Allow set values to be subtypes (#3665)Alon Zakai2021-03-091-8/+8
|
* [reference-types] Support passive elem segments (#3572)Abbas Mashayekh2021-03-051-13/+17
| | | | | | | | | | | Passive element segments do not belong to any table, so the link between Table and elem needs to be weaker; i.e. an elem may have a table in case of active segments, or simply be a collection of function references in case of passive/declarative segments. This PR takes Table::Segment out and turns it into a first class module element just like tables and functions. It also implements early support for parsing, printing, encoding and decoding passive/declarative elem segments.
* [Wasm Exceptions] Properly ensure unique Try labels after an inlining (#3632)Alon Zakai2021-03-011-0/+3
| | | | | | | | | The old code here just referred to Block and Loop. Refactor it to use the generic helper code that also handles Try. Also add validation of Try names in the validator. The testcase here would have $label appear twice before this fix. After the fix there is $label0 for one of them.
* Use enum instead of bool for StackSignature kind (#3625)Thomas Lively2021-02-261-5/+9
| | | | | As a readability improvement, use an enum with `Polymorphic` and `Fixed` variants to represent the polymorphic behavior of StackSignatures rather than a `bool uneachable`.
* [Wasm GC] Add array.wast and validator fixes for it (#3622)Alon Zakai2021-02-261-0/+1
|
* Support 64-bit data segment init-exps in Memory64 (#3593)Wouter van Oortmerssen2021-02-251-8/+17
| | | This as a consequence of https://reviews.llvm.org/D95651
* [EH] Make rethrow's target a try label (#3568)Heejin Ahn2021-02-181-14/+22
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | I was previously mistaken about `rethrow`'s argument rule and thought it only counted `catch`'s depth. But it turns out it follows the same rule `delegate`'s label: the immediate argument follows the same rule as when computing branch labels, but it only can target `try` labels (semantically it targets that `try`'s corresponding `catch`); otherwise it will be a validation failure. Unlike `delegate`, `rethrow`'s label denotes not where to rethrow, but which exception to rethrow. For example, ```wasm try $l0 catch ($l0) try $l1 catch ($l1) rethrow $l0 ;; rethrow the exception caught by 'catch ($l0)' end end ``` Refer to this comment for the more detailed informal semantics: https://github.com/WebAssembly/exception-handling/issues/146#issuecomment-777714491 --- This also reverts some of `delegateTarget` -> `exceptionTarget` changes done in #3562 in the validator. Label validation rules apply differently for `delegate` and `rethrow` for try-catch. For example, this is valid: ```wasm try $l0 try delegate $l0 catch ($l0) end ``` But this is NOT valid: ```wasm try $l0 catch ($l0) try delegate $l0 end ``` So `try`'s label should be used within try-catch range (not catch-end range) for `delegate`s. But for the `rethrow` the rule is different. For example, this is valid: ```wasm try $l0 catch ($l0) rethrow $l0 end ``` But this is NOT valid: ```wasm try $l0 rethrow $l0 catch ($l0) end ``` So the `try`'s label should be used within catch-end range instead.
* [EH] Rename delegateTarget to exceptionTarget (NFC) (#3562)Heejin Ahn2021-02-131-8/+8
| | | | | | | | | | | | | So far `Try`'s label is only targetted by `delegate`s, but it turns out `rethrow` also has to follow the same rule as `delegate` so it needs to target a `Try` label. So this renames variables like `delegateTargetNames` to `exceptionTargetNames` and methods like `replaceDelegateTargets` to `replaceExceptionTargets`. I considered `tryTarget`, but the branch/block counterpart name we use is not `blockTarget` but `branchTarget`, so I chose `exceptionTarget`. The patch that fixes `rethrow`'s target will follow; this is the preparation for that.
* [EH] Support reading/writing of delegate (#3561)Heejin Ahn2021-02-121-1/+67
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | This adds support for reading/writing of the new `delegate` instruction in the folded wast format, the stack IR format, the poppy IR format, and the binary format in Binaryen. We don't have a formal spec written down yet, but please refer to WebAssembly/exception-handling#137 and WebAssembly/exception-handling#146 for the informal semantics. In the current version of spec `delegate` is basically a rethrow, but with branch-like immediate argument so that it can bypass other catches/delegates in between. `delegate` is not represented as a new `Expression`, but it is rather an option within a `Try` class, like `catch`/`catch_all`. One special thing about `delegate` is, even though it is written _within_ a `try` in the folded wat format, like ```wasm (try (do ... ) (delegate $l) ) ``` In the unfolded wat format or in the binary format, `delegate` serves as a scope end instruction so there is no separate `end`: ```wasm try ... delegate $l ``` `delegate` semantically targets an outer `catch` or `delegate`, but we write `delegate` target as a `try` label because we only give labels to block-like scoping expressions. So far we have not given `Try` a label and used inner blocks or a wrapping block in case a branch targets the `try`. But in case of `delegate`, it can syntactically only target `try` and if it targets blocks or loops it is a validation failure. So after discussions in #3497, we give `Try` a label but this label can only be targeted by `delegate`s. Unfortunately this makes parsing and writing of `Try` expression somewhat complicated. Also there is one special case; if the immediate argument of `try` is the same as the depth of control flow stack, this means the 'delegate' delegates to the caller. To handle this case this adds a fake label `DELEGATE_CALLER_TARGET`, and when writing it back to the wast format writes it as an immediate value, unlike other cases in which we write labels. This uses `DELEGATE_FIELD_SCOPE_NAME_DEF/USE` to represent `try`'s label and `delegate`'s target. There are many cases that `try` and `delegate`'s labels need to be treated in the same way as block and branch labels, such as for hashing or comparing. But there are routines in which we automatically assume all label uses are branches. I thought about adding a new kind of defines such as `DELEGATE_FIELD_TRY_NAME_DEF/USE`, but I think it will also involve some duplication of existing routines or classes. So at the moment this PR chooses to use the existing `DELEGATE_FIELD_SCOPE_NAME_DEF/USE` for `try` and `delegate` labels and makes only necessary amount of changes in branch-utils. We can revisit this decision later if necessary. Many of changes to the existing test cases are because now all `try`s are automatically assigned a label. They will be removed in `RemoveUnusedNames` pass in the same way as block labels if not targeted by any delegates. This only supports reading and writing and has not been tested against any optimization passes yet. --- Original unfolded wat file to generate test/try-delegate.wasm: ```wasm (module (event $e) (func try try delegate 0 catch $e end) (func try try catch $e i32.const 0 drop try delegate 1 end catch $e end ) ) ```
* StackSignature subtypes and LUBs (#3543)Thomas Lively2021-02-111-3/+5
| | | | | | | | Add a utility for calculating the least upper bounds of two StackSignatures, taking into account polymorphic unreachable behavior. This will important in the finalization and validation of Poppy IR blocks, where a block is allowed to directly produce fewer values than the branches that target it carry if the difference can be made up for by polymorphism due to an unreachable instruction in the block.
* [reference-types] remove single table restriction in IR (#3517)Abbas Mashayekh2021-02-091-18/+30
| | | Adds support for modules with multiple tables. Adds a field for the table name to `CallIndirect` and updates the C/JS APIs accordingly.
* Use unordered maps of Name where possible (#3546)Alon Zakai2021-02-051-1/+1
| | | | | | | Unordered maps will hash the pointer, while ordered ones will compare the strings to find where to insert in the tree. I cannot confirm a speedup in time from this, though others can, but I do see a consistent improvement of a few % in perf stat results like number of instructions and cycles (and those results have little noise). And it seems logical that this could be faster.
* [GC] Do not crash on unreachable inputs to struct.get/set (#3542)Alon Zakai2021-02-031-0/+16
| | | | | | | If the reference is unreachable then we cannot find the heap type to print in the text format. Instead of crashing or emitting something invalid, print a block instead - the block contains the children so they are emitted, and as the instruction was unreachable anyhow, this has no noticeable effect. It also parallels what we do in the binary format - skip unreachable code.
* [GC] Add br_on_func/data/i31 (#3525)Alon Zakai2021-01-281-8/+13
| | | | | | | | This expands the existing BrOnCast into BrOn that can also handle the func/data/i31 variants. This is not as elegant as RefIs / RefAs in that BrOnCast has an extra rtt field, but I think it is still the best option. We already have optional fields on Break (the value and condition), so making rtt optional is not odd. And it allows us to share all the behavior of br_on_* which aside from the cast or the check itself, is identical - returning the value if the branch is not taken, etc.
* [GC] Update br_on_cast: the text format also no longer has a heap type (#3523)Alon Zakai2021-01-271-9/+6
| | | | | | | As a result, we cannot handle a br_on_cast with an unreachable RTT. The binary format solves the problem by ignoring unreachable code, and this makes the text format do the same. A nice benefit of this is that we can remove the castType extra field.
* [GC] RefIsNull => RefIs. (#3516)Alon Zakai2021-01-261-4/+4
| | | | | | | | This internal refactoring prepares us for ref.is_func/data/i31, by renaming the node and adding an "op" field. For now that field must always be "Null" which means it is a ref.is_null. This adjusts the C API to match the new IR shape. The high-level JS API is unchanged.
* Reorder i31ref and dataref (#3509)Heejin Ahn2021-01-231-2/+2
| | | | | | | | | | The binary spec (https://docs.google.com/document/d/1yAWU3dbs8kUa_wcnnirDxUu9nEBsNfq0Xo90OWx6yuo/edit#) lists `dataref` after `i31ref`, and `dataref` also comes after `i31ref` in its binary code in the value-increasing order. This reorders these two in wasm-type.h and other places, although in most of those places the order is irrelevant. This also adds C and JS API for `dataref`.
* Remove exnref and br_on_exn (#3505)Heejin Ahn2021-01-221-37/+0
| | | This removes `exnref` type and `br_on_exn` instruction.
* [GC] Add dataref type (#3500)Alon Zakai2021-01-211-1/+3
| | | | | This is not 100% of everything, but is enough to get tests passing, which includes full binary and text format support, getting all switches to compile without error, and some additions to InstrumentLocals.
* Update interpreter for new EH spec (#3498)Heejin Ahn2021-01-211-4/+2
| | | | | | | | | | | | | This updates the interpreter for the EH instructions (modulo `delegate`) to match the new spec. Before we had an `exnref` type so threw a `Literal` of `exnref` type which contained `ExceptionPackage`. But now that we don't have `exnref` anymore, so we add the contents of `ExceptionPackage` to `WasmException`, which is used only for the `ExpressionRunner` class hierarchy. `exnref` and `ExceptionPackage` will be removed in a followup CL. This allows nonzero depths for `rethrow` for now for testing; we disallowed that for safety measure, but given that there are no passes that modifies that field, I think the risk is low.
* Prototype additional f64x2 conversions (#3501)Thomas Lively2021-01-191-0/+6
| | | | As proposed in https://github.com/WebAssembly/simd/pull/383, with opcodes coordinated with the WIP V8 prototype.
* Basic EH instrucion support for the new spec (#3487)Heejin Ahn2021-01-151-14/+20
| | | | | | | | | | | | | | | | | | | | This updates `try`-`catch`-`catch_all` and `rethrow` instructions to match the new spec. `delegate` is not included. Now `Try` contains not a single `catchBody` expression but a vector of catch bodies and events. This updates most existing routines, optimizations, and tests modulo the interpreter and the CFG traversal. Because the interpreter has not been updated yet, the EH spec test is temporarily disabled in check.py. Also, because the CFG traversal for EH is not yet updated, several EH tests in `rse_all-features.wast`, which uses CFG traversal, are temporarily commented out. Also added a few more tests in existing EH test functions in test/passes. In the previous spec, `catch` was catching all exceptions so it was assumed that anything `try` body throws is caught by its `catch`, but now we can assume the same only if there is a `catch_all`. Newly added tests test cases when there is a `catch_all` and cases there are only `catch`es separately.
* [GC] Add Type::IsDefaultable and use that to do more validation (#3456)Alon Zakai2021-01-111-6/+3
|
* [GC] Validate that struct.set is to a mutable field. (#3473)Alon Zakai2021-01-081-1/+4
| | | | This required a few test fixes, to ensure we don't have invalid wasts with writes to immutable fields.
* [GC] Fix parsing/printing of ref types using i31 (#3469)Alon Zakai2021-01-071-1/+3
| | | | | | | | | | | | This lets us parse (ref null i31) and (ref i31) and not just i31ref. It also fixes the parsing of i31ref, making it nullable for now, which we need to do until we support non-nullability. Fix some internal handling of i31 where we had just i31ref (which meant we just handled the non-nullable type). After fixing a bug in printing (where we didn't print out (ref null i31) properly), I found some a simplification, to remove TypeName.