summaryrefslogtreecommitdiff
path: root/src
Commit message (Collapse)AuthorAgeFilesLines
...
* [Wasm GC] Generalize `skipCast` to work with all type hierarchies (#5422)Thomas Lively2023-01-121-4/+5
| | | | | | | | `skipCast` takes an optional parameter that bounds how general the resulting type is allowed to be. That parameter previously had a default value of `anyref` with the intention of allowing all casts to be skipped, but that default inadvertently prevented any casts in the `func` or `extern` type hierarchies from being skipped. Update `skipCast` so that the default parameter allows all casts to be skipped in all hierarchies.
* [NFC] Remove GCTypeUtils::evaluateKindCheck (#5421)Thomas Lively2023-01-112-70/+33
| | | | | | | | Since we refactored all the old kind-checking instructions to be represented as general cast instructions, `GCTypeUtils::evaluateKindCheck` had become a vestigial wrapper around `GCTypeUtils::evaluateCastCheck` that was only used in RemoveUnusedBrs. Remove `evaluateKindCheck` and use `evaluateCastCheck` in RemoveUnusedBrs without changing any functionality. A future PR may use the extra information from `evaluateCastCheck` to further optimize branching casts.
* [binaryen.js] Avoid use of the global buffer var which emcc has removed (#5419)Alon Zakai2023-01-111-1/+1
|
* [Wasm GC] Handle an unreachable br_on_cast_fail in DCE (#5418)Alon Zakai2023-01-111-1/+4
| | | Without this we hit an assertion on unreachable not being a heap type.
* [Wasm GC] Add missing RefTest optimizations to parallel RefCast (#5417)Alon Zakai2023-01-101-10/+23
| | | | We already handled Success and Failure. Also handle SuccessOnlyIfNull and SuccessOnlyIfNonNull.
* [Wasm GC] Replace `HeapType::data` with `HeapType::struct_` (#5416)Thomas Lively2023-01-1016-196/+126
| | | | | | `struct` has replaced `data` in the upstream spec, so update Binaryen's types to match. We had already supported `struct` as an alias for data, but now remove support for `data` entirely. Also remove instructions like `ref.is_data` that are deprecated and do not make sense without a `data` type.
* Represent ref.as_{func,data,i31} with RefCast (#5413)Thomas Lively2023-01-1016-145/+91
| | | | | | | | | | | | | These operations are deprecated and directly representable as casts, so remove their opcodes in the internal IR and parse them as casts instead. For now, add logic to the printing and binary writing of RefCast to continue emitting the legacy instructions to minimize test changes. The few test changes necessary are because it is no longer valid to perform a ref.as_func on values outside the func type hierarchy now that ref.as_func is subject to the ref.cast validation rules. RefAsExternInternalize, RefAsExternExternalize, and RefAsNonNull are left unmodified. A future PR may remove RefAsNonNull as well, since it is also expressible with casts.
* [NFC] Refactor cast check logic (#5404)Alon Zakai2023-01-102-108/+81
| | | Add a new evaluateCastCheck() utility and use that in relevant places.
* [Wasm GC] Optimize ref.as_non_null of a nullable cast (#5415)Alon Zakai2023-01-101-0/+16
|
* Fix iterator invalidation bug in GlobalStructInference (#5414)Alon Zakai2023-01-101-1/+3
| | | Fixes #5406
* [Wasm GC] More minor cast optimizations (#5402)Alon Zakai2023-01-091-84/+89
| | | | | | | | Look for definitely-failing casts along all the fallthrough values. Specifically, if any cast in the middle proves the final cast will fail, then we know we will trap. Fully optimize redundant casts, considering both the type and the heap type. Combine a cast with a ref.as_non_null.
* Replace `RefIs` with `RefIsNull` (#5401)Thomas Lively2023-01-0928-283/+158
| | | | | | | | | | | | | | | * Replace `RefIs` with `RefIsNull` The other `ref.is*` instructions are deprecated and expressible in terms of `ref.test`. Update binary and text parsing to parse those instructions as `RefTest` expressions. Also update the printing and emitting of `RefTest` expressions to emit the legacy instructions for now to minimize test changes and make this a mostly non-functional change. Since `ref.is_null` is the only `RefIs` instruction left, remove the `RefIsOp` field and rename the expression class to `RefIsNull`. The few test changes are due to the fact that `ref.is*` instructions are now subject to `ref.test` validation, and in particular it is no longer valid to perform a `ref.is_func` on a value outside of the `func` type hierarchy.
* [Wasm GC] Do not treat extern conversions as casts (#5411)Thomas Lively2023-01-091-1/+6
| | | | | | | | In particular, do not treat the converted value as "falling through" the conversion. Since the conversions cross type hierarchies, treating the converted values as fallthrough values would make subsequent casts look like they must fail, when in fact they may not. Fixes #5407.
* [Wasm GC] Refinalize in Vacuum (#5412)Alon Zakai2023-01-091-0/+13
| | | | | | We use TypeUpdater there, which handles updating unreachability. But with wasm GC we also need to refinalize if we refine types. Somehow, this was not noticed until now, but the new ref.cast null assertion on not losing type info was enough to uncover this long-existing issue.
* [Wasm GC] Add missing unreachable check in evaluateKindCheck (#5410)Alon Zakai2023-01-091-1/+3
|
* Fix a bug optimizing out br_on_cast (#5403)Thomas Lively2023-01-061-3/+7
| | | | | | | We were considering casts between unrelated types as unconditionally failing, but in the case where the unrelated types are nullable, the cast could still succeed if the value is null. This bug was introduced in #5397.
* [Wasm GC] Optimize impossible ref.casts better (#5400)Alon Zakai2023-01-061-19/+42
| | | | | | Also add some comments on related optimization opportunities. Also delete a test of a combination of types between hierarchies, which will soon not be expressible at all in the IR.
* Consolidate br_on* operations (#5399)Thomas Lively2023-01-0615-222/+172
| | | | | | | | | | | | | | | | | | The `br_on{_non}_{data,i31,func}` operations are deprecated and directly representable in terms of the new `br_on_cast` and `br_on_cast_fail` instructions, so remove their dedicated IR opcodes in favor of representing them as casts. `br_on_null` and `br_on_non_null` cannot be consolidated the same way because their behavior is not directly representable in terms of `br_on_cast` and `br_on_cast_fail`; when the cast to null bottom type succeeds, the null check instructions implicitly drop the null value whereas the cast instructions would propagate it. Add special logic to the binary writer and printer to continue emitting the deprecated instructions for now. This will allow us to update the test suite in a separate future PR with no additional functional changes. Some tests are updated because the validator no longer allows passing non-func data to `br_on_func`. Doing so has not made sense since we separated the three reference type hierarchies.
* [Wasm GC] Fix optimizations on ref.cast of null, and optimize to ↵Alon Zakai2023-01-061-1/+19
| | | | | | | | | | ref.as_non_null (#5398) We were checking the heap type, but now casts care about the nullability as well. If the nullability is the only problem, that is, the heap type will be fine but we might have a null, we can at least switch a ref.cast (non-null) to a ref.as_non_null.
* Support br_on_cast null (#5397)Thomas Lively2023-01-0515-56/+114
| | | | | | | | | As well as br_on_cast_fail null. Unlike the existing br_on_cast* instructions, these new instructions treat the cast as succeeding when the input is a null. Update the internal representation of the cast type in `BrOn` expressions to be a `Type` rather than a `HeapType` so it will include nullability information. Also update and improve `RemoveUnusedBrs` to handle the new instructions correctly and optimize in more cases.
* [Wasm GC] Fix non-nullable cast optimizations with multiple children (#5396)Alon Zakai2023-01-051-1/+32
| | | This fixes an oversight in #5395
* [Wasm GC] Turn casts non-nullable when they lead to a trap on null anyhow ↵Alon Zakai2023-01-051-0/+15
| | | | (#5395)
* [Wasm GC] Clean up and improve null trap and cast optimizations (#5394)Alon Zakai2023-01-051-20/+21
| | | | | | | | | visitRefCast can use trapOnNonNull. To make this not regress, add fallthrough analysis there as well. Minor test changes are due to trapOnNonNull using getDroppedChildren which only emits drops of necessary children. It also tells us to refinalize so it is ok for it to change the type to unreachable.
* [Parser] Parse blocks (#5393)Thomas Lively2023-01-053-18/+240
| | | | | | | | | | | | | Parse both the folded and unfolded forms of blocks and structure the code to make supporting additional block instructions like if-else and try-catch relatively simple. Parsing block types is extra fun because they may implicitly define new signature heap types via a typeuse, but only if their types are not given by a single result type. To figuring out whether a new type may be introduced in all the relevant parsing stages, always track at least the arity of parsed results. The parser parses block labels, but more work will be required to support branch instructions that use them.
* wasm2js: Stop emitting nan and infinity (#5391)Will Cohen2023-01-043-30/+6
| | | | | | | As noted in #4739, legacy language emitting nan and infinity exists, with the observation that it can be removed once asm.js is no longer used and global NaN is available. This commit removes that asm.js-specific code accordingly.
* [Wasm GC] Ignore call.without.effects for closed world validation (#5392)Alon Zakai2023-01-041-2/+8
| | | | It is implemented as an import, but functionally it is a call within the module, so it does not cause types to be public.
* wasm2js: Avoid emitting non-JS code during opt (#5378)Will Cohen2023-01-043-1/+13
| | | | | | | | | | | As noted in #4806, trying to optimize past level 0 can result in passes emitting non-JS code, which is then unable to be converted during final output. This commit creates a new targetJS option in PassOptions, which can be checked inside each pass where non-JS code might be emitted. This commit initially adds that logic to OptimizeInstructions, where this issue was first noticed.
* Allow non-nullable ref.cast of nullable references (#5386)Thomas Lively2023-01-045-43/+27
| | | | | | | This new cast configuration was not expressible with the legacy cast instructions. Although it is valid in Wasm, do not allow nullable casts of non-nullable references, since those would unnecessarily lose type information. Convert such casts to be non-nullable during expression finalization.
* [Wasm GC] Enforce closed-world in GlobalStructInference (#5385)Alon Zakai2023-01-031-0/+4
| | | | | | | After making the pass error when not in closed world, some testcases required changes. One forward-looking testcase can just be removed - the point of it was to see what happens if a type escapes, and now closed-world errors on it - and another testcase needed to avoid types on the boundary, and to use anyref+casts.
* [Wasm GC] Fix GlobalStructInference reasoning on unoptimizability (#5381)Alon Zakai2023-01-031-4/+18
| | | | | | | | | | | | | | | We have a data structure there, typeGlobals, which maps types to the list of globals for that type. Previously we used the convention of not having an entry in the map to mean that a type is unoptimizable. However, this was not used consistently, and in fact one place could insert to the map in a dangerous way: a subtype's global is added to the list of globals of the super, and typeGlobals[super].add(sub-global) would then effectively make an unoptimizable super into an optimizable one. To fix that, check for unoptimizability before propagating sub-globals. We do still use the convention of not keeping data in typeGlobals for unoptimizable things as it is a minor optimization to avoid wasted work. Fixes #5379
* Write debug info in Pass-Debug mode 3 (#5384)Alon Zakai2023-01-031-1/+1
| | | | Without the names section debugging can be hard sometimes, on the binaries that that mode emits for each pass.
* [Parser] Parse array access instructions (#5375)Thomas Lively2023-01-031-5/+82
| | | | | | | | | | | | | | | | | | | | | | | | | | | | * [NFC][Parser] Track definition indices For each definition in a module, record that definition's index in the relevant index space. Previously the index was inferred from its position in a list of module definitions, but that scheme does not scale to data segments defined inline inside memory definitions because these data segments occupy a slot in the data segment index space but do not have their own independent definitions. * clarify comment * [Parser] Parse data segments Parse active and passive data segments, including all their variations and abbreviations as well as data segments declared inline in memory declarations. Switch to parsing data strings, memory limits, and memory types during the ParseDecls phase so that the inline data segments can be completely parsed during that phase and never revisited. Parsing the inline data segments in a later phase would not work because they would be incorrectly inserted at the end of the data segment index space. Also update the printer to print a memory use on active data segments that are initialized in a non-default memory. * [Parser] Parse array creation and data segment instructions * [Parser] Parse array access instructions
* [Parser] Parse array creation and data segment instructions (#5374)Thomas Lively2023-01-031-8/+145
| | | | | | | | | | | | | | | | | | | | | | | | | | * [NFC][Parser] Track definition indices For each definition in a module, record that definition's index in the relevant index space. Previously the index was inferred from its position in a list of module definitions, but that scheme does not scale to data segments defined inline inside memory definitions because these data segments occupy a slot in the data segment index space but do not have their own independent definitions. * clarify comment * [Parser] Parse data segments Parse active and passive data segments, including all their variations and abbreviations as well as data segments declared inline in memory declarations. Switch to parsing data strings, memory limits, and memory types during the ParseDecls phase so that the inline data segments can be completely parsed during that phase and never revisited. Parsing the inline data segments in a later phase would not work because they would be incorrectly inserted at the end of the data segment index space. Also update the printer to print a memory use on active data segments that are initialized in a non-default memory. * [Parser] Parse array creation and data segment instructions
* [Parser] Parse data segments (#5373)Thomas Lively2023-01-033-35/+196
| | | | | | | | | | | | | | | | | | | | | | | | * [NFC][Parser] Track definition indices For each definition in a module, record that definition's index in the relevant index space. Previously the index was inferred from its position in a list of module definitions, but that scheme does not scale to data segments defined inline inside memory definitions because these data segments occupy a slot in the data segment index space but do not have their own independent definitions. * clarify comment * [Parser] Parse data segments Parse active and passive data segments, including all their variations and abbreviations as well as data segments declared inline in memory declarations. Switch to parsing data strings, memory limits, and memory types during the ParseDecls phase so that the inline data segments can be completely parsed during that phase and never revisited. Parsing the inline data segments in a later phase would not work because they would be incorrectly inserted at the end of the data segment index space. Also update the printer to print a memory use on active data segments that are initialized in a non-default memory.
* Maintain first memory import/export in Multi-Memory Lowering Pass (#5363)Ashley Nelson2023-01-031-2/+50
| | | This PR maintains the first memory's import/export in the single combined memory after multi-memories are lowered.
* [NFC][Parser] Track definition indices (#5372)Thomas Lively2023-01-031-13/+17
| | | | | | | | | | | * [NFC][Parser] Track definition indices For each definition in a module, record that definition's index in the relevant index space. Previously the index was inferred from its position in a list of module definitions, but that scheme does not scale to data segments defined inline inside memory definitions because these data segments occupy a slot in the data segment index space but do not have their own independent definitions. * clarify comment
* Move assert in MultiMemoryLowering (#5376)Ashley Nelson2023-01-031-3/+6
| | | Moved the assert that checks whether the DataSegment* offset type is Const. This assert only needs to happen when the DataSegment belongs to a memory other than the first.
* [Wasm GC] Do not refine types of exported globals in closed world (#5380)Alon Zakai2023-01-034-10/+64
| | | | | | Doing so can cause us to switch from a private type to a public type and error. Also refactor export-utils to make this easy.
* Make wasm::IString::operator bool() explicit (#5371)higher-performance2022-12-211-1/+1
| | | Fixes #5370
* Support `ref.test null` (#5368)Thomas Lively2022-12-2114-44/+64
| | | This new variant of ref.test returns 1 if the input is null.
* OptimizeInstructions: Check for possible added-constant overflows (#5227)Alon Zakai2022-12-201-14/+99
| | | | | | | | | | | Fix a regression from #5025 : we subtract constants there, and we need to be aware that such subtraction can change a constant from signed to unsigned if the comparison is signed, as 0x80000000 - 1 = 0x7fffffff 0x8000000 is a negative number when seen as signed, but always positive after the subtraction.
* Work around bugs with open world type optimizations (#5367)Thomas Lively2022-12-206-6/+27
| | | | | | | | | | | | | | Since #5347 public types are never updated by type optimizations, but the optimization passes have not yet been updated to take that into account, so they are all buggy under an open world assumption. In #5359 we worked around many closed world validation errors in the fuzzer by treating --closed-world like a feature flag and checking whether it was necessary for fuzzer input, but that did not prevent the type optimization passes from running under an open world, so it did not work around all the potential issues. Work around the problem more thoroughly by not running any type optimization passes in the fuzzer without --closed-world. Also add logic to those passes to error out if they are run without --closed-world and update the tests accordingly.
* Update RefCast representation to drop extra HeapType (#5350)Thomas Lively2022-12-2015-88/+96
| | | | | | | | | The latest upstream version of ref.cast is parameterized with a target reference type, not just a heap type, because the nullability of the result is parameterizable. As a first step toward implementing these new, more flexible ref.cast instructions, change the internal representation of ref.cast to use the expression type as the cast target rather than storing a separate heap type field. For now require that the encoded semantics match the previously allowed semantics, though, so that none of the optimization passes need to be updated.
* [Wasm GC] Do not cache signature types in nominal mode if they have a super ↵Alon Zakai2022-12-191-1/+5
| | | | | | | (#5364) This reduces the amount of public types, since if there is a super then using the type in a public place would make the super also public. It is safer for closed-world mode to reuse types without supers.
* Remove unused types during type optimizations (#5361)Thomas Lively2022-12-195-10/+84
| | | | | | | | | | | | | | | | | | | | | The type rewriting utility in type-updating.cpp gathers all the used heap types, then rewrites them to newly built and possibly modified heap types. The problem is that for the isorecursive type system, the set of "used" heap types was overly broad because it also included unused heap types that are in a rec group with used types. In the context of emitting a binary, it is important to treat these types as used because failing to emit them would change the identity of the used types, but in the context of type optimizations it is ok to treat them as truly unused because we are changing type identities anyway. Update the type rewriting utility to only include truly used types in the set of output types. This causes all existing type optimizations to implicitly drop unused types, but only if they find any other optimizations to do and actually run the rewriter utitility. Their output will also still include unused types that were used before their optimizations were applied. To overcome these limitations and better match the optimizing power of nominal mode, which never includes unused types in the output, add a new type optimization pass that removes unused types and does nothing else and run it near the end of the global optimization pipeline.
* Do not optimize public types (#5347)Thomas Lively2022-12-1610-63/+244
| | | | | | | | | | | | | | | | | Do not optimize or modify public heap types in any way. Public heap types include the types of imported or exported functions, tables, globals, etc. This is important to maintain the public interface of a module and ensure it can still link interact as intended with the outside world. Also add validation error if we find any nontrivial public types that are not the types of imported or exported functions. This error is meant to help the user ensure that type optimizations are not silently inhibited. In the future, we may want to add options to silence this error or downgrade it to a warning. This commit only updates the type updating machinery to avoid updating public types. It does not update any optimization passes accordingly. Since we avoid modifying public signature types already, this is not expected to break anything, but in the future once we have function subtyping or if we make the error optional, we may have to update some of our optimization passes.
* [Wasm GC] Optimize away null arms that would trap (#5358)Alon Zakai2022-12-161-5/+74
| | | | | | | | | | | | | | | | | | | | | | | | E.g. (struct.get (select (ref.null ..) (something) (condition) ) ) If traps-never-happen then this can be (drop (condition)) (struct.get (something) ) That is, we can remove the arm that is null, as it would trap but traps are assumed to not happen. Also fix a bug this uncovers on struct.set on a null type.
* In --debug mode, print partial wasm data that was read (#5356)Alon Zakai2022-12-152-2/+12
| | | | | | | | | | | | | | | | | | | If wasm-opt or wasm-dis are given an invalid binary, after the error message we can also print out the wasm we did manage to read. That includes global stuff like imports and also all the functions up until there. This can help debugging in some situations. Only do this when --debug is passed as it can be very verbose and in general users might not want it. This is technically easy to do, it turns out, since we already use a thrown exception on an error in parsing, and we fill up the wasm as we go, so it just contains what we've read so far, and we can just print it. Fixes #5344 Also switch an existing test's comments to ;; from # which was noticed here.
* Properly use pass options in nested pass runners (up to -O1) (#5351)Alon Zakai2022-12-152-8/+25
| | | | | | | | | | | | | | | | | | This fixes a TODO. There is a runtime cost to this in higher opt levels, as passing through -O3 makes nested optimization work take longer. But it can lead to better results. For now, this PR moves us from 0 before to a maximum of 1, as a compromise. 1 does not regress compile times, but there may be further benefits to allowing 2 and 3 in the future. Also fix a fuzzer bug that becomes uncovered by tihs PR: Now that we actually optimize in simplify-globals, we need to handle the case of the optimizer there seeing a call with the effects of writing to a global (we had an assert on that never happening, but with function effects that can happen, and so a GlobalSet is not the only thing that can set a global). Aside from the opt and shrink levels this passes through all other options, like trapsNeverHappen.
* Add memory: init, copy, fill support to Multi-Memory Lowering Pass (#5346)Ashley Nelson2022-12-151-0/+112
| | | This PR adds support for memory.init, memory.copy, and memory.fill instructions in the multi-memory lowering pass. Also includes optional bounds checks per the wasm spec guidelines.