| Commit message (Collapse) | Author | Age | Files | Lines |
| |
|
|
|
|
|
|
|
|
|
|
| |
This updates C and binaryen.js API to match the new `Try` structure to
support `delegate`, added in #3561. Now `try` can take a name (which can
be null) like a block, and also has an additional `delegateTarget` field
argument which should only be used for try-delegate and otherwise null.
This also adds several more variant of `makeTry` methods in
wasm-builder. Some are for making try-delegate and some are for
try-catch(_all).
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
So far `Try`'s label is only targetted by `delegate`s, but it turns out
`rethrow` also has to follow the same rule as `delegate` so it needs to
target a `Try` label. So this renames variables like
`delegateTargetNames` to `exceptionTargetNames` and methods like
`replaceDelegateTargets` to `replaceExceptionTargets`.
I considered `tryTarget`, but the branch/block counterpart name we use
is not `blockTarget` but `branchTarget`, so I chose `exceptionTarget`.
The patch that fixes `rethrow`'s target will follow; this is the
preparation for that.
|
| |
|
|
|
|
|
| |
That is, if a wasm says "simd", it is ok to let the user specify simd
as well as more features, and the the optimizer can perhaps do something
with them.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
This adds support for reading/writing of the new `delegate` instruction
in the folded wast format, the stack IR format, the poppy IR format, and
the binary format in Binaryen. We don't have a formal spec written down
yet, but please refer to WebAssembly/exception-handling#137 and
WebAssembly/exception-handling#146 for the informal semantics. In the
current version of spec `delegate` is basically a rethrow, but with
branch-like immediate argument so that it can bypass other
catches/delegates in between.
`delegate` is not represented as a new `Expression`, but it is rather
an option within a `Try` class, like `catch`/`catch_all`.
One special thing about `delegate` is, even though it is written
_within_ a `try` in the folded wat format, like
```wasm
(try
(do
...
)
(delegate $l)
)
```
In the unfolded wat format or in the binary format, `delegate` serves as
a scope end instruction so there is no separate `end`:
```wasm
try
...
delegate $l
```
`delegate` semantically targets an outer `catch` or `delegate`, but we
write `delegate` target as a `try` label because we only give labels to
block-like scoping expressions. So far we have not given `Try` a label
and used inner blocks or a wrapping block in case a branch targets the
`try`. But in case of `delegate`, it can syntactically only target `try`
and if it targets blocks or loops it is a validation failure.
So after discussions in #3497, we give `Try` a label but this label can
only be targeted by `delegate`s. Unfortunately this makes parsing and
writing of `Try` expression somewhat complicated. Also there is one
special case; if the immediate argument of `try` is the same as the
depth of control flow stack, this means the 'delegate' delegates to the
caller. To handle this case this adds a fake label
`DELEGATE_CALLER_TARGET`, and when writing it back to the wast format
writes it as an immediate value, unlike other cases in which we write
labels.
This uses `DELEGATE_FIELD_SCOPE_NAME_DEF/USE` to represent `try`'s label
and `delegate`'s target. There are many cases that `try` and
`delegate`'s labels need to be treated in the same way as block and
branch labels, such as for hashing or comparing. But there are routines
in which we automatically assume all label uses are branches. I thought
about adding a new kind of defines such as
`DELEGATE_FIELD_TRY_NAME_DEF/USE`, but I think it will also involve some
duplication of existing routines or classes. So at the moment this PR
chooses to use the existing `DELEGATE_FIELD_SCOPE_NAME_DEF/USE` for
`try` and `delegate` labels and makes only necessary amount of changes
in branch-utils. We can revisit this decision later if necessary.
Many of changes to the existing test cases are because now all `try`s
are automatically assigned a label. They will be removed in
`RemoveUnusedNames` pass in the same way as block labels if not targeted
by any delegates.
This only supports reading and writing and has not been tested against
any optimization passes yet.
---
Original unfolded wat file to generate test/try-delegate.wasm:
```wasm
(module
(event $e)
(func
try
try
delegate 0
catch $e
end)
(func
try
try
catch $e
i32.const 0
drop
try
delegate 1
end
catch $e
end
)
)
```
|
|
|
|
|
|
|
| |
If we find a data segment whose entire contents is EM_JS or EM_ASM
strings then strip it from the binary.
See: https://github.com/emscripten-core/emscripten/pull/13443
|
|
|
|
|
|
|
|
| |
Add a utility for calculating the least upper bounds of two StackSignatures,
taking into account polymorphic unreachable behavior. This will important in the
finalization and validation of Poppy IR blocks, where a block is allowed to
directly produce fewer values than the branches that target it carry if the
difference can be made up for by polymorphism due to an unreachable instruction
in the block.
|
| |
|
|
|
|
|
|
|
| |
GenerateDynCalls was hardcoding the table name to use in the call_indirects in
the dyncall thunks. The hardcoded name was different from the default name for
imported tables, so the call_indirects referred to a nonexistent table when
dynamic linking was enabled. This PR instead uses the name of table 0 when
creating call_indirects for the dyncall thunks.
|
|
|
|
|
|
|
|
| |
Support for multiple signatures per JS code string was removed in #2422.
emscripten now only needs to know that address and the body of the JS
function.
See https://github.com/emscripten-core/emscripten/pull/13452.
|
|
|
|
| |
This allows the reducer to operate on RTTs, but could help other
things too.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Adds a Poppify ("--poppify") pass for converting normal Binaryen IR to Poppy IR.
Like the existing construction of Stacky IR, Poppify depends on the
BinaryenIRWriter to drive the emitting of instructions in correct stack machine
order. As instructions are "emitted," Poppify replaces their children with pops
and collects them in a list. At the end of each scope, Poppify creates a block
containing all the collected instructions for that scope and injects that block
into the enclosing scope. All tuple globals and instructions dealing with tuples
are also expanded to remove all tuples from the program.
The validator currently fails to validate many valid Poppy IR patterns produced
in the tests, but fixing that is left as follow-on work to keep this PR focused
on the Poppify pass itself. For now the tests simply skip validation.
|
|
|
| |
Adds support for modules with multiple tables. Adds a field for the table name to `CallIndirect` and updates the C/JS APIs accordingly.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
I had completely missed that the spec allows ref.cast etc. of function types,
and not just data. Function types do not have an RTT, unlike GC data, but we
can still cast them. A function reference has the canonical RTT of the signature
for that type, so it's like a simplified case of the GC world, without a hierarchy
of RTTs.
As it turns out, our validation did not rule out rtt.canon of a function type,
nor ref.cast of one, so we unintentionally already had all the support for this
aside from the actual casting, which this PR adds.
The addition is mostly trivial, except that we now need a Module in the base
ExpressionRunner class, so that we can go from a function name to the actual
function. This PR refactors things to allow that.
|
|
|
|
|
| |
This is a pure refactor in preparation for change that will
enable stripping or at least zeroing segments that only contain
EM_JS/EM_ASM strings.
|
|
|
|
|
|
| |
The algorithm was trying to remove all __em_js functions but it was
using the names of functions rather than export names so it was failing
to remove these functions unless the internal function names happened to
match (this turns out of the true for build with debug names).
|
|
|
|
| |
We can't arbitrarily replace a non-defaultable type, as it may lead to us
needing a temp local for it (say, in a tuple).
|
|
|
|
|
|
| |
This will allow .fromBinary tests be executed with the desired featurs
so there will be no difference between those tests and .from-wast tests.
Fixes #3545
|
|
|
|
|
|
|
| |
Unordered maps will hash the pointer, while ordered ones will compare the
strings to find where to insert in the tree. I cannot confirm a speedup in time
from this, though others can, but I do see a consistent improvement of a
few % in perf stat results like number of instructions and cycles (and those
results have little noise). And it seems logical that this could be faster.
|
|
|
|
|
|
|
| |
If the reference is unreachable then we cannot find the heap type to print
in the text format. Instead of crashing or emitting something invalid, print
a block instead - the block contains the children so they are emitted, and
as the instruction was unreachable anyhow, this has no noticeable effect.
It also parallels what we do in the binary format - skip unreachable code.
|
|
|
|
|
|
|
|
| |
* Fix label fixup code to use delegates-fields. This makes it support BrOn etc.
* Add an isRtt() in places RTTs are not supported.
* Implement makeConst for arbitrary RTTs.
This is enough to get the fuzzer working for more than a few iterations at
a time, but no more.
|
| |
|
|
|
|
|
| |
This adds missing stack IR printing support for the new form of
try-catch-catch_all. Also uses `printMedium` when printing instructions
consistently.
|
|
|
|
|
|
|
| |
dataref was not noted as isRef, and we also did not handle the LUB for it,
which caused validation errors. After these two fixes, it is possible to add a
testcase that goes through the optimizer.
View without whitespace as the LUB change has a lot of that.
|
|
|
|
|
|
|
|
|
|
| |
As discussed in #3517, we need a way to maintain the ability to print
expressions in a backward-compatible way. This adds a FeatureSet
to PrintExpressionContents which defaults to FeatureSet::All in case
a feature set is not available.
This will be used for CallIndirect to decide whether to print the table
name arg.
|
|
|
|
|
|
|
|
| |
As proposed in https://github.com/WebAssembly/simd/pull/395. Note that the other
instructions in the proposal have not been implemented in LLVM or in V8, so
there is no need to implement them in Binaryen right now either. This PR
introduces a new expression class for the new instructions because they uniquely
take an immediate argument identifying which portion of the input vector to
widen.
|
|
|
|
|
|
|
|
|
| |
We added isGCData() before we had dataref. But now there is a clear
parallel of Function vs Data. This PR makes us more consistent there,
renaming isGCData to isData and using that throughout.
This also fixes a bug where the old isGCData just checked if the input
was an Array or a Struct, and ignored the data heap type itself. It is not
possible to test that, however, due to other bugs, so that is deferred.
|
|
|
|
|
|
|
|
|
|
|
| |
This is only partial support, as br_on_null also has an extra optional
value in the spec. Implementing that is cumbersome in binaryen, and
there is ongoing spec discussions about it (see
https://github.com/WebAssembly/function-references/issues/45 ), so
for now we only support the simple case without the default value.
Also fix prefixed opcodes to be LEBs in RefAs, which was noticed here
as the change here made it noticeable whether the values were int8 or
LEBs.
|
|
|
|
|
|
|
| |
That type is non-nullable, so we need to disable it until we fully support that.
Right now if we emit such locals we immediately get a validation error.
With this change the fuzzer can run at least a few thousand iterations with
no errors once more.
|
|
|
|
|
|
| |
This break stack is maintained to compute branch depths, but it seems we
don't need to push and pop for each of if and else block or every single
catch/catch_all block; it would be sufficient to have just one stack
entry for the whole try-catch or if-else.
|
|
|
|
|
|
|
| |
We used to error out in Flatten when EH is used because Flatten makes
all block types `none` by setting their return values to locals and
getting them later, but `br_on_exn` by definition pops value from the
value stack at the end of a block so it couldn't be flattened. Now that
we don't have `br_on_exn` we don't need these restriction.
|
|
|
|
|
|
| |
This is different than the other RefAs variants in that it is part of the
typed functions proposal, and not GC. But it is part of GC prototype 3.
Note: This is not useful to us yet as we don't support non-nullable types.
|
|
|
|
|
|
|
|
| |
This expands the existing BrOnCast into BrOn that can also handle the
func/data/i31 variants. This is not as elegant as RefIs / RefAs in that BrOnCast
has an extra rtt field, but I think it is still the best option. We already have optional
fields on Break (the value and condition), so making rtt optional is not odd. And
it allows us to share all the behavior of br_on_* which aside from the cast or the
check itself, is identical - returning the value if the branch is not taken, etc.
|
|
|
|
|
|
|
| |
As a result, we cannot handle a br_on_cast with an unreachable RTT. The
binary format solves the problem by ignoring unreachable code, and this makes
the text format do the same.
A nice benefit of this is that we can remove the castType extra field.
|
|
|
|
|
|
| |
wasm-finalize currently makes byte-wise copies of section data in the
user and data sections. If the section is large, that's extraordinarily
expensive. With a memcpy instead I see a speedup of 1.6 for a large
wasm binary with DWARF data.
|
|
|
|
|
|
|
|
|
|
| |
This used to return a simple name like "if" for an If, but it is redundant with
our proper printing logic. This PR turns it into a trivial helper that just prints
out the name of the class, so it now prints "If" with a capital. That is useful
for some logging, like in Metrics I think it is clearer than it was earlier (since
we are actually counting the classes, and our old emitting of text-format-like
names are just confusing, as we emitted "binary" there which is not valid).
Also replace some usages of that method with proper printing.
|
|
|
|
|
|
|
|
| |
These are similar to is, but instead of returning an i32 answer, they trap on
an invalid value, and return it otherwise.
These could in theory be in a single RefDoThing, with opcodes for both As
and Is, but as the return values are different, that would be a little odd, and
the name would be less clear.
|
| |
|
|
|
|
|
|
|
|
| |
This internal refactoring prepares us for ref.is_func/data/i31, by renaming
the node and adding an "op" field. For now that field must always be "Null"
which means it is a ref.is_null.
This adjusts the C API to match the new IR shape. The high-level JS API
is unchanged.
|
|
|
|
|
|
|
|
|
|
|
|
| |
Previously the addDefault* methods would avoid adding opt passes that we
know are incompatible with DWARF. However, that didn't handle the case of
passes that are added in other ways. For example, when running Asyncify,
emcc will run --flatten before, and that pass is not compatible with DWARF.
This PR lets us warn on that by annotating the passes themselves. Then we
use those annotation to either not run a pass at all (matching the previous
behavior) or to show a warning when necessary.
Fixes emscripten-core/emscripten#13288 . That is, concretely
after this PR running asyncify + DWARF will show a warning to the user.
|
|
|
|
|
|
|
|
| |
We now have multiple catches in each try, and a possible catch-all.
This changes our "extra delimiter" storage to store either an "else"
(unchanged from before) or an arbitrary list of things - we use that
for catches.
|
|
|
|
|
|
|
|
|
|
| |
The binary spec
(https://docs.google.com/document/d/1yAWU3dbs8kUa_wcnnirDxUu9nEBsNfq0Xo90OWx6yuo/edit#)
lists `dataref` after `i31ref`, and `dataref` also comes after `i31ref`
in its binary code in the value-increasing order. This reorders these
two in wasm-type.h and other places, although in most of those places
the order is irrelevant.
This also adds C and JS API for `dataref`.
|
|
|
|
|
| |
Some fields were removed, see
https://docs.google.com/document/d/1yAWU3dbs8kUa_wcnnirDxUu9nEBsNfq0Xo90OWx6yuo/edit#
|
|
|
| |
This removes `exnref` type and `br_on_exn` instruction.
|
|
|
|
|
| |
This is not 100% of everything, but is enough to get tests passing, which
includes full binary and text format support, getting all switches to compile
without error, and some additions to InstrumentLocals.
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
This updates the interpreter for the EH instructions (modulo `delegate`)
to match the new spec. Before we had an `exnref` type so threw a
`Literal` of `exnref` type which contained `ExceptionPackage`. But now
that we don't have `exnref` anymore, so we add the contents of
`ExceptionPackage` to `WasmException`, which is used only for the
`ExpressionRunner` class hierarchy. `exnref` and `ExceptionPackage` will
be removed in a followup CL.
This allows nonzero depths for `rethrow` for now for testing; we
disallowed that for safety measure, but given that there are no passes
that modifies that field, I think the risk is low.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
This updates CFG traversal to match the new spec. Previously there was
only a single `catch` block that caught all exceptions, so all throwing
instructions needed to have a link to its innermost catch BB. But now we
can have multiple catches per try, requiring all throwing instrutions to
have an edge to all of those innermost catch BBs. Furthermore, if there
are only `catch`es and not a `catch_all` in a try, throwing instructions
can further unwind to outer catches until they find a `catch_all`.
`unwindCatchStack` and `unwindExprStack` are necessary to track and make
correct links between throwing instructions and their unwind destination
BBs.
`processCatchStack` is used to remember the catch BBs currently being
processed, so that after processing all of them, we can make a link from
each of those catch's last block to the continuation block after the
try-catch.
RSE test cases are updated because they use the CFG traversal. The tests
there mainly test that if all possible CFG edge to a `local.set` sets
the same value to a local, the `local.set` is redundant and thus can be
removed.
|
|
|
|
|
| |
This uses existing `getAllNested` function in `ExpressionWrapper`
functions. Also adds `setAllNested` which works in the other direction
and uses it within `ExpressionWrapper` functions.
|
|
|
|
| |
As proposed in https://github.com/WebAssembly/simd/pull/383, with opcodes
coordinated with the WIP V8 prototype.
|