| Commit message (Collapse) | Author | Age | Files | Lines |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
We previously thought unreachable `tuple.make` instructions did not
require special unreachable handling, but consider the following wast:
```
(module
(func $foo
(tuple.make
(unreachable)
(i32.const 42)
)
)
)
```
This validates because the only expression in the body is unreachable,
but when it is emitted as a binary it becomes
```
unreachable
i32.const 42
```
This does not validate because it ends with an i32, but the function
expected an empty stack at the end. The fix is to emit an extra
`unreachable` after unreachable `tuple.make`
instructions. Unfortunately it is impossible to write a test for this
right now because the binary parser silently drops the `i32.const 42`,
making the function valid again.
|
|
|
| |
Iterate over tuple locals and separately load or store each component.
|
|
|
|
|
|
| |
The meaning we intend is "constant", and not the "Const"
node (which contains a number). So I think the full
name is less confusing.
|
|
|
|
|
| |
It should be a signed LEB128, not an unsigned LEB128. This bug was
causing modules to be invalid when the number of signatures in the
type section was large and multivalue blocks were present.
|
|
|
|
|
| |
RemoveUnusedBrs produces selects for some patterns, but selects of
multivalue types are not valid. This change checks that types are not
tuple types before producing selects.
|
|
|
|
|
|
|
|
|
| |
Previously the signature collection mechanism responsible for
populating the type section with signatures used by instructions only
collected signatures from indirect call and block instructions. This
works as long as all other control flow constructs like ifs, loops,
and tries contain blocks with the same signature. But it is possible
to have an if with non-block children, and we would need to collect
its signature as well.
|
| |
|
|
|
|
| |
Also increases the usefulness of a couple wasm-builder methods that
are useful here.
|
| |
|
|
|
|
|
|
|
|
| |
Also makes it work with any other constant expression such as a
ref.func or ref.null instructions. This optimization may not be very
important, but it illustrates how simple it can be to update a pass to
handle tuples (and also I was already looking at it because of the
prior changes that had to be made to it).
|
|
|
|
|
|
| |
This involves replacing `Literal::makeZero` with `Literal::makeZeroes`
and `Literal::makeSingleZero` and updating `isConstantExpression` to
handle constant tuples as well. Also makes `Literals` its own struct
and adds convenience methods on it.
|
|
|
|
| |
Updates the interpreter to properly flow vectors of values, including
at function boundaries. Adds a small spec test for multivalue return.
|
|
|
| |
Using CRTP, yay!
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
We assumed that the imports were already named (in their
internal name) properly. When processing a binary file without
names, or if the names don't match in general, that's not true.
To fix this, use ModuleUtils::renameFunctions to do a proper
renaming up front.
Also fix renameFunctions to not assert on the case of
renaming a function to the same name it already has.
Helps #2680
|
|
|
|
|
|
|
|
|
| |
Implements parsing and emitting of tuple creation and extraction and tuple-typed control flow for both the text and binary formats.
TODO:
- Extend Precompute/interpreter to handle tuple values
- C and JS API support/testing
- Figure out how to lower in stack IR
- Fuzzing
|
|
|
|
|
|
|
|
|
|
| |
Such a module can't have valid DIEs, since we have no way to
interpret them.
Also check if DWARF sections from LLVM have contents -
when they are empty the section may exist but have a null
for its data.
Fixes #2673
|
|
|
|
|
|
|
|
|
|
| |
Normally, a wrapper has to track state separately to know when to
unwind/rewind and when to actually call import functions.
Exposing Asyncify state can help avoid this duplication and avoid
subtle bugs when internal and wrapper state get out of sync.
Since this is a tiny function and it's useful for any Asyncify
embedder, I've decided to expose it by default rather than hide behind an option.
|
| |
|
| |
|
|
|
|
|
|
|
|
|
| |
Updates `BinaryInstWriter::mapLocalsAndEmitHeader` so it no longer hardcodes
each possible local type. Also adds a new inner loop over the elements of any
local tuple type in the IR. Updates the map from IR local indices to binary
indices to be additionally keyed on the index within a tuple type. Since we do
not generate tuple types yet, this additional index is hardcoded to zero
everywhere it is used for now. A later PR adding tuple creation operations will
extend this functionality and add tests.
|
| |
|
|
|
|
|
|
|
|
|
|
|
| |
This does two things:
- Treats the target branch of `br_on_exn` as unoptimizables, because it
is a conditional branch.
- Makes sure we don't move expressions that contain `exnref.pop`, which
should follow right after `catch`.
- Adds `containsChild` utility function, which can search all children,
optionally with limited depth. This was actually added to be used in
CodeFolding but ended up not being used, but wasn't removed in case
there will be uses later.
|
|
|
|
|
|
|
|
| |
* Fix to https://github.com/WebAssembly/binaryen/issues/2170
* Adjust fix
* clang-format
|
|
|
|
|
| |
This adds AutoDrop (+ ReFinalize) support for Try. We don't have
`--autodrop` option so I can't add a separate test for this, but this is
basically the same as what If does.
|
| |
|
|
|
|
| |
This adds support for UniqueNameMapper, and adds a test in Inlining
pass, which uses UniqueNameMapper.
|
|
|
|
|
|
|
|
|
| |
Like `br_if`, `br_on_exn` is a conditional branch and across which code
can be pushed past when conditions are satisfied.
Also adds a few lines of comments and NFC changes in a couple places.
Changes in Vacuum are NFC because they were being handled in `default:`
in the same way anyway, but I added them to be more explicit and
consistent with existing code.
|
|
|
|
|
|
|
|
|
|
|
| |
Don't print the entire module on an error. Instead, just print
the validation errors.
However, if the user passed --print, then do print it, as otherwise
nothing would get printed - the error would be before the pass
to print happens. And in general a user passing in a request
to print would expect a printed module anyhow.
fixes #2634
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
If an invalid entry appears - either it began as such, or became
invalid after optimization - we should not emit (0, 0) which is
an end marker. Instead, emit an invalid entry marker, something
with (0, x) for x != 0.
As a bonus, if a test/passes case has "noprint" in the name,
don't print the wasm, which we do by default. In the testcase
here for example we just care about the dwarf, and the
printed module would be quite large.
Thank you to @paolosevMSFT for identifying and suggesting
the fix.
|
|
|
|
|
|
|
|
|
|
| |
Allows a user to modify the inlining limits using the C- and JS-APIs.
* binaryen.**getAlwaysInlineMaxSize**(): `number`
* binaryen.**setAlwaysInlineMaxSize**(size: `number`): `void`
* binaryen.**getFlexibleInlineMaxSize**(): `number`
* binaryen.**setFlexibleInlineMaxSize**(size: `number`): `void`
* binaryen.**getOneCallerInlineMaxSize**(): `number`
* binaryen.**setOneCallerInlineMaxSize**(size: `number`): `void`
|
| |
|
|
|
|
|
|
|
|
|
|
| |
EMSCRIPTEN_END_FUNCS markers. (#2626)
* Fix missing newline after // EMSCRIPTEN_START_FUNCS and // EMSCRIPTEN_END_FUNCS markers.
* Flake
* Update tests
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* Optimize base64 decoding (about 7x-10x faster and temporary garbage-free compared to the original version)
* new Uint8Array
* Reuse Uint8Array view
* Fix end handling
* Code format
* Update tests
|
|
|
|
| |
If try's body does not throw, the whole try-catch can be replaced with
the try body.
|
|
|
|
|
|
|
|
|
| |
Allows a user to enable/disable the `lowMemoryUnused` option and to get/set/clear arbitrary pass arguments when using the C- or JS-APIs.
* binaryen.**getLowMemoryUnused**(): `boolean`
* binaryen.**setLowMemoryUnused**(on: `boolean`): `void`
* binaryen.**getPassArgument**(key: `string`): `string | null`
* binaryen.**setPassArgument**(key: `string`, value: `string | null`): `void`
* binaryen.**clearPassArguments**(): `void`
|
|
|
|
|
|
|
|
|
|
|
| |
Anything that merges/swaps/etc. locals, or inlines, or merges functions,
must be disabled for now. However, that does still leave almost all
passes, so this should not affect output sizes much (and the full LLVM
optimizer can be run before too).
Over time we can resolve each of those FIXMEs.
The test output here shows how disabling those allows over twice as
much debug_line info to be preserved.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Now that we have subtypes, we cannot reuse any local that contains the
same expression, because that local's type can be a supertype. For
example:
```
(local $0 anyref)
(local $1 nullref)
...
(local.set $0 (ref.null))
(local.set $1 (ref.null)) ;; cannot be replaced with (local.get $0)
```
This extends `usables` map's key to contain both `HashedExpression` and
the local's type, so we can get the right usable local in presence of
subtypes.
|
|
|
|
|
|
| |
- Adds support for `Try` in `optimizeBoolean` function
- Adds support for `Try` in `getFallThrough` function
- Adds approximate cost values for instructions in EH and reference
types proposals.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
We've been throwing some fuzzing at some wasm implementations recently
and one of our strategies is to use `wasm-opt -ttf` with the fuzzer's
input to generate a wasm module. Some of our tests, though, have been
failing due to out-of-memory while `wasm-opt` is generating a module.
This loop appears to be infinitely executing since the input
just-so-happens that `oneIn(3)` returns true for every byte of the input
file, or at least enough such that when the xor factor is merged in it
at least generates very long sequence of `true`.
It looks like elsewhere in the file when `while (oneIn(N))` is used it's
also guarded by `!finishedInput`, so I've added a similar guard here as
well.
|
|
|
|
|
|
|
|
|
|
|
| |
This makes the interpreter trap when the signature in `call_indirect`
instruction and that of the actual function in the table mismatch. This
also makes the `wasm-ctor-eval` not evaluate `call_indirect` in case the
signatures mismatch.
Before we only compared the arguments' signature and the function
signature, which was sufficient before we had subtypes, but now the
signature in `call_indirect` and that of the actual function can be
different even if the argument's signature is OK.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
This adds EH support to `EffectAnalyzer`. Before `throw` and `rethrow`
conservatively set property. Now `EffectAnalyzer` has a new property
`throws` to represent an expression that can throw, and expression that
can throw sets `throws` correctly.
When EH is enabled, any calls can throw too, so we cannot reorder them
with another expression with any side effects, meaning all calls should
be treated in the same way as branches when evaluating `invalidate`.
This prevents many reorderings, so this patch sets `throws` for calls
only when the exception handling features is enabled. This is also why I
passed `--disable-exception-handling` to `wasm2js` tests. Most of code
changes outside of `EffectAnalyzer` class was made in order to pass
`FeatureSet` to it.
`throws` isn't always set whenever an expression contains a throwable
instruction. When an throwable instruction is within an inner try, it
will be caught by the corresponding inner catch, so it does not set
`throws`.
|
|
|
|
|
|
|
|
|
| |
CMAKE_PROJECT_VERSION is only predefined on cmake 3.12 and later,
so the previous code produced an empty version number which leads
to parsing errors when emcc checks the version.
Use of the older PROJECT_VERSION variable as the source of the
original version works here, as there's only one toplevel project
defined.
|
|
|
|
|
|
|
|
| |
(#2628)
The debug_line section is the only one in which we change
sizes and so must update offsets. It turns out that there are such
offsets, DW_AT_stmt_list, so without updating them we can't
handle multi-unit dwarf files.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
This replaces imports like env.foo with a.foo, which can
save a bunch of bytes when there are many imported
functions.
Note that by changing all the import names to a it ends
up requiring a single merged import module.
Note also that when doing this we modify all the imports,
minifying their modules and names (since it makes no
sense to be careful about minifying only modules known
to us - env/wasi - if we are minifyin the names of all
modules).
This will require an emscripten PR to benefit from it.
|
|
|
|
|
|
|
|
|
| |
The LLVM SData field is 64-bit (to support 64-bit
addresses I suppose) so when we assigned to it we
actually led it to emit an LEB for a signed 64-bit value
that is an unsigned 32-bit one. This worked in LLVM
(where I guess it forces the value to 32-bit anyhow?)
but failed in gimli (where I guess it doesn't?).
|
|
|
|
|
| |
This reverts commit 132daae1e9154782bb1afa5df80dfe7ea35f0369.
This change is the same as before but the fix in #2619 should now make it safe.
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
We ignored them, which is a bad default, as typically they imply
we can call anything in the table (and the table might change).
Instead, notice indirect calls during traversal, and force the user
to decide whether to ignore them or not.
This was only an issue in PostEmscripten because the other
user, Asyncify, already had indirect call analysis because it
needed it for other things.
Fixes a bug uncovered by #2619 and fixes the current binaryen
roll.
|
|
|
|
|
|
|
| |
We should be looking at the import name when determining if a function
is an invoke function.
This is a precursor to re-landing the fix for
https://github.com/emscripten-core/emscripten/issues/9950.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Add support for that section to the YAML layer, and add
code to update it.
The updating is slightly tricky - unlike .debug_ranges, the
size of entries is not fixed. So we can't just skip entries,
as the end marker is smaller than a normal entry. Instead,
replace now-invalid segments with (1, 1) which is of size
0 and so should be ignored by the debugger (we can't use
(0, 0) as that would be an end marker, and (-1, *) is
the special base marker).
In the future we probably do want to do this in a more
sophisticated manner, completely rewriting the indexes
into the section as well. For now though this should be
enough for when binaryen does not optimize (as we
don't move/reorder anything).
Note that this doesn't update the location description
(like where on the wasm expression stack the value is).
Again, that is correct for when binaryen doesn't
optimize, but for fully optimized builds we would need
to track things (which would be hard!).
Also clean up some code that uses "Extra" instead of
"Delimiter" that was missed before, and shorten some
unnecessarily long names.
|