| Commit message (Collapse) | Author | Age | Files | Lines |
... | |
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
- atomic.notify -> memory.atomic.notify
- i32.atomic.wait -> memory.atomic.wait32
- i64.atomic.wait -> memory.atomic.wait64
See WebAssembly/threads#149.
This renames instruction name printing but not the internal data
structure names, such as `AtomicNotify`, which are not always the same
as printed instruction names anyway. This also does not modify C API.
But this fixes interface functions in binaryen.js because it seems
binaryen.js's interface functions all follow the corresponding
instruction names.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
We used to check if a load's sign matters before hashing it. If the load does
not extend, then the sign doesn't matter, and we ignored the value there. It
turns out that value could be garbage, as we didn't assign it in the binary
reader, if it wasn't relevant. In the rewrite this was missed, and actually it's
not really possible to do, since we have just a macro for the field, but not the
object it is on - which there may be more than one.
To fix this, just always assign the field. This is simpler anyhow, and avoids
confusion not just here but probably when debugging.
The testcase here is reduced from the fuzzer, and is not a 100% guarantee
to catch a read of uninitialized memory, but it can't hurt, and with ASan it
may be pretty consistent.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Adds the capability to programatically split a module into a primary and
secondary module such that the primary module can be compiled and run before the
secondary module has been instantiated. All calls to secondary functions (i.e.
functions that have been split out into the secondary module) in the primary
module are rewritten to be indirect calls through the table. Initially, the
table slots of all secondary functions contain references to imported
placeholder functions. When the secondary module is instantiated, it will
automatically patch the table to insert references to the original functions.
The process of module splitting involves these steps:
1. Create the new secondary module.
2. Export globals, events, tables, and memories from the primary module and
import them in the secondary module.
3. Move the deferred functions from the primary to the secondary module.
4. For any secondary function exported from the primary module, export in
its place a trampoline function that makes an indirect call to its
placeholder function (and eventually to the original secondary function),
allocating a new table slot for the placeholder if necessary.
5. Rewrite direct calls from primary functions to secondary functions to be
indirect calls to their placeholder functions (and eventually to their
original secondary functions), allocating new table slots for the
placeholders if necessary.
6. For each primary function directly called from a secondary function, export
the primary function if it is not already exported and import it into the
secondary module.
7. Replace all references to secondary functions in the primary module's table
segments with references to imported placeholder functions.
8. Create new active table segments in the secondary module that will replace
all the placeholder function references in the table with references to
their corresponding secondary functions upon instantiation.
Functions can be used or referenced three ways in a WebAssembly module: they can
be exported, called, or placed in a table. The above procedure introduces a
layer of indirection to each of those mechanisms that removes all references to
secondary functions from the primary module but restores the original program's
semantics once the secondary module is instantiated. As more mechanisms that
reference functions are added in the future, such as ref.func instructions, they
will have to be modified to use a similar layer of indirection.
The code as currently written makes a few assumptions about the module that is
being split:
1. It assumes that mutable-globals is allowed. This could be worked around by
introducing wrapper functions for globals and rewriting secondary code that
accesses them, but now that mutable-globals is shipped on all browsers,
hopefully that extra complexity won't be necessary.
2. It assumes that all table segment offsets are constants. This simplifies the
generation of segments to actively patch in the secondary functions without
overwriting any other table slots. This assumption could be relaxed by 1)
having secondary segments re-write primary function slots as well, 2)
allowing addition in segment offsets, or 3) synthesizing a start function to
modify the table instead of using segments.
3. It assumes that each function appears in the table at most once. This isn't
necessarily true in general or even for LLVM output after function
deduplication. Relaxing this assumption would just require slightly more
complex code, so it is a good candidate for a follow up PR.
Future Binaryen work for this feature includes providing a command line tool
exposing this functionality as well as C API, JS API, and fuzzer support. We
will also want to provide a simple instrumentation pass for finding dead or
late-executing functions that would be good candidates for splitting out. It
would also be good to integrate that instrumentation with future function
outlining work so that dead or exceptional basic blocks could be split out into
a separate module.
|
|
|
|
|
|
|
|
|
|
|
|
| |
OptimizeInstructions is seeing the most work these days, so it's good for
the fuzzer to focus on that some more.
Also move some code around in the main test wast: it's useful to put each
feature in its own module to maximize the chance of getting them to be used.
That is, if a module has a single use of atomics, then if atomics are disabled
in the current run, we can't use any of the module and we skip initial contents
entirely. Moving each feature to it's own module reduces that risk. (We do
pick randomly between the modules, and atm a small module has the same
chance as a big one, but this still seems worth it.)
|
|
|
|
| |
See discussion in #3303
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
X - Y <= 0
=>
X <= Y
That is true mathematically, but not in the case of an overflow, e.g.
X=10, Y=0x8000000000000000. X - Y is a negative number, so
X - Y <= 0 is true. But it is not true that X <= Y (as Y is negative, but
X is not).
See discussion in #3303 (comment)
The actual regression was in #3275, but the fuzzer had an easier time
finding it due to #3303
|
|
|
|
|
|
| |
We mistakenly tried to run all passes there, but should run only
the function ones.
Fixes #3333
|
|
|
|
|
|
|
|
|
| |
This is because we maybe need to reference the segments
during the start function. For example in the case of
pthreads we conditionally load passive segments during
start.
Tested in emscripten with: tests/runner.py wasm2js1
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Expands on #3294:
* Scope names must be distinguished as either defs or uses.
* Error when a core #define is missing, which is less error-prone, as
suggested by @tlively
* Add DELEGATE_GET_FIELD which lets one define "get the field"
once and then all the loops can use it. This helps avoid boilerplate for
loops at least in some cases (when there is a single object on which
to get the field).
With those, it is possible to replace boilerplate in comparisons and
hashing logic. This also fixes a bug where BrOnExn::sent was not
scanned there.
Add some unit tests for hashing. We didn't have any, and hashing can be
subtly wrong without observable external effects (just more collisions).
|
|
|
|
|
| |
The asmFunc now sets the outer scope's `bufferView` variable
as well as its own internal views.
|
|
|
|
|
|
| |
bool(i32(x) % C_pot) -> bool(i32(x) & (C_pot - 1))
bool(i32(x) % min_s) -> bool(i32(x) & max_s)
For all other situations we already do this for (i32|i64).rem_s
|
| |
|
|
|
|
|
|
|
| |
Using addition in more places is better for gzip, and helps simplify the
optimizer as well.
Add a FinalOptimizer phase to do optimizations like our signed LEB tweaks, to
reduce binary size in the rare case when we do want a subtraction.
|
|
|
| |
Specifically try to cleanup use of asm_v_wasm.h and asmjs constants.
|
|
|
| |
We no longer build modules that import `global.Math`.
|
| |
|
| |
|
|
|
|
|
|
|
| |
Division and remainder do not have an implicit trap if the
right-hand side is a constant and not one of the dangerous
values there.
Also refactor ignoreImplicitTrap handling for clarity.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
We can still make x * -1.0 cheaper for non-fastMath mode as:
x * -1.0 -> -0.0 - x
Should at least help baseline compilers.
Also it could enable further optimizations, e.g.:
a + b * -1
a + (-0.0 - b)
(a - 0.0) - b
a - b
|
|
|
| |
We can only pack memory if we know it is zero-filled before us.
|
|
|
|
|
| |
Selectify turns an if-else into a select where possible. Previously we abandoned
hope if any part of the if had a side effect. But it's fine for the condition to have a
side effect, so long as moving it to the end doesn't invalidate the arms.
|
|
|
|
|
|
|
| |
Make select cost more realistic - it should be as good as a jmp, as in an if.
Add missing child visiting.
Shorten repetitive cases in switches.
|
| |
|
|
|
|
|
|
|
| |
Specifically, pick a simple positive canonical NaN as the NaN output, when the output
is a NaN. This is the same as what tools like wabt do.
This fixes a testcase found by the fuzzer on #3289 but it was not that PR's fault.
|
|
|
| |
Fixed bug in memory64-lowering pass for memory.size/grow
|
|
|
|
|
| |
`C1 - (x + C2)` -> `(C1 - C2) - x`
`C1 - (x - C2)` -> `(C1 + C2) - x`
`C1 - (C2 - x)` -> `x + (C1 - C2)`
|
|
|
|
| |
Without this, we might think a function has no global uses if the only
global use of it is the start.
|
|
|
|
|
|
| |
Emscripten no longer needs this information as of
https://github.com/emscripten-core/emscripten/pull/12643.
This also removes the need to export __data_end.
|
| |
|
|
|
| |
Followup to #3276
|
| |
|
|
|
|
|
|
|
|
| |
Fixes a fuzz bug that was triggered by
https://github.com/WebAssembly/binaryen/pull/3015#issuecomment-718001620
but was actually a pre-existing bug in pow2, that that PR just happened
to uncover.
|
|
|
|
|
|
|
| |
Including saturating, rounding Q15 multiplication as proposed in
https://github.com/WebAssembly/simd/pull/365 and extending multiplications as
proposed in https://github.com/WebAssembly/simd/pull/376. Since these are just
prototypes, skips adding them to the C or JS APIs and the fuzzer, as well as
implementing them in the interpreter.
|
| |
|
|
|
| |
But only when doing so doesn't require adding a new local.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Previously when we processed a block for example, we'd do this:
;; start is here
(block (result type)
;; end is here
.. contents ..
)
;; end delimiter is here
Not how this represents the block's start and end as the "header", and
uses an extra delimiter to mark the end.
I think this is wrong, and was an attempt to handle some offsets from
LLVM that otherwise made no sense, ones at the end of the "header".
But it turns out that this makes us completely incorrect on some things
where there is a low/high pc pair, and we need to understand that the
end of a block is at the end opcode at the very end, and not the end of
the header. This PR changes us to do that, i.e.
;; start is here
(block (result type)
.. contents ..
)
;; end is here
This fixes a testcase already in the test suite,
test/passes/fib_nonzero-low-pc_dwarf.bin.txt
where you can see that lexical block now has a valid value for the end, and
not a 0 (the proper scope extends all the way to the end of the big block in
that function, and is now the same in the DWARF before and after we
process it). test/passes/fannkuch3_dwarf.bin.txt is also improved by
this.
To implement this, this removes the BinaryLocations::End delimeter. After
this we just need one type of delimiter actually, but I didn't refactor that any
more to keep this PR small (see TODO).
This removes an assertion in writeDebugLocationEnd() that is no longer
valid: the assert ensures that we wrote an end only if there was a 0 for
the end, but for a control flow structure, we write the end of the "header"
automatically like for any expression, and then overwrite it later when we
finish writing the children and the end marker. We could in theory special-case
control flow structures to avoid the first write, but it would add more complexity.
This uncovered what appears to be a possible bug in our debug_line
handling, see test/passes/fannkuch3_manyopts_dwarf.bin.txt. That needs
to be looked into more, but I suspect that was invalid info from when we
looked at the end of the "header" of control flow structures. Note that there
was one definite bug uncovered here, fixed by the extra
} else if (locationUpdater.hasOldExprEnd(oldAddr)) {
that is added here, which was definitely a bug.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Previously the fuzzer constructed a new random valid wasm file from
scratch. The new --initial-fuzz=FILENAME option makes it start from
an existing wasm file, and then add random contents on top of that. It
also randomly modifies the existing contents, for example tweaking
a Const, replacing some nodes with other things of the same type, etc.
It also has a chance to replace a drop with a logging (as some of our
tests just drop a result, and we match the optimized output's wasm
instead of the result; by logging, the fuzzer can check things).
The goal is to find bugs by using existing hand-written testcases as
a basis. This PR uses the test suite's testcases as initial fuzz contents.
This can find issues as they often check for corner cases - they are
designed to be "interesting", which random data may be less likely
to find.
This has found several bugs already, see recent fuzz fixes. I mentioned
the first few on Twitter but past 4 I stopped counting...
https://twitter.com/kripken/status/1314323318036602880
This required various changes to the fuzzer's generation to account
for the fact that there can be existing functions and so forth before
it starts to run, so it needs to avoid collisions and so forth.
|
|
|
|
|
|
| |
As proposed in https://github.com/WebAssembly/simd/pull/379. Since this
instruction is still being evaluated for inclusion in the SIMD proposal, this PR
does not add support for it to the C/JS APIs or to the fuzzer. This PR also
performs a drive-by fix for unrelated instructions in c-api-kitchen-sink.c
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
The DCE pass is one of the oldest in binaryen, and had quite a lot of
cruft from the changes in unreachability and other stuff in wasm and
binaryen's history. This PR rewrites it from scratch, making it about
1/3 the size.
I noticed this when looking for places to use code autogeneration.
The old version had annoying boilerplate, while the new one avoids
any need for it.
There may be noticeable differences, as the old pass did more than
it needed to. It overlapped with remove-unused-names for some
reason I don't remember. The new pass leaves that to the other
pass to do. I added another run of remove-unused-names to avoid
noticeable differences in optimized builds, but you can see
differences in the testcases that only run DCE by itself. (The test
differences in this PR are mostly whitespace.)
(The overlap is that if a block ended up not needed, that is, all
branches to it were removed, the old DCE would remove the block.)
This pass is about 15% faster than the old version. However, when
adding another run of remove-unused-names the difference
basically vanishes, so this isn't a speedup.
|
| |
|
| |
|
| |
|
|
|
|
|
| |
Extend ZeroRemover and optimizeAddedConstants to handle 64-bit integers as well.
Use Literal.makeFromInt64 to make this easier.
|
|
|
|
|
|
|
| |
These two tests had pops in invalid locations; pops are valid only after
`catch`. This fixes those invalid wasm files.
This removes pops from Os_print-stack-ir_all-features.wast too.
Fixes #3213 and #3283.
|
|
|
|
|
|
|
| |
These instructions are proposed in https://github.com/WebAssembly/simd/pull/350.
This PR implements them throughout Binaryen except in the C/JS APIs and in the
fuzzer, where it leaves TODOs instead. Right now these instructions are just
being implemented for prototyping so adding them to the APIs isn't critical and
they aren't generally available to be fuzzed in Wasm engines.
|
| |
|
|
|
|
|
|
|
|
| |
We checked if the type matches when deciding if two locals are equivalent,
but if the type didn't match, we forgot to reset any previously equivalent
things. So we thought something was equivalent when it wasn't, see the
reduced testcase.
Fixes #3266
|
|
|
|
| |
Move the tweak function to an outer location, and call it from mutate() with
some probability.
|
|
|
|
|
|
|
|
|
| |
And associated stack.h. The current stack.h clearly doesn't work with
the llvm back as it assumes the stack grows up, which means non of these
has been working or used in a long time.
Rather than trying to fix this unused features its probably cleaner to
just remove it for now and restore it rom git history if its someone
that anyone actually wants to use in the future.
|