| Commit message (Collapse) | Author | Age | Files | Lines |
... | |
|
|
|
|
| |
In that mode a walk on an entire module will reuse the same CFGWalker
instance, so we must manually clear some fields, and we forgot some
before.
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
As of
https://chromium-review.googlesource.com/c/v8/v8/+/5471674
V8 requires stringviews to be non-nullable. It might be possible to make that
change in our IR, or to remove views entirely, but for now this PR makes the
fuzzer stop emitting nullable stringviews as a workaround to allow us to fuzz
current V8.
There are still rare corner cases where this pattern is emitted, that we have
not tracked down, and so this also makes the fuzzer ignore the error for now.
|
|
|
|
|
| |
When we have a ref.func that refers to the secondary module then make a trampoline
that calls it directly. The trampoline's call is then fixed up like all direct calls to the
secondary module.
|
|
|
|
|
|
|
|
|
| |
This allows writing of binaries with DWARF info when multivalue is
enabled. Currently we just crash when both are enabled together. This
just assumes, unless we have run DWARF-invalidating passes, all locals
added for tuples or scratch locals would have been added at the end of
the local list, so just printing all locals in order would preserve the
DWARF info. Tuple locals are expanded in place and scratch locals are
added at the end.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* Keep debug locations at function start
The `fn_prolog_epilog.debugInfo` test is failing otherwise, since there
was debug information associated to the nop instruction at the beginning
of the function.
* Do not clear the debug information when reaching the end of the source map
The last segment should extend to the end of the function.
* Propagate debug location from the function prolog to its first instruction
* Fix printing of epilogue location
The text parser no longer propagates locations to the epilogue, so we
should always print the location if there is one.
* Fix debug location smearing
The debug location of the last instruction should not smear into the
function epilogue, and a debug location from a previous function should
not smear into the prologue of the current function.
|
|
|
|
|
| |
Without this the fuzzer can error on differences in behavior between V8 and us.
Also move the limitations constants to their own header.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Helping #6509, this fixes debugging support for StackIR, which makes it more
possible to use StackIR in more places.
The fix is basically just to pass around some more state, and then to call the
parent with "please write debug info" at the correct times, mirroring the
similar calls in BinaryenIRWriter.
The relevant Emscripten tests pass, and the source map test modified
here produces identical output in StackIR and non-StackIR modes (the
test is also simplified to remove --new-wat-parser which is no longer
needed, after which the test can clearly show that StackIR has the same
output as BinaryenIR).
|
|
|
|
| |
This makes the cleanup of bodies of functions that have had constants hoisted from them more effective.
|
|
|
|
|
|
|
|
| |
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).
|
|
|
|
| |
precompute (#6561)
|
|
|
|
|
|
|
| |
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.
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
(#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.
|
|
|
|
|
| |
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.
|
| |
|
| |
|
|
|
|
| |
Disallow returns from having any children, even unreachable children, in
function that do not return any values.
|
|
|
|
|
|
|
|
|
|
|
|
| |
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.
|
|
|
|
|
|
| |
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.
|
|
|
|
| |
Lex integers and floats on demand to avoid wasted work. Remove `Token`
completely now that all kinds of tokens are lexed on demand.
|
|
|
| |
Lex them on demand instead to avoid wasted work.
|
|
|
| |
Lex them on demand instead to avoid wasted work.
|
|
|
| |
Lex them on demand instead to avoid wasted work.
|
|
|
|
|
|
|
|
|
|
|
| |
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.
|
|
|
|
|
|
|
|
| |
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.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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`
|
|
|
|
|
|
| |
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).
|
|
|
|
|
|
|
| |
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.
|
|
|
|
|
|
|
|
| |
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.
|
|
|
|
|
| |
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.
|
| |
|
|
|
|
|
| |
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.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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.
|
|
|
|
|
|
|
|
|
| |
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.
|
|
|
| |
Also refactor the code a little to make it easier to add this (mostly whitespace).
|
|
|
|
|
| |
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.
|
| |
|
|
|
| |
The special block nesting logic also needs to handle emitting debug info.
|
|
|
|
|
|
|
| |
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.
|
|
|
|
| |
This adds fuzzing for string.new_wtf16_array and string.from_code_point. The
latter was also missing interpreter support, which this adds.
|
|
|
|
|
|
|
|
| |
`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`.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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.
|
|
|
|
|
| |
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.
|
|
|
|
|
|
|
|
|
| |
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).
|
|
|
|
|
|
|
|
|
|
|
| |
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.
|
|
|
|
|
|
|
| |
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.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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.
|
|
|
|
|
|
|
| |
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.
|
|
|
|
|
| |
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.
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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.
|
| |
|