summaryrefslogtreecommitdiff
path: root/src/wasm
Commit message (Collapse)AuthorAgeFilesLines
* Validate RefAsNonNull (#6785)Alon Zakai2024-07-242-3/+18
| | | Fixes #6781
* Properly validate ref.cast when lacking a common supertype (#6741)Alon Zakai2024-07-231-0/+15
| | | | | | | When lacking a common supertype the GLB operation makes the type of the cast unreachable, which errors on getHeapType in the later code. Fixes #6738
* [NFC] Add HeapType::isMaybeShared(BasicHeapType) utility (#6773)Thomas Lively2024-07-184-6/+4
| | | | | | | | | This abbreviates a common pattern where we first had to check whether a heap type was basic, then if it was, get its unshared version and compare it to some expected BasicHeapType. Suggested in https://github.com/WebAssembly/binaryen/pull/6771#discussion_r1683005495.
* Validate features for types used in element segments (#6769)Thomas Lively2024-07-181-0/+8
|
* Validate features for types used in tables (#6768)Thomas Lively2024-07-181-13/+8
| | | | We previously special-cased things like GC types, but switch to a more general solution of detecting what features a table's type requires.
* [threads] ref.i31_shared requires shared-everything in validation (#6767)Thomas Lively2024-07-181-0/+6
|
* [threads] Simplify and generalize reftype writing without GC (#6766)Thomas Lively2024-07-181-16/+8
| | | | | | Similar to #6765, but for types instead of heap types. Generalize the logic for transforming written reference types to types that are supported without GC so that it will automatically handle shared types and other new types correctly.
* [threads] Simplify and generalize heap type writing without GC (#6765)Thomas Lively2024-07-171-14/+1
| | | | | | | | | | We represent `ref.null`s as having bottom heap types, even when GC is not enabled. Bottom heap types are a feature of the GC proposal, so in that case the binary writer needs to write the corresponding top type instead. We previously had separate logic for this for each type hierarchy in the binary writer, but that did not handle shared types and would not have automatically handled other new types, either. Simplify and generalize the implementation and test that we can write `ref.null`s of shared types without GC enabled.
* [threads] Fix shared ref.eq and disallow mixed-shareability (#6763)Thomas Lively2024-07-172-1/+8
| | | | | | | Update the validator to reject mixed-shareability ref.eq, although this is still under discussion in https://github.com/WebAssembly/shared-everything-threads/issues/76. Fix the implementation of `Literal::operator==` to work properly with shared i31ref.
* Revert "[threads] Allow i31refs of mixed shareability to compare equal ↵Thomas Lively2024-07-171-9/+3
| | | | | | | | | | | | | | (#6752)" (#6761) Allowing Literals with different types to compare equal causes problems for passes that want equality to mean real equality, e.g. because they are using literals as map keys or because they otherwise need to use them interchangeably. At a minimum, we would need to differentiate a `refEq` operation where mixed-shareability i31refs can compare equal from physical equality on Literals, but there is also appetite to disallow mixed-shareability ref.eq at the spec level. See https://github.com/WebAssembly/shared-everything-threads/issues/76.
* Error more clearly on wasm components (#6751)Alon Zakai2024-07-171-1/+9
| | | | | | Component binary format: https://github.com/WebAssembly/component-model/blob/main/design/mvp/Binary.md#component-definitions Context: https://github.com/WebAssembly/binaryen/issues/6728#issuecomment-2231288924
* [threads] Validate all features required by ref.null (#6757)Thomas Lively2024-07-161-15/+25
| | | | | | | `ref.null` of shared types should only be allowed when shared-everything is enabled, but we were previously checking only that reference types were enabled when validating `ref.null`. Update the code to check all features required by the null type and factor out shared logic for printing lists of missing feature options in error messages.
* [threads] Fix feature detection for shared basic heap types (#6756)Thomas Lively2024-07-161-4/+4
| | | | The logic for adding the shared-everything feature was not previously executed for shared basic heap types.
* [threads] Allow i31refs of mixed shareability to compare equal (#6752)Thomas Lively2024-07-161-3/+9
| | | | | | | Normally, values of different types can never compare equal to each other, but since i31refs are not actually allocations, `ref.eq` has no way to differentiate a shared i31ref and an unshared i31ref with the same value, so it will report them as equal. Update the implementation of value equality to reflect this correctly.
* Remove extra space printed in empty structs (#6750)Thomas Lively2024-07-161-4/+0
| | | | | | When we switched to the new type printing machinery, we inserted this extra space to minimize the diff in the test output compared with the previous type printer. Improve the quality of the printed output by removing it.
* [threads] Fix struct op validation for shared null (#6742)Thomas Lively2024-07-131-1/+1
|
* [threads] ref.i31_shared (#6735)Thomas Lively2024-07-125-11/+21
| | | | | | | Implement `ref.i31_shared` the new instruction for creating references to shared i31s. Implement binary and text parsing and emitting as well as interpretation. Copy the upstream spec test for i31 and modify it so that all the heap types are shared. Comment out some parts that we do not yet support.
* [threads] Shared polymorphism for extern conversions (#6730)Thomas Lively2024-07-112-11/+16
| | | | | `any.convert_extern` and `extern.convert_any` return references to shared heap types iff their operands are references to shared heap types.
* StackIR: Optimize away a drop before an unreachable (#6719)Alon Zakai2024-07-081-1/+38
| | | | | | | | | | | | | | | | | | | | | | | | Anything else right before an unreachable is removed by the main DCE pass anyhow, but because of the structured form of BinaryenIR we can't remove a drop. That is, this is the difference between (i32.eqz (i32.const 42) (unreachable) ) and (drop (call $foo) ) (unreachable) In both cases the unreachable is preceded by something we don't need, but in the latter case it must remain in BinaryenIR for validation. To optimize this, add a rule in StackIR. Fixes #6715
* Rename external conversion instructions (#6716)Jérôme Vouillon2024-07-084-18/+18
| | | | | | | | | Rename instructions `extern.internalize` into `any.convert_extern` and `extern.externalize` into `extern.convert_any` to follow more closely the spec. This was changed in https://github.com/WebAssembly/gc/issues/432. The legacy name is still accepted in text inputs and in the C and JS APIs.
* [NFC] Add HeapType::getFeatures() (#6707)Alon Zakai2024-06-272-88/+91
|
* [threads] Validate shared-polymorphic instructions (#6702)Thomas Lively2024-06-252-72/+68
| | | | Such as `ref.eq`, `i31.get_{s,u}`, and `array.len`. Also validate that struct and array operations work on shared structs and arrays.
* [threads] Validate shared-to-unshared edges in heap types (#6698)Thomas Lively2024-06-251-18/+51
| | | Add spec tests checking validation for structs and arrays.
* Add missing struct/array type checks in binary reader (#6701)Alon Zakai2024-06-251-0/+30
| | | Fixes #6695
* Add a missing binary reading check for BrOn's reference child's type (#6700)Alon Zakai2024-06-251-0/+3
| | | | | | That child must be a reference, as `finalize()` assumes so. To avoid an assertion, error early. Fixes #6696
* Add a proper error for bad select results (#6697)Alon Zakai2024-06-241-1/+5
| | | | | The result cannot be `none` or `unreachable` etc. Fixes #6694
* Validate memarg offsets (#6683)Thomas Lively2024-06-201-0/+13
| | | | | For 32-bit memories, the offset value must be in the u32 range. Update the address.wast spec test to assert that a module with an overlarge offset value is invalid rather than malformed.
* Validate that names are valid UTF-8 (#6682)Thomas Lively2024-06-191-3/+5
| | | | | | Add an `isUTF8` utility and use it in both the text and binary parsers. Add missing checks for overlong encodings and overlarge code points in our WTF8 reader, which the new utility uses. Re-enable the spec tests that test UTF-8 validation.
* Check malformed mutability on imported globals (#6679)Thomas Lively2024-06-181-0/+3
| | | And re-enable the globals.wast spec test, which checks this.
* Re-enable binary.wast spec test (#6677)Thomas Lively2024-06-181-10/+23
| | | | | | Fix the wast parser to accept IDs on quoted modules, remove tests that are invalidated by the multimemory proposal, and add validation that the total number of variables in a function is less than 2^32 and that the code section is present if there is a non-empty function section.
* [threads] Shared basic heap types (#6667)Thomas Lively2024-06-193-89/+138
| | | | | | | | | | | Implement binary and text parsing and printing of shared basic heap types and incorporate them into the type hierarchy. To avoid the massive amount of code duplication that would be necessary if we were to add separate enum variants for each of the shared basic heap types, use bit 0 to indicate whether the type is shared and replace `getBasic()` with `getBasic(Unshared)`, which clears that bit. Update all the use sites to record whether the original type was shared and produce shared or unshared output without code duplication.
* [Parser] Fix bug in unreachable fallback logic (#6676)Thomas Lively2024-06-181-13/+18
| | | | | | | | | When popping past an unreachable instruction would lead to popping from an empty stack or popping an incorrect type, we need to avoid popping and produce new Unreachable instructions instead to ensure we parse valid IR. The logic for this was flawed and made the synthetic Unreachable come before the popped unreachable child, which was not correct in the case that that popped unreachable was a branch or other non-trapping instruction. Fix and simplify the logic and re-enable the spec test that uncovered the bug.
* Reject invalid section IDs (#6675)Thomas Lively2024-06-181-6/+7
| | | | | | Rather than treating them as custom sections. Also fix UB where invalid `Section` enum values could be used as keys in a map. Use the raw `uint8_t` section IDs as keys instead. Re-enable a disabled spec test that was failing because of this bug and UB.
* Fix DataSegment name handling (#6673)Alon Zakai2024-06-171-1/+1
| | | | | | | | | | | | | | | | | | | The code used i instead of index, as in this pseudocode: for i in range(num_names): index = readU32LEB() # index of the data segment to name name = readName() # name to give that segment data[i] = name # XXX 'i' should be 'index' That (funnily enough) happened to always work before since we write names in order. That is, normally given segments A,B,C we'd write then in the names section as A,B,C. Then the reader, which had the bug, would always have i and index identical in value anyhow. But if a wasm producer used different indexes, a problem could happen. To test this, add a binary file that has a reversed name section. Fixes #6672
* [threads] Binary reading and writing of shared composite types (#6664)Thomas Lively2024-06-141-0/+7
| | | | Also update the parser so that implicit type uses are not matched with shared function types.
* [threads] Add a "shared-everything" feature (#6658)Thomas Lively2024-06-144-5/+39
| | | | | Add the feature and flags to enable and disable it. Require the new feature to be enabled for shared heap types to validate. To make the test work, update the validator to actually check features for global types.
* [threads] Parse, build, and print shared composite types (#6654)Thomas Lively2024-06-121-0/+28
| | | | | | | | | | | | | | Parse the text format for shared composite types as described in the shared-everything thread proposal. Update the parser to use 'comptype' instead of 'strtype' to match the final GC spec and add the new syntactic class 'sharecomptype'. Update the type canonicalization logic to take sharedness into account to avoid merging shared and unshared types. Make the same change in the TypeMerging pass. Ensure that shared and unshared types cannot be in a subtype relationship with each other. Follow-up PRs will add shared abstract heap types, binary parsing and emitting for shared types, and fuzzer support for shared types.
* Fix scratch local optimizations when emitting string slice (#6649)Thomas Lively2024-06-111-31/+22
| | | | | | | | | | | | | | | | The binary writing of `stringview_wtf16.slice` requires scratch locals to store the `start` and `end` operands while the string operand is converted to a stringview. To avoid unbounded binary bloat when round-tripping, we detect the case that `start` and `end` are already `local.get`s and avoid using scratch locals by deferring the binary writing of the `local.get` operands until after the stringview conversoins is emitted. We previously optimized the scratch locals for `start` and `end` independently, but this could produce incorrect code in the case where the `local.get` for `start` is deferred but its value is changed by a `local.set` in the code for `end`. Fix the problem by only optimizing to avoid scratch locals in the case where both `start` and `end` are already `local.get`s, so they will still be emitted in the original relative order and they cannot interfere with each other anyway.
* Fix binary parser of declarative element segments (#6618)Rikito Taniguchi2024-06-031-1/+5
| | | | | | | | | | | | | | | The parser was incorrectly handling the parsing of declarative element segments whose `init` is a `vec(expr)`. https://webassembly.github.io/spec/core/binary/modules.html#element-section Binry parser was simply reading a single `u32LEB` value for `init` instead of parsing a expression regardless `usesExpressions = true`. This commit updates the `WasmBinaryReader::readElementSegments` function to correctly parse the expressions for declarative element segments by calling `readExpression` instead of `getU32LEB` when `usesExpressions = true`. Resolves the parsing exception: "[parse exception: bad section size, started at ... not being equal to new position ...]" Related discussion: https://github.com/tanishiking/scala-wasm/issues/136
* Remove obsolete parser code (#6607)Thomas Lively2024-05-293-4137/+3
| | | | | Remove `SExpressionParser`, `SExpressionWasmBuilder`, and `cashew::Parser`. Simplify gen-s-parser.py. Remove the --new-wat-parser and --deprecated-wat-parser flags.
* Fix fuzzer generation of a DataSegment + add validation that would have ↵Alon Zakai2024-05-231-2/+56
| | | | | | | | | | caught it (#6626) The DataSegment was manually added to .dataSegments, but we need to add it using addDataSegment so the maps are updated and getDataSegment(name) works. Also add validation that would have caught this earlier: check that each item in the item lists can be fetched by name.
* Fuzzer: Better fuzzing of globals (#6611)Alon Zakai2024-05-211-1/+16
| | | | | | | | | | | | | With this PR we generate global.gets in globals, which we did not do before. We do that by replacing makeConst (the only thing we did before, for the contents of globals) with makeTrivial, and add code to makeTrivial to sometimes make a global.get. When no suitable global exists, makeGlobalGet will emit a constant, so there is no danger in trying. Also raise the number of globals a little. Also explicitly note the current limitation of requiring all tuple globals to contain tuple.make and nothing else, including not global.get, and avoid adding such invalid global.gets in tuple globals in the fuzzer.
* [table64] Preserve 64-bit table flag when writing binaries (#6610)Sam Clegg2024-05-201-1/+1
|
* Rewrite wasm-shell to use new wast parser (#6601)Thomas Lively2024-05-172-1/+25
| | | | | | | | | | | | | | | | | | Use the new wast parser to parse a full script up front, then traverse the parsed script data structure and execute the commands. wasm-shell had previously used the new wat parser for top-level modules, but it now uses the new parser for module assertions as well. Fix various bugs this uncovered. After this change, wasm-shell supports all the assertions used in the upstream spec tests (although not new kinds of assertions introduced in any proposals). Uncomment various `assert_exhaustion` tests that we can now execute. Other kinds of assertions remain commented out in our tests: wasm-shell now supports `assert_unlinkable`, but the interpreter does not eagerly check for the existence of imports, so those tests do not pass. Tests that check for NaNs also remain commented out because they do not yet use the standard syntax that wasm-shell now supports for canonical and arithmetic NaN results, and our interpreter would not pass all of those tests even if they did use the standard syntax.
* Fix GlobalRefining's handling of gets in module code and add missing ↵Alon Zakai2024-05-171-3/+5
| | | | | | | | | | | validation (#6603) GlobalRefining did not traverse module code, so it did not update global.gets in other globals. Add missing validation that actually errors on that: We did not check global.get types. These could be separate PRs but it would be difficult to test them separately.
* Fix binary emitting of br_if with a refined value by emitting a cast (#6510)Alon Zakai2024-05-161-2/+157
| | | | | | | | | | | | | | | | This makes us compliant with the wasm spec by adding a cast: we use the refined type for br_if fallthrough values, and the wasm spec uses the branch target. If the two differ, we add a cast after the br_if to make things match. Alternatively we could match the wasm spec's typing in our IR, but we hope the wasm spec will improve here, and so this is will only be temporary in that case. Even if not, this is useful because by using the most refined type in the IR we optimize in the best way possible, and only suffer when we emit fixups in the binary, but in practice those cases are very rare: br_if is almost always dropped rather than used, in real-world code (except for fuzz cases and exploits). We check carefully when a br_if value is actually used (and not dropped) and its type actually differs, and it does not already have a cast. The last condition ensures that we do not keep adding casts over repeated roundtripping.
* Add table64 lowering pass (#6595)Sam Clegg2024-05-152-29/+15
| | | | | Changes to wasm-validator.cpp here are mostly for consistency between elem and data segment validation.
* [Strings] Remove operations not included in imported strings (#6589)Thomas Lively2024-05-156-266/+67
| | | | | | The stringref proposal has been superseded by the imported JS strings proposal, but the former has many more operations than the latter. To reduce complexity, remove all operations that are part of stringref but not part of imported strings.
* [Strings] Remove stringview types and instructions (#6579)Thomas Lively2024-05-159-462/+175
| | | | | | | | | | | | | | | | | | | | | | | | | | | | The stringview types from the stringref proposal have three irregularities that break common invariants and require pervasive special casing to handle properly: they are supertypes of `none` but not subtypes of `any`, they cannot be the targets of casts, and they cannot be used to construct nullable references. At the same time, the stringref proposal has been superseded by the imported strings proposal, which does not have these irregularities. The cost of maintaing and improving our support for stringview types is no longer worth the benefit of supporting them. Simplify the code base by entirely removing the stringview types and related instructions that do not have analogues in the imported strings proposal and do not make sense in the absense of stringviews. Three remaining instructions, `stringview_wtf16.get_codeunit`, `stringview_wtf16.slice`, and `stringview_wtf16.length` take stringview operands in the stringref proposal but cannot be removed because they lower to operations from the imported strings proposal. These instructions are changed to take stringref operands in Binaryen IR, and to allow a graceful upgrade path for users of these instructions, the text and binary parsers still accept but ignore `string.as_wtf16`, which is the instruction used to convert stringrefs to stringviews. The binary writer emits code sequences that use scratch locals and `string.as_wtf16` to keep the output valid. Future PRs will further align binaryen with the imported strings proposal instead of the stringref proposal, for example by making `string` a subtype of `extern` instead of a subtype of `any` and by removing additional instructions that do not have analogues in the imported strings proposal.
* Remove redundant ptrType from MemorySize/Grow instructions. NFC (#6590)Sam Clegg2024-05-153-9/+5
| | | | I recently add TableSize/Grow and noticed I didn't need these. It seems they are superfluous.