mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-18 15:55:36 +00:00
Bug 1335652 - wasm exceptions part 7: vendor the latest wat r=rhunt
Differential Revision: https://phabricator.services.mozilla.com/D99594
This commit is contained in:
parent
d7a0965c77
commit
bd345c38b9
8
Cargo.lock
generated
8
Cargo.lock
generated
@ -5641,18 +5641,18 @@ source = "git+https://github.com/mozilla-spidermonkey/wasm-tools?rev=1b7763faa48
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wast"
|
name = "wast"
|
||||||
version = "26.0.1"
|
version = "29.0.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b3f174eed73e885ede6c8fcc3fbea8c3757afa521840676496cde56bb742ddab"
|
checksum = "dcf2268937131d63c3d833242bf5e075406f9ed868b4265f3280e15dac29ac18"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"leb128",
|
"leb128",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wat"
|
name = "wat"
|
||||||
version = "1.0.27"
|
version = "1.0.30"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "26b2dccbce4d0e14875091846e110a2369267b18ddd0d6423479b88dad914d71"
|
checksum = "0d11a88d953b298172d218d18f22853f4e6e12873b62755d05617b864d312c68"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"wast",
|
"wast",
|
||||||
]
|
]
|
||||||
|
@ -20,5 +20,5 @@ smoosh = ['jsrust_shared/smoosh']
|
|||||||
jsrust_shared = { path = "./shared" }
|
jsrust_shared = { path = "./shared" }
|
||||||
# Workaround for https://github.com/rust-lang/rust/issues/58393
|
# Workaround for https://github.com/rust-lang/rust/issues/58393
|
||||||
mozglue-static = { path = "../../../mozglue/static/rust" }
|
mozglue-static = { path = "../../../mozglue/static/rust" }
|
||||||
wat = { version = "1.0.27" }
|
wat = { version = "1.0.30" }
|
||||||
wasmparser = { version = "0.48.2" }
|
wasmparser = { version = "0.48.2" }
|
||||||
|
2
third_party/rust/wast/.cargo-checksum.json
vendored
2
third_party/rust/wast/.cargo-checksum.json
vendored
File diff suppressed because one or more lines are too long
2
third_party/rust/wast/Cargo.toml
vendored
2
third_party/rust/wast/Cargo.toml
vendored
@ -13,7 +13,7 @@
|
|||||||
[package]
|
[package]
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
name = "wast"
|
name = "wast"
|
||||||
version = "26.0.1"
|
version = "29.0.0"
|
||||||
authors = ["Alex Crichton <alex@alexcrichton.com>"]
|
authors = ["Alex Crichton <alex@alexcrichton.com>"]
|
||||||
description = "Customizable Rust parsers for the WebAssembly Text formats WAT and WAST\n"
|
description = "Customizable Rust parsers for the WebAssembly Text formats WAT and WAST\n"
|
||||||
homepage = "https://github.com/bytecodealliance/wasm-tools/tree/main/crates/wast"
|
homepage = "https://github.com/bytecodealliance/wasm-tools/tree/main/crates/wast"
|
||||||
|
58
third_party/rust/wast/src/ast/expr.rs
vendored
58
third_party/rust/wast/src/ast/expr.rs
vendored
@ -84,7 +84,9 @@ enum If<'a> {
|
|||||||
enum Try<'a> {
|
enum Try<'a> {
|
||||||
/// Next thing to parse is the `do` block.
|
/// Next thing to parse is the `do` block.
|
||||||
Do(Instruction<'a>),
|
Do(Instruction<'a>),
|
||||||
/// Next thing to parse is the `catch` block.
|
/// Next thing to parse is `catch`/`catch_all`, or `unwind`.
|
||||||
|
CatchOrUnwind,
|
||||||
|
/// Next thing to parse is a `catch` block or `catch_all`.
|
||||||
Catch,
|
Catch,
|
||||||
/// This `try` statement has finished parsing and if anything remains it's a
|
/// This `try` statement has finished parsing and if anything remains it's a
|
||||||
/// syntax error.
|
/// syntax error.
|
||||||
@ -195,8 +197,8 @@ impl<'a> ExpressionParser<'a> {
|
|||||||
Level::Try(Try::Do(_)) => {
|
Level::Try(Try::Do(_)) => {
|
||||||
return Err(parser.error("previous `try` had no `do`"));
|
return Err(parser.error("previous `try` had no `do`"));
|
||||||
}
|
}
|
||||||
Level::Try(Try::Catch) => {
|
Level::Try(Try::CatchOrUnwind) => {
|
||||||
return Err(parser.error("previous `try` had no `catch`"));
|
return Err(parser.error("previous `try` had no `catch`, `catch_all`, or `unwind`"));
|
||||||
}
|
}
|
||||||
Level::Try(_) => {
|
Level::Try(_) => {
|
||||||
self.instrs.push(Instruction::End(None));
|
self.instrs.push(Instruction::End(None));
|
||||||
@ -305,7 +307,7 @@ impl<'a> ExpressionParser<'a> {
|
|||||||
/// than an `if` as the syntactic form is:
|
/// than an `if` as the syntactic form is:
|
||||||
///
|
///
|
||||||
/// ```wat
|
/// ```wat
|
||||||
/// (try (do $do) (catch $catch))
|
/// (try (do $do) (catch $event $catch))
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// where the `do` and `catch` keywords are mandatory, even for an empty
|
/// where the `do` and `catch` keywords are mandatory, even for an empty
|
||||||
@ -328,7 +330,7 @@ impl<'a> ExpressionParser<'a> {
|
|||||||
if parser.parse::<Option<kw::r#do>>()?.is_some() {
|
if parser.parse::<Option<kw::r#do>>()?.is_some() {
|
||||||
// The state is advanced here only if the parse succeeds in
|
// The state is advanced here only if the parse succeeds in
|
||||||
// order to strictly require the keyword.
|
// order to strictly require the keyword.
|
||||||
*i = Try::Catch;
|
*i = Try::CatchOrUnwind;
|
||||||
self.stack.push(Level::TryArm);
|
self.stack.push(Level::TryArm);
|
||||||
return Ok(true);
|
return Ok(true);
|
||||||
}
|
}
|
||||||
@ -338,10 +340,26 @@ impl<'a> ExpressionParser<'a> {
|
|||||||
return Ok(false);
|
return Ok(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
// `catch` handled similar to `do`, including requiring the keyword.
|
// After a try's `do`, there are several possible kinds of handlers.
|
||||||
if let Try::Catch = i {
|
if let Try::CatchOrUnwind = i {
|
||||||
self.instrs.push(Instruction::Catch);
|
// `catch` may be followed by more `catch`s or `catch_all`.
|
||||||
if parser.parse::<Option<kw::catch>>()?.is_some() {
|
if parser.parse::<Option<kw::catch>>()?.is_some() {
|
||||||
|
let evt = parser.parse::<ast::Index<'a>>()?;
|
||||||
|
self.instrs.push(Instruction::Catch(evt));
|
||||||
|
*i = Try::Catch;
|
||||||
|
self.stack.push(Level::TryArm);
|
||||||
|
return Ok(true);
|
||||||
|
}
|
||||||
|
// `catch_all` can only come at the end and has no argument.
|
||||||
|
if parser.parse::<Option<kw::catch_all>>()?.is_some() {
|
||||||
|
self.instrs.push(Instruction::CatchAll);
|
||||||
|
*i = Try::End;
|
||||||
|
self.stack.push(Level::TryArm);
|
||||||
|
return Ok(true);
|
||||||
|
}
|
||||||
|
// `unwind` is similar to `catch_all`.
|
||||||
|
if parser.parse::<Option<kw::unwind>>()?.is_some() {
|
||||||
|
self.instrs.push(Instruction::Unwind);
|
||||||
*i = Try::End;
|
*i = Try::End;
|
||||||
self.stack.push(Level::TryArm);
|
self.stack.push(Level::TryArm);
|
||||||
return Ok(true);
|
return Ok(true);
|
||||||
@ -349,6 +367,23 @@ impl<'a> ExpressionParser<'a> {
|
|||||||
return Ok(false);
|
return Ok(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let Try::Catch = i {
|
||||||
|
if parser.parse::<Option<kw::catch>>()?.is_some() {
|
||||||
|
let evt = parser.parse::<ast::Index<'a>>()?;
|
||||||
|
self.instrs.push(Instruction::Catch(evt));
|
||||||
|
*i = Try::Catch;
|
||||||
|
self.stack.push(Level::TryArm);
|
||||||
|
return Ok(true);
|
||||||
|
}
|
||||||
|
if parser.parse::<Option<kw::catch_all>>()?.is_some() {
|
||||||
|
self.instrs.push(Instruction::CatchAll);
|
||||||
|
*i = Try::End;
|
||||||
|
self.stack.push(Level::TryArm);
|
||||||
|
return Ok(true);
|
||||||
|
}
|
||||||
|
return Err(parser.error("unexpected items after `catch`"));
|
||||||
|
}
|
||||||
|
|
||||||
Err(parser.error("too many payloads inside of `(try)`"))
|
Err(parser.error("too many payloads inside of `(try)`"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -997,11 +1032,12 @@ instructions! {
|
|||||||
V128Load64Zero(MemArg<8>) : [0xfd, 0xfd] : "v128.load64_zero",
|
V128Load64Zero(MemArg<8>) : [0xfd, 0xfd] : "v128.load64_zero",
|
||||||
|
|
||||||
// Exception handling proposal
|
// Exception handling proposal
|
||||||
|
CatchAll : [0x05] : "catch_all", // Reuses the else opcode.
|
||||||
Try(BlockType<'a>) : [0x06] : "try",
|
Try(BlockType<'a>) : [0x06] : "try",
|
||||||
Catch : [0x07] : "catch",
|
Catch(ast::Index<'a>) : [0x07] : "catch",
|
||||||
Throw(ast::Index<'a>) : [0x08] : "throw",
|
Throw(ast::Index<'a>) : [0x08] : "throw",
|
||||||
Rethrow : [0x09] : "rethrow",
|
Rethrow(ast::Index<'a>) : [0x09] : "rethrow",
|
||||||
BrOnExn(BrOnExn<'a>) : [0x0a] : "br_on_exn",
|
Unwind : [0x0a] : "unwind",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
86
third_party/rust/wast/src/ast/memory.rs
vendored
86
third_party/rust/wast/src/ast/memory.rs
vendored
@ -1,5 +1,5 @@
|
|||||||
use crate::ast::{self, kw};
|
use crate::ast::{self, kw};
|
||||||
use crate::parser::{Parse, Parser, Result};
|
use crate::parser::{Lookahead1, Parse, Parser, Peek, Result};
|
||||||
|
|
||||||
/// A defined WebAssembly memory instance inside of a module.
|
/// A defined WebAssembly memory instance inside of a module.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
@ -33,7 +33,7 @@ pub enum MemoryKind<'a> {
|
|||||||
/// Whether or not this will be creating a 32-bit memory
|
/// Whether or not this will be creating a 32-bit memory
|
||||||
is_32: bool,
|
is_32: bool,
|
||||||
/// The inline data specified for this memory
|
/// The inline data specified for this memory
|
||||||
data: Vec<&'a [u8]>,
|
data: Vec<DataVal<'a>>,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -99,7 +99,7 @@ pub struct Data<'a> {
|
|||||||
|
|
||||||
/// Bytes for this `Data` segment, viewed as the concatenation of all the
|
/// Bytes for this `Data` segment, viewed as the concatenation of all the
|
||||||
/// contained slices.
|
/// contained slices.
|
||||||
pub data: Vec<&'a [u8]>,
|
pub data: Vec<DataVal<'a>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Different kinds of data segments, either passive or active.
|
/// Different kinds of data segments, either passive or active.
|
||||||
@ -170,3 +170,83 @@ impl<'a> Parse<'a> for Data<'a> {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Differnet ways the value of a data segment can be defined.
|
||||||
|
#[derive(Debug)]
|
||||||
|
#[allow(missing_docs)]
|
||||||
|
pub enum DataVal<'a> {
|
||||||
|
String(&'a [u8]),
|
||||||
|
Integral(Vec<u8>),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DataVal<'_> {
|
||||||
|
/// Returns the length, in bytes, of the memory used to represent this data
|
||||||
|
/// value.
|
||||||
|
pub fn len(&self) -> usize {
|
||||||
|
match self {
|
||||||
|
DataVal::String(s) => s.len(),
|
||||||
|
DataVal::Integral(s) => s.len(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Pushes the value of this data value onto the provided list of bytes.
|
||||||
|
pub fn push_onto(&self, dst: &mut Vec<u8>) {
|
||||||
|
match self {
|
||||||
|
DataVal::String(s) => dst.extend_from_slice(s),
|
||||||
|
DataVal::Integral(s) => dst.extend_from_slice(s),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Parse<'a> for DataVal<'a> {
|
||||||
|
fn parse(parser: Parser<'a>) -> Result<Self> {
|
||||||
|
if !parser.peek::<ast::LParen>() {
|
||||||
|
return Ok(DataVal::String(parser.parse()?));
|
||||||
|
}
|
||||||
|
|
||||||
|
return parser.parens(|p| {
|
||||||
|
let mut result = Vec::new();
|
||||||
|
let mut lookahead = p.lookahead1();
|
||||||
|
let l = &mut lookahead;
|
||||||
|
let r = &mut result;
|
||||||
|
if consume::<kw::i8, i8, _>(p, l, r, |u, v| v.push(u as u8))?
|
||||||
|
|| consume::<kw::i16, i16, _>(p, l, r, |u, v| v.extend(&u.to_le_bytes()))?
|
||||||
|
|| consume::<kw::i32, i32, _>(p, l, r, |u, v| v.extend(&u.to_le_bytes()))?
|
||||||
|
|| consume::<kw::i64, i64, _>(p, l, r, |u, v| v.extend(&u.to_le_bytes()))?
|
||||||
|
|| consume::<kw::f32, ast::Float32, _>(p, l, r, |u, v| {
|
||||||
|
v.extend(&u.bits.to_le_bytes())
|
||||||
|
})?
|
||||||
|
|| consume::<kw::f64, ast::Float64, _>(p, l, r, |u, v| {
|
||||||
|
v.extend(&u.bits.to_le_bytes())
|
||||||
|
})?
|
||||||
|
|| consume::<kw::v128, ast::V128Const, _>(p, l, r, |u, v| {
|
||||||
|
v.extend(&u.to_le_bytes())
|
||||||
|
})?
|
||||||
|
{
|
||||||
|
Ok(DataVal::Integral(result))
|
||||||
|
} else {
|
||||||
|
Err(lookahead.error())
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
fn consume<'a, T: Peek + Parse<'a>, U: Parse<'a>, F>(
|
||||||
|
parser: Parser<'a>,
|
||||||
|
lookahead: &mut Lookahead1<'a>,
|
||||||
|
dst: &mut Vec<u8>,
|
||||||
|
push: F,
|
||||||
|
) -> Result<bool>
|
||||||
|
where
|
||||||
|
F: Fn(U, &mut Vec<u8>),
|
||||||
|
{
|
||||||
|
if !lookahead.peek::<T>() {
|
||||||
|
return Ok(false);
|
||||||
|
}
|
||||||
|
parser.parse::<T>()?;
|
||||||
|
while !parser.is_empty() {
|
||||||
|
let val = parser.parse::<U>()?;
|
||||||
|
push(val, dst);
|
||||||
|
}
|
||||||
|
Ok(true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
4
third_party/rust/wast/src/ast/mod.rs
vendored
4
third_party/rust/wast/src/ast/mod.rs
vendored
@ -35,6 +35,8 @@
|
|||||||
/// }
|
/// }
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
|
///
|
||||||
|
/// Note that the keyword name can only start with a lower-case letter, i.e. 'a'..'z'.
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! custom_keyword {
|
macro_rules! custom_keyword {
|
||||||
($name:ident) => {
|
($name:ident) => {
|
||||||
@ -344,6 +346,7 @@ pub mod kw {
|
|||||||
custom_keyword!(binary);
|
custom_keyword!(binary);
|
||||||
custom_keyword!(block);
|
custom_keyword!(block);
|
||||||
custom_keyword!(catch);
|
custom_keyword!(catch);
|
||||||
|
custom_keyword!(catch_all);
|
||||||
custom_keyword!(code);
|
custom_keyword!(code);
|
||||||
custom_keyword!(data);
|
custom_keyword!(data);
|
||||||
custom_keyword!(declare);
|
custom_keyword!(declare);
|
||||||
@ -414,6 +417,7 @@ pub mod kw {
|
|||||||
custom_keyword!(table);
|
custom_keyword!(table);
|
||||||
custom_keyword!(then);
|
custom_keyword!(then);
|
||||||
custom_keyword!(r#try = "try");
|
custom_keyword!(r#try = "try");
|
||||||
|
custom_keyword!(unwind);
|
||||||
custom_keyword!(v128);
|
custom_keyword!(v128);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
5
third_party/rust/wast/src/ast/types.rs
vendored
5
third_party/rust/wast/src/ast/types.rs
vendored
@ -389,6 +389,8 @@ pub enum MemoryType {
|
|||||||
B64 {
|
B64 {
|
||||||
/// Limits on the page sizes of this memory
|
/// Limits on the page sizes of this memory
|
||||||
limits: Limits64,
|
limits: Limits64,
|
||||||
|
/// Whether or not this is a shared (atomic) memory type
|
||||||
|
shared: bool,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -397,7 +399,8 @@ impl<'a> Parse<'a> for MemoryType {
|
|||||||
if parser.peek::<kw::i64>() {
|
if parser.peek::<kw::i64>() {
|
||||||
parser.parse::<kw::i64>()?;
|
parser.parse::<kw::i64>()?;
|
||||||
let limits = parser.parse()?;
|
let limits = parser.parse()?;
|
||||||
Ok(MemoryType::B64 { limits })
|
let shared = parser.parse::<Option<kw::shared>>()?.is_some();
|
||||||
|
Ok(MemoryType::B64 { limits, shared })
|
||||||
} else {
|
} else {
|
||||||
parser.parse::<Option<kw::i32>>()?;
|
parser.parse::<Option<kw::i32>>()?;
|
||||||
let limits = parser.parse()?;
|
let limits = parser.parse()?;
|
||||||
|
34
third_party/rust/wast/src/binary.rs
vendored
34
third_party/rust/wast/src/binary.rs
vendored
@ -61,15 +61,6 @@ fn encode_fields(
|
|||||||
|
|
||||||
e.custom_sections(BeforeFirst);
|
e.custom_sections(BeforeFirst);
|
||||||
|
|
||||||
// let moduletys = modules
|
|
||||||
// .iter()
|
|
||||||
// .map(|m| match &m.kind {
|
|
||||||
// NestedModuleKind::Inline { ty, .. } => ty.as_ref().expect("type should be filled in"),
|
|
||||||
// _ => panic!("only inline modules should be present now"),
|
|
||||||
// })
|
|
||||||
// .collect::<Vec<_>>();
|
|
||||||
// e.section_list(100, Module, &moduletys);
|
|
||||||
|
|
||||||
let mut items = fields
|
let mut items = fields
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|i| match i {
|
.filter(|i| match i {
|
||||||
@ -106,13 +97,13 @@ fn encode_fields(
|
|||||||
}
|
}
|
||||||
list!(1, Type);
|
list!(1, Type);
|
||||||
list!(2, Import);
|
list!(2, Import);
|
||||||
list!(100, NestedModule, Module, |m| match &m.kind {
|
list!(14, NestedModule, Module, |m| match &m.kind {
|
||||||
NestedModuleKind::Inline { ty, .. } =>
|
NestedModuleKind::Inline { ty, .. } =>
|
||||||
ty.as_ref().expect("type should be filled in"),
|
ty.as_ref().expect("type should be filled in"),
|
||||||
_ => panic!("only inline modules should be present now"),
|
_ => panic!("only inline modules should be present now"),
|
||||||
});
|
});
|
||||||
list!(101, Instance);
|
list!(15, Instance);
|
||||||
list!(102, Alias);
|
list!(16, Alias);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -132,7 +123,7 @@ fn encode_fields(
|
|||||||
if contains_bulk_memory(&funcs) {
|
if contains_bulk_memory(&funcs) {
|
||||||
e.section(12, &data.len());
|
e.section(12, &data.len());
|
||||||
}
|
}
|
||||||
e.section_list(103, ModuleCode, &modules);
|
e.section_list(17, ModuleCode, &modules);
|
||||||
e.section_list(10, Code, &funcs);
|
e.section_list(10, Code, &funcs);
|
||||||
e.section_list(11, Data, &data);
|
e.section_list(11, Data, &data);
|
||||||
|
|
||||||
@ -450,8 +441,8 @@ impl Encode for Import<'_> {
|
|||||||
match self.field {
|
match self.field {
|
||||||
Some(s) => s.encode(e),
|
Some(s) => s.encode(e),
|
||||||
None => {
|
None => {
|
||||||
e.push(0x01);
|
e.push(0x00);
|
||||||
e.push(0xc0);
|
e.push(0xff);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.item.encode(e);
|
self.item.encode(e);
|
||||||
@ -547,8 +538,10 @@ impl Encode for MemoryType {
|
|||||||
max.encode(e);
|
max.encode(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
MemoryType::B64 { limits } => {
|
MemoryType::B64 { limits, shared } => {
|
||||||
let flags = (limits.max.is_some() as u8) | 0x04;
|
let flag_max = limits.max.is_some() as u8;
|
||||||
|
let flag_shared = *shared as u8;
|
||||||
|
let flags = flag_max | (flag_shared << 1) | 0x04;
|
||||||
e.push(flags);
|
e.push(flags);
|
||||||
limits.min.encode(e);
|
limits.min.encode(e);
|
||||||
if let Some(max) = limits.max {
|
if let Some(max) = limits.max {
|
||||||
@ -651,6 +644,9 @@ impl Encode for Elem<'_> {
|
|||||||
fn encode(&self, e: &mut Vec<u8>) {
|
fn encode(&self, e: &mut Vec<u8>) {
|
||||||
// Try to switch element expressions to indices if we can which uses a
|
// Try to switch element expressions to indices if we can which uses a
|
||||||
// more MVP-compatible encoding.
|
// more MVP-compatible encoding.
|
||||||
|
//
|
||||||
|
// FIXME(WebAssembly/wabt#1447) ideally we wouldn't do this so we could
|
||||||
|
// be faithful to the original format.
|
||||||
let mut to_encode = self.payload.clone();
|
let mut to_encode = self.payload.clone();
|
||||||
if let ElemPayload::Exprs {
|
if let ElemPayload::Exprs {
|
||||||
ty:
|
ty:
|
||||||
@ -769,8 +765,8 @@ impl Encode for Data<'_> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.data.iter().map(|l| l.len()).sum::<usize>().encode(e);
|
self.data.iter().map(|l| l.len()).sum::<usize>().encode(e);
|
||||||
for list in self.data.iter() {
|
for val in self.data.iter() {
|
||||||
e.extend_from_slice(list);
|
val.push_onto(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -77,6 +77,7 @@ pub fn run(fields: &mut Vec<ModuleField>) {
|
|||||||
min: u64::from(pages),
|
min: u64::from(pages),
|
||||||
max: Some(u64::from(pages)),
|
max: Some(u64::from(pages)),
|
||||||
},
|
},
|
||||||
|
shared: false,
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
let data = match mem::replace(&mut m.kind, kind) {
|
let data = match mem::replace(&mut m.kind, kind) {
|
||||||
@ -90,11 +91,7 @@ pub fn run(fields: &mut Vec<ModuleField>) {
|
|||||||
kind: DataKind::Active {
|
kind: DataKind::Active {
|
||||||
memory: Index::Id(id),
|
memory: Index::Id(id),
|
||||||
offset: Expression {
|
offset: Expression {
|
||||||
instrs: Box::new([if is_32 {
|
instrs: Box::new([Instruction::I32Const(0)]),
|
||||||
Instruction::I32Const(0)
|
|
||||||
} else {
|
|
||||||
Instruction::I64Const(0)
|
|
||||||
}]),
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
data,
|
data,
|
||||||
|
118
third_party/rust/wast/src/resolve/expand.rs
vendored
118
third_party/rust/wast/src/resolve/expand.rs
vendored
@ -363,6 +363,9 @@ impl<'a> Expander<'a> {
|
|||||||
ModuleField::Alias(a) => {
|
ModuleField::Alias(a) => {
|
||||||
let (_idx, ns) = Ns::from_export(&a.kind);
|
let (_idx, ns) = Ns::from_export(&a.kind);
|
||||||
self.record_defined(&a.id, ns);
|
self.record_defined(&a.id, ns);
|
||||||
|
if let Some(instance) = &a.instance {
|
||||||
|
self.record_missing(instance, Ns::Instance);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ModuleField::NestedModule(m) => {
|
ModuleField::NestedModule(m) => {
|
||||||
@ -418,6 +421,121 @@ impl<'a> Expander<'a> {
|
|||||||
self.record_missing(&t.src, Ns::Table);
|
self.record_missing(&t.src, Ns::Table);
|
||||||
self.record_missing(&t.dst, Ns::Table);
|
self.record_missing(&t.dst, Ns::Table);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MemorySize(i) | MemoryGrow(i) | MemoryFill(i) => {
|
||||||
|
self.record_missing(&i.mem, Ns::Memory);
|
||||||
|
}
|
||||||
|
MemoryInit(i) => {
|
||||||
|
self.record_missing(&i.mem, Ns::Memory);
|
||||||
|
}
|
||||||
|
MemoryCopy(i) => {
|
||||||
|
self.record_missing(&i.src, Ns::Memory);
|
||||||
|
self.record_missing(&i.dst, Ns::Memory);
|
||||||
|
}
|
||||||
|
|
||||||
|
I32Load(m)
|
||||||
|
| I64Load(m)
|
||||||
|
| F32Load(m)
|
||||||
|
| F64Load(m)
|
||||||
|
| I32Load8s(m)
|
||||||
|
| I32Load8u(m)
|
||||||
|
| I32Load16s(m)
|
||||||
|
| I32Load16u(m)
|
||||||
|
| I64Load8s(m)
|
||||||
|
| I64Load8u(m)
|
||||||
|
| I64Load16s(m)
|
||||||
|
| I64Load16u(m)
|
||||||
|
| I64Load32s(m)
|
||||||
|
| I64Load32u(m)
|
||||||
|
| I32Store(m)
|
||||||
|
| I64Store(m)
|
||||||
|
| F32Store(m)
|
||||||
|
| F64Store(m)
|
||||||
|
| I32Store8(m)
|
||||||
|
| I32Store16(m)
|
||||||
|
| I64Store8(m)
|
||||||
|
| I64Store16(m)
|
||||||
|
| I64Store32(m)
|
||||||
|
| I32AtomicLoad(m)
|
||||||
|
| I64AtomicLoad(m)
|
||||||
|
| I32AtomicLoad8u(m)
|
||||||
|
| I32AtomicLoad16u(m)
|
||||||
|
| I64AtomicLoad8u(m)
|
||||||
|
| I64AtomicLoad16u(m)
|
||||||
|
| I64AtomicLoad32u(m)
|
||||||
|
| I32AtomicStore(m)
|
||||||
|
| I64AtomicStore(m)
|
||||||
|
| I32AtomicStore8(m)
|
||||||
|
| I32AtomicStore16(m)
|
||||||
|
| I64AtomicStore8(m)
|
||||||
|
| I64AtomicStore16(m)
|
||||||
|
| I64AtomicStore32(m)
|
||||||
|
| I32AtomicRmwAdd(m)
|
||||||
|
| I64AtomicRmwAdd(m)
|
||||||
|
| I32AtomicRmw8AddU(m)
|
||||||
|
| I32AtomicRmw16AddU(m)
|
||||||
|
| I64AtomicRmw8AddU(m)
|
||||||
|
| I64AtomicRmw16AddU(m)
|
||||||
|
| I64AtomicRmw32AddU(m)
|
||||||
|
| I32AtomicRmwSub(m)
|
||||||
|
| I64AtomicRmwSub(m)
|
||||||
|
| I32AtomicRmw8SubU(m)
|
||||||
|
| I32AtomicRmw16SubU(m)
|
||||||
|
| I64AtomicRmw8SubU(m)
|
||||||
|
| I64AtomicRmw16SubU(m)
|
||||||
|
| I64AtomicRmw32SubU(m)
|
||||||
|
| I32AtomicRmwAnd(m)
|
||||||
|
| I64AtomicRmwAnd(m)
|
||||||
|
| I32AtomicRmw8AndU(m)
|
||||||
|
| I32AtomicRmw16AndU(m)
|
||||||
|
| I64AtomicRmw8AndU(m)
|
||||||
|
| I64AtomicRmw16AndU(m)
|
||||||
|
| I64AtomicRmw32AndU(m)
|
||||||
|
| I32AtomicRmwOr(m)
|
||||||
|
| I64AtomicRmwOr(m)
|
||||||
|
| I32AtomicRmw8OrU(m)
|
||||||
|
| I32AtomicRmw16OrU(m)
|
||||||
|
| I64AtomicRmw8OrU(m)
|
||||||
|
| I64AtomicRmw16OrU(m)
|
||||||
|
| I64AtomicRmw32OrU(m)
|
||||||
|
| I32AtomicRmwXor(m)
|
||||||
|
| I64AtomicRmwXor(m)
|
||||||
|
| I32AtomicRmw8XorU(m)
|
||||||
|
| I32AtomicRmw16XorU(m)
|
||||||
|
| I64AtomicRmw8XorU(m)
|
||||||
|
| I64AtomicRmw16XorU(m)
|
||||||
|
| I64AtomicRmw32XorU(m)
|
||||||
|
| I32AtomicRmwXchg(m)
|
||||||
|
| I64AtomicRmwXchg(m)
|
||||||
|
| I32AtomicRmw8XchgU(m)
|
||||||
|
| I32AtomicRmw16XchgU(m)
|
||||||
|
| I64AtomicRmw8XchgU(m)
|
||||||
|
| I64AtomicRmw16XchgU(m)
|
||||||
|
| I64AtomicRmw32XchgU(m)
|
||||||
|
| I32AtomicRmwCmpxchg(m)
|
||||||
|
| I64AtomicRmwCmpxchg(m)
|
||||||
|
| I32AtomicRmw8CmpxchgU(m)
|
||||||
|
| I32AtomicRmw16CmpxchgU(m)
|
||||||
|
| I64AtomicRmw8CmpxchgU(m)
|
||||||
|
| I64AtomicRmw16CmpxchgU(m)
|
||||||
|
| I64AtomicRmw32CmpxchgU(m)
|
||||||
|
| V128Load(m)
|
||||||
|
| V128Load8x8S(m)
|
||||||
|
| V128Load8x8U(m)
|
||||||
|
| V128Load16x4S(m)
|
||||||
|
| V128Load16x4U(m)
|
||||||
|
| V128Load32x2S(m)
|
||||||
|
| V128Load32x2U(m)
|
||||||
|
| V128Load8Splat(m)
|
||||||
|
| V128Load16Splat(m)
|
||||||
|
| V128Load32Splat(m)
|
||||||
|
| V128Load64Splat(m)
|
||||||
|
| V128Load32Zero(m)
|
||||||
|
| V128Load64Zero(m)
|
||||||
|
| V128Store(m)
|
||||||
|
| MemoryAtomicNotify(m)
|
||||||
|
| MemoryAtomicWait32(m)
|
||||||
|
| MemoryAtomicWait64(m) => self.record_missing(&m.memory, Ns::Memory),
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
115
third_party/rust/wast/src/resolve/names.rs
vendored
115
third_party/rust/wast/src/resolve/names.rs
vendored
@ -64,6 +64,13 @@ pub struct Module<'a> {
|
|||||||
/// currently-being-processed field. This should always be empty after
|
/// currently-being-processed field. This should always be empty after
|
||||||
/// processing is complete.
|
/// processing is complete.
|
||||||
to_prepend: Vec<ModuleField<'a>>,
|
to_prepend: Vec<ModuleField<'a>>,
|
||||||
|
|
||||||
|
/// Cache for copying over types from other modules, used for module-linking
|
||||||
|
/// module types. The key of this map is the `(module_index, type_index)`
|
||||||
|
/// and the value is the copied over item into this module.
|
||||||
|
///
|
||||||
|
/// This is used by the `copy_type_from_module` method.
|
||||||
|
type_cache: HashMap<(usize, Index<'a>), Item<'a>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
enum InstanceDef<'a> {
|
enum InstanceDef<'a> {
|
||||||
@ -146,22 +153,35 @@ impl<'a> Resolver<'a> {
|
|||||||
//
|
//
|
||||||
// Practically there is no purpose to interleaving the type and module
|
// Practically there is no purpose to interleaving the type and module
|
||||||
// section today. As a result we can safely sort all types to the front.
|
// section today. As a result we can safely sort all types to the front.
|
||||||
// This, however, can break the roundtrip binary-text-binary for
|
|
||||||
// strictly-speaking compliant modules with the module linking spec.
|
|
||||||
// Anyway, this is a bummer, should figure out a better thing in the
|
|
||||||
// future.
|
|
||||||
//
|
|
||||||
// I've tried to open discussion about this at
|
// I've tried to open discussion about this at
|
||||||
// WebAssembly/module-linking#8
|
// WebAssembly/module-linking#8
|
||||||
fields.sort_by_key(|field| match field {
|
//
|
||||||
ModuleField::Type(_)
|
// Note that to avoid breaking round-tripping and as a convenience for
|
||||||
| ModuleField::Alias(Alias {
|
// writing tests, we don't reorder any fields if we don't have to fill
|
||||||
kind: ExportKind::Type(_),
|
// in the type for any modules.
|
||||||
..
|
let sort_types_first = fields.iter().any(|f| match f {
|
||||||
}) => 0,
|
ModuleField::NestedModule(m) => match &m.kind {
|
||||||
_ => 1,
|
NestedModuleKind::Inline { ty, .. } => ty.is_none(),
|
||||||
|
_ => false,
|
||||||
|
},
|
||||||
|
ModuleField::Import(i) => match &i.item.kind {
|
||||||
|
ItemKind::Module(ty) => ty.index.is_none(),
|
||||||
|
_ => false,
|
||||||
|
},
|
||||||
|
_ => false,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if sort_types_first {
|
||||||
|
fields.sort_by_key(|field| match field {
|
||||||
|
ModuleField::Type(_)
|
||||||
|
| ModuleField::Alias(Alias {
|
||||||
|
kind: ExportKind::Type(_),
|
||||||
|
..
|
||||||
|
}) => 0,
|
||||||
|
_ => 1,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// Number everything in the module, recording what names correspond to
|
// Number everything in the module, recording what names correspond to
|
||||||
// what indices.
|
// what indices.
|
||||||
let module = &mut self.modules[self.cur];
|
let module = &mut self.modules[self.cur];
|
||||||
@ -183,14 +203,16 @@ impl<'a> Resolver<'a> {
|
|||||||
// This is the same as the comment above, only we're doing it now after
|
// This is the same as the comment above, only we're doing it now after
|
||||||
// the full expansion process since all types should now be present in
|
// the full expansion process since all types should now be present in
|
||||||
// the module.
|
// the module.
|
||||||
fields.sort_by_key(|field| match field {
|
if sort_types_first {
|
||||||
ModuleField::Type(_)
|
fields.sort_by_key(|field| match field {
|
||||||
| ModuleField::Alias(Alias {
|
ModuleField::Type(_)
|
||||||
kind: ExportKind::Type(_),
|
| ModuleField::Alias(Alias {
|
||||||
..
|
kind: ExportKind::Type(_),
|
||||||
}) => 0,
|
..
|
||||||
_ => 1,
|
}) => 0,
|
||||||
});
|
_ => 1,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// And finally the last step is to replace all our `Index::Id` instances
|
// And finally the last step is to replace all our `Index::Id` instances
|
||||||
// with `Index::Num` in the AST. This does not recurse into nested
|
// with `Index::Num` in the AST. This does not recurse into nested
|
||||||
@ -694,8 +716,22 @@ impl<'a> Resolver<'a> {
|
|||||||
type_idx: &Index<'a>,
|
type_idx: &Index<'a>,
|
||||||
switch_module_to_instance: bool,
|
switch_module_to_instance: bool,
|
||||||
) -> Result<Item<'a>, Error> {
|
) -> Result<Item<'a>, Error> {
|
||||||
|
// First check the cache to avoid doing this work multiple times if
|
||||||
|
// necessary. Note that we also don't do this in the
|
||||||
|
// `switch_module_to_instance` case which happens only in rare cases
|
||||||
|
// above anyway.
|
||||||
|
//
|
||||||
|
// This prevents us from recursively realizing we don't need to copy
|
||||||
|
// over types each time we are asked to copy a type. This short-circuit
|
||||||
|
// prevents an exponential blowup of runtime for deeply nested modules.
|
||||||
|
if !switch_module_to_instance {
|
||||||
|
if let Some(ret) = self.modules[self.cur].type_cache.get(&(child, *type_idx)) {
|
||||||
|
return Ok(ret.clone());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let (ty, child) = self.type_for(child, type_idx)?;
|
let (ty, child) = self.type_for(child, type_idx)?;
|
||||||
match ty {
|
let item = match ty {
|
||||||
TypeInfo::Func(key) => {
|
TypeInfo::Func(key) => {
|
||||||
let key = key.clone();
|
let key = key.clone();
|
||||||
let my_key = (
|
let my_key = (
|
||||||
@ -708,7 +744,7 @@ impl<'a> Resolver<'a> {
|
|||||||
.map(|ty| self.copy_valtype_from_module(span, child, *ty))
|
.map(|ty| self.copy_valtype_from_module(span, child, *ty))
|
||||||
.collect::<Result<Box<[_]>, Error>>()?,
|
.collect::<Result<Box<[_]>, Error>>()?,
|
||||||
);
|
);
|
||||||
Ok(Item::Func(self.modules[self.cur].key_to_idx(span, my_key)))
|
Item::Func(self.modules[self.cur].key_to_idx(span, my_key))
|
||||||
}
|
}
|
||||||
|
|
||||||
TypeInfo::Instance { key, .. } => {
|
TypeInfo::Instance { key, .. } => {
|
||||||
@ -720,9 +756,7 @@ impl<'a> Resolver<'a> {
|
|||||||
.map(|x| (*name, x))
|
.map(|x| (*name, x))
|
||||||
})
|
})
|
||||||
.collect::<Result<Vec<_>, Error>>()?;
|
.collect::<Result<Vec<_>, Error>>()?;
|
||||||
Ok(Item::Instance(
|
Item::Instance(self.modules[self.cur].key_to_idx(span, my_key))
|
||||||
self.modules[self.cur].key_to_idx(span, my_key),
|
|
||||||
))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TypeInfo::Module { key, .. } => {
|
TypeInfo::Module { key, .. } => {
|
||||||
@ -748,16 +782,20 @@ impl<'a> Resolver<'a> {
|
|||||||
.map(|x| (*module, *field, x))
|
.map(|x| (*module, *field, x))
|
||||||
})
|
})
|
||||||
.collect::<Result<Vec<_>, Error>>()?;
|
.collect::<Result<Vec<_>, Error>>()?;
|
||||||
Ok(Item::Module(
|
Item::Module(self.modules[self.cur].key_to_idx(span, (imports, exports)))
|
||||||
self.modules[self.cur].key_to_idx(span, (imports, exports)),
|
|
||||||
))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TypeInfo::Other => Err(Error::new(
|
TypeInfo::Other => {
|
||||||
span,
|
return Err(Error::new(
|
||||||
format!("cannot copy reference types between modules right now"),
|
span,
|
||||||
)),
|
format!("cannot copy reference types between modules right now"),
|
||||||
}
|
))
|
||||||
|
}
|
||||||
|
};
|
||||||
|
self.modules[self.cur]
|
||||||
|
.type_cache
|
||||||
|
.insert((child, *type_idx), item.clone());
|
||||||
|
Ok(item)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn copy_reftype_from_module(
|
fn copy_reftype_from_module(
|
||||||
@ -1927,10 +1965,13 @@ impl<'a, 'b> ExprResolver<'a, 'b> {
|
|||||||
Throw(i) => {
|
Throw(i) => {
|
||||||
self.module.resolve(i, Ns::Event)?;
|
self.module.resolve(i, Ns::Event)?;
|
||||||
}
|
}
|
||||||
BrOnExn(b) => {
|
Rethrow(i) => {
|
||||||
self.resolve_label(&mut b.label)?;
|
self.resolve_label(i)?;
|
||||||
self.module.resolve(&mut b.exn, Ns::Event)?;
|
|
||||||
}
|
}
|
||||||
|
Catch(i) => {
|
||||||
|
self.module.resolve(i, Ns::Event)?;
|
||||||
|
}
|
||||||
|
|
||||||
BrOnCast(b) => {
|
BrOnCast(b) => {
|
||||||
self.resolve_label(&mut b.label)?;
|
self.resolve_label(&mut b.label)?;
|
||||||
self.module.resolve_heaptype(&mut b.val)?;
|
self.module.resolve_heaptype(&mut b.val)?;
|
||||||
@ -2077,6 +2118,8 @@ impl<'a, 'b> ExprResolver<'a, 'b> {
|
|||||||
| V128Load16Splat(m)
|
| V128Load16Splat(m)
|
||||||
| V128Load32Splat(m)
|
| V128Load32Splat(m)
|
||||||
| V128Load64Splat(m)
|
| V128Load64Splat(m)
|
||||||
|
| V128Load32Zero(m)
|
||||||
|
| V128Load64Zero(m)
|
||||||
| V128Store(m)
|
| V128Store(m)
|
||||||
| MemoryAtomicNotify(m)
|
| MemoryAtomicNotify(m)
|
||||||
| MemoryAtomicWait32(m)
|
| MemoryAtomicWait32(m)
|
||||||
|
2
third_party/rust/wat/.cargo-checksum.json
vendored
2
third_party/rust/wat/.cargo-checksum.json
vendored
@ -1 +1 @@
|
|||||||
{"files":{"Cargo.toml":"4b973805b8ce9c658bd9ca10e76e512496d02c689054c5953eec3d091a7c9b13","README.md":"6653a386a2210f0f7e36964f15214bc441e2c723c42867dfe90dfcedcd301814","src/lib.rs":"03652351228b7f7a520f4e7f1e689fa34a37b8e5e0fc8367a167cc893cdbc449"},"package":"26b2dccbce4d0e14875091846e110a2369267b18ddd0d6423479b88dad914d71"}
|
{"files":{"Cargo.toml":"61a583833e6205f9c9bcb28b3a7148d23861d2ce884775c14eb2ca9bd3c64c45","README.md":"6653a386a2210f0f7e36964f15214bc441e2c723c42867dfe90dfcedcd301814","src/lib.rs":"03652351228b7f7a520f4e7f1e689fa34a37b8e5e0fc8367a167cc893cdbc449"},"package":"0d11a88d953b298172d218d18f22853f4e6e12873b62755d05617b864d312c68"}
|
4
third_party/rust/wat/Cargo.toml
vendored
4
third_party/rust/wat/Cargo.toml
vendored
@ -13,7 +13,7 @@
|
|||||||
[package]
|
[package]
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
name = "wat"
|
name = "wat"
|
||||||
version = "1.0.27"
|
version = "1.0.30"
|
||||||
authors = ["Alex Crichton <alex@alexcrichton.com>"]
|
authors = ["Alex Crichton <alex@alexcrichton.com>"]
|
||||||
description = "Rust parser for the WebAssembly Text format, WAT\n"
|
description = "Rust parser for the WebAssembly Text format, WAT\n"
|
||||||
homepage = "https://github.com/bytecodealliance/wasm-tools/tree/main/crates/wat"
|
homepage = "https://github.com/bytecodealliance/wasm-tools/tree/main/crates/wat"
|
||||||
@ -22,4 +22,4 @@ readme = "README.md"
|
|||||||
license = "Apache-2.0 WITH LLVM-exception"
|
license = "Apache-2.0 WITH LLVM-exception"
|
||||||
repository = "https://github.com/bytecodealliance/wasm-tools/tree/main/crates/wat"
|
repository = "https://github.com/bytecodealliance/wasm-tools/tree/main/crates/wat"
|
||||||
[dependencies.wast]
|
[dependencies.wast]
|
||||||
version = "26.0.0"
|
version = "29.0.0"
|
||||||
|
Loading…
Reference in New Issue
Block a user