diff --git a/crates/wast/src/core/binary.rs b/crates/wast/src/core/binary.rs index 3e773aee41..d3f842f9e6 100644 --- a/crates/wast/src/core/binary.rs +++ b/crates/wast/src/core/binary.rs @@ -427,7 +427,13 @@ impl Encode for Table<'_> { fn encode(&self, e: &mut Vec) { assert!(self.exports.names.is_empty()); match &self.kind { - TableKind::Normal(t) => t.encode(e), + TableKind::Normal { ty, init_expr: None } => ty.encode(e), + TableKind::Normal { ty, init_expr: Some(init_expr) } => { + e.push(0x40); + e.push(0x00); + ty.encode(e); + init_expr.encode(e); + } _ => panic!("TableKind should be normal during encoding"), } } diff --git a/crates/wast/src/core/resolve/deinline_import_export.rs b/crates/wast/src/core/resolve/deinline_import_export.rs index db88706817..c338407182 100644 --- a/crates/wast/src/core/resolve/deinline_import_export.rs +++ b/crates/wast/src/core/resolve/deinline_import_export.rs @@ -120,13 +120,16 @@ pub fn run(fields: &mut Vec) { ElemPayload::Indices(v) => v.len(), ElemPayload::Exprs { exprs, .. } => exprs.len(), }; - let kind = TableKind::Normal(TableType { - limits: Limits { - min: len as u32, - max: Some(len as u32), + let kind = TableKind::Normal { + ty: TableType { + limits: Limits { + min: len as u32, + max: Some(len as u32), + }, + elem: *elem, }, - elem: *elem, - }); + init_expr: None, + }; let payload = match mem::replace(&mut t.kind, kind) { TableKind::Inline { payload, .. } => payload, _ => unreachable!(), @@ -146,7 +149,7 @@ pub fn run(fields: &mut Vec) { })); } - TableKind::Normal(_) => {} + TableKind::Normal { .. } => {} } } diff --git a/crates/wast/src/core/resolve/names.rs b/crates/wast/src/core/resolve/names.rs index 87428e51ef..db2b330c88 100644 --- a/crates/wast/src/core/resolve/names.rs +++ b/crates/wast/src/core/resolve/names.rs @@ -262,8 +262,11 @@ impl<'a> Resolver<'a> { } ModuleField::Table(t) => { - if let TableKind::Normal(t) = &mut t.kind { - self.resolve_heaptype(&mut t.elem.heap)?; + if let TableKind::Normal { ty, init_expr } = &mut t.kind { + self.resolve_heaptype(&mut ty.elem.heap)?; + if let Some(init_expr) = init_expr { + self.resolve_expr(init_expr)?; + } } Ok(()) } diff --git a/crates/wast/src/core/table.rs b/crates/wast/src/core/table.rs index 005bfe2046..4f16861de4 100644 --- a/crates/wast/src/core/table.rs +++ b/crates/wast/src/core/table.rs @@ -30,7 +30,12 @@ pub enum TableKind<'a> { }, /// A typical memory definition which simply says the limits of the table - Normal(TableType<'a>), + Normal { + /// Table type. + ty: TableType<'a>, + /// Optional items initializer expression. + init_expr: Option>, + }, /// The elem segments of this table, starting from 0, explicitly listed Inline { @@ -68,7 +73,14 @@ impl<'a> Parse<'a> for Table<'a> { })?; TableKind::Inline { elem, payload } } else if l.peek::() { - TableKind::Normal(parser.parse()?) + TableKind::Normal { + ty: parser.parse()?, + init_expr: if parser.peek::() { + Some(parser.parse::()?) + } else { + None + }, + } } else if let Some(import) = parser.parse()? { TableKind::Import { import, diff --git a/tests/local/function-references/table-nonnull.wast b/tests/local/function-references/table-nonnull.wast new file mode 100644 index 0000000000..2b43eeac1a --- /dev/null +++ b/tests/local/function-references/table-nonnull.wast @@ -0,0 +1,19 @@ +;; Table initializer + +(module + (type $dummy (func)) + (func $dummy) + + (table $t1 10 funcref) + (table $t2 10 funcref (ref.func $dummy)) + (table $t3 10 (ref $dummy) (ref.func $dummy)) + (table $t4 10 (ref func) (ref.func $dummy)) + + (func (export "get1") (result funcref) (table.get $t1 (i32.const 1))) + (func (export "get2") (result funcref) (table.get $t2 (i32.const 4))) + (func (export "get3") (result funcref) (table.get $t3 (i32.const 7))) +) + +(assert_return (invoke "get1") (ref.null)) +(assert_return (invoke "get2") (ref.func)) +(assert_return (invoke "get3") (ref.func))