summaryrefslogtreecommitdiff
path: root/src/wasm/wasm-binary.cpp
Commit message (Collapse)AuthorAgeFilesLines
* [NFC] Make MemoryOrder parameters non-optional (#7171)Thomas Lively2024-12-211-3/+5
| | | | | | Update Builder and IRBuilder makeStructGet and makeStructSet functions to require the memory order to be explicitly supplied. This is slightly more verbose, but will reduce the chances that we forget to properly consider synchronization when implementing new features in the future.
* Support atomic struct accessors (#7155)Thomas Lively2024-12-181-0/+40
| | | | | | | | | | | | | | | | | | | | | Implement support for both sequentially consistent and acquire-release variants of `struct.atomic.get` and `struct.atomic.set`, as proposed by shared-everything-threads. Introduce a new `MemoryOrdering` enum for describing different levels of atomicity (or the lack thereof). This new enum should eventually be adopted by linear memory atomic accessors as well to support acquire-release semantics, but for now just use it in `StructGet` and `StructSet`. In addition to implementing parsing and emitting for the instructions, validate that shared-everything is enabled to use them, mark them as having synchronization side effects, and lightly optimize them by relaxing acquire-release accesses to non-shared structs to normal, unordered accesses. This is valid because such accesses cannot possibly synchronize with other threads. Also update Precompute to avoid optimizing out synchronization points. There are probably other passes that need to be updated to avoid incorrectly optimizing synchronizing accesses, but identifying and fixing them is left as future work.
* Support control flow inputs in IRBuilder (#7149)Thomas Lively2024-12-131-20/+20
| | | | | | | | | | | | | | | | | | | | Since multivalue was standardized, WebAssembly has supported not only multiple results but also an arbitrary number of inputs on control flow structures, but until now Binaryen did not support control flow input. Binaryen IR still has no way to represent control flow input, so lower it away using scratch locals in IRBuilder. Since both the text and binary parsers use IRBuilder, this gives us full support for parsing control flow inputs. The lowering scheme is mostly simple. A local.set writing the control flow inputs to a scratch local is inserted immediately before the control flow structure begins and a local.get retrieving those inputs is inserted inside the control flow structure before the rest of its body. The only complications come from ifs, in which the inputs must be retrieved at the beginning of both arms, and from loops, where branches to the beginning of the loop must be transformed so their values are written to the scratch local along the way. Resolves #6407.
* Add bulk-memory-opt feature and ignore call-indirect-overlong (#7139)Derek Schuff2024-12-061-0/+10
| | | | | | | | | | LLVM recently split the bulk-memory-opt feature out from bulk-memory, containing just memory.copy and memory.fill. This change follows that, making bulk-memory-opt also enabled when all of bulk-memory is enabled. It also introduces call-indirect-overlong following LLVM, but ignores it, since Binaryen has always allowed the encoding (i.e. command line flags enabling or disabling the feature are accepted but ignored).
* Remove incorrect warning when reading name section (#7140)Thomas Lively2024-12-061-5/+0
| | | | | | | | | When we refactored how the name section is read, we accidentally left an old warning about invalid field name indices in place. The old warning code compares the type index from the names section to the size of the parsed type vector to determine if the index is out-of-bounds. Now that we parse the name section before the type section, this is no longer correct. Delete the old warning; we already have a new, correct warning for out-of-bound indices when we parse the type section.
* [NFC] Encapsulate source map reader state (#7132)Thomas Lively2024-12-031-250/+9
| | | | | | | | | | | | Move all state relevant to reading source maps out of WasmBinaryReader and into a new utility, SourceMapReader. This is a prerequisite for parallelizing the parsing of function bodies, since the source map reader state is different at the beginning of each function. Also take the opportunity to simplify the way we read source maps, for example by deferring the reading of anything but the position of a debug location until it will be used and by using `std::optional` instead of singleton `std::set`s to store function prologue and epilogue debug locations.
* [NFC] Rename {F32,F64}NearestInt to {F32,F64}Nearest (#7089)Thomas Lively2024-11-271-5/+1
| | | | | | Rename the opcode values in wasm-binary.h to better match the names of the corresponding instructions. This also makes these names match the scheme used by the rest of the basic unary operations, allowing for more macro use in the binary reader.
* Use IRBuilder in the binary parser (#6963)Thomas Lively2024-11-261-4246/+1419
| | | | | | | | | | | | | | | | | | | | | | IRBuilder is a utility for turning arbitrary valid streams of Wasm instructions into valid Binaryen IR. It is already used in the text parser, so now use it in the binary parser as well. Since the IRBuilder API for building each intruction requires only the information that the binary and text formats include as immediates to that instruction, the parser is now much simpler than before. In particular, it does not need to manage a stack of instructions to figure out what the children of each expression should be; IRBuilder handles this instead. There are some differences between the IR constructed by IRBuilder and the IR the binary parser constructed before this change. Most importantly, IRBuilder generates better multivalue code because it avoids eagerly breaking up multivalue results into individual components that might need to be immediately reassembled into a tuple. It also parses try-delegate more correctly, allowing the delegate to target arbitrary labels, not just other `try`s. There are also a couple superficial differences in the generated label and scratch local names. As part of this change, add support for recording binary source locations in IRBuilder.
* Make validation of stale types stricter (#7097)Thomas Lively2024-11-211-5/+6
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | We previously allowed valid expressions to have stale types as long as those stale types were supertypes of the most precise possible types for the expressions. Allowing stale types like this could mask bugs where we failed to propagate precise type information, though. Make validation stricter by requiring all expressions except for control flow structures to have the most precise possible types. Control flow structures are exempt because many passes that can refine types wrap the refined expressions in blocks with the old type to avoid the need for refinalization. This pattern would be broken and we would need to refinalize more frequently without this exception for control flow structures. Now that all non-control flow expressions must have precise types, remove functionality relating to building select instructions with non-precise types. Since finalization of selects now always calculates a LUB rather than using a provided type, remove the type parameter from BinaryenSelect in the C and JS APIs. Now that stale types are no longer valid, fix a bug in TypeSSA where it failed to refinalize module-level code. This bug previously would not have caused problems on its own, but the stale types could cause problems for later runs of Unsubtyping. Now the stale types would cause TypeSSA output to fail validation. Also fix a bug where Builder::replaceWithIdenticalType was in fact replacing with refined types. Fixes #7087.
* Record binary locations for nested blocks (#7078)Thomas Lively2024-11-141-0/+20
| | | | | | | | | | | The binary reader has special handling for blocks immediately nested inside other blocks to eliminate recursion while parsing very deep stacks of blocks. This special handling did not record binary locations for the nested blocks, though. Add logic to record binary locations for nested blocks. This binary reading code is about to be replaced with completely different code that uses IRBuilder instead, but this change will eliminate some test differences that we would otherwise see when we make that change.
* [NFC] Eagerly set local names in binary reader (#7076)Thomas Lively2024-11-141-19/+25
| | | | | | | | | | | | | | | | Instead of setting the local names at the end of binary reading, eagerly set them before parsing function bodies. This is NFC now, but will fix a future bug once the binary reader uses IRBuilder. IRBuilder can introduce new scratch locals, and it gives them the names `$scratch`, `$scratch_1`, etc. If the name section includes locals with the same names and we set those local names after parsing function bodies, then we can end up with multiple locals with the same names. Setting the names before parsing the function bodies ensures that IRBuilder will generate different names for the scratch locals. The alternative fix would be to generate fresh names when setting names from the name section, but it is better to respect the names in the name section and use fresh names for the newly introduced scratch locals instead.
* Read the names section first (#7074)Thomas Lively2024-11-131-326/+325
| | | | | | | | | Rather than back-patching names when we get to the names section in the binary reader, skip ahead to read the names section before anything else so we can use the final names right away. This is a prerequisite for using IRBuilder in the binary reader. The only functional change is that we now allow empty local names. Empty names are perfectly valid.
* Rename indexType -> addressType. NFC (#7060)Sam Clegg2024-11-071-7/+7
| | | See https://github.com/WebAssembly/memory64/pull/92
* Remove FeaturePrefix::FeatureRequired (NFC) (#7034)Heejin Ahn2024-11-041-6/+2
| | | | | | | | This has not been emitted in LLVM since https://github.com/llvm/llvm-project/commit/3f34e1b883351c7d98426b084386a7aa762aa366. The corresponding proposed tool-conventions change: https://github.com/WebAssembly/tool-conventions/pull/236
* [EH][GC] Send a non-nullable exnref from TryTable (#7013)Alon Zakai2024-10-171-3/+5
| | | | | | | | | | | | | | | When EH+GC are enabled then wasm has non-nullable types, and the sent exnref should be non-nullable. In BinaryenIR we use the non- nullable type all the time, which we also do for function references and other things; we lower it if GC is not enabled to a nullable type for the binary format (see `WasmBinaryWriter::writeType`, to which comments were added in this PR). That is, this PR makes us handle exnref the same as those other types. A new test verifies that behavior. Various existing tests are updated because ReFinalize will now use the more refined type, so this is an optimization. It is also a bugfix as in #6987 we started to emit the refined form in the fuzzer, and this PR makes us handle it properly in validation and ReFinalization.
* Source Maps: Support 5 segment mappings (#6795)Ömer Sinan Ağacan2024-10-011-13/+61
| | | | | | | Support 5-segment source mappings, which add a name. Reference: https://github.com/tc39/source-map/blob/main/source-map-rev3.md#proposed-format
* Binary parser: Lift the limit on the number of locals (#6973)Jérôme Vouillon2024-09-301-6/+14
| | | | | | | This raises the number of locals accepted by the binary parser to the absolute limit in the spec. A warning is now printed when writing a binary file if the Web limit of 50,000 locals is exceeded. Fixes #6968.
* [FP16] Implement conversion operations. (#6974)Brendan Dahl2024-09-261-0/+16
| | | | | | | | | | 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] Eagerly create segments when parsing datacount (#6958)Thomas Lively2024-09-191-3/+21
| | | | | | | | | The purpose of the datacount section is to pre-declare how many data segments there will be so that engines can allocate space for them and not have to back patch subsequent instructions in the code section that refer to them. Once we use IRBuilder in the binary parser, we will have to have the data segments available by the time we parse instructions that use them, so eagerly construct the data segments when parsing the datacount section.
* [NFC] Eagerly create Functions in binary parser (#6957)Thomas Lively2024-09-191-11/+11
| | | | | | | | In preparation for using IRBuilder in the binary parser, eagerly create Functions when parsing the function section so that they are already created once we parse the code section. IRBuilder will require the functions to exist when parsing calls so it can figure out what type each call should have, even when there is a call to a function whose body has not been parsed yet.
* [NFC] Remove excessive debug logging from binary reading (#6927)Alon Zakai2024-09-101-177/+6
| | | | | | | | We were doing a debug logging for every LEB byte. It turns out that the isDebugEnabled() calls are expensive when called so frequently: in a release+assertion build, even with debug disabled, these checks are the highest thing in the profile. This PR removes the checks, which makes binary reading 12% faster.
* Add a --preserve-type-order option (#6916)Thomas Lively2024-09-101-1/+6
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Unlike other module elements, types are not stored on the `Module`. Instead, they are collected by traversing the IR before printing and binary writing. The code that collects the types tries to optimize the order of rec groups based on the number of times each type is used. As a result, the output order of types generally has no relation to the input order of types. In addition, most type optimizations rewrite the types into a single large rec group, and the order of types in that group is essentially arbitrary. Changes to the code for counting type uses, sorting types, or sorting rec groups can yield very large changes in the output order of types, producing test diffs that are hard to review and potentially harming the readability of tests by moving output types away from the corresponding input types. To help make test output more stable and readable, introduce a tool option that causes the order of output types to match the order of input types as closely as possible. It is implemented by having the parsers record the indices of the input types on the `Module` just like they already record the type names. The `GlobalTypeRewriter` infrastructure used by type optimizations associates the new types with the old indices just like it already does for names and also respects the input order when rewriting types into a large recursion group. By default, wasm-opt and other tools clear the recorded type indices after parsing the module, so their default behavior is not modified by this change. Follow-on PRs will use the new flag in more tests, which will generate large diffs but leave the tests in stable, more readable states that will no longer change due to other changes to the optimizing type sorting logic.
* [EH] Rename Catch(All)_P3 to Catch(All)_Legacy (NFC) (#6901)Heejin Ahn2024-09-041-6/+7
| | | | | | | This renames `Catch(All)_P3` enum to denote the old Phase 3 `catch(_all)` instructions to `Catch(All)_Legacy`, which sounds clearer. This is also to be consistent with https://github.com/llvm/llvm-project/pull/107187.
* [FP16] Implement madd and nmadd. (#6878)Brendan Dahl2024-09-031-0/+8
| | | | | | | | | | | | | | 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-8/+8
| | | | | | | 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-0/+28
| | | | Specified at https://github.com/WebAssembly/half-precision/blob/main/proposals/half-precision/Overview.md
* [FP16] Add a feature flag for FP16. (#6864)Brendan Dahl2024-08-221-0/+4
| | | Ensure the "fp16" feature is enabled for FP16 instructions.
* [FP16] Implement arithmetic operations. (#6855)Brendan Dahl2024-08-211-0/+32
| | | | Specified at https://github.com/WebAssembly/half-precision/blob/main/proposals/half-precision/Overview.md
* Fix encoding of heap type definitions (#6856)Thomas Lively2024-08-201-13/+13
| | | | | | | | The leading bytes that indicate what kind of heap type is being defined are bytes, but we were previously treating them as SLEB128-encoded values. Since we emit the smallest LEB encodings possible, we were writing the correct bytes in output files, but we were also improperly accepting binaries that used more than one byte to encode these values. This was caught by an upstream spec test.
* [NFC] Use HeapType::getKind more broadly (#6846)Thomas Lively2024-08-191-22/+29
| | | | | | | | Replace code that checked `isStruct()`, `isArray()`, etc. in sequence with uses of `HeapType::getKind()` and switch statements. This will make it easier to find the code that needs updating if/when we add new heap type kinds in the future. It also makes it much easier to find code that already needs updating to handle continuation types by grepping for "TODO: cont".
* Implement table.init (#6827)Alon Zakai2024-08-161-0/+20
| | | | | Also use TableInit in the interpreter to initialize module's table state, which will now handle traps properly, fixing #6431
* Save build ID in a source map (#6799)Marcin Kolny2024-08-151-1/+26
| | | | | | | This is based on these two proposals: * https://github.com/WebAssembly/tool-conventions/blob/main/BuildId.md * https://github.com/tc39/source-map/blob/main/proposals/debug-id.md
* [FP16] Implement relation operations. (#6825)Brendan Dahl2024-08-091-0/+24
| | | | 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/+14
| | | | Specified at https://github.com/WebAssembly/half-precision/blob/main/proposals/half-precision/Overview.md
* [FP16] Implement load and store instructions. (#6796)Brendan Dahl2024-08-061-16/+49
| | | | Specified at https://github.com/WebAssembly/half-precision/blob/main/proposals/half-precision/Overview.md
* [Source maps] Handle single-segment entries in source map header decoder (#6794)Ömer Sinan Ağacan2024-08-061-6/+13
| | | | | Single-segment mappings were already handled in readNextDebugLocation, but not in readSourceMapHeader.
* WasmBinaryReader: Use helper function to create names for items. NFC (#6810)Sam Clegg2024-08-051-14/+15
| | | | | As a followup we could probably make these more consistent. For example, we could use a single char prefix for defined functions/tables/globals (e.g. f0/t0/g0)
* Use Names::getValidNameGivenExisting in binary reading (#6793)Alon Zakai2024-07-311-8/+3
| | | | | | We had a TODO to use it once Names was optimized, which it has been. The Names version is also far faster. When building https://github.com/JetBrains/kotlinconf-app it saves 70 seconds(!).
* [NFC] Add HeapType::isMaybeShared(BasicHeapType) utility (#6773)Thomas Lively2024-07-181-1/+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] 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.
* 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] ref.i31_shared (#6735)Thomas Lively2024-07-121-6/+12
| | | | | | | 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.
* Rename external conversion instructions (#6716)Jérôme Vouillon2024-07-081-6/+6
| | | | | | | | | 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.
* [threads] Validate shared-polymorphic instructions (#6702)Thomas Lively2024-06-251-2/+7
| | | | Such as `ref.eq`, `i31.get_{s,u}`, and `array.len`. Also validate that struct and array operations work on shared 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 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.