Skip to content

Commit 774995b

Browse files
authored
Wasmi IR v3.0 (#1650)
* initial commit * remove indoc dependency * initial commit * fix codegen for unary ops * add wasmi_ir2 crate contents * rename files and Instruction -> Op * add codegen for binary ops * add cmp+branch ops codegen * add Copy and Clone impls for Op * add cmp+select ops codegen * add load ops codegen * fix load ops codegen * add DisplayIdent for LoadOp * add Maybe utility type * add Display for Field * rename result_ident -> ident_prefix * add DisplayIndented utility type * remove unused code * apply rustfmt * add store ops codegen * add missing unary and binary ops * fix codegen * remove lots of unused code and imports * clean-up codegen a bit * add reserve to Isa * generalize DisplayIndented -> DisplayPair * add GenericOp::new * add control and copy ops to ISA * add DisplaySequence utility * add control and copy ops codegen * add GenericOp with 5 fields * add some table ops codegen * add From<GenericOp<N>> for Op impls * use new generic from impls * change immediate index type of Table{Get,Set} to u32 * add remaining table ops codegen * add more from impls for Op * define Op via macro * add memory ops codegen * add size_of and align_of test for Op * use DisplaySequence in DisplayEnum<Isa> impl * fix formatting issues in generated code * add call ops codegen * unsilence warnings and fix lots of warnings * add global ops codegen * add ref.func op codegen * remove more unused code * remove unused input_ty method * apply some clippy suggestions * use into_maybe where applicable * refactor Maybe -> DisplayMaybe and put into display module * replace DisplayPair with the more generic DisplayConcat * move display.rs -> display/mod.rs * move Display utils into utils sub-module * fix superflous newlines in codegen * clean-up DisplayEnum<LoadOp> impl * remove , from Field Display impl * improve DisplayIdent impls * make DisplayIdent case aware * move DisplayIdent into ident submodule * add cased Sep (separator) display utility * use new cased separator utilit in DisplayIdent * add more return ops for returning single values * unsilence more warnings * simplify DisplayEnum impl for UnaryOp * remove From impls from DisplayConcat * no longer use raw identifiers in define_ident macro * add DisplayIdent<UnaryOp> impl and use it * fix warnings in wasmi_ir2 * impl Display for DisplayIdent<BinaryOp> and use it * add Display impl for DisplayIdent<CmpBranchOp> * impl Display for DisplayIdent<CmpSelectOp> * implement DisplayIdent for the remaining ops * add BranchTable[Span] ops * rename len -> len_targets * add wide-arithmetic ops codegen * allocate just once for contents * use reserve_exact (since we know exactly how many ops) * make Field fields pub * move Field defs more to top * add field getters to all op types * move Indent to utils submodule * rename DisplayEnum -> DisplayOp * move DisplayOp impls into its own submodule * fix GlobalSet ops fields * take reference for DisplayOp<Isa> * remove unused import * add DisplayResultMut codegen * add fields methods to all ops * use offset_field in DisplayOp<CmpBranchOp> * add Op constructor codegen * add indent to DisplayOp codegen * simplify DisplayOp via fields methods * remove DisplayOp::scoped utility * add separator field to DisplaySequence * use new DisplaySequence separator * fix intendation for Op type in codegen * add wasmi_ir2::{Encoder, Encode} traits and impls * add OpCode enum codegen * add Encoder::encode_op_code and Encode impl for OpCode * add From<OpCode> for u16 impl * add Encode impls for f{32,64} and NonZero<{u32,64}> * add impl Encode for Op codegen * reserve proper amount for contents * generate encode.rs in its own file * use Config instead of &Path * add `simd` feature support and a demo simd copy128 op * reduce amount of code generated for Encode impls * add u128 and i128 Encode impls * apply clippy suggestions * change/fix Encode impl for BoundedStackSpan * add trivial Offset16 from impl * make Sign::new crate public * add FixedStackSpan::new_unchecked constructor * add Decode and Decoder traits and impls * use Self where applicate in matchers * add decode codegen * add Encode impls for tuples * add generic Encode impl for &T * drastically reduce codegen for Encode impls * inline crate re-exports * fix indentation of OpCode enum * fix idents of some div/rem ops * fix broken doc link * move Input more to top of file * rename Input -> OperandKind * add v128.splat ops codegen * apply clippy suggestion * fix invalid doc link * use TrapCode and u8 conversions in wasmi_ir2 * rename V128Splat -> V128SplatOp * add Encode and Decode impls for ImmLaneIdx type * add extract_lane simd ops codegen * improve comment * add v128.replace_lane ops codegen * deduplicate lots of code in build.rs * refactor and clean-up isa construction * clean-up add_simd_replace_lane_ops * move add_simd_ops to top of simd construction * add Encode and Decode for arrays * add more binary simd ops to isa * rename val -> value * reorder macro generated Op impls * generate code for DisplayOp for Op * refactor and clean-up ident_prefix queries * add comments to signal splits * add binary simd ops codegen * adjust expected generated file sizes * deduplicate codegen code * apply rustfmt * add simd shift ops codegen * add #[track_caller] for write_to_buffer * add unary SIMD ops codegen * rename UnaryOpKind::input_ty -> value_ty * remove V128SplatOp and use UnaryOp instead + clean-ups * add partial v128.load ops codegen * refactor ReplaceLaneWidth -> LaneWidth * add V128LoadLane simd ops codegen * dedup constructor codegen with macro * dedup encode codegen with macro * dedup variant codegen with macro * add StoreNLane simd ops codegen * add relaxed-simd ops codegen * rename submodule: token -> ident * apply clippy suggestion * rename [{Bounded,Fixed}]Stack[Span]: Stack -> Slot * add TryFrom<u16> impl for OpCode * add Decode impl for OpCode * split generated op.rs into op.rs and op_code.rs * add docs to Op and OpCode types * fix codegen indentation * add missing f{32,64}.not_{lt,le} operators * bump simd capacity requirements * fix identifiers of select operators * no longer generate icmp select instructions with lhs immediates * apply rustfmt * fix Ident::NotEq snake case identifier * fix ReturnSpan field * reorder some CmpOpKind variants * remove unnecessary angle brackets * simplify Encode impl for BoundedSlotSpan * add proper Encode/Decode impls for FixedSlotSpan<N> * add BranchTableTarget type * reorder macro parameters * slightly simplify macro generated Encode impls * ignore coverage stats of wasmi_ir2 since it has not yet been integrated
1 parent 5439ae6 commit 774995b

28 files changed

+6795
-0
lines changed

Cargo.lock

Lines changed: 7 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ members = [
88
"crates/wasmi",
99
"crates/wasi",
1010
"crates/ir",
11+
"crates/ir2",
1112
"crates/fuzz",
1213
"crates/wast",
1314
"fuzz",
@@ -34,6 +35,7 @@ wasmi = { version = "0.51.0", path = "crates/wasmi", default-features = false }
3435
wasmi_wasi = { version = "0.51.0", path = "crates/wasi", default-features = false }
3536
wasmi_core = { version = "0.51.0", path = "crates/core", default-features = false }
3637
wasmi_ir = { version = "0.51.0", path = "crates/ir", default-features = false }
38+
wasmi_ir2 = { version = "0.51.0", path = "crates/ir2", default-features = false }
3739
wasmi_collections = { version = "0.51.0", path = "crates/collections", default-features = false }
3840
wasmi_c_api_impl = { version = "0.51.0", path = "crates/c_api" }
3941
wasmi_c_api_macros = { version = "0.51.0", path = "crates/c_api/macro" }

codecov.yml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
coverage:
2+
status:
3+
project:
4+
default:
5+
target: auto
6+
threshold: 1%
7+
8+
ignore:
9+
- "crates/ir2/**"

crates/ir2/Cargo.toml

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
[package]
2+
name = "wasmi_ir2"
3+
version.workspace = true
4+
rust-version.workspace = true
5+
documentation = "https://docs.rs/wasmi_ir2/"
6+
description = "WebAssembly interpreter internal bytecode representation"
7+
authors.workspace = true
8+
repository.workspace = true
9+
edition.workspace = true
10+
readme.workspace = true
11+
license.workspace = true
12+
keywords.workspace = true
13+
categories.workspace = true
14+
exclude = [
15+
"benches/wat",
16+
"benches/wasm",
17+
"tests/spec/testsuite",
18+
"**.wast",
19+
]
20+
21+
[dependencies]
22+
wasmi_core = { workspace = true }
23+
24+
[features]
25+
default = ["std"]
26+
std = [
27+
"wasmi_core/std",
28+
]
29+
simd = ["wasmi_core/simd"]
30+
31+
[package.metadata.docs.rs]
32+
features = ["std", "simd"]

crates/ir2/build.rs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
use self::build::Config;
2+
use std::{fs, path::Path};
3+
4+
#[path = "build/mod.rs"]
5+
mod build;
6+
7+
fn main() {
8+
watch_dir_recursively(Path::new("build"));
9+
let config = Config::default();
10+
build::generate_code(&config).unwrap()
11+
}
12+
13+
fn watch_dir_recursively(path: &Path) {
14+
if !path.is_dir() {
15+
return;
16+
}
17+
let entries = match fs::read_dir(path) {
18+
Ok(entries) => entries,
19+
Err(error) => panic!("failed to read directory: {error}"),
20+
};
21+
for entry in entries {
22+
let entry = match entry {
23+
Ok(entry) => entry,
24+
Err(error) => panic!("failed to read directory entry: {error}"),
25+
};
26+
let path = entry.path();
27+
if path.is_file() {
28+
println!("cargo:rerun-if-changed={}", path.display());
29+
}
30+
watch_dir_recursively(&path);
31+
}
32+
}
Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
use crate::build::{
2+
display::{ident::DisplayIdent, utils::DisplaySequence, Indent},
3+
ident::SnakeCase,
4+
isa::Isa,
5+
op::{
6+
BinaryOp,
7+
CmpBranchOp,
8+
CmpSelectOp,
9+
Field,
10+
GenericOp,
11+
LoadOp,
12+
StoreOp,
13+
TableGetOp,
14+
TableSetOp,
15+
UnaryOp,
16+
V128LoadLaneOp,
17+
V128ReplaceLaneOp,
18+
},
19+
};
20+
use core::fmt::{self, Display};
21+
22+
pub struct DisplayConstructor<T> {
23+
pub value: T,
24+
pub indent: Indent,
25+
}
26+
27+
impl<T> DisplayConstructor<T> {
28+
pub fn new(value: T, indent: Indent) -> Self {
29+
Self { value, indent }
30+
}
31+
32+
pub fn map<V>(&self, value: V) -> DisplayConstructor<V> {
33+
DisplayConstructor {
34+
value,
35+
indent: self.indent,
36+
}
37+
}
38+
}
39+
40+
impl<'a, T> DisplayConstructor<&'a T> {
41+
fn display_constructor(&self, f: &mut fmt::Formatter, fields: &[Option<Field>]) -> fmt::Result
42+
where
43+
DisplayIdent<&'a T>: Display,
44+
{
45+
let indent = self.indent;
46+
let snake_ident = DisplayIdent::snake(self.value);
47+
let camel_ident = DisplayIdent::camel(self.value);
48+
let fn_params = DisplaySequence::new(", ", fields.iter().filter_map(Option::as_ref));
49+
let struct_params = DisplaySequence::new(
50+
", ",
51+
fields
52+
.iter()
53+
.filter_map(Option::as_ref)
54+
.map(|param| param.ident)
55+
.map(SnakeCase),
56+
);
57+
write!(
58+
f,
59+
"\
60+
{indent}pub fn {snake_ident}({fn_params}) -> Self {{\n\
61+
{indent} Self::{camel_ident} {{ {struct_params} }}\n\
62+
{indent}}}\n\
63+
"
64+
)
65+
}
66+
}
67+
68+
impl Display for DisplayConstructor<&'_ Isa> {
69+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
70+
let indent = self.indent;
71+
let variants = DisplaySequence::new(
72+
"",
73+
self.value
74+
.ops
75+
.iter()
76+
.map(|op| DisplayConstructor::new(op, indent.inc_by(1))),
77+
);
78+
write!(
79+
f,
80+
"\
81+
{indent}impl Op {{\n\
82+
{variants}\
83+
{indent}}}\n\
84+
"
85+
)
86+
}
87+
}
88+
89+
macro_rules! impl_display_constructor {
90+
( $($ty:ty),* $(,)? ) => {
91+
$(
92+
impl Display for DisplayConstructor<&'_ $ty> {
93+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
94+
let fields = self.value.fields().map(Option::from);
95+
self.display_constructor(f, &fields)
96+
}
97+
}
98+
)*
99+
};
100+
}
101+
impl_display_constructor! {
102+
UnaryOp,
103+
BinaryOp,
104+
CmpBranchOp,
105+
CmpSelectOp,
106+
LoadOp,
107+
StoreOp,
108+
TableGetOp,
109+
TableSetOp,
110+
V128ReplaceLaneOp,
111+
V128LoadLaneOp,
112+
}
113+
114+
impl<const N: usize> Display for DisplayConstructor<&'_ GenericOp<N>> {
115+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
116+
let fields = self.value.fields.map(Option::from);
117+
self.display_constructor(f, &fields)
118+
}
119+
}

0 commit comments

Comments
 (0)