Upgrade to witx 0.8.0 with tagged unions (#921)
* witx tagged unions: updates to wig to use new semantics * wig: emit a `#variant: ()` union variant for empty variants * wasi-common: translate to use tagged unions * update to flattened layout of event struct * wig: generate layout tests, and delete bindgen ones the bindgen tests became out-of-date with the latest changes to the representation of unions, and the re-jiggering of various struct definitions that went along with it. * wasi: point at master with tagged union PR merged * fix event struct repr on windows
This commit is contained in:
@@ -39,17 +39,41 @@ pub fn gen(args: TokenStream, mode: Mode) -> TokenStream {
|
||||
}
|
||||
|
||||
fn gen_datatypes(output: &mut TokenStream, doc: &witx::Document, mode: Mode) {
|
||||
let mut test_contents = TokenStream::new();
|
||||
for namedtype in doc.typenames() {
|
||||
if mode.include_target_types() != namedtype_has_target_size(&namedtype) {
|
||||
continue;
|
||||
}
|
||||
|
||||
gen_datatype(output, mode, &namedtype);
|
||||
gen_datatype(output, &mut test_contents, mode, &namedtype);
|
||||
}
|
||||
match mode {
|
||||
Mode::Wasi | Mode::Wasi32 => output.extend(quote! {
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
#test_contents
|
||||
}
|
||||
}),
|
||||
Mode::Host => {} // Don't emit tests for host reprs - the layout is different
|
||||
}
|
||||
}
|
||||
|
||||
fn gen_datatype(output: &mut TokenStream, mode: Mode, namedtype: &witx::NamedType) {
|
||||
fn gen_datatype(
|
||||
output: &mut TokenStream,
|
||||
test_contents: &mut TokenStream,
|
||||
mode: Mode,
|
||||
namedtype: &witx::NamedType,
|
||||
) {
|
||||
let wasi_name = format_ident!("__wasi_{}_t", namedtype.name.as_str());
|
||||
let (size, align) = {
|
||||
use witx::Layout;
|
||||
let sa = namedtype.type_().mem_size_align();
|
||||
(sa.size, sa.align)
|
||||
};
|
||||
let mut test_code = quote! {
|
||||
assert_eq!(::std::mem::size_of::<#wasi_name>(), #size, concat!("Size of: ", stringify!(#wasi_name)));
|
||||
assert_eq!(::std::mem::align_of::<#wasi_name>(), #align, concat!("Align of: ", stringify!(#wasi_name)));
|
||||
};
|
||||
match &namedtype.tref {
|
||||
witx::TypeRef::Name(alias_to) => {
|
||||
let to = tref_tokens(mode, &alias_to.tref);
|
||||
@@ -102,29 +126,59 @@ fn gen_datatype(output: &mut TokenStream, mode: Mode, namedtype: &witx::NamedTyp
|
||||
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);
|
||||
for ml in s.member_layout().iter() {
|
||||
let member_name = format_ident!("r#{}", ml.member.name.as_str());
|
||||
let member_type = tref_tokens(mode, &ml.member.tref);
|
||||
let offset = ml.offset;
|
||||
inner.extend(quote!(pub #member_name: #member_type,));
|
||||
test_code.extend(quote!{
|
||||
assert_eq!(
|
||||
unsafe { &(*(::std::ptr::null::<#wasi_name>())).#member_name as *const _ as usize },
|
||||
#offset,
|
||||
concat!(
|
||||
"Offset of field: ",
|
||||
stringify!(#wasi_name),
|
||||
"::",
|
||||
stringify!(#member_name),
|
||||
)
|
||||
);
|
||||
});
|
||||
}
|
||||
let braced = Group::new(Delimiter::Brace, inner);
|
||||
output.extend(TokenStream::from(TokenTree::Group(braced)));
|
||||
}
|
||||
witx::Type::Union(u) => {
|
||||
let u_name = format_ident!("__wasi_{}_u_t", namedtype.name.as_str());
|
||||
output.extend(quote!(#[repr(C)]));
|
||||
output.extend(quote!(#[derive(Copy, Clone)]));
|
||||
output.extend(quote!(#[allow(missing_debug_implementations)]));
|
||||
|
||||
output.extend(quote!(pub union #wasi_name));
|
||||
output.extend(quote!(pub union #u_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,));
|
||||
if let Some(ref tref) = variant.tref {
|
||||
let variant_type = tref_tokens(mode, tref);
|
||||
inner.extend(quote!(pub #variant_name: #variant_type,));
|
||||
} else {
|
||||
inner.extend(quote!(pub #variant_name: (),));
|
||||
}
|
||||
}
|
||||
let braced = Group::new(Delimiter::Brace, inner);
|
||||
output.extend(TokenStream::from(TokenTree::Group(braced)));
|
||||
|
||||
output.extend(quote!(#[repr(C)]));
|
||||
output.extend(quote!(#[derive(Copy, Clone)]));
|
||||
output.extend(quote!(#[allow(missing_debug_implementations)]));
|
||||
|
||||
output.extend(quote!(pub struct #wasi_name));
|
||||
let tag_name = format_ident!("__wasi_{}_t", u.tag.name.as_str());
|
||||
let inner = quote!(pub tag: #tag_name, pub u: #u_name,);
|
||||
output.extend(TokenStream::from(TokenTree::Group(Group::new(
|
||||
Delimiter::Brace,
|
||||
inner,
|
||||
))));
|
||||
}
|
||||
witx::Type::Handle(_h) => {
|
||||
output.extend(quote!(pub type #wasi_name = u32;));
|
||||
@@ -154,6 +208,14 @@ fn gen_datatype(output: &mut TokenStream, mode: Mode, namedtype: &witx::NamedTyp
|
||||
// Generate strerror for errno type
|
||||
gen_errno_strerror(output, namedtype);
|
||||
}
|
||||
|
||||
let test_func_name = format_ident!("wig_test_layout_{}", namedtype.name.as_str());
|
||||
test_contents.extend(quote! {
|
||||
#[test]
|
||||
fn #test_func_name() {
|
||||
#test_code
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
fn gen_errno_strerror(output: &mut TokenStream, namedtype: &witx::NamedType) {
|
||||
@@ -288,7 +350,10 @@ fn type_has_target_size(ty: &witx::Type) -> bool {
|
||||
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)),
|
||||
witx::Type::Union(u) => u
|
||||
.variants
|
||||
.iter()
|
||||
.any(|v| v.tref.as_ref().map(tref_has_target_size).unwrap_or(false)),
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user