summaryrefslogtreecommitdiff
path: root/src/wasm-builder.h
Commit message (Collapse)AuthorAgeFilesLines
...
* Add table.size operation (#4224)Max Graey2021-10-081-0/+6
|
* Add table.set operation (#4215)Max Graey2021-10-071-0/+8
|
* Implement table.get (#4195)Alon Zakai2021-09-301-0/+8
| | | | Adds the part of the spec test suite that this passes (without table.set we can't do it all).
* [Wasm GC] Implement static (rtt-free) StructNew, ArrayNew, ArrayInit (#4172)Alon Zakai2021-09-231-0/+24
| | | | | | | | | See #4149 This modifies the test added in #4163 which used static casts on dynamically-created structs and arrays. That was technically not valid (as we won't want users to "mix" the two forms). This makes that test 100% static, which both fixes the test and gives test coverage to the new instructions added here.
* [Wasm GC] Add static variants of ref.test, ref.cast, and br_on_cast* (#4163)Alon Zakai2021-09-201-0/+23
| | | | | | | | | | | | These variants take a HeapType that is the type we intend to cast to, and do not take an RTT. These are intended to be more statically optimizable. For now though this PR just implements the minimum to get them parsing and to get through the optimizer without crashing. Spec: https://docs.google.com/document/d/1afthjsL_B9UaMqCA5ekgVmOm75BVFu6duHNsN9-gnXw/edit# See #4149
* [Wasm GC] ArrayInit support (#4138)Alon Zakai2021-09-101-0/+8
| | | | | | | array.init is like array.new_with_rtt except that it takes as arguments the values to initialize the array with (as opposed to a size and an optional initial value). Spec: https://docs.google.com/document/d/1afthjsL_B9UaMqCA5ekgVmOm75BVFu6duHNsN9-gnXw/edit#
* [Wasm GC] Fix Heap2Local + non-nullable locals (#4017)Alon Zakai2021-07-231-0/+5
| | | | | | | | | | | | | | | | | | | | | | | | | | | Given (local $x (ref $foo)) (local.set $x ..) (.. (local.get $x)) If we remove the local.set but not the get, then we end up with (local $x (ref $foo)) (.. (local.get $x)) It looks like the local.get reads the initial value of a non-nullable local, which is not allowed. In practice, this would crash in precompute-propagate which would try to propagate the initial value to the get. Add an assertion there with a clear message, as until we have full validation of non-nullable locals (and the spec for that is in flux), that pass is where bugs will end up being noticed. To fix this, replace the get as well. We can replace it with a null for simplicity; it will never be used anyhow. This also uncovered a small bug with reached not containing all the things we reached - it was missing local.gets.
* Preserve Function HeapTypes (#3952)Thomas Lively2021-06-301-16/+13
| | | | | | | | | When using nominal types, func.ref of two functions with identical signatures but different HeapTypes will yield different types. To preserve these semantics, Functions need to track their HeapTypes, not just their Signatures. This PR replaces the Signature field in Function with a HeapType field and adds new utility methods to make it almost as simple to update and query the function HeapType as it was to update and query the Function Signature.
* [EH] Make tag's attribute encoding detail (#3947)Heejin Ahn2021-06-211-3/+1
| | | | | | | | | This removes `attribute` field from `Tag` class, making the reserved and unused field known only to binary encoder and decoder. This also removes the `attribute` parameter from `makeTag` and `addTag` methods in wasm-builder.h, C API, and Binaryen JS API. Suggested in https://github.com/WebAssembly/binaryen/pull/3946#pullrequestreview-687756523.
* [EH] Replace event with tag (#3937)Heejin Ahn2021-06-181-21/+21
| | | | | | | | | | | We recently decided to change 'event' to 'tag', and to 'event section' to 'tag section', out of the rationale that the section contains a generalized tag that references a type, which may be used for something other than exceptions, and the name 'event' can be confusing in the web context. See - https://github.com/WebAssembly/exception-handling/issues/159#issuecomment-857910130 - https://github.com/WebAssembly/exception-handling/pull/161
* [Wasm GC] rtt.fresh_sub (#3936)Alon Zakai2021-06-171-0/+5
| | | | | | | | | | This is the same as rtt.sub, but creates a "new" rtt each time. See https://docs.google.com/document/d/1DklC3qVuOdLHSXB5UXghM_syCh-4cMinQ50ICiXnK3Q/edit# The old Literal implementation of rtts becomes a little more complex here, as it was designed for the original spec where only structure matters. It may be worth a complete redesign there, but for now as the spec is in flux I think the approach here is good enough.
* [Wasm GC] Add experimental array.copy (#3911)Alon Zakai2021-05-271-0/+14
| | | | | | | | Spec for it is here: https://docs.google.com/document/d/1DklC3qVuOdLHSXB5UXghM_syCh-4cMinQ50ICiXnK3Q/edit# Also reorder some things in wasm.h that were not in the canonical order (that has no effect, but it is confusing to read).
* Implement all Builder::replaceWithIdenticalType() cases as best we can (#3872)Alon Zakai2021-05-101-6/+4
| | | | | | The method had TODOs which it halted on. But we should not halt the entire program, as this is a best-effort attempt to replace a node with something simpler of the same type (we call it when we know the value is not actually used).
* Minor wasm-split improvements (#3825)Thomas Lively2021-04-201-1/+13
| | | | | | | | | | | - Support functions appearing more than once in the table. It turns out we were assuming and asserting that functions would appear at most once, but we weren't making use of that assumption in any way. - Make TableSlotManager::getSlot take a function Name rather than a RefFunc expression to avoid allocating and leaking unnecessary expressions. - Add and use a Builder interface for building TableElementSegments to make them more similar to other module-level items.
* RefFunc: Validate that the type is non-nullable, and avoid possible bugs in ↵Alon Zakai2021-04-081-3/+3
| | | | | | | | the builder (#3790) The builder can receive a HeapType so that callers don't need to set non-nullability themselves. Not NFC as some of the callers were in fact still making it nullable.
* [RT] Add type to tables and element segments (#3763)Abbas Mashayekh2021-04-061-2/+5
|
* Update SIMD names and opcodes (#3771)Thomas Lively2021-04-051-10/+0
| | | | Also removes experimental SIMD instructions that were not included in the final spec proposal.
* Fix a fuzz regression from #3669 (#3715)Alon Zakai2021-03-221-27/+0
| | | | | | | | | | | | | | | | | I'm not entirely sure how LUB removal made this noticeable, as it seems to be a pre-existing bug. However, somehow before #3669 it was not noticable - perhaps the finalize code worked around it. The bug is that RemoveUnusedBrs was moving code around and finalizing the parent before the child. The correct pattern is always to work from the children outwards, as otherwise the parent is trying to finalize itself based on non-finalized children. The fix is to just not finalize in the stealSlice method. The caller can do it after finishing any other work it has. As part of this refactoring, move stealSlice into the single pass that uses it; aside from that being more orderly, this method is really not a general-purpose tool, it is quite specific to what RemoveUnusedBrs does, and it might easily be used incorrectly elsewhere.
* [Wasm GC] Add test/spec/br_on_null.wast and validation fixes for it (#3623)Alon Zakai2021-03-011-1/+61
| | | | | | This adds ValidationBuilder which can allow sharing of builder code that also validates, between the text and binary parsers. In general we share that code in the validator, but the validator can only run once IR exists, and in some cases we can't even emit valid IR structure at all.
* [EH] Make rethrow's target a try label (#3568)Heejin Ahn2021-02-181-2/+2
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | I was previously mistaken about `rethrow`'s argument rule and thought it only counted `catch`'s depth. But it turns out it follows the same rule `delegate`'s label: the immediate argument follows the same rule as when computing branch labels, but it only can target `try` labels (semantically it targets that `try`'s corresponding `catch`); otherwise it will be a validation failure. Unlike `delegate`, `rethrow`'s label denotes not where to rethrow, but which exception to rethrow. For example, ```wasm try $l0 catch ($l0) try $l1 catch ($l1) rethrow $l0 ;; rethrow the exception caught by 'catch ($l0)' end end ``` Refer to this comment for the more detailed informal semantics: https://github.com/WebAssembly/exception-handling/issues/146#issuecomment-777714491 --- This also reverts some of `delegateTarget` -> `exceptionTarget` changes done in #3562 in the validator. Label validation rules apply differently for `delegate` and `rethrow` for try-catch. For example, this is valid: ```wasm try $l0 try delegate $l0 catch ($l0) end ``` But this is NOT valid: ```wasm try $l0 catch ($l0) try delegate $l0 end ``` So `try`'s label should be used within try-catch range (not catch-end range) for `delegate`s. But for the `rethrow` the rule is different. For example, this is valid: ```wasm try $l0 catch ($l0) rethrow $l0 end ``` But this is NOT valid: ```wasm try $l0 rethrow $l0 catch ($l0) end ``` So the `try`'s label should be used within catch-end range instead.
* [EH] Update C and binaryen.js API for delegate (#3565)Heejin Ahn2021-02-131-9/+49
| | | | | | | | | | This updates C and binaryen.js API to match the new `Try` structure to support `delegate`, added in #3561. Now `try` can take a name (which can be null) like a block, and also has an additional `delegateTarget` field argument which should only be used for try-delegate and otherwise null. This also adds several more variant of `makeTry` methods in wasm-builder. Some are for making try-delegate and some are for try-catch(_all).
* [GC] Support RTT constants in Builder::makeConstantExpression (#3550)Alon Zakai2021-02-091-0/+15
| | | | This allows the reducer to operate on RTTs, but could help other things too.
* [reference-types] remove single table restriction in IR (#3517)Abbas Mashayekh2021-02-091-1/+13
| | | Adds support for modules with multiple tables. Adds a field for the table name to `CallIndirect` and updates the C/JS APIs accordingly.
* [GC] Add br_on_func/data/i31 (#3525)Alon Zakai2021-01-281-2/+4
| | | | | | | | This expands the existing BrOnCast into BrOn that can also handle the func/data/i31 variants. This is not as elegant as RefIs / RefAs in that BrOnCast has an extra rtt field, but I think it is still the best option. We already have optional fields on Break (the value and condition), so making rtt optional is not odd. And it allows us to share all the behavior of br_on_* which aside from the cast or the check itself, is identical - returning the value if the branch is not taken, etc.
* [GC] Update br_on_cast: the text format also no longer has a heap type (#3523)Alon Zakai2021-01-271-3/+1
| | | | | | | As a result, we cannot handle a br_on_cast with an unreachable RTT. The binary format solves the problem by ignoring unreachable code, and this makes the text format do the same. A nice benefit of this is that we can remove the castType extra field.
* [GC] ref.as_* (#3520)Alon Zakai2021-01-271-0/+7
| | | | | | | | These are similar to is, but instead of returning an i32 answer, they trap on an invalid value, and return it otherwise. These could in theory be in a single RefDoThing, with opcodes for both As and Is, but as the return values are different, that would be a little odd, and the name would be less clear.
* [GC] RefIsNull => RefIs. (#3516)Alon Zakai2021-01-261-2/+3
| | | | | | | | This internal refactoring prepares us for ref.is_func/data/i31, by renaming the node and adding an "op" field. For now that field must always be "Null" which means it is a ref.is_null. This adjusts the C API to match the new IR shape. The high-level JS API is unchanged.
* Reorder i31ref and dataref (#3509)Heejin Ahn2021-01-231-2/+2
| | | | | | | | | | The binary spec (https://docs.google.com/document/d/1yAWU3dbs8kUa_wcnnirDxUu9nEBsNfq0Xo90OWx6yuo/edit#) lists `dataref` after `i31ref`, and `dataref` also comes after `i31ref` in its binary code in the value-increasing order. This reorders these two in wasm-type.h and other places, although in most of those places the order is irrelevant. This also adds C and JS API for `dataref`.
* Remove exnref and br_on_exn (#3505)Heejin Ahn2021-01-221-16/+0
| | | This removes `exnref` type and `br_on_exn` instruction.
* [GC] Add dataref type (#3500)Alon Zakai2021-01-211-0/+2
| | | | | This is not 100% of everything, but is enough to get tests passing, which includes full binary and text format support, getting all switches to compile without error, and some additions to InstrumentLocals.
* Basic EH instrucion support for the new spec (#3487)Heejin Ahn2021-01-151-6/+13
| | | | | | | | | | | | | | | | | | | | This updates `try`-`catch`-`catch_all` and `rethrow` instructions to match the new spec. `delegate` is not included. Now `Try` contains not a single `catchBody` expression but a vector of catch bodies and events. This updates most existing routines, optimizations, and tests modulo the interpreter and the CFG traversal. Because the interpreter has not been updated yet, the EH spec test is temporarily disabled in check.py. Also, because the CFG traversal for EH is not yet updated, several EH tests in `rse_all-features.wast`, which uses CFG traversal, are temporarily commented out. Also added a few more tests in existing EH test functions in test/passes. In the previous spec, `catch` was catching all exceptions so it was assumed that anything `try` body throws is caught by its `catch`, but now we can assume the same only if there is a `catch_all`. Newly added tests test cases when there is a `catch_all` and cases there are only `catch`es separately.
* Prototype prefetch instructions (#3467)Thomas Lively2021-01-061-0/+10
| | | | As proposed in https://github.com/WebAssembly/simd/pull/352, using the opcodes used in the LLVM and V8 implementations.
* [GC] Add br_on_cast (#3451)Alon Zakai2020-12-171-2/+6
| | | | | | | | | | | | | | | | The tricky part here, as pointed out by aheejin in my previous attempt, is that we need to know the type of the value we send if the branch is taken. We can normally calculate that from the rtt parameter's type - we are casting to that RTT, so we know what type that is - but if the rtt is unreachable, that's a problem. To fix that, store the cast type on BrOnCast instructions. This includes a test with a br_on_cast that succeeds and sends the cast value, one that fails and passes through the uncast value, and also of one with an unreachable RTT. This includes a fix for Precompute, as noticed by that new test. If a break is taken, with a ref as a value, we can't precompute it - for the same reasons we can't precompute a ref in general, that it is a pointer to possibly shared data.
* [GC] Add ref.test and ref.cast (#3439)Alon Zakai2020-12-111-4/+6
| | | | This adds enough to read and write them and test that, but leaves interpreter support for later.
* [GC] Add Array operations (#3436)Alon Zakai2020-12-101-8/+17
| | | | | | | | | | | | | | array.new/get/set/len - pretty straightforward after structs and all the infrastructure for them. Also fixes validation of the unnecessary heapType param in the text and binary formats in structs as well as arrays. Fixes printing of packed types in type names, which emitted i32 for them. That broke when we emitted the same name for an array of i8 and i32 as in the new testing here. Also fix a bug in Field::operator< which was wrong for packed types; again, this was easy to notice with the new testing.
* [GC] Add struct.new and start to test interesting execution (#3433)Alon Zakai2020-12-091-2/+4
| | | | | | | | | | | | | | With struct.new read/write support, we can start to do interesting things! This adds a test of creating a struct and seeing that references behave like references, that is, if we write to the value X refers to, and if Y refers to the same thing, when reading from Y's value we see the change as well. The test is run through all of -O1, which uncovered a minor issue in Precompute: We can't try to precompute a reference type, as we can't replace a reference with a value. Note btw that the test shows the optimizer properly running CoalesceLocals on reference types, merging two locals.
* [GC] Add basic RTT support (#3432)Alon Zakai2020-12-081-4/+10
| | | | | | | | | | | | | | | | This adds rtt.canon and rtt.sub together with RTT type support that is necessary for them. Together this lets us test roundtripping the instructions and types. Also fixes a missing traversal over globals in collectHeapTypes, which the example from the GC docs requires, as the RTTs are in globals there. This does not yet add full interpreter support and other things. It disables initial contents on GC in the fuzzer, to avoid the fuzzer breaking. Renames the binary ID for exnref, which is being removed from the spec, and which overlaps with the binary ID for rtt.
* [GC] Add struct.set (#3430)Alon Zakai2020-12-071-7/+7
| | | | | | | | | | Mostly straightforward after struct.get. This renames the value field in struct.get to ref. I think this makes more sense because struct.set has both a reference to a thing, and a value to set onto that thing. So calling the former ref seems more consistent, giving us ref, value. This mirrors load/store for example where we use ptr, value, and ref is playing the role of ptr here basically.
* [GC] Add struct.get instruction parsing and execution (#3429)Alon Zakai2020-12-071-12/+17
| | | | | | | | | | | | | | | | | | | | This is the first instruction that uses a GC Struct or Array, so it's where we start to actually need support in the interpreter for those values, which is added here. GC data is modeled as a gcData field on a Literal, which is just a Literals. That is, both a struct and an array are represented as an array of values. The type which is alongside would indicate if it's a struct or an array. Note that the data is referred to using a shared_ptr so it should "just work", but we'll only be able to really test that once we add struct.new and so can verify that references are by reference and not value, etc. As the first instruction to care about i8/16 types (which are only possible in a Struct or Array) this adds support for parsing and emitting them. This PR includes fuzz fixes for some minor things the fuzzer found, including some bad printing of not having ResultTypeName in necessary places (found by the text format roundtripping fuzzer).
* [TypedFunctionReferences] Implement call_ref (#3396)Alon Zakai2020-11-241-0/+13
| | | | | | | | Includes minimal support in various passes. Also includes actual optimization work in Directize, which was easy to add. Almost has fuzzer support, but the actual makeCallRef is just a stub so far. Includes s-parser support for parsing typed function references types.
* [TypedFunctionReferences] Add Typed Function References feature and use the ↵Alon Zakai2020-11-231-5/+9
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | types (#3388) This adds the new feature and starts to use the new types where relevant. We use them even without the feature being enabled, as we don't know the features during wasm loading - but the hope is that given the type is a subtype, it should all work out. In practice, if you print out the internal type you may see a typed function reference-specific type for a ref.func for example, instead of a generic funcref, but it should not affect anything else. This PR does not support non-nullable types, that is, everything is nullable for now. As suggested by @tlively this is simpler for now and leaves nullability for later work (which will apparently require let or something else, and many passes may need to be changed). To allow this PR to work, we need to provide a type on creating a RefFunc. The wasm-builder.h internal API is updated for this, as are the C and JS APIs, which are breaking changes. cc @dcodeIO We must also write and read function types properly. This PR improves collectSignatures to find all the types, and also to sort them by the dependencies between them (as we can't emit X in the binary if it depends on Y, and Y has not been emitted - we need to give Y's index). This sorting ends up changing a few test outputs. InstrumentLocals support for printing function types that are not funcref is disabled for now, until we figure out how to make that work and/or decide if it's important enough to work on. The fuzzer has various fixes to emit valid types for things (mostly whitespace there). Also two drive-by fixes to call makeTrivial where it should be (when we fail to create a specific node, we can't just try to make another node, in theory it could infinitely recurse). Binary writing changes here to replace calls to a standalone function to write out a type with one that is called on the binary writer object itself, which maintains a mapping of type indexes (getFunctionSignatureByIndex).
* [wasm-builder] Construct module elements as unique_ptrs (#3391)Thomas Lively2020-11-191-35/+35
| | | | | | | | | When Functions, Globals, Events, and Exports are added to a module, if they are not already in std::unique_ptrs, they are wrapped in a new std::unique_ptr owned by the Module. This adds an extra layer of indirection when accessing those elements that can be avoided by allocating those elements as std::unique_ptrs. This PR updates wasm-builder to allocate module elements via std::make_unique rather than `new`. In the future, we should remove the raw pointer versions of Module::add* to encourage using std::unique_ptrs more broadly.
* [Types] Handle function types fully in more places (#3381)Alon Zakai2020-11-181-10/+19
| | | | | | | | Call isFunction to check for a general function type instead of just a funcref, in places where we care about both, and some other minor miscellaneous typing fixes in preparation for typed function references (this will be tested fully at that time). Change is mostly whitespace.
* Module splitting (#3317)Thomas Lively2020-11-121-1/+2
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 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.
* Implement v128.{load,store}{8,16,32,64}_lane instructions (#3278)Thomas Lively2020-10-221-0/+16
| | | | | | | 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.
* Refactor naming convention for functions handling tuples (#3196)Max Graey2020-10-091-1/+1
| | | When there are two versions of a function, one handling tuples and the other handling non-tuple values, the previous naming convention was to have "Single" in the name of the non-tuple handling function. This PR simplifies the convention and shortens function names by making the names plural for the tuple-handling version and singular for the non-tuple-handling version.
* refactor makeFromUInt64 to makeFromInt64 (#3194)Max Graey2020-10-051-1/+1
| | | For consistency with `makeFromInt32`.
* GC: Add stubs for the remaining instructions (#3174)Daniel Wirtz2020-09-291-0/+72
| | | NFC, except adding most of the boilerplate for the remaining GC instructions. Each implementation site is marked with a respective `TODO (gc): theInstruction` in between the typical boilerplate code.
* GC: Fuzzing support for i31 (#3169)Daniel Wirtz2020-09-291-2/+2
| | | Integrates `i31ref` types and instructions into the fuzzer, by assuming that `(i31.new (i32.const N))` is constant and hence suitable to be used in global initializers.
* GC: Add i31 instructions (#3154)Daniel Wirtz2020-09-241-0/+13
| | | Adds the `i31.new` and `i31.get_s/u` instructions for creating and working with `i31ref` typed values. Does not include fuzzer integration just yet because the fuzzer expects that trivial values it creates are suitable in global initializers, which is not the case for trivial `i31ref` expressions.