summaryrefslogtreecommitdiff
path: root/src/wasm/wasm-binary.cpp
Commit message (Collapse)AuthorAgeFilesLines
...
* [EH] Replace event with tag (#3937)Heejin Ahn2021-06-181-54/+54
| | | | | | | | | | | 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-2/+6
| | | | | | | | | | 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.
* Parsing and emitting nominal types (#3933)Thomas Lively2021-06-151-6/+26
| | | | | | | Adds a `--nominal` option to switch the type machinery from equirecursive to nominal. Implements binary and text parsing and emitting of nominal types using new type constructor opcodes and an `(extends $super)` text syntax extension. When not in nominal mode, these extensions will still be parsed but will not have any effect and will not be used when emitting.
* [EH] Allow catch/delegate-less trys (#3924)Heejin Ahn2021-06-101-5/+7
| | | | This removes the restriction that `try` should have at least one `catch`/`catch_all`/`delegate`. See WebAssembly/exception-handling#157.
* Store signatures as HeapTypes when parsing binaries (#3929)Thomas Lively2021-06-101-21/+32
| | | | | | | When parsing func.ref instructions, we need to get the HeapType corresponding to the referenced function's signature. Since constructing HeapTypes from Signatures can be expensive under equirecursive typing, keep track of the original function signature HeapTypes directly during parsing rather than storing them as Signatures.
* [Wasm GC] Add negated BrOn* operations (#3913)Alon Zakai2021-06-021-1/+19
| | | | | | They are basically the flip versions. The only interesting part in the impl is that their returned typed and sent types are different. Spec: https://docs.google.com/document/d/1DklC3qVuOdLHSXB5UXghM_syCh-4cMinQ50ICiXnK3Q/edit
* [Wasm GC] Add experimental array.copy (#3911)Alon Zakai2021-05-271-0/+21
| | | | | | | | 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).
* [wasm-split] Add an option to emit only the module names (#3901)Thomas Lively2021-05-251-2/+8
| | | | | | Even when other names are stripped, it can be useful for wasm-split to preserve the module name so that the split modules can be differentiated in stack traces. Adding this option to wasm-split requires adding similar options to ModuleWriter and WasmBinaryWriter.
* [Wasm GC] Do not inline a function with an RTT parameter (#3808)Alon Zakai2021-04-141-1/+1
| | | | | Inlined parameters become locals, and rtts cannot be handled as locals, unlike non-nullable values which we can at least fix up. So do not inline functions with rtt params.
* Rename SIMD extending load instructions (#3798)Daniel Wirtz2021-04-121-6/+6
| | | | | | | | | Renames the SIMD instructions * LoadExtSVec8x8ToVecI16x8 -> Load8x8SVec128 * LoadExtUVec8x8ToVecI16x8 -> Load8x8UVec128 * LoadExtSVec16x4ToVecI32x4 -> Load16x4SVec128 * LoadExtUVec16x4ToVecI32x4 -> Load16x4UVec128 * LoadExtSVec32x2ToVecI64x2 -> Load32x2SVec128 * LoadExtUVec32x2ToVecI64x2 -> Load32x2UVec128
* Update SIMD binary constants (#3799)Daniel Wirtz2021-04-121-60/+60
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Updates binary constants of SIMD instructions to match new opcodes: * I16x8LoadExtSVec8x8 -> V128Load8x8S * I16x8LoadExtUVec8x8 -> V128Load8x8U * I32x4LoadExtSVec16x4 -> V128Load16x4S * I32x4LoadExtUVec16x4 -> V128Load16x4U * I64x2LoadExtSVec32x2 -> V128Load32x2S * I64x2LoadExtUVec32x2 -> V128Load32x2U * V8x16LoadSplat -> V128Load8Splat * V16x8LoadSplat -> V128Load16Splat * V32x4LoadSplat -> V128Load32Splat * V64x2LoadSplat -> V128Load64Splat * V8x16Shuffle -> I8x16Shuffle * V8x16Swizzle -> I8x16Swizzle * V128AndNot -> V128Andnot * F32x4DemoteZeroF64x2 -> F32x4DemoteF64x2Zero * I8x16NarrowSI16x8 -> I8x16NarrowI16x8S * I8x16NarrowUI16x8 -> I8x16NarrowI16x8U * I16x8ExtAddPairWiseSI8x16 -> I16x8ExtaddPairwiseI8x16S * I16x8ExtAddPairWiseUI8x16 -> I16x8ExtaddPairwiseI8x16U * I32x4ExtAddPairWiseSI16x8 -> I32x4ExtaddPairwiseI16x8S * I32x4ExtAddPairWiseUI16x8 -> I32x4ExtaddPairwiseI16x8U * I16x8Q15MulrSatS -> I16x8Q15mulrSatS * I16x8NarrowSI32x4 -> I16x8NarrowI32x4S * I16x8NarrowUI32x4 -> I16x8NarrowI32x4U * I16x8ExtendLowSI8x16 -> I16x8ExtendLowI8x16S * I16x8ExtendHighSI8x16 -> I16x8ExtendHighI8x16S * I16x8ExtendLowUI8x16 -> I16x8ExtendLowI8x16U * I16x8ExtendHighUI8x16 -> I16x8ExtendHighI8x16U * I16x8ExtMulLowSI8x16 -> I16x8ExtmulLowI8x16S * I16x8ExtMulHighSI8x16 -> I16x8ExtmulHighI8x16S * I16x8ExtMulLowUI8x16 -> I16x8ExtmulLowI8x16U * I16x8ExtMulHighUI8x16 -> I16x8ExtmulHighI8x16U * I32x4ExtendLowSI16x8 -> I32x4ExtendLowI16x8S * I32x4ExtendHighSI16x8 -> I32x4ExtendHighI16x8S * I32x4ExtendLowUI16x8 -> I32x4ExtendLowI16x8U * I32x4ExtendHighUI16x8 -> I32x4ExtendHighI16x8U * I32x4DotSVecI16x8 -> I32x4DotI16x8S * I32x4ExtMulLowSI16x8 -> I32x4ExtmulLowI16x8S * I32x4ExtMulHighSI16x8 -> I32x4ExtmulHighI16x8S * I32x4ExtMulLowUI16x8 -> I32x4ExtmulLowI16x8U * I32x4ExtMulHighUI16x8 -> I32x4ExtmulHighI16x8U * I64x2ExtendLowSI32x4 -> I64x2ExtendLowI32x4S * I64x2ExtendHighSI32x4 -> I64x2ExtendHighI32x4S * I64x2ExtendLowUI32x4 -> I64x2ExtendLowI32x4U * I64x2ExtendHighUI32x4 -> I64x2ExtendHighI32x4U * I64x2ExtMulLowSI32x4 -> I64x2ExtmulLowI32x4S * I64x2ExtMulHighSI32x4 -> I64x2ExtmulHighI32x4S * I64x2ExtMulLowUI32x4 -> I64x2ExtmulLowI32x4U * I64x2ExtMulHighUI32x4 -> I64x2ExtmulHighI32x4U * F32x4PMin -> F32x4Pmin * F32x4PMax -> F32x4Pmax * F64x2PMin -> F64x2Pmin * F64x2PMax -> F64x2Pmax * I32x4TruncSatSF32x4 -> I32x4TruncSatF32x4S * I32x4TruncSatUF32x4 -> I32x4TruncSatF32x4U * F32x4ConvertSI32x4 -> F32x4ConvertI32x4S * F32x4ConvertUI32x4 -> F32x4ConvertI32x4U * I32x4TruncSatZeroSF64x2 -> I32x4TruncSatF64x2SZero * I32x4TruncSatZeroUF64x2 -> I32x4TruncSatF64x2UZero * F64x2ConvertLowSI32x4 -> F64x2ConvertLowI32x4S * F64x2ConvertLowUI32x4 -> F64x2ConvertLowI32x4U
* Rename various SIMD load instructions (#3795)Daniel Wirtz2021-04-111-6/+6
| | | | | | | | | Renames the SIMD instructions * LoadSplatVec8x16 -> Load8SplatVec128 * LoadSplatVec16x8 -> Load16SplatVec128 * LoadSplatVec32x4 -> Load32SplatVec128 * LoadSplatVec64x2 -> Load64SplatVec128 * Load32Zero -> Load32ZeroVec128 * Load64Zero -> Load64ZeroVec128
* RefFunc: Validate that the type is non-nullable, and avoid possible bugs in ↵Alon Zakai2021-04-081-2/+1
| | | | | | | | 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.
* Add v128.load/storeN_lane SIMD instructions to C/JS API (#3784)Daniel Wirtz2021-04-081-8/+8
| | | | | | | | | | | Adds C/JS APIs for the SIMD instructions * Load8LaneVec128 (was LoadLaneVec8x16) * Load16LaneVec128 (was LoadLaneVec16x8) * Load32LaneVec128 (was LoadLaneVec32x4) * Load64LaneVec128 (was LoadLaneVec64x2) * Store8LaneVec128 (was StoreLaneVec8x16) * Store16LaneVec128 (was StoreLaneVec16x8) * Store32LaneVec128 (was StoreLaneVec32x4) * Store64LaneVec128 (was StoreLaneVec64x2)
* Write names subsections by increasing id (#3779)Sam Clegg2021-04-071-27/+33
| | | | | See https://webassembly.github.io/spec/core/appendix/custom.html "Each subsection may occur at most once, and in order of increasing id."
* [RT] Add type to tables and element segments (#3763)Abbas Mashayekh2021-04-061-31/+26
|
* Update SIMD names and opcodes (#3771)Thomas Lively2021-04-051-133/+56
| | | | Also removes experimental SIMD instructions that were not included in the final spec proposal.
* Fix binary reading of tuples containing non-nullable types (#3734)Alon Zakai2021-03-251-5/+21
| | | | | | | | We must write them to a tuple with nullable types, then fix that up when reading. This is similar to what we do in handleNonNullableLocals, except that it operates on the entire tuple type, so it can't share that code. This fixes a regression from #3710 that was harder to notice by the fuzzer until now.
* Refactor TypeBuilder (#3728)Thomas Lively2021-03-241-5/+5
| | | | | | | | | | Makes TypeBuilders growable, adds a `getTempHeapType` method, allows the `getTemp*Type` methods to take arbitrary temporary or canonical HeapTypes rather than just an index, and allows BasicHeapTypes to be assigned to TypeBuilder slots. All of these changes are necessary for the upcoming re-implementation of equirecursive LUB calculation. Also adds a new utility to TypeBuilder for using `operator[]` as an intuitive and readable wrapper around the `getTempHeapType` and `setHeapType` methods.
* [RT] Support expressions in element segments (#3666)Abbas Mashayekh2021-03-241-27/+49
| | | | | | This PR adds support for `ref.null t` as a valid element segment item. The abbreviated format of `(elem ... func $f $g...)` is kept in both printing and binary emitting if all items are `ref.func`s. Public APIs aren't updated in this PR.
* [Wasm GC] Add support for non-nullable types, all except for locals (#3710)Alon Zakai2021-03-231-11/+15
| | | | | | | | | | | | | | | | | | | | | | After this PR we still do not support non-nullable locals. But we no longer turn all types into nullable upon load. In particular, we support non-nullable types on function parameters and struct fields, etc. This should be enough to experiment with optimizations in both binaryen and in VMs regarding non- nullability (since we expect that optimizing VMs can do well inside functions anyhow; it's non-nullability across calls and from data that the VM can't be expected to think about). Let is handled as before, by lowering it into gets and sets. In addition, we turn non-nullable locals into nullable ones, and add a ref.as_non_null on all their gets (to keep the type identical there). This is used not just for loading code with a let but also is needed after inlining. Most of the code changes here are removing FIXMEs for allowing non-nullable types. But there is also code to handle the issues mentioned above. Most of the test updates are removing extra nulls that we added before when we turned all types nullable. A few tests had actual issues, though, and also some new tests are added to cover the code changes here.
* wasm-emscripten-finalize: Do not skip the start function body (#3714)Alon Zakai2021-03-221-1/+8
| | | | | | When we can skip function bodies, we still need to parse the start function for the pthreads case, see details in the comments. This still gives us 99% of the speedup as the start function is just 1 function and it's not that big, so with this we return to full speed after the reversion in #3705
* Fixed reading 64-bit memories and output of globals (#3709)Wouter van Oortmerssen2021-03-191-2/+2
|
* wasm-emscripten-finalize: Do not read the Names section when not writing ↵Alon Zakai2021-03-181-1/+5
| | | | | | | | | | | | | | | | | output (#3698) When not writing output we don't need debug info, as it is not relevant for our metadata. This saves loading and interning all the names, which takes several seconds on massive inputs. This is possible in principle in other tools, but this does not change anything in them for now. (We do use names internally in some nontrivial ways without opting in to it, so that would require further refactoring. Also the other tools almost always do write an output.) This is not 100% unobservable. If validation fails then the validation error would just contain the function index instead of the name from the Names section if there is one. However finalize does not validate atm so that would only matter if we change that later.
* Skip function bodies in wasm-emscripten-finalize when we don't need them (#3689)Alon Zakai2021-03-171-1/+11
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | After sbc100 's work on EM_ASM and EM_JS they are now parsed from the wasm using exports etc. and so we no longer need to parse function bodies. As a result if we are not emitting a wasm from wasm-emscripten-finalize then all we are doing is scanning global structures like imports and exports and emitting metadata about them. And indeed we do not need to emit a wasm in some cases, specifically when not optimizing and when using WASM_BIGINT (to avoid needing to legalize). We had considering skipping wasm-emscripten-finalize entirely in that situation, and instead to parse the metadata from the wasm in python on the emscripten side. However sbc100 had the brilliant idea today to just skip function bodies. That is very simple to do - no need to write another parser for wasm, and also look at how simple this PR is - and also it will be faster to run wasm-emscripten-finalize in this mode than to run python. (With the only downside that the bytes of the wasm are loaded even if they aren't parsed; but almost certainly they are in the disk cache anyhow.) This PR implements that idea: when wasm-emscripten-finalize knows it will not write a wasm output, it notes "skip function bodies". The binary reader then skips the bodies and places unreachables there instead (so that the wasm still validates). There are no new tests here because this can't be tested - by design it is an unobservable optimization. (If we could notice the bodies have been skipped, we would not have skipped them.) This is also why no changes are needed on the emscripten side to benefit from this speedup. Basically when binaryen sees it will not need X, it skips parsing of X automatically. Benchmarking speed, it is as fast as you'd expect: the wasm-emscripten-finalize step is 15x faster on SQLite (1MB of wasm) and almost 50x faster on the biggest wasm I have on my drive (40MB of LLVM). (These numbers are on release builds, without debug info - debug into makes things slower, so the speedup is lower there, and will need further work.) Tested manually and also on wasm0 wasm2 other on emscripten.
* [Wasm GC] Fix RTT type parsing (#3672)Alon Zakai2021-03-101-2/+2
| | | | | | This was missing from #3663 Fixes #3656
* [Wasm GC] Properly handle "typeindex" in the binary format (#3663)Alon Zakai2021-03-091-15/+23
| | | | | | | | | We handled them as S63 instead of U32. That should be fine, as all U32 values fit in S63. But it is not strictly correct. The signed encoding may use an additional byte which is unnecessary, and there is an actual correctness issue where a U32 may be interpreted as a large negative S63 (because it sign extends a final bit that happens to be 1). May help #3656 but that testcase still does not pass even with this.
* [reference-types] Support passive elem segments (#3572)Abbas Mashayekh2021-03-051-79/+146
| | | | | | | | | | | Passive element segments do not belong to any table, so the link between Table and elem needs to be weaker; i.e. an elem may have a table in case of active segments, or simply be a collection of function references in case of passive/declarative segments. This PR takes Table::Segment out and turns it into a first class module element just like tables and functions. It also implements early support for parsing, printing, encoding and decoding passive/declarative elem segments.
* Fix binary writing of local name indexes (#3649)Alon Zakai2021-03-041-9/+25
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | When writing a binary, we take the local indexes in the IR and turn them into the format in the binary, which clumps them by type. When writing the names section we should be aware of that ordering, but we never were, as noticed in #3499 This fixes that by saving the mapping of locals when we are emitting the name section, then using it when emitting the local names. This also fixes the order of the types themselves as part of the refactoring. We used to depend on the ordering of types to decide which to emit first, but that isn't good for at least two reasons. First, it hits #3648 - that order is not fully defined for recursive types. Also, it's not good for code size - we've ordered the locals in a way we think is best already (ReorderLocals pass). This PR makes us pick an order of types based on that, as much as possible, that is, when we see a type for the first time we append it to a list whose order we use. Test changes: Some are just because we use a different order than before, as in atomics64. But some are actual fixes, e.g. in heap-types where we now have (local $tv (ref null $vector)) which is indeed right - v there is for vector, and likewise m for matrix etc. - we just had wrong names before. Another example, we now have (local $local_externref externref) whereas before the name was funcref, and which was wrong... seems like the incorrectness was more common on reference types and GC types, which is why this was not noticed before. Fixes #3499 Makes part of #3648 moot.
* Emit "elem declare" for functions that need it (#3653)Alon Zakai2021-03-041-0/+28
| | | | | | | This adds support for reading (elem declare func $foo .. in the text and binary formats. We can simply ignore it: we don't need to represent it in IR, rather we find what needs to be declared when writing. That part takes a little more work, for which this adds a shared helper function.
* [Wasm GC] Allow subtyping in arguments to struct.get etc. Fixes #3636 (#3644)Alon Zakai2021-03-021-1/+1
| | | | | | | | | Note that Binaryen "canonicalizes" the type, so in the test output here we end up with $grandchild twice. This is a consequence of us not storing the heap type as an extra field. I can't think of a downside to this canonicalization, aside from losing perfect roundtripping, but I think that's a worthwhile tradeoff for efficiency as we've been thinking so far. Fixes #3636
* Remove duplicate assertion (#3638)Alon Zakai2021-03-021-1/+0
|
* [Wasm GC] Add Names section support for field names (#3589)Alon Zakai2021-03-011-0/+48
| | | | | | | | | | Adds support for GC struct fields in the binary format, implementing WebAssembly/gc#193 No extra tests needed, see the .fromBinary output which shows this working. This also has a minor fix in the s-parser, we should not always add a name to the map of index=>name - only if it exists. Without that fix, the binary emitter would write out null strings.
* [Wasm GC] Add test/spec/br_on_null.wast and validation fixes for it (#3623)Alon Zakai2021-03-011-1/+1
| | | | | | 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.
* Support 64-bit data segment init-exps in Memory64 (#3593)Wouter van Oortmerssen2021-02-251-1/+1
| | | This as a consequence of https://reviews.llvm.org/D95651
* Support Type names in the Names section (#3615)Alon Zakai2021-02-251-0/+37
|
* Refactor name processing (escaping/deduplication) to a shared place. NFC (#3609)Alon Zakai2021-02-241-29/+29
| | | | (not 100% NFC since it also fixes a bug by moving a line out of a loop)
* Support type use before definition in binaries (#3588)Thomas Lively2021-02-191-90/+181
| | | | | | Update parsing of binary type sections to use TypeBuilder to support uses before definitions. Now that both the binary and text parsers support out-of-order type uses, this PR also relaxes the logic for emitting types to allow uses to be emitted before definitions.
* [Wasm Exceptions] Fix binary parsing of a normal break to a try in a ↵Alon Zakai2021-02-191-4/+0
| | | | | | | | | | | | | | | | | | singleton (#3581) The fix here is to remove the code with // maybe we don't need a block here? That would remove a try's block if we thought it wasn't needed. However, it just checked for exception branches, but not normal branches, which are also possible. At that location, we don't have a good way to find out if the block has other branches to it aside from scanning its contents. So this PR just gives up on doing so, which means we add an unnecessary block if the optimizer is not run. If this matters we could make the binary parser more complicated by remembering whether a block had branches in the past, but I'm not sure if it's worth it.
* [EH] Change catch_all's opcode (#3574)Heejin Ahn2021-02-191-5/+2
| | | | | | | | | | We decided to change `catch_all`'s opcode from 0x05, which is the same as `else`, to 0x19, to avoid some complicated handling in the tools. See: https://github.com/WebAssembly/exception-handling/issues/147 lso this contains the original cpp file used to generate dwarf_with_exceptions.wasm; instructions to generate the wasm from that cpp file are in the comments.
* [EH] Make rethrow's target a try label (#3568)Heejin Ahn2021-02-181-10/+13
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 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] Rename delegateTarget to exceptionTarget (NFC) (#3562)Heejin Ahn2021-02-131-13/+14
| | | | | | | | | | | | | So far `Try`'s label is only targetted by `delegate`s, but it turns out `rethrow` also has to follow the same rule as `delegate` so it needs to target a `Try` label. So this renames variables like `delegateTargetNames` to `exceptionTargetNames` and methods like `replaceDelegateTargets` to `replaceExceptionTargets`. I considered `tryTarget`, but the branch/block counterpart name we use is not `blockTarget` but `branchTarget`, so I chose `exceptionTarget`. The patch that fixes `rethrow`'s target will follow; this is the preparation for that.
* [EH] Support reading/writing of delegate (#3561)Heejin Ahn2021-02-121-54/+119
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | This adds support for reading/writing of the new `delegate` instruction in the folded wast format, the stack IR format, the poppy IR format, and the binary format in Binaryen. We don't have a formal spec written down yet, but please refer to WebAssembly/exception-handling#137 and WebAssembly/exception-handling#146 for the informal semantics. In the current version of spec `delegate` is basically a rethrow, but with branch-like immediate argument so that it can bypass other catches/delegates in between. `delegate` is not represented as a new `Expression`, but it is rather an option within a `Try` class, like `catch`/`catch_all`. One special thing about `delegate` is, even though it is written _within_ a `try` in the folded wat format, like ```wasm (try (do ... ) (delegate $l) ) ``` In the unfolded wat format or in the binary format, `delegate` serves as a scope end instruction so there is no separate `end`: ```wasm try ... delegate $l ``` `delegate` semantically targets an outer `catch` or `delegate`, but we write `delegate` target as a `try` label because we only give labels to block-like scoping expressions. So far we have not given `Try` a label and used inner blocks or a wrapping block in case a branch targets the `try`. But in case of `delegate`, it can syntactically only target `try` and if it targets blocks or loops it is a validation failure. So after discussions in #3497, we give `Try` a label but this label can only be targeted by `delegate`s. Unfortunately this makes parsing and writing of `Try` expression somewhat complicated. Also there is one special case; if the immediate argument of `try` is the same as the depth of control flow stack, this means the 'delegate' delegates to the caller. To handle this case this adds a fake label `DELEGATE_CALLER_TARGET`, and when writing it back to the wast format writes it as an immediate value, unlike other cases in which we write labels. This uses `DELEGATE_FIELD_SCOPE_NAME_DEF/USE` to represent `try`'s label and `delegate`'s target. There are many cases that `try` and `delegate`'s labels need to be treated in the same way as block and branch labels, such as for hashing or comparing. But there are routines in which we automatically assume all label uses are branches. I thought about adding a new kind of defines such as `DELEGATE_FIELD_TRY_NAME_DEF/USE`, but I think it will also involve some duplication of existing routines or classes. So at the moment this PR chooses to use the existing `DELEGATE_FIELD_SCOPE_NAME_DEF/USE` for `try` and `delegate` labels and makes only necessary amount of changes in branch-utils. We can revisit this decision later if necessary. Many of changes to the existing test cases are because now all `try`s are automatically assigned a label. They will be removed in `RemoveUnusedNames` pass in the same way as block labels if not targeted by any delegates. This only supports reading and writing and has not been tested against any optimization passes yet. --- Original unfolded wat file to generate test/try-delegate.wasm: ```wasm (module (event $e) (func try try delegate 0 catch $e end) (func try try catch $e i32.const 0 drop try delegate 1 end catch $e end ) ) ```
* [reference-types] remove single table restriction in IR (#3517)Abbas Mashayekh2021-02-091-81/+202
| | | Adds support for modules with multiple tables. Adds a field for the table name to `CallIndirect` and updates the C/JS APIs accordingly.
* Use unordered maps of Name where possible (#3546)Alon Zakai2021-02-051-4/+4
| | | | | | | Unordered maps will hash the pointer, while ordered ones will compare the strings to find where to insert in the tree. I cannot confirm a speedup in time from this, though others can, but I do see a consistent improvement of a few % in perf stat results like number of instructions and cycles (and those results have little noise). And it seems logical that this could be faster.
* Prototype i32x4.widen_i8x16_{s,u} (#3535)Thomas Lively2021-02-011-0/+24
| | | | | | | | As proposed in https://github.com/WebAssembly/simd/pull/395. Note that the other instructions in the proposal have not been implemented in LLVM or in V8, so there is no need to implement them in Binaryen right now either. This PR introduces a new expression class for the new instructions because they uniquely take an immediate argument identifying which portion of the input vector to widen.
* [GC] br_on_null (#3528)Alon Zakai2021-02-011-0/+6
| | | | | | | | | | | This is only partial support, as br_on_null also has an extra optional value in the spec. Implementing that is cumbersome in binaryen, and there is ongoing spec discussions about it (see https://github.com/WebAssembly/function-references/issues/45 ), so for now we only support the simple case without the default value. Also fix prefixed opcodes to be LEBs in RefAs, which was noticed here as the change here made it noticeable whether the values were int8 or LEBs.
* [GC] ref.as_non_null (#3527)Alon Zakai2021-01-281-0/+6
| | | | | | This is different than the other RefAs variants in that it is part of the typed functions proposal, and not GC. But it is part of GC prototype 3. Note: This is not useful to us yet as we don't support non-nullable types.
* [GC] Add br_on_func/data/i31 (#3525)Alon Zakai2021-01-281-8/+22
| | | | | | | | 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-1/+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.