IF YOU WOULD LIKE TO GET AN ACCOUNT, please write an
email to Administrator. User accounts are meant only to access repo
and report issues and/or generate pull requests.
This is a purpose-specific Git hosting for
BaseALT
projects. Thank you for your understanding!
Только зарегистрированные пользователи имеют доступ к сервису!
Для получения аккаунта, обратитесь к администратору.
Previously the constructor ran the start method and other initialization. Doing
that in an explicit function that the user calls makes it possible to do things in
the middle. The specific thing I would like to do in the middle is have a function
to change the interpreter instance's mode to "reject as nonconstant relaxed SIMD",
but I've wanted this in the past too, and worked around it - seems best to just
fix it.
Adding more flags to the constructor is another option, but there are already
several, and more in the parent classes, and several levels of inheritance through
which all such options must be forwarded, which is annoying.
TypeRefiningGUFA refines struct types based on the types that flow into fields,
and looks past the immediate types in the IR. As a result, it can require
casts when we end up storing something that appears not-sufficiently-
refined to wasm validation rules, in ways that cannot occur with normal
TypeRefining.
The specific problem that can happen is that casts are disallowed in
globals, so we must be careful to not refine too much there.
The random number generator adds into `xorFactor` in various places.
This variable was previously signed, so overflows from these adds were
UB. Make it unsigned to avoid UB.
Update `TypeBuilder::build` to return a vector of `HeapTypeDef`.
Although `HeapTypeDef` is implicitly convertible to `HeapType`,
containers of `HeapTypeDef` are not implicitly convertible to containers
of `HeapType`, so this change requires several other utilities and
passes to start using `HeapTypeDef` directly and transitively.
`printTypeOrName`, used to print types for BINARYEN_PRINT_FULL and a few
other niche use cases, previously had bespoke printing for references
that did not follow the standard format. To improve the output and
reduce the number of ways we print types, change it to use the standard
printing utility.
Now that we have exact heap types, non-abstract heap types no longer
correspond 1:1 with heap type definitions. We previously used a single
type, `HeapType`, to represent both heap types and heap type
definitions. Now that `HeapType` can represent multiple heap types
corresponding to the same definition, there is a new class of potential
bugs in which code that expects `HeapType` values to map 1:1 with heap
type definitions observes both an exact and inexact heap type for the
same definition.
To eliminate this class of bugs, introduce a new type, `HeapTypeDef`,
whose values do correspond 1:1 with heap type definitions. `HeapTypeDef`
is a subclass of `HeapType`, so it supports all the same functionality,
but it cannot represent exact heap types because its constructor clears
the exact bit.
As an initial proof-of-concept, use HeapTypeDef in the type printing
machinery, which only cares about heap type names corresponding to heap
type definitions. Future PRs will use HeapTypeDef in more places.
Rename the function in anticipation of exact heap types appearing in the
IR. When an expression like `StructNew` has an exact heap type, the
`exact` does not appear in `struct.new $foo`. In this case `$foo` is not
the full heap type, but rather than name of the heap type definition.
This variation of TypeRefining uses GUFA to determine what types to refine
struct fields to. GUFA does a (slow) whole-program analysis which can infer
things the normal pass cannot, e.g. refinements that contain cycles through
things like locals or globals.
This is mainly a proof of concept, as it is pretty slow to compute GUFA just
for this, and while I see improvements on real-world code, they are minor.
If we find that the benefits here are worth it, a larger refactoring could
do this optimization in the existing GUFA pass (which already does the
computation of the graph anyhow).
The pass refines cast types of br_on, but that will un-refine the sent
type of a br_on_cast_fail - a more refined cast type means more things
fail it, so more things are sent. We need to avoid that.
Rather than encode to WTF8 and re-encode, instead make the unescaping logic go
from UTF8 straight to WTF16. That makes it simpler and more efficient.
Make the JSON parser get a parameter for which encoding to use for strings, so
we can use ascii in old places.
With dynamic linking, build and link mimalloc's dynamic library, and include it
in the installation (this also brings along the headers and CMake files, but it
seemed like more trouble than it was worth to try to manually install just the
library or remove the extras).
The static build remains the same.
Remove the restriction that mimalloc can only be linked into a static-lib build.
Also fix `with(Inexact)` to no longer strip sharedness from basic heap
types. Add exact heap types, defined subtypes, and exact subtypes to the
gtest for heap type relations.
When the last instruction of the outlined sequence is unreachable, we
need to insert an unreachable instruction immediately after the call to
the outlined function. This maintains the unreachable type in the
original scope of the outlined sequence.
The custom descriptors proposal has moved exactness from reference types
to defined (but not abstract) heap types. Since we only use a bit in the
heap type representation to represent sharedness for abstract heap
types, we can conveniently reuse the same bit to represent exactness for
heap types.
Implement basic support for representing exact heap types and taking
them into account in canonicalization. Also ensure that other operations
like getting the rec group of a heap type or looking up its structure
work properly on exact heap types.
Globals that refer to globals lead to more work. This work cannot be
infinite, as globals only refer to previous ones, but this can end up as
exponential time, so this is actually important to optimize here.
For exponential time, it is enough to have a chain of these:
(global $global$N+1 (ref $A) (struct.new $A
(global.get $global$N)
(global.get $global$N)
))
That is, two references from each global to its predecessor, causing
us to double the work each time we scan back.
Fixes#7405 (where the above pattern appears)
Now that we aren't supporting exact reference types, we no longer need
to leave bit 2 free for use by the Type representation. Shift the basic
HeapType representations down to start at bit 2 instead of bit 3.
We decided that Custom Descriptors should introduce exact heap types
rather than exact reference types. Although these new features are very
similar, the APIs we need to change for them are completely different.
One option would have been to keep the existing exact reference type
implementation while additionally implementing exact heap types, but
there are not enough free bits in the type implementation to have both
at once without increasing the alignment of HeapTypeInfo allocations.
Portably increasing the alignment is annoying enough that it's easier to
just eagerly remove exact reference types to free up the bit for use
with exact heap types.
Fully or partially revert the following PRs:
- #7371
- #7365
- #7360
- #7357
- #7356
- #7355
- #7354
- #7353
- #7347
- #7342
- #7328
Keep the new `.with(...)` Type APIs and the relevant parts of the type
relations gtest that were introduced as part of the reverted work.
In the interest of improved test readability, moved the return part of
the FilterBranches test into its own test. Also condensed the test to
remove the unnecessary consts.
While determining whether repeat sequences of instructions are
candidates for outlining, remove sequences that overlap, giving weight
to sequences that are longer and appear more frequently.
This converts imported string constants into string.const, and imported
string instructions into string.* expressions. After this pass they are
represented using stringref and we can optimize them fully (e.g.
precomputing a string.concat of two constants). Typically a user would
later lower then back down using StringLowering.
This pass allows users to avoid emitting stringref directly, which means
they are emitting standard wasm which can run in VMs, leaving wasm-opt
entirely optional.
Also refactor a few shared constants with StringLowering into a helper file.
Left as TODOs: contents of the strings custom section, and casts (see
comments in source).
Fixes most of #7370
Our tools all stated that if -o is not provided, we write to stdout by
default. But that is not true - we do nothing in that case. I believe the
rationale is that we write text to stdout by default in say wasm2js, but
for wasm-opt etc. we don't want to write binary to stdout (as that is
dangerous).
The length macro used in a type test in type-builder.cpp was causing
extremely long compile times in some compilers. Use a lambda instead to
fix it. This makes the error messages less useful when a test fails, but
under normal circumstances the test should not be failing, so this is a
good trade off.
Fixes#7383.
To ensure soundness, there are very particular rules about how described
and descriptor type declarations must relate to one another and their
supertypes. Implement and test these rules.
Implement text and binary parsing as well as binary writing for
`descriptor` and `describes` clauses, as specified in the
custom-descriptors proposal. Also simplify some neighboring code dealing
with shared types as a drive-by.
We recently started updating RefFunc types in I64ToI32Lowering to ensure
that their types matched the updated types of their functions. But the
way we updated the types of RefFunc expressions and Functions were not
the same. When updating Functions that return i64, we replace the result
type with i32 and use a global to propagate the remaining bits to the
caller. Previously when updating RefFunc result types, we would instead
split i64s into pairs of i32s, depending on multivalue to lower the
type. Update the logic for updating RefFunc results to match the
existing logic for updating Functions.
As a holdout from before GC was implemented, we previously allowed
RefFunc expressions to have type `funcref` rather than a specific
signature type matching that of the referenced function. Remove this
allowance and start requiring the types to be correct and precise to
eliminate the possibility of stale types inhibiting (or invalidating!)
optimizations.
Update various older passes to update the types of RefFuncs, including
those in tables, to keep their output passing validation. Also update
the kitchen sink example test to construct RefFunc expressions with the
correct type via the C API.
Since mimalloc is linked statically into the Binaryen tools, none of its
files need to be installed with Binaryen.
Also use CMAKE_SYSTEM_NAME instead of LINUX, as the latter was
introduced in CMake 3.25