summaryrefslogtreecommitdiff
path: root/src
Commit message (Collapse)AuthorAgeFilesLines
...
* [Strings] Limit string allocations like we do arrays (#6562)Alon Zakai2024-04-291-3/+8
| | | | | | | | When we concat strings, check if their length exceeds a reasonable limit. (We do not need to do this for string.new as that reads from an array, which is already properly limited.) This avoids very slow pauses in the fuzzer (that sometimes OOM).
* [Strings] wasm-ctor-eval: Stop on seeing a string view, which we cannot ↵Alon Zakai2024-04-291-0/+8
| | | | precompute (#6561)
* [Parser] Re-use blocks instead of wrapping where possible (#6552)Thomas Lively2024-04-291-6/+11
| | | | | | | When the input has branches to block scope, IR builder generally has to add a wrapper block with a label name for the branch to target. To reduce the parsed IR size, add a special case for when the wrapped expression is already an unnamed block. In that case we can simply add the label to the existing block instead of creating a new wrapper block.
* [Strings] Work around ref.cast not working on string views, and add fuzzing ↵Alon Zakai2024-04-293-4/+52
| | | | | | | | | | | | | (#6549) As suggested in #6434 (comment) , lower ref.cast of string views to ref.as_non_null in binary writing. It is a simple hack that avoids the problem of V8 not allowing them to be cast. Add fuzzing support for the last three core string operations, after which that problem becomes very frequent. Also add yet another makeTrappingRefUse that was missing in that fuzzer code.
* [Parser][NFC] Clean up the lexer index/pos API (#6553)Thomas Lively2024-04-293-32/+30
| | | | | The lexer previously had both `getPos` and `getIndex` APIs that did different things, but after a recent refactoring there is no difference between the index and the position. Deduplicate the API surface.
* [NFC] Use the new wat parser in RemoveNonJSOps (#6554)Thomas Lively2024-04-291-5/+4
|
* Use the new wat parser in the C API (#6555)Thomas Lively2024-04-291-7/+4
|
* Improve return validation (#6551)Thomas Lively2024-04-291-10/+18
| | | | Disallow returns from having any children, even unreachable children, in function that do not return any values.
* Fix a bug with unreachable control flow in IRBuilder (#6558)Jérôme Vouillon2024-04-292-14/+30
| | | | | | | | | | | | When branches target control flow structures other than blocks or loops, the IRBuilder wraps those control flow structures with an extra block for the branches to target in Binaryen IR. When the control flow structure is unreachable because all its bodies are unreachable, the wrapper block may still need to have a non-unreachable type if it is targeted by branches. This is achieved by tracking whether the wrapper block will be targeted by any branches and use the control flow structure's original, non-unreachable type if so. However, this was not properly tracked when moving into the `else` branch of an `if` or the `catch`/`cath_all` handlers of a `try` block.
* [jspi] - Support new version of JSPI for module splitting. (#6546)Brendan Dahl2024-04-291-6/+20
| | | | | | With the old version of JSPI, the JSPI pass was required to be run before splitting and would automatically add an export to be able to find the load_secondary_module function. Now that the pass is no longer needed, just add an import manually for the load_secondary_module function.
* [Parser] Do not eagerly lex numbers (#6544)Thomas Lively2024-04-252-293/+141
| | | | Lex integers and floats on demand to avoid wasted work. Remove `Token` completely now that all kinds of tokens are lexed on demand.
* [Parser] Do not eagerly lex strings (#6543)Thomas Lively2024-04-252-49/+25
| | | Lex them on demand instead to avoid wasted work.
* [Parser] Do not eagerly lex IDs (#6542)Thomas Lively2024-04-252-43/+23
| | | Lex them on demand instead to avoid wasted work.
* [Parser] Do not eagerly lex keywords (#6541)Thomas Lively2024-04-252-85/+56
| | | Lex them on demand instead to avoid wasted work.
* [Parser] Do not eagerly lex parens (#6540)Thomas Lively2024-04-253-66/+36
| | | | | | | | | | | The lexer currently lexes tokens eagerly and stores them in a `Token` variant ahead of when they are actually requested by the parser. It is wasteful, however, to classify tokens before they are requested by the parser because it is likely that the next token will be precisely the kind the parser requests. The work of checking and rejecting other possible classifications ahead of time is not useful. To make incremental progress toward removing `Token` completely, lex parentheses on demand instead of eagerly.
* [Strings] Fix effects of string.compare and add fuzzing (#6547)Alon Zakai2024-04-253-12/+34
| | | | | | | | We added string.compare late in the spec process, and forgot to add effects for it. Unlike string.eq, it can trap. Also use makeTrappingRefUse in recent fuzzer string generation places that I forgot, which should reduce the amount of traps in fuzzer output.
* [Parser] Enable the new text parser by default (#6371)Thomas Lively2024-04-252-1/+3
| | | | | | | | | | | | | | The new text parser is faster and more standards compliant than the old text parser. Enable it by default in wasm-opt and update the tests to reflect the slightly different results it produces. Besides following the spec, the new parser differs from the old parser in that it: - Does not synthesize `loop` and `try` labels unnecessarily - Synthesizes different block names in some cases - Parses exports in a different order - Parses `nop`s instead of empty blocks for empty control flow arms - Does not support parsing Poppy IR - Produces different error messages - Cannot parse `pop` except as the first instruction inside a `catch`
* GUFA: Handle bottom types in filterDataContents() (#6545)Alon Zakai2024-04-251-1/+7
| | | | | | Normally a bottom type cannot reach there, as we ignore unreachable GC operations early on. However, we can infer a bottom type later during the flow, so we need to handle that (just not error on it, and for clarity during debugging we also clear the contents).
* [Strings] Fuzz string.encode (#6539)Alon Zakai2024-04-252-15/+52
| | | | | | | A little trickier than the others due to the risk of trapping, which this handles like the other array operations. Also stop using immutable i16 arrays for string operations - only mutable ones work atm.
* Do not add an extra null character when reading files (#6538)Thomas Lively2024-04-245-11/+5
| | | | | | | | The new wat parser currently considers itself to be at the end of the file whenever it cannot lex another token. This is not quite right, but fixing it causes parser errors because of the extra null character we were appending to files when we read them. This null character is not useful since we can already read files as `std::string`, which always has an implicit null character, so remove it. Clean up some users of `read_file` while we're at it.
* Fuzzer: Update the typeLocals data structure before mutation (#6537)Alon Zakai2024-04-242-2/+20
| | | | | Rather than compute the map of type to locals of that type once, at the start, also update it when relevant, as we can add more locals in some cases. This allows us to local.get from those late-added locals too.
* [Strings] Implement string.measure_wtf16 in interpreter (#6535)Alon Zakai2024-04-241-1/+1
|
* Add a flag to opt in to the old WAT parser (#6536)Thomas Lively2024-04-241-0/+7
| | | | | This flag is intended to help users gracefully migrate to the new wat parser. It will be removed again not too long after the new wat parser is enabled by default in wasm-opt.
* [Parser] Use the new parser in wasm-shell and wasm-as (#6529)Thomas Lively2024-04-246-74/+136
| | | | | | | | | | | | | | | | | | | Updating just one or the other of these tools would cause the tests spec/import-after-*.fail.wast to fail, since only the updated tool would correctly fail to parse its contents. To avoid this, update both tools at once. (The tests erroneously pass before this change because check.py does not ensure that .fail.wast tests fail, only that failing tests end in .fail.wast.) In wasm-shell, to minimize the diff, only use the new parser to parse modules and instructions. Continue using the legacy parsing based on s-expressions for the other wast commands. Updating the parsing of the other commands to use `Lexer` instead of `SExpressionParser` is left as future work. The boundary between the two parsing styles is somewhat hacky, but it is worth it to enable incremental development. Update the tests to fix incorrect wast rejected by the new parser. Many of the spec/old_* tests use non-standard forms from before Wasm MVP was standardized, so fixing them would have been onerous. All of these tests have non-old_* variants, so simply delete them.
* [wasm-shell] Error on unknown commands (#6528)Thomas Lively2024-04-241-0/+2
| | | | | | | | | We previously ignored unknown wast commands, which could lead to the mistaken impression that we were passing test cases that we were in fact not running at all. Clarify matters by having wasm-shell error out on unrecognized commands, and comment out all such commands in our versions of the spec test. As we work toward being able to run the upstream spec tests, having these unsupported commands explicitly commented out will make it easier to track progress toward full support.
* [Strings] Fuzzer: Emit StringConcat (#6532)Alon Zakai2024-04-242-67/+90
| | | Also refactor the code a little to make it easier to add this (mostly whitespace).
* [Strings] Do not reuse mutable globals in StringGathering (#6531)Alon Zakai2024-04-241-1/+2
| | | | | We were reusing mutable globals in StringGathering, which meant that we'd use a global to represent a particular string but if it was mutated then it could contain a different string during execution.
* Fuzzer: Compare strings (#6530)Alon Zakai2024-04-241-11/+15
|
* Source maps: Fix missing debug info in nested blocks (#6525)Jérôme Vouillon2024-04-241-0/+1
| | | The special block nesting logic also needs to handle emitting debug info.
* [Strings] Add the string heaptype to core fuzzer places (#6527)Alon Zakai2024-04-231-20/+23
| | | | | | | With this we emit strings spontaneously (as opposed to just getting them from initial contents). The relevant -ttf test has been tweaked slightly to show the impact of this change: now there are some string.new/const in the output.
* [Strings] Fuzz and interpret all relevant StringNew methods (#6526)Alon Zakai2024-04-233-41/+94
| | | | This adds fuzzing for string.new_wtf16_array and string.from_code_point. The latter was also missing interpreter support, which this adds.
* [EH] Fix assumption that all throw_refs are created from rethrows (#6524)Heejin Ahn2024-04-241-5/+7
| | | | | | | | `shouldBeRef` incorrectly assumed that all `throw_ref`s within a `catch` body had been generated from `rethrow`s, which was not true, because `throw_ref`s are also created when translating `try`-`delegate`s: https://github.com/WebAssembly/binaryen/blob/219e668e87b012c0634043ed702534b8be31231f/src/passes/TranslateEH.cpp#L304 This fixes the assumption and changes `cast` to `dynCast`.
* [EH] Fix missing outer block for catchless try (#6519)Heejin Ahn2024-04-241-8/+21
| | | | | | | | | | | | | | | | | | | When translating a `try` expression, we may need an 'outer' block that wraps the newly generated `try_table` so we can jump out of the expression when an exception does not occur. (The condition we use is when the `try` has any catches or if the `try` is a target of any inner `try-delegate`s: https://github.com/WebAssembly/binaryen/blob/219e668e87b012c0634043ed702534b8be31231f/src/passes/TranslateEH.cpp#L677) In case the `try` has either of `catch` or `delegate`, when we have the 'outer' block, we add the newly created `try_table` in the 'outer' block and replace the whole expression with the block: https://github.com/WebAssembly/binaryen/blob/219e668e87b012c0634043ed702534b8be31231f/src/passes/TranslateEH.cpp#L670 https://github.com/WebAssembly/binaryen/blob/219e668e87b012c0634043ed702534b8be31231f/src/passes/TranslateEH.cpp#L332-L340 But in case of a catchless `try`, we forgot to do that: https://github.com/WebAssembly/binaryen/blob/219e668e87b012c0634043ed702534b8be31231f/src/passes/TranslateEH.cpp#L388 So this PR fixes it.
* Precompute: Ignore mutable arrays in StringNew (#6522)Alon Zakai2024-04-231-0/+22
| | | | | All Struct/Array operations must ignore mutable fields in Precompute atm, which we did, but StringNew has an array variant that does an effective ArrayGet operation, which we didn't handle.
* OptimizeInstructions: Optimize subsequent struct.sets after ↵Alon Zakai2024-04-231-12/+21
| | | | | | | | | struct.new_with_default (#6523) Before we preferred not to add default values, as that increases code size. But since #6495 we turn more things into struct.new_with default, so it is important to handle this. It seems likely that in most cases the code size downside of adding default values is offset by avoiding a local.set later, so always do this (rather than add some kind of heuristic).
* [EH] Fix delegating to caller when func result is concrete (#6518)Heejin Ahn2024-04-231-1/+1
| | | | | | | | | | | hen the function return type is concrete, the translation result of a `try`-`delegate` that targets the caller includes a `return` that returns the whole function body: https://github.com/WebAssembly/binaryen/blob/219e668e87b012c0634043ed702534b8be31231f/src/passes/TranslateEH.cpp#L751-L763 We should do that based on the function's return type, not the function body's return type. The previous code didn't handle the case where the function's return type is concrete but the function body's return type is unreachable.
* [wasm-split] Do not split out functions referring to segments (#6517)Thomas Lively2024-04-231-4/+62
| | | | | | | Since data and elem segments cannot be imported or exported, there is no way to access them from the secondary module, so functions that need to refer to them cannot be split out. Fixes #6512.
* DebugLocationPropagation: pass debuglocation from parent node to chil… (#6500)许鑫权2024-04-215-45/+106
| | | | | | | | | | | | | | | | | | | This PR creates a pass to propagate debug location from parent node to child nodes which has no debug location with pre-order traversal. This is useful for compilers that use Binaryen API to generate WebAssembly modules. It behaves like `wasm-opt` read text format file: children are tagged with the debug info of the parent, if they have no annotation of their own. For compilers that use Binaryen API to generate WebAssembly modules, it is a bit redundant to add debugInfo for each expression, Especially when the compiler wrap expressions. With this pass, compilers just need to add debugInfo for the parent node, which is more convenient. For example: ``` (drop (call $voidFunc) ) ``` Without this pass, if the compiler only adds debugInfo for the wrapped expression `drop`, the `call` expression has no corresponding source code mapping in DevTools debugging, which is obviously not user-friendly.
* [Parser][NFC] Do less work when parsing function types (#6516)Thomas Lively2024-04-192-3/+11
| | | | | | | After the initial parsing pass to find the locations of all the module elements and after the type definitions have been parsed, the next phase of parsing is to visit all of the module elements and parse their types. This phase does not require parsing function bodies, but it previously parsed entire functions anyway for simplicity. To improve performance, skip that useless work.
* [Parser][NFC] Improve performance of idchar lexing (#6515)Thomas Lively2024-04-191-30/+18
| | | | | The parsing of idchars was hot enough to show up while profiling the parsing of a very large module. Optimize it to speed up the overall parse by about 16% in a very unscientific measurement.
* [Parser][NFC] Solve performance issue by adding maybeLabelidx (#6514)Thomas Lively2024-04-181-7/+21
| | | | | | | | | | | | | Creating an error in the parser is an extremely expensive operation for very large files because it has to traverse the input buffer and count newlines to compute the error message. Despite that, there are a few places were we create errors just to discard them and continue parsing. The most notable of these places was where we parsed the list of label index immediates for the br_table instruction. The parser determined the end of the list by intercepting the error produced when trying to parse one more label index. Fix this significant performance problem causing parsing to be quadratic by introducing and using `maybeLabelidx`, which tries to parse a label index but does not produce an error if it fails.
* [Strings] Fix finalize() of StringNew on arrays (#6511)Alon Zakai2024-04-181-1/+3
|
* OptimizeCasts: Also handle local.tee (#6507)Jérôme Vouillon2024-04-181-27/+26
| | | | | | | | | | | | | | | | | | Converts the following: (some.operation (ref.cast .. (local.tee $ref ..)) (local.get $ref) ) into: (some.operation (local.tee $temp (ref.cast .. (local.tee $ref ..)) ) (local.get $temp) )
* Remove unused options from wasm-shell (#6508)Thomas Lively2024-04-171-53/+10
| | | | | None of our tests exercised the --entry or --skip options in wasm-shell, and since wasm-shell is probably not used for anything outside our testing, there's no reason to keep them. Remove them.
* [Parser] Preserve try labels (#6505)Thomas Lively2024-04-172-43/+43
| | | | | | | | | | | | | | | | | | In the standard text format, try scopes can be targeted by both normal branches and delegates, but in Binaryen IR we only allow them to be targeted by delegates, so we have to translate branches to try scopes into branches to wrapper blocks instead. These wrapper blocks must have different names than the try expressions they wrap, so we actually need to track two label names for try expressions: one for delegates and another for normal branches. We previously tried to avoid this complexity by tracking only the branch label and computing the delegate label from the branch label as necessary, but that produced unnecessary wrapper blocks and ugly label names that did not appear in the source. To produce better IR and minimize the diff when switching to the new text parser, bite the bullet and track the delegate and branch label names separately. This eliminates unnecessary wrapper blocks and keeps try names the same as in the wat source where possible.
* [Parser] Match legacy parser block naming (#6504)Thomas Lively2024-04-163-7/+17
| | | | To reduce the size of the test output diff when switching to the new text parser, update it to generate the same block names as the legacy parser.
* [Parser] Pop past unreachables where possible (#6489)Thomas Lively2024-04-164-506/+1645
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | We previously would eagerly drop all concretely typed expressions on the stack when pushing an unreachable instruction. This was semantically correct and closely modeled the semantics of unreachable instructions, which implicitly drop the entire stack and start a new polymorphic stack. However, it also meant that the structure of the parsed IR did not match the structure of the folded input, which meant that tests involving unreachable children would not parse as intended, preventing the test from testing the intended behavior. For example, this wat: ```wasm (i32.add (i32.const 0) (unreachable) ) ``` Would previously parse into this IR: ```wasm (drop (i32.const 0) ) (i32.add (unreachable) (unreachable) ) ``` To fix this problem, we need to stop eagerly dropping stack values when encountering an unreachable instruction so we can still pop expressions pushed before the unreachable as direct children of later instructions. In the example above, we need to keep the `i32.const 0` on the stack so it is available to be popped and become a child of the `i32.add`. However, the naive solution of simply popping past unreachables would produce invalid IR in some cases. For example, consider this wat: ```wasm f32.const 0 unreachable i32.add ``` The naive solution would parse this wat into this IR: ```wasm (i32.add (f32.const 0) (unreachable) ) ``` But we do not want to parse an `i32.add` with an `f32`-typed child. Neither do we want to reject this input, since it is a perfectly valid Wasm fragment. In this case, we actually want the old behavior of dropping the `f32.const` and replacing it with another `unreachable` as the first child of the `i32.add`. To both match the input structure where possible and also gracefully fall back to the old behavior of dropping expressions prior to the unreachable, collect constraints on the types of each child for each kind of expression and compare them to the types of available expressions on the stack when an unreachable instruction will be popped. When the constraints are satisfied, pop expressions normally, even after popping the unreachable instruction. Otherwise, drop the instructions that precede the unreachable instruction to ensure we parse valid IR. To collect the constraints, add a new `ChildTyper` utility that calls a different callback for each kind of possible type constraint for each child. In the future, this utility can be used to simplify the validator as well.
* CoalesceLocals: ReFinalize when we refine a type (#6502)Alon Zakai2024-04-161-12/+12
| | | | | | | | | | | The code had a different workaround, namely to add a block with an explicit type to avoid changing the type at all (i.e. the block declared the original type of the thing we replaced, not the refined type). But by adding a block we can end up with an invalid pop, as the fuzzer found, see the EH testcase here. To fix this, use the usual workaround of just running ReFinalize. That is simpler and also improves the code while we do it. It does add more work, but this is likely a very rare situation anyhow.
* Do not repeat types names in text output (#6499)Thomas Lively2024-04-161-2/+35
| | | | | | | | | | For types that do not have explicit names, we generate index-based names in the printer. However, we did not previously ensure that the generated types were not already used as explicit names, so it was possible to print the same name for multiple types, which is not valid. Fix the problem by skipping indices that are already used as type names. Fixes #6492.
* Fuzzer: Randomly pick which functions to use in RefFunc (#6503)Alon Zakai2024-04-151-10/+12
| | | | | | | Previously we chose the first with a proper type, and now we start to scan from a random index, giving later functions a chance too, so we should be emitting a greater variety of ref.func targets. Also remove some obsolete fuzzer TODOs.