diff --git a/Cargo.toml b/Cargo.toml index 7fde3f87..efa37b40 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -29,7 +29,7 @@ leb128 = "0.2.4" log = "0.4.8" rayon = { version = "1.1.0", optional = true } walrus-macro = { path = './crates/macro', version = '=0.13.0' } -wasmparser = "0.39.1" +wasmparser = "0.42.0" [features] parallel = ['rayon', 'id-arena/rayon'] diff --git a/crates/tests/tests/spec-tests.rs b/crates/tests/tests/spec-tests.rs index cc13dcc1..8ceaea22 100644 --- a/crates/tests/tests/spec-tests.rs +++ b/crates/tests/tests/spec-tests.rs @@ -26,6 +26,7 @@ fn run(wast: &Path) -> Result<(), anyhow::Error> { None => &[], Some("mutable-global") => &[], Some("sign-extension-ops") => &["--enable-sign-extension"], + Some("multi-value") => &["--enable-multi-value"], Some("nontrapping-float-to-int-conversions") => &["--enable-saturating-float-to-int"], // Currently wabt doesn't have support for `ref.host` which is used in @@ -35,9 +36,6 @@ fn run(wast: &Path) -> Result<(), anyhow::Error> { // Currently wabt has broken support for `ref.func` initializers Some("bulk-memory-operations") => return Ok(()), - // TODO: we should actually implement this proposal! - Some("multi-value") => return Ok(()), - // TODO: should get threads working Some("threads") => return Ok(()), // Some("threads") => &["--enable-threads"], diff --git a/src/init_expr.rs b/src/init_expr.rs index a81dbc79..f17f5aeb 100644 --- a/src/init_expr.rs +++ b/src/init_expr.rs @@ -25,7 +25,8 @@ impl InitExpr { I64Const { value } => InitExpr::Value(Value::I64(value)), F32Const { value } => InitExpr::Value(Value::F32(f32::from_bits(value.bits()))), F64Const { value } => InitExpr::Value(Value::F64(f64::from_bits(value.bits()))), - GetGlobal { global_index } => InitExpr::Global(ids.get_global(global_index)?), + V128Const { value } => InitExpr::Value(Value::V128(v128_to_u128(&value))), + GlobalGet { global_index } => InitExpr::Global(ids.get_global(global_index)?), _ => bail!("invalid constant expression"), }; match reader.read()? { @@ -50,3 +51,23 @@ impl Emit for InitExpr { cx.encoder.byte(0x0b); // end } } + +pub(crate) fn v128_to_u128(value: &wasmparser::V128) -> u128 { + let n = value.bytes(); + ((n[0] as u128) << 0) + | ((n[1] as u128) << 8) + | ((n[2] as u128) << 16) + | ((n[3] as u128) << 24) + | ((n[4] as u128) << 32) + | ((n[5] as u128) << 40) + | ((n[6] as u128) << 48) + | ((n[7] as u128) << 56) + | ((n[8] as u128) << 64) + | ((n[9] as u128) << 72) + | ((n[10] as u128) << 80) + | ((n[11] as u128) << 88) + | ((n[12] as u128) << 96) + | ((n[13] as u128) << 104) + | ((n[14] as u128) << 112) + | ((n[15] as u128) << 120) +} diff --git a/src/ir/mod.rs b/src/ir/mod.rs index 56c82f8d..edfc7c8c 100644 --- a/src/ir/mod.rs +++ b/src/ir/mod.rs @@ -508,12 +508,24 @@ pub enum Instr { table: TableId, }, + /// `table.fill` + TableFill { + /// The table we're filling + table: TableId, + }, + /// `ref.null` RefNull {}, /// `ref.is_null` RefIsNull {}, + /// `ref.func` + RefFunc { + /// The function that this instruction is referencing + func: FunctionId, + }, + /// `v128.bitselect` V128Bitselect {}, @@ -1127,8 +1139,10 @@ impl Instr { | Instr::TableSet(..) | Instr::TableGrow(..) | Instr::TableSize(..) + | Instr::TableFill(..) | Instr::RefNull(..) | Instr::RefIsNull(..) + | Instr::RefFunc(..) | Instr::V128Bitselect(..) | Instr::V128Swizzle(..) | Instr::V128Shuffle(..) diff --git a/src/module/elements.rs b/src/module/elements.rs index bb350cf3..4d5d7d8e 100644 --- a/src/module/elements.rs +++ b/src/module/elements.rs @@ -76,12 +76,13 @@ impl Module { let segment = segment?; match segment.kind { - wasmparser::ElementKind::Passive(_) => { + wasmparser::ElementKind::Passive { .. } => { bail!("passive element segments not supported yet"); } wasmparser::ElementKind::Active { table_index, init_expr, + items, } => { let table = ids.get_table(table_index)?; let table = match &mut self.tables.get_mut(table).kind { @@ -93,7 +94,7 @@ impl Module { let offset = InitExpr::eval(&init_expr, ids) .with_context(|| format!("in segment {}", i))?; - let functions = segment.items.get_items_reader()?.into_iter().map(|func| { + let functions = items.get_items_reader()?.into_iter().map(|func| { let func = func?; ids.get_func(func) }); diff --git a/src/module/functions/local_function/emit.rs b/src/module/functions/local_function/emit.rs index 77928142..a61401ea 100644 --- a/src/module/functions/local_function/emit.rs +++ b/src/module/functions/local_function/emit.rs @@ -752,12 +752,22 @@ impl<'instr> Visitor<'instr> for Emit<'_, '_> { let idx = self.indices.get_table_index(e.table); self.encoder.u32(idx); } + TableFill(e) => { + self.encoder.raw(&[0xfc, 0x11]); + let idx = self.indices.get_table_index(e.table); + self.encoder.u32(idx); + } RefNull(_e) => { self.encoder.byte(0xd0); } RefIsNull(_e) => { self.encoder.byte(0xd1); } + RefFunc(e) => { + self.encoder.byte(0xd2); + let idx = self.indices.get_func_index(e.func); + self.encoder.u32(idx); + } V128Bitselect(_) => { self.simd(0x50); diff --git a/src/module/functions/local_function/mod.rs b/src/module/functions/local_function/mod.rs index 3d1f0c67..560b09af 100644 --- a/src/module/functions/local_function/mod.rs +++ b/src/module/functions/local_function/mod.rs @@ -409,26 +409,26 @@ fn validate_instruction<'context>( ctx.alloc_instr(CallIndirect { table, ty: type_id }, loc); ctx.push_operands(ty.results()); } - Operator::GetLocal { local_index } => { + Operator::LocalGet { local_index } => { let local = ctx.indices.get_local(ctx.func_id, local_index)?; let ty = ctx.module.locals.get(local).ty(); ctx.alloc_instr(LocalGet { local }, loc); ctx.push_operand(Some(ty)); } - Operator::SetLocal { local_index } => { + Operator::LocalSet { local_index } => { let local = ctx.indices.get_local(ctx.func_id, local_index)?; let ty = ctx.module.locals.get(local).ty(); ctx.pop_operand_expected(Some(ty))?; ctx.alloc_instr(LocalSet { local }, loc); } - Operator::TeeLocal { local_index } => { + Operator::LocalTee { local_index } => { let local = ctx.indices.get_local(ctx.func_id, local_index)?; let ty = ctx.module.locals.get(local).ty(); ctx.pop_operand_expected(Some(ty))?; ctx.alloc_instr(LocalTee { local }, loc); ctx.push_operand(Some(ty)); } - Operator::GetGlobal { global_index } => { + Operator::GlobalGet { global_index } => { let global = ctx .indices .get_global(global_index) @@ -437,7 +437,7 @@ fn validate_instruction<'context>( ctx.alloc_instr(GlobalGet { global }, loc); ctx.push_operand(Some(ty)); } - Operator::SetGlobal { global_index } => { + Operator::GlobalSet { global_index } => { let global = ctx .indices .get_global(global_index) @@ -455,23 +455,7 @@ fn validate_instruction<'context>( const_(ctx, F64, Value::F64(f64::from_bits(value.bits()))); } Operator::V128Const { value } => { - let n = value.bytes(); - let val = ((n[0] as u128) << 0) - | ((n[1] as u128) << 8) - | ((n[2] as u128) << 16) - | ((n[3] as u128) << 24) - | ((n[4] as u128) << 32) - | ((n[5] as u128) << 40) - | ((n[6] as u128) << 48) - | ((n[7] as u128) << 56) - | ((n[8] as u128) << 64) - | ((n[9] as u128) << 72) - | ((n[10] as u128) << 80) - | ((n[11] as u128) << 88) - | ((n[12] as u128) << 96) - | ((n[13] as u128) << 104) - | ((n[14] as u128) << 112) - | ((n[15] as u128) << 120); + let val = crate::init_expr::v128_to_u128(&value); const_(ctx, V128, Value::V128(val)); } Operator::I32Eqz => testop(ctx, I32, UnaryOp::I32Eqz)?, @@ -581,28 +565,28 @@ fn validate_instruction<'context>( Operator::F64Copysign => binop(ctx, F64, BinaryOp::F64Copysign)?, Operator::I32WrapI64 => one_op(ctx, I64, I32, UnaryOp::I32WrapI64)?, - Operator::I32TruncSF32 => one_op(ctx, F32, I32, UnaryOp::I32TruncSF32)?, - Operator::I32TruncUF32 => one_op(ctx, F32, I32, UnaryOp::I32TruncUF32)?, - Operator::I32TruncSF64 => one_op(ctx, F64, I32, UnaryOp::I32TruncSF64)?, - Operator::I32TruncUF64 => one_op(ctx, F64, I32, UnaryOp::I32TruncUF64)?, - - Operator::I64ExtendSI32 => one_op(ctx, I32, I64, UnaryOp::I64ExtendSI32)?, - Operator::I64ExtendUI32 => one_op(ctx, I32, I64, UnaryOp::I64ExtendUI32)?, - Operator::I64TruncSF32 => one_op(ctx, F32, I64, UnaryOp::I64TruncSF32)?, - Operator::I64TruncUF32 => one_op(ctx, F32, I64, UnaryOp::I64TruncUF32)?, - Operator::I64TruncSF64 => one_op(ctx, F64, I64, UnaryOp::I64TruncSF64)?, - Operator::I64TruncUF64 => one_op(ctx, F64, I64, UnaryOp::I64TruncUF64)?, - - Operator::F32ConvertSI32 => one_op(ctx, I32, F32, UnaryOp::F32ConvertSI32)?, - Operator::F32ConvertUI32 => one_op(ctx, I32, F32, UnaryOp::F32ConvertUI32)?, - Operator::F32ConvertSI64 => one_op(ctx, I64, F32, UnaryOp::F32ConvertSI64)?, - Operator::F32ConvertUI64 => one_op(ctx, I64, F32, UnaryOp::F32ConvertUI64)?, + Operator::I32TruncF32S => one_op(ctx, F32, I32, UnaryOp::I32TruncSF32)?, + Operator::I32TruncF32U => one_op(ctx, F32, I32, UnaryOp::I32TruncUF32)?, + Operator::I32TruncF64S => one_op(ctx, F64, I32, UnaryOp::I32TruncSF64)?, + Operator::I32TruncF64U => one_op(ctx, F64, I32, UnaryOp::I32TruncUF64)?, + + Operator::I64ExtendI32S => one_op(ctx, I32, I64, UnaryOp::I64ExtendSI32)?, + Operator::I64ExtendI32U => one_op(ctx, I32, I64, UnaryOp::I64ExtendUI32)?, + Operator::I64TruncF32S => one_op(ctx, F32, I64, UnaryOp::I64TruncSF32)?, + Operator::I64TruncF32U => one_op(ctx, F32, I64, UnaryOp::I64TruncUF32)?, + Operator::I64TruncF64S => one_op(ctx, F64, I64, UnaryOp::I64TruncSF64)?, + Operator::I64TruncF64U => one_op(ctx, F64, I64, UnaryOp::I64TruncUF64)?, + + Operator::F32ConvertI32S => one_op(ctx, I32, F32, UnaryOp::F32ConvertSI32)?, + Operator::F32ConvertI32U => one_op(ctx, I32, F32, UnaryOp::F32ConvertUI32)?, + Operator::F32ConvertI64S => one_op(ctx, I64, F32, UnaryOp::F32ConvertSI64)?, + Operator::F32ConvertI64U => one_op(ctx, I64, F32, UnaryOp::F32ConvertUI64)?, Operator::F32DemoteF64 => one_op(ctx, F64, F32, UnaryOp::F32DemoteF64)?, - Operator::F64ConvertSI32 => one_op(ctx, I32, F64, UnaryOp::F64ConvertSI32)?, - Operator::F64ConvertUI32 => one_op(ctx, I32, F64, UnaryOp::F64ConvertUI32)?, - Operator::F64ConvertSI64 => one_op(ctx, I64, F64, UnaryOp::F64ConvertSI64)?, - Operator::F64ConvertUI64 => one_op(ctx, I64, F64, UnaryOp::F64ConvertUI64)?, + Operator::F64ConvertI32S => one_op(ctx, I32, F64, UnaryOp::F64ConvertSI32)?, + Operator::F64ConvertI32U => one_op(ctx, I32, F64, UnaryOp::F64ConvertUI32)?, + Operator::F64ConvertI64S => one_op(ctx, I64, F64, UnaryOp::F64ConvertSI64)?, + Operator::F64ConvertI64U => one_op(ctx, I64, F64, UnaryOp::F64ConvertUI64)?, Operator::F64PromoteF32 => one_op(ctx, F32, F64, UnaryOp::F64PromoteF32)?, Operator::I32ReinterpretF32 => one_op(ctx, F32, I32, UnaryOp::I32ReinterpretF32)?, @@ -897,7 +881,7 @@ fn validate_instruction<'context>( store(ctx, memarg, I64, StoreKind::I64_32 { atomic: false })? } - Operator::Fence { flags } => { + Operator::AtomicFence { flags } => { if flags != 0 { bail!("fence with nonzero flags not supported yet"); } @@ -979,19 +963,19 @@ fn validate_instruction<'context>( Operator::I64AtomicRmwAdd { memarg } => { atomicrmw(ctx, memarg, I64, AtomicOp::Add, AtomicWidth::I64)?; } - Operator::I32AtomicRmw8UAdd { memarg } => { + Operator::I32AtomicRmw8AddU { memarg } => { atomicrmw(ctx, memarg, I32, AtomicOp::Add, AtomicWidth::I32_8)?; } - Operator::I32AtomicRmw16UAdd { memarg } => { + Operator::I32AtomicRmw16AddU { memarg } => { atomicrmw(ctx, memarg, I32, AtomicOp::Add, AtomicWidth::I32_16)?; } - Operator::I64AtomicRmw8UAdd { memarg } => { + Operator::I64AtomicRmw8AddU { memarg } => { atomicrmw(ctx, memarg, I64, AtomicOp::Add, AtomicWidth::I64_8)?; } - Operator::I64AtomicRmw16UAdd { memarg } => { + Operator::I64AtomicRmw16AddU { memarg } => { atomicrmw(ctx, memarg, I64, AtomicOp::Add, AtomicWidth::I64_16)?; } - Operator::I64AtomicRmw32UAdd { memarg } => { + Operator::I64AtomicRmw32AddU { memarg } => { atomicrmw(ctx, memarg, I64, AtomicOp::Add, AtomicWidth::I64_32)?; } @@ -1001,19 +985,19 @@ fn validate_instruction<'context>( Operator::I64AtomicRmwSub { memarg } => { atomicrmw(ctx, memarg, I64, AtomicOp::Sub, AtomicWidth::I64)?; } - Operator::I32AtomicRmw8USub { memarg } => { + Operator::I32AtomicRmw8SubU { memarg } => { atomicrmw(ctx, memarg, I32, AtomicOp::Sub, AtomicWidth::I32_8)?; } - Operator::I32AtomicRmw16USub { memarg } => { + Operator::I32AtomicRmw16SubU { memarg } => { atomicrmw(ctx, memarg, I32, AtomicOp::Sub, AtomicWidth::I32_16)?; } - Operator::I64AtomicRmw8USub { memarg } => { + Operator::I64AtomicRmw8SubU { memarg } => { atomicrmw(ctx, memarg, I64, AtomicOp::Sub, AtomicWidth::I64_8)?; } - Operator::I64AtomicRmw16USub { memarg } => { + Operator::I64AtomicRmw16SubU { memarg } => { atomicrmw(ctx, memarg, I64, AtomicOp::Sub, AtomicWidth::I64_16)?; } - Operator::I64AtomicRmw32USub { memarg } => { + Operator::I64AtomicRmw32SubU { memarg } => { atomicrmw(ctx, memarg, I64, AtomicOp::Sub, AtomicWidth::I64_32)?; } @@ -1023,19 +1007,19 @@ fn validate_instruction<'context>( Operator::I64AtomicRmwAnd { memarg } => { atomicrmw(ctx, memarg, I64, AtomicOp::And, AtomicWidth::I64)?; } - Operator::I32AtomicRmw8UAnd { memarg } => { + Operator::I32AtomicRmw8AndU { memarg } => { atomicrmw(ctx, memarg, I32, AtomicOp::And, AtomicWidth::I32_8)?; } - Operator::I32AtomicRmw16UAnd { memarg } => { + Operator::I32AtomicRmw16AndU { memarg } => { atomicrmw(ctx, memarg, I32, AtomicOp::And, AtomicWidth::I32_16)?; } - Operator::I64AtomicRmw8UAnd { memarg } => { + Operator::I64AtomicRmw8AndU { memarg } => { atomicrmw(ctx, memarg, I64, AtomicOp::And, AtomicWidth::I64_8)?; } - Operator::I64AtomicRmw16UAnd { memarg } => { + Operator::I64AtomicRmw16AndU { memarg } => { atomicrmw(ctx, memarg, I64, AtomicOp::And, AtomicWidth::I64_16)?; } - Operator::I64AtomicRmw32UAnd { memarg } => { + Operator::I64AtomicRmw32AndU { memarg } => { atomicrmw(ctx, memarg, I64, AtomicOp::And, AtomicWidth::I64_32)?; } @@ -1045,19 +1029,19 @@ fn validate_instruction<'context>( Operator::I64AtomicRmwOr { memarg } => { atomicrmw(ctx, memarg, I64, AtomicOp::Or, AtomicWidth::I64)?; } - Operator::I32AtomicRmw8UOr { memarg } => { + Operator::I32AtomicRmw8OrU { memarg } => { atomicrmw(ctx, memarg, I32, AtomicOp::Or, AtomicWidth::I32_8)?; } - Operator::I32AtomicRmw16UOr { memarg } => { + Operator::I32AtomicRmw16OrU { memarg } => { atomicrmw(ctx, memarg, I32, AtomicOp::Or, AtomicWidth::I32_16)?; } - Operator::I64AtomicRmw8UOr { memarg } => { + Operator::I64AtomicRmw8OrU { memarg } => { atomicrmw(ctx, memarg, I64, AtomicOp::Or, AtomicWidth::I64_8)?; } - Operator::I64AtomicRmw16UOr { memarg } => { + Operator::I64AtomicRmw16OrU { memarg } => { atomicrmw(ctx, memarg, I64, AtomicOp::Or, AtomicWidth::I64_16)?; } - Operator::I64AtomicRmw32UOr { memarg } => { + Operator::I64AtomicRmw32OrU { memarg } => { atomicrmw(ctx, memarg, I64, AtomicOp::Or, AtomicWidth::I64_32)?; } @@ -1067,19 +1051,19 @@ fn validate_instruction<'context>( Operator::I64AtomicRmwXor { memarg } => { atomicrmw(ctx, memarg, I64, AtomicOp::Xor, AtomicWidth::I64)?; } - Operator::I32AtomicRmw8UXor { memarg } => { + Operator::I32AtomicRmw8XorU { memarg } => { atomicrmw(ctx, memarg, I32, AtomicOp::Xor, AtomicWidth::I32_8)?; } - Operator::I32AtomicRmw16UXor { memarg } => { + Operator::I32AtomicRmw16XorU { memarg } => { atomicrmw(ctx, memarg, I32, AtomicOp::Xor, AtomicWidth::I32_16)?; } - Operator::I64AtomicRmw8UXor { memarg } => { + Operator::I64AtomicRmw8XorU { memarg } => { atomicrmw(ctx, memarg, I64, AtomicOp::Xor, AtomicWidth::I64_8)?; } - Operator::I64AtomicRmw16UXor { memarg } => { + Operator::I64AtomicRmw16XorU { memarg } => { atomicrmw(ctx, memarg, I64, AtomicOp::Xor, AtomicWidth::I64_16)?; } - Operator::I64AtomicRmw32UXor { memarg } => { + Operator::I64AtomicRmw32XorU { memarg } => { atomicrmw(ctx, memarg, I64, AtomicOp::Xor, AtomicWidth::I64_32)?; } @@ -1089,19 +1073,19 @@ fn validate_instruction<'context>( Operator::I64AtomicRmwXchg { memarg } => { atomicrmw(ctx, memarg, I64, AtomicOp::Xchg, AtomicWidth::I64)?; } - Operator::I32AtomicRmw8UXchg { memarg } => { + Operator::I32AtomicRmw8XchgU { memarg } => { atomicrmw(ctx, memarg, I32, AtomicOp::Xchg, AtomicWidth::I32_8)?; } - Operator::I32AtomicRmw16UXchg { memarg } => { + Operator::I32AtomicRmw16XchgU { memarg } => { atomicrmw(ctx, memarg, I32, AtomicOp::Xchg, AtomicWidth::I32_16)?; } - Operator::I64AtomicRmw8UXchg { memarg } => { + Operator::I64AtomicRmw8XchgU { memarg } => { atomicrmw(ctx, memarg, I64, AtomicOp::Xchg, AtomicWidth::I64_8)?; } - Operator::I64AtomicRmw16UXchg { memarg } => { + Operator::I64AtomicRmw16XchgU { memarg } => { atomicrmw(ctx, memarg, I64, AtomicOp::Xchg, AtomicWidth::I64_16)?; } - Operator::I64AtomicRmw32UXchg { memarg } => { + Operator::I64AtomicRmw32XchgU { memarg } => { atomicrmw(ctx, memarg, I64, AtomicOp::Xchg, AtomicWidth::I64_32)?; } @@ -1111,22 +1095,22 @@ fn validate_instruction<'context>( Operator::I64AtomicRmwCmpxchg { memarg } => { cmpxchg(ctx, memarg, I64, AtomicWidth::I64)?; } - Operator::I32AtomicRmw8UCmpxchg { memarg } => { + Operator::I32AtomicRmw8CmpxchgU { memarg } => { cmpxchg(ctx, memarg, I32, AtomicWidth::I32_8)?; } - Operator::I32AtomicRmw16UCmpxchg { memarg } => { + Operator::I32AtomicRmw16CmpxchgU { memarg } => { cmpxchg(ctx, memarg, I32, AtomicWidth::I32_16)?; } - Operator::I64AtomicRmw8UCmpxchg { memarg } => { + Operator::I64AtomicRmw8CmpxchgU { memarg } => { cmpxchg(ctx, memarg, I64, AtomicWidth::I64_8)?; } - Operator::I64AtomicRmw16UCmpxchg { memarg } => { + Operator::I64AtomicRmw16CmpxchgU { memarg } => { cmpxchg(ctx, memarg, I64, AtomicWidth::I64_16)?; } - Operator::I64AtomicRmw32UCmpxchg { memarg } => { + Operator::I64AtomicRmw32CmpxchgU { memarg } => { cmpxchg(ctx, memarg, I64, AtomicWidth::I64_32)?; } - Operator::Wake { ref memarg } => { + Operator::AtomicNotify { ref memarg } => { ctx.pop_operand_expected(Some(I32))?; ctx.pop_operand_expected(Some(I32))?; let memory = ctx.indices.get_memory(0)?; @@ -1139,9 +1123,9 @@ fn validate_instruction<'context>( ); ctx.push_operand(Some(I32)); } - Operator::I32Wait { ref memarg } | Operator::I64Wait { ref memarg } => { + Operator::I32AtomicWait { ref memarg } | Operator::I64AtomicWait { ref memarg } => { let (ty, sixty_four) = match inst { - Operator::I32Wait { .. } => (I32, false), + Operator::I32AtomicWait { .. } => (I32, false), _ => (I64, true), }; ctx.pop_operand_expected(Some(I64))?; @@ -1191,6 +1175,17 @@ fn validate_instruction<'context>( ctx.alloc_instr(TableSize { table }, loc); ctx.push_operand(Some(I32)); } + Operator::TableFill { table } => { + let table = ctx.indices.get_table(table)?; + let expected_ty = match ctx.module.tables.get(table).kind { + TableKind::Anyref(_) => Anyref, + TableKind::Function(_) => bail!("cannot set function table yet"), + }; + ctx.pop_operand_expected(Some(I32))?; + ctx.pop_operand_expected(Some(expected_ty))?; + ctx.pop_operand_expected(Some(I32))?; + ctx.alloc_instr(TableFill { table }, loc); + } Operator::RefNull => { ctx.alloc_instr(RefNull {}, loc); ctx.push_operand(Some(Anyref)); @@ -1200,6 +1195,14 @@ fn validate_instruction<'context>( ctx.alloc_instr(RefIsNull {}, loc); ctx.push_operand(Some(I32)); } + Operator::RefFunc { function_index }=> { + let func = ctx + .indices + .get_func(function_index) + .context("invalid call")?; + ctx.alloc_instr(RefFunc { func }, loc); + ctx.push_operand(Some(Anyref)); + } Operator::V8x16Swizzle => { ctx.pop_operand_expected(Some(V128))?; @@ -1387,28 +1390,28 @@ fn validate_instruction<'context>( Operator::F64x2Min => binop(ctx, V128, BinaryOp::F64x2Min)?, Operator::F64x2Max => binop(ctx, V128, BinaryOp::F64x2Max)?, - Operator::I32x4TruncSF32x4Sat => unop(ctx, V128, UnaryOp::I32x4TruncSF32x4Sat)?, - Operator::I32x4TruncUF32x4Sat => unop(ctx, V128, UnaryOp::I32x4TruncUF32x4Sat)?, - Operator::I64x2TruncSF64x2Sat => unop(ctx, V128, UnaryOp::I64x2TruncSF64x2Sat)?, - Operator::I64x2TruncUF64x2Sat => unop(ctx, V128, UnaryOp::I64x2TruncUF64x2Sat)?, - Operator::F32x4ConvertSI32x4 => unop(ctx, V128, UnaryOp::F32x4ConvertSI32x4)?, - Operator::F32x4ConvertUI32x4 => unop(ctx, V128, UnaryOp::F32x4ConvertUI32x4)?, - Operator::F64x2ConvertSI64x2 => unop(ctx, V128, UnaryOp::F64x2ConvertSI64x2)?, - Operator::F64x2ConvertUI64x2 => unop(ctx, V128, UnaryOp::F64x2ConvertUI64x2)?, - - Operator::I32TruncSSatF32 => one_op(ctx, F32, I32, UnaryOp::I32TruncSSatF32)?, - Operator::I32TruncUSatF32 => one_op(ctx, F32, I32, UnaryOp::I32TruncUSatF32)?, - Operator::I32TruncSSatF64 => one_op(ctx, F64, I32, UnaryOp::I32TruncSSatF64)?, - Operator::I32TruncUSatF64 => one_op(ctx, F64, I32, UnaryOp::I32TruncUSatF64)?, - Operator::I64TruncSSatF32 => one_op(ctx, F32, I64, UnaryOp::I64TruncSSatF32)?, - Operator::I64TruncUSatF32 => one_op(ctx, F32, I64, UnaryOp::I64TruncUSatF32)?, - Operator::I64TruncSSatF64 => one_op(ctx, F64, I64, UnaryOp::I64TruncSSatF64)?, - Operator::I64TruncUSatF64 => one_op(ctx, F64, I64, UnaryOp::I64TruncUSatF64)?, - - Operator::I8x16LoadSplat { memarg } => load_splat(ctx, memarg, LoadSplatKind::I8)?, - Operator::I16x8LoadSplat { memarg } => load_splat(ctx, memarg, LoadSplatKind::I16)?, - Operator::I32x4LoadSplat { memarg } => load_splat(ctx, memarg, LoadSplatKind::I32)?, - Operator::I64x2LoadSplat { memarg } => load_splat(ctx, memarg, LoadSplatKind::I64)?, + Operator::I32x4TruncSatF32x4S => unop(ctx, V128, UnaryOp::I32x4TruncSF32x4Sat)?, + Operator::I32x4TruncSatF32x4U => unop(ctx, V128, UnaryOp::I32x4TruncUF32x4Sat)?, + Operator::I64x2TruncSatF64x2S => unop(ctx, V128, UnaryOp::I64x2TruncSF64x2Sat)?, + Operator::I64x2TruncSatF64x2U => unop(ctx, V128, UnaryOp::I64x2TruncUF64x2Sat)?, + Operator::F32x4ConvertI32x4S => unop(ctx, V128, UnaryOp::F32x4ConvertSI32x4)?, + Operator::F32x4ConvertI32x4U => unop(ctx, V128, UnaryOp::F32x4ConvertUI32x4)?, + Operator::F64x2ConvertI64x2S => unop(ctx, V128, UnaryOp::F64x2ConvertSI64x2)?, + Operator::F64x2ConvertI64x2U => unop(ctx, V128, UnaryOp::F64x2ConvertUI64x2)?, + + Operator::I32TruncSatF32S => one_op(ctx, F32, I32, UnaryOp::I32TruncSSatF32)?, + Operator::I32TruncSatF32U => one_op(ctx, F32, I32, UnaryOp::I32TruncUSatF32)?, + Operator::I32TruncSatF64S => one_op(ctx, F64, I32, UnaryOp::I32TruncSSatF64)?, + Operator::I32TruncSatF64U => one_op(ctx, F64, I32, UnaryOp::I32TruncUSatF64)?, + Operator::I64TruncSatF32S => one_op(ctx, F32, I64, UnaryOp::I64TruncSSatF32)?, + Operator::I64TruncSatF32U => one_op(ctx, F32, I64, UnaryOp::I64TruncUSatF32)?, + Operator::I64TruncSatF64S => one_op(ctx, F64, I64, UnaryOp::I64TruncSSatF64)?, + Operator::I64TruncSatF64U => one_op(ctx, F64, I64, UnaryOp::I64TruncUSatF64)?, + + Operator::V8x16LoadSplat { memarg } => load_splat(ctx, memarg, LoadSplatKind::I8)?, + Operator::V16x8LoadSplat { memarg } => load_splat(ctx, memarg, LoadSplatKind::I16)?, + Operator::V32x4LoadSplat { memarg } => load_splat(ctx, memarg, LoadSplatKind::I32)?, + Operator::V64x2LoadSplat { memarg } => load_splat(ctx, memarg, LoadSplatKind::I64)?, op @ Operator::TableInit { .. } | op @ Operator::ElemDrop { .. }