From dbc4eebbfe4404a959153a09cdfb2975882ce203 Mon Sep 17 00:00:00 2001 From: Pat Hickey Date: Wed, 4 Dec 2019 17:16:29 -0800 Subject: [PATCH 1/2] wig: update to latest witx --- crates/wasi-common/WASI | 2 +- crates/wasi-common/wig/src/raw_types.rs | 302 ++++++++++++------------ 2 files changed, 147 insertions(+), 157 deletions(-) diff --git a/crates/wasi-common/WASI b/crates/wasi-common/WASI index 9b298d7911..9150e66a34 160000 --- a/crates/wasi-common/WASI +++ b/crates/wasi-common/WASI @@ -1 +1 @@ -Subproject commit 9b298d7911986788bdfac662ed115ea6701b2c9a +Subproject commit 9150e66a349dff6215b0290ee8f66794fbfa5ea8 diff --git a/crates/wasi-common/wig/src/raw_types.rs b/crates/wasi-common/wig/src/raw_types.rs index c03b03471e..7168dc3c97 100644 --- a/crates/wasi-common/wig/src/raw_types.rs +++ b/crates/wasi-common/wig/src/raw_types.rs @@ -39,114 +39,114 @@ pub fn gen(args: TokenStream, mode: Mode) -> TokenStream { } fn gen_datatypes(output: &mut TokenStream, doc: &witx::Document, mode: Mode) { - for datatype in doc.datatypes() { - if mode.include_target_types() != type_has_target_size(doc, &datatype) { + for namedtype in doc.typenames() { + if mode.include_target_types() != namedtype_has_target_size(&namedtype) { continue; } - gen_datatype(output, doc, mode, &datatype); + gen_datatype(output, mode, &namedtype); } } -fn gen_datatype( - output: &mut TokenStream, - doc: &witx::Document, - mode: Mode, - datatype: &witx::Datatype, -) { - match &datatype.variant { - witx::DatatypeVariant::Alias(a) => { - if a.name.as_str() == "size" { - let wasi_name = format_ident!("__wasi_{}_t", a.name.as_str()); - match mode { - Mode::Host => output.extend(quote!(pub type #wasi_name = usize;)), - Mode::Wasi => panic!("size has target-specific size"), - Mode::Wasi32 => output.extend(quote!(pub type #wasi_name = u32;)), +fn gen_datatype(output: &mut TokenStream, mode: Mode, namedtype: &witx::NamedType) { + let wasi_name = format_ident!("__wasi_{}_t", namedtype.name.as_str()); + match &namedtype.dt { + witx::TypeRef::Name(alias_to) => { + let to = tref_tokens(mode, &alias_to.dt); + output.extend(quote!(pub type #wasi_name = #to;)); + } + witx::TypeRef::Value(v) => match &**v { + witx::Type::Enum(e) => { + let repr = int_repr_tokens(e.repr); + output.extend(quote!(pub type #wasi_name = #repr;)); + for (index, variant) in e.variants.iter().enumerate() { + let value_name = format_ident!( + "__WASI_{}_{}", + namedtype.name.as_str().to_shouty_snake_case(), + variant.name.as_str().to_shouty_snake_case() + ); + let index_name = Literal::usize_unsuffixed(index); + output.extend(quote!(pub const #value_name: #wasi_name = #index_name;)); } - } else { - let wasi_name = format_ident!("__wasi_{}_t", a.name.as_str()); - let to = ident_tokens(mode, &a.to); - output.extend(quote!(pub type #wasi_name = #to;)); } - } - witx::DatatypeVariant::Enum(e) => { - let wasi_name = format_ident!("__wasi_{}_t", e.name.as_str()); - let repr = int_repr_tokens(e.repr); - output.extend(quote!(pub type #wasi_name = #repr;)); - for (index, variant) in e.variants.iter().enumerate() { - let value_name = format_ident!( - "__WASI_{}_{}", - e.name.as_str().to_shouty_snake_case(), - variant.name.as_str().to_shouty_snake_case() - ); - let index_name = Literal::usize_unsuffixed(index); - output.extend(quote!(pub const #value_name: #wasi_name = #index_name;)); + witx::Type::Flags(f) => { + let repr = int_repr_tokens(f.repr); + output.extend(quote!(pub type #wasi_name = #repr;)); + for (index, flag) in f.flags.iter().enumerate() { + let value_name = format_ident!( + "__WASI_{}_{}", + namedtype.name.as_str().to_shouty_snake_case(), + flag.name.as_str().to_shouty_snake_case() + ); + let flag_value = Literal::u128_unsuffixed( + 1u128 + .checked_shl(u32::try_from(index).expect("flag value overflow")) + .expect("flag value overflow"), + ); + output.extend(quote!(pub const #value_name: #wasi_name = #flag_value;)); + } } - } - witx::DatatypeVariant::Flags(f) => { - let wasi_name = format_ident!("__wasi_{}_t", f.name.as_str()); - let repr = int_repr_tokens(f.repr); - output.extend(quote!(pub type #wasi_name = #repr;)); - for (index, flag) in f.flags.iter().enumerate() { - let value_name = format_ident!( - "__WASI_{}_{}", - f.name.as_str().to_shouty_snake_case(), - flag.name.as_str().to_shouty_snake_case() - ); - let flag_value = Literal::u128_unsuffixed( - 1u128 - .checked_shl(u32::try_from(index).expect("flag value overflow")) - .expect("flag value overflow"), - ); - output.extend(quote!(pub const #value_name: #wasi_name = #flag_value;)); - } - } - witx::DatatypeVariant::Struct(s) => { - output.extend(quote!(#[repr(C)])); + witx::Type::Struct(s) => { + output.extend(quote!(#[repr(C)])); + // Types which contain unions can't trivially implement Debug, + // Hash, or Eq, because the type itself doesn't record which + // union member is active. + if struct_has_union(&s) { + output.extend(quote!(#[derive(Copy, Clone)])); + output.extend(quote!(#[allow(missing_debug_implementations)])); + } else { + output.extend(quote!(#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)])); + } - // Types which contain unions can't trivially implement Debug, - // Hash, or Eq, because the type itself doesn't record which - // union member is active. - if struct_has_union(&doc, s) { + output.extend(quote!(pub struct #wasi_name)); + + let mut inner = TokenStream::new(); + for member in &s.members { + let member_name = format_ident!("r#{}", member.name.as_str()); + let member_type = tref_tokens(mode, &member.tref); + inner.extend(quote!(pub #member_name: #member_type,)); + } + let braced = Group::new(Delimiter::Brace, inner); + output.extend(TokenStream::from(TokenTree::Group(braced))); + } + witx::Type::Union(u) => { + output.extend(quote!(#[repr(C)])); output.extend(quote!(#[derive(Copy, Clone)])); output.extend(quote!(#[allow(missing_debug_implementations)])); - } else { - output.extend(quote!(#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)])); + + output.extend(quote!(pub union #wasi_name)); + + let mut inner = TokenStream::new(); + for variant in &u.variants { + let variant_name = format_ident!("r#{}", variant.name.as_str()); + let variant_type = tref_tokens(mode, &variant.tref); + inner.extend(quote!(pub #variant_name: #variant_type,)); + } + let braced = Group::new(Delimiter::Brace, inner); + output.extend(TokenStream::from(TokenTree::Group(braced))); } - - let wasi_name = format_ident!("__wasi_{}_t", s.name.as_str()); - output.extend(quote!(pub struct #wasi_name)); - - let mut inner = TokenStream::new(); - for member in &s.members { - let member_name = format_ident!("r#{}", member.name.as_str()); - let member_type = ident_tokens(mode, &member.type_); - inner.extend(quote!(pub #member_name: #member_type,)); + witx::Type::Handle(_h) => { + output.extend(quote!(pub type #wasi_name = u32;)); } - let braced = Group::new(Delimiter::Brace, inner); - output.extend(TokenStream::from(TokenTree::Group(braced))); - } - witx::DatatypeVariant::Union(u) => { - output.extend(quote!(#[repr(C)])); - output.extend(quote!(#[derive(Copy, Clone)])); - output.extend(quote!(#[allow(missing_debug_implementations)])); - - let wasi_name = format_ident!("__wasi_{}_t", u.name.as_str()); - output.extend(quote!(pub union #wasi_name)); - - let mut inner = TokenStream::new(); - for variant in &u.variants { - let variant_name = format_ident!("r#{}", variant.name.as_str()); - let variant_type = ident_tokens(mode, &variant.type_); - inner.extend(quote!(pub #variant_name: #variant_type,)); + witx::Type::Builtin(b) => { + if namedtype.name.as_str() == "size" { + match mode { + Mode::Host => output.extend(quote!(pub type #wasi_name = usize;)), + Mode::Wasi => panic!("size has target-specific size"), + Mode::Wasi32 => output.extend(quote!(pub type #wasi_name = u32;)), + } + } else { + let b_type = builtin_tokens(mode, *b); + output.extend(quote!(pub type #wasi_name = #b_type;)); + } } - let braced = Group::new(Delimiter::Brace, inner); - output.extend(TokenStream::from(TokenTree::Group(braced))); - } - witx::DatatypeVariant::Handle(a) => { - let wasi_name = format_ident!("__wasi_{}_t", a.name.as_str()); - output.extend(quote!(pub type #wasi_name = u32;)); - } + witx::Type::Pointer { .. } + | witx::Type::ConstPointer { .. } + | witx::Type::Array { .. } => { + let tref_tokens = tref_tokens(mode, &namedtype.dt); + output.extend(quote!(pub type #wasi_name = #tref_tokens;)); + } + }, } } @@ -179,86 +179,76 @@ fn builtin_tokens(mode: Mode, builtin: witx::BuiltinType) -> TokenStream { } } -fn ident_tokens(mode: Mode, ident: &witx::DatatypeIdent) -> TokenStream { - match ident { - witx::DatatypeIdent::Builtin(builtin) => builtin_tokens(mode, *builtin), - witx::DatatypeIdent::Ident(ident) => TokenStream::from(TokenTree::Ident(format_ident!( +fn tref_tokens(mode: Mode, tref: &witx::TypeRef) -> TokenStream { + match tref { + witx::TypeRef::Name(n) => TokenStream::from(TokenTree::Ident(format_ident!( "__wasi_{}_t", - ident.name.as_str() + n.name.as_str() ))), - witx::DatatypeIdent::Pointer(pointee) => { - let pointee = ident_tokens(mode, pointee); - match mode { - Mode::Host => quote!(*mut #pointee), - Mode::Wasi => panic!("pointers have target-specific size"), - Mode::Wasi32 => quote!(u32), + witx::TypeRef::Value(v) => match &**v { + witx::Type::Builtin(b) => builtin_tokens(mode, *b), + witx::Type::Pointer(pointee) => { + let pointee = tref_tokens(mode, pointee); + match mode { + Mode::Host => quote!(*mut #pointee), + Mode::Wasi => panic!("pointers have target-specific size"), + Mode::Wasi32 => quote!(u32), + } } - } - witx::DatatypeIdent::ConstPointer(pointee) => { - let pointee = ident_tokens(mode, pointee); - match mode { - Mode::Host => quote!(*const #pointee), - Mode::Wasi => panic!("pointers have target-specific size"), - Mode::Wasi32 => quote!(u32), + witx::Type::ConstPointer(pointee) => { + let pointee = tref_tokens(mode, pointee); + match mode { + Mode::Host => quote!(*const #pointee), + Mode::Wasi => panic!("pointers have target-specific size"), + Mode::Wasi32 => quote!(u32), + } } - } - witx::DatatypeIdent::Array(element) => { - let element_name = ident_tokens(mode, element); - match mode { - Mode::Host => quote!((*const #element_name, usize)), - Mode::Wasi => panic!("arrays have target-specific size"), - Mode::Wasi32 => quote!((u32, u32)), + witx::Type::Array(element) => { + let element_name = tref_tokens(mode, element); + match mode { + Mode::Host => quote!((*const #element_name, usize)), + Mode::Wasi => panic!("arrays have target-specific size"), + Mode::Wasi32 => quote!((u32, u32)), + } } - } + t => panic!("cannot give name to anonymous type {:?}", t), + }, } } /// Test whether the given struct contains any union members. -fn struct_has_union(doc: &witx::Document, s: &witx::StructDatatype) -> bool { - s.members.iter().any(|member| match &member.type_ { - witx::DatatypeIdent::Ident(ident) => match &doc.datatype(&ident.name).unwrap().variant { - witx::DatatypeVariant::Union(_) => true, - witx::DatatypeVariant::Struct(s) => struct_has_union(doc, &s), - _ => false, - }, +fn struct_has_union(s: &witx::StructDatatype) -> bool { + s.members.iter().any(|member| match &*member.tref.type_() { + witx::Type::Union { .. } => true, + witx::Type::Struct(s) => struct_has_union(&s), _ => false, }) } +fn tref_has_target_size(tref: &witx::TypeRef) -> bool { + match tref { + witx::TypeRef::Name(nt) => namedtype_has_target_size(&nt), + witx::TypeRef::Value(t) => type_has_target_size(&t), + } +} + /// Test whether the given type has a target-specific size. -fn type_has_target_size(doc: &witx::Document, type_: &witx::Datatype) -> bool { - match &type_.variant { - witx::DatatypeVariant::Alias(a) => { - a.name.as_str() == "size" || ident_has_target_size(doc, &a.to) - } - witx::DatatypeVariant::Enum(_) => false, - witx::DatatypeVariant::Flags(_) => false, - witx::DatatypeVariant::Struct(s) => s - .members - .iter() - .any(|m| ident_has_target_size(doc, &m.type_)), - witx::DatatypeVariant::Union(u) => u - .variants - .iter() - .any(|v| ident_has_target_size(doc, &v.type_)), - witx::DatatypeVariant::Handle(_) => false, +fn namedtype_has_target_size(nt: &witx::NamedType) -> bool { + if nt.name.as_str() == "size" { + true + } else { + tref_has_target_size(&nt.dt) } } /// Test whether the given type ident has a target-specific size. -fn ident_has_target_size(doc: &witx::Document, ident: &witx::DatatypeIdent) -> bool { - match ident { - witx::DatatypeIdent::Ident(ident) => { - type_has_target_size(doc, &doc.datatype(&ident.name).unwrap()) - } - witx::DatatypeIdent::Builtin(builtin) => { - if let witx::BuiltinType::String = builtin { - true - } else { - false - } - } - witx::DatatypeIdent::Pointer(_) | witx::DatatypeIdent::ConstPointer(_) => true, - witx::DatatypeIdent::Array(element) => ident_has_target_size(doc, element), +fn type_has_target_size(ty: &witx::Type) -> bool { + match ty { + witx::Type::Builtin(witx::BuiltinType::String) => true, + witx::Type::Pointer { .. } | witx::Type::ConstPointer { .. } => true, + witx::Type::Array(elem) => tref_has_target_size(elem), + witx::Type::Struct(s) => s.members.iter().any(|m| tref_has_target_size(&m.tref)), + witx::Type::Union(u) => u.variants.iter().any(|v| tref_has_target_size(&v.tref)), + _ => false, } } From 5793b14dd6b7311578f7d6b6f3e9d7642d461556 Mon Sep 17 00:00:00 2001 From: Pat Hickey Date: Thu, 5 Dec 2019 13:54:39 -0800 Subject: [PATCH 2/2] wig: update comments per code review --- crates/wasi-common/wig/src/raw_types.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/crates/wasi-common/wig/src/raw_types.rs b/crates/wasi-common/wig/src/raw_types.rs index 7168dc3c97..15de007bdb 100644 --- a/crates/wasi-common/wig/src/raw_types.rs +++ b/crates/wasi-common/wig/src/raw_types.rs @@ -225,6 +225,7 @@ fn struct_has_union(s: &witx::StructDatatype) -> bool { }) } +/// Test whether the type referred to has a target-specific size. fn tref_has_target_size(tref: &witx::TypeRef) -> bool { match tref { witx::TypeRef::Name(nt) => namedtype_has_target_size(&nt), @@ -232,7 +233,7 @@ fn tref_has_target_size(tref: &witx::TypeRef) -> bool { } } -/// Test whether the given type has a target-specific size. +/// Test whether the given named type has a target-specific size. fn namedtype_has_target_size(nt: &witx::NamedType) -> bool { if nt.name.as_str() == "size" { true @@ -241,7 +242,7 @@ fn namedtype_has_target_size(nt: &witx::NamedType) -> bool { } } -/// Test whether the given type ident has a target-specific size. +/// Test whether the given type has a target-specific size. fn type_has_target_size(ty: &witx::Type) -> bool { match ty { witx::Type::Builtin(witx::BuiltinType::String) => true,