Skip to content

Commit

Permalink
Update memory64 validation
Browse files Browse the repository at this point in the history
Handles a few points clarified in WebAssembly/memory64#7
  • Loading branch information
alexcrichton committed Aug 5, 2020
1 parent 8e1f3d3 commit e3dcee7
Show file tree
Hide file tree
Showing 6 changed files with 81 additions and 25 deletions.
20 changes: 11 additions & 9 deletions crates/wasmparser/src/operators_validator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1849,7 +1849,7 @@ impl OperatorValidator {
if segment >= resources.data_count() {
bail_op_err!("unknown data segment {}", segment);
}
self.check_operands_3(ty, ty, ty)?;
self.check_operands_3(ty, Type::I32, Type::I32)?;
self.func_state.change_frame(3)?;
}
Operator::DataDrop { segment } => {
Expand All @@ -1860,14 +1860,16 @@ impl OperatorValidator {
}
Operator::MemoryCopy { src, dst } => {
self.check_bulk_memory_enabled()?;
let ty = self.check_memory_index(src, resources)?;
if src != dst {
// FIXME(WebAssembly/memory64#6) - should this be allowed?
if ty != self.check_memory_index(dst, resources)? {
bail_op_err!("cannot copy between 32/64 bit memories");
}
}
self.check_operands_3(ty, ty, ty)?;
let src_ty = self.check_memory_index(src, resources)?;
let dst_ty = self.check_memory_index(dst, resources)?;
self.check_operands_3(
dst_ty,
src_ty,
match src_ty {
Type::I32 => Type::I32,
_ => dst_ty,
},
)?;
self.func_state.change_frame(3)?;
}
Operator::MemoryFill { mem } => {
Expand Down
2 changes: 1 addition & 1 deletion crates/wasmprinter/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1442,7 +1442,7 @@ impl Printer {
init_expr,
} => {
if *memory_index != 0 {
bail!("don't know how to print active nonzero memory data");
write!(self.result, " (memory {}) ", memory_index)?;
}
self.print_init_expr(&init_expr)?;
self.result.push_str(" ");
Expand Down
18 changes: 15 additions & 3 deletions crates/wast/src/ast/memory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,12 @@ pub enum MemoryKind<'a> {
Normal(ast::MemoryType),

/// The data of this memory, starting from 0, explicitly listed
Inline(Vec<&'a [u8]>),
Inline {
/// Whether or not this will be creating a 32-bit memory
is_32: bool,
/// The inline data specified for this memory
data: Vec<&'a [u8]>,
},
}

impl<'a> Parse<'a> for Memory<'a> {
Expand All @@ -49,7 +54,14 @@ impl<'a> Parse<'a> for Memory<'a> {
import,
ty: parser.parse()?,
}
} else if l.peek::<ast::LParen>() {
} else if l.peek::<ast::LParen>() || parser.peek2::<ast::LParen>() {
let is_32 = if parser.parse::<Option<kw::i32>>()?.is_some() {
true
} else if parser.parse::<Option<kw::i64>>()?.is_some() {
false
} else {
true
};
let data = parser.parens(|parser| {
parser.parse::<kw::data>()?;
let mut data = Vec::new();
Expand All @@ -58,7 +70,7 @@ impl<'a> Parse<'a> for Memory<'a> {
}
Ok(data)
})?;
MemoryKind::Inline(data)
MemoryKind::Inline { data, is_32 }
} else if l.peek::<u32>() || l.peek::<kw::i32>() || l.peek::<kw::i64>() {
MemoryKind::Normal(parser.parse()?)
} else {
Expand Down
33 changes: 22 additions & 11 deletions crates/wast/src/resolve/deinline_import_export.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,20 +60,27 @@ pub fn run(fields: &mut Vec<ModuleField>) {
}
// If data is defined inline insert an explicit `data` module
// field here instead, switching this to a `Normal` memory.
MemoryKind::Inline(ref data) => {
MemoryKind::Inline { is_32, ref data } => {
let len = data.iter().map(|l| l.len()).sum::<usize>() as u32;
let pages = (len + page_size() - 1) / page_size();
// FIXME(WebAssembly/memory64#5) is 32-bit always here
// right?
let kind = MemoryKind::Normal(MemoryType::B32 {
limits: Limits {
min: pages,
max: Some(pages),
},
shared: false,
let kind = MemoryKind::Normal(if is_32 {
MemoryType::B32 {
limits: Limits {
min: pages,
max: Some(pages),
},
shared: false,
}
} else {
MemoryType::B64 {
limits: Limits64 {
min: u64::from(pages),
max: Some(u64::from(pages)),
},
}
});
let data = match mem::replace(&mut m.kind, kind) {
MemoryKind::Inline(data) => data,
MemoryKind::Inline { data, .. } => data,
_ => unreachable!(),
};
let id = gensym::fill(m.span, &mut m.id);
Expand All @@ -83,7 +90,11 @@ pub fn run(fields: &mut Vec<ModuleField>) {
kind: DataKind::Active {
memory: Index::Id(id),
offset: Expression {
instrs: vec![Instruction::I32Const(0)],
instrs: vec![if is_32 {
Instruction::I32Const(0)
} else {
Instruction::I64Const(0)
}],
},
},
data,
Expand Down
26 changes: 25 additions & 1 deletion tests/local/memory64.wast
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
(func
i64.const 0 i64.const 0 i64.const 0 memory.copy
i64.const 0 i32.const 0 i64.const 0 memory.fill
i64.const 0 i64.const 0 i64.const 0 memory.init $seg
i64.const 0 i32.const 0 i32.const 0 memory.init $seg

memory.size i32.load drop
i64.const 0 memory.grow i64.load drop
Expand Down Expand Up @@ -128,3 +128,27 @@
(assert_invalid
(module (memory i64 1) (data (i32.const 0) ".."))
"type mismatch")

(module $copy_between_memories
(memory $m64 i64 1)
(memory $m32 i32 1)

(func
i32.const 0 i32.const 0 i32.const 0 memory.copy $m32 $m32
i64.const 0 i32.const 0 i32.const 0 memory.copy $m64 $m32
i32.const 0 i64.const 0 i32.const 0 memory.copy $m32 $m64
i64.const 0 i64.const 0 i64.const 0 memory.copy $m64 $m64
)
)

(module $copy_between_memories
(memory $a (data "..."))
(memory $b i32 (data "..."))
(memory $c i64 (data "..."))

(func
i32.const 0 i32.load $a drop
i32.const 0 i32.load $b drop
i64.const 0 i32.load $c drop
)
)
7 changes: 7 additions & 0 deletions tests/local/multi-memory.wast
Original file line number Diff line number Diff line change
Expand Up @@ -207,3 +207,10 @@
"(func i32.load $a)"
)
"failed to find memory")

(module
(memory 1)
(memory $m 1)
(data (memory $m) (i32.const 0) "...")
)

0 comments on commit e3dcee7

Please sign in to comment.