summaryrefslogtreecommitdiff
path: root/src
Commit message (Collapse)AuthorAgeFilesLines
* 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
|
* Notice parse errors on number parsing in the text format (#1608)Loppin Vincent2018-07-241-0/+6
| | | | | | | * - Throw ParseException when istringstream failed to read a number. - Modify now invalid tests. * Add invalid_number.wast test
* Clarify what function-parallel passes can do, and fix an asm2wasm bug (#1627)Alon Zakai2018-07-233-13/+29
| | | | | The problem this fixes is that we made precompute look at globals in #1622, while asm2wasm was creating globals while adding functions and optimizing them - which could race. This was caught by threadSanitizer (with low frequency, so we missed it on the initial landing). The underlying issue is that function-parallel passes should be able to read global state, just not modify it, and not read other functions' contents (which is why the Call node has a name, not a pointer to a function). This PR clarifies that in the docs, and fixes asm2wasm by not handling function bodies in parallel to creating globals.
* Some minor LocalGraph improvements (#1625)Alon Zakai2018-07-211-80/+57
| | | | | * Remove the Action class - we just need a pointer to a get or set. This simplifies the code and saves a little memory, but doesn't seem to have any impact on speed. * Miscellaneous code style and comment changes.
* Mark arguments const in callExport (#1626)Alex Beregszaszi2018-07-211-6/+5
| | | The arguments is read only and therefore could be const. The immediate benefit is callers do not need to define it as a local variable (see Literal callExport(Name name)).
* Speedup localgraph (#1610)Loppin Vincent2018-07-201-18/+64
| | | | | | | | | | * LocalGraph : Replace seen unordered_set by boolean check. * LocalGraph : use unordered_map to store index -> last set_local instead of vector. * LocalGraph : - Use internal counter to avoid invalidation at each cycle. - Move all blocks structs into a contiguous vector of smaller ones.
* Support constant globals in precompute pass (#1622)Daniel Wirtz2018-07-182-24/+32
| | | | | | | | | This PR includes non-mutable globals in precompute, which will allow me to continue removing manual inlining of constants in AssemblyScript without breaking something. Related: #1621, i.e. enum Animal { CAT = 0, DOG = CAT + 1 // requires that `Animal.CAT` is evaluated to // precompute the constant value for `Animal.DOG` }
* Refactor stack writing code into a new StackWriter class (#1620)Alon Zakai2018-07-162-227/+247
| | | | | | | This separates out the WasmBinaryWriter parts that do stack writing into a separate class, StackWriter. Previously the WasmBinaryWriter did both the general writing and the stack stuff, and the stack stuff has global state, which it manually cleaned up etc. - seems nicer to have it as a separate class, a class focused on just that one thing. Should be no functional changes in this PR. Also add a timeout to the wasm-reduce test, which happened to fail on one of the commits here. It was running slower on that commit for some reason, could have been random - I verified that general wasm writing speed is unaffected by this PR. (But I added the timeout to prevent future random timeouts.)
* Minor code cleanups (#1617)Alon Zakai2018-07-104-125/+130
| | | | | | * code cleanups in wasm-binary: remove an & param, and standardize whitespace * add some docs for how the relooper handles blocks with no outgoing branches [ci skip]
* Proper error handling in add* and get* methods (#1570)Alon Zakai2018-07-103-32/+97
| | | | | | | See #1479 (comment) Also a one-line readme update, remove an obsolete compiler (mir2wasm) and add a new one (asterius). Also improve warning and error reporting in binaryen.js - show a stack trace when relevant (instead of node.js process.exit), and avoid atexit warning spam in debug builds.
* emscripten no longer allows modifying Module['print'] at runtime. Modify the ↵Alon Zakai2018-07-031-9/+9
| | | | internal out() method instead. see kripken/emscripten#6756 (#1614)
* Remove s2wasm (#1607)Sam Clegg2018-06-287-2535/+12
| | | | s2wasm is no longer used my emscripten and as far as I know now as no other users.
* Improve source map parsing to handle whitespace (#1598)Sam Clegg2018-06-131-14/+34
|