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!
Только зарегистрированные пользователи имеют доступ к сервису!
Для получения аккаунта, обратитесь к администратору.
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
StringLowering converts strings to externs, which makes sense as we
lower stringrefs to imported JS strings. For the reverse transform it is
convenient to just have strings be subtypes of ext, see #7370 - that makes it
simple to switch stringref to externref and vice versa.
This also adds support for internalizing externref strings, which we
represent as anyref literals (basically a hidden subtype of anyref).
The new CMake flag MIMALLOC_STATIC controls this.
mimalloc fixes perf problems, especially on heavily multi-threaded
workloads (many functions, high core count machines) on the musl
allocator, see #5561.
Make it print the diff again. Previously, when there was a formatting
problem, the script would exit the first time it ran `git clang-format`
without printing the results. Update the script to ignore errors on that
first run to ensure it makes it to the part where the results are
printed.
Update HeapTypeInfo, the rec group hashing and equality comparison
utilities, the type canonicalization algorithm, and the TypeBuilder
interface to support `describes` and `descriptor` clauses on heap type
definitions.
Parsing, the binary format, and validation for these clauses is left to
future PRs.
`RefNull` expression now have type `(ref exact null bot)`, allowing them
to be used wherever a nullable exact reference is expected. Update the
fuzzer and fix a few bugs with exactness propagation this uncovers.
Change the type of the field `value` in class `Export` to
`std::variant<Name, HeapType>`, since a type export references a heap
type and not a named component.
GUFA in TNH mode will infer that this will trap:
(func $foo (param $x)
(ref.cast $T (local.get $x))
)
(func $bar
(call $foo (X))
)
If X's type will cause a trap when cast to T, then we infer that the call
will trap, and optimize. However, we were missing a check for the
param being trampled,
(func $foo (param $x)
(local.set $x (Y)) ;; !!!!!!!!!!
(ref.cast $T (local.get $x))
)
Then if Y can be cast, we should not actually trap.
Fix this by just tracking which params are written to. We only look
in the first basic block anyhow, and traverse it in order, so that is
enough.
Fixes#7366
The logic for optimizing ref.casts that are known to succeed did not
account for possible casts to exact null types, leading to it producing
invalid IR. Fix it and add a test.
When optimizing branching casts, RemoveUnusedBrs previously assumed that
if a source reference type was not a subtype of another target reference
type, but the source's heap type was a subtype of the target's heap
type, then it could use ref.as_non_null to convert from the source to
the target. This is no longer true now that we have exact types because
the types may differ in their exactness rather than in their nullness.
Update the check guarding the use of ref.as_non_null to specifically
check that a non-nullable version of the source type is a subtype of the
destination type and add a test.
There are many places where we have to copy a reference type with some
modification, for example to make it refer to a different heap type or
to make it non-nullable or nullable. Previously the only way to do this
was with the `Type` constructor, retrieving and passing in the
unmodified fields of the old type explicitly.
With the addition of exact types, all of these sites have to be updated
to additionally propagate the old type's exactness. To simplify these
call sites and make them more robust against future additions to the
structure of reference types, introduce new APIs to update just a single
part of a reference type at a time.
Some passes leave non-defaultable locals in an invalid state where not
all the gets of the local are structurally dominated by sets. To fix
this, the pass runner automatically calls
`TypeUpdating::handleNonDefaultableLocals` to find the problematic
locals and make them nullable. This function did not previously preserve
exactness in the updated local types. Fix it and add a test.
Update the locations in wasm-type.h and type-updating.cpp responsible
for propagating exactness from references in heap types from the old
types to the new types and add a test. Leave updating other parts of
type-updating to later PRs with further tests that will exercise them.
After calculating the best possible type for a local, LocalSubtyping
then checks to see whether the local can be non-nullable based on
whether all of its gets are dominated by sets. If it cannot be
non-nullable, the new type is adjusted to be nullable. This adjustment
did not previously preserve exactness, causing an assertion that the
optimization improves the type to fail. Fix the adjustment and add a
test.
When optimizing a cast to an exact reference to a bottom type,
OptimizeInstructions previously triggered an assertion that expected the
cast type to be inexact. Fix the assertion and surrounding code to be
more robust to the presence of exact reference types and add a test.
Update the finalization of all instructions whose types (or sent types)
depend on their operand reference types to handle exact references
correctly. Specifically, update `ref.as_non_null`, `br_on_null`,
`br_on_non_null`, `br_on_cast`, and `br_on_cast_fail`. Also add TODOs on
all instructions that allocate new heap objects to remind us to make
their types exact in the future.
V8 does not yet support custom descriptors, so update all fuzz handlers
that use it to avoid running when the feature is enabled. Since running
V8 is important, though, disable the feature most of the time, just like
we do for shared-everything.
The binary format for casts needs to be extended to support exact
references. In particular, add new opcodes for `ref.test` and `ref.cast`
that take reference type immediates instead of heap type immediates. Use
two more bits in the flags immediate of `br_on_cast` and
`br_on_cast_fail` to encode the source and destination exactness.
This patch makes MergeSimilarFunctions do a return_call when the module
has tail-call enabled. This is not merely an optimization, but is
crucial for correctness when optimizing wasm modules produced by GHC
that relies on tail-call to do control flow transfers. Previously, -Oz
would break tail-call enabled modules by making the control stack grow
where it shouldn't.
For `struct.new`, `array.new`, `ref.func`, `ref.i31`, `cont.new`, and
`cont.bind`, check in the validator that the result type is a
non-nullable reference. This ensures that we have the most precise
possible type information for these instructions. The generic stale type
checker does not check this because finalizing these expressions does
not change their types.
The repeated "merge new content in, and filter based on the location it
arrives to" operation is non-commutative, and it turns out there was a
corner case we missed. Filtering before and after is enough to make us
return the same result with the ordering swapped.
This does make GUFA 5% slower, unfortunately. But this does result
in better code in some cases aside from fixing the nondeterminism.
Also add clearer comments about the problem here. We likely need to
just make the order of operations here deterministic (though a downside
of that is that the fuzzer wouldn't find bugs like this, and it would be
slower).