summaryrefslogtreecommitdiff
path: root/src/wasm/literal.cpp
Commit message (Collapse)AuthorAgeFilesLines
* Fix UBSan on CI (#7173)Thomas Lively2024-12-201-0/+6
| | | | | | | | | | The UBSan builder started failing with an error about a misaligned store in wasm-ctor-eval.cpp. The store was already done via `memcpy` to avoid alignment issues, but apparently this is no longer enough. Use `void*` as the destination type to further avoid giving the impression of guaranteed alignment. Also fix UB when executing std::abs on minimum negative integers in literal.cpp.
* [FP16] Implement conversion operations. (#6974)Brendan Dahl2024-09-261-0/+43
| | | | | | | | | | Note: FP16 is a little different from F32/F64 since it can't represent the full 2^16 integer range. 65504 is the max whole integer. This leads to some slightly strange behavior when converting integers greater than 65504 since they become infinity. Specified at https://github.com/WebAssembly/half-precision/blob/main/proposals/half-precision/Overview.md
* [NFC] Make the GCData constructor a move constructor (#6946)Alon Zakai2024-09-171-1/+1
| | | | | | | This avoids creating a large Literals (SmallVector of Literal) and then copying it. All the places that construct GCData do not need the Literals afterwards. This gives a 7% speedup on the --precompute benchmark from #6931
* [FP16] Fix replace lane for F16x8. (#6906)Brendan Dahl2024-09-061-1/+4
| | | | | | | | | | | | | | | Before this change, replace lane was converting all the F16 lanes to F32 and then replacing one lane with the F16 (I32 representation) value, but it did not then convert all the other lanes back to F16 (I32). To fix this we can just leave the lanes as I32 and replace the one lane. Note: Previous replace lane tests didn't catch this since they started with vectors with all zeros so the F32->I32 didn't matter. Also, other operations don't run into this issue since they iterate over all lanes and convert the F32's back to F16 (I32). --------- Co-authored-by: Alon Zakai <alonzakai@gmail.com>
* [FP16] Implement madd and nmadd. (#6878)Brendan Dahl2024-09-031-6/+21
| | | | | | | | | | | | | | Specified at https://github.com/WebAssembly/half-precision/blob/main/proposals/half-precision/Overview.md A few notes: - The F32x4 and F64x2 versions of madd and nmadd are missing spect tests. - For madd, the implementation was incorrectly doing `(b*c)+a` where it should be `(a*b)+c`. - For nmadd, the implementation was incorrectly doing `(-b*c)+a` where it should be `-(a*b)+c`. - There doesn't appear to be a great way to actually implement a fused nmadd, but the spec allows the double rounded version I added.
* Rename relaxed SIMD fma instructions to match spec. (#6876)Brendan Dahl2024-08-271-14/+18
| | | | | | | The instructions relaxed_fma and relaxed_fnma have been renamed to relaxed_madd and relaxed_nmadd. https://github.com/WebAssembly/relaxed-simd/blob/main/proposals/relaxed-simd/Overview.md#binary-format
* [FP16] Implement unary operations. (#6867)Brendan Dahl2024-08-271-7/+29
| | | | Specified at https://github.com/WebAssembly/half-precision/blob/main/proposals/half-precision/Overview.md
* Support more reference constants in wast scripts (#6865)Thomas Lively2024-08-261-18/+0
| | | | | | | | | | | | | | Spec tests use constants like `ref.array` and `ref.eq` to assert that exported function return references of the correct types. Support more such constants in the wast parser. Also fix a bug where the interpretation of `array.new_data` for arrays of packed fields was not properly truncating the packed data. Move the function for reading fields from memory from literal.cpp to wasm-interpreter.h, where the function for truncating packed data lives. Other bugs prevent us from enabling any more spec tests as a result of this change, but we can get farther through several of them before failing. Update the comments about the failures accordingly.
* [FP16] Implement arithmetic operations. (#6855)Brendan Dahl2024-08-211-5/+46
| | | | Specified at https://github.com/WebAssembly/half-precision/blob/main/proposals/half-precision/Overview.md
* Support `ref.extern n` in spec tests (#6858)Thomas Lively2024-08-211-0/+3
| | | | | | | | | | | | | | | | | Spec tests pass the value `ref.extern n`, where `n` is some integer, into exported functions that expect to receive externrefs and receive such values back out as return values. The payload serves to distinguish externrefs so the test can assert that the correct one was returned. Parse these values in wast scripts and represent them as externalized i31refs carrying the payload. We will need a different representation eventually, since some tests explicitly expect these externrefs to not be i31refs, but this suffices to get several new tests passing. To get the memory64 version of table_grow.wast passing, additionally fix the interpreter to handle growing 64-bit tables correctly. Delete the local versions of the upstream tests that can now be run successfully.
* [Exceptions] Finish interpreter + optimizer support for try_table. (#6814)Sébastien Doeraene2024-08-201-1/+17
| | | | | | * Add interpreter support for exnref values. * Fix optimization passes to support try_table. * Enable the interpreter (but not in V8, see code) on exceptions.
* Fix direct comparisons with unshared basic heap types (#6845)Thomas Lively2024-08-161-1/+1
| | | | | Audit the remaining ocurrences of `== HeapType::` and fix those that did not handle shared types correctly. Add tests for some of the fixes; others are NFC but clarify the code.
* [NFC] Clean up Literal copy constructor (#6841)Alon Zakai2024-08-151-30/+27
| | | | | | | | Diff without whitespace is smaller. * HeapType::ext was handled in two places. The second place was wrong, but not reached. * Near the end all we have left are refs, so no need to check isRef etc. * Simplify the code to get the heap type once.
* [FP16] Implement relation operations. (#6825)Brendan Dahl2024-08-091-0/+18
| | | | Specified at https://github.com/WebAssembly/half-precision/blob/main/proposals/half-precision/Overview.md
* [FP16] Implement lane access instructions. (#6821)Brendan Dahl2024-08-081-0/+19
| | | | Specified at https://github.com/WebAssembly/half-precision/blob/main/proposals/half-precision/Overview.md
* Restore isString type methods (#6815)Thomas Lively2024-08-061-1/+1
| | | | | | | | | PR ##6803 proposed removing Type::isString and HeapType::isString in favor of more explicit, verbose callsites. There was no consensus to make this change, but it was accidentally committed as part of #6804. Revert the accidental change, except for the useful, noncontroversial parts, such as fixing the `isString` implementation and a few other locations to correctly handle shared types.
* [NFC] Add HeapType::getKind returning a new HeapTypeKind enum (#6804)Thomas Lively2024-08-061-1/+1
| | | | | | | | | | | | | | | | | The HeapType API has functions like `isBasic()`, `isStruct()`, `isSignature()`, etc. to test the classification of a heap type. Many users have to call these functions in sequence and handle all or most of the possible classifications. When we add a new kind of heap type, finding and updating all these sites is a manual and error-prone process. To make adding new heap type kinds easier, introduce a new API that returns an enum classifying the heap type. The enum can be used in switch statements and the compiler's exhaustiveness checker will flag use sites that need to be updated when we add a new kind of heap type. This commit uses the new enum internally in the type system, but follow-on commits will add new uses and convert uses of the existing APIs to use `getKind` instead.
* [NFC] Avoid a temp local (#6800)Alon Zakai2024-08-011-3/+3
| | | | | The local was only used once, so it didn't really add much. And, it was causing some compilers to error on "unused variable" (when building without assertions, the use was removed).
* Fix shareability of externalized nulls (#6791)Alon Zakai2024-07-301-2/+3
|
* Fix shareability of internalized nulls (#6789)Alon Zakai2024-07-291-2/+3
|
* Generalize Literal::externalize/internalize for strings and shareability (#6784)Alon Zakai2024-07-291-18/+12
|
* [NFC] Add HeapType::isMaybeShared(BasicHeapType) utility (#6773)Thomas Lively2024-07-181-2/+1
| | | | | | | | | 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.
* [threads] Fix shared ref.eq and disallow mixed-shareability (#6763)Thomas Lively2024-07-171-1/+2
| | | | | | | 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.
* [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.
* [threads] ref.i31_shared (#6735)Thomas Lively2024-07-121-1/+2
| | | | | | | 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 basic heap types (#6667)Thomas Lively2024-06-191-5/+9
| | | | | | | | | | | 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.
* Rewrite wasm-shell to use new wast parser (#6601)Thomas Lively2024-05-171-0/+16
| | | | | | | | | | | | | | | | | | 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.
* [Strings] Remove stringview types and instructions (#6579)Thomas Lively2024-05-151-10/+0
| | | | | | | | | | | | | | | | | | | | | | | | | | | | 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.
* Typed continuations: nocont and cont basic heap types (#6468)Frank Emrich2024-04-041-0/+6
| | | | | | | | This PR is part of a series that adds basic support for the typed continuations/wasmfx proposal. This particular PR adds cont and nocont as top and bottom types for continuation types, completely analogous to func and nofunc for function types (also: exn and noexn).
* [Strings] Escape strings printed by fuzz-exec (#6441)Thomas Lively2024-03-261-6/+5
| | | | | | | | | | | Previously we printed strings as WTF-8 in the output of fuzz-exec, but this could produce invalid unicode output and did not make unprintable characters visible. Fix both these problems by escaping the output, using the JSON string escape procedure since the string to be escaped is WTF-16. Reimplement the same escaping procedure in fuzz_shell.js so that the way we print strings when running on a real JS engine matches the way we print them in our own fuzz-exec interpreter. Fixes #6435.
* [Strings] Represent string values as WTF-16 internally (#6418)Thomas Lively2024-03-221-5/+18
| | | | | | | | | | | | | | | | WTF-16, i.e. arbitrary sequences of 16-bit values, is the encoding of Java and JavaScript strings, and using the same encoding makes the interpretation of string operations trivial, even when accounting for non-ascii characters. Specifically, use little-endian WTF-16. Re-encode string constants from WTF-8 to WTF-16 in the parsers, then back to WTF-8 in the writers. Update the constructor for string `Literal`s to interpret the string as WTF-16 and store a sequence of WTF-16 code units, i.e. 16-bit integers. Update `Builder::makeConstantExpression` accordingly to convert from the new `Literal` string representation back to a WTF-16 string. Update the interpreter to remove the logic for detecting non-ascii characters and bailing out. The naive implementations of all the string operations are correct now that our string encoding matches the JS string encoding.
* [EH] Add exnref type back (#6149)Heejin Ahn2023-12-081-0/+8
| | | | | | | | | | | | | At the Oct hybrid CG meeting, we decided to add back `exnref`, which was removed in 2020: https://github.com/WebAssembly/meetings/blob/main/main/2023/CG-10.md The new version of the proposal reflected in the explainer: https://github.com/WebAssembly/exception-handling/blob/main/proposals/exception-handling/Exceptions.md While adding support for `exnref` in the current codebase which has all GC subtype hierarchies, I noticed we might need `noexn` heap type for the bottom type of `exn`. We don't have it now so I just set it to 0xff for the moment.
* Work around a gcc 13 issue with signbit that made us not compute fmin of -0 ↵Alon Zakai2023-10-041-4/+14
| | | | properly (#5994)
* Limit printing of Literal[s] in a general way (#5792)Alon Zakai2023-06-281-16/+49
| | | | | | | | Previously we limited printing in a single Literals. But we can have infinitely recursive GC literals, or just huge graphs even without infinite recursion where no single Literals is that big (but we still get exponential blowup). This PR adds a general limit on how much we print once we start to print a Literal or Literals.
* Limit literal printing to a reasonable limit (#5779)Alon Zakai2023-06-211-0/+8
| | | | | | | | | Without this, a massive GC array for example can end up being printed as a huge amount of output, which is a problem in the fuzzer. I noticed this because a testcase was taking minutes to run. Perhaps we should add an option (BINARYEN_PRINT_FULL=1?) to disable this limit, but let's see if we ever need that.
* [Wasm GC] wasm-ctor-eval: Handle cycles of data (#5685)Alon Zakai2023-05-051-0/+1
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | A cycle of data is something we can't just naively emit as wasm globals. If at runtime we end up, for example, with an object A that refers to itself, then we can't just emit (global $A (struct.new $A (global.get $A))) The struct.get is of this very global, and such a self-reference is invalid. So we need to break such cycles as we emit them. The simple idea used here is to find paths in the cycle that are nullable and mutable, and replace the initial value with a null that is fixed up later in the start function: (global $A (struct.new $A (ref.null $A))) (func $start (struct.set (global.get $A) (global.get $A))) ) This is not optimal in terms of breaking cycles, but it is fast (linear time) and simple, and does well in practice on j2wasm (where cycles in fact occur).
* Support interpretation of extern.externalize and extern.internalize (#5576)Thomas Lively2023-03-161-10/+50
| | | | | | | To allow the external and internal reference values to be differentiated yet round-trippable, set the `Literal` type to externref on external references, but keep the gcData the same for both. The only exception is for i31 references, for which the externalized version gets a `gcData` that contains a copy of the original i31 literal.
* [Strings] Add hashing and equality support for strings (#5507)Alon Zakai2023-02-211-0/+3
| | | This is enough to test RSE.
* [Strings] Add support for strings in getLiteral and Literal() (#5500)Alon Zakai2023-02-171-0/+10
| | | This is enough for DAE and other opts to run on string consts.
* [Strings] Initial string execution support (#5491)Alon Zakai2023-02-151-2/+16
| | | | | | | | | | Store string data as GC data. Inefficient (one Const per char), but ok for now. Implement string.new_wtf16 and string.const, enough for basic testing. Create strings in makeConstantExpression, which enables ctor-eval support. Print strings in fuzz-exec which makes testing easier.
* [Wasm GC] Replace `HeapType::data` with `HeapType::struct_` (#5416)Thomas Lively2023-01-101-2/+2
| | | | | | `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.
* Implement `array.new_data` and `array.new_elem` (#5214)Thomas Lively2022-11-071-0/+51
| | | | | | | | | In order to test them, fix the binary and text parsers to accept passive data segments even if a module has no memory. In addition to parsing and emitting the new instructions, also implement their validation and interpretation. Test the interpretation directly with wasm-shell tests adapted from the upstream spec tests. Running the upstream spec tests directly would require fixing too many bugs in the legacy text parser, so it will have to wait for the new text parser to be ready.
* Implement `array` basic heap type (#5148)Thomas Lively2022-10-181-0/+2
| | | | | | | | | `array` is the supertype of all defined array types and for now is a subtype of `data`. (Once `data` becomes `struct` this will no longer be true.) Update the binary and text parsing of `array.len` to ignore the obsolete type annotation and update the binary emitting to emit a zero in place of the old type annotation and the text printing to print an arbitrary heap type for the annotation. A follow-on PR will add support for the newer unannotated version of `array.len`.
* Implement bottom heap types (#5115)Thomas Lively2022-10-071-70/+76
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | These types, `none`, `nofunc`, and `noextern` are uninhabited, so references to them can only possibly be null. To simplify the IR and increase type precision, introduce new invariants that all `ref.null` instructions must be typed with one of these new bottom types and that `Literals` have a bottom type iff they represent null values. These new invariants requires several additional changes. First, it is now possible that the `ref` or `target` child of a `StructGet`, `StructSet`, `ArrayGet`, `ArraySet`, or `CallRef` instruction has a bottom reference type, so it is not possible to determine what heap type annotation to emit in the binary or text formats. (The bottom types are not valid type annotations since they do not have indices in the type section.) To fix that problem, update the printer and binary emitter to emit unreachables instead of the instruction with undetermined type annotation. This is a valid transformation because the only possible value that could flow into those instructions in that case is null, and all of those instructions trap on nulls. That fix uncovered a latent bug in the binary parser in which new unreachables within unreachable code were handled incorrectly. This bug was not previously found by the fuzzer because we generally stop emitting code once we encounter an instruction with type `unreachable`. Now, however, it is possible to emit an `unreachable` for instructions that do not have type `unreachable` (but are known to trap at runtime), so we will continue emitting code. See the new test/lit/parse-double-unreachable.wast for details. Update other miscellaneous code that creates `RefNull` expressions and null `Literals` to maintain the new invariants as well.
* Refactor standardizeNaN (#5064)Max Graey2022-10-041-34/+32
| | | Change `standardizeNaN` to take a `Literal` to reduce usage verbosity.
* [OptimizeInstructions] Simplify floating point ops with NaN on right side ↵Max Graey2022-09-121-27/+9
| | | | | | | | | | | | | | | | | | | (#4985) x + nan -> nan' x - nan -> nan' x * nan -> nan' x / nan -> nan' min(x, nan) -> nan' max(x, nan) -> nan' where nan' is canonicalized nan of rhs x != nan -> 1 x == nan -> 0 x >= nan -> 0 x <= nan -> 0 x > nan -> 0 x < nan -> 0
* Restore the `extern` heap type (#4898)Thomas Lively2022-08-171-0/+5
| | | | | | | The GC proposal has split `any` and `extern` back into two separate types, so reintroduce `HeapType::ext` to represent `extern`. Before it was originally removed in #4633, externref was a subtype of anyref, but now it is not. Now that we have separate heaptype type hierarchies, make `HeapType::getLeastUpperBound` fallible as well.
* Remove RTTs (#4848)Thomas Lively2022-08-051-73/+1
| | | | | | | RTTs were removed from the GC spec and if they are added back in in the future, they will be heap types rather than value types as in our implementation. Updating our implementation to have RTTs be heap types would have been more work than deleting them for questionable benefit since we don't know how long it will be before they are specced again.
* Update reference type Literal constructors to use HeapType (#4857)Thomas Lively2022-08-011-4/+2
| | | | | | We already require non-null literals to have non-null types, but with this change we can enforce that constraint by construction. Also remove the default behavior of creating a function reference literal with heap type `func`, since there is always a more specific function type to use.