-
Notifications
You must be signed in to change notification settings - Fork 1.5k
Minimal implementation of fixed size lists to enable wit-bindgen runtime tests #10619
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 1 commit
c87e8c5
23f832d
46e9b5c
b663725
1cf1e10
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -50,6 +50,7 @@ pub struct ComponentTypesBuilder { | |
future_tables: HashMap<TypeFutureTable, TypeFutureTableIndex>, | ||
stream_tables: HashMap<TypeStreamTable, TypeStreamTableIndex>, | ||
error_context_tables: HashMap<TypeErrorContextTable, TypeComponentLocalErrorContextTableIndex>, | ||
fixed_size_lists: HashMap<TypeFixedSizeList, TypeFixedSizeListIndex>, | ||
|
||
component_types: ComponentTypes, | ||
module_types: ModuleTypesBuilder, | ||
|
@@ -111,6 +112,7 @@ impl ComponentTypesBuilder { | |
component_types: ComponentTypes::default(), | ||
type_info: TypeInformationCache::default(), | ||
resources: ResourcesBuilder::default(), | ||
fixed_size_lists: HashMap::default(), | ||
} | ||
} | ||
|
||
|
@@ -418,6 +420,9 @@ impl ComponentTypesBuilder { | |
ComponentDefinedType::Stream(ty) => { | ||
InterfaceType::Stream(self.stream_table_type(types, ty)?) | ||
} | ||
ComponentDefinedType::FixedSizeList(ty, size) => { | ||
InterfaceType::FixedSizeList(self.fixed_size_list_type(types, ty, *size)?) | ||
} | ||
}; | ||
let info = self.type_information(&ret); | ||
if info.depth > MAX_TYPE_DEPTH { | ||
|
@@ -531,6 +536,19 @@ impl ComponentTypesBuilder { | |
self.add_tuple_type(TypeTuple { types, abi }) | ||
} | ||
|
||
fn fixed_size_list_type(&mut self, types: TypesRef<'_>, ty: &ComponentValType, size: u32) -> Result<TypeFixedSizeListIndex> { | ||
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<KebabString>) -> TypeFlagsIndex { | ||
let flags = TypeFlags { | ||
names: flags.iter().map(|s| s.to_string()).collect(), | ||
|
@@ -647,6 +665,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) | ||
|
@@ -782,6 +805,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], | ||
} | ||
} | ||
} | ||
|
@@ -891,6 +915,7 @@ struct TypeInformationCache { | |
options: PrimaryMap<TypeOptionIndex, TypeInformation>, | ||
results: PrimaryMap<TypeResultIndex, TypeInformation>, | ||
lists: PrimaryMap<TypeListIndex, TypeInformation>, | ||
fixed_size_lists: PrimaryMap<TypeFixedSizeListIndex, TypeInformation>, | ||
} | ||
|
||
struct TypeInformation { | ||
|
@@ -1040,6 +1065,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))); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same as above, I think it'd be best to avoid "feigning" a record here and using a dedicated computation for fixed-size lists to avoid O(n) in the length of the list |
||
} | ||
|
||
fn enums(&mut self, _types: &ComponentTypesBuilder, _ty: &TypeEnum) { | ||
self.depth = 1; | ||
self.flat.push(FlatType::I32, FlatType::I32); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -16,11 +16,7 @@ | |
//! can be somewhat arbitrary, an intentional decision. | ||
|
||
use crate::component::{ | ||
CanonicalAbiInfo, ComponentTypesBuilder, FixedEncoding as FE, FlatType, InterfaceType, | ||
StringEncoding, Transcode, TypeComponentLocalErrorContextTableIndex, TypeEnumIndex, | ||
TypeFlagsIndex, TypeFutureTableIndex, TypeListIndex, TypeOptionIndex, TypeRecordIndex, | ||
TypeResourceTableIndex, TypeResultIndex, TypeStreamTableIndex, TypeTupleIndex, | ||
TypeVariantIndex, VariantInfo, FLAG_MAY_ENTER, FLAG_MAY_LEAVE, MAX_FLAT_PARAMS, | ||
CanonicalAbiInfo, ComponentTypesBuilder, FixedEncoding as FE, FlatType, InterfaceType, StringEncoding, Transcode, TypeComponentLocalErrorContextTableIndex, TypeEnumIndex, TypeFixedSizeListIndex, TypeFlagsIndex, TypeFutureTableIndex, TypeListIndex, TypeOptionIndex, TypeRecordIndex, TypeResourceTableIndex, TypeResultIndex, TypeStreamTableIndex, TypeTupleIndex, TypeVariantIndex, VariantInfo, FLAG_MAY_ENTER, FLAG_MAY_LEAVE, MAX_FLAT_PARAMS | ||
}; | ||
use crate::fact::signature::Signature; | ||
use crate::fact::transcode::Transcoder; | ||
|
@@ -1044,6 +1040,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) { | ||
|
@@ -1083,6 +1080,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); | ||
} | ||
} | ||
} | ||
|
||
|
@@ -2628,6 +2628,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); | ||
} | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is a bit of an interesting case. Effectively what this is doing is unrolling Basically what I'm saying is that I think we must implement the loop-based variant of translating lists, not just the fully-unrolled version of translating lists. |
||
|
||
fn translate_variant( | ||
&mut self, | ||
src_ty: TypeVariantIndex, | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could this be done with a new helper? I'm wary of defining an O(n) thing here and relying on LLVM to optimize it. This could make
list<T, BigNumber>
excessively slow in debug builds of Wasmtime for example.