summaryrefslogtreecommitdiff
path: root/src
Commit message (Collapse)AuthorAgeFilesLines
...
* [Wasm Exceptions] Fix binary parsing of a normal break to a try in a ↵Alon Zakai2021-02-191-4/+0
| | | | | | | | | | | | | | | | | | singleton (#3581) The fix here is to remove the code with // maybe we don't need a block here? That would remove a try's block if we thought it wasn't needed. However, it just checked for exception branches, but not normal branches, which are also possible. At that location, we don't have a good way to find out if the block has other branches to it aside from scanning its contents. So this PR just gives up on doing so, which means we add an unnecessary block if the optimizer is not run. If this matters we could make the binary parser more complicated by remembering whether a block had branches in the past, but I'm not sure if it's worth it.
* Support type uses before definitions in text parser (#3584)Thomas Lively2021-02-183-77/+192
| | | | | | | | | | | | | | | | | | | | | | Traverses the module to find type definitions and uses a TypeBuilder to construct the corresponding HeapTypes rather than constructing them directly. This allows types to be used in the definitions of other types before they themselves are defined, which is an important step toward supporting recursive types. After this PR, no further text parsing changes will be necessary to support recursive types. Beyond allowing types to be used before their definitions, this PR also makes a couple incidental changes to the parser's behavior. First, compound heaptypes can now only be declared in `(type ...)` elements and cannot be declared inline at their site of use. This reduces the flexibility of the parser, but is in line with what the text format spec will probably look like eventually (see https://github.com/WebAssembly/function-references/issues/42). The second change is that `(type ...)` elements are now all parsed before `(func ...)` elements rather than in text order with them, so the type indices will be different and wasts using numeric type indices will be broken. Note however, that we were already not completely spec compliant in this regard because we parsed types defined by `(type...)` and `(func...)` elements before types defined by the type uses of `call_indirect` instructions.
* Fix TypeBuilder canonicalization (#3578)Thomas Lively2021-02-181-27/+96
| | | | | | | | | | | | | | | | | | | | | | When types or heap types were used multiple times in a TypeBuilder instance, it was possible for the canonicalization algorithm to canonicalize a parent type before canonicalizing all of its component child types, leaking the temporary types into globally interned types. This bug led to incorrect canonicalization results and use-after free bugs. The cause of the bug was that types were canonicalized in the reverse of the order that they were visited in, but children were visited after the first occurrence of their parents, not necessarily after the last occurrence of their parents. One fix could have been to remove the logic that prevented types from being visited multiple times so that children would always be visited after their parents. That simple fix, however, would not scale gracefully to handle recursive types because it would require some way to detect recursions without accidentally reintroducing these bugs. This PR implements a more robust solution: topologically sorting the traversed types to ensure that children are canonicalized before their parents. This solution will be trivial to adapt for recursive types because recursive types are trivial to detect from the reachability graph used to perform the topological sort.
* [Wasm Exceptions] Handle delegation to the caller in RemoveUnusedNames (#3585)Alon Zakai2021-02-181-1/+6
|
* [Wasm Exceptions] Fix RemoveUnusedNames on Try (#3583)Alon Zakai2021-02-181-11/+11
| | | | | | | | | | | | | | The delegate field of Try was not being scanned, so we could remove a name that was used only by a delegate. The bug was because visitTry overrides the generic visitor visitExpression. So we need to call it manually. Sadly the code here was pretty old (I probably wrote it back in 2015 or so) and it was misleading, as it had unnecessary calls from the generic visitor to visitBlock, visitLoop, which are not needed. This PR removes them which is shorter and cleaner. Also, we must handle the case of the delegate field being unset, so check name.is().
* [Wasm Exceptions] Scan catch events in RemoveUnusedModuleElements (#3582)Alon Zakai2021-02-181-23/+16
| | | | Also refactor away some annoying repeated code in that pass. visitTry is the only actual change.
* [EH] Change catch_all's opcode (#3574)Heejin Ahn2021-02-192-7/+4
| | | | | | | | | | We decided to change `catch_all`'s opcode from 0x05, which is the same as `else`, to 0x19, to avoid some complicated handling in the tools. See: https://github.com/WebAssembly/exception-handling/issues/147 lso this contains the original cpp file used to generate dwarf_with_exceptions.wasm; instructions to generate the wasm from that cpp file are in the comments.
* Create a table import if there is none in ↵Alon Zakai2021-02-181-3/+7
| | | | | | | | | | | | | | | | | GenerateDynCalls::generateDynCallThunk (#3580) This fixes LLVM=>emscripten autoroller breakage due to llvm/llvm-project@f48923e commit f48923e884611e6271a8da821a58aedd24d91cf7 (HEAD) Author: Andy Wingo <wingo@igalia.com> Date: Wed Feb 17 17:20:28 2021 +0100 [WebAssembly][lld] --importTable flag only imports table if needed Before, --importTable forced the creation of an indirect function table, whether it was needed or not. Now it only imports a table if needed. Differential Revision: https://reviews.llvm.org/D96872
* Allow em_js strings to be exported as globals (#3577)Sam Clegg2021-02-181-14/+27
|
* Remove assertions that prevent non-assertion builds (#3576)Alon Zakai2021-02-174-8/+7
| | | And fix errors from such a build.
* [EH] Make rethrow's target a try label (#3568)Heejin Ahn2021-02-1813-82/+76
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 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.
* cleanup to allow binaryen to be built in more strict environments (#3566)walkingeyerobot2021-02-1620-11/+35
|
* [GC] Fuzzer: Avoid creating tuples with non-defaultable types (#3567)Alon Zakai2021-02-161-3/+7
|
* Fix removal of em_js strings (#3570)Sam Clegg2021-02-161-1/+1
|
* [EH] Update C and binaryen.js API for delegate (#3565)Heejin Ahn2021-02-134-23/+133
| | | | | | | | | | This updates C and binaryen.js API to match the new `Try` structure to support `delegate`, added in #3561. Now `try` can take a name (which can be null) like a block, and also has an additional `delegateTarget` field argument which should only be used for try-delegate and otherwise null. This also adds several more variant of `makeTry` methods in wasm-builder. Some are for making try-delegate and some are for try-catch(_all).
* [EH] Rename delegateTarget to exceptionTarget (NFC) (#3562)Heejin Ahn2021-02-137-27/+28
| | | | | | | | | | | | | 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.
* Print the features section in a comment (#3563)Alon Zakai2021-02-122-0/+19
|
* Allow specifying additional features past the features section (#3564)Alon Zakai2021-02-121-2/+2
| | | | | That is, if a wasm says "simd", it is ok to let the user specify simd as well as more features, and the the optimizer can perhaps do something with them.
* [EH] Support reading/writing of delegate (#3561)Heejin Ahn2021-02-1219-91/+422
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 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 ) ) ```
* finalize: strip segments that contain only EM_ASM/EM_JS data (#3557)Sam Clegg2021-02-122-49/+144
| | | | | | | If we find a data segment whose entire contents is EM_JS or EM_ASM strings then strip it from the binary. See: https://github.com/emscripten-core/emscripten/pull/13443
* StackSignature subtypes and LUBs (#3543)Thomas Lively2021-02-113-99/+207
| | | | | | | | 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.
* Comment on validation in wasm-dis (#3556)Alon Zakai2021-02-101-0/+6
|
* Use correct table name in GenerateDynCalls (#3560)Thomas Lively2021-02-101-3/+2
| | | | | | | GenerateDynCalls was hardcoding the table name to use in the call_indirects in the dyncall thunks. The hardcoded name was different from the default name for imported tables, so the call_indirects referred to a nonexistent table when dynamic linking was enabled. This PR instead uses the name of table 0 when creating call_indirects for the dyncall thunks.
* Simplify asmConst handling. NFC. (#3558)Sam Clegg2021-02-091-76/+9
| | | | | | | | Support for multiple signatures per JS code string was removed in #2422. emscripten now only needs to know that address and the body of the JS function. See https://github.com/emscripten-core/emscripten/pull/13452.
* [GC] Support RTT constants in Builder::makeConstantExpression (#3550)Alon Zakai2021-02-092-7/+16
| | | | This allows the reducer to operate on RTTs, but could help other things too.
* Poppify pass (#3541)Thomas Lively2021-02-096-2/+521
| | | | | | | | | | | | | | Adds a Poppify ("--poppify") pass for converting normal Binaryen IR to Poppy IR. Like the existing construction of Stacky IR, Poppify depends on the BinaryenIRWriter to drive the emitting of instructions in correct stack machine order. As instructions are "emitted," Poppify replaces their children with pops and collects them in a list. At the end of each scope, Poppify creates a block containing all the collected instructions for that scope and injects that block into the enclosing scope. All tuple globals and instructions dealing with tuples are also expanded to remove all tuples from the program. The validator currently fails to validate many valid Poppy IR patterns produced in the tests, but fixing that is left as follow-on work to keep this PR focused on the Poppify pass itself. For now the tests simply skip validation.
* [reference-types] remove single table restriction in IR (#3517)Abbas Mashayekh2021-02-0945-484/+1180
| | | Adds support for modules with multiple tables. Adds a field for the table name to `CallIndirect` and updates the C/JS APIs accordingly.
* [GC] Support casts of function types (#3554)Alon Zakai2021-02-092-28/+45
| | | | | | | | | | | | | | | I had completely missed that the spec allows ref.cast etc. of function types, and not just data. Function types do not have an RTT, unlike GC data, but we can still cast them. A function reference has the canonical RTT of the signature for that type, so it's like a simplified case of the GC world, without a hierarchy of RTTs. As it turns out, our validation did not rule out rtt.canon of a function type, nor ref.cast of one, so we unintentionally already had all the support for this aside from the actual casting, which this PR adds. The addition is mostly trivial, except that we now need a Module in the base ExpressionRunner class, so that we can go from a function name to the actual function. This PR refactors things to allow that.
* finalize: Refactor C string extraction code. NFC. (#3555)Sam Clegg2021-02-081-82/+84
| | | | | This is a pure refactor in preparation for change that will enable stripping or at least zeroing segments that only contain EM_JS/EM_ASM strings.
* Fix removal of EM_JS functions (#3552)Sam Clegg2021-02-081-9/+5
| | | | | | The algorithm was trying to remove all __em_js functions but it was using the names of functions rather than export names so it was failing to remove these functions unless the internal function names happened to match (this turns out of the true for build with debug names).
* [GC] Avoid replacing non-defaultable types in the fuzzer (#3549)Alon Zakai2021-02-081-2/+10
| | | | We can't arbitrarily replace a non-defaultable type, as it may lead to us needing a temp local for it (say, in a tuple).
* Add feature options to wasm-dis (#3548)Abbas Mashayekh2021-02-081-4/+7
| | | | | | This will allow .fromBinary tests be executed with the desired featurs so there will be no difference between those tests and .from-wast tests. Fixes #3545
* Use unordered maps of Name where possible (#3546)Alon Zakai2021-02-053-11/+11
| | | | | | | 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-032-0/+31
| | | | | | | 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] Small fuzz fixes for GC (#3540)Alon Zakai2021-02-031-35/+49
| | | | | | | | * Fix label fixup code to use delegates-fields. This makes it support BrOn etc. * Add an isRtt() in places RTTs are not supported. * Implement makeConst for arbitrary RTTs. This is enough to get the fuzzer working for more than a few iterations at a time, but no more.
* [GC] Feedback for #3536 (#3539)Alon Zakai2021-02-021-5/+5
|
* Support Stack IR for new try-catch(_all) (#3538)Heejin Ahn2021-02-033-12/+43
| | | | | This adds missing stack IR printing support for the new form of try-catch-catch_all. Also uses `printMedium` when printing instructions consistently.
* [GC] dataref typing fixes (#3536)Alon Zakai2021-02-031-18/+29
| | | | | | | dataref was not noted as isRef, and we also did not handle the LUB for it, which caused validation errors. After these two fixes, it is possible to add a testcase that goes through the optimizer. View without whitespace as the LUB change has a lot of that.
* Allow printing expressions based on feature set (#3537)Abbas Mashayekh2021-02-021-68/+83
| | | | | | | | | | As discussed in #3517, we need a way to maintain the ability to print expressions in a backward-compatible way. This adds a FeatureSet to PrintExpressionContents which defaults to FeatureSet::All in case a feature set is not available. This will be used for CallIndirect to decide whether to print the table name arg.
* Prototype i32x4.widen_i8x16_{s,u} (#3535)Thomas Lively2021-02-0116-1/+123
| | | | | | | | As proposed in https://github.com/WebAssembly/simd/pull/395. Note that the other instructions in the proposal have not been implemented in LLVM or in V8, so there is no need to implement them in Binaryen right now either. This PR introduces a new expression class for the new instructions because they uniquely take an immediate argument identifying which portion of the input vector to widen.
* [GC] isGCData => isData (#3534)Alon Zakai2021-02-015-21/+43
| | | | | | | | | We added isGCData() before we had dataref. But now there is a clear parallel of Function vs Data. This PR makes us more consistent there, renaming isGCData to isData and using that throughout. This also fixes a bug where the old isGCData just checked if the input was an Array or a Struct, and ignored the data heap type itself. It is not possible to test that, however, due to other bugs, so that is deferred.
* [GC] br_on_null (#3528)Alon Zakai2021-02-018-9/+51
| | | | | | | | | | | This is only partial support, as br_on_null also has an extra optional value in the spec. Implementing that is cumbersome in binaryen, and there is ongoing spec discussions about it (see https://github.com/WebAssembly/function-references/issues/45 ), so for now we only support the simple case without the default value. Also fix prefixed opcodes to be LEBs in RefAs, which was noticed here as the change here made it noticeable whether the values were int8 or LEBs.
* [GC] Don't emit i31ref in fuzzer (#3531)Alon Zakai2021-02-011-11/+10
| | | | | | | That type is non-nullable, so we need to disable it until we fully support that. Right now if we emit such locals we immediately get a validation error. With this change the fuzzer can run at least a few thousand iterations with no errors once more.
* Remove unnecessary breakStack pushes for if/try (NFC) (#3533)Heejin Ahn2021-02-021-9/+0
| | | | | | This break stack is maintained to compute branch depths, but it seems we don't need to push and pop for each of if and else block or every single catch/catch_all block; it would be sufficient to have just one stack entry for the whole try-catch or if-else.
* Don't error out when EH is used for Flatten (#3526)Heejin Ahn2021-01-291-4/+0
| | | | | | | We used to error out in Flatten when EH is used because Flatten makes all block types `none` by setting their return values to locals and getting them later, but `br_on_exn` by definition pops value from the value stack at the end of a block so it couldn't be flattened. Now that we don't have `br_on_exn` we don't need these restriction.
* [GC] ref.as_non_null (#3527)Alon Zakai2021-01-288-0/+24
| | | | | | This is different than the other RefAs variants in that it is part of the typed functions proposal, and not GC. But it is part of GC prototype 3. Note: This is not useful to us yet as we don't support non-nullable types.
* [GC] Add br_on_func/data/i31 (#3525)Alon Zakai2021-01-2820-70/+204
| | | | | | | | 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-278-25/+19
| | | | | | | 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.
* Memcpy data instead of bytewise copies (#3521)Philip Pfaffe2021-01-272-19/+23
| | | | | | wasm-finalize currently makes byte-wise copies of section data in the user and data sections. If the section is large, that's extraordinarily expensive. With a memcpy instead I see a speedup of 1.6 for a large wasm binary with DWARF data.
* Simplfy getExpressionName (#3522)Alon Zakai2021-01-275-164/+20
| | | | | | | | | | This used to return a simple name like "if" for an If, but it is redundant with our proper printing logic. This PR turns it into a trivial helper that just prints out the name of the class, so it now prints "If" with a capital. That is useful for some logging, like in Metrics I think it is clearer than it was earlier (since we are actually counting the classes, and our old emitting of text-format-like names are just confusing, as we emitted "binary" there which is not valid). Also replace some usages of that method with proper printing.