* Update to arbitrary 1.3.1
And use workspace dependencies for arbitrary.
* Prune cargo vet's supply-chain files
This is the mechanical changes made by running `cargo vet prune` which was
suggested to me when I ran `cargo vet`.
* winch(x64): Add support for table instructions
This change adds support for the following table insructions:
`elem.drop`, `table.copy`, `table.set`, `table.get`, `table.fill`,
`table.grow`, `table.size`, `table.init`.
This change also introduces partial support for the `Ref` WebAssembly
type, more conretely the `Func` heap type, which means that all the
table instructions above, only work this WebAssembly type as of this
change.
Finally, this change is also a small follow up to the primitives
introduced in https://github.com/bytecodealliance/wasmtime/pull/7100,
more concretely:
* `FnCall::with_lib`: tracks the presence of a libcall and ensures that
any result registers are freed right when the call is emitted.
* `MacroAssembler::table_elem_addr` returns an address rather than the
value of the address, making it convenient for other use cases like
`table.set`.
--
prtest:full
* chore: Make stack functions take impl IntoIterator<..>
* Update winch/codegen/src/codegen/call.rs
Co-authored-by: Trevor Elliott <awesomelyawesome@gmail.com>
* Remove a dangling `dbg!`
* Add comment on branching
---------
Co-authored-by: Trevor Elliott <awesomelyawesome@gmail.com>
* winch(x64): Call indirect
This change adds support for the `call_indirect` instruction to Winch.
Libcalls are a pre-requisite for supporting `call_indirect` in order to
lazily initialy funcrefs. This change adds support for libcalls to
Winch by introducing a `BuiltinFunctions` struct similar to Cranelift's
`BuiltinFunctionSignatures` struct.
In general, libcalls are handled like any other function call, with the
only difference that given that not all the information to fulfill the
function call might be known up-front, control is given to the caller
for finalizing the call.
The introduction of function references also involves dealing with
pointer-sized loads and stores, so this change also adds the required
functionality to `FuncEnv` and `MacroAssembler` to be pointer aware,
making it straight forward to derive an `OperandSize` or `WasmType` from
the target's pointer size.
Finally, given the complexity of the call_indirect instrunction, this
change bundles an improvement to the register allocator, allowing it to
track the allocatable vs non-allocatable registers, this is done to
avoid any mistakes when allocating/de-allocating registers that are not
alloctable.
--
prtest:full
* Address review comments
* Fix typos
* Better documentation for `new_unchecked`
* Introduce `max` for `BitSet`
* Make allocatable property `u64`
* winch(calls): Overhaul `FnCall`
This commit simplifies `FnCall`'s interface making its usage more
uniform throughout the compiler. In summary, this change:
* Avoids side effects in the `FnCall::new` constructor, and also makes
it the only constructor.
* Exposes `FnCall::save_live_registers` and
`FnCall::calculate_call_stack_space` to calculate the stack space
consumed by the call and so that the caller can decide which one to
use at callsites depending on their use-case.
* tests: Fix regset tests
* winch: Support f32.abs and f64.abs on x64
Co-authored-by: Nick Fitzgerald <fitzgen@gmail.com>
* Add an implementation of f32.neg and f64.neg
* Enable spec tests for winch with f{32,64}.{neg,abs}
* Enable differential fuzzing for f{32,64}.{neg,abs} for winch
* Comments from code review
---------
Co-authored-by: Nick Fitzgerald <fitzgen@gmail.com>
* winch: Add support for `br_table`
This change adds support for the `br_table` instruction, including
several modifications to the existing control flow implementation:
* Improved handling of jumps to loops: Previously, the compiler erroneously
treated the result of loop blocks as the definitive result of the jump. This
change fixes this bug.
* Streamlined result handling and stack pointer balancing: In the past, these
operations were executed in two distinct steps, complicating the process of
ensuring the correct invariants when emitting unconditional jumps. To simplify
this, `CodeGenContext::unconditional_jump` is introduced . This function
guarantees all necessary invariants are met, encapsulating the entire operation
within a single function for easier understanding and maintenance.
* Handling of unreachable state at the end of a function: when reaching the end
of a function in an unreachable state, clear the stack and ensure that the
machine stack pointer is correctly placed according to the expectations of the
outermost block.
In addition to the above refactoring, the main implementation of the
`br_table` instruction involves emitting labels for each target. Within each
label, an unconditional jump is emitted to the frame's label, ensuring correct
stack pointer balancing when the jump is emitted.
While it is possible to optimize this process by avoiding intermediate labels
when balancing isn't required, I've opted to maintain the current
implementation until such optimization becomes necessary.
* chore: Rust fmt
* fuzzing: Add `BrTable` to list of support instructions
* docs: Improve documentation for `unconditional_jump`
* Fix some warnings on nightly Rust
* Fix some more fuzz-test cases from pooling changes
This commit addresses some more fallout from #6835 by updating some
error messages and adding clauses for new conditions. Namely:
* Module compilation is now allowed to fail when the module may have
more memories/tables than the pooling allocator allows per-module.
* The error message for the core instance limit being reached has been
updated.
* winch: Initial support for floats
This change introuduces the necessary building blocks to support floats in
Winch as well as support for both `f32.const` and `f64.const` instructions.
To achieve support for floats, this change adds several key enhancements to the
compiler:
* Constant pool: A constant pool is implemented, at the Assembler level, using the machinery
exposed by Cranelift's `VCode` and `MachBuffer`. Float immediates are stored
using their bit representation in the value stack, and whenever they are
used at the MacroAssembler level they are added to the constant
pool, from that point on, they are referenced through a `Constant` addressing
mode, which gets translated to a RIP-relative addressing mode during emission.
* More precise value tagging: aside from immediates, from which the type can
be easily inferred, all the other value stack entries (`Memory`, `Reg`, and `Local`) are
modified to explicitly contain a WebAssembly type. This allows for better
instruction selection.
--
prtest:full
* fix: Account for relative sp position when pushing float regs
This was an oversight of the initial implementation. When pushing float
registers, always return an address that is relative to the current position of
the stack pointer, essentially storing to (%rsp). The previous implementation
accounted for static addresses, which is not correct.
* fix: Introduce `stack_arg_slot_size_for_type`
To correctly calculate the stack argument slot sizes, instead of overallocating
for `word_bytes`, since for `f32` floating points we only need to worry about
loading/storing 4 bytes.
* fix: Correctly type the result register.
The previous version wrongly typed the register as a general purpose register.
* refactor: Re-write `add_constants` through `add_constant`
* docs: Replace old comment
* chore: Rust fmt
* refactor: Index regset per register class
This commit implements `std::ops::{Index, IndexMut}` for `RegSet` to index each
of the bitsets by class. This reduces boilerplate and repetition throuhg the
code generation context, register allocator and register set.
* refactor: Correctly size callee saved registers
To comply with the expectation of the underlying architecture: for example in
Aarch64, only the low 64 bits of VRegs are callee saved (the D-view) and in the
`fastcall` calling convention it's expected that the callee saves the entire 128
bits of the register xmm6-xmm15.
This change also fixes the the stores/loads of callee saved float registers in the
fastcall calling convention, as in the previous implementation only the low 64
bits were saved/restored.
* docs: Add comment regarding typed-based spills
* Wasmtime: Rename `IndexAllocator` to `ModuleAffinityIndexAllocator`
We will have multiple kinds of index allocators soon, so clarify which one this
is.
* Wasmtime: Introduce a simple index allocator
This will be used in future commits refactoring the pooling allocator.
* Wasmtime: refactor the pooling allocator for components
We used to have one index allocator, an index per instance, and give out N
tables and M memories to every instance regardless how many tables and memories
they need.
Now we have an index allocator for memories and another for tables. An instance
isn't associated with a single instance, each of its memories and tables have an
index. We allocate exactly as many tables and memories as the instance actually
needs.
Ultimately, this gives us better component support, where a component instance
might have varying numbers of internal tables and memories.
Additionally, you can now limit the number of tables, memories, and core
instances a single component can allocate from the pooling allocator, even if
there is the capacity for that many available. This is to give embedders tools
to limit individual component instances and prevent them from hogging too much
of the pooling allocator's resources.
* Remove unused file
Messed up from rebasing, this code is actually just inline in the index
allocator module.
* Address review feedback
* Fix benchmarks build
* Fix ignoring test under miri
The `async_functions` module is not even compiled-but-ignored with miri, it is
completely `cfg`ed off. Therefore we ahve to do the same with this test that
imports stuff from that module.
* Fix doc links
* Allow testing utilities to be unused
The exact `cfg`s that unlock the tests that use these are platform and feature
dependent and ends up being like 5 things and super long. Simpler to just allow
unused for when we are testing on other platforms or don't have the compile time
features enabled.
* Debug assert that the pool is empty on drop, per Alex's suggestion
Also fix a couple scenarios where we could leak indices if allocating an index
for a memory/table succeeded but then creating the memory/table itself failed.
* Fix windows compile errors
This commit adds support for the `local.tee` instruction. This change
also introduces a refactoring to the original implementation of
`local.set` to be able to share most of the code for the implementation
of `local.tee`.
This change adds support for the `loop`, `br` and `br_if` instructions
as well as unreachable code handling. Whenever an instruction that
affects reachability is emitted (`br` in the case of this PR), the
compiler will enter into an unreachable code state, essentially ignoring
most of the subsequent instructions. When handling the unreachable code
state some instructions are still observed, in order to determine if
reachability should be restored.
This change, particulary the handling of unreachable code, adds all the
necessary building blocks to the compiler to emit other instructions
that affect reachability (e.g `unreachable`, `return`).
Address review feedback
* Rename `branch_target` to `is_branch_target`
* Use the visitor pattern to handle unreachable code
Avoid string comparison and split unreachable handling functions
* Add i32.popcnt and i64.popcnt to winch
Co-authored-by: Nick Fitzgerald <fitzgen@gmail.com>
Co-authored-by: Chris Fallin <chris@cfallin.org>
* Add fallback implementation for popcnt
Move popcnt fallback up into the macroassembler.
Share code between 32-bit and 64-bit popcnt
Add Popcnt to winch differential fuzzing
* Use _rr functions where possible
* Avoid using scratch register for popcnt
The scratch register was getting clobbered by the calls to `and`,
so this is instead passing in a CodeGenContext to the masm's `popcnt`
and letting it handle its own registers
* Add filetests for the fallback popcnt impls
* address PR comments
* Update filetests
---------
Co-authored-by: Nick Fitzgerald <fitzgen@gmail.com>
Co-authored-by: Chris Fallin <chris@cfallin.org>
* winch(x64) Add support for if/else
This change adds the necessary building blocks to support control flow;
this change also adds support for the `If` / `Else` operators.
This change does not include multi-value support. The idea is to add
support for multi-value across the compiler (functions and blocks) as
a separate future change.
The general gist of the change is to track the presence of control flow
frames as part of the code generation context and emit the corresponding
labels as and instructions as control flow blocks are found.
* PR review
* Allocate 64 slots for `ControlStackFrames`
* Explicitly track else branches through an else entry in
`ControlStackFrame`
* winch(fuzz): Refactor Winch's fuzzing
This change is a follow-up to the discussion in
https://github.com/bytecodealliance/wasmtime/pull/6281.
The most notable characteristic of this change is that it enables
`winch` by default in the fuzzers. If compilation time is a big enough
concern I can add the cargo feature back. I opted to enable `winch` by
default for several reasons:
* It substantially reduces the `cfg` complexity -- at first I thought
I had covered all the places in which a `cfg` check would be needed,
but then I realized that I missed the Cranelift specific compiler
flags.
* It's the fastest route to enable winch by default in the fuzzers,
which we want to do eventually -- the only change we'd need at that
point would be to get rid of the winch-specific environment variable.
* We can get rid of the winch-specific checks in CI for fuzzing
* Implement Arbitraty for CompilerStrategy
Unconditionally return `Cranelift` for the `Arbitrary` implementation of
`CompilerStrategy`. This ensures that `Cranelift` is used as the
compiler for all the targets unless explicitly requested otherwise. As
of this change, only the differential target overrides the
`CompilerStrategy`
This fuzz target was accidentally broken by #6378 and I forgot to update
this fuzz target. Namely all the generated types now need names to
satisfy possible restrictions depending on the structure. For simplicity
everything is given a name to avoid having to special case some vs
others which isn't the purpose of this fuzz target.
* add fuel parameter to control plane
Co-authored-by: Falk Zwimpfer <24669719+FalkZ@users.noreply.github.com>
Co-authored-by: Moritz Waser <mzrw.dev@pm.me>
* remove unused cranelift setting
Co-authored-by: Falk Zwimpfer <24669719+FalkZ@users.noreply.github.com>
Co-authored-by: Moritz Waser <mzrw.dev@pm.me>
* update fuel parameter documentation
Co-authored-by: Falk Zwimpfer <24669719+FalkZ@users.noreply.github.com>
Co-authored-by: Moritz Waser <mzrw.dev@pm.me>
* include control plane in printed test case
Co-authored-by: Falk Zwimpfer <24669719+FalkZ@users.noreply.github.com>
Co-authored-by: Moritz Waser <mzrw.dev@pm.me>
* print control plane as comment
Co-authored-by: Falk Zwimpfer <24669719+FalkZ@users.noreply.github.com>
Co-authored-by: Moritz Waser <mzrw.dev@pm.me>
* set fuel limit in cranelift settings
Co-authored-by: Falk Zwimpfer <24669719+FalkZ@users.noreply.github.com>
Co-authored-by: Moritz Waser <mzrw.dev@pm.me>
* separate cli arg parsing from arbitrary impl
`ControlPlane::new` is replaced with an `Arbitrary` implementation
and `ControlPlane::set_fuel`, as it was before.
The CLI argument parsing inside the fuzz target `cranelift-fuzzgen`
is separated from the `Arbitrary` implementation of `TestCase`.
To achieve this, the `TestCase` doesn't carry a build TargetIsa
anymore, but it it generated with an isa- and flags-builder.
The CLI argument can then modify the flags further before the
`TargetIsa` is built.
The `TestCase.isa_builder` is wrapper in an `Rc` such that optimized
test cases can share the same one and it doesn't need to be made
`Clone`.
Co-authored-by: Falk Zwimpfer <24669719+FalkZ@users.noreply.github.com>
Co-authored-by: Moritz Waser <mzrw.dev@pm.me>
* parse control planes with clif-util
Co-authored-by: Falk Zwimpfer <24669719+FalkZ@users.noreply.github.com>
Co-authored-by: Moritz Waser <mzrw.dev@pm.me>
* move parsing logic from cranelift-control to cranelift-reader
Co-authored-by: Falk Zwimpfer <24669719+FalkZ@users.noreply.github.com>
Co-authored-by: Moritz Waser <mzrw.dev@pm.me>
* remove parsing and settings plumbing
Co-authored-by: Falk Zwimpfer <24669719+FalkZ@users.noreply.github.com>
Co-authored-by: Moritz Waser <mzrw.dev@pm.me>
---------
Co-authored-by: Falk Zwimpfer <24669719+FalkZ@users.noreply.github.com>
Co-authored-by: Moritz Waser <mzrw.dev@pm.me>
* Unify differential result comparison logic
Execution of functions handles the case where one instance stack
overflows and the other didn't, but instantiation didn't handle this
case. This commit fixes this issue by sharing the result comparison
logic between the two branches.
* Update crates/fuzzing/src/oracles.rs
Co-authored-by: bjorn3 <17426603+bjorn3@users.noreply.github.com>
---------
Co-authored-by: bjorn3 <17426603+bjorn3@users.noreply.github.com>
* Improve longevity for fuzzing corpus of wasm modules
This commit is an improvement to the longevity of Wasmtime's corpus of
fuzz inputs to the `instantiate` fuzzer. Currently the input to this
fuzzers is arbitrary binary data which is a "DNA" of sorts of what to
do. This DNA changes over time as we update the fuzzer and add
configuration options, for example. When this happens though the
meaning of all existing inputs in the corpus changes because they all
have slightly different meanings now. The goal of this commit is to
improve the usefulness of a historical corpus, with respect to the
WebAssembly modules generated, across changes to the DNA.
A custom mutator is now provided for the `instantiate` fuzzer. This
mutator will not only perform libfuzzer's default mutation for the input
but will additionally place an "envelope" around the fuzz input. Namely,
the fuzz input is encoded as a valid WebAssembly module where the actual
input to the fuzzer is a trailing custom section. When the fuzzer runs
over this input it will read the custom section, perform any
configuration generation necessary, and then use the envelope module as
the actual input to the fuzzer instead of whatever was generated from
the fuzz input. This means that when a future update is made to the DNA
of a module the interpretation of the fuzz input section will change but
the module in question will not change. This means that any interesting
shapes of modules with respect to instructions should be preserved over
time in theory.
Some consequences of this strategy, however, are:
* If the DNA changes then it's difficult to produce minor mutations of
the original module. This is because mutations generate a module based
on the new DNA which is likely much different than the preexisting
module. This mainly just means that libFuzzer will have to rediscover
how to mutate up into interesting shapes on DNA changes but it'll
still be able to retain all the existing interesting modules.
Additionally this can be mitigate with the integration of
`wasm-mutate` perhaps into these fuzzers as well.
* Protection is necessary against libFuzzer itself with respect to the
module. The existing fuzzers only expect valid modules to be created,
but libFuzzer can now create mutations which leave the trailing
section in place, meaning the module is no longer valid. One option is
to record a cryptographic hash in the fuzz input section of the
previous module, only using the module if the hashes match. This
approach will not work over time in the face of binary format changes,
however. For example the multi-memory proposal changed binary
encodings a year or so ago meaning that any previous fuzz-generated
cases would no longer be guaranteed to be valid. The strategy settled
by this PR is to pass a flag to the execution function indicating if
the module is "known valid" and gracefully handle error if it isn't
(for example if it's a prior test case).
I'll note that this new strategy of fuzzing is not applied to the
`differential` fuzzer. This could theoretically use the same strategy
but it relies much more strictly on being able to produce a module with
properties like NaN canonicalization, resource limits, fuel to limit
execution, etc. While it may be possible to integrate this with
`differential` in the future I figured it'd be better to start with the
`instantiate` fuzzer and go from there.
* Fix doc build
This commit updates the test case generation for the `component_api`
fuzzer to prepare for an update to the `arbitrary` crate. The current
algorithm, with the latest `arbitrary` crate, generates a 20MB source
file which is a bit egregious. The goal here was to get that under
control by altering the parameters of test case generation and
additionally changing the structure of what's generated.
The new strategy is to have a limited set of "type fuel" which is
consumed as a type is generated. This bounds the maximal size of a type
in addition to its depth as prior. Additionally a fixed set of types are
generated first and then test cases select from these types as opposed
to test cases always generating types for themselves. Coupled together
this brings the size of the generated file back into the 200K range as
it was before.
* winch(fuzz): Initial support for differential fuzzing
This commit introduces initial support for differential fuzzing for Winch. In
order to fuzz winch, this change introduces the `winch` cargo feature. When the
`winch` cargo feature is enabled the differential fuzz target uses `wasmi` as
the differential engine and `wasm-smith` and `single-inst` as the module sources.
The intention behind this change is to have a *local* approach for fuzzing and
verifying programs generated by Winch and to have an initial implementation that
will allow us to eventually enable this change by default. Currently it's not
worth it to enable this change by default given all the filtering that needs to
happen to ensure that the generated modules are supported by Winch.
It's worth noting that the Wasm filtering code will be temporary, until Winch
reaches feature parity in terms of Wasm operators.
* Check build targets with the `winch` feature flag
* Rename fuzz target feature to `fuzz-winch`
Previously it could affect the PartialEq and Hash impls. Ignoring the
sequence number in PartialEq and Hash allows us to not renumber all
blocks in the incremental cache.
Fuzz additional targets in the cranelift-icache target. The list of targets fuzzed is controlled by the targets enabled in fuzz/Cargo.toml.
This PR also reworks how instruction disabling is done in function generator, moving the deny-list to a function to make the decision at runtime instead of compile time.
We have some operations defined on DataFlowGraph purely to work around borrow-checker issues with InstructionData and other data on DataFlowGraph. Part of the problem is that indexing the DFG directly hides the fact that we're only indexing the insts field of the DFG.
This PR makes the insts field of the DFG public, but wraps it in a newtype that only allows indexing. This means that the borrow checker is better able to tell when operations on memory held by the DFG won't conflict, which comes up frequently when mutating ValueLists held by InstructionData.
This commit changes the APIs in the `wasmtime` crate for configuring the
pooling allocator. I plan on adding a few more configuration options in
the near future and the current structure was feeling unwieldy for
adding these new abstractions.
The previous `struct`-based API has been replaced with a builder-style
API in a similar shape as to `Config`. This is done to help make it
easier to add more configuration options in the future through adding
more methods as opposed to adding more field which could break prior
initializations.
The `libfuzzer-sys` update in #5068 included some changes to the
`fuzz_target!` macro which caused a bare `run` function to be shadowed
by the macro-defined `run` function (changed in
rust-fuzz/libfuzzer#95) which meant that some of our fuzz targets were
infinite looping or stack overflowing as the same function was called
indefinitely. This renames the top-level `run` function to something
else in the meantime.
* fuzzgen: Test compiler flags
* cranelift: Generate `all()` function for all enum flags
This allows a user to iterate all flags that exist.
* fuzzgen: Minimize regalloc_checker compiles
* fuzzgen: Limit the amount of test case inputs
* fuzzgen: Add egraphs flag
It's finally here! 🥳
* cranelift: Add fuzzing comment to settings
* fuzzgen: Add riscv64
* fuzzgen: Unconditionally enable some flags