From 80fad86f83fe765d2b05e8c45270dc0e47d0564e Mon Sep 17 00:00:00 2001 From: Christof Petig Date: Sun, 20 Apr 2025 14:26:33 +0200 Subject: [PATCH 01/14] necessary parts to make the wit-bindgen test pass --- crates/cli-flags/src/lib.rs | 4 +++ crates/environ/src/component/types.rs | 17 +++++++++++ crates/environ/src/component/types_builder.rs | 30 +++++++++++++++++-- crates/environ/src/fact/trampoline.rs | 29 ++++++++++++++++++ crates/wasmtime/src/config.rs | 10 +++++++ .../src/runtime/component/func/typed.rs | 1 + .../wasmtime/src/runtime/component/types.rs | 2 ++ .../wasmtime/src/runtime/component/values.rs | 4 +++ 8 files changed, 95 insertions(+), 2 deletions(-) diff --git a/crates/cli-flags/src/lib.rs b/crates/cli-flags/src/lib.rs index 51fbd9b1ea63..b7ca5b02bb87 100644 --- a/crates/cli-flags/src/lib.rs +++ b/crates/cli-flags/src/lib.rs @@ -409,6 +409,9 @@ wasmtime_option_group! { pub exceptions: Option, /// Whether or not any GC infrastructure in Wasmtime is enabled or not. pub gc_support: Option, + /// Component model support for fixed size lists: this corresponds + /// to the 🔧 emoji in the component model specification + pub component_model_fixed_size_list: Option, } enum Wasm { @@ -1067,6 +1070,7 @@ impl CommonOptions { ("component-model-async", component_model_async_stackful, wasm_component_model_async_stackful) ("component-model-async", component_model_threading, wasm_component_model_threading) ("component-model", component_model_error_context, wasm_component_model_error_context) + ("component-model", component_model_fixed_size_list, wasm_component_model_fixed_size_lists) ("threads", threads, wasm_threads) ("gc", gc, wasm_gc) ("gc", reference_types, wasm_reference_types) diff --git a/crates/environ/src/component/types.rs b/crates/environ/src/component/types.rs index 8db6b800c4fe..cc7936911a24 100644 --- a/crates/environ/src/component/types.rs +++ b/crates/environ/src/component/types.rs @@ -89,6 +89,8 @@ indices! { pub struct TypeResultIndex(u32); /// Index pointing to a list type in the component model. pub struct TypeListIndex(u32); + /// Index pointing to a fixed size list type in the component model. + pub struct TypeFixedSizeListIndex(u32); /// Index pointing to a future type in the component model. pub struct TypeFutureIndex(u32); @@ -296,6 +298,7 @@ pub struct ComponentTypes { pub(super) stream_tables: PrimaryMap, pub(super) error_context_tables: PrimaryMap, + pub(super) fixed_size_lists: PrimaryMap, } impl TypeTrace for ComponentTypes { @@ -369,6 +372,7 @@ impl ComponentTypes { InterfaceType::Enum(i) => &self[*i].abi, InterfaceType::Option(i) => &self[*i].abi, InterfaceType::Result(i) => &self[*i].abi, + InterfaceType::FixedSizeList(i) => &self[*i].abi, } } @@ -418,6 +422,7 @@ impl_index! { impl Index for ComponentTypes { TypeFutureTable => future_tables } impl Index for ComponentTypes { TypeStreamTable => stream_tables } impl Index for ComponentTypes { TypeErrorContextTable => error_context_tables } + impl Index for ComponentTypes { TypeFixedSizeList => fixed_size_lists } } // Additionally forward anything that can index `ModuleTypes` to `ModuleTypes` @@ -595,6 +600,7 @@ pub enum InterfaceType { Future(TypeFutureTableIndex), Stream(TypeStreamTableIndex), ErrorContext(TypeComponentLocalErrorContextTableIndex), + FixedSizeList(TypeFixedSizeListIndex), } /// Bye information about a type in the canonical ABI, with metadata for both @@ -1175,6 +1181,17 @@ pub struct TypeList { pub element: InterfaceType, } +/// Shape of a "fixed size list" interface type. +#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)] +pub struct TypeFixedSizeList { + /// The element type of the list. + pub element: InterfaceType, + /// The fixed length of the list. + pub size: u32, + /// Byte information about this type in the canonical ABI. + pub abi: CanonicalAbiInfo, +} + /// Maximum number of flat types, for either params or results. pub const MAX_FLAT_TYPES: usize = if MAX_FLAT_PARAMS > MAX_FLAT_RESULTS { MAX_FLAT_PARAMS diff --git a/crates/environ/src/component/types_builder.rs b/crates/environ/src/component/types_builder.rs index 090081388a2b..ef30ad6b8f70 100644 --- a/crates/environ/src/component/types_builder.rs +++ b/crates/environ/src/component/types_builder.rs @@ -50,6 +50,7 @@ pub struct ComponentTypesBuilder { future_tables: HashMap, stream_tables: HashMap, error_context_tables: HashMap, + fixed_size_lists: HashMap, component_types: ComponentTypes, module_types: ModuleTypesBuilder, @@ -118,6 +119,7 @@ impl ComponentTypesBuilder { type_info: TypeInformationCache::default(), resources: ResourcesBuilder::default(), abstract_resources: 0, + fixed_size_lists: HashMap::default(), } } @@ -456,8 +458,8 @@ impl ComponentTypesBuilder { ComponentDefinedType::Stream(ty) => { InterfaceType::Stream(self.stream_table_type(types, ty)?) } - ComponentDefinedType::FixedSizeList(..) => { - bail!("support not implemented for fixed-size-lists"); + ComponentDefinedType::FixedSizeList(ty, size) => { + InterfaceType::FixedSizeList(self.fixed_size_list_type(types, ty, *size)?) } ComponentDefinedType::Map(..) => { bail!("support not implemented for map type"); @@ -575,6 +577,19 @@ impl ComponentTypesBuilder { self.add_tuple_type(TypeTuple { types, abi }) } + fn fixed_size_list_type(&mut self, types: TypesRef<'_>, ty: &ComponentValType, size: u32) -> Result { + assert_eq!(types.id(), self.module_types.validator_id()); + let element = self.valtype(types, ty)?; + Ok(self.new_fixed_size_list_type(element, size)) + } + + pub(crate) fn new_fixed_size_list_type(&mut self, element: InterfaceType, size: u32) -> TypeFixedSizeListIndex { + let element_abi = self.component_types.canonical_abi(&element); + let abi = CanonicalAbiInfo::record( + (0..size).into_iter().map(|_| element_abi)); + self.add_fixed_size_list_type(TypeFixedSizeList { element, size, abi }) + } + fn flags_type(&mut self, flags: &IndexSet) -> TypeFlagsIndex { let flags = TypeFlags { names: flags.iter().map(|s| s.to_string()).collect(), @@ -691,6 +706,11 @@ impl ComponentTypesBuilder { intern_and_fill_flat_types!(self, tuples, ty) } + /// Interns a new tuple type within this type information. + pub fn add_fixed_size_list_type(&mut self, ty: TypeFixedSizeList) -> TypeFixedSizeListIndex { + intern_and_fill_flat_types!(self, fixed_size_lists, ty) + } + /// Interns a new variant type within this type information. pub fn add_variant_type(&mut self, ty: TypeVariant) -> TypeVariantIndex { intern_and_fill_flat_types!(self, variants, ty) @@ -826,6 +846,7 @@ impl ComponentTypesBuilder { InterfaceType::Enum(i) => &self.type_info.enums[*i], InterfaceType::Option(i) => &self.type_info.options[*i], InterfaceType::Result(i) => &self.type_info.results[*i], + InterfaceType::FixedSizeList(i) => &self.type_info.fixed_size_lists[*i], } } } @@ -935,6 +956,7 @@ struct TypeInformationCache { options: PrimaryMap, results: PrimaryMap, lists: PrimaryMap, + fixed_size_lists: PrimaryMap, } struct TypeInformation { @@ -1084,6 +1106,10 @@ impl TypeInformation { self.build_record(ty.types.iter().map(|t| types.type_information(t))); } + fn fixed_size_lists(&mut self, types: &ComponentTypesBuilder, ty: &TypeFixedSizeList) { + self.build_record((0..ty.size).into_iter().map(|_| types.type_information(&ty.element))); + } + fn enums(&mut self, _types: &ComponentTypesBuilder, _ty: &TypeEnum) { self.depth = 1; self.flat.push(FlatType::I32, FlatType::I32); diff --git a/crates/environ/src/fact/trampoline.rs b/crates/environ/src/fact/trampoline.rs index f75c30ccf34a..fc1571ac149b 100644 --- a/crates/environ/src/fact/trampoline.rs +++ b/crates/environ/src/fact/trampoline.rs @@ -1126,6 +1126,7 @@ impl<'a, 'b> Compiler<'a, 'b> { | InterfaceType::Future(_) | InterfaceType::Stream(_) | InterfaceType::ErrorContext(_) => 1, + InterfaceType::FixedSizeList(i) => self.types[*i].size as usize, }; match self.fuel.checked_sub(cost) { @@ -1165,6 +1166,9 @@ impl<'a, 'b> Compiler<'a, 'b> { InterfaceType::ErrorContext(t) => { self.translate_error_context(*t, src, dst_ty, dst) } + InterfaceType::FixedSizeList(t) => { + self.translate_fixed_size_list(*t, src, dst_ty, dst); + } } } @@ -2858,6 +2862,31 @@ impl<'a, 'b> Compiler<'a, 'b> { } } + fn translate_fixed_size_list( + &mut self, + src_ty: TypeFixedSizeListIndex, + src: &Source<'_>, + dst_ty: &InterfaceType, + dst: &Destination, + ) { + let src_ty = &self.types[src_ty]; + let dst_ty = match dst_ty { + InterfaceType::FixedSizeList(t) => &self.types[*t], + _ => panic!("expected a fixed size list"), + }; + + // TODO: subtyping + assert_eq!(src_ty.size, dst_ty.size); + + let srcs = src + .record_field_srcs(self.types, (0..src_ty.size).into_iter().map(|_| src_ty.element)); + let dsts = dst + .record_field_dsts(self.types, (0..dst_ty.size).into_iter().map(|_| dst_ty.element)); + for (src, dst) in srcs.zip(dsts) { + self.translate(&src_ty.element, &src, &dst_ty.element, &dst); + } + } + fn translate_variant( &mut self, src_ty: TypeVariantIndex, diff --git a/crates/wasmtime/src/config.rs b/crates/wasmtime/src/config.rs index d4b4485d9de1..de61426acb3e 100644 --- a/crates/wasmtime/src/config.rs +++ b/crates/wasmtime/src/config.rs @@ -1296,6 +1296,16 @@ impl Config { self } + /// This corresponds to the 🔧 emoji in the component model specification. + /// + /// Please note that Wasmtime's support for this feature is _very_ + /// incomplete. + #[cfg(feature = "component-model")] + pub fn wasm_component_model_fixed_size_lists(&mut self, enable: bool) -> &mut Self { + self.wasm_feature(WasmFeatures::CM_FIXED_SIZE_LIST, enable); + self + } + /// Configures whether the [Exception-handling proposal][proposal] is enabled or not. /// /// [proposal]: https://github.com/WebAssembly/exception-handling diff --git a/crates/wasmtime/src/runtime/component/func/typed.rs b/crates/wasmtime/src/runtime/component/func/typed.rs index add17eddea40..ce634baaeed9 100644 --- a/crates/wasmtime/src/runtime/component/func/typed.rs +++ b/crates/wasmtime/src/runtime/component/func/typed.rs @@ -2895,6 +2895,7 @@ pub fn desc(ty: &InterfaceType) -> &'static str { InterfaceType::Future(_) => "future", InterfaceType::Stream(_) => "stream", InterfaceType::ErrorContext(_) => "error-context", + InterfaceType::FixedSizeList(_) => "list<_, N>", } } diff --git a/crates/wasmtime/src/runtime/component/types.rs b/crates/wasmtime/src/runtime/component/types.rs index 948fc8e51f9d..bcb0c553cc6a 100644 --- a/crates/wasmtime/src/runtime/component/types.rs +++ b/crates/wasmtime/src/runtime/component/types.rs @@ -158,6 +158,7 @@ impl TypeChecker<'_> { (InterfaceType::Stream(_), _) => false, (InterfaceType::ErrorContext(_), InterfaceType::ErrorContext(_)) => true, (InterfaceType::ErrorContext(_), _) => false, + (InterfaceType::FixedSizeList(_), _) => todo!(), } } @@ -855,6 +856,7 @@ impl Type { InterfaceType::Future(index) => Type::Future(instance.future_type(*index)), InterfaceType::Stream(index) => Type::Stream(instance.stream_type(*index)), InterfaceType::ErrorContext(_) => Type::ErrorContext, + InterfaceType::FixedSizeList(_) => todo!(), } } diff --git a/crates/wasmtime/src/runtime/component/values.rs b/crates/wasmtime/src/runtime/component/values.rs index d0b1d0209db2..034eb762764d 100644 --- a/crates/wasmtime/src/runtime/component/values.rs +++ b/crates/wasmtime/src/runtime/component/values.rs @@ -215,6 +215,7 @@ impl Val { InterfaceType::ErrorContext(_) => { ErrorContext::linear_lift_from_flat(cx, ty, next(src))?.into_val() } + InterfaceType::FixedSizeList(_) => todo!(), }) } @@ -341,6 +342,7 @@ impl Val { InterfaceType::ErrorContext(_) => { ErrorContext::linear_lift_from_memory(cx, ty, bytes)?.into_val() } + InterfaceType::FixedSizeList(_) => todo!(), }) } @@ -491,6 +493,7 @@ impl Val { ) } (InterfaceType::ErrorContext(_), _) => unexpected(ty, self), + (InterfaceType::FixedSizeList(_), _) => todo!(), } } @@ -644,6 +647,7 @@ impl Val { ) } (InterfaceType::ErrorContext(_), _) => unexpected(ty, self), + (InterfaceType::FixedSizeList(_), _) => todo!(), } } From 7d4422c62e07ad2745e3b7ad0ab8ad80b87084bd Mon Sep 17 00:00:00 2001 From: Christof Petig Date: Sat, 12 Jul 2025 17:34:00 +0200 Subject: [PATCH 02/14] post-merge fixes --- crates/environ/src/component/types_builder.rs | 22 ++++++++++++++----- crates/environ/src/fact/trampoline.rs | 19 ++++++++++------ crates/wasmtime/src/config.rs | 3 +-- 3 files changed, 30 insertions(+), 14 deletions(-) diff --git a/crates/environ/src/component/types_builder.rs b/crates/environ/src/component/types_builder.rs index ef30ad6b8f70..411dfc0d0b83 100644 --- a/crates/environ/src/component/types_builder.rs +++ b/crates/environ/src/component/types_builder.rs @@ -577,16 +577,24 @@ impl ComponentTypesBuilder { self.add_tuple_type(TypeTuple { types, abi }) } - fn fixed_size_list_type(&mut self, types: TypesRef<'_>, ty: &ComponentValType, size: u32) -> Result { + fn fixed_size_list_type( + &mut self, + types: TypesRef<'_>, + ty: &ComponentValType, + size: u32, + ) -> Result { assert_eq!(types.id(), self.module_types.validator_id()); let element = self.valtype(types, ty)?; Ok(self.new_fixed_size_list_type(element, size)) } - pub(crate) fn new_fixed_size_list_type(&mut self, element: InterfaceType, size: u32) -> TypeFixedSizeListIndex { + pub(crate) fn new_fixed_size_list_type( + &mut self, + element: InterfaceType, + size: u32, + ) -> TypeFixedSizeListIndex { let element_abi = self.component_types.canonical_abi(&element); - let abi = CanonicalAbiInfo::record( - (0..size).into_iter().map(|_| element_abi)); + let abi = CanonicalAbiInfo::record((0..size).into_iter().map(|_| element_abi)); self.add_fixed_size_list_type(TypeFixedSizeList { element, size, abi }) } @@ -1107,7 +1115,11 @@ impl TypeInformation { } fn fixed_size_lists(&mut self, types: &ComponentTypesBuilder, ty: &TypeFixedSizeList) { - self.build_record((0..ty.size).into_iter().map(|_| types.type_information(&ty.element))); + self.build_record( + (0..ty.size) + .into_iter() + .map(|_| types.type_information(&ty.element)), + ); } fn enums(&mut self, _types: &ComponentTypesBuilder, _ty: &TypeEnum) { diff --git a/crates/environ/src/fact/trampoline.rs b/crates/environ/src/fact/trampoline.rs index fc1571ac149b..9fc237dea36e 100644 --- a/crates/environ/src/fact/trampoline.rs +++ b/crates/environ/src/fact/trampoline.rs @@ -19,9 +19,10 @@ use crate::component::{ CanonicalAbiInfo, ComponentTypesBuilder, FLAG_MAY_ENTER, FLAG_MAY_LEAVE, FixedEncoding as FE, FlatType, InterfaceType, MAX_FLAT_ASYNC_PARAMS, MAX_FLAT_PARAMS, PREPARE_ASYNC_NO_RESULT, PREPARE_ASYNC_WITH_RESULT, START_FLAG_ASYNC_CALLEE, StringEncoding, Transcode, - TypeComponentLocalErrorContextTableIndex, TypeEnumIndex, TypeFlagsIndex, TypeFutureTableIndex, - TypeListIndex, TypeOptionIndex, TypeRecordIndex, TypeResourceTableIndex, TypeResultIndex, - TypeStreamTableIndex, TypeTupleIndex, TypeVariantIndex, VariantInfo, + TypeComponentLocalErrorContextTableIndex, TypeEnumIndex, TypeFixedSizeListIndex, + TypeFlagsIndex, TypeFutureTableIndex, TypeListIndex, TypeOptionIndex, TypeRecordIndex, + TypeResourceTableIndex, TypeResultIndex, TypeStreamTableIndex, TypeTupleIndex, + TypeVariantIndex, VariantInfo, }; use crate::fact::signature::Signature; use crate::fact::transcode::Transcoder; @@ -2878,10 +2879,14 @@ impl<'a, 'b> Compiler<'a, 'b> { // TODO: subtyping assert_eq!(src_ty.size, dst_ty.size); - let srcs = src - .record_field_srcs(self.types, (0..src_ty.size).into_iter().map(|_| src_ty.element)); - let dsts = dst - .record_field_dsts(self.types, (0..dst_ty.size).into_iter().map(|_| dst_ty.element)); + let srcs = src.record_field_srcs( + self.types, + (0..src_ty.size).into_iter().map(|_| src_ty.element), + ); + let dsts = dst.record_field_dsts( + self.types, + (0..dst_ty.size).into_iter().map(|_| dst_ty.element), + ); for (src, dst) in srcs.zip(dsts) { self.translate(&src_ty.element, &src, &dst_ty.element, &dst); } diff --git a/crates/wasmtime/src/config.rs b/crates/wasmtime/src/config.rs index de61426acb3e..00955cf9ed77 100644 --- a/crates/wasmtime/src/config.rs +++ b/crates/wasmtime/src/config.rs @@ -1268,7 +1268,6 @@ impl Config { self.wasm_features(WasmFeatures::CM_THREADING, enable); self } - /// This corresponds to the 📝 emoji in the component model specification. /// /// Please note that Wasmtime's support for this feature is _very_ @@ -1302,7 +1301,7 @@ impl Config { /// incomplete. #[cfg(feature = "component-model")] pub fn wasm_component_model_fixed_size_lists(&mut self, enable: bool) -> &mut Self { - self.wasm_feature(WasmFeatures::CM_FIXED_SIZE_LIST, enable); + self.wasm_features(WasmFeatures::CM_FIXED_SIZE_LIST, enable); self } From cf25b676b46a444a446380d5861f150c87e18609 Mon Sep 17 00:00:00 2001 From: Christof Petig Date: Thu, 8 Jan 2026 00:03:43 +0100 Subject: [PATCH 03/14] fix clippy --- crates/environ/src/component/types_builder.rs | 8 ++------ crates/environ/src/fact/trampoline.rs | 10 ++-------- 2 files changed, 4 insertions(+), 14 deletions(-) diff --git a/crates/environ/src/component/types_builder.rs b/crates/environ/src/component/types_builder.rs index 411dfc0d0b83..828921d2cf78 100644 --- a/crates/environ/src/component/types_builder.rs +++ b/crates/environ/src/component/types_builder.rs @@ -594,7 +594,7 @@ impl ComponentTypesBuilder { size: u32, ) -> TypeFixedSizeListIndex { let element_abi = self.component_types.canonical_abi(&element); - let abi = CanonicalAbiInfo::record((0..size).into_iter().map(|_| element_abi)); + let abi = CanonicalAbiInfo::record((0..size).map(|_| element_abi)); self.add_fixed_size_list_type(TypeFixedSizeList { element, size, abi }) } @@ -1115,11 +1115,7 @@ impl TypeInformation { } fn fixed_size_lists(&mut self, types: &ComponentTypesBuilder, ty: &TypeFixedSizeList) { - self.build_record( - (0..ty.size) - .into_iter() - .map(|_| types.type_information(&ty.element)), - ); + self.build_record((0..ty.size).map(|_| types.type_information(&ty.element))); } fn enums(&mut self, _types: &ComponentTypesBuilder, _ty: &TypeEnum) { diff --git a/crates/environ/src/fact/trampoline.rs b/crates/environ/src/fact/trampoline.rs index 9fc237dea36e..851c900bce37 100644 --- a/crates/environ/src/fact/trampoline.rs +++ b/crates/environ/src/fact/trampoline.rs @@ -2879,14 +2879,8 @@ impl<'a, 'b> Compiler<'a, 'b> { // TODO: subtyping assert_eq!(src_ty.size, dst_ty.size); - let srcs = src.record_field_srcs( - self.types, - (0..src_ty.size).into_iter().map(|_| src_ty.element), - ); - let dsts = dst.record_field_dsts( - self.types, - (0..dst_ty.size).into_iter().map(|_| dst_ty.element), - ); + let srcs = src.record_field_srcs(self.types, (0..src_ty.size).map(|_| src_ty.element)); + let dsts = dst.record_field_dsts(self.types, (0..dst_ty.size).map(|_| dst_ty.element)); for (src, dst) in srcs.zip(dsts) { self.translate(&src_ty.element, &src, &dst_ty.element, &dst); } From 99958ae13152000ab544a568a954bf7e90353d21 Mon Sep 17 00:00:00 2001 From: Christof Petig Date: Thu, 8 Jan 2026 00:56:09 +0100 Subject: [PATCH 04/14] inline type computations --- crates/environ/src/component/types_builder.rs | 24 +++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/crates/environ/src/component/types_builder.rs b/crates/environ/src/component/types_builder.rs index 828921d2cf78..26337bb0ba16 100644 --- a/crates/environ/src/component/types_builder.rs +++ b/crates/environ/src/component/types_builder.rs @@ -594,7 +594,13 @@ impl ComponentTypesBuilder { size: u32, ) -> TypeFixedSizeListIndex { let element_abi = self.component_types.canonical_abi(&element); - let abi = CanonicalAbiInfo::record((0..size).map(|_| element_abi)); + let mut abi = element_abi.clone(); + // this assumes that size32 is already rounded up to alignment + abi.size32 = element_abi.size32 * size; + abi.size64 = element_abi.size64 * size; + abi.flat_count = element_abi + .flat_count + .map(|c| c.saturating_mul(size.min(255) as u8)); self.add_fixed_size_list_type(TypeFixedSizeList { element, size, abi }) } @@ -1115,7 +1121,21 @@ impl TypeInformation { } fn fixed_size_lists(&mut self, types: &ComponentTypesBuilder, ty: &TypeFixedSizeList) { - self.build_record((0..ty.size).map(|_| types.type_information(&ty.element))); + let element_info = types.type_information(&ty.element); + self.depth = 1 + element_info.depth; + self.has_borrow = element_info.has_borrow; + match element_info.flat.as_flat_types() { + Some(types) => { + 'outer: for _ in 0..ty.size { + for (t32, t64) in types.memory32.iter().zip(types.memory64) { + if self.flat.push(*t32, *t64) { + break 'outer; + } + } + } + } + None => self.flat.len = u8::try_from(MAX_FLAT_TYPES + 1).unwrap(), + } } fn enums(&mut self, _types: &ComponentTypesBuilder, _ty: &TypeEnum) { From b14475a2946a3b4a13174d5248c14c53c018937f Mon Sep 17 00:00:00 2001 From: Christof Petig Date: Thu, 8 Jan 2026 00:56:33 +0100 Subject: [PATCH 05/14] link missing functionality to an issue --- crates/wasmtime/src/runtime/component/types.rs | 4 ++-- crates/wasmtime/src/runtime/component/values.rs | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/crates/wasmtime/src/runtime/component/types.rs b/crates/wasmtime/src/runtime/component/types.rs index bcb0c553cc6a..ded4944542d2 100644 --- a/crates/wasmtime/src/runtime/component/types.rs +++ b/crates/wasmtime/src/runtime/component/types.rs @@ -158,7 +158,7 @@ impl TypeChecker<'_> { (InterfaceType::Stream(_), _) => false, (InterfaceType::ErrorContext(_), InterfaceType::ErrorContext(_)) => true, (InterfaceType::ErrorContext(_), _) => false, - (InterfaceType::FixedSizeList(_), _) => todo!(), + (InterfaceType::FixedSizeList(_), _) => todo!(), // FIXME(#12279) } } @@ -856,7 +856,7 @@ impl Type { InterfaceType::Future(index) => Type::Future(instance.future_type(*index)), InterfaceType::Stream(index) => Type::Stream(instance.stream_type(*index)), InterfaceType::ErrorContext(_) => Type::ErrorContext, - InterfaceType::FixedSizeList(_) => todo!(), + InterfaceType::FixedSizeList(_) => todo!(), // FIXME(#12279) } } diff --git a/crates/wasmtime/src/runtime/component/values.rs b/crates/wasmtime/src/runtime/component/values.rs index 034eb762764d..2e478ae6116e 100644 --- a/crates/wasmtime/src/runtime/component/values.rs +++ b/crates/wasmtime/src/runtime/component/values.rs @@ -215,7 +215,7 @@ impl Val { InterfaceType::ErrorContext(_) => { ErrorContext::linear_lift_from_flat(cx, ty, next(src))?.into_val() } - InterfaceType::FixedSizeList(_) => todo!(), + InterfaceType::FixedSizeList(_) => todo!(), // FIXME(#12279) }) } @@ -342,7 +342,7 @@ impl Val { InterfaceType::ErrorContext(_) => { ErrorContext::linear_lift_from_memory(cx, ty, bytes)?.into_val() } - InterfaceType::FixedSizeList(_) => todo!(), + InterfaceType::FixedSizeList(_) => todo!(), // FIXME(#12279) }) } @@ -493,7 +493,7 @@ impl Val { ) } (InterfaceType::ErrorContext(_), _) => unexpected(ty, self), - (InterfaceType::FixedSizeList(_), _) => todo!(), + (InterfaceType::FixedSizeList(_), _) => todo!(), // FIXME(#12279) } } @@ -647,7 +647,7 @@ impl Val { ) } (InterfaceType::ErrorContext(_), _) => unexpected(ty, self), - (InterfaceType::FixedSizeList(_), _) => todo!(), + (InterfaceType::FixedSizeList(_), _) => todo!(), // FIXME(#12279) } } From c7004f6c658cd4fdb89ab3bd00e5e6d22ad8a2c4 Mon Sep 17 00:00:00 2001 From: Christof Petig Date: Thu, 8 Jan 2026 01:00:04 +0100 Subject: [PATCH 06/14] undo unintended removal of blank line --- crates/wasmtime/src/config.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/crates/wasmtime/src/config.rs b/crates/wasmtime/src/config.rs index 00955cf9ed77..0bfb531db8d2 100644 --- a/crates/wasmtime/src/config.rs +++ b/crates/wasmtime/src/config.rs @@ -1268,6 +1268,7 @@ impl Config { self.wasm_features(WasmFeatures::CM_THREADING, enable); self } + /// This corresponds to the 📝 emoji in the component model specification. /// /// Please note that Wasmtime's support for this feature is _very_ From fe3a478c30403a9df1d2fde2ff31c15c6c9601a3 Mon Sep 17 00:00:00 2001 From: Christof Petig Date: Sat, 10 Jan 2026 13:27:36 +0100 Subject: [PATCH 07/14] fix logic mistake, enable feature in wasmtime --- crates/environ/src/component/types_builder.rs | 2 +- crates/wasmtime/src/config.rs | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/crates/environ/src/component/types_builder.rs b/crates/environ/src/component/types_builder.rs index 26337bb0ba16..d3ddcbc4373a 100644 --- a/crates/environ/src/component/types_builder.rs +++ b/crates/environ/src/component/types_builder.rs @@ -1128,7 +1128,7 @@ impl TypeInformation { Some(types) => { 'outer: for _ in 0..ty.size { for (t32, t64) in types.memory32.iter().zip(types.memory64) { - if self.flat.push(*t32, *t64) { + if !self.flat.push(*t32, *t64) { break 'outer; } } diff --git a/crates/wasmtime/src/config.rs b/crates/wasmtime/src/config.rs index 0bfb531db8d2..2d9b2529606a 100644 --- a/crates/wasmtime/src/config.rs +++ b/crates/wasmtime/src/config.rs @@ -2274,7 +2274,8 @@ impl Config { | WasmFeatures::CM_ASYNC_BUILTINS | WasmFeatures::CM_THREADING | WasmFeatures::CM_ERROR_CONTEXT - | WasmFeatures::CM_GC; + | WasmFeatures::CM_GC + | WasmFeatures::CM_FIXED_SIZE_LIST; #[allow(unused_mut, reason = "easier to avoid #[cfg]")] let mut unsupported = !features_known_to_wasmtime; From 0e828ba517610f75afef9e06576c1000c2cdda67 Mon Sep 17 00:00:00 2001 From: Christof Petig Date: Sat, 10 Jan 2026 16:41:02 +0100 Subject: [PATCH 08/14] optimized conversion --- crates/environ/src/fact/trampoline.rs | 87 +++++++++++++++++++++++++-- 1 file changed, 83 insertions(+), 4 deletions(-) diff --git a/crates/environ/src/fact/trampoline.rs b/crates/environ/src/fact/trampoline.rs index 851c900bce37..6bf599992bcc 100644 --- a/crates/environ/src/fact/trampoline.rs +++ b/crates/environ/src/fact/trampoline.rs @@ -2879,10 +2879,89 @@ impl<'a, 'b> Compiler<'a, 'b> { // TODO: subtyping assert_eq!(src_ty.size, dst_ty.size); - let srcs = src.record_field_srcs(self.types, (0..src_ty.size).map(|_| src_ty.element)); - let dsts = dst.record_field_dsts(self.types, (0..dst_ty.size).map(|_| dst_ty.element)); - for (src, dst) in srcs.zip(dsts) { - self.translate(&src_ty.element, &src, &dst_ty.element, &dst); + match (&src, &dst) { + // Generate custom code for memory to memory copy + (Source::Memory(src_mem), Destination::Memory(dst_mem)) => { + let src_opts = src.opts(); + let dst_opts = dst.opts(); + + let src_mem_opts = match &src.opts().data_model { + DataModel::Gc {} => todo!("CM+GC"), + DataModel::LinearMemory(opts) => opts, + }; + let dst_mem_opts = match &dst.opts().data_model { + DataModel::Gc {} => todo!("CM+GC"), + DataModel::LinearMemory(opts) => opts, + }; + let src_element_bytes = self.types.size_align(src_mem_opts, &src_ty.element).0; + let dst_element_bytes = self.types.size_align(dst_mem_opts, &dst_ty.element).0; + assert_ne!(src_element_bytes, 0); + assert_ne!(dst_element_bytes, 0); + + // because data is stored in-line, we assume that source and destination memory have been validated upstream + + self.instruction(LocalGet(src_mem.addr.idx)); + let cur_src_ptr = self.local_set_new_tmp(src_mem_opts.ptr()); + self.instruction(LocalGet(dst_mem.addr.idx)); + let cur_dst_ptr = self.local_set_new_tmp(dst_mem_opts.ptr()); + + self.instruction(I32Const(src_ty.size as i32)); + let remaining = self.local_set_new_tmp(ValType::I32); + + self.instruction(Loop(BlockType::Empty)); + + // Translate the next element in the list + let element_src = Source::Memory(Memory { + opts: src_opts, + offset: 0, + addr: TempLocal::new(cur_src_ptr.idx, cur_src_ptr.ty), + }); + let element_dst = Destination::Memory(Memory { + opts: dst_opts, + offset: 0, + addr: TempLocal::new(cur_dst_ptr.idx, cur_dst_ptr.ty), + }); + self.translate(&src_ty.element, &element_src, &dst_ty.element, &element_dst); + + // Update the two loop pointers + self.instruction(LocalGet(cur_src_ptr.idx)); + self.ptr_uconst(src_mem_opts, src_element_bytes); + self.ptr_add(src_mem_opts); + self.instruction(LocalSet(cur_src_ptr.idx)); + self.instruction(LocalGet(cur_dst_ptr.idx)); + self.ptr_uconst(dst_mem_opts, dst_element_bytes); + self.ptr_add(dst_mem_opts); + self.instruction(LocalSet(cur_dst_ptr.idx)); + + // Update the remaining count, falling through to break out if it's zero + // now. + self.instruction(LocalGet(remaining.idx)); + self.ptr_iconst(src_mem_opts, -1); + self.ptr_add(src_mem_opts); + self.instruction(LocalTee(remaining.idx)); + self.ptr_br_if(src_mem_opts, 0); + self.instruction(End); // end of loop + + self.free_temp_local(cur_dst_ptr); + self.free_temp_local(cur_src_ptr); + self.free_temp_local(remaining); + return; + } + // for the non-memory-to-memory case fall back to using generic tuple translation + (_, _) => { + // Assumes that the number of elements are small enough for this unrolling + assert!( + src_ty.size as usize <= MAX_FLAT_PARAMS + && dst_ty.size as usize <= MAX_FLAT_PARAMS + ); + let srcs = + src.record_field_srcs(self.types, (0..src_ty.size).map(|_| src_ty.element)); + let dsts = + dst.record_field_dsts(self.types, (0..dst_ty.size).map(|_| dst_ty.element)); + for (src, dst) in srcs.zip(dsts) { + self.translate(&src_ty.element, &src, &dst_ty.element, &dst); + } + } } } From 1cd39045d6650a2da416acdffb9c535b1393c33b Mon Sep 17 00:00:00 2001 From: Christof Petig Date: Sat, 10 Jan 2026 17:10:07 +0100 Subject: [PATCH 09/14] add offset --- crates/environ/src/fact/trampoline.rs | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/crates/environ/src/fact/trampoline.rs b/crates/environ/src/fact/trampoline.rs index 6bf599992bcc..269d632ed73d 100644 --- a/crates/environ/src/fact/trampoline.rs +++ b/crates/environ/src/fact/trampoline.rs @@ -2882,14 +2882,11 @@ impl<'a, 'b> Compiler<'a, 'b> { match (&src, &dst) { // Generate custom code for memory to memory copy (Source::Memory(src_mem), Destination::Memory(dst_mem)) => { - let src_opts = src.opts(); - let dst_opts = dst.opts(); - - let src_mem_opts = match &src.opts().data_model { + let src_mem_opts = match &src_mem.opts.data_model { DataModel::Gc {} => todo!("CM+GC"), DataModel::LinearMemory(opts) => opts, }; - let dst_mem_opts = match &dst.opts().data_model { + let dst_mem_opts = match &dst_mem.opts.data_model { DataModel::Gc {} => todo!("CM+GC"), DataModel::LinearMemory(opts) => opts, }; @@ -2901,8 +2898,16 @@ impl<'a, 'b> Compiler<'a, 'b> { // because data is stored in-line, we assume that source and destination memory have been validated upstream self.instruction(LocalGet(src_mem.addr.idx)); + if src_mem.offset != 0 { + self.ptr_uconst(src_mem_opts, src_mem.offset); + self.ptr_add(src_mem_opts); + } let cur_src_ptr = self.local_set_new_tmp(src_mem_opts.ptr()); self.instruction(LocalGet(dst_mem.addr.idx)); + if dst_mem.offset != 0 { + self.ptr_uconst(dst_mem_opts, dst_mem.offset); + self.ptr_add(dst_mem_opts); + } let cur_dst_ptr = self.local_set_new_tmp(dst_mem_opts.ptr()); self.instruction(I32Const(src_ty.size as i32)); @@ -2912,12 +2917,12 @@ impl<'a, 'b> Compiler<'a, 'b> { // Translate the next element in the list let element_src = Source::Memory(Memory { - opts: src_opts, + opts: src_mem.opts, offset: 0, addr: TempLocal::new(cur_src_ptr.idx, cur_src_ptr.ty), }); let element_dst = Destination::Memory(Memory { - opts: dst_opts, + opts: dst_mem.opts, offset: 0, addr: TempLocal::new(cur_dst_ptr.idx, cur_dst_ptr.ty), }); From b8ad8dae1e2d089843f1a0feec88a1bb4f2594d0 Mon Sep 17 00:00:00 2001 From: Christof Petig Date: Mon, 12 Jan 2026 20:32:40 +0100 Subject: [PATCH 10/14] unify on name and implement wast option --- crates/cli-flags/src/lib.rs | 4 +- crates/fuzzing/src/generators/config.rs | 3 + crates/fuzzing/src/generators/module.rs | 2 + crates/test-util/src/wasmtime_wast.rs | 3 + crates/test-util/src/wast.rs | 1 + .../component-model/fixed_size_list.wast | 421 ++++++++++++++++++ 6 files changed, 432 insertions(+), 2 deletions(-) create mode 100644 tests/misc_testsuite/component-model/fixed_size_list.wast diff --git a/crates/cli-flags/src/lib.rs b/crates/cli-flags/src/lib.rs index b7ca5b02bb87..ca8bdf430786 100644 --- a/crates/cli-flags/src/lib.rs +++ b/crates/cli-flags/src/lib.rs @@ -411,7 +411,7 @@ wasmtime_option_group! { pub gc_support: Option, /// Component model support for fixed size lists: this corresponds /// to the 🔧 emoji in the component model specification - pub component_model_fixed_size_list: Option, + pub component_model_fixed_size_lists: Option, } enum Wasm { @@ -1070,7 +1070,7 @@ impl CommonOptions { ("component-model-async", component_model_async_stackful, wasm_component_model_async_stackful) ("component-model-async", component_model_threading, wasm_component_model_threading) ("component-model", component_model_error_context, wasm_component_model_error_context) - ("component-model", component_model_fixed_size_list, wasm_component_model_fixed_size_lists) + ("component-model", component_model_fixed_size_lists, wasm_component_model_fixed_size_lists) ("threads", threads, wasm_threads) ("gc", gc, wasm_gc) ("gc", reference_types, wasm_reference_types) diff --git a/crates/fuzzing/src/generators/config.rs b/crates/fuzzing/src/generators/config.rs index d4782a77c5de..f4461bbaa81b 100644 --- a/crates/fuzzing/src/generators/config.rs +++ b/crates/fuzzing/src/generators/config.rs @@ -140,6 +140,7 @@ impl Config { component_model_threading, component_model_error_context, component_model_gc, + component_model_fixed_size_lists, simd, exceptions, legacy_exceptions: _, @@ -165,6 +166,7 @@ impl Config { self.module_config.component_model_error_context = component_model_error_context.unwrap_or(false); self.module_config.component_model_gc = component_model_gc.unwrap_or(false); + self.module_config.component_model_fixed_size_lists = component_model_fixed_size_lists.unwrap_or(false); // Enable/disable proposals that wasm-smith has knobs for which will be // read when creating `wasmtime::Config`. @@ -290,6 +292,7 @@ impl Config { cfg.wasm.component_model_error_context = Some(self.module_config.component_model_error_context); cfg.wasm.component_model_gc = Some(self.module_config.component_model_gc); + cfg.wasm.component_model_fixed_size_lists = Some(self.module_config.component_model_fixed_size_lists); cfg.wasm.custom_page_sizes = Some(self.module_config.config.custom_page_sizes_enabled); cfg.wasm.epoch_interruption = Some(self.wasmtime.epoch_interruption); cfg.wasm.extended_const = Some(self.module_config.config.extended_const_enabled); diff --git a/crates/fuzzing/src/generators/module.rs b/crates/fuzzing/src/generators/module.rs index 58e10cf90316..8120e4526a6e 100644 --- a/crates/fuzzing/src/generators/module.rs +++ b/crates/fuzzing/src/generators/module.rs @@ -22,6 +22,7 @@ pub struct ModuleConfig { pub component_model_threading: bool, pub component_model_error_context: bool, pub component_model_gc: bool, + pub component_model_fixed_size_lists: bool, pub legacy_exceptions: bool, pub shared_memory: bool, } @@ -79,6 +80,7 @@ impl<'a> Arbitrary<'a> for ModuleConfig { component_model_threading: false, component_model_error_context: false, component_model_gc: false, + component_model_fixed_size_lists: false, legacy_exceptions: false, shared_memory: false, function_references_enabled: config.gc_enabled, diff --git a/crates/test-util/src/wasmtime_wast.rs b/crates/test-util/src/wasmtime_wast.rs index a20f011b1261..63dce5dadeb4 100644 --- a/crates/test-util/src/wasmtime_wast.rs +++ b/crates/test-util/src/wasmtime_wast.rs @@ -43,6 +43,7 @@ pub fn apply_test_config(config: &mut Config, test_config: &wast::TestConfig) { component_model_threading, component_model_error_context, component_model_gc, + component_model_fixed_size_lists, nan_canonicalization, simd, exceptions, @@ -72,6 +73,7 @@ pub fn apply_test_config(config: &mut Config, test_config: &wast::TestConfig) { let component_model_threading = component_model_threading.unwrap_or(false); let component_model_error_context = component_model_error_context.unwrap_or(false); let component_model_gc = component_model_gc.unwrap_or(false); + let component_model_fixed_size_lists = component_model_fixed_size_lists.unwrap_or(false); let nan_canonicalization = nan_canonicalization.unwrap_or(false); let relaxed_simd = relaxed_simd.unwrap_or(false); let legacy_exceptions = legacy_exceptions.unwrap_or(false); @@ -111,6 +113,7 @@ pub fn apply_test_config(config: &mut Config, test_config: &wast::TestConfig) { .wasm_component_model_threading(component_model_threading) .wasm_component_model_error_context(component_model_error_context) .wasm_component_model_gc(component_model_gc) + .wasm_component_model_fixed_size_lists(component_model_fixed_size_lists) .wasm_exceptions(exceptions) .wasm_stack_switching(stack_switching) .cranelift_nan_canonicalization(nan_canonicalization); diff --git a/crates/test-util/src/wast.rs b/crates/test-util/src/wast.rs index c07dda1f8b52..572315fb49d5 100644 --- a/crates/test-util/src/wast.rs +++ b/crates/test-util/src/wast.rs @@ -268,6 +268,7 @@ macro_rules! foreach_config_option { component_model_threading component_model_error_context component_model_gc + component_model_fixed_size_lists simd gc_types exceptions diff --git a/tests/misc_testsuite/component-model/fixed_size_list.wast b/tests/misc_testsuite/component-model/fixed_size_list.wast new file mode 100644 index 000000000000..5e20913caed1 --- /dev/null +++ b/tests/misc_testsuite/component-model/fixed_size_list.wast @@ -0,0 +1,421 @@ +;;! component_model_fixed_size_lists = true + +;; This contains two components which exercise fixed-size-list +;; types. The first acts as a roundtrip, the second calls the first +;; and compares the results. + +;; As this was written with C++ and wit-bindgen the functions +;; are not expected to be easily human readable. + +;; The exported function run() from the second component +;; calls nested-roundtrip([[1, 2], [3, 4]], [[-1, -2], [-3, -4]]) +;; from the first module and compares the resulting tuple with a +;; concatenation of the inputs. + +;; Every mismatch increases the return value by 1. + +(component + (component (;0;) + (type $ty-test:fixed-size-lists/to-test (;0;) + (instance + (type (;0;) (list u32 2)) + (type (;1;) (list 0 2)) + (type (;2;) (list s32 2)) + (type (;3;) (list 2 2)) + (type (;4;) (tuple 1 3)) + (type (;5;) (func (param "a" 1) (param "b" 3) (result 4))) + (export (;0;) "nested-roundtrip" (func (type 5))) + ) + ) + (import "test:fixed-size-lists/to-test" (instance $test:fixed-size-lists/to-test (;0;) (type $ty-test:fixed-size-lists/to-test))) + (core module $main (;0;) + (type (;0;) (func (param i32 i32 i32 i32 i32 i32 i32 i32 i32))) + (type (;1;) (func (result i32))) + (import "test:fixed-size-lists/to-test" "nested-roundtrip" (func (;0;) (type 0))) + (memory (;0;) 2) + (global (;0;) (mut i32) (i32.const 67232)) + (export "memory" (memory 0)) + ;; test runner, pass the values from the address 1024ff in registers + ;; to the roundtrip function and + ;; return the number of non-matching results + (export "run" (func 1)) + (func (;1;) (type 1) (result i32) + (local i32 i32 i32 i32 i32 i32 i32 i32 i32) + (global.set 0 + (local.tee 0 + (i32.add + (global.get 0) + (i32.const -64)))) + (i64.store + (i32.add + (local.tee 1 + (i32.add + (local.get 0) + (i32.const 16))) + (i32.const 8)) + (i64.load align=4 + (i32.const 1032))) + (i64.store + (i32.add + (local.get 0) + (i32.const 8)) + (i64.load align=4 + (i32.const 1048))) + (i64.store offset=16 + (local.get 0) + (i64.load align=4 + (i32.const 1024))) + (i64.store + (local.get 0) + (i64.load align=4 + (i32.const 1040))) + (global.set 0 + (local.tee 2 + (i32.sub + (global.get 0) + (i32.const 32)))) + (call 0 + (i32.load + (local.get 1)) + (i32.load offset=4 + (local.get 1)) + (i32.load offset=8 + (local.get 1)) + (i32.load offset=12 + (local.get 1)) + (i32.load + (local.get 0)) + (i32.load offset=4 + (local.get 0)) + (i32.load offset=8 + (local.get 0)) + (i32.load offset=12 + (local.get 0)) + (local.get 2)) + (i64.store offset=24 align=4 + (local.tee 1 + (i32.add + (local.get 0) + (i32.const 32))) + (i64.load offset=24 + (local.get 2))) + (i64.store offset=16 align=4 + (local.get 1) + (i64.load offset=16 + (local.get 2))) + (i64.store offset=8 align=4 + (local.get 1) + (i64.load offset=8 + (local.get 2))) + (i64.store align=4 + (local.get 1) + (i64.load + (local.get 2))) + (global.set 0 + (i32.add + (local.get 2) + (i32.const 32))) + (local.set 2 + (i32.load offset=48 + (local.get 0))) + (i32.add + (i32.add + (i32.add + (i32.add + (i32.add + (i32.add + (i32.add + (i32.ne + (i32.load offset=32 + (local.get 0)) + (local.set 3 + (i32.load offset=36 + (local.get 0))) + (local.set 4 + (i32.load offset=52 + (local.get 0))) + (local.set 5 + (i32.load offset=40 + (local.get 0))) + (local.set 6 + (i32.load offset=56 + (local.get 0))) + (local.set 7 + (i32.load offset=44 + (local.get 0))) + (local.set 8 + (i32.load offset=60 + (local.get 0))) + ;; here the output values are checked + (global.set 0 + (i32.sub + (local.get 0) + (i32.const -64))) + (i32.const 1)) + (i32.ne + (local.get 2) + (i32.const -1))) + (i32.ne + (local.get 3) + (i32.const 2))) + (i32.ne + (local.get 4) + (i32.const -2))) + (i32.ne + (local.get 5) + (i32.const 3))) + (i32.ne + (local.get 6) + (i32.const -3))) + (i32.ne + (local.get 7) + (i32.const 4))) + (i32.ne + (local.get 8) + (i32.const -4))) + ) + ;; here are the input values + (data (;0;) (i32.const 1024) "\01\00\00\00\02\00\00\00\03\00\00\00\04\00\00\00\ff\ff\ff\ff\fe\ff\ff\ff\fd\ff\ff\ff\fc\ff\ff\ff") + (data (;1;) (i32.const 1056) "\ff\ff\ff\ff\00\00\02") + (@producers + (processed-by "wit-component" "0.243.0") + ) + ) + (core module $wit-component-shim-module (;1;) + (type (;0;) (func (param i32 i32 i32 i32 i32 i32 i32 i32 i32))) + (table (;0;) 1 1 funcref) + (export "0" (func 0)) + (export "$imports" (table 0)) + (func (;0;) (type 0) (param i32 i32 i32 i32 i32 i32 i32 i32 i32) + (call_indirect (type 0) + (local.get 0) + (local.get 1) + (local.get 2) + (local.get 3) + (local.get 4) + (local.get 5) + (local.get 6) + (local.get 7) + (local.get 8) + (i32.const 0)) + ) + (@producers + (processed-by "wit-component" "0.243.0") + ) + ) + (core module $wit-component-fixup (;2;) + (type (;0;) (func (param i32 i32 i32 i32 i32 i32 i32 i32 i32))) + (import "" "0" (func (;0;) (type 0))) + (import "" "$imports" (table (;0;) 1 1 funcref)) + (elem (;0;) (i32.const 0) func 0) + (@producers + (processed-by "wit-component" "0.243.0") + ) + ) + (core instance $wit-component-shim-instance (;0;) (instantiate $wit-component-shim-module)) + (alias core export $wit-component-shim-instance "0" (core func $indirect-test:fixed-size-lists/to-test-nested-roundtrip (;0;))) + (core instance $test:fixed-size-lists/to-test (;1;) + (export "nested-roundtrip" (func $indirect-test:fixed-size-lists/to-test-nested-roundtrip)) + ) + (core instance $main (;2;) (instantiate $main + (with "test:fixed-size-lists/to-test" (instance $test:fixed-size-lists/to-test)) + ) + ) + (alias core export $main "memory" (core memory $memory (;0;))) + (alias core export $wit-component-shim-instance "$imports" (core table $"shim table" (;0;))) + (alias export $test:fixed-size-lists/to-test "nested-roundtrip" (func $nested-roundtrip (;0;))) + (core func $"#core-func1 indirect-test:fixed-size-lists/to-test-nested-roundtrip" (@name "indirect-test:fixed-size-lists/to-test-nested-roundtrip") (;1;) (canon lower (func $nested-roundtrip) (memory $memory))) + (core instance $fixup-args (;3;) + (export "$imports" (table $"shim table")) + (export "0" (func $"#core-func1 indirect-test:fixed-size-lists/to-test-nested-roundtrip")) + ) + (core instance $fixup (;4;) (instantiate $wit-component-fixup + (with "" (instance $fixup-args)) + ) + ) + (type (;1;) (func (result u32))) + (alias core export $main "run" (core func $run (;2;))) + (func $run (;1;) (type 1) (canon lift (core func $run))) + (export $"#func2 run" (@name "run") (;2;) "run" (func $run)) + (@producers + (processed-by "wit-component" "0.243.0") + ) + ) + (component (;1;) + (core module $main (;0;) + (type (;0;) (func (param i32 i32 i32 i32 i32 i32 i32 i32) (result i32))) + (memory (;0;) 2) + (global (;0;) (mut i32) (i32.const 67248)) + (export "memory" (memory 0)) + (export "test:fixed-size-lists/to-test#nested-roundtrip" (func 0)) + ;; This is an obfuscated store from the stack to address 1056, + ;; which is then returned + (func (;0;) (type 0) (param i32 i32 i32 i32 i32 i32 i32 i32) (result i32) + (local i32 i32 i64 i64) + (global.set 0 + (local.tee 8 + (i32.sub + (global.get 0) + (i32.const 96)))) + (i32.store + (local.tee 9 + (i32.add + (local.get 8) + (i32.const 56))) + (local.get 2)) + (i32.store + (local.tee 2 + (i32.add + (local.get 8) + (i32.const 40))) + (local.get 6)) + (i32.store offset=60 + (local.get 8) + (local.get 3)) + (i64.store + (local.tee 6 + (i32.add + (local.tee 3 + (i32.add + (local.get 8) + (i32.const 16))) + (i32.const 8))) + (i64.load + (local.get 9))) + (i32.store offset=44 + (local.get 8) + (local.get 7)) + (i64.store + (local.tee 7 + (i32.add + (local.get 8) + (i32.const 8))) + (i64.load + (local.get 2))) + (i64.store offset=48 + (local.get 8) + (local.tee 10 + (i64.or + (i64.extend_i32_u + (local.get 0)) + (i64.shl + (i64.extend_i32_u + (local.get 1)) + (i64.const 32))))) + (i64.store offset=32 + (local.get 8) + (local.tee 11 + (i64.or + (i64.extend_i32_u + (local.get 4)) + (i64.shl + (i64.extend_i32_u + (local.get 5)) + (i64.const 32))))) + (i64.store offset=16 + (local.get 8) + (local.get 10)) + (i64.store + (local.get 8) + (local.get 11)) + (i64.store align=4 + (local.tee 0 + (i32.sub + (local.get 8) + (i32.const -64))) + (i64.load align=4 + (local.get 3))) + (i64.store offset=16 align=4 + (local.get 0) + (i64.load align=4 + (local.get 8))) + (i64.store align=4 + (local.tee 1 + (i32.add + (local.get 0) + (i32.const 8))) + (i64.load align=4 + (local.get 6))) + (i64.store align=4 + (i32.add + (local.get 0) + (i32.const 24)) + (i64.load align=4 + (local.get 7))) + (i64.store + (i32.const 1064) + (i64.load align=4 + (local.get 1))) + (i64.store + (i32.const 1056) + (i64.load offset=64 align=4 + (local.get 8))) + (i64.store + (i32.const 1072) + (i64.load offset=80 align=4 + (local.get 8))) + (i64.store + (i32.const 1080) + (i64.load align=4 + (i32.add + (local.get 8) + (i32.const 88)))) + (global.set 0 + (i32.add + (local.get 8) + (i32.const 96))) + (i32.const 1056) + ) + (data (;0;) (i32.const 1024) "\ff\ff\ff\ff\00\00\02") + (@producers + (processed-by "wit-component" "0.243.0") + ) + ) + (core instance $main (;0;) (instantiate $main)) + (alias core export $main "memory" (core memory $memory (;0;))) + (type (;0;) (list u32 2)) + (type (;1;) (list 0 2)) + (type (;2;) (list s32 2)) + (type (;3;) (list 2 2)) + (type (;4;) (tuple 1 3)) + (type (;5;) (func (param "a" 1) (param "b" 3) (result 4))) + (alias core export $main "test:fixed-size-lists/to-test#nested-roundtrip" (core func $test:fixed-size-lists/to-test#nested-roundtrip (;0;))) + (func $nested-roundtrip (;0;) (type 5) (canon lift (core func $test:fixed-size-lists/to-test#nested-roundtrip) (memory $memory))) + (component $test:fixed-size-lists/to-test-shim-component (;0;) + (type (;0;) (list u32 2)) + (type (;1;) (list 0 2)) + (type (;2;) (list s32 2)) + (type (;3;) (list 2 2)) + (type (;4;) (tuple 1 3)) + (type (;5;) (func (param "a" 1) (param "b" 3) (result 4))) + (import "import-func-nested-roundtrip" (func (;0;) (type 5))) + (type (;6;) (list u32 2)) + (type (;7;) (list 6 2)) + (type (;8;) (list s32 2)) + (type (;9;) (list 8 2)) + (type (;10;) (tuple 7 9)) + (type (;11;) (func (param "a" 7) (param "b" 9) (result 10))) + (export (;1;) "nested-roundtrip" (func 0) (func (type 11))) + ) + (instance $test:fixed-size-lists/to-test-shim-instance (;0;) (instantiate $test:fixed-size-lists/to-test-shim-component + (with "import-func-nested-roundtrip" (func $nested-roundtrip)) + ) + ) + (export $test:fixed-size-lists/to-test (;1;) "test:fixed-size-lists/to-test" (instance $test:fixed-size-lists/to-test-shim-instance)) + (@producers + (processed-by "wit-component" "0.243.0") + ) + ) + (instance (;0;) (instantiate 1)) + (alias export 0 "test:fixed-size-lists/to-test" (instance (;1;))) + (instance (;2;) (instantiate 0 + (with "test:fixed-size-lists/to-test" (instance 1)) + ) + ) + (alias export 2 "run" (func (;0;))) + (export (;1;) "run" (func 0)) +) + +;; call run, it will return the number of mismatches in the test +(assert_return (invoke "run") + (u32.const 0)) From 3c5791815584a5bec21be97898ae1f112a308492 Mon Sep 17 00:00:00 2001 From: Christof Petig Date: Mon, 12 Jan 2026 20:58:33 +0100 Subject: [PATCH 11/14] cargo fmt and beautify fixed_size_list_type --- crates/environ/src/component/types_builder.rs | 7 ++++--- crates/fuzzing/src/generators/config.rs | 6 ++++-- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/crates/environ/src/component/types_builder.rs b/crates/environ/src/component/types_builder.rs index d3ddcbc4373a..a1bc71fc6f1a 100644 --- a/crates/environ/src/component/types_builder.rs +++ b/crates/environ/src/component/types_builder.rs @@ -596,11 +596,12 @@ impl ComponentTypesBuilder { let element_abi = self.component_types.canonical_abi(&element); let mut abi = element_abi.clone(); // this assumes that size32 is already rounded up to alignment - abi.size32 = element_abi.size32 * size; - abi.size64 = element_abi.size64 * size; + abi.size32 = element_abi.size32.saturating_mul(size); + abi.size64 = element_abi.size64.saturating_mul(size); abi.flat_count = element_abi .flat_count - .map(|c| c.saturating_mul(size.min(255) as u8)); + .zip(u8::try_from(size).ok()) + .and_then(|(flat_count, size)| flat_count.checked_mul(size)); self.add_fixed_size_list_type(TypeFixedSizeList { element, size, abi }) } diff --git a/crates/fuzzing/src/generators/config.rs b/crates/fuzzing/src/generators/config.rs index f4461bbaa81b..c9cef0cd9478 100644 --- a/crates/fuzzing/src/generators/config.rs +++ b/crates/fuzzing/src/generators/config.rs @@ -166,7 +166,8 @@ impl Config { self.module_config.component_model_error_context = component_model_error_context.unwrap_or(false); self.module_config.component_model_gc = component_model_gc.unwrap_or(false); - self.module_config.component_model_fixed_size_lists = component_model_fixed_size_lists.unwrap_or(false); + self.module_config.component_model_fixed_size_lists = + component_model_fixed_size_lists.unwrap_or(false); // Enable/disable proposals that wasm-smith has knobs for which will be // read when creating `wasmtime::Config`. @@ -292,7 +293,8 @@ impl Config { cfg.wasm.component_model_error_context = Some(self.module_config.component_model_error_context); cfg.wasm.component_model_gc = Some(self.module_config.component_model_gc); - cfg.wasm.component_model_fixed_size_lists = Some(self.module_config.component_model_fixed_size_lists); + cfg.wasm.component_model_fixed_size_lists = + Some(self.module_config.component_model_fixed_size_lists); cfg.wasm.custom_page_sizes = Some(self.module_config.config.custom_page_sizes_enabled); cfg.wasm.epoch_interruption = Some(self.wasmtime.epoch_interruption); cfg.wasm.extended_const = Some(self.module_config.config.extended_const_enabled); From 172e3e4ef343380009ee6bfde7fc8029b0ff494f Mon Sep 17 00:00:00 2001 From: Christof Petig Date: Tue, 13 Jan 2026 22:01:19 +0100 Subject: [PATCH 12/14] add multi memory as it is needed by the test runner --- tests/misc_testsuite/component-model/fixed_size_list.wast | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/misc_testsuite/component-model/fixed_size_list.wast b/tests/misc_testsuite/component-model/fixed_size_list.wast index 5e20913caed1..3afd7d297063 100644 --- a/tests/misc_testsuite/component-model/fixed_size_list.wast +++ b/tests/misc_testsuite/component-model/fixed_size_list.wast @@ -1,3 +1,4 @@ +;;! multi_memory = true ;;! component_model_fixed_size_lists = true ;; This contains two components which exercise fixed-size-list From 8bccd35890f266ea2fc7c46d476764808462e223 Mon Sep 17 00:00:00 2001 From: Christof Petig Date: Tue, 13 Jan 2026 22:28:44 +0100 Subject: [PATCH 13/14] standardize on the official name (component model standard) "fixed-length lists" changing wasm-tools (parser etc. is a different task) --- crates/cli-flags/src/lib.rs | 4 +-- crates/environ/src/component/types.rs | 12 ++++----- crates/environ/src/component/types_builder.rs | 25 +++++++++++-------- crates/environ/src/fact/trampoline.rs | 10 ++++---- crates/fuzzing/src/generators/config.rs | 10 ++++---- crates/fuzzing/src/generators/module.rs | 4 +-- crates/test-util/src/wasmtime_wast.rs | 6 ++--- crates/test-util/src/wast.rs | 2 +- crates/wasmtime/src/config.rs | 2 +- .../src/runtime/component/func/typed.rs | 2 +- .../wasmtime/src/runtime/component/types.rs | 4 +-- .../wasmtime/src/runtime/component/values.rs | 8 +++--- ...size_list.wast => fixed_length_lists.wast} | 2 +- 13 files changed, 47 insertions(+), 44 deletions(-) rename tests/misc_testsuite/component-model/{fixed_size_list.wast => fixed_length_lists.wast} (99%) diff --git a/crates/cli-flags/src/lib.rs b/crates/cli-flags/src/lib.rs index ca8bdf430786..742b07948fa8 100644 --- a/crates/cli-flags/src/lib.rs +++ b/crates/cli-flags/src/lib.rs @@ -411,7 +411,7 @@ wasmtime_option_group! { pub gc_support: Option, /// Component model support for fixed size lists: this corresponds /// to the 🔧 emoji in the component model specification - pub component_model_fixed_size_lists: Option, + pub component_model_fixed_length_lists: Option, } enum Wasm { @@ -1070,7 +1070,7 @@ impl CommonOptions { ("component-model-async", component_model_async_stackful, wasm_component_model_async_stackful) ("component-model-async", component_model_threading, wasm_component_model_threading) ("component-model", component_model_error_context, wasm_component_model_error_context) - ("component-model", component_model_fixed_size_lists, wasm_component_model_fixed_size_lists) + ("component-model", component_model_fixed_length_lists, wasm_component_model_fixed_length_lists) ("threads", threads, wasm_threads) ("gc", gc, wasm_gc) ("gc", reference_types, wasm_reference_types) diff --git a/crates/environ/src/component/types.rs b/crates/environ/src/component/types.rs index cc7936911a24..0f1a811a0d0f 100644 --- a/crates/environ/src/component/types.rs +++ b/crates/environ/src/component/types.rs @@ -90,7 +90,7 @@ indices! { /// Index pointing to a list type in the component model. pub struct TypeListIndex(u32); /// Index pointing to a fixed size list type in the component model. - pub struct TypeFixedSizeListIndex(u32); + pub struct TypeFixedLengthListIndex(u32); /// Index pointing to a future type in the component model. pub struct TypeFutureIndex(u32); @@ -298,7 +298,7 @@ pub struct ComponentTypes { pub(super) stream_tables: PrimaryMap, pub(super) error_context_tables: PrimaryMap, - pub(super) fixed_size_lists: PrimaryMap, + pub(super) fixed_length_lists: PrimaryMap, } impl TypeTrace for ComponentTypes { @@ -372,7 +372,7 @@ impl ComponentTypes { InterfaceType::Enum(i) => &self[*i].abi, InterfaceType::Option(i) => &self[*i].abi, InterfaceType::Result(i) => &self[*i].abi, - InterfaceType::FixedSizeList(i) => &self[*i].abi, + InterfaceType::FixedLengthList(i) => &self[*i].abi, } } @@ -422,7 +422,7 @@ impl_index! { impl Index for ComponentTypes { TypeFutureTable => future_tables } impl Index for ComponentTypes { TypeStreamTable => stream_tables } impl Index for ComponentTypes { TypeErrorContextTable => error_context_tables } - impl Index for ComponentTypes { TypeFixedSizeList => fixed_size_lists } + impl Index for ComponentTypes { TypeFixedLengthList => fixed_length_lists } } // Additionally forward anything that can index `ModuleTypes` to `ModuleTypes` @@ -600,7 +600,7 @@ pub enum InterfaceType { Future(TypeFutureTableIndex), Stream(TypeStreamTableIndex), ErrorContext(TypeComponentLocalErrorContextTableIndex), - FixedSizeList(TypeFixedSizeListIndex), + FixedLengthList(TypeFixedLengthListIndex), } /// Bye information about a type in the canonical ABI, with metadata for both @@ -1183,7 +1183,7 @@ pub struct TypeList { /// Shape of a "fixed size list" interface type. #[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)] -pub struct TypeFixedSizeList { +pub struct TypeFixedLengthList { /// The element type of the list. pub element: InterfaceType, /// The fixed length of the list. diff --git a/crates/environ/src/component/types_builder.rs b/crates/environ/src/component/types_builder.rs index a1bc71fc6f1a..68352f8e0158 100644 --- a/crates/environ/src/component/types_builder.rs +++ b/crates/environ/src/component/types_builder.rs @@ -50,7 +50,7 @@ pub struct ComponentTypesBuilder { future_tables: HashMap, stream_tables: HashMap, error_context_tables: HashMap, - fixed_size_lists: HashMap, + fixed_length_lists: HashMap, component_types: ComponentTypes, module_types: ModuleTypesBuilder, @@ -119,7 +119,7 @@ impl ComponentTypesBuilder { type_info: TypeInformationCache::default(), resources: ResourcesBuilder::default(), abstract_resources: 0, - fixed_size_lists: HashMap::default(), + fixed_length_lists: HashMap::default(), } } @@ -459,7 +459,7 @@ impl ComponentTypesBuilder { InterfaceType::Stream(self.stream_table_type(types, ty)?) } ComponentDefinedType::FixedSizeList(ty, size) => { - InterfaceType::FixedSizeList(self.fixed_size_list_type(types, ty, *size)?) + InterfaceType::FixedLengthList(self.fixed_size_list_type(types, ty, *size)?) } ComponentDefinedType::Map(..) => { bail!("support not implemented for map type"); @@ -582,7 +582,7 @@ impl ComponentTypesBuilder { types: TypesRef<'_>, ty: &ComponentValType, size: u32, - ) -> Result { + ) -> Result { assert_eq!(types.id(), self.module_types.validator_id()); let element = self.valtype(types, ty)?; Ok(self.new_fixed_size_list_type(element, size)) @@ -592,7 +592,7 @@ impl ComponentTypesBuilder { &mut self, element: InterfaceType, size: u32, - ) -> TypeFixedSizeListIndex { + ) -> TypeFixedLengthListIndex { let element_abi = self.component_types.canonical_abi(&element); let mut abi = element_abi.clone(); // this assumes that size32 is already rounded up to alignment @@ -602,7 +602,7 @@ impl ComponentTypesBuilder { .flat_count .zip(u8::try_from(size).ok()) .and_then(|(flat_count, size)| flat_count.checked_mul(size)); - self.add_fixed_size_list_type(TypeFixedSizeList { element, size, abi }) + self.add_fixed_size_list_type(TypeFixedLengthList { element, size, abi }) } fn flags_type(&mut self, flags: &IndexSet) -> TypeFlagsIndex { @@ -722,8 +722,11 @@ impl ComponentTypesBuilder { } /// Interns a new tuple type within this type information. - pub fn add_fixed_size_list_type(&mut self, ty: TypeFixedSizeList) -> TypeFixedSizeListIndex { - intern_and_fill_flat_types!(self, fixed_size_lists, ty) + pub fn add_fixed_size_list_type( + &mut self, + ty: TypeFixedLengthList, + ) -> TypeFixedLengthListIndex { + intern_and_fill_flat_types!(self, fixed_length_lists, ty) } /// Interns a new variant type within this type information. @@ -861,7 +864,7 @@ impl ComponentTypesBuilder { InterfaceType::Enum(i) => &self.type_info.enums[*i], InterfaceType::Option(i) => &self.type_info.options[*i], InterfaceType::Result(i) => &self.type_info.results[*i], - InterfaceType::FixedSizeList(i) => &self.type_info.fixed_size_lists[*i], + InterfaceType::FixedLengthList(i) => &self.type_info.fixed_length_lists[*i], } } } @@ -971,7 +974,7 @@ struct TypeInformationCache { options: PrimaryMap, results: PrimaryMap, lists: PrimaryMap, - fixed_size_lists: PrimaryMap, + fixed_length_lists: PrimaryMap, } struct TypeInformation { @@ -1121,7 +1124,7 @@ impl TypeInformation { self.build_record(ty.types.iter().map(|t| types.type_information(t))); } - fn fixed_size_lists(&mut self, types: &ComponentTypesBuilder, ty: &TypeFixedSizeList) { + fn fixed_length_lists(&mut self, types: &ComponentTypesBuilder, ty: &TypeFixedLengthList) { let element_info = types.type_information(&ty.element); self.depth = 1 + element_info.depth; self.has_borrow = element_info.has_borrow; diff --git a/crates/environ/src/fact/trampoline.rs b/crates/environ/src/fact/trampoline.rs index 269d632ed73d..cd6f24fcb0c3 100644 --- a/crates/environ/src/fact/trampoline.rs +++ b/crates/environ/src/fact/trampoline.rs @@ -19,7 +19,7 @@ use crate::component::{ CanonicalAbiInfo, ComponentTypesBuilder, FLAG_MAY_ENTER, FLAG_MAY_LEAVE, FixedEncoding as FE, FlatType, InterfaceType, MAX_FLAT_ASYNC_PARAMS, MAX_FLAT_PARAMS, PREPARE_ASYNC_NO_RESULT, PREPARE_ASYNC_WITH_RESULT, START_FLAG_ASYNC_CALLEE, StringEncoding, Transcode, - TypeComponentLocalErrorContextTableIndex, TypeEnumIndex, TypeFixedSizeListIndex, + TypeComponentLocalErrorContextTableIndex, TypeEnumIndex, TypeFixedLengthListIndex, TypeFlagsIndex, TypeFutureTableIndex, TypeListIndex, TypeOptionIndex, TypeRecordIndex, TypeResourceTableIndex, TypeResultIndex, TypeStreamTableIndex, TypeTupleIndex, TypeVariantIndex, VariantInfo, @@ -1127,7 +1127,7 @@ impl<'a, 'b> Compiler<'a, 'b> { | InterfaceType::Future(_) | InterfaceType::Stream(_) | InterfaceType::ErrorContext(_) => 1, - InterfaceType::FixedSizeList(i) => self.types[*i].size as usize, + InterfaceType::FixedLengthList(i) => self.types[*i].size as usize, }; match self.fuel.checked_sub(cost) { @@ -1167,7 +1167,7 @@ impl<'a, 'b> Compiler<'a, 'b> { InterfaceType::ErrorContext(t) => { self.translate_error_context(*t, src, dst_ty, dst) } - InterfaceType::FixedSizeList(t) => { + InterfaceType::FixedLengthList(t) => { self.translate_fixed_size_list(*t, src, dst_ty, dst); } } @@ -2865,14 +2865,14 @@ impl<'a, 'b> Compiler<'a, 'b> { fn translate_fixed_size_list( &mut self, - src_ty: TypeFixedSizeListIndex, + src_ty: TypeFixedLengthListIndex, src: &Source<'_>, dst_ty: &InterfaceType, dst: &Destination, ) { let src_ty = &self.types[src_ty]; let dst_ty = match dst_ty { - InterfaceType::FixedSizeList(t) => &self.types[*t], + InterfaceType::FixedLengthList(t) => &self.types[*t], _ => panic!("expected a fixed size list"), }; diff --git a/crates/fuzzing/src/generators/config.rs b/crates/fuzzing/src/generators/config.rs index c9cef0cd9478..1663e963c58a 100644 --- a/crates/fuzzing/src/generators/config.rs +++ b/crates/fuzzing/src/generators/config.rs @@ -140,7 +140,7 @@ impl Config { component_model_threading, component_model_error_context, component_model_gc, - component_model_fixed_size_lists, + component_model_fixed_length_lists, simd, exceptions, legacy_exceptions: _, @@ -166,8 +166,8 @@ impl Config { self.module_config.component_model_error_context = component_model_error_context.unwrap_or(false); self.module_config.component_model_gc = component_model_gc.unwrap_or(false); - self.module_config.component_model_fixed_size_lists = - component_model_fixed_size_lists.unwrap_or(false); + self.module_config.component_model_fixed_length_lists = + component_model_fixed_length_lists.unwrap_or(false); // Enable/disable proposals that wasm-smith has knobs for which will be // read when creating `wasmtime::Config`. @@ -293,8 +293,8 @@ impl Config { cfg.wasm.component_model_error_context = Some(self.module_config.component_model_error_context); cfg.wasm.component_model_gc = Some(self.module_config.component_model_gc); - cfg.wasm.component_model_fixed_size_lists = - Some(self.module_config.component_model_fixed_size_lists); + cfg.wasm.component_model_fixed_length_lists = + Some(self.module_config.component_model_fixed_length_lists); cfg.wasm.custom_page_sizes = Some(self.module_config.config.custom_page_sizes_enabled); cfg.wasm.epoch_interruption = Some(self.wasmtime.epoch_interruption); cfg.wasm.extended_const = Some(self.module_config.config.extended_const_enabled); diff --git a/crates/fuzzing/src/generators/module.rs b/crates/fuzzing/src/generators/module.rs index 8120e4526a6e..db89d56b5b82 100644 --- a/crates/fuzzing/src/generators/module.rs +++ b/crates/fuzzing/src/generators/module.rs @@ -22,7 +22,7 @@ pub struct ModuleConfig { pub component_model_threading: bool, pub component_model_error_context: bool, pub component_model_gc: bool, - pub component_model_fixed_size_lists: bool, + pub component_model_fixed_length_lists: bool, pub legacy_exceptions: bool, pub shared_memory: bool, } @@ -80,7 +80,7 @@ impl<'a> Arbitrary<'a> for ModuleConfig { component_model_threading: false, component_model_error_context: false, component_model_gc: false, - component_model_fixed_size_lists: false, + component_model_fixed_length_lists: false, legacy_exceptions: false, shared_memory: false, function_references_enabled: config.gc_enabled, diff --git a/crates/test-util/src/wasmtime_wast.rs b/crates/test-util/src/wasmtime_wast.rs index 63dce5dadeb4..d9a22a8684e8 100644 --- a/crates/test-util/src/wasmtime_wast.rs +++ b/crates/test-util/src/wasmtime_wast.rs @@ -43,7 +43,7 @@ pub fn apply_test_config(config: &mut Config, test_config: &wast::TestConfig) { component_model_threading, component_model_error_context, component_model_gc, - component_model_fixed_size_lists, + component_model_fixed_length_lists, nan_canonicalization, simd, exceptions, @@ -73,7 +73,7 @@ pub fn apply_test_config(config: &mut Config, test_config: &wast::TestConfig) { let component_model_threading = component_model_threading.unwrap_or(false); let component_model_error_context = component_model_error_context.unwrap_or(false); let component_model_gc = component_model_gc.unwrap_or(false); - let component_model_fixed_size_lists = component_model_fixed_size_lists.unwrap_or(false); + let component_model_fixed_length_lists = component_model_fixed_length_lists.unwrap_or(false); let nan_canonicalization = nan_canonicalization.unwrap_or(false); let relaxed_simd = relaxed_simd.unwrap_or(false); let legacy_exceptions = legacy_exceptions.unwrap_or(false); @@ -113,7 +113,7 @@ pub fn apply_test_config(config: &mut Config, test_config: &wast::TestConfig) { .wasm_component_model_threading(component_model_threading) .wasm_component_model_error_context(component_model_error_context) .wasm_component_model_gc(component_model_gc) - .wasm_component_model_fixed_size_lists(component_model_fixed_size_lists) + .wasm_component_model_fixed_length_lists(component_model_fixed_length_lists) .wasm_exceptions(exceptions) .wasm_stack_switching(stack_switching) .cranelift_nan_canonicalization(nan_canonicalization); diff --git a/crates/test-util/src/wast.rs b/crates/test-util/src/wast.rs index 572315fb49d5..5408ee33feb4 100644 --- a/crates/test-util/src/wast.rs +++ b/crates/test-util/src/wast.rs @@ -268,7 +268,7 @@ macro_rules! foreach_config_option { component_model_threading component_model_error_context component_model_gc - component_model_fixed_size_lists + component_model_fixed_length_lists simd gc_types exceptions diff --git a/crates/wasmtime/src/config.rs b/crates/wasmtime/src/config.rs index 2d9b2529606a..ac6850648165 100644 --- a/crates/wasmtime/src/config.rs +++ b/crates/wasmtime/src/config.rs @@ -1301,7 +1301,7 @@ impl Config { /// Please note that Wasmtime's support for this feature is _very_ /// incomplete. #[cfg(feature = "component-model")] - pub fn wasm_component_model_fixed_size_lists(&mut self, enable: bool) -> &mut Self { + pub fn wasm_component_model_fixed_length_lists(&mut self, enable: bool) -> &mut Self { self.wasm_features(WasmFeatures::CM_FIXED_SIZE_LIST, enable); self } diff --git a/crates/wasmtime/src/runtime/component/func/typed.rs b/crates/wasmtime/src/runtime/component/func/typed.rs index ce634baaeed9..b88ebdd5c6c9 100644 --- a/crates/wasmtime/src/runtime/component/func/typed.rs +++ b/crates/wasmtime/src/runtime/component/func/typed.rs @@ -2895,7 +2895,7 @@ pub fn desc(ty: &InterfaceType) -> &'static str { InterfaceType::Future(_) => "future", InterfaceType::Stream(_) => "stream", InterfaceType::ErrorContext(_) => "error-context", - InterfaceType::FixedSizeList(_) => "list<_, N>", + InterfaceType::FixedLengthList(_) => "list<_, N>", } } diff --git a/crates/wasmtime/src/runtime/component/types.rs b/crates/wasmtime/src/runtime/component/types.rs index ded4944542d2..63aff29672d1 100644 --- a/crates/wasmtime/src/runtime/component/types.rs +++ b/crates/wasmtime/src/runtime/component/types.rs @@ -158,7 +158,7 @@ impl TypeChecker<'_> { (InterfaceType::Stream(_), _) => false, (InterfaceType::ErrorContext(_), InterfaceType::ErrorContext(_)) => true, (InterfaceType::ErrorContext(_), _) => false, - (InterfaceType::FixedSizeList(_), _) => todo!(), // FIXME(#12279) + (InterfaceType::FixedLengthList(_), _) => todo!(), // FIXME(#12279) } } @@ -856,7 +856,7 @@ impl Type { InterfaceType::Future(index) => Type::Future(instance.future_type(*index)), InterfaceType::Stream(index) => Type::Stream(instance.stream_type(*index)), InterfaceType::ErrorContext(_) => Type::ErrorContext, - InterfaceType::FixedSizeList(_) => todo!(), // FIXME(#12279) + InterfaceType::FixedLengthList(_) => todo!(), // FIXME(#12279) } } diff --git a/crates/wasmtime/src/runtime/component/values.rs b/crates/wasmtime/src/runtime/component/values.rs index 2e478ae6116e..695cb140a864 100644 --- a/crates/wasmtime/src/runtime/component/values.rs +++ b/crates/wasmtime/src/runtime/component/values.rs @@ -215,7 +215,7 @@ impl Val { InterfaceType::ErrorContext(_) => { ErrorContext::linear_lift_from_flat(cx, ty, next(src))?.into_val() } - InterfaceType::FixedSizeList(_) => todo!(), // FIXME(#12279) + InterfaceType::FixedLengthList(_) => todo!(), // FIXME(#12279) }) } @@ -342,7 +342,7 @@ impl Val { InterfaceType::ErrorContext(_) => { ErrorContext::linear_lift_from_memory(cx, ty, bytes)?.into_val() } - InterfaceType::FixedSizeList(_) => todo!(), // FIXME(#12279) + InterfaceType::FixedLengthList(_) => todo!(), // FIXME(#12279) }) } @@ -493,7 +493,7 @@ impl Val { ) } (InterfaceType::ErrorContext(_), _) => unexpected(ty, self), - (InterfaceType::FixedSizeList(_), _) => todo!(), // FIXME(#12279) + (InterfaceType::FixedLengthList(_), _) => todo!(), // FIXME(#12279) } } @@ -647,7 +647,7 @@ impl Val { ) } (InterfaceType::ErrorContext(_), _) => unexpected(ty, self), - (InterfaceType::FixedSizeList(_), _) => todo!(), // FIXME(#12279) + (InterfaceType::FixedLengthList(_), _) => todo!(), // FIXME(#12279) } } diff --git a/tests/misc_testsuite/component-model/fixed_size_list.wast b/tests/misc_testsuite/component-model/fixed_length_lists.wast similarity index 99% rename from tests/misc_testsuite/component-model/fixed_size_list.wast rename to tests/misc_testsuite/component-model/fixed_length_lists.wast index 3afd7d297063..9e1d76563bd0 100644 --- a/tests/misc_testsuite/component-model/fixed_size_list.wast +++ b/tests/misc_testsuite/component-model/fixed_length_lists.wast @@ -1,5 +1,5 @@ ;;! multi_memory = true -;;! component_model_fixed_size_lists = true +;;! component_model_fixed_length_lists = true ;; This contains two components which exercise fixed-size-list ;; types. The first acts as a roundtrip, the second calls the first From 8ac25135d5f3daac878991789b5b78778adde952 Mon Sep 17 00:00:00 2001 From: Christof Petig Date: Tue, 13 Jan 2026 22:39:16 +0100 Subject: [PATCH 14/14] More instances of fixed size corrected to fixed length --- crates/cli-flags/src/lib.rs | 2 +- crates/environ/src/component/types_builder.rs | 12 ++++++------ crates/environ/src/fact/trampoline.rs | 4 ++-- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/crates/cli-flags/src/lib.rs b/crates/cli-flags/src/lib.rs index 742b07948fa8..6cc61e6cfb07 100644 --- a/crates/cli-flags/src/lib.rs +++ b/crates/cli-flags/src/lib.rs @@ -409,7 +409,7 @@ wasmtime_option_group! { pub exceptions: Option, /// Whether or not any GC infrastructure in Wasmtime is enabled or not. pub gc_support: Option, - /// Component model support for fixed size lists: this corresponds + /// Component model support for fixed-length lists: this corresponds /// to the 🔧 emoji in the component model specification pub component_model_fixed_length_lists: Option, } diff --git a/crates/environ/src/component/types_builder.rs b/crates/environ/src/component/types_builder.rs index 68352f8e0158..ddfe291b0826 100644 --- a/crates/environ/src/component/types_builder.rs +++ b/crates/environ/src/component/types_builder.rs @@ -459,7 +459,7 @@ impl ComponentTypesBuilder { InterfaceType::Stream(self.stream_table_type(types, ty)?) } ComponentDefinedType::FixedSizeList(ty, size) => { - InterfaceType::FixedLengthList(self.fixed_size_list_type(types, ty, *size)?) + InterfaceType::FixedLengthList(self.fixed_length_list_type(types, ty, *size)?) } ComponentDefinedType::Map(..) => { bail!("support not implemented for map type"); @@ -577,7 +577,7 @@ impl ComponentTypesBuilder { self.add_tuple_type(TypeTuple { types, abi }) } - fn fixed_size_list_type( + fn fixed_length_list_type( &mut self, types: TypesRef<'_>, ty: &ComponentValType, @@ -585,10 +585,10 @@ impl ComponentTypesBuilder { ) -> Result { assert_eq!(types.id(), self.module_types.validator_id()); let element = self.valtype(types, ty)?; - Ok(self.new_fixed_size_list_type(element, size)) + Ok(self.new_fixed_length_list_type(element, size)) } - pub(crate) fn new_fixed_size_list_type( + pub(crate) fn new_fixed_length_list_type( &mut self, element: InterfaceType, size: u32, @@ -602,7 +602,7 @@ impl ComponentTypesBuilder { .flat_count .zip(u8::try_from(size).ok()) .and_then(|(flat_count, size)| flat_count.checked_mul(size)); - self.add_fixed_size_list_type(TypeFixedLengthList { element, size, abi }) + self.add_fixed_length_list_type(TypeFixedLengthList { element, size, abi }) } fn flags_type(&mut self, flags: &IndexSet) -> TypeFlagsIndex { @@ -722,7 +722,7 @@ impl ComponentTypesBuilder { } /// Interns a new tuple type within this type information. - pub fn add_fixed_size_list_type( + pub fn add_fixed_length_list_type( &mut self, ty: TypeFixedLengthList, ) -> TypeFixedLengthListIndex { diff --git a/crates/environ/src/fact/trampoline.rs b/crates/environ/src/fact/trampoline.rs index cd6f24fcb0c3..2df0b1e6babb 100644 --- a/crates/environ/src/fact/trampoline.rs +++ b/crates/environ/src/fact/trampoline.rs @@ -1168,7 +1168,7 @@ impl<'a, 'b> Compiler<'a, 'b> { self.translate_error_context(*t, src, dst_ty, dst) } InterfaceType::FixedLengthList(t) => { - self.translate_fixed_size_list(*t, src, dst_ty, dst); + self.translate_fixed_length_list(*t, src, dst_ty, dst); } } } @@ -2863,7 +2863,7 @@ impl<'a, 'b> Compiler<'a, 'b> { } } - fn translate_fixed_size_list( + fn translate_fixed_length_list( &mut self, src_ty: TypeFixedLengthListIndex, src: &Source<'_>,