From b0068fca45bc933678902730c82430e6e5e0cfcf Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 21 Jan 2020 12:05:34 -0600 Subject: [PATCH] Update a number of dependencies (#152) * Update the `wasmpaser` dependency * Update the precompiled `wabt` * Update the spec-test `testsuite` And then get everything working again! --- .github/workflows/main.yml | 12 ++--- Cargo.toml | 2 +- crates/tests/tests/spec-tests | 2 +- crates/tests/tests/spec-tests.rs | 5 +++ src/error.rs | 2 +- src/ir/mod.rs | 7 ++- src/module/elements.rs | 50 +++++++++++++++------ src/module/functions/local_function/emit.rs | 13 +++++- src/module/functions/local_function/mod.rs | 10 ++++- src/module/mod.rs | 3 ++ src/module/tables.rs | 2 +- src/passes/used.rs | 4 +- src/passes/validate.rs | 6 +++ 13 files changed, 89 insertions(+), 29 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index f5650ef7..145d6b7c 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -15,8 +15,8 @@ jobs: - name: Install wabt run: | set -e - curl -L https://github.com/WebAssembly/wabt/releases/download/1.0.12/wabt-1.0.12-linux.tar.gz | tar xzf - - echo "##[add-path]`pwd`/wabt-1.0.12" + curl -L https://github.com/WebAssembly/wabt/releases/download/1.0.13/wabt-1.0.13-linux.tar.gz | tar xzf - + echo "##[add-path]`pwd`/wabt-1.0.13" - name: Install binaryen run: | set -e @@ -38,8 +38,8 @@ jobs: - name: Install wabt run: | set -e - curl -L https://github.com/WebAssembly/wabt/releases/download/1.0.12/wabt-1.0.12-linux.tar.gz | tar xzf - - echo "##[add-path]`pwd`/wabt-1.0.12" + curl -L https://github.com/WebAssembly/wabt/releases/download/1.0.13/wabt-1.0.13-linux.tar.gz | tar xzf - + echo "##[add-path]`pwd`/wabt-1.0.13" - name: Install binaryen run: | set -e @@ -65,8 +65,8 @@ jobs: - name: Install wabt run: | set -e - curl -L https://github.com/WebAssembly/wabt/releases/download/1.0.12/wabt-1.0.12-linux.tar.gz | tar xzf - - echo "##[add-path]`pwd`/wabt-1.0.12" + curl -L https://github.com/WebAssembly/wabt/releases/download/1.0.13/wabt-1.0.13-linux.tar.gz | tar xzf - + echo "##[add-path]`pwd`/wabt-1.0.13" - name: Install binaryen run: | set -e diff --git a/Cargo.toml b/Cargo.toml index 799fdb23..5c61ce52 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -29,7 +29,7 @@ leb128 = "0.2.4" log = "0.4.8" rayon = { version = "1.1.0", optional = true } walrus-macro = { path = './crates/macro', version = '=0.14.0' } -wasmparser = "0.45.0" +wasmparser = "0.48.0" [features] parallel = ['rayon', 'id-arena/rayon'] diff --git a/crates/tests/tests/spec-tests b/crates/tests/tests/spec-tests index 2a2099d5..c7225cc2 160000 --- a/crates/tests/tests/spec-tests +++ b/crates/tests/tests/spec-tests @@ -1 +1 @@ -Subproject commit 2a2099d52103215962707fbe9f44cd51fd146636 +Subproject commit c7225cc210e9a089e7ce87ecac053334eb4af0aa diff --git a/crates/tests/tests/spec-tests.rs b/crates/tests/tests/spec-tests.rs index 8ceaea22..098080a1 100644 --- a/crates/tests/tests/spec-tests.rs +++ b/crates/tests/tests/spec-tests.rs @@ -38,6 +38,11 @@ fn run(wast: &Path) -> Result<(), anyhow::Error> { // TODO: should get threads working Some("threads") => return Ok(()), + // TODO: should get simd working + Some("simd") => return Ok(()), + // TODO: should get tail-call working + Some("tail-call") => return Ok(()), + // Some("threads") => &["--enable-threads"], Some(other) => panic!("unknown wasm proposal: {}", other), }; diff --git a/src/error.rs b/src/error.rs index 97e5d33a..5ce597ae 100644 --- a/src/error.rs +++ b/src/error.rs @@ -4,7 +4,7 @@ pub use anyhow::Error; use std::fmt; /// Either `Ok(T)` or `Err(failure::Error)`. -pub type Result = ::std::result::Result; +pub use anyhow::Result; /// A leaf wasm error type. /// diff --git a/src/ir/mod.rs b/src/ir/mod.rs index 304a97ef..270aac64 100644 --- a/src/ir/mod.rs +++ b/src/ir/mod.rs @@ -320,7 +320,12 @@ pub enum Instr { }, /// `select` - Select {}, + Select { + /// Optionally listed type that the `select` instruction is expected to + /// produce, used in subtyping relations with the gc proposal. + #[walrus(skip_visit)] + ty: Option, + }, /// `unreachable` Unreachable {}, diff --git a/src/module/elements.rs b/src/module/elements.rs index 4d5d7d8e..63403654 100644 --- a/src/module/elements.rs +++ b/src/module/elements.rs @@ -76,13 +76,12 @@ impl Module { let segment = segment?; match segment.kind { - wasmparser::ElementKind::Passive { .. } => { + wasmparser::ElementKind::Passive { .. } | wasmparser::ElementKind::Declared => { bail!("passive element segments not supported yet"); } wasmparser::ElementKind::Active { table_index, init_expr, - items, } => { let table = ids.get_table(table_index)?; let table = match &mut self.tables.get_mut(table).kind { @@ -94,10 +93,17 @@ impl Module { let offset = InitExpr::eval(&init_expr, ids) .with_context(|| format!("in segment {}", i))?; - let functions = items.get_items_reader()?.into_iter().map(|func| { - let func = func?; - ids.get_func(func) - }); + let functions = + segment + .items + .get_items_reader()? + .into_iter() + .map(|e| -> Result<_> { + Ok(match e? { + wasmparser::ElementItem::Func(f) => Some(ids.get_func(f)?), + wasmparser::ElementItem::Null => None, + }) + }); match offset { InitExpr::Value(Value::I32(n)) => { @@ -106,7 +112,7 @@ impl Module { while i + offset + 1 > table.elements.len() { table.elements.push(None); } - table.elements[i + offset] = Some(id?); + table.elements[i + offset] = id?; } } InitExpr::Global(global) if self.globals.get(global).ty == ValType::I32 => { @@ -181,11 +187,12 @@ impl Emit for ModuleElements { // // Note that much of this is in accordance with the // currently-in-progress bulk-memory proposal for WebAssembly. - let active_table_header = |cx: &mut EmitContext, index: u32| { + let active_table_header = |cx: &mut EmitContext, index: u32, exprs: bool| { + let exprs_bit = if exprs { 0x4 } else { 0x0 }; if index == 0 { - cx.encoder.byte(0x00); + cx.encoder.byte(0x00 | exprs_bit); } else { - cx.encoder.byte(0x02); + cx.encoder.byte(0x02 | exprs_bit); cx.encoder.u32(index); } }; @@ -194,7 +201,7 @@ impl Emit for ModuleElements { // constant offsets for (&id, table, offset, len) in chunks { let table_index = cx.indices.get_table_index(id); - active_table_header(&mut cx, table_index); + active_table_header(&mut cx, table_index, false); InitExpr::Value(Value::I32(offset as i32)).emit(&mut cx); cx.encoder.usize(len); for item in table.elements[offset..][..len].iter() { @@ -208,12 +215,27 @@ impl Emit for ModuleElements { for (id, table) in active.iter() { let table_index = cx.indices.get_table_index(*id); for (global, list) in table.relative_elements.iter() { - active_table_header(&mut cx, table_index); + let exprs = list.iter().any(|i| i.is_none()); + active_table_header(&mut cx, table_index, exprs); InitExpr::Global(*global).emit(&mut cx); cx.encoder.usize(list.len()); for func in list { - let index = cx.indices.get_func_index(*func); - cx.encoder.u32(index); + match func { + Some(id) => { + let index = cx.indices.get_func_index(*id); + if exprs { + cx.encoder.byte(0xd2); + cx.encoder.u32(index); + cx.encoder.byte(0x0b); + } else { + cx.encoder.u32(index); + } + } + None => { + cx.encoder.byte(0xd1); + cx.encoder.byte(0x0b); + } + } } } } diff --git a/src/module/functions/local_function/emit.rs b/src/module/functions/local_function/emit.rs index d8abe46c..1ada940e 100644 --- a/src/module/functions/local_function/emit.rs +++ b/src/module/functions/local_function/emit.rs @@ -530,8 +530,17 @@ impl<'instr> Visitor<'instr> for Emit<'_, '_> { } } - Select(_) => { - self.encoder.byte(0x1b); // select + Select(e) => { + match e.ty { + Some(ty) => { + self.encoder.byte(0x1c); + self.encoder.byte(0x01); + ty.emit(self.encoder); + } + None => { + self.encoder.byte(0x1b); // select + } + } } Unreachable(_) => { diff --git a/src/module/functions/local_function/mod.rs b/src/module/functions/local_function/mod.rs index 3b645bb4..d4a5ad78 100644 --- a/src/module/functions/local_function/mod.rs +++ b/src/module/functions/local_function/mod.rs @@ -608,7 +608,15 @@ fn validate_instruction<'context>( ctx.pop_operand_expected(Some(I32))?; let t1 = ctx.pop_operand()?; let t2 = ctx.pop_operand_expected(t1)?; - ctx.alloc_instr(Select {}, loc); + ctx.alloc_instr(Select { ty: None }, loc); + ctx.push_operand(t2); + } + Operator::TypedSelect { ty } => { + let ty = ValType::parse(&ty)?; + ctx.pop_operand_expected(Some(ty))?; + let t1 = ctx.pop_operand()?; + let t2 = ctx.pop_operand_expected(t1)?; + ctx.alloc_instr(Select { ty: Some(ty) }, loc); ctx.push_operand(t2); } Operator::Return => { diff --git a/src/module/mod.rs b/src/module/mod.rs index d4d83084..2be9265b 100644 --- a/src/module/mod.rs +++ b/src/module/mod.rs @@ -168,6 +168,9 @@ impl Module { } wasmparser::SectionCode::Start => { let idx = section.get_start_section_content()?; + if ret.start.is_some() { + bail!("multiple start sections found"); + } ret.start = Some(indices.get_func(idx)?); } wasmparser::SectionCode::Function => { diff --git a/src/module/tables.rs b/src/module/tables.rs index 82fcbfc0..ac78b445 100644 --- a/src/module/tables.rs +++ b/src/module/tables.rs @@ -64,7 +64,7 @@ pub struct FunctionTable { /// Elements of this table which are relative to a global, typically /// imported. - pub relative_elements: Vec<(GlobalId, Vec)>, + pub relative_elements: Vec<(GlobalId, Vec>)>, } /// Components of a table of `anyref` diff --git a/src/passes/used.rs b/src/passes/used.rs index 6b722238..29e88d04 100644 --- a/src/passes/used.rs +++ b/src/passes/used.rs @@ -174,7 +174,9 @@ impl Used { for (global, list) in list.relative_elements.iter() { stack.push_global(*global); for id in list { - stack.push_func(*id); + if let Some(id) = *id { + stack.push_func(id); + } } } } diff --git a/src/passes/validate.rs b/src/passes/validate.rs index 15ed0dbc..879dd33b 100644 --- a/src/passes/validate.rs +++ b/src/passes/validate.rs @@ -236,4 +236,10 @@ impl<'a> Visitor<'a> for Validate<'a> { let width = if e.sixty_four { 8 } else { 4 }; self.require_atomic(e.memory, &e.arg, width); } + + fn visit_global_set(&mut self, e: &GlobalSet) { + if !self.module.globals.get(e.global).mutable { + self.err("cannot mutate immutable global"); + } + } }