summaryrefslogtreecommitdiff
path: root/src
Commit message (Collapse)AuthorAgeFilesLines
...
* Followup to #3451 after feedback (#3457)Alon Zakai2020-12-181-1/+1
| | | | The validation code can be further simplified after adding castType, and we were missing a test for the type that flows out of br_on_cast.
* finalize: there can only ever be a single initializer function. NFC. (#3452)Sam Clegg2020-12-183-13/+8
|
* [module-splitting] Fix a crash when a function is exported twice (#3455)Thomas Lively2020-12-171-0/+4
| | | | | | | | | `ModuleSplitter::thunkExportedSecondaryFunctions` creates a thunk for each secondary function that needs to be exported from the main module. Previously, if a secondary function was exported twice, this code would try to create two thunks for it rather than just making one thunk and exporting it twice. This caused a fatal error because the second thunk had the same name as the first thunk and therefore could not be added to the module. This PR fixes the issue by creating no more than one thunk per function.
* [GC] Add br_on_cast (#3451)Alon Zakai2020-12-1715-42/+154
| | | | | | | | | | | | | | | | 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.
* [wasm-split] Add an --initial-table option (#3454)Thomas Lively2020-12-171-0/+38
| | | | | | | | Adds an option to wasm-split to allow the user to specify the initial table size for both instrumenting and splitting use cases. In the short term this will be used in Emscripten SPLIT_MODULE + dynamic linking workflow to ensure that the expected table size baked into the JS works for both the instrumented and the primary split modules. In the longer term this may be replaced with a more elegant mechanism for making the JS works in both cases.
* Refactor printing code so that printing Expressions always works (#3450)Alon Zakai2020-12-1724-159/+96
| | | | | | | | This avoids needing to add include wasm-printing if a file doesn't already have it. To achieve that, add the std::ostream hooks in wasm.h, and also use them when possible, removing the need for the special WasmPrinter object. Also stop printing in "full" (print types on each line) in error messages by default. The user can still get that, as always, using BINARYEN_PRINT_FULL=1 in the env.
* Add comment a followup to #3424. NFC. (#3449)Sam Clegg2020-12-161-0/+4
|
* More refactoring of branch utility code to remove boilerplate. (#3448)Alon Zakai2020-12-165-158/+83
| | | | | | | | | | | | | | | | | | | This is almost NFC, but it may emit slightly different IR in cases that don't matter much. Specifically, (block (result i32) ;; can also be unreachable (unreachable) (i32.const 1) ) That can be finalized to have type unreachable or i32, as both are valid. After this PR we should consistently do the same thing in all places. (Either option would be ok - we prefer to keep the type if there is one.) In practice, DCE will remove all the dead code anyhow, leaving no difference to matter. However, the IR is different without DCE, and that may be noticeable in an unoptimized build - but it should have no effect on behavior, just on the binary.
* Fix wasm-split name collision bug (#3447)Thomas Lively2020-12-161-3/+16
| | | | | | | | | During module splitting, a map is constructed from internal names to their corresponding export names. This code previously did not take into account the fact that the same internal name may be used by different kinds of entities (e.g. a table and a memory may have the same internal name), which resulted in the secondary module incorrectly using the same import name for all of the entities that shared an internal name. This PR fixes the problem by including the ExternalKind of the entity in the keys of the export map.
* [GC] Fully implement RTT semantics (#3441)Alon Zakai2020-12-157-36/+227
| | | | | | | | | | | | | | This adds info to RTT literals so that they can represent the chain of rtt.canon/sub commands that generated them, and it adds an internal RTT for each GC allocation (array or struct). The approach taken is to simply store the full chain of rtt.sub types that led to each literal. This is not efficient, but it is simple and seems sufficient for the semantics described in the GC MVP doc - specifically, only the types matter, in that repeated executions of rtt.canon/sub on the same inputs yield equal outputs. This PR fixes a bunch of minor issues regarding that, enough to allow testing of the optimization and execution of ref.test/cast.
* Use enums for mutability and nullability (#3443)Thomas Lively2020-12-147-29/+42
| | | | | Previously we were using bools for both of these concepts, but using enums makes the code clearer. In particular, the PR removes many instances of `/*nullability=*/ true`.
* Fixed wasm-emscripten-finalize AsmConstWalker not handling 64-bit pointers ↵Wouter van Oortmerssen2020-12-141-6/+15
| | | | | (#3431) Also improved the LLD test scripts to accomodate 64-bit tests.
* [StackCheck] Handle colliding names (#3390)Alon Zakai2020-12-141-31/+30
| | | | | Add Names::getValidGlobalName calls to ensure we don't collide with an existing name. Fixes emscripten-core/emscripten#12834
* Refactor BranchUtils to avoid boilerplate. NFC (#3442)Alon Zakai2020-12-143-143/+114
| | | This should make it easier to add br_on_cast for example.
* [wasm-reduce] Improve support for reducing on text files (#3437)Alon Zakai2020-12-141-4/+8
| | | | Passing --detect-features there doesn't work (as there is no feature section).
* Prototype SIMD instructions implemented in LLVM (#3440)Thomas Lively2020-12-1112-35/+267
| | | | | | - i64x2.eq (https://github.com/WebAssembly/simd/pull/381) - i64x2 widens (https://github.com/WebAssembly/simd/pull/290) - i64x2.bitmask (https://github.com/WebAssembly/simd/pull/368) - signselect ops (https://github.com/WebAssembly/simd/pull/124)
* [GC] Fix Array optimization issues (#3438)Alon Zakai2020-12-112-13/+38
| | | | | | | | | | | Precompute still tried to precompute a reference because the check was not in the topmost place. Also we truncated i8/i16 values, but did not extend them properly. That was also an issue with structs. The new test replaces the old one by moving from -O1 to -Oz (which runs more opts, and would have noticed this earlier), and adds array operations too, including sign extends.
* [GC] Add ref.test and ref.cast (#3439)Alon Zakai2020-12-1112-45/+103
| | | | This adds enough to read and write them and test that, but leaves interpreter support for later.
* TypeBuilder (#3418)Thomas Lively2020-12-102-8/+352
| | | | | | | | | | | | | | | | | Introduce TypeBuilder, a utility for constructing heap types in terms of other heap types that may have not yet been defined. Internally, it works by creating HeapTypes backed by mutable HeapTypeInfos owned by the TypeBuilder. That lets the TypeBuilder create temporary Types that can refer to the TypeBuilder-managed HeapTypes. Those temporary Types can in turn be used to initialize the very HeapTypes they refer to. Since the TypeBuilder-managed HeapTypes are only valid for the lifetime of their TypeBuilder, there is a canonicalization step that converts them into globally interned canonical HeapTypes. This PR allows HeapTypes to be built in terms of as of yet undefined HeapTypes, but it currently errors out in the presence of recursive types. Supporting recursive types will require further work to canonicalize them into finite, acyclic representations. Currently any attempt to compare, print, or otherwise manipulate recursive types would infinitely recurse.
* [GC] Add Array operations (#3436)Alon Zakai2020-12-1017-174/+469
| | | | | | | | | | | | | | 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.
* Read and write data segments names in names section (#3435)Sam Clegg2020-12-094-1/+52
|
* Small RTT cleanups (#3434)Thomas Lively2020-12-092-11/+7
|
* [GC] Add struct.new and start to test interesting execution (#3433)Alon Zakai2020-12-0915-34/+172
| | | | | | | | | | | | | | 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-0818-84/+205
| | | | | | | | | | | | | | | | 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.
* Intern HeapTypes and clean up types code (#3428)Thomas Lively2020-12-074-524/+633
| | | | | | | | | Interns HeapTypes using the same patterns and utilities already used to intern Types. This allows HeapTypes to efficiently be compared for equality and hashed, which may be important for very large struct types in the future. This change also has the benefit of increasing symmetry between the APIs of Type and HeapType, which will make the developer experience more consistent. Finally, this change will make TypeBuilder (#3418) much simpler because it will no longer have to introduce TypeInfo variants to refer to HeapTypes indirectly.
* [GC] Add struct.set (#3430)Alon Zakai2020-12-0714-45/+106
| | | | | | | | | | 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-0720-104/+261
| | | | | | | | | | | | | | | | | | | | 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).
* Make NUM_PARAMS in FuncCastEmulation a configuration option (#3411)Dexter Chua2020-12-071-16/+18
| | | | | | Compiling scipy requires a `NUM_PARAMS` of at least 61 (!) https://github.com/iodide-project/pyodide patches emsdk in order to compile, which this PR can avoid.
* [GC] Support reading and writing of Struct and Array types (#3423)Alon Zakai2020-12-057-118/+246
| | | | | | This adds support in the text and binary format handling, which allows us to have a full test of reading and writing the types. This also adds a "name" field to struct fields, which the text format supports.
* wasm-emscripten-finalize: Support PIC + threads (#3427)Sam Clegg2020-12-041-4/+12
| | | | | | | | | | | With PIC + threads the offset of passive segments is not constant but relative to `__memory_base`. When trying to find passive segment offset based on the target of the `memory.init` instruction we need to consider this possibility as well as the regular constant one. For the llvm side of this that generates the calls to memory.init see: https://reviews.llvm.org/D92620
* Remove legacy DYNAMICTOP_PTR support from SafeHeap (#3425)Sam Clegg2020-12-041-6/+1
|
* [GC] Refactor Vacuum pass. NFC. (#3421)Alon Zakai2020-12-041-134/+65
| | | | | | This is shorter by using ChildIterator, so it's more general. The greater generality should not be noticeable atm, but it will allow this pass to just work on GC instructions once we have them (without this, in my testing the optimizer does not do very well on GC).
* Don't apply SafeHeap to wasm start function (#3424)Sam Clegg2020-12-041-2/+8
| | | | | | In relocable code (MAIN/SIDE modules) we use the start function to run `__wasm_init_memory` which loads the data segments into place. We can't call get_sbkr pointer during that function because the sbrk pointer itself lives in static data segment.
* [Types] Refactor signature collection to heap type collection. NFC. (#3420)Alon Zakai2020-12-036-98/+156
| | | | | | | | | This will allow writing GC types in the future, which are non-signature heap types. To allow this PR to work, it adds operator< for HeapType so that it can be used in the data structures that collect uses. Drive-by fix of a weird hack with sending a Name* in Print.
* [NFC] Rename BasicID to BasicType (#3419)Thomas Lively2020-12-034-14/+15
| | | | This name is more descriptive and paves the way toward interning HeapTypes as well, with an analogous BasicHeapType.
* [Types] Return const& for HeapTypes and their Structs and Arrays. NFC (#3417)Alon Zakai2020-12-032-10/+20
| | | | | | | | | I am starting to write lines like curr->value->type.getHeapType().getStruct().fields[curr->index].type and it scares me to think that there may be copies going on there. The issue is that Types are interned, but HeapTypes and their components are not.
* [DWARF] Properly handle LLVM's new tombstone values (#3416)Alon Zakai2020-12-021-4/+15
| | | | | See https://reviews.llvm.org/D91803 - there are now -1 or -2 in places that mark something that the linker removed as not existing/not relevant. We should ignore those like we ignore 0s there.
* [OptimizeInstructions] Fix fuzz bug with shifts (#3376)Alon Zakai2020-12-021-8/+14
| | | | | | | | | | | | | | | | | | | | | | | The code there looks for a "sign-extend": (x << a) >> b where the right shift is signed. If a = b = 24 for example then that is a sign extend of an 8-bit value (it works by shifting the 8-bit value's sign bit to the position of the 32-bit value's sign bit, then shifting all the way back, which fills everything above 8 bits with the sign bit). The tricky thing is that in some cases we can handle a != b - but we forgot a place to check that. Specifically, a repeated sign-extend is not necessary, but if the outer one has extra shifts, we can't do it. This is annoyingly complex code, but for purposes of reviewing this PR, you can see (unless I messed up) that the only change is to ensure that when we look for a repeated sign extend, then we only optimize that case when there are no extra shifts. And a repeated sign-extend is obviously ok to remove, (((x << a) >> a) << a) >> a => (x << a) >> a This is an ancient bug, showing how hard it can be to find certain patterns either by fuzzing or in the real world... Fixes #3362
* [OptimizeInstructions] Fix a fuzz bug with getting the shifts of an ↵Alon Zakai2020-12-021-0/+8
| | | | unreachable (#3413)
* [GC types] Refactoring to allow future heap type parsing. NFC (#3409)Alon Zakai2020-12-025-110/+105
| | | | | | | | | | Defined types in wasm are really one of the "heap types": a signature type, or (with GC) a struct or an array type. This refactors the binary and text parsers to load the defined types into an array of heap types, so that we can start to parse GC types. This replaces the existing array of signature types (which could not support a struct or an array). Locally this PR can parse and print as text simple GC types. For that it was necessary to also fix Type::getFeatures for GC.
* [wasm-split] Record checksums in profiles (#3412)Thomas Lively2020-12-021-10/+24
| | | | | | | | | | | Calculate a checksum of the original uninstrumented module and emit it as part of the profile data. When reading the profile, compare the checksum it contains to the checksum of the module that is being split. Error out if the module being split is not the same as the module that was originally instrumented. Also fixes a bug in how the profile data was being read. When `char` is signed, bytes read from the profile were being incorrectly sign extended. We had not noticed this before because the profiles we have tested have contained only small-valued counts.
* [module-splitting] Allow splitting with non-const table offsets (#3408)Thomas Lively2020-12-012-86/+189
| | | | | | | | | | Extend the splitting logic to handle splitting modules with a single table segment with a non-const offset. In this situation the placeholder function names are interpreted as offsets from the table base global rather than absolute indices into the table. Since addition is not allowed in segment offset expressions, the secondary module's segment must start at the same place as the first table's segment. That means that some primary functions must be duplicated in the secondary segment to fill any gaps. They are exported and imported as necessary.
* [Printing] Print type names where possible. (#3410)Alon Zakai2020-12-011-4/+43
| | | | | | | | | | | | For a nested type, we used to print e.g. (param $x (ref (func (param i32)))) Instead of expanding the full type inline, which can get long for a deeply nested type, print a name when running the Print pass. In this example that would be something like (param $x (ref $i32_=>_none))
* [OptimizeInstructions] Fix a fuzz bug with comparing signed and unsigned ↵Alon Zakai2020-12-011-38/+41
| | | | values (#3399)
* [NFC] Clean up sign/zero extension code in properties.h (#3404)Thomas Lively2020-11-251-48/+38
| | | | Use matchers and more descriptive variable names to clarify the intent of the functions for finding and inspecting sign extension patterns.
* [TypedFunctionReferences] Enable call_ref in fuzzer, and fix minor misc fuzz ↵Alon Zakai2020-11-2513-51/+153
| | | | | | | | | | | | | | | | | | | | bugs (#3401) * Count signatures in tuple locals. * Count nested signature types (confirming @aheejin was right, that was missing). * Inlining was using the wrong type. * OptimizeInstructions should return -1 for unhandled types, not error. * The fuzzer should check for ref types as well, not just typed function references, similar to what GC does. * The fuzzer now creates a function if it has no other option for creating a constant expression of a function type, then does a ref.func of that. * Handle unreachability in call_ref binary reading. * S-expression parsing fixes in more places, and add a tiny fuzzer for it. * Switch fuzzer test to just have the metrics, and not print all the fuzz output which changes a lot. Also fix noprint handling which only worked on binaries before. * Fix Properties::getLiteral() to use the specific function type properly, and make Literal's function constructor require that, to prevent future bugs. * Turn all input types into nullable types, for now.
* [wasm-type][NFC] Encapsulate type canonicalization in a TypeStore (#3403)Thomas Lively2020-11-251-88/+96
| | | | | | | Although there is only one "type store" right now, a subsequent PR will add a new "TypeBuilder" class that manages its own universe of temporary types. Rather than duplicate all the logic behind type creation and canonicalization, it makes more sense to encapsulate that logic in a class that TypeBuilder will be able to reuse.
* [wasm-split] Read and use profiles (#3400)Thomas Lively2020-11-242-2/+59
| | | | | | Read the profiles produced by wasm-split's instrumentation to guide splitting. In this initial implementation, all functions that the profile shows to have been called are kept in the initial module. In the future, users may be able to tune this so that functions that are run later will still be split out.
* [TypedFunctionReferences] Implement call_ref (#3396)Alon Zakai2020-11-2427-157/+450
| | | | | | | | 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.
* Let EnforceStackLimits have pointers to Globals (NFC) (#3397)Heejin Ahn2020-11-241-5/+6
| | | | These can be simply raw pointers, given that they are stored in modules using `unique_ptr`s.