| Commit message (Collapse) | Author | Age | Files | Lines |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
E.g.
(i32.add
(select
(i32.const 100)
(i32.const 200)
(..condition..)
)
(i32.const 50)
)
;; =>
(select
(i32.const 150)
(i32.const 250)
(..condition..)
)
We cannot fully precompute the select, but we can "partially precompute" it, by precomputing
its arms using the parent.
This may require looking several steps up the parent chain, which is an awkward operation in
our simple walkers, so to do it we capture stacks of parents and operate directly on them. This
is a little slower than a normal walk, so only do it when we see a promising select, and only in
-O2 and above (this makes the pass 7% or so slower; not a large cost, but best to avoid it in
-O1).
|
|
|
| |
Parse types like `exnref` and `nofunc` that we did not previously support.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
We tested --generate-global-effects --vacuum and such, but not
--generate-global-effects -O3 or the other -O flags. Unfortunately, our
targeted testing missed a bug because of that. Specifically, we have special
logic for -O flags to make sure the passes they expand into run with the
proper opt and shrink levels, but that logic happened to also interfere with
global effect computation. It would also interfere with allowing GUFA info
or other things to be stored on the side, which we've proposed. This PR
fixes that + future issues.
The fix is to just allow a pass runner to execute more than once. We thought
to avoid that and assert against it to keep the model "hermetic" (you create
a pass runner, you run the passes, and you throw it out), which feels nice in
a way, but it led to the bug here, and I'm not sure it would prevent any other
ones really. It is also more code. It is simpler to allow a runner to execute more
than once, and add a method to clear it. With that, the logic for -O3 execution
is both simpler and does not interfere with anything but the opt and shrink
level flags: we create a single runner, give it the proper options, and then keep
using that runner + those options as we go, normally.
|
|
|
| |
I think this is a nicer/better way to do #6204.
|
|
|
|
|
|
|
| |
Since branches to loops go to the beginnings of the loops, they should send
values matching the input types for the loops (which are always none because we
don't support loop input types). IRBuilder was previously using the output types
of loops to determine what values the branches should carry, which was
incorrect. Fix it.
|
|
|
|
|
|
| |
The intrinsics file changed in #6201 and somehow CMake doesn't automatically
update itself, and needs a manual step for people with existing checkouts (a new
fresh checkout always works). To avoid annoyance for existing checkouts, rename
the vars, which forces CMake to recompute the contents.
|
| |
|
|
|
|
| |
The new text parser and IRBuilder were previously not differentiating between
`br` and `br_if`. Handle `br_if` correctly by popping and assigning a condition.
|
|
|
|
|
|
|
|
|
|
|
|
| |
We previously supported (and primarily used) a non-standard text format for
conditionals in which the condition, if-true expression, and if-false expression
were all simply s-expression children of the `if` expression. The standard text
format, however, requires the use of `then` and `else` forms to introduce the
if-true and if-false arms of the conditional. Update the legacy text parser to
require the standard format and update all tests to match. Update the printer to
print the standard format as well.
The .wast and .wat test inputs were mechanically updated with this script:
https://gist.github.com/tlively/85ae7f01f92f772241ec994c840ccbb1
|
|
|
|
|
| |
Update the legacy text parser and all tests to use the standard text format for shared memories, e.g. `(memory $m 1 1 shared)` rather than `(memory $m (shared 1 1))`. Also remove support for non-standard in-line "data" or "segment" declarations.
This change makes the tests more compatible with the new text parser, which only supports the standard format.
|
|
|
|
| |
The planned spec change to use "sub open" never came together, so the standard
format remains "sub final".
|
|
|
|
| |
And validate in IRBuilder both that the input annotation is valid and that the
input matches it.
|
|
|
|
|
|
| |
These type annotations were removed during the development of the GC proposal,
but we maintained support for parsing them to ease the transition. Now that GC
is shipped, remove support for the non-standard annotation and update our tests
accordingly.
|
|
|
|
|
|
|
|
|
|
|
|
| |
To parse folded instructions in the right order, we need to defer parsing each
instruction until we have parsed each of its children and found its closing
parenthesis. Previously we naively looked for parentheses to determine where
instructions began and ended before we parsed them, but that scheme did not
correctly handle instructions that can contain parentheses in their immediates,
such as call_indirect.
Fix the problem by using the actual instruction parser functions with a
placeholder context to find the end of the instructions, including any kind of
immediates they might have.
|
|
|
|
|
| |
- Deletes a stray whitespace after `throw_ref`
- Adds missing `makeThrowRef` to `wasm-builder.h`
- Adds a case for `TryTable` in `ControlFlowWalker`
|
|
|
|
|
|
|
|
|
| |
Avoid replacing with the exact same thing in the case of RefNull and a default
tuple.
Also be more careful with handling of numbers. Before we exited immediately
if we saw a number, but we can try to replace a number with a 0 or a 1, even
if it was a number before. That is, we consider 1 simpler than e.g. 12345678, and
0 simpler than 1.
|
|
|
|
| |
We previously support the in-line import abbreviation, but now add support for
explicit, non-abbreviated imports as well.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
As suggested in
https://github.com/WebAssembly/binaryen/pull/6181#discussion_r1427188670,
using `std::optional<Type>`, this unifies two different versions of
`make***`, for block-like structures (`block`, `if`, `loop`, `try`, and
`try_table`) with and without a type parameter.
This also allows unifying of `finalize` methods, with and without a
type. This also sets `breakability` argument of `Block::finalize` to
`Unknown` so we can only have one `Block::finalize` that handles all
cases.
This also adds an optional `std::optional<Type> type` parameter to
`blockifyWithName`, and `makeSequence` functions in `wasm-builder.h`.
blockify was not included because it has a variadic parameter.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
We previously supported a non-standard `(func "name" ...` syntax for declaring
functions exported with the quoted name. Since that is not part of the standard
text format, drop support for it, replacing it with the standard `(func $name
(export "name") ...` syntax instead.
Also replace our other usage of the quoted form in our text output, which was
where we quoted names containing characters that are not allowed to appear in
standard names. To handle that case, adjust our output from `"$name"` to
`$"name"`, which is the standards-track way of supporting such names. Also fix
how we detect non-standard name characters to match the spec.
Update the lit test output generation script to account for these changes,
including by making the `$` prefix on names mandatory. This causes the script to
stop interpreting declarative element segments with the `(elem declare ...`
syntax as being named "declare", so prevent our generated output from regressing
by counting "declare" as a name in the script.
|
| |
|
|
|
|
|
|
|
|
|
|
| |
This adds validation for the new EH instructions (`try_table` and
`throw_ref`):
https://github.com/WebAssembly/exception-handling/blob/main/proposals/exception-handling/Exceptions.md
This also adds a spec test for checking invalid modules. We cannot check
the executions yet because we don't have the interpreter implementation.
The new test file also contains tests for the existing `throw`, because
this is meant to replace the old spec test someday.
|
|
|
|
|
| |
Without this fuzzer testcases fail if the initial content has a tuple.drop but multivalue
is disabled (then the initial content validates erroneously, and that content is remixed
into more content using multivalue which fails to validate).
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
This adds basic support for the new instructions in the new EH proposal
passed at the Oct CG hybrid CG meeting:
https://github.com/WebAssembly/meetings/blob/main/main/2023/CG-10.md
https://github.com/WebAssembly/exception-handling/blob/main/proposals/exception-handling/Exceptions.md
This mainly adds two instructions: `try_table` and `throw_ref`. This is
the bare minimum required to read and write text and binary format, and
does not include analyses or optimizations. (It includes some analysis
required for validation of existing instructions.) Validation for
the new instructions is not yet included.
`try_table` faces the same problem with the `resume` instruction in
#6083 that without the module-level tag info, we are unable to know the
'sent types' of `try_table`. This solves it with a similar approach
taken in #6083: this adds `Module*` parameter to `finalize` methods,
which defaults to `nullptr` when not given. The `Module*` parameter is
given when called from the binary and text parser, and we cache those
tag types in `sentTypes` array within `TryTable` class. In later
optimization passes, as long as they don't touch tags, it is fine to
call `finalize` without the `Module*`. Refer to
https://github.com/WebAssembly/binaryen/pull/6083#issuecomment-1854634679
and #6096 for related discussions when `resume` was added.
|
|
|
|
|
|
|
| |
`_VECTOR` or `_ARRAY` defines in `wasm-delegations-fields.def` are
supposed to be defined in terms of their non-vector/array counterparts
when undefined. This removes empty `_VECTOR`/`_ARRAY` defines when
including `wasm-delegations-fields.def`, while adding definitions for
`DELEGATE_GET_FIELD` in case it is missing.
|
| |
|
|
|
|
|
| |
Parse `tuple.make`, `tuple.extract`, and `tuple.drop`. Also slightly improve the
way we break up tuples into individual elements in IRBuilder by using a
`local.tee` instead of a block containing a `local.set` and `local.get`.
|
|
|
|
|
|
|
|
|
| |
In Binaryen IR, we allow single `Drop` expressions to drop multiple values
packaged up as a tuple. When using IRBuilder to rebuild IR containing such a
drop, it previously treated the drop as a normal WebAssembly drop that dropped
only a single value, producing invalid IR that had extra, undropped values. Fix
the problem by preserving the arity of `Drop` inputs in IRBuilder. To avoid
bloating the IR, thread the size of the desired value through IRBuilder's pop
implementation so that tuple values do not need to be split up and recombined.
|
|
|
|
| |
Existing convention uses _@once@_ but we also use @ for class separation.
It is cleaner&more future proof to use something other convention like _<once>_.
|
|
|
|
|
|
|
| |
Parse `array.new_elem`, `array.init_data`, and `array.init_elem`.
Accidentally also includes:
* [Parser] Parse string types and operations (#6161)
|
|
|
|
| |
Like `delegate`, rethrow takes a `Try` label. Refactor the delegate handling so
that `Try` can share its logic.
|
|
|
|
|
|
|
|
| |
Once support for tuple.extract lands in the new WAT parser, this arity immediate
will let the parser determine how many values it should pop off the stack to
serve as the tuple operand to `tuple.extract`. This will usually coincide with
the arity of a tuple-producing instruction on top of the stack, but in the
spirit of treating the input as a proper stack machine, it will not have to and
the parser will still work correctly.
|
|
|
|
| |
Including table.get, table.set, table.size, table.grow, table.fill, and
table.copy.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
The patch puts a new guardrail that will only hoist the field
if it is initialized with the owner class.
The constant hoisting optimization in J2CL pass relies on the
assumption that clinit that will initialize the field will be
executed before the read of the field. That means the field
that is optimized is within the same class:
class Foo {
public static final Object field = new Object();
}
Although it is possible to observe the initial value, that is
not intention of the developer (which the point of the
optimization).
However can also see a similar pattern in following:
class Foo {
public static Object field;
}
class Zoo {
static {
Foo.field = new Object();
}
}
Currently the pass also optimizes it as well since the field
is only initialized once and by a clinit. However Zoo clinit
is not guaranteed to be run before Foo.field access so it is
less safe to speculate on the intention of the developer here
hence it is not worth the risk.
FWIW, we haven't seen this issue. But this is something we
are also guarding in Closure Compiler so I decided it is
worthwhile to do here as well.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
We previously overloaded `drop` to mean both normal drops of single values and
also drops of tuple values. That works fine in the legacy text parser since it
can infer parent-child relationships directly from the s-expression structure of
the input, so it knows that a drop should drop an entire tuple if the
tuple-producing instruction is a child of the drop. The new text parser,
however, is much more like the binary parser in that it uses instruction types
to create parent-child instructions. The new parser always assumes that `drop`
is meant to drop just a single value because that's what it does in WebAssembly.
Since we want to continue to let `Drop` IR expressions consume tuples, and since
we will need a way to write tests for that IR pattern that work with the new
parser, introduce a new pseudoinstruction, `tuple.drop`, to represent drops of
tuples. This pseudoinstruction only exists in the text format and it parses to
normal `Drop` expressions. `tuple.drop` takes the arity of its operand as an
immediate, which will let the new parser parse it correctly in the future.
|
|
|
|
|
|
|
|
|
|
| |
Previously, the number of tuple elements was inferred from the number of
s-expression children of the `tuple.make` expression, but that scheme would not
work in the new wat parser, where s-expressions are optional and cannot be
semantically meaningful.
Update the text format to take the number of tuple elements (i.e. the tuple
arity) as an immediate. This new format will be able to be implemented in the
new parser as follow-on work.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
This PR creates a new pass to optimize J2CL specific patterns
that would otherwise difficult to recognize/prove generically
by other binaryen passes.
The pass currently handles fields what we call as "constant-like".
These fields are fields initialized once and unconditionally through
"clinit" function and technically they do have 2 observable states;
- initial null/0 state
- initialized state.
However you can only observe initial null/0 state in contrived examples,
not in real world/correct applications.
This pass moves such "clinit" initialized fields to global initialization.
Above pattern also matches other lazy init construct like String and Class
literals (which binaryen already reduces to constant expressions). So
the pass is generalized to include them as well. (by matching any functions
with the name pattern "_@once_")
In order for this pass to be effective:
1. It needs to run between O3 passes
2. We need to stop inlining of "once" functions.
Stopping inlining of the once functions are important to preserve their
structure. This both helps existing OnceReducer pass and new J2CL pass to
be a lot more effective. Also it is not useful to inline these functions
as by defintion they only executed once. This could be achieved by passing
no-inline filter.
Although the inlining is generally disabled for these functions, it is
still needed for some cases since inliner is effectively responsible for
removal of the once functions that are simplified into empty or simple
delegating functions. For this reason, the pass will rename such trivial
function so no-inline filter will no longer match them.
Also note that after all optimizations completed, it does make sense to
have a final stage where the "partial inline" of all once functions are
allowed. This will speed them up by moving the initialization check to
call-site.
|
|
|
|
| |
Those fields should be copied together with all the rest of the metadata that
already is. This was just missed in the prior PR.
|
|
|
|
|
| |
Currently the legacy GC encoding's nullexternref encoding overlaps with
exnref's. We assume the legacy GC encoding won't be used with the exnref
for the moment and assign a random value to it to prevent the clash.
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
At the Oct hybrid CG meeting, we decided to add back `exnref`, which was
removed in 2020:
https://github.com/WebAssembly/meetings/blob/main/main/2023/CG-10.md
The new version of the proposal reflected in the explainer:
https://github.com/WebAssembly/exception-handling/blob/main/proposals/exception-handling/Exceptions.md
While adding support for `exnref` in the current codebase which has all
GC subtype hierarchies, I noticed we might need `noexn` heap type for
the bottom type of `exn`. We don't have it now so I just set it to 0xff
for the moment.
|
| |
|
|
|
|
|
|
|
|
|
|
| |
Adds support for the loop instruction to be outlined and a test showing a repeat loop being outlined.
Reviewers: tlively
Reviewed By: tlively
Pull Request: https://github.com/WebAssembly/binaryen/pull/6141
|
|
|
|
|
|
|
|
|
|
|
|
| |
- Change outlining debug logs to use std::cerr
- Add controlFlowQueue push log
- Fix build error with wasm-ir-builder log's use of ShallowExpression
Reviewers: tlively
Reviewed By: tlively
Pull Request: https://github.com/WebAssembly/binaryen/pull/6140
|
|
|
|
|
|
|
|
|
|
| |
Changes the controlFlowQueue used in stringify-walker to push values of Expression*, This ensures that we walk the Wasm module in the same order, regardless of whether the control flow expression is outlined.
Reviewers: tlively
Reviewed By: tlively
Pull Request: https://github.com/WebAssembly/binaryen/pull/6139
|
| |
|
|
|
|
|
|
|
| |
These module fields are especially complex to parse because they contain both
nontrivial types and instructions, so their parsing logic needs to be spread out
across the ParseDecls, ParseModuleTypes, and ParseDefs phases of parsing. This
applies to in-line elements in table definitions as well, which means we need to
be able to match a table to its in-line element segment across multiple phases.
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Any function can now be annotated as not to be inlined fully (normally) or not to be
inlined partially. In the future we'll want to read those annotations from the proposed
wasm metadata section on code hints, and from wat text as well, but for now add
trivial passes that set those fields based on function name wildcards, e.g.:
--no-inline=*leave-alone* --inlining
That will not inline any function whose name contains "leave-alone" in the name.
--no-inline disables all inlining (full or partial) while --no-full-inline and
--no-partial-inline affect only full or partial inlining.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
A trivial call is something like a function that just calls another immediately,
function foo(x, y) {
return bar(y, 15);
}
We can inline those and expect to benefit in most cases, though we might
increase code size slightly. Hence it makes sense to inline such cases, even
though in general we are careful and do not inline functions with calls in
them; a "trampoline" like that likely has most of the work in the call itself,
which we can avoid by inlining.
Suggested based on findings in Java.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Remove hardcoded paths for globals/functions/etc. in favor of general code
paths that support all the module elements uniformly. As a result of that, we
now support all parts of wasm, such as tables and element segments, that
we didn't before.
This refactoring is NFC aside from adding functionality. Note that this reduces
the size of wasm-metadce by 10% while increasing its functionality - the
benefits of writing generic code.
To support this, add some trivial generic helpers to get or iterate over module
elements using their kind in a dynamic manner. Using them might make
wasm-metadce slightly slower, but I can't measure any difference.
|
|
|
|
|
|
|
|
|
|
|
|
| |
Avoid adding suffixes when we don't need them to keep names unique.
As background, the suffixes are not used by emcc at all, so they are just
for internal use in the tool. How that works is that metadce gets as input
the list of things the user cares about, with names for them, so it knows
the proper names to give imports and exports, and makes up names for
other things. Those made up names will not be read by the user, so we
can make them prettier as this PR does without breaking anything.
The main benefit of this PR is to make debugging easier.
|