components: Fix support for 0-sized flags (#4560)
This commit goes through and updates support in the various argument passing routines to support 0-sized flags. A bit of a degenerate case but clarified in WebAssembly/component-model#76 as intentional.
This commit is contained in:
@@ -352,6 +352,7 @@ fn expand_record_for_component_type(
|
||||
#[repr(C)]
|
||||
pub struct #lower <#lower_generic_params> {
|
||||
#lower_field_declarations
|
||||
_align: [wasmtime::ValRaw; 0],
|
||||
}
|
||||
|
||||
unsafe impl #impl_generics wasmtime::component::ComponentType for #name #ty_generics #where_clause {
|
||||
@@ -965,6 +966,10 @@ fn expand_flags(flags: &Flags) -> Result<TokenStream> {
|
||||
let count = flags.flags.len();
|
||||
|
||||
match size {
|
||||
FlagsSize::Size0 => {
|
||||
ty = quote!(());
|
||||
eq = quote!(true);
|
||||
}
|
||||
FlagsSize::Size1 => {
|
||||
ty = quote!(u8);
|
||||
|
||||
@@ -1021,6 +1026,17 @@ fn expand_flags(flags: &Flags) -> Result<TokenStream> {
|
||||
let mut not;
|
||||
|
||||
match size {
|
||||
FlagsSize::Size0 => {
|
||||
count = 0;
|
||||
as_array = quote!([]);
|
||||
bitor = quote!(Self {});
|
||||
bitor_assign = quote!();
|
||||
bitand = quote!(Self {});
|
||||
bitand_assign = quote!();
|
||||
bitxor = quote!(Self {});
|
||||
bitxor_assign = quote!();
|
||||
not = quote!(Self {});
|
||||
}
|
||||
FlagsSize::Size1 | FlagsSize::Size2 => {
|
||||
count = 1;
|
||||
as_array = quote!([self.__inner0 as u32]);
|
||||
@@ -1085,6 +1101,7 @@ fn expand_flags(flags: &Flags) -> Result<TokenStream> {
|
||||
component_names.extend(quote!(#component_name,));
|
||||
|
||||
let fields = match size {
|
||||
FlagsSize::Size0 => quote!(),
|
||||
FlagsSize::Size1 => {
|
||||
let init = 1_u8 << index;
|
||||
quote!(__inner0: #init)
|
||||
|
||||
@@ -48,6 +48,8 @@ impl From<DiscriminantSize> for usize {
|
||||
|
||||
/// Represents the number of bytes required to store a flags value in the component model
|
||||
pub enum FlagsSize {
|
||||
/// There are no flags
|
||||
Size0,
|
||||
/// Flags can fit in a u8
|
||||
Size1,
|
||||
/// Flags can fit in a u16
|
||||
@@ -59,7 +61,9 @@ pub enum FlagsSize {
|
||||
impl FlagsSize {
|
||||
/// Calculate the size needed to represent a value with the specified number of flags.
|
||||
pub fn from_count(count: usize) -> FlagsSize {
|
||||
if count <= 8 {
|
||||
if count == 0 {
|
||||
FlagsSize::Size0
|
||||
} else if count <= 8 {
|
||||
FlagsSize::Size1
|
||||
} else if count <= 16 {
|
||||
FlagsSize::Size2
|
||||
|
||||
@@ -53,10 +53,8 @@ enum ValType {
|
||||
Float64,
|
||||
Char,
|
||||
Record(Vec<ValType>),
|
||||
// FIXME(WebAssembly/component-model#75) are zero-sized flags allowed?
|
||||
//
|
||||
// ... otherwise go up to 65 flags to exercise up to 3 u32 values
|
||||
Flags(UsizeInRange<1, 65>),
|
||||
// Up to 65 flags to exercise up to 3 u32 values
|
||||
Flags(UsizeInRange<0, 65>),
|
||||
Tuple(Vec<ValType>),
|
||||
Variant(NonZeroLenVec<ValType>),
|
||||
Union(NonZeroLenVec<ValType>),
|
||||
|
||||
@@ -700,6 +700,7 @@ impl Compiler<'_, '_> {
|
||||
assert_eq!(src_ty.names, dst_ty.names);
|
||||
let cnt = src_ty.names.len();
|
||||
match FlagsSize::from_count(cnt) {
|
||||
FlagsSize::Size0 => {}
|
||||
FlagsSize::Size1 => {
|
||||
let mask = if cnt == 8 { 0xff } else { (1 << cnt) - 1 };
|
||||
self.convert_u8_mask(src, dst, mask);
|
||||
|
||||
@@ -606,6 +606,10 @@ impl Type {
|
||||
}
|
||||
|
||||
Type::Flags(handle) => match FlagsSize::from_count(handle.names().len()) {
|
||||
FlagsSize::Size0 => SizeAndAlignment {
|
||||
size: 0,
|
||||
alignment: 1,
|
||||
},
|
||||
FlagsSize::Size1 => SizeAndAlignment {
|
||||
size: 1,
|
||||
alignment: 1,
|
||||
|
||||
@@ -699,6 +699,7 @@ impl Val {
|
||||
ty: handle.clone(),
|
||||
count: u32::try_from(handle.names().len())?,
|
||||
value: match FlagsSize::from_count(handle.names().len()) {
|
||||
FlagsSize::Size0 => Box::new([]),
|
||||
FlagsSize::Size1 => iter::once(u8::load(mem, bytes)? as u32).collect(),
|
||||
FlagsSize::Size2 => iter::once(u16::load(mem, bytes)? as u32).collect(),
|
||||
FlagsSize::Size4Plus(n) => (0..n)
|
||||
@@ -850,6 +851,7 @@ impl Val {
|
||||
|
||||
Val::Flags(Flags { count, value, .. }) => {
|
||||
match FlagsSize::from_count(*count as usize) {
|
||||
FlagsSize::Size0 => {}
|
||||
FlagsSize::Size1 => u8::try_from(value[0]).unwrap().store(mem, offset)?,
|
||||
FlagsSize::Size2 => u16::try_from(value[0]).unwrap().store(mem, offset)?,
|
||||
FlagsSize::Size4Plus(_) => {
|
||||
@@ -1018,6 +1020,7 @@ fn lower_list<T>(
|
||||
/// Note that this will always return at least 1, even if the `count` parameter is zero.
|
||||
pub(crate) fn u32_count_for_flag_count(count: usize) -> usize {
|
||||
match FlagsSize::from_count(count) {
|
||||
FlagsSize::Size0 => 0,
|
||||
FlagsSize::Size1 | FlagsSize::Size2 => 1,
|
||||
FlagsSize::Size4Plus(n) => n,
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user