diff --git a/crates/ir2/build/ident.rs b/crates/ir2/build/ident.rs index 6048e03134..617cb77766 100644 --- a/crates/ir2/build/ident.rs +++ b/crates/ir2/build/ident.rs @@ -125,9 +125,9 @@ define_ident!( NotLt: not_lt, NotLe: not_le, - BitAnd: bit_and, - BitOr: bit_or, - BitXor: bit_xor, + BitAnd: bitand, + BitOr: bitor, + BitXor: bitxor, Branch: branch, BranchTable: branch_table, @@ -209,6 +209,7 @@ define_ident!( Value: value, Result: result, Results: results, + Params: params, Len: len, LenTargets: len_targets, LenValues: len_values, @@ -244,7 +245,7 @@ define_ident!( I64Add128: i64_add128, I64Sub128: i64_sub128, - S64MulWide: s64_mul_wide, + I64MulWide: i64_mul_wide, U64MulWide: u64_mul_wide, Lhs: lhs, @@ -264,7 +265,10 @@ define_ident!( V128: v128, Lane: lane, - Splat: splat, + Splat8: splat8, + Splat16: splat16, + Splat32: splat32, + Splat64: splat64, S8x16ExtractLane: s8x16_extract_lane, U8x16ExtractLane: u8x16_extract_lane, S16x8ExtractLane: s16x8_extract_lane, diff --git a/crates/ir2/build/isa.rs b/crates/ir2/build/isa.rs index 0751466f61..3ecde77552 100644 --- a/crates/ir2/build/isa.rs +++ b/crates/ir2/build/isa.rs @@ -373,41 +373,12 @@ fn add_store_ops(isa: &mut Isa) { StoreOpKind::I64Store32, ]; for op in ops { - isa.push_op(StoreOp::new( - op, - OperandKind::Slot, - OperandKind::Slot, - false, - false, - )); - isa.push_op(StoreOp::new( - op, - OperandKind::Slot, - OperandKind::Immediate, - false, - false, - )); - isa.push_op(StoreOp::new( - op, - OperandKind::Immediate, - OperandKind::Slot, - false, - false, - )); - isa.push_op(StoreOp::new( - op, - OperandKind::Slot, - OperandKind::Slot, - true, - true, - )); - isa.push_op(StoreOp::new( - op, - OperandKind::Slot, - OperandKind::Immediate, - true, - true, - )); + for value in [OperandKind::Slot, OperandKind::Immediate] { + for ptr in [OperandKind::Slot, OperandKind::Immediate] { + isa.push_op(StoreOp::new(op, ptr, value, false, false)); + } + isa.push_op(StoreOp::new(op, OperandKind::Slot, value, true, true)); + } } } @@ -509,21 +480,21 @@ fn add_call_ops(isa: &mut Isa) { Op::from(GenericOp::new( Ident::CallInternal, [ - Field::new(Ident::Results, FieldTy::SlotSpan), + Field::new(Ident::Params, FieldTy::BoundedSlotSpan), Field::new(Ident::Func, FieldTy::InternalFunc), ], )), Op::from(GenericOp::new( Ident::CallImported, [ - Field::new(Ident::Results, FieldTy::SlotSpan), + Field::new(Ident::Params, FieldTy::BoundedSlotSpan), Field::new(Ident::Func, FieldTy::Func), ], )), Op::from(GenericOp::new( Ident::CallIndirect, [ - Field::new(Ident::Results, FieldTy::SlotSpan), + Field::new(Ident::Params, FieldTy::BoundedSlotSpan), Field::new(Ident::Index, FieldTy::Slot), Field::new(Ident::FuncType, FieldTy::FuncType), Field::new(Ident::Table, FieldTy::Table), @@ -531,15 +502,22 @@ fn add_call_ops(isa: &mut Isa) { )), Op::from(GenericOp::new( Ident::ReturnCallInternal, - [Field::new(Ident::Func, FieldTy::InternalFunc)], + [ + Field::new(Ident::Params, FieldTy::BoundedSlotSpan), + Field::new(Ident::Func, FieldTy::InternalFunc), + ], )), Op::from(GenericOp::new( Ident::ReturnCallImported, - [Field::new(Ident::Func, FieldTy::Func)], + [ + Field::new(Ident::Params, FieldTy::BoundedSlotSpan), + Field::new(Ident::Func, FieldTy::Func), + ], )), Op::from(GenericOp::new( Ident::ReturnCallIndirect, [ + Field::new(Ident::Params, FieldTy::BoundedSlotSpan), Field::new(Ident::Index, FieldTy::Slot), Field::new(Ident::FuncType, FieldTy::FuncType), Field::new(Ident::Table, FieldTy::Table), @@ -724,7 +702,7 @@ fn add_wide_arithmetic_ops(isa: &mut Isa) { ], )), Op::from(GenericOp::new( - Ident::S64MulWide, + Ident::I64MulWide, [ Field::new(Ident::Results, FieldTy::FixedSlotSpan2), Field::new(Ident::Lhs, FieldTy::Slot), @@ -776,7 +754,12 @@ fn add_simd_ops(isa: &mut Isa, config: &Config) { } fn add_simd_splat_ops(isa: &mut Isa) { - let kinds = [UnaryOpKind::V128Splat32, UnaryOpKind::V128Splat64]; + let kinds = [ + UnaryOpKind::V128Splat8, + UnaryOpKind::V128Splat16, + UnaryOpKind::V128Splat32, + UnaryOpKind::V128Splat64, + ]; for kind in kinds { isa.push_op(UnaryOp::new(kind, OperandKind::Slot)); isa.push_op(UnaryOp::new(kind, OperandKind::Immediate)); diff --git a/crates/ir2/build/op.rs b/crates/ir2/build/op.rs index 29eac3dae6..cbba3c421f 100644 --- a/crates/ir2/build/op.rs +++ b/crates/ir2/build/op.rs @@ -214,6 +214,8 @@ pub enum UnaryOpKind { F64ConvertU64, // SIMD: Generic Unary Ops + V128Splat8, + V128Splat16, V128Splat32, V128Splat64, V128Not, @@ -287,6 +289,8 @@ pub enum UnaryOpKind { impl UnaryOpKind { pub fn is_conversion(&self) -> bool { self.value_ty() != self.result_ty() + && self.value_ty().is_wasm() + && self.result_ty().is_wasm() } pub fn value_ty(&self) -> Ty { @@ -328,6 +332,8 @@ impl UnaryOpKind { | Self::F64ConvertU64 => Ty::U64, // SIMD: Generic Unary Ops + | Self::V128Splat8 => Ty::B8, + | Self::V128Splat16 => Ty::B16, | Self::V128Splat32 => Ty::B32, | Self::V128Splat64 => Ty::B64, | Self::V128Not | Self::V128AnyTrue => Ty::V128, @@ -435,7 +441,12 @@ impl UnaryOpKind { | Self::F64ConvertU64 => Ty::F64, // SIMD: Generic Unary Ops - | Self::V128Splat32 | Self::V128Splat64 | Self::V128Not | Self::V128AnyTrue => Ty::V128, + | Self::V128Splat8 + | Self::V128Splat16 + | Self::V128Splat32 + | Self::V128Splat64 + | Self::V128Not + | Self::V128AnyTrue => Ty::V128, // SIMD: `i8x16` Unary Ops | Self::I8x16Abs | Self::I8x16Neg @@ -551,8 +562,10 @@ impl UnaryOpKind { Self::F64ConvertU64 => Ident::Convert, // SIMD: Generic Unary Ops - Self::V128Splat32 => Ident::Splat, - Self::V128Splat64 => Ident::Splat, + Self::V128Splat8 => Ident::Splat8, + Self::V128Splat16 => Ident::Splat16, + Self::V128Splat32 => Ident::Splat32, + Self::V128Splat64 => Ident::Splat64, Self::V128Not => Ident::Not, Self::V128AnyTrue => Ident::AnyTrue, // SIMD: `i8x16` Unary Ops @@ -1384,6 +1397,10 @@ pub enum Ty { U32, /// A unsigned 64-bit integer type. U64, + /// A generic 8-bits value. + B8, + /// A generic 16-bits value. + B16, /// A generic 32-bits value. B32, /// A generic 64-bits value. @@ -1425,8 +1442,14 @@ pub enum Ty { } impl Ty { + pub fn is_wasm(&self) -> bool { + !matches!(self, Self::B8 | Self::B16 | Self::B32 | Self::B64) + } + pub fn to_field_ty(self) -> Option { let ty = match self { + | Ty::B8 => FieldTy::U8, + | Ty::B16 => FieldTy::U16, | Ty::S32 | Ty::I32 => FieldTy::I32, | Ty::S64 | Ty::I64 => FieldTy::I64, | Ty::B32 | Ty::U32 => FieldTy::U32, @@ -1448,6 +1471,8 @@ impl Display for Ty { Ty::S64 => "i64", Ty::U32 => "u32", Ty::U64 => "u64", + Ty::B8 => "8", + Ty::B16 => "16", Ty::B32 => "32", Ty::B64 => "64", Ty::F32 => "f32", @@ -1487,6 +1512,8 @@ impl Display for CamelCase { Ty::S64 => "I64", Ty::U32 => "U32", Ty::U64 => "U64", + Ty::B8 => "8", + Ty::B16 => "16", Ty::B32 => "32", Ty::B64 => "64", Ty::F32 => "F32", @@ -1515,6 +1542,7 @@ impl Display for CamelCase { pub enum FieldTy { Slot, SlotSpan, + BoundedSlotSpan, FixedSlotSpan2, U8, U16, @@ -1557,6 +1585,7 @@ impl Display for FieldTy { let s = match self { Self::Slot => "Slot", Self::SlotSpan => "SlotSpan", + Self::BoundedSlotSpan => "BoundedSlotSpan", Self::FixedSlotSpan2 => "FixedSlotSpan<2>", Self::U8 => "u8", Self::U16 => "u16", diff --git a/crates/ir2/src/encode.rs b/crates/ir2/src/encode.rs index e82c8d6dd2..e57efc98fd 100644 --- a/crates/ir2/src/encode.rs +++ b/crates/ir2/src/encode.rs @@ -42,6 +42,9 @@ pub trait Encoder { /// Registers an encoded [`BranchOffset`] to the encoder. /// + /// This is required in order to update the branch offsets of + /// branch operators once all forward branch offsets are known. + /// /// # Errors /// /// If the encoder cannot register the `branch_offset`. @@ -50,6 +53,16 @@ pub trait Encoder { pos: Self::Pos, branch_offset: BranchOffset, ) -> Result<(), Self::Error>; + + /// Registers an encoded [`BlockFuel`] to the encoder. + /// + /// This is required in order to update the consumed fuel of + /// [`Op::ConsumeFuel`] operators during translation. + /// + /// # Errors + /// + /// If the encoder cannot register the `block_fuel`. + fn block_fuel(&mut self, pos: Self::Pos, block_fuel: BlockFuel) -> Result<(), Self::Error>; } /// Types that can be encoded by types that implement [`Encoder`]. @@ -80,6 +93,17 @@ impl Encode for BranchOffset { } } +impl Encode for BlockFuel { + fn encode(&self, encoder: &mut E) -> Result + where + E: Encoder, + { + let pos = u64::from(*self).encode(encoder)?; + encoder.block_fuel(pos, *self)?; + Ok(pos) + } +} + impl Encode for BoundedSlotSpan { fn encode(&self, encoder: &mut E) -> Result { (self.span(), self.len()).encode(encoder) @@ -128,7 +152,6 @@ macro_rules! impl_encode_using { impl_encode_using! { bool as u8 = Into::into, Offset16 as u16 = Into::into, - BlockFuel as u64 = Into::into, Address as u64 = Into::into, Slot as u16 = Into::into, Func as u32 = Into::into, diff --git a/crates/ir2/src/op.rs b/crates/ir2/src/op.rs index 4eb10d1c72..0e10d9aa3c 100644 --- a/crates/ir2/src/op.rs +++ b/crates/ir2/src/op.rs @@ -5,6 +5,7 @@ use crate::{ index::{Data, Elem, Func, FuncType, Global, InternalFunc, Memory, Table}, Address, BlockFuel, + BoundedSlotSpan, BranchOffset, FixedSlotSpan, Offset16,