| Commit message (Collapse) | Author | Age | Files | Lines |
... | |
|
|
| |
As specified in https://github.com/WebAssembly/simd/pull/122.
|
|
|
|
|
|
| |
This API enables use cases where we want to keep the original expression, yet utilize passes like `vacuum` or `precompute` to evaluate it without implicitly modifying the original.
C-API: **BinaryenExpressionCopy**(expr, module)
JS-API: **Module#copyExpression**(expr)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
In WebAssembly/exception-handling#52, We decided to put `try` bodies in
a `do` clause to be more consistent with `catch`.
- Before
```wast
(try
...
(catch
...
)
)
```
- After
```wast
(try
(do
...
)
(catch
...
)
)
```
Another upside of this change is when there are multiple instructions
within a `try` body, we no longer need to wrap them in a `block`.
|
|
|
|
| |
This adds missing handlings for `throw` and `rethrow` in DCE. They
should set `reachable` variable to `false`, like other branches.
|
|
|
|
|
|
| |
This feature was very useful in the early days of the C API,
but has not shown usefuless for quite a while, and has a
significant maintenance burden, so it it's makes sense to
remove it now.
|
|
|
|
|
|
|
| |
Turned out that the behavior of MODULARIZE_INSTANCE, which has
been removed from Emscripten lately, cannot be easily reproduced
using MODULARIZE. So, instead of modularizing and attempting to
undo it, this just uses some good old wrapper code to achieve the same.
|
|
|
|
| |
This hopefully fixes a build problem on older GCC as reported in
#2827.
|
|
|
|
|
|
|
|
|
| |
This adds interpreter support for EH instructions. This adds
`ExceptionPackage` struct, which contains info of a thrown exception (an
event tag and thrown values), and the union in `Literal` can take a
`unique_ptr` to `ExceptionPackage`. We need a destructor, a copy
constructor, and an assignment operator for `Literal`, because the union
in `Literal` now has a member that cannot be trivially copied or
deleted.
|
|
|
|
|
|
|
| |
GCC complains that the enclosing class of the constexpr member
function is not a literal type. This change removes the constexpr
qualifier to fix the GCC build.
Fixes #2827.
|
|
|
| |
As described in https://github.com/WebAssembly/simd/pull/209.
|
|
|
|
|
|
|
| |
This allows emscripten to statically set the initial value of the
stack pointer.
Should allow use to avoid doing it dynamically at startup:
https://github.com/emscripten-core/emscripten/pull/11031
|
|
|
|
| |
This list is identical to the export list no there is no need to
output this twice.
|
|
|
|
|
|
| |
The refactoring of the loop in #2812 was wrong - we need to
loop over all the exports and ignore the non-function ones.
Rewrote it to stress that part.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Tackles the concerns raised in https://github.com/WebAssembly/binaryen/issues/2797 directly related to https://github.com/WebAssembly/binaryen/pull/2702 by reverting merging all of `PrecomputeExpressionRunner` into the base `ExpressionRunner`, instead adding a common base for both the precompute pass and the new C-API to inherit. No functional changes.
---
### Current hierarchy after https://github.com/WebAssembly/binaryen/pull/2702 is
```
ExpressionRunner
├ [PrecomputeExpressionRunner]
├ [CExpressionRunner]
├ ConstantExpressionRunner
└ RuntimeExpressionRunner
```
where `ExpressionRunner` contains functionality not utilized by `ConstantExpressionRunner` and `RuntimeExpressionRunner`.
### New hierarchy will be:
```
ExpressionRunner
├ ConstantExpressionRunner
│ ├ [PrecomputeExpressionRunner]
│ └ [CExpressionRunner]
├ InitializerExpressionRunner
└ RuntimeExpressionRunner
```
with the precompute pass's and the C-API's shared functionality now moved out of `ExpressionRunner` into a new `ConstantExpressionRunner`. Also renames the previous `ConstantExpressionRunner` to `InitializerExpressionRunner` to [better represent its uses](https://webassembly.org/docs/modules/#initializer-expression) and to make its previous name usable for the new intermediate template, where it fits perfectly. Also adds a few comments answering some of the questions that came up recently.
### Old hierarchy before https://github.com/WebAssembly/binaryen/pull/2702 for comparison:
```
ExpressionRunner
├ [PrecomputeExpressionRunner]
├ ConstantExpressionRunner
└ RuntimeExpressionRunner
```
|
|
|
|
|
|
| |
Avoid pass-debug when fuzzing emcc, as it can be slow and isn't
what we care about.
Clean up a loop.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
We had some ad-hoc tuning of which nodes to emit more
frequently in the fuzzer, but it wasn't very good. Things like
loads and stores for example were far too rare. Also it wasn't
easy to adjust the frequencies.
This adds a simple way to adjust them, by passing a size_t
which is the "weight" of that node. Then it just makes that
number of copies of it, making it more likely to be picked.
Example output comparison:
node before after
================================
binary 281 365
block 898 649
break 278 144
call 182 290
call_indirect 9 42
const 808 854
drop 43 92
global.get 440 398
global.set 223 171
if 335 254
load 22 84
local.get 429 301
local.set 434 211
loop 176 99
nop 117 54
return 264 197
select 8 33
store 1 39
unary 405 304
unreachable 1 2
Lots of noise here obviously, but there are large increases
for loads and stores compared to before.
Also add a testcase of random data of the typical size the
fuzzer runs, and print metrics on it. This might help us get
a feel for how future tuning changes affect frequencies.
|
|
|
| |
Since the --roundtrip pass is more general than --fuzz-binary anyways. Also reimplements `ModuleUtils::clearModule` to use the module destructor and placement new to ensure that no members are missed.
|
|
|
|
|
|
|
|
|
| |
This adds a variant on wasm2c that uses emcc instead of a
native compiler. This helps us fuzz emcc.
To make that practical, rewrite the setjmp glue to only use one
setjmp. The wasm backend ends up doing linear work per setjmp,
so it's quadratic with many setjmps. Instead, do a big switch-loop
construct around a single setjmp.
|
|
|
|
| |
type. fixes #2807 (#2808)
|
|
|
| |
As described in the spec.
|
|
|
|
|
|
|
| |
Fixes #2788 found by the fuzzer, introduced in #2702, which turned
out to be incorrect usage of std::move, by removing any std::moves
introduced in that PR to be better safe than sorry. Also fixes
problems with WASM_INTERPRETER_DEBUG spotted during
debugging.
|
| |
|
|
|
|
|
|
|
| |
Without this we emitted a binary, which confused the size comparisons.
(When reducing a smaller size is usually a good sign. And also it provides
a deterministic way to know when to stop - we can't infinite loop if we keep
going while the size shrinks.)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
This adds support for fuzzing with wabt's wasm2c that @binji wrote.
Basically we compile the wasm to C, then compile the C to a native
executable with a custom main() to wrap around it. The executable
should then print exactly the same as that wasm when run in either
the binaryen interpreter or in a JS VM with our wrapper JS for that
wasm. In other words, compiling the wasm to C is another way to
run that wasm.
The main reasons I want this are to fuzz wasm2c itself, and to
have another option for fuzzing emcc. For the latter, we do fuzz
wasm-opt quite a lot, but that doesn't fuzz the non-wasm-opt
parts of emcc. And using wasm2c for that is nice since the
starting point is always a wasm file, which means we
can use tools like wasm-reduce and so forth, which can be
integrated with this fuzzer.
This also:
Refactors the fuzzer harness a little to make it easier to
add more "VMs" to run wasms in.
Do not autoreduce when re-running a testcase, which I hit
while developing this.
|
| |
|
|
|
|
|
|
| |
Without this change only the import gets renamed not the internal
name. Since the internal name is the one that ends up in the name
section this means that rename wasn't effecting the name section.
|
|
|
|
|
|
|
| |
Refactors most of the precompute pass's expression runner into its
base class so it can also be used via the C and JS APIs. Also adds
the option to populate the runner with known constant local and global
values upfront, and remembers assigned intermediate values as well
as traversing into functions if requested.
|
|
|
|
|
|
|
|
|
| |
1. Only emit exnref as part of a subtype if exception-handling is
enabled in the fuzzer.
2. Correctly report that funcref and nullref require reference-types
to be enabled.
3. Re-enable multivalue as a normal feature in the fuzzer.
Possibly fixes #2770.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
This adds dummy interpreter support for EH instructions, mainly for
fuzzing. The plan is to make the interpreter support for EH instructions
correctly using Asyncify in the future. Also to support the correct
behavior we will need a `Literal` of `exnref` type too, which will be
added later too.
Currently what this dummy implementation does is:
- `try`-`catch`-`end`: only runs `try` body and ignores `catch` body
- `throw`: traps
- `retyrow`:
- Traps on nullref argument (correct behavior based on the spec)
- Traps otherwise too (dummy implementation for now)
- `br_on_exn`:
- Traps on nullref (correct behavior)
- Otherwise we assume the current expression matches the current event
and extracts a 0 literal based on the current type.
This also adds some interpreter tests, which tests the basic dummy
behaviors for now. (Deleted tests are the ones that weren't tested
before.)
|
|
|
| |
This was previously an unwritten and unchecked assumption.
|
|
|
|
|
|
|
|
|
| |
We should only do weird changes to the fuzz code if we
allow out of bounds operations, because the OOB checks
are generated as we build the IR, and changing them can
remove the checks.
(we fuzz 50% of the time with and 50% without OOBs,
so this doesn't really hurt us)
|
|
|
|
|
|
|
|
| |
Emit tuple.make, tuple.extract, and multivalue control flow, and tuple locals
and globals when multivalue is enabled. Also slightly refactors the top-level
`makeConcrete` function to be more selective about what it tries to
make based on the requested type to reduce the number of trivial nodes
created because the requested type is incompatible with the requested
node.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
The main benefit here is comparing VMs, instead of just comparing
each VM to itself after opts. Comparing VMs is a little tricky since there
is room for nondeterminism with how results are printed and other
annoying things, which is why that didn't work well earlier.
With this PR I can run 10's of thousands of iterations without finding
any issues between v8 and the binaryen interpreter. That's after
fixing the various issues over the last few days as found by this:
#2760 #2757 #2750 #2752
Aside from that main benefit I ended up adding more improvements
to make it practical to do all that testing:
Randomize global fuzz settings like whether we allow NaNs and
out-of-bounds memory accesses. (This was necessary here since
we have to disable cross-VM comparisons if NaNs are enabled.)
Better logging of statistics like how many times each handler
was run.
Remove redundant FuzzExecImmediately handler (looks like
after past refactorings it was no longer adding any value).
Deterministic testcase handling: if you run e.g. fuzz_opt.py 42 it
will run one testcase and exactly the same one. If you run without
an argument it will run forever until it fails, and if it fails, it prints out
that ID so that you can easily reproduce it (I guess, on the same
binaryen + same python, not sure how python's deterministic
RNG changes between versions and builds).
Upgrade to Python 3.
|
|
|
|
|
|
|
|
|
|
| |
Previously we tried to reuse `Const` node if a precomputed value is a
constant node. But now we have two more kinds of constant node
(`RefNull` and `RefFunc`), so we shouldn't reuse them interchangeably,
meaning we shouldn't try to reuse a `Const` node when the value at hand
is a `RefNull`. This correctly checks the type of node and tries to
reuse only if the types of nodes match.
Fixes #2759.
|
|
|
|
|
|
| |
When it is certain that the try body does not throw, we can replace the
try-catch with the try body. But in this case we have to notify the type
updater that the catch body is removed, so that all parents' type should
be updated properly.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
I am working to bring up the fuzzer on comparisons between VMs.
Comparing between the binaryen interpreter and v8, it found some
atomics issues:
Atomic operations, including loads and stores, must be aligned
or they trap.
AtomicRMW did the wrong thing with the operands.
AtomicCmpxchg must wrap the input to the proper size (if we
only load 1 byte, only look at 1 byte of the expected value too).
AtomicWait and AtomicNotify must take into account their
offsets. Also SIMDLoadExtend was missing that. This was
confusing in the code as two getFinalAddresses existed,
one that doesn't compute with an offset, and one that does.
I renamed the one without to getFinalAddressWithoutOffset
so it's explicit and we can easily see we only call that one on
an instruction without an offset (which is the case for
MemoryInit, MemoryCopy, and MemoryFill).
AtomicNotify must check its address to see if it should trap,
even though we don't actually have multiple threads running.
Atomic loads of fewer bytes than the type always do an
unsigned extension, not signed.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Instead of using indices into the global interned type table. This
means that a lock is *never* needed to access an expanded Type. The
Type lock is now only acquired when a complex Type is created. On a
real-world wasm2js workload this improves wall clock time by 23% on my
machine with 72 cores and makes traffic on the Type lock entirely
insignificant.
**Before**
72 cores
real 0m6.914s
user 184.014s
sys 0m3.995s
1 core
real 0m25.903s
user 0m25.658s
sys 0m0.253s
**After**
72 cores
real 5.349s
user 70.309s
sys 9.691s
1 core
real 25.859s
user 25.615s
sys 0.253s
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
In wasm2js we ignore things that trap in wasm that we can't
really handle, like a load from memory out of bounds would
trap in wasm, but in JS we don't want to emit a bounds check
on each load. So wasm2js focuses on programs that don't
trap.
However, this is annoying in the fuzzer as it turns out that
our behavior for places where wasm would trap was not
deterministic. That is, wasm would trap, wasm2js would not
trap and do behavior X, and wasm2js with optimizations
would also not trap but do behavior Y != X. This produced
false positives in the fuzzer (and might be annoying in
manual debugging too).
As a workaround, this adds a --deterministic flag to wasm2js,
which tries to be deterministic about what it does for cases
where wasm would trap. This handles the case of an int
division by 0 which traps in wasm but without this flag could
have different behavior in wasm2js with or without opts
(see details in the patch).
|
|
|
| |
Fixes #2751.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
We used std::cerr as a workaround for that this logging
interfered with spec testing. But it's easy enough to filter
out this stuff for the spec tests.
The benefit to using std::cout is that as you can see in
the test output here, this is relevant test output - it's not
a side channel for debugging. If the rest of the interpreter
output is in std::cout but only traps are in std::cerr then
they might end up out of order etc., so best to keep them
all together.
This will allow easier additions of tests for fuzz testcases
|
|
|
|
| |
We shouldn't actually nop, we forgot that the value may have
side effects, so just drop it (opts will remove it later, if possible).
|
|
|
|
|
|
|
|
|
| |
These seem to be accidentally introduced in when we enforced use of
`Type::` on type names in #2434.
By the way TIL this actually compiles, and don't know why:
```
Type::Type::Type::Type::Type::Type::Type::Type::none
```
|
|
|
| |
Fixes #2749
|
|
|
|
|
| |
The fuzzer was previously unconditionally emitting one event parameter
more than it was supposed to, which meant multivalue events were
emitted when multivalue was not enabled.
|
|
|
|
| |
Based on freedback in #2741 it looks like we can use the existing
`simplify-globals-optimizing` pass to trigger this cleanups we need.
|
|
|
|
|
| |
Since the global is never read, we know that any write operation
will be unobservable.
|
|
|
|
|
|
| |
Avoid taking the type interning lock to look up the size when the
provided ID corresponds to a statically known type. This eliminates a
considerable amount of unnecessary lock traffic when using the C or JS
APIs.
|
|
|
|
|
| |
Instead of adding globals for hardcoded basic types, traverse the
module to collect all call types that might need to be handled and
emit a global for each of them. Adapted from #2712.
|