diff --git a/crates/wasm-encoder/src/component/builder.rs b/crates/wasm-encoder/src/component/builder.rs index 9a4099d7f7..c2065a249a 100644 --- a/crates/wasm-encoder/src/component/builder.rs +++ b/crates/wasm-encoder/src/component/builder.rs @@ -507,14 +507,14 @@ impl ComponentBuilder { } /// Declares a new `context.get` intrinsic. - pub fn context_get(&mut self, i: u32) -> u32 { - self.canonical_functions().context_get(i); + pub fn context_get(&mut self, ty: ValType, i: u32) -> u32 { + self.canonical_functions().context_get(ty, i); self.core_funcs.add(Some(&format!("context.get {i}"))) } /// Declares a new `context.set` intrinsic. - pub fn context_set(&mut self, i: u32) -> u32 { - self.canonical_functions().context_set(i); + pub fn context_set(&mut self, ty: ValType, i: u32) -> u32 { + self.canonical_functions().context_set(ty, i); self.core_funcs.add(Some(&format!("context.set {i}"))) } diff --git a/crates/wasm-encoder/src/component/canonicals.rs b/crates/wasm-encoder/src/component/canonicals.rs index b2fed82933..1e89d9cd62 100644 --- a/crates/wasm-encoder/src/component/canonicals.rs +++ b/crates/wasm-encoder/src/component/canonicals.rs @@ -1,4 +1,6 @@ -use crate::{ComponentSection, ComponentSectionId, ComponentValType, Encode, encode_section}; +use crate::{ + ComponentSection, ComponentSectionId, ComponentValType, Encode, ValType, encode_section, +}; use alloc::vec::Vec; /// Represents options for canonical function definitions. @@ -234,19 +236,21 @@ impl CanonicalFunctionSection { self } - /// Defines a new `context.get` intrinsic of the ith slot. - pub fn context_get(&mut self, i: u32) -> &mut Self { + /// Defines a new `context.get` intrinsic of the ith slot with the given + /// value type. + pub fn context_get(&mut self, ty: ValType, i: u32) -> &mut Self { self.bytes.push(0x0a); - self.bytes.push(0x7f); + ty.encode(&mut self.bytes); i.encode(&mut self.bytes); self.num_added += 1; self } - /// Defines a new `context.set` intrinsic of the ith slot. - pub fn context_set(&mut self, i: u32) -> &mut Self { + /// Defines a new `context.set` intrinsic of the ith slot with the given + /// value type. + pub fn context_set(&mut self, ty: ValType, i: u32) -> &mut Self { self.bytes.push(0x0b); - self.bytes.push(0x7f); + ty.encode(&mut self.bytes); i.encode(&mut self.bytes); self.num_added += 1; self diff --git a/crates/wasm-encoder/src/reencode/component.rs b/crates/wasm-encoder/src/reencode/component.rs index 464c28a20e..acb753713b 100644 --- a/crates/wasm-encoder/src/reencode/component.rs +++ b/crates/wasm-encoder/src/reencode/component.rs @@ -996,11 +996,11 @@ pub mod component_utils { wasmparser::CanonicalFunction::TaskCancel => { section.task_cancel(); } - wasmparser::CanonicalFunction::ContextGet(i) => { - section.context_get(i); + wasmparser::CanonicalFunction::ContextGet { ty, slot } => { + section.context_get(reencoder.val_type(ty)?, slot); } - wasmparser::CanonicalFunction::ContextSet(i) => { - section.context_set(i); + wasmparser::CanonicalFunction::ContextSet { ty, slot } => { + section.context_set(reencoder.val_type(ty)?, slot); } wasmparser::CanonicalFunction::ThreadYield { cancellable } => { section.thread_yield(cancellable); diff --git a/crates/wasmparser/src/readers/component/canonicals.rs b/crates/wasmparser/src/readers/component/canonicals.rs index 26df1257cd..7876805d4b 100644 --- a/crates/wasmparser/src/readers/component/canonicals.rs +++ b/crates/wasmparser/src/readers/component/canonicals.rs @@ -1,6 +1,6 @@ use crate::limits::MAX_WASM_CANONICAL_OPTIONS; use crate::prelude::*; -use crate::{BinaryReader, ComponentValType, FromReader, Result, SectionLimited}; +use crate::{BinaryReader, ComponentValType, FromReader, Result, SectionLimited, ValType}; /// Represents options for component functions. #[derive(Debug, Clone, Copy, PartialEq, Eq)] @@ -108,9 +108,23 @@ pub enum CanonicalFunction { /// A function to acknowledge cancellation of the current task. TaskCancel, /// A `context.get` intrinsic for the `i`th slot of task-local storage. - ContextGet(u32), + ContextGet { + /// The type of the slot. Currently only `ValType::I32` and + /// `ValType::I64` are accepted by the validator (with `I64` gated on + /// the component-model 64-bit feature). + ty: ValType, + /// The index of the task-local storage slot. + slot: u32, + }, /// A `context.set` intrinsic for the `i`th slot of task-local storage. - ContextSet(u32), + ContextSet { + /// The type of the slot. Currently only `ValType::I32` and + /// `ValType::I64` are accepted by the validator (with `I64` gated on + /// the component-model 64-bit feature). + ty: ValType, + /// The index of the task-local storage slot. + slot: u32, + }, /// A function which yields control to the host so that other tasks are able /// to make progress, if any. ThreadYield { @@ -337,13 +351,13 @@ impl<'a> FromReader<'a> for CanonicalFunction { result: crate::read_resultlist(reader)?, options: read_opts(reader)?, }, - 0x0a => match reader.read_u8()? { - 0x7f => CanonicalFunction::ContextGet(reader.read_var_u32()?), - x => return reader.invalid_leading_byte(x, "context.get intrinsic type"), + 0x0a => CanonicalFunction::ContextGet { + ty: reader.read()?, + slot: reader.read_var_u32()?, }, - 0x0b => match reader.read_u8()? { - 0x7f => CanonicalFunction::ContextSet(reader.read_var_u32()?), - x => return reader.invalid_leading_byte(x, "context.set intrinsic type"), + 0x0b => CanonicalFunction::ContextSet { + ty: reader.read()?, + slot: reader.read_var_u32()?, }, 0x0c => CanonicalFunction::ThreadYield { cancellable: reader.read()?, diff --git a/crates/wasmparser/src/validator/component.rs b/crates/wasmparser/src/validator/component.rs index f323315630..6ae9da4601 100644 --- a/crates/wasmparser/src/validator/component.rs +++ b/crates/wasmparser/src/validator/component.rs @@ -1203,8 +1203,8 @@ impl ComponentState { self.task_return(&result, &options, types, offset) } CanonicalFunction::TaskCancel => self.task_cancel(types, offset), - CanonicalFunction::ContextGet(i) => self.context_get(i, types, offset), - CanonicalFunction::ContextSet(i) => self.context_set(i, types, offset), + CanonicalFunction::ContextGet { ty, slot } => self.context_get(ty, slot, types, offset), + CanonicalFunction::ContextSet { ty, slot } => self.context_set(ty, slot, types, offset), CanonicalFunction::ThreadYield { cancellable: _ } => self.thread_yield(types, offset), CanonicalFunction::SubtaskDrop => self.subtask_drop(types, offset), CanonicalFunction::SubtaskCancel { async_ } => { @@ -1517,34 +1517,64 @@ impl ComponentState { Ok(()) } - fn context_get(&mut self, i: u32, types: &mut TypeAlloc, offset: usize) -> Result<()> { + fn context_get( + &mut self, + ty: ValType, + i: u32, + types: &mut TypeAlloc, + offset: usize, + ) -> Result<()> { if !self.features.cm_async() { bail!( offset, "`context.get` requires the component model async feature" ) } + self.validate_context_type(ty, "context.get", offset)?; self.validate_context_immediate(i, "context.get", offset)?; self.core_funcs - .push(types.intern_func_type(FuncType::new([], [ValType::I32]), offset)); + .push(types.intern_func_type(FuncType::new([], [ty]), offset)); Ok(()) } - fn context_set(&mut self, i: u32, types: &mut TypeAlloc, offset: usize) -> Result<()> { + fn context_set( + &mut self, + ty: ValType, + i: u32, + types: &mut TypeAlloc, + offset: usize, + ) -> Result<()> { if !self.features.cm_async() { bail!( offset, "`context.set` requires the component model async feature" ) } + self.validate_context_type(ty, "context.set", offset)?; self.validate_context_immediate(i, "context.set", offset)?; self.core_funcs - .push(types.intern_func_type(FuncType::new([ValType::I32], []), offset)); + .push(types.intern_func_type(FuncType::new([ty], []), offset)); Ok(()) } + fn validate_context_type(&self, ty: ValType, intrinsic: &str, offset: usize) -> Result<()> { + match ty { + ValType::I32 => Ok(()), + ValType::I64 => { + if !self.features.cm64() { + bail!( + offset, + "64-bit `{intrinsic}` requires the component model 64-bit feature" + ) + } + Ok(()) + } + _ => bail!(offset, "`{intrinsic}` only supports `i32` or `i64`"), + } + } + fn thread_yield(&mut self, types: &mut TypeAlloc, offset: usize) -> Result<()> { if !self.features.cm_async() { bail!( diff --git a/crates/wasmprinter/src/component.rs b/crates/wasmprinter/src/component.rs index e8a90b85f2..524760fd7a 100644 --- a/crates/wasmprinter/src/component.rs +++ b/crates/wasmprinter/src/component.rs @@ -977,15 +977,19 @@ impl Printer<'_, '_> { CanonicalFunction::TaskCancel => { self.print_intrinsic(state, "canon task.cancel", &|_, _| Ok(()))?; } - CanonicalFunction::ContextGet(i) => { - self.print_intrinsic(state, "canon context.get", &|me, _state| { - write!(me.result, " i32 {i}")?; + CanonicalFunction::ContextGet { ty, slot } => { + self.print_intrinsic(state, "canon context.get", &|me, state| { + me.result.write_str(" ")?; + me.print_valtype(state, ty)?; + write!(me.result, " {slot}")?; Ok(()) })?; } - CanonicalFunction::ContextSet(i) => { - self.print_intrinsic(state, "canon context.set", &|me, _state| { - write!(me.result, " i32 {i}")?; + CanonicalFunction::ContextSet { ty, slot } => { + self.print_intrinsic(state, "canon context.set", &|me, state| { + me.result.write_str(" ")?; + me.print_valtype(state, ty)?; + write!(me.result, " {slot}")?; Ok(()) })?; } diff --git a/crates/wast/src/component/binary.rs b/crates/wast/src/component/binary.rs index 658f238c3f..eb90edb6c8 100644 --- a/crates/wast/src/component/binary.rs +++ b/crates/wast/src/component/binary.rs @@ -392,13 +392,13 @@ impl<'a> Encoder<'a> { self.core_func_names.push(name); self.funcs.task_cancel(); } - CoreFuncKind::ContextGet(i) => { + CoreFuncKind::ContextGet(ty, i) => { self.core_func_names.push(name); - self.funcs.context_get(*i); + self.funcs.context_get((*ty).into(), *i); } - CoreFuncKind::ContextSet(i) => { + CoreFuncKind::ContextSet(ty, i) => { self.core_func_names.push(name); - self.funcs.context_set(*i); + self.funcs.context_set((*ty).into(), *i); } CoreFuncKind::ThreadYield(info) => { self.core_func_names.push(name); diff --git a/crates/wast/src/component/func.rs b/crates/wast/src/component/func.rs index bb995117a7..17d31b5f90 100644 --- a/crates/wast/src/component/func.rs +++ b/crates/wast/src/component/func.rs @@ -58,8 +58,8 @@ pub enum CoreFuncKind<'a> { BackpressureDec, TaskReturn(CanonTaskReturn<'a>), TaskCancel, - ContextGet(u32), - ContextSet(u32), + ContextGet(crate::core::ValType<'a>, u32), + ContextSet(crate::core::ValType<'a>, u32), ThreadYield(CanonThreadYield), SubtaskDrop, SubtaskCancel(CanonSubtaskCancel), @@ -139,12 +139,12 @@ impl<'a> CoreFuncKind<'a> { Ok(CoreFuncKind::TaskCancel) } else if l.peek::()? { parser.parse::()?; - parser.parse::()?; - Ok(CoreFuncKind::ContextGet(parser.parse()?)) + let ty = parser.parse()?; + Ok(CoreFuncKind::ContextGet(ty, parser.parse()?)) } else if l.peek::()? { parser.parse::()?; - parser.parse::()?; - Ok(CoreFuncKind::ContextSet(parser.parse()?)) + let ty = parser.parse()?; + Ok(CoreFuncKind::ContextSet(ty, parser.parse()?)) } else if l.peek::()? { Ok(CoreFuncKind::ThreadYield(parser.parse()?)) } else if l.peek::()? { diff --git a/crates/wast/src/component/resolve.rs b/crates/wast/src/component/resolve.rs index ca290fafe8..cca50c4f11 100644 --- a/crates/wast/src/component/resolve.rs +++ b/crates/wast/src/component/resolve.rs @@ -408,7 +408,8 @@ impl<'a> Resolver<'a> { } self.canon_opts(&mut info.opts)?; } - CoreFuncKind::ContextGet(_) | CoreFuncKind::ContextSet(_) => {} + CoreFuncKind::ContextGet(ty, _) => self.ref_type(ty)?, + CoreFuncKind::ContextSet(ty, _) => self.ref_type(ty)?, CoreFuncKind::StreamNew(info) => { self.resolve_ns(&mut info.ty, Ns::Type)?; } @@ -486,6 +487,18 @@ impl<'a> Resolver<'a> { Ok(()) } + fn ref_type(&mut self, ty: &mut ValType<'a>) -> Result<(), Error> { + Ok(match ty { + ValType::I32 | ValType::I64 | ValType::F32 | ValType::F64 | ValType::V128 => {} + ValType::Ref(r) => match &mut r.heap { + core::HeapType::Abstract { .. } => {} + core::HeapType::Concrete(id) | core::HeapType::Exact(id) => { + self.resolve_ns(id, Ns::Type)?; + } + }, + }) + } + fn canon_opts(&mut self, opts: &mut [CanonOpt<'a>]) -> Result<(), Error> { for opt in opts { match opt { @@ -658,15 +671,7 @@ impl<'a> Resolver<'a> { self.stack.pop(); } TypeDef::Resource(r) => { - match &mut r.rep { - ValType::I32 | ValType::I64 | ValType::F32 | ValType::F64 | ValType::V128 => {} - ValType::Ref(r) => match &mut r.heap { - core::HeapType::Abstract { .. } => {} - core::HeapType::Concrete(id) | core::HeapType::Exact(id) => { - self.resolve_ns(id, Ns::Type)?; - } - }, - } + self.ref_type(&mut r.rep)?; if let Some(dtor) = &mut r.dtor { self.core_item_ref(dtor)?; } diff --git a/crates/wit-component/src/encoding.rs b/crates/wit-component/src/encoding.rs index 958e1eb7df..e16e70cb3d 100644 --- a/crates/wit-component/src/encoding.rs +++ b/crates/wit-component/src/encoding.rs @@ -1977,12 +1977,12 @@ impl<'a> EncodingState<'a> { let index = self.component.waitable_join(); Ok((ExportKind::Func, index)) } - Import::ContextGet(n) => { - let index = self.component.context_get(*n); + Import::ContextGet { ty, slot } => { + let index = self.component.context_get((*ty).try_into()?, *slot); Ok((ExportKind::Func, index)) } - Import::ContextSet(n) => { - let index = self.component.context_set(*n); + Import::ContextSet { ty, slot } => { + let index = self.component.context_set((*ty).try_into()?, *slot); Ok((ExportKind::Func, index)) } Import::ExportedTaskCancel => { @@ -2630,8 +2630,8 @@ impl<'a> Shims<'a> { | Import::WaitableSetNew | Import::WaitableSetDrop | Import::WaitableJoin - | Import::ContextGet(_) - | Import::ContextSet(_) + | Import::ContextGet { .. } + | Import::ContextSet { .. } | Import::ThreadIndex | Import::ThreadSuspendToSuspended { .. } | Import::ThreadSuspend { .. } diff --git a/crates/wit-component/src/encoding/world.rs b/crates/wit-component/src/encoding/world.rs index 66b412e767..84cf92dd84 100644 --- a/crates/wit-component/src/encoding/world.rs +++ b/crates/wit-component/src/encoding/world.rs @@ -415,8 +415,8 @@ impl<'a> ComponentWorld<'a> { | Import::MainModuleMemory | Import::MainModuleExport { .. } | Import::Item(_) - | Import::ContextGet(_) - | Import::ContextSet(_) + | Import::ContextGet { .. } + | Import::ContextSet { .. } | Import::BackpressureInc | Import::BackpressureDec | Import::WaitableSetNew diff --git a/crates/wit-component/src/validation.rs b/crates/wit-component/src/validation.rs index a9d3d3e664..d7565b5600 100644 --- a/crates/wit-component/src/validation.rs +++ b/crates/wit-component/src/validation.rs @@ -276,9 +276,19 @@ pub enum Import { ExportedTaskCancel, /// The `context.get` intrinsic for the nth slot of storage. - ContextGet(u32), + ContextGet { + /// The type of the slot (`i32` or `i64`). + ty: ValType, + /// The index of the storage slot. + slot: u32, + }, /// The `context.set` intrinsic for the nth slot of storage. - ContextSet(u32), + ContextSet { + /// The type of the slot (`i32` or `i64`). + ty: ValType, + /// The index of the storage slot. + slot: u32, + }, /// A `canon backpressure.inc` intrinsic. BackpressureInc, @@ -685,15 +695,15 @@ impl ImportMap { return Ok(Import::ErrorContextDebugMessage { encoding }); } - if let Some(i) = names.context_get(name) { - let expected = FuncType::new([], [ValType::I32]); + if let Some((slot_ty, slot)) = names.context_get(name) { + let expected = FuncType::new([], [slot_ty]); validate_func_sig(name, &expected, ty)?; - return Ok(Import::ContextGet(i)); + return Ok(Import::ContextGet { ty: slot_ty, slot }); } - if let Some(i) = names.context_set(name) { - let expected = FuncType::new([ValType::I32], []); + if let Some((slot_ty, slot)) = names.context_set(name) { + let expected = FuncType::new([slot_ty], []); validate_func_sig(name, &expected, ty)?; - return Ok(Import::ContextSet(i)); + return Ok(Import::ContextSet { ty: slot_ty, slot }); } if names.thread_index(name) { let expected = FuncType::new([], [ValType::I32]); @@ -1583,8 +1593,8 @@ trait NameMangling { fn error_context_new(&self, name: &str) -> Option; fn error_context_debug_message(&self, name: &str) -> Option; fn error_context_drop(&self, name: &str) -> bool; - fn context_get(&self, name: &str) -> Option; - fn context_set(&self, name: &str) -> Option; + fn context_get(&self, name: &str) -> Option<(ValType, u32)>; + fn context_set(&self, name: &str) -> Option<(ValType, u32)>; fn future_new(&self, lookup_context: &PayloadLookupContext, name: &str) -> Option; fn future_write( &self, @@ -1776,10 +1786,10 @@ impl NameMangling for Standard { fn error_context_drop(&self, _name: &str) -> bool { false } - fn context_get(&self, _name: &str) -> Option { + fn context_get(&self, _name: &str) -> Option<(ValType, u32)> { None } - fn context_set(&self, _name: &str) -> Option { + fn context_set(&self, _name: &str) -> Option<(ValType, u32)> { None } fn thread_index(&self, _name: &str) -> bool { @@ -2235,13 +2245,11 @@ impl NameMangling for Legacy { fn error_context_drop(&self, name: &str) -> bool { name == "[error-context-drop]" } - fn context_get(&self, name: &str) -> Option { - let (n, rest) = prefixed_integer(name, "[context-get-")?; - if rest.is_empty() { Some(n) } else { None } + fn context_get(&self, name: &str) -> Option<(ValType, u32)> { + parse_context_name(name, "[context-get-") } - fn context_set(&self, name: &str) -> Option { - let (n, rest) = prefixed_integer(name, "[context-set-")?; - if rest.is_empty() { Some(n) } else { None } + fn context_set(&self, name: &str) -> Option<(ValType, u32)> { + parse_context_name(name, "[context-set-") } fn thread_index(&self, name: &str) -> bool { name == "[thread-index]" @@ -2700,11 +2708,23 @@ fn prefixed_intrinsic<'a>(name: &'a str, prefix: &str) -> Option<(&'a str, &'a s Some((&suffix[..index], rest)) } -/// Matches `name` as `[${prefix}N]...`, and if found returns `(N, "...")` -fn prefixed_integer<'a>(name: &'a str, prefix: &str) -> Option<(u32, &'a str)> { +/// Parses a `[context-get-]` / `[context-set-]` style name, optionally +/// carrying a type width infix: `[context-get-i64-]`. +/// +/// Returns the value type together with the numeric slot. Additional type +/// widths can be added here by extending the match below. +fn parse_context_name(name: &str, prefix: &str) -> Option<(ValType, u32)> { let (suffix, rest) = prefixed_intrinsic(name, prefix)?; - let n = suffix.parse().ok()?; - Some((n, rest)) + if !rest.is_empty() { + return None; + } + let (ty, slot) = match suffix.split_once('-') { + Some(("i64", slot)) => (ValType::I64, slot), + Some(("i32", slot)) => (ValType::I32, slot), + _ => (ValType::I32, suffix), + }; + let slot = slot.parse().ok()?; + Some((ty, slot)) } fn get_function<'a>( diff --git a/tests/cli/component-model/async/task-builtins.wast b/tests/cli/component-model/async/task-builtins.wast index 7cc328897e..ae8cca69f3 100644 --- a/tests/cli/component-model/async/task-builtins.wast +++ b/tests/cli/component-model/async/task-builtins.wast @@ -344,29 +344,41 @@ (component (core func (canon context.set i32 100))) "immediate must be zero: 100") -(assert_malformed - (component quote - "(core func (canon context.get i64 100))") - "expected keyword `i32`") -(assert_malformed - (component quote - "(core func (canon context.set i64 100))") - "expected keyword `i32`") +;; `i64` is accepted syntactically but requires the component model 64-bit +;; feature (`cm64`), which is not enabled by this test. +(assert_invalid + (component + (core func (canon context.get i64 0))) + "64-bit `context.get` requires the component model 64-bit feature") +(assert_invalid + (component + (core func (canon context.set i64 0))) + "64-bit `context.set` requires the component model 64-bit feature") -(assert_malformed +(assert_invalid (component binary "\00asm" "\0d\00\01\00" ;; component header "\08\04" ;; canonicals section, 4 bytes "\01" ;; 1 count "\0a\7e\00") ;; context.get i64 0 - "invalid leading byte (0x7e) for context.get") -(assert_malformed + "64-bit `context.get` requires the component model 64-bit feature") +(assert_invalid (component binary "\00asm" "\0d\00\01\00" ;; component header "\08\04" ;; canonicals section, 4 bytes "\01" ;; 1 count "\0b\7e\00") ;; context.set i64 0 - "invalid leading byte (0x7e) for context.set") + "64-bit `context.set` requires the component model 64-bit feature") + +;; Other value types (e.g. `f32`) are rejected regardless of the `cm64` feature. +(assert_invalid + (component + (core func (canon context.get f32 0))) + "`context.get` only supports `i32` or `i64`") +(assert_invalid + (component + (core func (canon context.set f32 0))) + "`context.set` only supports `i32` or `i64`") ;; different forms of canonical intrinsics diff --git a/tests/cli/component-model/memory64/context.wast b/tests/cli/component-model/memory64/context.wast new file mode 100644 index 0000000000..fd82df477c --- /dev/null +++ b/tests/cli/component-model/memory64/context.wast @@ -0,0 +1,69 @@ +;; RUN: wast --assert default --snapshot tests/snapshots % -f cm-async,cm64 + +;; i64 context.{get,set} slots are accepted when the component model 64-bit +;; feature is enabled. +(component + (core func $get0 (canon context.get i64 0)) + (core func $set0 (canon context.set i64 0)) + + (core module $m + (import "" "get0" (func (result i64))) + (import "" "set0" (func (param i64))) + ) + (core instance (instantiate $m + (with "" (instance + (export "get0" (func $get0)) + (export "set0" (func $set0)) + )) + )) +) + +;; Mixed i32 and i64 slots round-trip independently. +(component + (core func (canon context.get i32 0)) + (core func (canon context.set i32 0)) + (core func (canon context.get i64 0)) + (core func (canon context.set i64 0)) +) + +;; Signature must match the declared slot width. +(assert_invalid + (component + (core module $m (import "" "" (func (result i32)))) + (core func $f (canon context.get i64 0)) + (core instance (instantiate $m (with "" (instance (export "" (func $f)))))) + ) + "found: (func (result i64))") + +(assert_invalid + (component + (core module $m (import "" "" (func (param i32)))) + (core func $f (canon context.set i64 0)) + (core instance (instantiate $m (with "" (instance (export "" (func $f)))))) + ) + "found: (func (param i64))") + +(assert_invalid + (component + (core module $m (import "" "" (func (result i64)))) + (core func $f (canon context.get i32 0)) + (core instance (instantiate $m (with "" (instance (export "" (func $f)))))) + ) + "found: (func (result i32))") + +(assert_invalid + (component + (core module $m (import "" "" (func (param i64)))) + (core func $f (canon context.set i32 0)) + (core instance (instantiate $m (with "" (instance (export "" (func $f)))))) + ) + "found: (func (param i32))") + +;; Binary form: `0x7e` type byte is i64. +(component binary + "\00asm" "\0d\00\01\00" ;; component header + "\08\07" ;; canonicals section, 7 bytes + "\02" ;; 2 entries + "\0a\7e\00" ;; context.get i64 0 + "\0b\7e\00" ;; context.set i64 0 +) diff --git a/tests/snapshots/cli/component-model/async/task-builtins.wast.json b/tests/snapshots/cli/component-model/async/task-builtins.wast.json index 195e931af7..13cfdbf05c 100644 --- a/tests/snapshots/cli/component-model/async/task-builtins.wast.json +++ b/tests/snapshots/cli/component-model/async/task-builtins.wast.json @@ -251,43 +251,57 @@ "text": "immediate must be zero: 100" }, { - "type": "assert_malformed", - "line": 348, - "filename": "task-builtins.38.wat", - "module_type": "text", - "text": "expected keyword `i32`" + "type": "assert_invalid", + "line": 350, + "filename": "task-builtins.38.wasm", + "module_type": "binary", + "text": "64-bit `context.get` requires the component model 64-bit feature" }, { - "type": "assert_malformed", - "line": 352, - "filename": "task-builtins.39.wat", - "module_type": "text", - "text": "expected keyword `i32`" + "type": "assert_invalid", + "line": 354, + "filename": "task-builtins.39.wasm", + "module_type": "binary", + "text": "64-bit `context.set` requires the component model 64-bit feature" }, { - "type": "assert_malformed", - "line": 357, + "type": "assert_invalid", + "line": 359, "filename": "task-builtins.40.wasm", "module_type": "binary", - "text": "invalid leading byte (0x7e) for context.get" + "text": "64-bit `context.get` requires the component model 64-bit feature" }, { - "type": "assert_malformed", - "line": 364, + "type": "assert_invalid", + "line": 366, "filename": "task-builtins.41.wasm", "module_type": "binary", - "text": "invalid leading byte (0x7e) for context.set" + "text": "64-bit `context.set` requires the component model 64-bit feature" }, { - "type": "module", - "line": 373, + "type": "assert_invalid", + "line": 375, "filename": "task-builtins.42.wasm", + "module_type": "binary", + "text": "`context.get` only supports `i32` or `i64`" + }, + { + "type": "assert_invalid", + "line": 379, + "filename": "task-builtins.43.wasm", + "module_type": "binary", + "text": "`context.set` only supports `i32` or `i64`" + }, + { + "type": "module", + "line": 385, + "filename": "task-builtins.44.wasm", "module_type": "binary" }, { "type": "module", - "line": 433, - "filename": "task-builtins.43.wasm", + "line": 445, + "filename": "task-builtins.45.wasm", "module_type": "binary" } ] diff --git a/tests/snapshots/cli/component-model/async/task-builtins.wast/42.print b/tests/snapshots/cli/component-model/async/task-builtins.wast/44.print similarity index 100% rename from tests/snapshots/cli/component-model/async/task-builtins.wast/42.print rename to tests/snapshots/cli/component-model/async/task-builtins.wast/44.print diff --git a/tests/snapshots/cli/component-model/async/task-builtins.wast/43.print b/tests/snapshots/cli/component-model/async/task-builtins.wast/45.print similarity index 100% rename from tests/snapshots/cli/component-model/async/task-builtins.wast/43.print rename to tests/snapshots/cli/component-model/async/task-builtins.wast/45.print diff --git a/tests/snapshots/cli/component-model/memory64/context.wast.json b/tests/snapshots/cli/component-model/memory64/context.wast.json new file mode 100644 index 0000000000..e2673f2b59 --- /dev/null +++ b/tests/snapshots/cli/component-model/memory64/context.wast.json @@ -0,0 +1,51 @@ +{ + "source_filename": "tests/cli/component-model/memory64/context.wast", + "commands": [ + { + "type": "module", + "line": 5, + "filename": "context.0.wasm", + "module_type": "binary" + }, + { + "type": "module", + "line": 22, + "filename": "context.1.wasm", + "module_type": "binary" + }, + { + "type": "assert_invalid", + "line": 31, + "filename": "context.2.wasm", + "module_type": "binary", + "text": "found: (func (result i64))" + }, + { + "type": "assert_invalid", + "line": 39, + "filename": "context.3.wasm", + "module_type": "binary", + "text": "found: (func (param i64))" + }, + { + "type": "assert_invalid", + "line": 47, + "filename": "context.4.wasm", + "module_type": "binary", + "text": "found: (func (result i32))" + }, + { + "type": "assert_invalid", + "line": 55, + "filename": "context.5.wasm", + "module_type": "binary", + "text": "found: (func (param i32))" + }, + { + "type": "module", + "line": 63, + "filename": "context.6.wasm", + "module_type": "binary" + } + ] +} \ No newline at end of file diff --git a/tests/snapshots/cli/component-model/memory64/context.wast/0.print b/tests/snapshots/cli/component-model/memory64/context.wast/0.print new file mode 100644 index 0000000000..30493a358a --- /dev/null +++ b/tests/snapshots/cli/component-model/memory64/context.wast/0.print @@ -0,0 +1,18 @@ +(component + (core func $get0 (;0;) (canon context.get i64 0)) + (core func $set0 (;1;) (canon context.set i64 0)) + (core module $m (;0;) + (type (;0;) (func (result i64))) + (type (;1;) (func (param i64))) + (import "" "get0" (func (;0;) (type 0))) + (import "" "set0" (func (;1;) (type 1))) + ) + (core instance (;0;) + (export "get0" (func $get0)) + (export "set0" (func $set0)) + ) + (core instance (;1;) (instantiate $m + (with "" (instance 0)) + ) + ) +) diff --git a/tests/snapshots/cli/component-model/memory64/context.wast/1.print b/tests/snapshots/cli/component-model/memory64/context.wast/1.print new file mode 100644 index 0000000000..d46be4e689 --- /dev/null +++ b/tests/snapshots/cli/component-model/memory64/context.wast/1.print @@ -0,0 +1,6 @@ +(component + (core func (;0;) (canon context.get i32 0)) + (core func (;1;) (canon context.set i32 0)) + (core func (;2;) (canon context.get i64 0)) + (core func (;3;) (canon context.set i64 0)) +) diff --git a/tests/snapshots/cli/component-model/memory64/context.wast/6.print b/tests/snapshots/cli/component-model/memory64/context.wast/6.print new file mode 100644 index 0000000000..80914678a6 --- /dev/null +++ b/tests/snapshots/cli/component-model/memory64/context.wast/6.print @@ -0,0 +1,4 @@ +(component + (core func (;0;) (canon context.get i64 0)) + (core func (;1;) (canon context.set i64 0)) +)