| Commit message (Collapse) | Author | Age | Files | Lines |
... | |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* Import `abort` from the environment
* Add passing spec tests
* Bind the abort function
* wasm2asm: Fix name collisions
Currently function names and local names can collide in namespaces, causing
buggy results when a function intends to call another function but ends up using
a local value as the target!
This fix was required to enable the `fac` spec test
* wasm2asm: Get multiple modules in one file working
The spec tests seem to have multiple modules defined in some tests and the
invocations all use the most recently defined module. This commit updates the
`--allow-asserts` mode of wasm2asm to work with this mode of tests, enabling us
to enable more spec tests for wasm2asm.
* wasm2asm: Enable the float_literals spec test
This needed to be modified to account for how JS engines don't work with NaN
bits the same way, but it's otherwise largely the same test. Additionally it
turns out that asm.js doesn't accept either `Infinity` or `NaN` ambient globals
so they needed to get imported through the `global` variable rather than defined
as literals in code
* wasm2asm: Fix function pointer invocations
This commit fixes invocations of functions through function pointers as
previously the table names on lookup and definition were mismatched. Both tables
now go through signature-based namification rather than athe name of the type
itself.
Overall this enables a slew of spec tests
* wasm2asm: Enable the left-to-right spec test
There were two small bugs in the order of evaluation of operators with
wasm2asm. The `select` instruction would sometimes evaluate the condition first
when it was supposed to be last. Similarly a `call_indirect` instruction would
evaluate the function pointer first when it was supposed to be evaluated last.
The `select` instruction case was a relatively small fix but the one for
`call_indirect` was a bit more pessimized to generate some temporaries.
Hopefully if this becomes up a problem it can be tightened up.
* wasm2asm: Fix signed load promotions of 64-bit ints
This commit enables the `endianness` spec test which revealed a bug in 64-bit
loads from smaller sizes which were signed. Previously the upper bits of the
64-bit number were all set to zero but the fix was for signed loads to have all
the upper bits match the highest bit of the low 32 bits that we load.
* wasm2asm: Enable the `stack` spec test
Internally the spec test uses a mixture of the s-expression syntax and the wat
syntax, so this is copied over into the `wasm2asm` folder after going through
`wat2wasm` to ensure it's consistent for binaryen.
* wasm2asm: Fix unaligned loads/stores of floats
Replace these operations in `RemoveNonJSOps` by using reinterpretation to
translate floats to integers and then use the existing code for unaligned
loads/stores of integers.
* wasm2asm: Fix a tricky grow_memory codegen bug
This commit fixes a tricky codegen bug found in the `grow_memory` instruction.
Specifically if you stored the result of `grow_memory` immediately into memory
it would look like:
HEAP32[..] = __wasm_grow_memory(..);
Here though it looks like JS evaluates the destination *before* the grow
function is called, but the grow function will invalidate the destination!
Furthermore this is actually generalizable to all function calls:
HEAP32[..] = foo(..);
Because any function could transitively call `grow_memory`. This commit fixes
the issue by ensuring that store instructions are always considered statements,
unconditionally evaluating the value into a temporary and then storing that into
the destination. While a bit of a pessmimization for now it should hopefully fix
the bug here.
* wasm2asm: Handle offsets in tables
This commit fixes initializing tables whose elements have an initial offset.
This should hopefully help fix some more Rust code which has all function
pointers offset by default!
* Update tests
* Tweak * location on types
* Rename entries of NameScope and document fromName
* Comment on lowercase names
* Update compiled JS
* Update js test output expectation
* Rename NameScope::Global to NameScope::Top
* Switch to `enum class`
* Switch to `Fatal()`
* Add TODO for when asm.js is no longer generated
|
|
|
|
|
|
|
|
|
|
| |
Remove executable bit and #! from scripts that don't have
entry point.
Add missing licence test.
Move arg parsing into a function.
Remove legacy --only_prepare (with underscrore) argument.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* wasm2asm: Finish i64 lowering operations
This commit finishes out lowering i64 operations to JS with implementations of
division and remainder for JS. The primary change here is to have these compiled
from Rust to wasm and then have them "linked in" via intrinsics. The
`RemoveNonJSOps` pass has been updated to include some of what
`I64ToI32Lowering` was previously doing, basically replacing some instructions
with calls to intrinsics. The intrinsics are now all tracked in one location.
Hopefully the intrinsics don't need to be regenerated too much, but for
posterity the source currently [lives in a gist][gist], although I suspect that
gist won't continue to compile and work as-is for all of time.
[gist]: https://gist.github.com/alexcrichton/e7ea67bcdd17ce4b6254e66f77165690
|
| |
|
|
|
| |
Don't skip through flowing tee values, just drop the current outermost which we find is redundant. the child tees may still be necessary.
|
|
|
|
|
|
|
|
|
| |
This commit lifts the same conversion strategy that `emcc` takes to convert
between floats point numbers and integers, and it should implement all the
various matrices of i32/u32/i64/u64 to f32/f64
Some refactoring was performed in the i64->i32 pass to allow for temporary
variables to get allocated which have types other than i32, but otherwise this
contains a pretty direct translation of `emcc`'s operations to `wasm2asm`.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
implementFunctions should use the export names, not the
internal/debug name for a function. This is especially
imported with lld where the debug names are demanagled.
implementFunctions should only contain functions that are
accessible from outside the module. i.e. those that have
been exported. There is no point in adding internal-only
functions to this list as they won't be accessible from
outside anyway.
Tesed with emscripten using: ./tests/runner.py binaryen2.test_time
|
|
|
|
|
|
| |
This commit implements the `copysign` instruction for the wasm2asm binary. The
implementation here is a new pass which wholesale replaces `copysign`
instructions with the equivalent bit ops and reinterpretation instructions. It's
intended that this matches Emscripten's implementation of lowering here.
|
|
|
|
|
|
|
|
|
|
|
| |
readability (#1552)
Like this:
(block $x
..
) ;; end block $x
Also fix some current breakage on master.
|
| |
|
|
|
|
| |
Not much fancy here, but rather each operation is naively lowered inline to the
if/else chain to execute it.
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
As mentioned in #1458 a naive implementation of these instructions is to round
trip the value through address 0 in linear memory. Also pointed out in #1458
this isn't necessarily valid for all languages. For now, though, languages like
Rust, C, and C++ would likely be horribly broken if valid data could be stored
at low addresses, so this commit goes ahead and adds an implementation of the
reinterpretation instructions by traveling data through address 0. This will
likely need an update if a language comes a long which can validly store data in
the first 8 bytes of linear memory, but it seems like that won't happen in the
near future.
Closes #1458
|
|
|
|
|
| |
* Move wasm2asm test outputs into their natural location, test/wasm2asm/
* Let people create new tests in there that ./auto_update_tests.py will auto-generate outputs for, just like all the other tests.
|
|
|
|
| |
Mostly piggy-back pon the previous 64-bit shift lowering code, just filling in a
few gaps.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
E.g.
```
(block
..
(loop $l
..
(br_if $l (..))
.. code that does not branch to the loop top
)
.. that code could be moved here ..
)
```
Moving the code out of the loop may help the loop body become a singleton expression, and is more readable anyhow.
|
|
|
|
|
|
|
|
|
| |
wasm-emscripten (#1539)
This allows the same functionality to be used also in
wasm-emscripten-finalize (i.e. the lld path).
|
|
|
|
|
|
|
|
|
| |
If locals are known to contain the same value, we can
* Pick which local to use for a get_local of any of them. Makes sense to prefer the most common, to increase the chance of one dropping to zero uses.
* Remove copies between a local and one that we know contains the same value.
This is a consistent win, small though, around 0.1-0.2%.
|
|
|
|
|
|
| |
* Add a helper class to iterate over all a node's children, and use that when attempting to replace a node with its children.
* If a child has a different type than the parent, try to replace the parent with a conversion + the child (for example, a call may receive two f32 inputs and return an i32; we can try to replace the call with one of those f32s and a conversion to an i32).
* When possible, try to replace the function body with a child even if the child has a different type, by changing the function return value.
|
|
|
|
|
| |
Remove the entire memory/table when possible, in particular, when not imported, exported, or used. Previously we did not look at whether they were imported, so we assumed we could never remove them.
Also add a variant that removes everything but functions, which can be useful when reducing a testcase that only cares about code in functions.
|
| |
|
|
|
|
|
| |
* remove-unused-brs: handle an if declared as returning a value despite having an unreachable condition
* simplify-locals: don't work on loops while the main pass is making changes, as set_locals are being tracked and modified.
|
| |
|
|
|
|
|
|
| |
* Use an if return value when one side is unreachable.
* Undo an if return value if we can use a br_if instead
|
|
|
|
|
| |
Add a version of simplify-locals which does not create nesting. This keeps the IR flat (in the sense of --flatten).
Also refactor simpify-locals to be a template, so the various modes are all template parameters.
|
| |
|
|
|
|
| |
opts (#1523)
|
|
|
|
|
| |
The option keeps running the passes (that we were told to run) in cycles until we converge in terms of the binary size, that is, keep optimizing until we can't shrink any more.
Also fix a --metrics bug this uncovered: we can't expect the Metrics object to still be around if running passes later in another PassRunner.
|
| |
|
|
|
| |
One pass may remove code that includes a tee which then makes more optimization possible. Found by the Souper investigations.
|
|
|
|
|
|
|
|
| |
Noticed by Souper.
* We only folded identical code in an if-else when both arms were blocks, so we were missing the case of one arm being just a singleton expression. This PR will wraps that in a block so the rest of the optimization can work on it, if it sees it is going to be folded out. Turns out this is common for phis.
* We only ran code-folding in -Os, because I assumed it was just good for code size, but as it may remove phis in the wasm VM later, seems like we should run it when not optimizing for size as well.
Together, these two shrink lua -O3 by almost 1%.
|
|
|
| |
Propagate constants through a tee_local. Found by Souper. Details in patch comments - basically we didn't differentiate precomputing a value and an expression.
|
|
|
| |
`xor` of 0, `and` and `or` of -1
|
|
|
|
|
| |
* Optimize shifts of 0.
* Optimize f(x, x) for various f (e.g., x & x => x).
|
|
|
|
|
|
|
|
|
| |
Stuff like x + 5 != 2 => x != -3.
Also some cleanups of utility functions I noticed while writing this, isTypeFloat => isFloatType.
Inspired by
https://github.com/golang/go/blob/master/src/cmd/compile/internal/ssa/gen/generic.rules
|
|
|
| |
Improve error handling, validation, and assertions for having a non-concrete type in an inappropriate place. Fixes a fuzz testcase.
|
|
|
|
|
|
|
|
|
|
| |
Inspired by #1501
* remove unneeded appearances of the default switch target (at the front or back of the list of targets)
* optimize a switch with 0, 1 or 2 targets into an if or if-chain
* optimize a br_if br pair when they have the same target
Makes e.g. fastcomp libc++ 2% smaller. Noticeable improvements on other things like box2d etc.
|
|
|
|
|
| |
The optimization in #1495 had a bug which was found by the fuzzer: our binary format parsing will not emit unreachable code (it may be stacky, so we ignore it). However, while parsing it we note breaks that are taken there, and then we removed that code, leading to a state where a break was not taken in the code, but we thought it was.
This PR clarifies the difference between unreachable code in the wasm sense (anything from the start of a block til an unreachable is "reachable") and the literal sense (even that code at the start may not be literally reachable if the block is not reachable), and then we use literal unreachability to know what code will be ignored and therefore we should ignore breaks in.
|
|
|
|
|
|
|
|
|
|
|
|
| |
llvm-mirror/llvm@9273bb3([Phabricator](https://reviews.llvm.org/D44256))
changed alias assignment syntax from
```
x = y
```
to
```
.set x, y
```
This patch reflects the change.
|
|
|
|
|
|
|
|
|
|
| |
When lowering i64 values in a function, we create new local variables
for all of the i64 local variables, one local for the low bits, and one
for the high bits. We create a mapping between the old locals and the
new as well. During translation, when we encountered a `get_local` that
didn't have type `i64`, we skipped it, on the supposition that there was
nothing to do. But that's not true; the local it was getting may have
been remapped to a new index in the lowered function, and we need to
account for that change. Similar logic holds for `set_local`.
|
|
|
|
|
|
|
| |
The documentation for the simplify-locals pass suggests running
reorder-locals after it to clean up unnecessary locals. wasm2asm wasn't
doing this, which meant that generated code had a number of unused
variables. A good minimizer will probably clean that up, but let's go
ahead and clean it up in wasm2asm itself.
|
|
|
|
|
| |
We were using the global to return 64-bit values from functions, but
said global wasn't actually present in the IR. This omission caused the
generated code to fail validation.
|
|
|
|
| |
unreachable, the modified version is as well (#1481)
|
|
|
|
|
|
|
|
|
| |
We were using Math_{min,max} in wasm2asm-generated files without
declaring said functions. This decision created problems for tests,
because Math_min (resp. max) would first be used on f32s, thus returning
f32, and then validation would fail when it was used on f64s.
The resulting changes make wasm2asm tests pass with MOZJS asm.js
validation, which moves #1443 forward.
|
|
|
|
|
|
|
|
|
|
|
| |
This adds a pass that implements "function pointer cast emulation" - allows indirect calls to go through even if the number of arguments or their types is incorrect. That is undefined behavior in C/C++ but in practice somehow works in native archs. It is even relied upon in e.g. Python.
Emscripten already has such emulation for asm.js, which also worked for asm2wasm. This implements something like it in binaryen which also allows the wasm backend to use it. As a result, Python should now be portable using the wasm backend.
The mechanism used for the emulation is to make all indirect calls use a fixed number of arguments, all of type i64, and a return type of also i64. Thunks are then placed in the table which translate the arguments properly for the target, basically by reinterpreting to i64 and back. As a result, receiving an i64 when an i32 is sent will have the upper bits all zero, and the reverse would truncate the upper bits, etc. (Note that this is different than emscripten's existing emulation, which converts (as signed) to a double. That makes sense for JS where double's can contain all numeric values, but in wasm we have i64s. Also, bitwise conversion may be more like what native archs do anyhow. It is enough for Python.)
Also adds validation for a function's type matching the function's actual params and result (surprised we didn't have that before, but we didn't, and there was even a place in the test suite where that was wrong).
Also simplifies the build script by moving two cpp files into the wasm/ subdir, so they can be built once and shared between the various tools.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* Emit invokeFuncs list as metadata
* Refactor s2wasm to use ModuleWriter
* Fix wasm-emscripten-finalize metadata output for binary output
* Add a flag to emit binary from s2wasm
NOTE: I chose to emit text by default, and binary behind a flag. This
mismatches with asm2wasm (and the expectations of users of a "2wasm"
tool), but doesn't break any existing users of s2wasm. If s2wasm is
deprecated in favor of lld, this will be the least disruptive change,
and we won't have to live with awkward defaults for too long.
* Emit source maps in the binary output of s2wasm
* Only emit binary with an outfile specified
|
|
|
|
|
| |
* allow tests in test/passes/ to have a numeric name, in which case there is a name.passes file with the names instead of the name containing the passes (which might be long, see #1020)
|
|
|
|
| |
This change eliminates one issue that prevents asm.js validation of the
generated code, see #1443.
|
|
|
|
|
|
| |
* Drop start function in RemoveUnusedModuleElements if empty
* Update tests and dist files
|
| |
|
|
|
|
|
|
|
|
|
|
| |
* refactor BINARYEN_PASS_DEBUG code for writing byn-* files, make it easy to emit binaries instead of text
* fix up bad argument numbers in asm2wasm. This can be caused by undefined behavior on the LLVM side, which happens to work natively. it's nicer to fix it up like it would be in a native build, and give a warning, instead of failing to compile
* update build-js.sh
* updated builds
|