summaryrefslogtreecommitdiff
path: root/src
Commit message (Collapse)AuthorAgeFilesLines
...
* add support for new call_indirect syntax ; fixes #1724 (#1725)Alon Zakai2018-11-051-8/+29
|
* Suppress the 'has StackIR' comment when printing StackIR (#1726)Daniel Wirtz2018-11-041-1/+1
| | | Follow-up to #1717
* Fix asm2wasm handling of HEAP8[x >> 2] (#1720)Alon Zakai2018-11-021-1/+13
| | | | | | fixes kripken/emscripten#1718 The way fastcomp emits compareExchange is a little odd, we just need to ignore the shift.
* Don't call static desructors when Fatal() errors occur (#1722)Sam Clegg2018-11-022-3/+6
| | | | | This was causing a deadlock while destroying the thread pool.
* Add pass to minify import and export names (#1719)Alon Zakai2018-11-014-0/+173
| | | | | | | | | This new pass minifies import and export names, for example, this may minify (import "env" "longname" (func $internal)) to (import "env" "a" (func $internal)) By updating the JS that provides those imports/calls those exports, we can use the minified names properly. This can save a useful amount of space in the wasm and JS, see kripken/emscripten#7414
* Emit imports before defined things in text format (#1715)Alon Zakai2018-11-012-5/+42
| | | | | That is the correct order in the text format, wabt errors otherwise. See AssemblyScript/assemblyscript#310
* Add Module#emitStackIR to the JS-API (#1717)Daniel Wirtz2018-10-311-0/+10
| | | Related to #1716 (comment)
* Add missing include guard (#1713)Michał Janiszewski2018-10-291-0/+1
|
* Expand asmConsts metadata to fit the shape of proxying async EM_ASMs (no ↵Jacob Gravelle2018-10-251-0/+6
| | | | actual support) (#1711)
* comment on nondeterminism in precompute pass [ci skip] (#1704)Alon Zakai2018-10-161-0/+5
|
* Support 4GB Memories (#1702)Alon Zakai2018-10-158-22/+29
| | | This fixes asm2wasm parsing of the max to allow 4GB, and also changes the internal Memory::kMaxValue values to reflect that. We used to use kMaxValue to also represent "no limit", so I split that out into kUnlimitedValue.
* properly handle unreachable atomic operations, fixes a regression from #1693 ↵Alon Zakai2018-10-111-2/+2
| | | | (#1696)
* Shared memory support for add memory import and set memory functions. (#1686)Nidin Vinayakan2018-10-113-10/+13
|
* Add BinaryenRemoveGlobal / Module.removeGlobal to C/JS API (#1692)Daniel Wirtz2018-10-093-0/+14
|
* No atomic float operations (#1693)Alon Zakai2018-10-052-5/+19
| | | | | SafeHeap was emitting them, but it looks like they are invalid according to the wasm-threads spec. Fixes kripken/emscripten#7208
* Add initial/maximum table size parameters to C/JS API (#1687)Daniel Wirtz2018-09-283-9/+11
|
* More #1678 fixes (#1685)Alon Zakai2018-09-204-4/+15
| | | While debugging to fix the waterfall regressions I noticed that wasm-reduce regressed. We need to be more careful with visitFunction which now may visit an imported function - I found a few not-well-tested passes that also regressed that way.
* fix an iterator invalidation regression from #1678 (#1684)Alon Zakai2018-09-201-5/+24
| | | Fixes the 3 regressions mentioned in a comment on #1678
* Unify imported and non-imported things (#1678)Alon Zakai2018-09-1960-1654/+1299
| | | | | | | | | | | | | | Fixes #1649 This moves us to a single object for functions, which can be imported or nor, and likewise for globals (as a result, GetGlobals do not need to check if the global is imported or not, etc.). All imported things now inherit from Importable, which has the module and base of the import, and if they are set then it is an import. For convenient iteration, there are a few helpers like ModuleUtils::iterDefinedGlobals(wasm, [&](Global* global) { .. use global .. }); as often iteration only cares about imported or defined (non-imported) things.
* Add debug information locations to the function prolog/epilog (#1674)Yury Delendik2018-09-177-78/+154
| | | | | | | The current patch: * Preserves the debug locations from function prolog and epilog * Preserves the debug locations of the nested blocks
* fix sign detection of a floating-point mod ; fixes kripken/emscripten#7123 ↵Alon Zakai2018-09-151-1/+1
| | | | (#1681)
* Note that calls to imports are not lightweight in inlining pass (#1673)Alon Zakai2018-09-121-0/+5
| | | | * call_import is not lightweight for inlining purposes - we had call but not callimport, which is even less light
* Misc tiny fuzz fixes (#1668)Alon Zakai2018-09-124-2/+12
| | | | | | | | | | | | * show a proper error for an empty asm2wasm input * handle end of input in processExpressions in binary reading * memory segment sizes should be unsigned * validate input in wasm-ctor-eval * update tests
* remove PageSize and HasFeature, which wasm removed a while back (#1667)Alon Zakai2018-09-129-34/+4
| | | From #1665 (a fuzz bug noticed they were not handled in stack.h).
* Fix parsing of memory attributes in s-expression parser (#1666)Alon Zakai2018-09-111-13/+21
| | | | | We need to check not to read past the length of the string. From #1665
* Binary format local parsing fixes (#1664)Alon Zakai2018-09-112-9/+13
| | | | | | * Error if there are more locals than browsers allow (50,000). We usually just warn about stuff like this, but we do need some limit (or else we hang or OOM), and if so, why not use the agreed-upon Web limit. * Do not generate nice string names for locals in binary parsing - the name is just $var$x instead of $x, so not much benefit, and worse as our names are interned this is actually slow (which is why the fuzz testcase here hangs instead of OOMing). Testcases and bugreport in #1663.
* [wasm2js] Fix base64 encoding (#1670)Yury Delendik2018-09-051-8/+8
| | | The static std::string base64Encode(std::vector<char> &data) { uses signed char in input data. The ((int)data[0]) converts it the signed int, making '\xFF' char into -1. The patch fixes casting.
* DeadArgumentElimination Pass (#1641)Alon Zakai2018-09-0510-29/+462
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | This adds a pass to remove unnecessary call arguments in an LTO-like manner, that is: * If a parameter is not actually used in a function, we don't need to send anything, and can remove it from the function's declaration. Concretely, (func $a (param $x i32) ..no uses of $x.. ) (func $b (call $a (..)) ) => (func $a ..no uses of $x.. ) (func $b (call $a) ) And * If a parameter is only ever sent the same constant value, we can just set that constant value in the function (which then means that the values sent from the outside are no longer used, as in the previous point). Concretely, (func $a (param $x i32) ..may use $x.. ) (func $b (call $a (i32.const 1)) (call $a (i32.const 1)) ) => (func $a (local $x i32) (set_local $x (i32.const 1) ..may use $x.. ) (func $b (call $a) (call $a) ) How much this helps depends on the codebase obviously, but sometimes it is pretty useful. For example, it shrinks 0.72% on Unity and 0.37% on Mono. Note that those numbers include not just the optimization itself, but the other optimizations it then enables - in particular the second point from earlier leads to inlining a constant value, which often allows constant propagation, and also removing parameters may enable more duplicate function elimination, etc. - which explains how this can shrink Unity by almost 1%. Implementation is pretty straightforward, but there is some work to make the heavy part of the pass parallel, and a bunch of corner cases to avoid (can't change a function that is exported or in the table, etc.). Like the Inlining pass, there is both a standard and an "optimizing" version of this pass - the latter also optimizes the functions it changes, as like Inlining, it's useful to not need to re-run all function optimizations on the whole module.
* [wasm2js] Fix nested selects (#1671)Yury Delendik2018-09-051-3/+3
| | | | In wasmjs, the nested selects are trying to use the same temporary locals. The patch reserves temporaries "at right time" to avoid overriding the values.
* Loop Invariant Code Motion (#1658)Alon Zakai2018-09-046-3/+265
| | | | | | | | | | | | | | | | | | | | | This adds an licm pass. Not that important for LLVM-originating code obviously, but for AssemblyScript and other non-LLVM compilers this might help a lot. Also when wasm has GC a bunch more non-LLVM languages may arrive that can benefit. The pass is mostly straightforward. I considered using the DataFlow IR since it's in SSA form, or the CFG IR, but in the end it's actually pretty convenient to use the main IR as it is - with explicit loops already present - plus LocalGraph which connects each get to the sets influencing it. Passed a bunch of fuzzing, and also the emscripten test suite at -O1 with licm added to the default passes (but I don't think it would make sense to run this by default, as LLVM doesn't need it). We limit code moved by this pass as follows: An increased code size on fuzz testcases (and, more rarely, on real inputs) can happen due to stuff like this: (loop (set_local $x (i32.const 1)) .. ) => (set_local $x (i32.const 1)) (loop .. ) For a const or a get_local, such an assignment to a local is both very cheap (a copy to another local may be optimized out later), and moving it out may prevent other optimizations (since we have no pass that tries to move code back in to a loop edit well, not by default, precompute-propagate etc. would do it, but are only run on high opt levels). So I made the pass not move such trivial code (sets/tees of consts or gets). However, the risk remains if code is moved out that is later reduced to a constant, so something like -Os --flatten --licm -Os may make sense.
* Change the Literal class's operator== to be bitwise (#1661)Alon Zakai2018-09-016-20/+13
| | | | | The change means that nan values will be compared bitwise when writing A == B, and so the float rule of a nan is different from itself would not apply. I think this is a safer default. In particular this PR fixes a fuzz bug in the rse pass, which placed Literals in a hash table, and due to nan != nan, an infinite loop... Also, looks like we really want a bitwise comparison pretty much everywhere anyhow, as can be seen in the diff here. Really the single place we need a floaty comparison is in the intepreter where we implement f32.eq etc., and there the code was already using the proper code path anyhow.
* BinaryenSetFunctionTable now accepts array of func names not funcs. (#1650)Jay Phelps2018-09-013-36/+37
| | | | | This allows using imports in the table. Fixes #1645
* Remove assert that import names match (#1662)Jacob Gravelle2018-08-311-4/+0
| | | | | We're about to rewrite both names anyway. This fixes LLVM's c++ invokes, which get escaped to not match as of PR #1646
* Fix findField (#1660)Yury Delendik2018-08-311-0/+2
|
* Fix read-write of dylink section (#1648)Alon Zakai2018-08-314-9/+34
| | | | | | The 'dylink' user section must be emitted before all other sections, per the spec (to allow simple parsing by loaders) This PR makes reading and writing of a dynamic library remain a valid dynamic library.
* Escape name section ids in binary format reading/writing to be WebAssembly ↵Yury Delendik2018-08-312-2/+69
| | | | spec compatible. (#1646)
* Remove replaced imports in LegalizeJSInterface (#1657)Sam Clegg2018-08-301-0/+4
| | | | This pass was replacing all the uses of certain imports but wasn't bothering to delete the old ones.
* Rename `wasm2asm` to `wasm2js`, emit ESM by default (#1642)Alex Crichton2018-08-303-109/+296
| | | | | | | | | | | | | | | | | | | | | | | | * Rename the `wasm2asm` tool to `wasm2js` This commit performs a relatively simple rename of the `wasm2asm` tool to `wasm2js`. The functionality of the tool doesn't change just yet but it's intended that we'll start generating an ES module instead of just an `asm.js` function soon. * wasm2js: Support `*.wasm` input files Previously `wasm2js` only supported `*.wast` files but to make it a bit easier to use in tooling pipelines this commit adds support for reading in a `*.wasm` file directly. Determining which parser to use depends on the input filename, where the binary parser is used with `*.wasm` files and the wast parser is used for all other files. * wasm2js: Emit ESM imports/exports by default This commit alters the default behavior of `wasm2js` to emit an ESM by default, either importing items from the environment or exporting. Items like initialization of memory are also handled here.
* Run legalize-js-interface during wasm-emscripten-finalize (#1653)Sam Clegg2018-08-293-4/+24
| | | | This ensures that 64-bit values are correctly handled on the JS boundary.
* wasm-emscripten-finalize: Don't allow duplicates in 'declares'/'invok… (#1655)Sam Clegg2018-08-291-2/+10
| | | | | Allowing duplicates here was causes emscripten to generate a JS object with duplicate keys.
* Greatly simplify iteration.h (#1654)Alon Zakai2018-08-291-139/+20
| | | This avoids us needing to update it for new Expression types (SIMD, GC, etc.) in the future.
* wasm-emscripten-finalize: make _wasm_call_ctors optional (#1647)Sam Clegg2018-08-281-1/+3
|
* Improve getFallthrough (#1643)Alon Zakai2018-08-272-18/+38
| | | | | That method looks through tee_locals and other operations that receive a value and let it flow through them, like a block's final value, etc. It just handled a few such operations, with this PR all of them should be handled. Also refactor it out of the OptimizeInstructions pass as I think it may be useful for propagating returned constants.
* Souper integration + DataFlow optimizations (#1638)Alon Zakai2018-08-2712-5/+2184
| | | | | | | | | Background: google/souper#323 This adds a --souperify pass, which emits Souper IR in text format. That can then be read by Souper which can emit superoptimization rules. We hope that eventually we can integrate those rules into Binaryen. How this works is we emit an internal "DataFlow IR", which is an SSA-based IR, and then write that out into Souper text. This also adds a --dfo pass, which stands for data-flow optimizations. A DataFlow IR is generated, like in souperify, and then performs some trivial optimizations using it. There are very few things that can do that our other optimizations can't already, but this is also good testing for the DataFlow IR, plus it is good preparation for using Souper's superoptimization output (which would also construct DataFlow IR, like here, but then do some matching on the Souper rules).
* Fix value flowing in remove-unused-brs (#1639)Alon Zakai2018-08-201-24/+28
| | | | | The fuzzer found a bug with flowing of values in that pass: when one arm of an if is none-typed, we can't flow a value through the other. Odd the fuzzer didn't find this earlier, as it's been a bug since the pass was written years ago, but in practice it seems you need a specific set of circumstances on the outside for it to be hit. The fix is to stop flowing a value in that case. Also, I realized after fixing it that the valueCanFlow global state variable is entirely unneeded. Removing it makes the pass significantly simpler: at all times, flows contains branches and values that might be flowing, and if the flow stops we remove them, etc. - we don't need an extra state variable to say if flowing is possible. So when we want to use the flows, we just check what is there (and then for a flowing branch we can remove it, and for a flowing value we can replace the branch with the value, etc., as in both cases they flow to the right place anyhow).
* switch from CMAKE_SOURCE_DIR to PROJECT_SOURCE_DIR to support ↵Jay Phelps2018-08-171-2/+2
| | | | add_subdirectory(binaryen) (#1637)
* Print Stack IR in proper .wat format (#1630)Alon Zakai2018-08-147-420/+618
| | | This now makes --generate-stack-ir --print-stack-ir emit a fully valid .wat wasm file, in stacky format.
* wasm-ctor-eval improvements (#1631)Alon Zakai2018-08-071-0/+4
| | | | | * When we eval a ctor, don't just nop the function body that no longer needs to be executed, also remove the export (as we report the ctor being evalled, and the outside will no longer call it). * Run the pass to remove unused global things. This can usually remove evalled ctors (unless something else happens to call them, which can't happen normally as LLVM wouldn't use a ctor in another place, but e.g. duplicate function merging might merge a ctor with another function).
* Stack IR (#1623)Alon Zakai2018-07-3020-973/+1988
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | This adds a new IR, "Stack IR". This represents wasm at a very low level, as a simple stream of instructions, basically the same as wasm's binary format. This is unlike Binaryen IR which is structured and in a tree format. This gives some small wins on binary sizes, less than 1% in most cases, usually 0.25-0.50% or so. That's not much by itself, but looking forward this prepares us for multi-value, which we really need an IR like this to be able to optimize well. Also, it's possible there is more we can do already - currently there are just a few stack IR optimizations implemented, DCE local2stack - check if a set_local/get_local pair can be removed, which keeps the set's value on the stack, which if the stars align it can be popped instead of the get. Block removal - remove any blocks with no branches, as they are valid in wasm binary format. Implementation-wise, the IR is defined in wasm-stack.h. A new StackInst is defined, representing a single instruction. Most are simple reflections of Binaryen IR (an add, a load, etc.), and just pointers to them. Control flow constructs are expanded into multiple instructions, like a block turns into a block begin and end, and we may also emit extra unreachables to handle the fact Binaryen IR has unreachable blocks/ifs/loops but wasm does not. Overall, all the Binaryen IR differences with wasm vanish on the way to stack IR. Where this IR lives: Each Function now has a unique_ptr to stack IR, that is, a function may have stack IR alongside the main IR. If the stack IR is present, we write it out during binary writing; if not, we do the same binaryen IR => wasm binary process as before (this PR should not affect speed there). This design lets us use normal Passes on stack IR, in particular this PR defines 3 passes: Generate stack IR Optimize stack IR (might be worth splitting out into separate passes eventually) Print stack IR for debugging purposes Having these as normal passes is convenient as then they can run in parallel across functions and all the other conveniences of our current Pass system. However, a downside of keeping the second IR as an option on Functions, and using normal Passes to operate on it, means that we may get out of sync: if you generate stack IR, then modify binaryen IR, then the stack IR may no longer be valid (for example, maybe you removed locals or modified instructions in place etc.). To avoid that, Passes now define if they modify Binaryen IR or not; if they do, we throw away the stack IR. Miscellaneous notes: Just writing Stack IR, then writing to binary - no optimizations - is 20% slower than going directly to binary, which is one reason why we still support direct writing. This does lead to some "fun" C++ template code to make that convenient: there is a single StackWriter class, templated over the "mode", which is either Binaryen2Binary (direct writing), Binaryen2Stack, or Stack2Binary. This avoids a lot of boilerplate as the 3 modes share a lot of code in overlapping ways. Stack IR does not support source maps / debug info. We just don't use that IR if debug info is present. A tiny text format comment (if emitting non-minified text) indicates stack IR is present, if it is ((; has Stack IR ;)). This may help with debugging, just in case people forget. There is also a pass to print out the stack IR for debug purposes, as mentioned above. The sieve binaryen.js test was actually not validating all along - these new opts broke it in a more noticeable manner. Fixed. Added extra checks in pass-debug mode, to verify that if stack IR should have been thrown out, it was. This should help avoid any confusion with the IR being invalid. Added a comment about the possible future of stack IR as the main IR, depending on optimization results, following some discussion earlier today.
* Fix source map entries offset when LEB is compressed. (#1628)Yury Delendik2018-07-252-16/+42
|