summaryrefslogtreecommitdiff
path: root/src
Commit message (Collapse)AuthorAgeFilesLines
...
* Allow different arguments for multiple instances of a pass (#6687)Christian Speckner2024-07-1520-79/+170
| | | | | | | | | | | | Each pass instance can now store an argument for it, which can be different. This may be a breaking change for the corner case of running a pass multiple times and setting the pass's argument multiple times as well (before, the last pass argument affected them all; now, it affects the last instance only). This only affects arguments with the name of a pass; others remain global, as before (and multiple passes can read them, in fact). See the CHANGELOG for details. Fixes #6646
* [threads] Fix struct op validation for shared null (#6742)Thomas Lively2024-07-131-1/+1
|
* Monomorphize dropped functions (#6734)Alon Zakai2024-07-125-36/+227
| | | | | | | | | | | | | | | | | | | | | | | | | We now consider a drop to be part of the call context: If we see (drop (call $foo) ) (func $foo (result i32) (i32.const 42) ) Then we'd monomorphize to this: (call $foo_1) ;; call the specialized function instead (func $foo_1 ;; the specialized function returns nothing (drop ;; the drop was moved into here (i32.const 42) ) ) With the drop now in the called function, we may be able to optimize out unused work. Refactor a bit of code out of DAE that we can reuse here, into a new return-utils.h.
* Remove non-standard `i31.new` (#6736)Thomas Lively2024-07-121-20/+9
| | | | The standard name for the instruction is `ref.i31`. Remove support for the non-standard name and update tests that were still using it.
* [threads] ref.i31_shared (#6735)Thomas Lively2024-07-1216-32/+76
| | | | | | | Implement `ref.i31_shared` the new instruction for creating references to shared i31s. Implement binary and text parsing and emitting as well as interpretation. Copy the upstream spec test for i31 and modify it so that all the heap types are shared. Comment out some parts that we do not yet support.
* SafeHeap: Handle overflows when adding the pointer and the size (#6409)Alon Zakai2024-07-121-11/+33
| | | | | | | | | | | | | E.g. loading 4 bytes from 2^32 - 2 should error: 2 bytes are past the maximum address. Before this PR we added 2^32 - 2 + 4 and overflowed to 2, which we saw as a low and safe address. This PR adds an extra check for an overflow in that add. Also add unreachables after calls to segfault(), which reduces the overhead of the extra check here (the unreachable apparently allows VMs to see that control flow ends, after the segfault() which is truly no-return). Fixes emscripten-core/emscripten#21557
* Do not abbreviate items in element segments (#6737)Thomas Lively2024-07-121-1/+2
| | | | | | | | The full syntax for an expression in an element syntax looks like `(item (ref.null none))`, but we have been printing the abbreviated version, which omits the `(item ...)`. This abbreviation is only valid when the item has only a single instruction, so it is not always correct to use it. Rather than determining whether or not to use the abbreviation on a case-by-case basis, always print the full syntax.
* Memory64Lowering: Handle -1 return value from memory.grow (#6733)Sam Clegg2024-07-111-2/+25
| | | This edge case make the lowering a little more tricky.
* Monomorphize: Use -O3 over -O1 + tweaks (#6732)Alon Zakai2024-07-111-22/+12
| | | | | Eventually we will need to do some tuning of compile time speed, but for now it is going to be simpler to do all the opts, in particular because it makes writing tests simpler.
* [threads] Shared polymorphism for extern conversions (#6730)Thomas Lively2024-07-112-11/+16
| | | | | `any.convert_extern` and `extern.convert_any` return references to shared heap types iff their operands are references to shared heap types.
* [wasm-split] Use a fresh table when reference types are enabled (#6726)Thomas Lively2024-07-111-13/+18
| | | | | | | Rather than trying to trampoline primary-to-secondary calls through an existing table, just create a fresh table for this purpose. This ensures that modifications to the existing tables cannot interfere with primary-to-secondary calls and conversely that loading the secondary module cannot overwrite modifications to the tables.
* [WasmGC] Heap2Local: Optimize RefCast failures (#6727)Alon Zakai2024-07-111-22/+22
| | | | | | | Previously we just did not optimize cases where our escape analysis showed an allocation flowed into a cast that failed. However, after inlining there can be real-world cases where that happens, even in traps-never-happen mode (if the cast is behind a conditional branch), so it seems worth optimizing.
* Heap2Local: Drop RefEq's two arms (#6729)Alon Zakai2024-07-111-3/+3
| | | | | This is a tiny bit more code but it is more consistent with other operations, and it saves work later.
* Monomorphization: Optimize constants (#6711)Alon Zakai2024-07-114-83/+456
| | | | | | | | | | | | | | | | | | | | | | | Previously the pass would monomorphize a call when we were sending more refined types than the target expects. This generalizes the pass to also consider the case where we send a constant in a parameter. To achieve that, this refactors the pass to explicitly define the "call context", which is the code around the call (inputs and outputs) that may end up leading to optimization opportunities when combined with the target function. Also add comments about the overall design + roadmap. The existing test is mostly unmodified, and the diff there is smaller when ignoring whitespace. We do "regress" those tests by adding more local.set operations, as in the refactoring that makes things a lot simpler, that is, to handle the general case of an operand having either a refined type or be a constant, we copy it inside the function, which works either way. This "regression" is only in the testing version of the pass (the normal version runs optimizations, which would remove that extra code). This also enables the pass when GC is disabled. Previously we only handled refined types, so only GC could benefit. Add a test for MVP content specifically to show we operate there as well.
* [WasmGC] Heap2Local: Optimize RefIs and RefTest (#6705)Alon Zakai2024-07-111-1/+62
|
* [StackIR] Allow StackIR to be disabled from the commandline (#6725)Alon Zakai2024-07-102-3/+18
| | | | | | | | | Normally we use it when optimizing (above a certain level). This lets the user prevent it from being used even then. Also add optimization options to wasm-metadce so that this is possible there as well and not just in wasm-opt (this also opens the door to running more passes in metadce, which may be useful later).
* Allow --keepfuncs and --splitfuncs to be use alongside a profile data (#6322)Benjamin Ling2024-07-102-25/+38
| | | | | | | | | There are times after collecting a profile, we wish to manually include specific functions into the primary module. It could be due to non-deterministic profiling or functions for error scenarios (e.g. _trap). This PR helps to unlock this workflow by honoring both the `--keep-funcs` flag as well as the `--profile` flag
* [C API] Add APIs for getting/setting function types, and a CallRef example ↵Alon Zakai2024-07-092-0/+11
| | | | | (#6721) Fixes #6718
* StackIR: Optimize away a drop before an unreachable (#6719)Alon Zakai2024-07-081-1/+38
| | | | | | | | | | | | | | | | | | | | | | | | Anything else right before an unreachable is removed by the main DCE pass anyhow, but because of the structured form of BinaryenIR we can't remove a drop. That is, this is the difference between (i32.eqz (i32.const 42) (unreachable) ) and (drop (call $foo) ) (unreachable) In both cases the unreachable is preceded by something we don't need, but in the latter case it must remain in BinaryenIR for validation. To optimize this, add a rule in StackIR. Fixes #6715
* Rename external conversion instructions (#6716)Jérôme Vouillon2024-07-0822-50/+68
| | | | | | | | | Rename instructions `extern.internalize` into `any.convert_extern` and `extern.externalize` into `extern.convert_any` to follow more closely the spec. This was changed in https://github.com/WebAssembly/gc/issues/432. The legacy name is still accepted in text inputs and in the C and JS APIs.
* [DebugInfo] Add debug info to the values emitted in GlobalStructInference ↵Alon Zakai2024-07-021-15/+23
| | | | | | | | | (#6709) Previously the replacement select got the debug info, but we should also copy it to the values, as often optimizations lead to one of those values remaining by itself. Similar to #6652 in general form.
* ConstantFieldPropagation: Add a variation that picks between 2 values using ↵Alon Zakai2024-06-273-16/+255
| | | | | | | | | | | | | | | | | | | | | | | | | | | RefTest (#6692) CFP focuses on finding when a field always contains a constant, and then replaces a struct.get with that constant. If we find there are two constant values, then in some cases we can still optimize, if we have a way to pick between them. All we have is the struct.get and its reference, so we must use a ref.test: (struct.get $T x (..ref..)) => (select (..constant1..) (..constant2..) (ref.test $U (..ref..)) ) This is valid if, of all the subtypes of $T, those that pass the test have constant1 in that field, and those that fail the test have constant2. For example, a simple case is where $T has two subtypes, $T is never created itself, and each of the two subtypes has a different constant value. This is a somewhat risky operation, as ref.test is not necessarily cheap. To mitigate that, this is a new pass, --cfp-reftest that is not run by default, and also we only optimize when we can use a ref.test on what we think will be a final type (because ref.test on a final type can be faster in VMs).
* [NFC] Add HeapType::getFeatures() (#6707)Alon Zakai2024-06-274-89/+95
|
* [threads] Fuzz shared types in type fuzzer (#6704)Thomas Lively2024-06-264-101/+139
| | | | | | | | | | | | | | Give the type fuzzer the ability to generate shared heap types when the shared-everything feature is enabled. It correctly ensures that shared structs and arrays cannot reference unshared heap types, but that unshared heap types can reference any heap type. Update the main fuzzer so that for the time being it never uses the shared-everything feature when generating additional heap types, so it never generates shared types. We can lift this restriction once the main fuzzer has been updated to properly handle shared types. As a drive-by, fix some logic for subtracting feature sets from each other that is used in this commit.
* [WasmGC] Heap2Local: Optimize RefEq (#6703)Alon Zakai2024-06-261-2/+42
| | | | | If an allocation does not escape, then we can compute ref.eq for it: when compared to itself the result is 1, and when compared to anything else it is 0 (since it did not escape, anything else must be different).
* [threads] Validate shared-polymorphic instructions (#6702)Thomas Lively2024-06-252-72/+68
| | | | Such as `ref.eq`, `i31.get_{s,u}`, and `array.len`. Also validate that struct and array operations work on shared structs and arrays.
* [threads] Validate shared-to-unshared edges in heap types (#6698)Thomas Lively2024-06-252-18/+53
| | | Add spec tests checking validation for structs and arrays.
* Add missing struct/array type checks in binary reader (#6701)Alon Zakai2024-06-251-0/+30
| | | Fixes #6695
* Add a missing binary reading check for BrOn's reference child's type (#6700)Alon Zakai2024-06-251-0/+3
| | | | | | That child must be a reference, as `finalize()` assumes so. To avoid an assertion, error early. Fixes #6696
* [NFC] Remove a minor compile-time optimization in Heap2Local (#6699)Alon Zakai2024-06-251-43/+6
| | | | | | | | We tracked which expressions we saw an allocated struct/array reach, and then quickly exited when another one did (as when two allocations mix, we can optimize neither). It turns out that this helps very little in actual measurements (looks like within noise - likely we are ruling out the un-optimizable cases early otherwise anyhow). Also the complexity it adds is a problem for an improvement I want to make to the pass, so remove it.
* [WasmGC] Add missing ArrayNew variants to Properties::isGenerative (#6691)Alon Zakai2024-06-241-0/+2
| | | Fixes #6690
* Add a proper error for bad select results (#6697)Alon Zakai2024-06-241-1/+5
| | | | | The result cannot be `none` or `unreachable` etc. Fixes #6694
* Add TraceCalls pass (#6619)Marcin Kolny2024-06-214-0/+224
| | | | | | | This pass receives a list of functions to trace, and then wraps them in calls to imports. This can be useful for tracing malloc/free calls, for example, but is generic. Fixes #6548
* wasm2js: Fix the names of temp vars with named reference types (#6689)Alon Zakai2024-06-211-0/+1
| | | | | | We were missing code to mangle such names for JS. Without that, the name of a temp var for the type `(ref $foo)` would end up with `(`, `)` in the name, which is not valid in JS.
* GlobalStructInference: Un-nest struct.news in globals when that is helpful ↵Alon Zakai2024-06-201-62/+220
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | (#6688) If we have (global $g (struct.new $S (i32.const 1) (struct.new $T ..) (ref.func $f) )) then before this PR if we wanted to read the middle field we'd stop, as it is non-constant. However, we can un-nest it, making it constant: (global $g.unnested (struct.new $T ..)) (global $g (struct.new $S (i32.const 1) (global.get $g.unnested) (ref.func $f) )) Now the field is a global.get of an immutable global, which is constant. Using this technique we can handle anything in a struct field, constant or not. The cost of adding a global is likely offset by the benefit of being able to refer to it directly, as that opens up more opportunities later. Concretely, this replaces the constant values we look for in GSI with a variant over constants or expressions (we do still want to group constants, as multiple globals with the same constant field can be treated as a whole). And we note cases where we need to un-nest, and handle those at the end.
* Validate memarg offsets (#6683)Thomas Lively2024-06-201-0/+13
| | | | | For 32-bit memories, the offset value must be in the u32 range. Update the address.wast spec test to assert that a module with an overlarge offset value is invalid rather than malformed.
* [NFC] Add pragma to ignore maybe-uninitialized in strings.cpp (#6686)Thomas Lively2024-06-201-0/+5
| | | This will hopefully fix the build on the coverage builder.
* Validate that names are valid UTF-8 (#6682)Thomas Lively2024-06-195-8/+36
| | | | | | Add an `isUTF8` utility and use it in both the text and binary parsers. Add missing checks for overlong encodings and overlarge code points in our WTF8 reader, which the new utility uses. Re-enable the spec tests that test UTF-8 validation.
* Fix validation of unused LEB128 bits (#6680)Thomas Lively2024-06-191-11/+16
| | | | | The unused bits must be a sign extension of the significant value, but we were previously only validating that unsigned LEBs had their unused bytes set to zero. Re-enable the spec test that checks for proper validation.
* Check malformed mutability on imported globals (#6679)Thomas Lively2024-06-181-0/+3
| | | And re-enable the globals.wast spec test, which checks this.
* Re-enable binary.wast spec test (#6677)Thomas Lively2024-06-183-11/+26
| | | | | | Fix the wast parser to accept IDs on quoted modules, remove tests that are invalidated by the multimemory proposal, and add validation that the total number of variables in a function is less than 2^32 and that the code section is present if there is a non-empty function section.
* [threads] Shared basic heap types (#6667)Thomas Lively2024-06-1913-209/+322
| | | | | | | | | | | Implement binary and text parsing and printing of shared basic heap types and incorporate them into the type hierarchy. To avoid the massive amount of code duplication that would be necessary if we were to add separate enum variants for each of the shared basic heap types, use bit 0 to indicate whether the type is shared and replace `getBasic()` with `getBasic(Unshared)`, which clears that bit. Update all the use sites to record whether the original type was shared and produce shared or unshared output without code duplication.
* [Parser] Fix bug in unreachable fallback logic (#6676)Thomas Lively2024-06-181-13/+18
| | | | | | | | | When popping past an unreachable instruction would lead to popping from an empty stack or popping an incorrect type, we need to avoid popping and produce new Unreachable instructions instead to ensure we parse valid IR. The logic for this was flawed and made the synthetic Unreachable come before the popped unreachable child, which was not correct in the case that that popped unreachable was a branch or other non-trapping instruction. Fix and simplify the logic and re-enable the spec test that uncovered the bug.
* fix(#6671): fix possible stack buffer overflow in gen-s-parser.inc (#6678)mtb2024-06-181-0/+8
| | | | | | The stack buffer overflow is occurring because memcpy(buf, op.data(), op.size()); can write up to op.size() bytes into buf, but buf is only 33 bytes long. If op.size() is greater than 33, this will result in a buffer overflow.
* Reject invalid section IDs (#6675)Thomas Lively2024-06-182-7/+8
| | | | | | Rather than treating them as custom sections. Also fix UB where invalid `Section` enum values could be used as keys in a map. Use the raw `uint8_t` section IDs as keys instead. Re-enable a disabled spec test that was failing because of this bug and UB.
* GlobalStructInference: Optimize globals too (#6674)Alon Zakai2024-06-171-11/+10
| | | | This is achieved by simply replacing the Literal with PossibleConstantValues, which supports both Literals and Globals.
* Fix DataSegment name handling (#6673)Alon Zakai2024-06-171-1/+1
| | | | | | | | | | | | | | | | | | | The code used i instead of index, as in this pseudocode: for i in range(num_names): index = readU32LEB() # index of the data segment to name name = readName() # name to give that segment data[i] = name # XXX 'i' should be 'index' That (funnily enough) happened to always work before since we write names in order. That is, normally given segments A,B,C we'd write then in the names section as A,B,C. Then the reader, which had the bug, would always have i and index identical in value anyhow. But if a wasm producer used different indexes, a problem could happen. To test this, add a binary file that has a reversed name section. Fixes #6672
* wasm2js: Support arbitrary temp variable types (#6661)Alon Zakai2024-06-171-20/+18
| | | | | | | | Previously only basic types were allowed. Generalizing this to arbitrary types means we use a map instead of a vector, which is slower, but I can't measure any noticeable difference. Temp vars are pretty rare, and there are just much slower parts of wasm2js, I think.
* [Parser] Fix error message on required reftype (#6666)Thomas Lively2024-06-141-9/+15
| | | | | | | | | Not all uses of the `reftype` parser handled the fact that it returned a `MaybeResult`. Change its name to `maybeReftype`, add a new `reftype` parser that returns an error if there is no reftype, and update all the use sites. Fixes #6655.
* [Parser] Update requirements for implicit type uses (#6665)Thomas Lively2024-06-141-1/+1
| | | | | | | As an abbreviation, a `typeuse` can be given as just a list of parameters and results, in which case it corresponds to the index of the first function type with the same parameters and results. That function type must also be an MVP function type, i.e. it cannot have a nontrivial rec group, be non-final, or have a declared supertype. The parser did not previously implement all of these rules.