Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bump to version 117 #101

Merged
merged 663 commits into from
Jul 12, 2024
Merged

Bump to version 117 #101

merged 663 commits into from
Jul 12, 2024

Conversation

radekdoulik
Copy link
Member

No description provided.

tlively and others added 30 commits October 25, 2023 00:16
These missing includes were not a problem in our standard build configuration,
but were breaking other build configurations.
Simplify the monotone analyzer by replacing all the state it used to store in
`BlockState` with a simple vector of lattice elements. Use simple indices to
refer to both blocks and their associated states in the vector. Remove the
ability for transfer functions to control the initial enqueued order of basic
blocks since that was a leaky abstraction. Replace the worklist with a
UniqueDeferredQueue since that has generally proven to be more efficient in
smiilarly contexts, and more importantly, it has a nicer API. Make miscellaneous
simplifications to other code as well.

Delete a few unit tests that exposed the order in which blocks were analyzed
because they printed intermediate results. These tests should be replaced with
tests of analyses' public APIs in the future.
… lattice (WebAssembly#6035)

In general, the operation of taking the least upper bound of two lattice
elements may depend on some state stored in the lattice object rather than in
the elements themselves. To avoid forcing the elements to be larger and more
complicated in that case (by storing a parent pointer back to the lattice), move
the least upper bound operation to make it a method of the lattice rather than
the lattice element. This is also more consistent with where we put e.g. the
`compare` method.

While we are at it, rename `makeLeastUpperBound` to `join`, which is much
shorter and nicer. Usually we avoid using esoteric mathematical jargon like
this, but "join" as a normal verb actually describes the operation nicely, so I
think it is ok in this case.
This is a lattice with two elements: `false` is bottom and `true` is top.

Add a new gtest file for testing lattices.
Implement a generic lattice template for integral types ordered by `<`.
…y#6038)

The FullLattice concept extends the base Lattice with `getTop` and `meet`
operations. The `Inverted` lattice uses these operations to reverse the order of
an arbitrary full lattice, for example to create a lattice of integers ordered
by `>` rather than by `<`.
Given a type `T`, `Flat<T>` is the lattice where none of the values of `T` are
comparable except with themselves, but they are all greater than a common bottom
element not in `T` and less than a common top element also not in `T`.
Followup to WebAssembly#6048, we did not handle nondefaultable tuples because of this.
This lattice "lifts" another lattice by inserting a new bottom element
underneath it.
Apparently the version of node on the Alpine runner was updated and no longer
recognizes the --experimental-wasm-threads option. Delete this option out of the
test that was using it.
…y#6053)

Closed-world mode allows function types to escape if they are on exported functions,
because that has been possible since wasm MVP and cannot be avoided. But we need to
also allow all types in those type's rec groups as well. Consider this case:

(module
 (rec
  (type $0 (func))
  (type $1 (func))
 )
 (func "0" (type $0)
  (nop)
 )
 (func "1" (type $1)
  (nop)
 )
)

The two exported functions make the two types public, so this module validates in
closed world mode. Now imagine that metadce removes one export:

(module
 (rec
  (type $0 (func))
  (type $1 (func))
 )
 (func "0" (type $0)
  (nop)
 )
 ;; The export "1" is gone.
)

Before this PR that no longer validates, because it only marks the type $0 as public.
But when a type is public that makes its entire rec group public, so $1 is errored on.

To fix that, this PR allows all types in a rec group of an exported function's type, which
makes that last module validate.
Implement new `RandomLattice` and `RandomFullLattice` utilities that are
lattices randomly created from other lattices. By recursively using themselves
as the parameter lattices for lattices like `Inverted` and `Lift`, these random
lattices can become arbitrarily nested.

Decouple the checking of lattice properties from the checking of transfer
function properties by creating a new, standalone `checkLatticeProperties`
function.
…mbly#6051)

If there are newlines in the list, then we split using them in a simple manner
(that does not take into account nesting of any other delimiters).

Fixes WebAssembly#6047
Fixes WebAssembly#5271
…ly#6056)

Since these methods, which operate on lattice elements, moved to the lattice
types, it no longer makes much sense for their parameters to be called `self`
and `other`. Rename them to `joinee` and `joiner` for joins and `meetee` and
`meeter` for meets.
The elements of `Array<L, N>` lattice are arrays of length `N` of elements of
`L`, compared pairwise with each other. This lattice is a concrete
implementation of what would be written L^N with pen and paper.
The vector lattice is nearly identical to the array lattice, except that the
size of the elements is specified at runtime when the lattice object is created
rather than at compile time. The code and tests are largely copy-pasted and
fixed up from the array implementation, but there are a couple differences.
First, initializing vector elements does not need the template magic used to
initialize array elements. Second, the obvious implementations of join and meet
do not work for vectors of bools because they might be specialized to be bit
vectors, so we need workarounds for that particular case.
This lattice combines any number of other lattices into a single lattice whose
elements are tuples of elements of the other lattices. This will be one of the
most important lattices in the analysis framework because it will be used to
combine information about different parts of the program, e.g. locals and the
value stack, into a single lattice.
…ly#6061)

In particular, if the body just calls another "once" function, then we can
skip the early-exit logic.
Add a lattice that is a thin wrapper around `wasm::Type` giving it the interface
of a lattice. As usual, `Type::unreachable` is the bottom element, but unlike in
the underlying API, we uniformly treat `Type::none` as the top type so that we
have a proper lattice.
Many of the lattice tests were essentially copy-pasted from one lattice to the
next because they all tested isomorphic subsets of the various lattices,
specifically in the shape of a diamond. Refactor the code so that all lattices
that have tests of this shape use the same utility test functions.
We handled references but not tuples in one place.
…4 argument (WebAssembly#6074)

In wasm64, function pointers are 64-bit like all pointers.

fixes WebAssembly#6073
…6072)

Previously the fuzzer never added gets or sets of globals from initial content. That was
an oversight, I'm pretty sure - it's just that the code that sets up the lists from which we
pick globals for gets and sets was in another place. That is, any globals in the initial
content file were never used in new random code the fuzzer generates (only new
globals the fuzzer generated were used there).

This PR allows us to use those globals, but also ignores them with some probability,
to avoid breaking patterns like "once" globals (that we want to only be used from
initial content, at least much of the time).

Also simplify the code here: we don't need isInvalidGlobal just to handle the hang
limit global, which is already handled by not being added to the lists we pick names
from anyhow.
…bly#6067)

The analysis framework stores a separate lattice element for each basic block
being analyzed to represent the program state at the beginning of the block.
However, in many analyses a significant portion of program state is not
flow-sensitive, so does not benefit from having a separate copy per block. For
example, an analysis might track constraints on the types of locals that do not
vary across blocks, so it really only needs a single copy of the constrains for
each local. It would be correct to simply duplicate the state across blocks
anyway, but it would not be efficient.

To make it possible to share a single copy of a lattice element across basic
blocks, introduce a `Shared<L>` lattice. Mathematically, this lattice represents
a single ascending chain in the underlying lattice and its elements are ordered
according to sequence numbers corresponding to positions in that chain.
Concretely, though, the `Shared<L>` lattice only ever materializes a single,
monotonically increasing element of `L` and all of its elements provide access
to that shared underlying element.

`Shared<L>` will let us get the benefits of having mutable shared state in the
concrete implementation of analyses without losing the benefits of keeping those
analyses expressible purely in terms of the monotone framework.
Remove the ability to represent the top element of the stack lattice since it
isn't necessary. Also simplify the element type to be a simple vector, update
the lattice method implementations to be more consistent with implementations in
other lattices, and make the tests more consistent with the tests for other
lattices.
…mbly#6071)

Previously, modifying a single vector element of a `Shared<Vector>` element
required materializing a full vector to do the join. When there is just a single
element to update, materializing all the other elements with bottom value is
useless work. Add a `Vector<L>::SingletonElement` utility that represents but
does not materialize a vector with a single non-bottom element and allow it to
be passed to `Vector<L>::join`. Also update `Shared` and `Inverted` so that
`SingletonElement` joins still work on vectors wrapped in those other lattices.
…ly#6077)

Combine the `transfer` and `getDependents` methods of a transfer function so
that a transfer function only has to implement `transfer`, which now returns a
range of basic blocks that may need to be re-analyzed.

To make it easier to implement the returned basic block range, change the
requirement so that it provides iterators to `const BasicBlock*` rather than
`BasicBlock`. This allows us to entirely remove cfg-impl.h.
tlively and others added 23 commits February 22, 2024 09:09
Remove the layer of abstraction sitting between the parser and the lexer now
that the lexer has an interface the parser can use directly.
Replace the general `peek` method that returned a `Token` with specific peek
methods that look for (but do not consume) specific kinds of tokens. This change
is a prerequisite for simplifying the lexer implementation by removing `Token`
entirely.
)

JS engines print i31ref as just a number, so we need a small regex to
standardize the representation (similar to what we do for funcrefs on
the code above).

On the C++ side, make it actually print the i31ref rather than treat it
like a generic reference (for whom we only print "object"). To do that
we must unwrap an externalized i31 as necessary, and add a case for
i31 in the printing logic.

Also move that printing logic to its own function, as it was starting to
get quite long.
One problem was that spec testcases had exports with names that are not
valid to write as JS exports.name. For example an export with a - in the
name would end up as exports.foo-bar etc. Since WebAssembly#6310 that is fixed as
we do not emit such JS (we use the generic fuzz_shell.js script which iterates
over the keys in exports with exports[name]).

Also fix a few trivial fuzzer issues that initial content uncovered:

- Ignore a wat file with invalid utf-8.
- Print string literals in the same way from JS as from C++.
- Enable the stringref flag in V8.
- Remove tag imports (the same as we do for global and function and other imports).
We used to fuzz MVP 1/3, all 1/3, and a mixture 1/3, but that gives far too much
priority to the MVP which is increasingly less important. It is also a good idea to
give "all" more priority as that enables more initial content to run (the fuzzer will
discard initial content if it doesn't validate with the features chosen in the current
iteration).

Also (NFC) rename POSSIBLE_FEATURE_OPTS to make the code easier to follow.
This PR is part of a series that adds basic support for the [typed
continuations/wasmfx proposal](https://github.com/wasmfx/specfx).

This particular PR adds support for the `cont.new` instruction for creating
continuations, documented [here(https://github.com/wasmfx/specfx/blob/main/proposals/continuations/Overview.md#instructions).

In short, these instructions are of the form `(cont.new $ct)` where `$ct` must
be a continuation type. The instruction takes a single (nullable) function
reference as its argument, which means that the folded representation of the
instruction is of the form `(cont.new $ct (foo ...))`. 

Support for the instruction is implemented in both the old and the new wat
parser.

Note that this PR does not implement validation of the new instruction.
…Assembly#6337)

See WebAssembly#5665 WebAssembly#5599, this is an existing issue and we have a workaround for it
using --dce, but it does not always work. I seem to be seeing this in higher
frequency since landing recent fuzzer improvements, so ignore it.

There is some risk of us missing real bugs here (that we validate and V8
does not), but this is a validation error which is not as serious as a difference
in behavior. And this is a long-standing issue that hasn't bitten us yet.
A bit of clean-up, changes getBranchValue to use pop().
Also rename the existing droppedSegments to droppedDataSegments for clarity.
No changes here to binaryen.js/wasm builds.

1. Add a flag to enable pthreads.

2. Use SINGLE_FILE on binaryen.js/.wasm as before, which is nice for library users
as they want just a single file to distribute for Binaryen support. For other builds
like wasm-opt.js etc. no longer set SINGLE_FILE, as that type of build wants to be
a replacement for a normal wasm-opt build as much as possible, so avoid the
overhead of SINGLE_FILE.

(Previously we disabled SINGLE_FILE also in the case of BUILD_FOR_BROWSER
but I don't think we need to special-case that any more.)
Before this we only printed the type of a BigInt and not the value.
…sembly#6350)

Before this all Emscripten builds would use 1 core, but it is important to
allow pthreads builds there to use more.
…y#6345)

Parse annotations using the standards-track `(@annotation ...)` format as well
as the `;;@ source-map:0:1` format. Have the lexer implicitly collect
annotations while it skips whitespace and add lexer APIs to access the
annotations since the last token was parsed. Collect annotations before parsing
each instruction and pass the annotations explicitly to the parser and parser
context functions for instructions. Add an API to `IRBuilder` to set a debug
location to be attached to the next visited or created instruction and use it
from the parser.
WebAssembly#6353)

Previously we lowered this to `getCodePointAt`, which has different semantics
around surrogate pairs.
Simply build wasm-opt with Emscripten and bundle that up.

Example build:

https://github.com/kripken/binaryen/releases/tag/wasm-build-1

Specifically

binaryen-wasm-build-1-wasm.tar.gz

Only 1.72 MB, as it's just wasm-opt and not any other tool, so it is
much smaller than our other targets. Perhaps we will add more of the
tools later as needed (wasm-metadce, wasm-split, etc.).

Also update the readme regarding which toolchains use us as a library, that I
noticed while editing it to add the release platforms.
…bAssembly#6344)

When we do a local.set of a value into a local then we have both a subtyping constraint - for
the value to be valid to put in that local - and also a flow of a value, which can then reach
more places. Such flow then interacts with casts in Unsubtyping, since it needs to know
what can flow where in order to know how casts force us to keep subtyping relations.

That regressed in the not-actually-NFC WebAssembly#6323 in which I added the innocuous lines
to add subtyping constraints in ref.eq. It seems fine to require that the arms of a
RefEq must be of type eqref, but Unsubtyping then assuming those arms flowed into
a location of type eqref... which means casts might force us to not optimize some
things.

To fix this, differentiate the rare case of non-flowing subtyping constraints, which is
basically only RefEq. There are perhaps a few more cases (like i31 operations) but they
do not matter in practice for Unsubtyping anyhow; I suggest we land this first to undo
the regression and then at our leisure investigate the other instructions.
…e run on it (WebAssembly#6357)

Before FUZZ_OPTS was used both when doing --translate-to-fuzz/-ttf to generate the
wasm from the random bytes and also when later running optimizations to generate
a second wasm file for comparison. That is, we ended up doing this, if the opts were -O3:

wasm-opt random.input -ttf -o a.wasm -O3
wasm-opt a.wasm -O3 -o b.wasm

Now we have a pair a.wasm,b.wasm which we can test. However, we have run -O3
on both which is a little silly - the second -O3 might not actually have anything left
to do, which would mean we compare the same wasm to itself.

Worse, this is incorrect, as there are things we need to do only during the
generation phase, like --denan. We need that in order to generate a valid wasm to
test on, but it is "destructive" in itself: when removing NaNs (to avoid nondeterminism)
if replaces them with 0, which is different. As a result, running --denan when
generating the second wasm from the first could lead to different execution in them.
This was always a problem, but became more noticable recently now that DeNaN
modifies SIMD operations, as one optimization we do is to replace a memory.copy
with v128.load + v128.store, and --denan will make sure the loaded value has no
NaNs...

To fix this, separate the generation and optimization phase. Instead of

wasm-opt random.input -ttf -o a.wasm --denan -O3
wasm-opt a.wasm --denan -O3 -o b.wasm

(note how --denan -O3 appears twice), do this:

wasm-opt random.input -ttf -o a.wasm --denan
wasm-opt a.wasm -O3 -o b.wasm

(note how --denan appears in generation, and -O3 in optimization).
@radekdoulik radekdoulik merged commit 1c7cda9 into dotnet/main Jul 12, 2024
10 checks passed
@akoeplinger akoeplinger deleted the pr-bump-to-version-117 branch July 12, 2024 12:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.