Bug 1823476 - Update wast vendor dependency. r=supply-chain-reviewers

Updated wast=55.0.0.

And also wasm-smith to avoid duplicate copy of wasm-encoder.

Differential Revision: https://phabricator.services.mozilla.com/D173217
This commit is contained in:
Yury Delendik 2023-03-22 19:27:18 +00:00
Родитель 39d1882677
Коммит 4d09764c66
47 изменённых файлов: 1540 добавлений и 600 удалений

16
Cargo.lock сгенерированный
Просмотреть файл

@ -6159,18 +6159,18 @@ version = "0.2.100"
[[package]]
name = "wasm-encoder"
version = "0.23.0"
version = "0.25.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1c3e4bc09095436c8e7584d86d33e6c3ee67045af8fb262cbb9cc321de553428"
checksum = "4eff853c4f09eec94d76af527eddad4e9de13b11d6286a1ef7134bc30135a2b7"
dependencies = [
"leb128",
]
[[package]]
name = "wasm-smith"
version = "0.12.2"
version = "0.12.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "411278ee8e89067a252a3a6d6d578038251f9c0a1d4c088adf4162ad13e97b04"
checksum = "549cb78be46f43ad6746402871336cb6a989127fb847e93eb6ba0817647485a6"
dependencies = [
"arbitrary",
"flagset",
@ -6182,9 +6182,9 @@ dependencies = [
[[package]]
name = "wasmparser"
version = "0.100.0"
version = "0.102.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "64b20236ab624147dfbb62cf12a19aaf66af0e41b8398838b66e997d07d269d4"
checksum = "48134de3d7598219ab9eaf6b91b15d8e50d31da76b8519fe4ecfcec2cf35104b"
dependencies = [
"indexmap",
"url",
@ -6192,9 +6192,9 @@ dependencies = [
[[package]]
name = "wast"
version = "53.0.0"
version = "55.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8244fa24196b1d8fd3ca4a96a3a164c40f846498c5deab6caf414c67340ca4af"
checksum = "4984d3e1406571f4930ba5cf79bd70f75f41d0e87e17506e0bd19b0e5d085f05"
dependencies = [
"leb128",
"memchr",

Просмотреть файл

@ -5,6 +5,6 @@ authors = ["Christian Holler"]
license = "MPL-2.0"
[dependencies]
wasm-smith = "0.12.2"
wasm-smith = "0.12.5"
arbitrary = { version = "1.0.0", features = ["derive"] }
libc = "0.2"

Просмотреть файл

@ -19,4 +19,4 @@ gluesmith = ['jsrust_shared/gluesmith']
jsrust_shared = { path = "./shared" }
# Workaround for https://github.com/rust-lang/rust/issues/58393
mozglue-static = { path = "../../../mozglue/static/rust" }
wast = { version = "53.0.0" }
wast = { version = "55.0.0" }

Просмотреть файл

@ -197,24 +197,48 @@ criteria = "safe-to-deploy"
version = "0.23.0"
notes = "The Bytecode Alliance is the author of this crate."
[[audits.bytecode-alliance.audits.wasm-encoder]]
who = "Alex Crichton <alex@alexcrichton.com>"
criteria = "safe-to-deploy"
version = "0.25.0"
notes = "The Bytecode Alliance is the author of this crate."
[[audits.bytecode-alliance.audits.wasm-smith]]
who = "Alex Crichton <alex@alexcrichton.com>"
criteria = "safe-to-run"
version = "0.12.2"
notes = "The Bytecode Alliance is the author of this crate."
[[audits.bytecode-alliance.audits.wasm-smith]]
who = "Alex Crichton <alex@alexcrichton.com>"
criteria = "safe-to-run"
version = "0.12.5"
notes = "The Bytecode Alliance is the author of this crate."
[[audits.bytecode-alliance.audits.wasmparser]]
who = "Alex Crichton <alex@alexcrichton.com>"
criteria = "safe-to-deploy"
version = "0.100.0"
notes = "The Bytecode Alliance is the author of this crate."
[[audits.bytecode-alliance.audits.wasmparser]]
who = "Alex Crichton <alex@alexcrichton.com>"
criteria = "safe-to-deploy"
version = "0.102.0"
notes = "The Bytecode Alliance is the author of this crate."
[[audits.bytecode-alliance.audits.wast]]
who = "Alex Crichton <alex@alexcrichton.com>"
criteria = "safe-to-deploy"
version = "53.0.0"
notes = "The Bytecode Alliance is the author of this crate."
[[audits.bytecode-alliance.audits.wast]]
who = "Alex Crichton <alex@alexcrichton.com>"
criteria = "safe-to-deploy"
version = "55.0.0"
notes = "The Bytecode Alliance is the author of this crate."
[[audits.chromeos.audits.fastrand]]
who = "George Burgess IV <gbiv@google.com>"
criteria = "safe-to-deploy"

Просмотреть файл

@ -1 +1 @@
{"files":{"Cargo.toml":"fefb25e72fb204befadd0bedd4b998538a04bdbec2c28d4f70ef725a0de35a17","LICENSE":"268872b9816f90fd8e85db5a28d33f8150ebb8dd016653fb39ef1f94f2686bc5","README.md":"ac016c4843a7e1a5737255b39418732783592222dc518020730edf9dd46a1c13","src/component.rs":"c84b64b732fa84222452e13589ec187d62bee55098ca9e5b299810791b972906","src/component/aliases.rs":"be5215154b872ed5664f3bfe2aa1391f36a2575aa9d53971ab61868a1c446e9d","src/component/canonicals.rs":"8b270caef4e0f1e2b62af5b27560ac370399d11ce411aae6b811dddeaedb7750","src/component/components.rs":"07b8cae3a400e1955cc39d142569910b4fef2136021053d0ddbd6404d810aa52","src/component/exports.rs":"9a685fb44af0cfefbb2e92ddb0259955766cf6d1c0022830a865f92426ce0f7b","src/component/imports.rs":"41414a4cb71d79404e8721a985dd1d3a7df287f6417b4cab017d12e9aef31c43","src/component/instances.rs":"c86f24e466aeb6889413f32d95e039a90a1e20d2e5a0505339aa81fc086a8c24","src/component/modules.rs":"9e80907e72360fae4d8057b6b0e7a6b58edd7ba6aba6e63ba17346518e169617","src/component/names.rs":"7b651284ffdf147aabf1e01226f34ddc8bbe3d38a2dcd26ca0fc15ad24002b6f","src/component/start.rs":"4055553d5c99c99abbc01bb8abb928ecb8b909d148b647a9977fbd444bb464a3","src/component/types.rs":"885e26ce451a50ff48ab472161d8923c0195406180f36588c1d38c79181dee51","src/core.rs":"492e5ce8de8e0c0bfe55fdad62d0b8825ed88b4a01f4e1dcffae60020f27aea0","src/core/code.rs":"0dd762215e487f76d138dd6507679c24bfd747531d989baaa78d7e2382f099e4","src/core/custom.rs":"df2d6a8c5a64603822301522e9df4344022226301df846941d95930f1f4d99c4","src/core/data.rs":"c9d59eab2ab811bd950da52e6766c7df2367986c7a3a0d94d7aeb47d86f203ac","src/core/elements.rs":"361eba770b0bd6129e5b96f3081b022c5fa74640730d1d0501a33d93fea7d707","src/core/exports.rs":"f37351587cd0cfa7608f94e0fcbfa09d41c7df1d123c47825992c364d5d9ff11","src/core/functions.rs":"c18b9872ac0c21048a3ce32e5e44e8e702f97a57fa1b3a07bdd98c7f6c820f09","src/core/globals.rs":"560d8e8c818d968cd8a101ab3c639f723b1c754716aa1178d1c4570efd84d010","src/core/imports.rs":"782bbc2e70b379831f85716c0f50c0221d1487c8cba26e8845028b2ae1962c0c","src/core/linking.rs":"5c7d5bce822fad92dc096ceafde878c6d25869004ca26dde1378e78ae37071c9","src/core/memories.rs":"840d15fcd9bd4a668298491c6a91455b145c5c7ff1adf8c769aaf49d6c664d3a","src/core/names.rs":"1337a5ab769e1a1b83113041d6fc59652db34a01ef44f14a2641b3748c216dc1","src/core/producers.rs":"e96156e2b87a4e9162b918b8f9cae870c5abc9410835651d74ac54f0ff2665e7","src/core/start.rs":"a01d4a91bcd93048977ccafc6af160357297450395bf598351f5a3e6d322e0de","src/core/tables.rs":"f87a9761002e93c8e04e646cdf19fb5d012b190a4dbba542e8bfe1cfc606b545","src/core/tags.rs":"26d58904871d92f395eed67d4c25f0914b337d213bab2288011abe3ad31fa12b","src/core/types.rs":"42125c08577c418237982980fd13eb9a21e63b52674c0820c2df2e61b5f454fc","src/lib.rs":"aaec7fa68ae0764721d7b4b6d0d935ea60380c6268cbd512480fee2f7a61b755","src/raw.rs":"a6a72cfe8f88ea6476eccee4acf362030ba2d2e5710215bc4f13cde7de6d71ae"},"package":"1c3e4bc09095436c8e7584d86d33e6c3ee67045af8fb262cbb9cc321de553428"}
{"files":{"Cargo.toml":"b96ee82a5f62db5b6f57000e3f1fdab6872b1bed6d36350e9af08d90984b47af","LICENSE":"268872b9816f90fd8e85db5a28d33f8150ebb8dd016653fb39ef1f94f2686bc5","README.md":"ac016c4843a7e1a5737255b39418732783592222dc518020730edf9dd46a1c13","src/component.rs":"b07b239571c54100a258da3fb00d9155c85d3750f93cc24d408ebc17301f3e66","src/component/aliases.rs":"be5215154b872ed5664f3bfe2aa1391f36a2575aa9d53971ab61868a1c446e9d","src/component/canonicals.rs":"8b270caef4e0f1e2b62af5b27560ac370399d11ce411aae6b811dddeaedb7750","src/component/components.rs":"07b8cae3a400e1955cc39d142569910b4fef2136021053d0ddbd6404d810aa52","src/component/exports.rs":"9a685fb44af0cfefbb2e92ddb0259955766cf6d1c0022830a865f92426ce0f7b","src/component/imports.rs":"41414a4cb71d79404e8721a985dd1d3a7df287f6417b4cab017d12e9aef31c43","src/component/instances.rs":"75e0ec12a578aa22d78053add818a960373171ff10c3619ca1e8058ded277a41","src/component/modules.rs":"9e80907e72360fae4d8057b6b0e7a6b58edd7ba6aba6e63ba17346518e169617","src/component/names.rs":"7b651284ffdf147aabf1e01226f34ddc8bbe3d38a2dcd26ca0fc15ad24002b6f","src/component/start.rs":"4055553d5c99c99abbc01bb8abb928ecb8b909d148b647a9977fbd444bb464a3","src/component/types.rs":"02982d0b7962462f0b083ade9a639216cc040775a0426ad431afbf9fbedf664b","src/core.rs":"7b02ef53a430693cfadcfd83f3aa9f556062eb9b9408e661ead5364e2150cd5e","src/core/code.rs":"b340cb948d1e28e8bd369353c729674146bcc28508bbb427a8d249af4fd491fe","src/core/custom.rs":"df2d6a8c5a64603822301522e9df4344022226301df846941d95930f1f4d99c4","src/core/data.rs":"c9d59eab2ab811bd950da52e6766c7df2367986c7a3a0d94d7aeb47d86f203ac","src/core/elements.rs":"76ab78bed1956fad030821b267a115511a99c61f33f2c6e588b5a8d4ee9b4204","src/core/exports.rs":"f37351587cd0cfa7608f94e0fcbfa09d41c7df1d123c47825992c364d5d9ff11","src/core/functions.rs":"c18b9872ac0c21048a3ce32e5e44e8e702f97a57fa1b3a07bdd98c7f6c820f09","src/core/globals.rs":"560d8e8c818d968cd8a101ab3c639f723b1c754716aa1178d1c4570efd84d010","src/core/imports.rs":"782bbc2e70b379831f85716c0f50c0221d1487c8cba26e8845028b2ae1962c0c","src/core/linking.rs":"5c7d5bce822fad92dc096ceafde878c6d25869004ca26dde1378e78ae37071c9","src/core/memories.rs":"840d15fcd9bd4a668298491c6a91455b145c5c7ff1adf8c769aaf49d6c664d3a","src/core/names.rs":"1337a5ab769e1a1b83113041d6fc59652db34a01ef44f14a2641b3748c216dc1","src/core/producers.rs":"e96156e2b87a4e9162b918b8f9cae870c5abc9410835651d74ac54f0ff2665e7","src/core/start.rs":"a01d4a91bcd93048977ccafc6af160357297450395bf598351f5a3e6d322e0de","src/core/tables.rs":"d5ae8c92c8707332eda6be6e5649f2f8042a1c6242494b0174cbee5e1971cace","src/core/tags.rs":"26d58904871d92f395eed67d4c25f0914b337d213bab2288011abe3ad31fa12b","src/core/types.rs":"988175ad3a47f4aca29c7fad9d594b54c5a5717fedf7ecd6296fbb45cb058999","src/lib.rs":"aaec7fa68ae0764721d7b4b6d0d935ea60380c6268cbd512480fee2f7a61b755","src/raw.rs":"a6a72cfe8f88ea6476eccee4acf362030ba2d2e5710215bc4f13cde7de6d71ae"},"package":"4eff853c4f09eec94d76af527eddad4e9de13b11d6286a1ef7134bc30135a2b7"}

2
third_party/rust/wasm-encoder/Cargo.toml поставляемый
Просмотреть файл

@ -12,7 +12,7 @@
[package]
edition = "2021"
name = "wasm-encoder"
version = "0.23.0"
version = "0.25.0"
authors = ["Nick Fitzgerald <fitzgen@gmail.com>"]
description = """
A low-level WebAssembly encoder.

Просмотреть файл

@ -42,6 +42,12 @@ const INSTANCE_SORT: u8 = 0x05;
pub trait ComponentSection: Encode {
/// Gets the section identifier for this section.
fn id(&self) -> u8;
/// Appends this section to the specified destination list of bytes.
fn append_to_component(&self, dst: &mut Vec<u8>) {
dst.push(self.id());
self.encode(dst);
}
}
/// Known section identifiers of WebAssembly components.
@ -101,13 +107,19 @@ pub struct Component {
}
impl Component {
/// The 8-byte header at the beginning of all components.
#[rustfmt::skip]
pub const HEADER: [u8; 8] = [
// Magic
0x00, 0x61, 0x73, 0x6D,
// Version
0x0c, 0x00, 0x01, 0x00,
];
/// Begin writing a new `Component`.
pub fn new() -> Self {
Self {
bytes: vec![
0x00, 0x61, 0x73, 0x6D, // magic (`\0asm`)
0x0c, 0x00, 0x01, 0x00, // version
],
bytes: Self::HEADER.to_vec(),
}
}

Просмотреть файл

@ -59,17 +59,18 @@ impl InstanceSection {
}
/// Define an instance by instantiating a core module.
pub fn instantiate<'a, A>(&mut self, module_index: u32, args: A) -> &mut Self
pub fn instantiate<A, S>(&mut self, module_index: u32, args: A) -> &mut Self
where
A: IntoIterator<Item = (&'a str, ModuleArg)>,
A: IntoIterator<Item = (S, ModuleArg)>,
A::IntoIter: ExactSizeIterator,
S: AsRef<str>,
{
let args = args.into_iter();
self.bytes.push(0x00);
module_index.encode(&mut self.bytes);
args.len().encode(&mut self.bytes);
for (name, arg) in args {
name.encode(&mut self.bytes);
name.as_ref().encode(&mut self.bytes);
arg.encode(&mut self.bytes);
}
self.num_added += 1;
@ -77,16 +78,17 @@ impl InstanceSection {
}
/// Define an instance by exporting core WebAssembly items.
pub fn export_items<'a, E>(&mut self, exports: E) -> &mut Self
pub fn export_items<E, S>(&mut self, exports: E) -> &mut Self
where
E: IntoIterator<Item = (&'a str, ExportKind, u32)>,
E: IntoIterator<Item = (S, ExportKind, u32)>,
E::IntoIter: ExactSizeIterator,
S: AsRef<str>,
{
let exports = exports.into_iter();
self.bytes.push(0x01);
exports.len().encode(&mut self.bytes);
for (name, kind, index) in exports {
name.encode(&mut self.bytes);
name.as_ref().encode(&mut self.bytes);
kind.encode(&mut self.bytes);
index.encode(&mut self.bytes);
}
@ -146,17 +148,18 @@ impl ComponentInstanceSection {
}
/// Define an instance by instantiating a component.
pub fn instantiate<'a, A>(&mut self, component_index: u32, args: A) -> &mut Self
pub fn instantiate<A, S>(&mut self, component_index: u32, args: A) -> &mut Self
where
A: IntoIterator<Item = (&'a str, ComponentExportKind, u32)>,
A: IntoIterator<Item = (S, ComponentExportKind, u32)>,
A::IntoIter: ExactSizeIterator,
S: AsRef<str>,
{
let args = args.into_iter();
self.bytes.push(0x00);
component_index.encode(&mut self.bytes);
args.len().encode(&mut self.bytes);
for (name, kind, index) in args {
name.encode(&mut self.bytes);
name.as_ref().encode(&mut self.bytes);
kind.encode(&mut self.bytes);
index.encode(&mut self.bytes);
}

Просмотреть файл

@ -92,9 +92,9 @@ impl<'a> CoreTypeEncoder<'a> {
self.0.push(0x60);
params.len().encode(self.0);
self.0.extend(params.map(u8::from));
params.for_each(|p| p.encode(self.0));
results.len().encode(self.0);
self.0.extend(results.map(u8::from));
results.for_each(|p| p.encode(self.0));
}
/// Define a module type.

22
third_party/rust/wasm-encoder/src/core.rs поставляемый
Просмотреть файл

@ -48,6 +48,12 @@ pub(crate) const CORE_TAG_SORT: u8 = 0x04;
pub trait Section: Encode {
/// Gets the section identifier for this section.
fn id(&self) -> u8;
/// Appends this section to the specified destination list of bytes.
fn append_to(&self, dst: &mut Vec<u8>) {
dst.push(self.id());
self.encode(dst);
}
}
/// Known section identifiers of WebAssembly modules.
@ -110,16 +116,20 @@ pub struct Module {
}
impl Module {
/// The 8-byte header at the beginning of all core wasm modules.
#[rustfmt::skip]
pub const HEADER: [u8; 8] = [
// Magic
0x00, 0x61, 0x73, 0x6D,
// Version
0x01, 0x00, 0x00, 0x00,
];
/// Begin writing a new `Module`.
#[rustfmt::skip]
pub fn new() -> Self {
Module {
bytes: vec![
// Magic
0x00, 0x61, 0x73, 0x6D,
// Version
0x01, 0x00, 0x00, 0x00,
],
bytes: Self::HEADER.to_vec(),
}
}

Просмотреть файл

@ -1,4 +1,4 @@
use crate::{encode_section, Encode, Section, SectionId, ValType};
use crate::{encode_section, Encode, HeapType, Section, SectionId, ValType};
use std::borrow::Cow;
/// An encoder for the code section.
@ -318,9 +318,13 @@ pub enum Instruction<'a> {
Br(u32),
BrIf(u32),
BrTable(Cow<'a, [u32]>, u32),
BrOnNull(u32),
BrOnNonNull(u32),
Return,
Call(u32),
CallRef(HeapType),
CallIndirect { ty: u32, table: u32 },
ReturnCallRef(HeapType),
ReturnCall(u32),
ReturnCallIndirect { ty: u32, table: u32 },
Throw(u32),
@ -513,9 +517,10 @@ pub enum Instruction<'a> {
// Reference types instructions.
TypedSelect(ValType),
RefNull(ValType),
RefNull(HeapType),
RefIsNull,
RefFunc(u32),
RefAsNonNull,
// Bulk memory instructions.
TableInit { elem_index: u32, table: u32 },
@ -764,15 +769,17 @@ pub enum Instruction<'a> {
F64x2ConvertLowI32x4U,
F32x4DemoteF64x2Zero,
F64x2PromoteLowF32x4,
// Relaxed simd proposal
I8x16RelaxedSwizzle,
I32x4RelaxedTruncSatF32x4S,
I32x4RelaxedTruncSatF32x4U,
I32x4RelaxedTruncSatF64x2SZero,
I32x4RelaxedTruncSatF64x2UZero,
F32x4RelaxedFma,
F32x4RelaxedFnma,
F64x2RelaxedFma,
F64x2RelaxedFnma,
I32x4RelaxedTruncF32x4S,
I32x4RelaxedTruncF32x4U,
I32x4RelaxedTruncF64x2SZero,
I32x4RelaxedTruncF64x2UZero,
F32x4RelaxedMadd,
F32x4RelaxedNmadd,
F64x2RelaxedMadd,
F64x2RelaxedNmadd,
I8x16RelaxedLaneselect,
I16x8RelaxedLaneselect,
I32x4RelaxedLaneselect,
@ -782,9 +789,8 @@ pub enum Instruction<'a> {
F64x2RelaxedMin,
F64x2RelaxedMax,
I16x8RelaxedQ15mulrS,
I16x8DotI8x16I7x16S,
I32x4DotI8x16I7x16AddS,
F32x4RelaxedDotBf16x8AddF32x4,
I16x8RelaxedDotI8x16I7x16S,
I32x4RelaxedDotI8x16I7x16AddS,
// Atomic instructions (the threads proposal)
MemoryAtomicNotify(MemArg),
@ -905,16 +911,33 @@ impl Encode for Instruction<'_> {
ls.encode(sink);
l.encode(sink);
}
Instruction::BrOnNull(l) => {
sink.push(0xD4);
l.encode(sink);
}
Instruction::BrOnNonNull(l) => {
sink.push(0xD6);
l.encode(sink);
}
Instruction::Return => sink.push(0x0F),
Instruction::Call(f) => {
sink.push(0x10);
f.encode(sink);
}
Instruction::CallRef(ty) => {
sink.push(0x14);
ty.encode(sink);
}
Instruction::CallIndirect { ty, table } => {
sink.push(0x11);
ty.encode(sink);
table.encode(sink);
}
Instruction::ReturnCallRef(ty) => {
sink.push(0x15);
ty.encode(sink);
}
Instruction::ReturnCall(f) => {
sink.push(0x12);
f.encode(sink);
@ -1290,6 +1313,7 @@ impl Encode for Instruction<'_> {
sink.push(0xd2);
f.encode(sink);
}
Instruction::RefAsNonNull => sink.push(0xD3),
// Bulk memory instructions.
Instruction::TableInit { elem_index, table } => {
@ -2347,35 +2371,35 @@ impl Encode for Instruction<'_> {
sink.push(0xFD);
0x100u32.encode(sink);
}
Instruction::I32x4RelaxedTruncSatF32x4S => {
Instruction::I32x4RelaxedTruncF32x4S => {
sink.push(0xFD);
0x101u32.encode(sink);
}
Instruction::I32x4RelaxedTruncSatF32x4U => {
Instruction::I32x4RelaxedTruncF32x4U => {
sink.push(0xFD);
0x102u32.encode(sink);
}
Instruction::I32x4RelaxedTruncSatF64x2SZero => {
Instruction::I32x4RelaxedTruncF64x2SZero => {
sink.push(0xFD);
0x103u32.encode(sink);
}
Instruction::I32x4RelaxedTruncSatF64x2UZero => {
Instruction::I32x4RelaxedTruncF64x2UZero => {
sink.push(0xFD);
0x104u32.encode(sink);
}
Instruction::F32x4RelaxedFma => {
Instruction::F32x4RelaxedMadd => {
sink.push(0xFD);
0x105u32.encode(sink);
}
Instruction::F32x4RelaxedFnma => {
Instruction::F32x4RelaxedNmadd => {
sink.push(0xFD);
0x106u32.encode(sink);
}
Instruction::F64x2RelaxedFma => {
Instruction::F64x2RelaxedMadd => {
sink.push(0xFD);
0x107u32.encode(sink);
}
Instruction::F64x2RelaxedFnma => {
Instruction::F64x2RelaxedNmadd => {
sink.push(0xFD);
0x108u32.encode(sink);
}
@ -2415,18 +2439,14 @@ impl Encode for Instruction<'_> {
sink.push(0xFD);
0x111u32.encode(sink);
}
Instruction::I16x8DotI8x16I7x16S => {
Instruction::I16x8RelaxedDotI8x16I7x16S => {
sink.push(0xFD);
0x112u32.encode(sink);
}
Instruction::I32x4DotI8x16I7x16AddS => {
Instruction::I32x4RelaxedDotI8x16I7x16AddS => {
sink.push(0xFD);
0x113u32.encode(sink);
}
Instruction::F32x4RelaxedDotBf16x8AddF32x4 => {
sink.push(0xFD);
0x114u32.encode(sink);
}
// Atmoic instructions from the thread proposal
Instruction::MemoryAtomicNotify(memarg) => {
@ -2801,7 +2821,7 @@ impl ConstExpr {
}
/// Create a constant expression containing a single `ref.null` instruction.
pub fn ref_null(ty: ValType) -> Self {
pub fn ref_null(ty: HeapType) -> Self {
Self::new_insn(Instruction::RefNull(ty))
}

Просмотреть файл

@ -1,4 +1,4 @@
use crate::{encode_section, ConstExpr, Encode, Section, SectionId, ValType};
use crate::{encode_section, ConstExpr, Encode, RefType, Section, SectionId};
/// An encoder for the element section.
///
@ -9,12 +9,12 @@ use crate::{encode_section, ConstExpr, Encode, Section, SectionId, ValType};
/// ```
/// use wasm_encoder::{
/// Elements, ElementSection, Module, TableSection, TableType,
/// ValType, ConstExpr
/// RefType, ConstExpr
/// };
///
/// let mut tables = TableSection::new();
/// tables.table(TableType {
/// element_type: ValType::FuncRef,
/// element_type: RefType::FUNCREF,
/// minimum: 128,
/// maximum: None,
/// });
@ -22,7 +22,7 @@ use crate::{encode_section, ConstExpr, Encode, Section, SectionId, ValType};
/// let mut elements = ElementSection::new();
/// let table_index = 0;
/// let offset = ConstExpr::i32_const(42);
/// let element_type = ValType::FuncRef;
/// let element_type = RefType::FUNCREF;
/// let functions = Elements::Functions(&[
/// // Function indices...
/// ]);
@ -80,7 +80,7 @@ pub struct ElementSegment<'a> {
/// The element segment's mode.
pub mode: ElementMode<'a>,
/// The element segment's type.
pub element_type: ValType,
pub element_type: RefType,
/// This segment's elements.
pub elements: Elements<'a>,
}
@ -171,7 +171,7 @@ impl ElementSection {
&mut self,
table_index: Option<u32>,
offset: &ConstExpr,
element_type: ValType,
element_type: RefType,
elements: Elements<'_>,
) -> &mut Self {
self.segment(ElementSegment {
@ -187,7 +187,7 @@ impl ElementSection {
/// Encode a passive element segment.
///
/// Passive segments are part of the bulk memory proposal.
pub fn passive<'a>(&mut self, element_type: ValType, elements: Elements<'a>) -> &mut Self {
pub fn passive<'a>(&mut self, element_type: RefType, elements: Elements<'a>) -> &mut Self {
self.segment(ElementSegment {
mode: ElementMode::Passive,
element_type,
@ -198,7 +198,7 @@ impl ElementSection {
/// Encode a declared element segment.
///
/// Declared segments are part of the bulk memory proposal.
pub fn declared<'a>(&mut self, element_type: ValType, elements: Elements<'a>) -> &mut Self {
pub fn declared<'a>(&mut self, element_type: RefType, elements: Elements<'a>) -> &mut Self {
self.segment(ElementSegment {
mode: ElementMode::Declared,
element_type,

Просмотреть файл

@ -1,4 +1,4 @@
use crate::{encode_section, Encode, Section, SectionId, ValType};
use crate::{encode_section, ConstExpr, Encode, RefType, Section, SectionId};
/// An encoder for the table section.
///
@ -7,11 +7,11 @@ use crate::{encode_section, Encode, Section, SectionId, ValType};
/// # Example
///
/// ```
/// use wasm_encoder::{Module, TableSection, TableType, ValType};
/// use wasm_encoder::{Module, TableSection, TableType, RefType};
///
/// let mut tables = TableSection::new();
/// tables.table(TableType {
/// element_type: ValType::FuncRef,
/// element_type: RefType::FUNCREF,
/// minimum: 128,
/// maximum: None,
/// });
@ -49,6 +49,18 @@ impl TableSection {
self.num_added += 1;
self
}
/// Define a table with an explicit initialization expression.
///
/// Note that this is part of the function-references proposal.
pub fn table_with_init(&mut self, table_type: TableType, init: &ConstExpr) -> &mut Self {
self.bytes.push(0x40);
self.bytes.push(0x00);
table_type.encode(&mut self.bytes);
init.encode(&mut self.bytes);
self.num_added += 1;
self
}
}
impl Encode for TableSection {
@ -67,7 +79,7 @@ impl Section for TableSection {
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub struct TableType {
/// The table's element type.
pub element_type: ValType,
pub element_type: RefType,
/// Minimum size, in elements, of this table
pub minimum: u32,
/// Maximum size, in elements, of this table

Просмотреть файл

@ -2,41 +2,120 @@ use crate::{encode_section, Encode, Section, SectionId};
/// The type of a core WebAssembly value.
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Ord, PartialOrd)]
#[repr(u8)]
pub enum ValType {
/// The `i32` type.
I32 = 0x7F,
I32,
/// The `i64` type.
I64 = 0x7E,
I64,
/// The `f32` type.
F32 = 0x7D,
F32,
/// The `f64` type.
F64 = 0x7C,
F64,
/// The `v128` type.
///
/// Part of the SIMD proposal.
V128 = 0x7B,
/// The `funcref` type.
V128,
/// A reference type.
///
/// Part of the reference types proposal when used anywhere other than a
/// table's element type.
FuncRef = 0x70,
/// The `externref` type.
///
/// Part of the reference types proposal.
ExternRef = 0x6F,
/// The `funcref` and `externref` type fall into this category and the full
/// generalization here is due to the implementation of the
/// function-references proposal.
Ref(RefType),
}
impl From<ValType> for u8 {
#[inline]
fn from(t: ValType) -> u8 {
t as u8
}
impl ValType {
/// Alias for the `funcref` type in WebAssembly
pub const FUNCREF: ValType = ValType::Ref(RefType::FUNCREF);
/// Alias for the `externref` type in WebAssembly
pub const EXTERNREF: ValType = ValType::Ref(RefType::EXTERNREF);
}
impl Encode for ValType {
fn encode(&self, sink: &mut Vec<u8>) {
sink.push(*self as u8);
match self {
ValType::I32 => sink.push(0x7F),
ValType::I64 => sink.push(0x7E),
ValType::F32 => sink.push(0x7D),
ValType::F64 => sink.push(0x7C),
ValType::V128 => sink.push(0x7B),
ValType::Ref(rt) => rt.encode(sink),
}
}
}
/// A reference type.
///
/// This is largely part of the function references proposal for WebAssembly but
/// additionally is used by the `funcref` and `externref` types. The full
/// generality of this type is only exercised with function-references.
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Ord, PartialOrd)]
#[allow(missing_docs)]
pub struct RefType {
pub nullable: bool,
pub heap_type: HeapType,
}
impl RefType {
/// Alias for the `funcref` type in WebAssembly
pub const FUNCREF: RefType = RefType {
nullable: true,
heap_type: HeapType::Func,
};
/// Alias for the `externref` type in WebAssembly
pub const EXTERNREF: RefType = RefType {
nullable: true,
heap_type: HeapType::Extern,
};
}
impl Encode for RefType {
fn encode(&self, sink: &mut Vec<u8>) {
if self.nullable {
// Favor the original encodings of `funcref` and `externref` where
// possible
match self.heap_type {
HeapType::Func => return sink.push(0x70),
HeapType::Extern => return sink.push(0x6f),
_ => {}
}
}
if self.nullable {
sink.push(0x6C);
} else {
sink.push(0x6B);
}
self.heap_type.encode(sink);
}
}
impl From<RefType> for ValType {
fn from(ty: RefType) -> ValType {
ValType::Ref(ty)
}
}
/// Part of the function references proposal.
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Ord, PartialOrd)]
pub enum HeapType {
/// A function reference. When nullable, equivalent to `funcref`
Func,
/// An extern reference. When nullable, equivalent to `externref`
Extern,
/// A reference to a particular index in a table.
TypedFunc(u32),
}
impl Encode for HeapType {
fn encode(&self, sink: &mut Vec<u8>) {
match self {
HeapType::Func => sink.push(0x70),
HeapType::Extern => sink.push(0x6F),
// Note that this is encoded as a signed type rather than unsigned
// as it's decoded as an s33
HeapType::TypedFunc(i) => i64::from(*i).encode(sink),
}
}
}
@ -91,9 +170,9 @@ impl TypeSection {
self.bytes.push(0x60);
params.len().encode(&mut self.bytes);
self.bytes.extend(params.map(u8::from));
params.for_each(|p| p.encode(&mut self.bytes));
results.len().encode(&mut self.bytes);
self.bytes.extend(results.map(u8::from));
results.for_each(|p| p.encode(&mut self.bytes));
self.num_added += 1;
self
}

Просмотреть файл

@ -1 +1 @@
{"files":{"Cargo.toml":"b99b0bed493c2364e7dd63d34be429a7858d1066b19b59bc0fd9cb5d51d9b5f4","LICENSE":"268872b9816f90fd8e85db5a28d33f8150ebb8dd016653fb39ef1f94f2686bc5","README.md":"9202d01e78acf04e38e23e162a91c20ece8968f6172c87bfa6f18bf0b3f27d74","benches/corpus.rs":"2df29556be0799f0cb1f32c8d0ae5ba0c4b9815cf4d59a8b71744d926c0693a0","src/component.rs":"8cb11020b03ef2f5b8a78bd71694334362df1777541ba5247c430f0dd7ac1673","src/component/encode.rs":"09eddb96b5b607a87673714208c6d43b247ec4870168661d27d2c3ce92c43afd","src/config.rs":"3d33dea22d53081504e13fea4b5c99898624f26ed03013a831bae0c9759823fc","src/core.rs":"1412d51c92f998054fd87381becd433641f0261407796cec28372c1ae3c3f873","src/core/code_builder.rs":"5c36773e5c5a43ceb1dcd5243a1e64a392021ed890c6953a4c789018fff3df11","src/core/code_builder/no_traps.rs":"e004030a038916e748b716e0b08f340fc8d4451cd7057416f6299c870cc01156","src/core/encode.rs":"b8599fc907573827ff5e85108421a9c74a031fc57de502c22e021bb9986af58c","src/core/terminate.rs":"d24af5206a13aee7d6a6ea900ccdf088c09d053c36026cf1607cc38c972b3ba9","src/lib.rs":"77ed926d64d325a73613f1c307db39c65c428a1eafae114033c73a60da586fd3","tests/component.rs":"54c69ebdda583207f9f0467a600ee0ca87fbee6b365e97ec3deff7b46bd6af06","tests/core.rs":"b3f51e9c81685f1ee23a01df3f1f48876f416d33db4aeb1e6609aaba9d7bb77a"},"package":"411278ee8e89067a252a3a6d6d578038251f9c0a1d4c088adf4162ad13e97b04"}
{"files":{"Cargo.toml":"3fab85439f91b5b0dfc20abd90cabf4a9f29ab1c422ab1308851c344302d32b3","LICENSE":"268872b9816f90fd8e85db5a28d33f8150ebb8dd016653fb39ef1f94f2686bc5","README.md":"9202d01e78acf04e38e23e162a91c20ece8968f6172c87bfa6f18bf0b3f27d74","benches/corpus.rs":"2df29556be0799f0cb1f32c8d0ae5ba0c4b9815cf4d59a8b71744d926c0693a0","src/component.rs":"32f93aac210f70fbc3f870c400993f4e7ff780ca6e111453a4dc4545906887e8","src/component/encode.rs":"09eddb96b5b607a87673714208c6d43b247ec4870168661d27d2c3ce92c43afd","src/config.rs":"3d33dea22d53081504e13fea4b5c99898624f26ed03013a831bae0c9759823fc","src/core.rs":"40949add77c2b90e9f3fc0ce6862a7c83ac03d5dd9babde5abee536d6fe074e6","src/core/code_builder.rs":"60e407a758ff58aafdcf4eb4e9141aca2ab7c7fe09d6644bc6e31043f88d0d69","src/core/code_builder/no_traps.rs":"e595dbde06551f5f8b23e03cfac0634beacab08e6243c66d6ffda95079212b24","src/core/encode.rs":"b4cc82895e3c3afe26e2e62bbdd63c44e7c1f091133e49f0eaf7e7ec22400e40","src/core/terminate.rs":"d24af5206a13aee7d6a6ea900ccdf088c09d053c36026cf1607cc38c972b3ba9","src/lib.rs":"77ed926d64d325a73613f1c307db39c65c428a1eafae114033c73a60da586fd3","tests/component.rs":"54c69ebdda583207f9f0467a600ee0ca87fbee6b365e97ec3deff7b46bd6af06","tests/core.rs":"da9e27e7057a7cd9435666d4bd4d57cec03b0d5d74bad289373db7beb8a2e1a6"},"package":"549cb78be46f43ad6746402871336cb6a989127fb847e93eb6ba0817647485a6"}

6
third_party/rust/wasm-smith/Cargo.toml поставляемый
Просмотреть файл

@ -12,7 +12,7 @@
[package]
edition = "2021"
name = "wasm-smith"
version = "0.12.2"
version = "0.12.5"
authors = ["Nick Fitzgerald <fitzgen@gmail.com>"]
exclude = ["/benches/corpus"]
description = "A WebAssembly test case generator"
@ -50,10 +50,10 @@ features = ["derive"]
optional = true
[dependencies.wasm-encoder]
version = "0.23.0"
version = "0.25.0"
[dependencies.wasmparser]
version = "0.100.0"
version = "0.102.0"
[dev-dependencies.criterion]
version = "0.3.3"

Просмотреть файл

@ -1868,7 +1868,7 @@ fn inverse_scalar_canonical_abi_for(
.cloned(),
ValType::F32 => Ok(ComponentValType::Primitive(PrimitiveValType::Float32)),
ValType::F64 => Ok(ComponentValType::Primitive(PrimitiveValType::Float64)),
ValType::V128 | ValType::FuncRef | ValType::ExternRef => {
ValType::V128 | ValType::Ref(_) => {
unreachable!("not used in canonical ABI")
}
};

49
third_party/rust/wasm-smith/src/core.rs поставляемый
Просмотреть файл

@ -14,7 +14,7 @@ use std::marker;
use std::ops::Range;
use std::rc::Rc;
use std::str::{self, FromStr};
use wasm_encoder::{BlockType, ConstExpr, ExportKind, ValType};
use wasm_encoder::{BlockType, ConstExpr, ExportKind, HeapType, RefType, ValType};
pub(crate) use wasm_encoder::{GlobalType, MemoryType, TableType};
// NB: these constants are used to control the rate at which various events
@ -285,7 +285,7 @@ pub(crate) struct TagType {
#[derive(Debug)]
struct ElementSegment {
kind: ElementKind,
ty: ValType,
ty: RefType,
items: Elements,
}
@ -655,7 +655,7 @@ impl Module {
wasmparser::TypeRef::Table(table_ty) => {
let table_ty = TableType {
element_type: convert_type(table_ty.element_type),
element_type: convert_reftype(table_ty.element_type),
minimum: table_ty.initial,
maximum: table_ty.maximum,
};
@ -879,14 +879,13 @@ impl Module {
ValType::F32 => ConstExpr::f32_const(u.arbitrary()?),
ValType::F64 => ConstExpr::f64_const(u.arbitrary()?),
ValType::V128 => ConstExpr::v128_const(u.arbitrary()?),
ValType::ExternRef => ConstExpr::ref_null(ValType::ExternRef),
ValType::FuncRef => {
if num_funcs > 0 && u.arbitrary()? {
ValType::Ref(ty) => {
assert!(ty.nullable);
if ty.heap_type == HeapType::Func && num_funcs > 0 && u.arbitrary()? {
let func = u.int_in_range(0..=num_funcs - 1)?;
return Ok(GlobalInitExpr::FuncRef(func));
} else {
ConstExpr::ref_null(ValType::FuncRef)
}
ConstExpr::ref_null(ty.heap_type)
}
}))
}));
@ -1073,7 +1072,7 @@ impl Module {
continue;
}
let dst = if ty.element_type == ValType::FuncRef {
let dst = if ty.element_type == RefType::FUNCREF {
&mut funcrefs
} else {
&mut externrefs
@ -1081,7 +1080,7 @@ impl Module {
let minimum = ty.minimum;
// If the first table is a funcref table then it's a candidate for
// the MVP encoding of element segments.
if i == 0 && ty.element_type == ValType::FuncRef {
if i == 0 && ty.element_type == RefType::FUNCREF {
dst.push(Box::new(move |u| {
arbitrary_active_elem(u, minimum, None, disallow_traps, ty)
}));
@ -1105,10 +1104,10 @@ impl Module {
let mut choices = Vec::new();
if !funcrefs.is_empty() {
choices.push((&funcrefs, ValType::FuncRef));
choices.push((&funcrefs, RefType::FUNCREF));
}
if !externrefs.is_empty() {
choices.push((&externrefs, ValType::ExternRef));
choices.push((&externrefs, RefType::EXTERNREF));
}
if choices.is_empty() {
@ -1133,13 +1132,13 @@ impl Module {
// Pick whether we're going to use expression elements or
// indices. Note that externrefs must use expressions,
// and functions without reference types must use indices.
let items = if ty == ValType::ExternRef
let items = if ty == RefType::EXTERNREF
|| (self.config.reference_types_enabled() && u.arbitrary()?)
{
let mut init = vec![];
arbitrary_loop(u, self.config.min_elements(), max, |u| {
init.push(
if ty == ValType::ExternRef || func_max == 0 || u.arbitrary()? {
if ty == RefType::EXTERNREF || func_max == 0 || u.arbitrary()? {
None
} else {
Some(u.int_in_range(0..=func_max - 1)?)
@ -1381,8 +1380,8 @@ pub(crate) fn configured_valtypes(config: &dyn Config) -> Vec<ValType> {
valtypes.push(ValType::V128);
}
if config.reference_types_enabled() {
valtypes.push(ValType::ExternRef);
valtypes.push(ValType::FuncRef);
valtypes.push(ValType::EXTERNREF);
valtypes.push(ValType::FUNCREF);
}
valtypes
}
@ -1431,9 +1430,9 @@ pub(crate) fn arbitrary_table_type(u: &mut Unstructured, config: &dyn Config) ->
}
Ok(TableType {
element_type: if config.reference_types_enabled() {
*u.choose(&[ValType::FuncRef, ValType::ExternRef])?
*u.choose(&[RefType::FUNCREF, RefType::EXTERNREF])?
} else {
ValType::FuncRef
RefType::FUNCREF
},
minimum,
maximum,
@ -1634,8 +1633,18 @@ fn convert_type(parsed_type: wasmparser::ValType) -> ValType {
F32 => ValType::F32,
F64 => ValType::F64,
V128 => ValType::V128,
FuncRef => ValType::FuncRef,
ExternRef => ValType::ExternRef,
Ref(ty) => ValType::Ref(convert_reftype(ty)),
}
}
fn convert_reftype(ty: wasmparser::RefType) -> RefType {
wasm_encoder::RefType {
nullable: ty.nullable,
heap_type: match ty.heap_type {
wasmparser::HeapType::Func => wasm_encoder::HeapType::Func,
wasmparser::HeapType::Extern => wasm_encoder::HeapType::Extern,
wasmparser::HeapType::TypedFunc(i) => wasm_encoder::HeapType::TypedFunc(i.into()),
},
}
}

Просмотреть файл

@ -6,7 +6,7 @@ use arbitrary::{Result, Unstructured};
use std::collections::{BTreeMap, BTreeSet};
use std::convert::TryFrom;
use std::rc::Rc;
use wasm_encoder::{BlockType, MemArg};
use wasm_encoder::{BlockType, MemArg, RefType};
mod no_traps;
macro_rules! instructions {
@ -350,10 +350,10 @@ instructions! {
(Some(simd_v128_v128_on_stack), i8x16_swizzle, Vector),
(Some(simd_v128_v128_on_stack_relaxed), i8x16_relaxed_swizzle, Vector),
(Some(simd_v128_v128_v128_on_stack), v128_bitselect, Vector),
(Some(simd_v128_v128_v128_on_stack_relaxed), i8x16_laneselect, Vector),
(Some(simd_v128_v128_v128_on_stack_relaxed), i16x8_laneselect, Vector),
(Some(simd_v128_v128_v128_on_stack_relaxed), i32x4_laneselect, Vector),
(Some(simd_v128_v128_v128_on_stack_relaxed), i64x2_laneselect, Vector),
(Some(simd_v128_v128_v128_on_stack_relaxed), i8x16_relaxed_laneselect, Vector),
(Some(simd_v128_v128_v128_on_stack_relaxed), i16x8_relaxed_laneselect, Vector),
(Some(simd_v128_v128_v128_on_stack_relaxed), i32x4_relaxed_laneselect, Vector),
(Some(simd_v128_v128_v128_on_stack_relaxed), i64x2_relaxed_laneselect, Vector),
(Some(simd_v128_v128_on_stack), i8x16_eq, Vector),
(Some(simd_v128_v128_on_stack), i8x16_ne, Vector),
(Some(simd_v128_v128_on_stack), i8x16_lt_s, Vector),
@ -544,22 +544,21 @@ instructions! {
(Some(simd_v128_on_stack), f64x2_convert_low_i32x4u, Vector),
(Some(simd_v128_on_stack), f32x4_demote_f64x2_zero, Vector),
(Some(simd_v128_on_stack), f64x2_promote_low_f32x4, Vector),
(Some(simd_v128_on_stack_relaxed), i32x4_relaxed_trunc_sat_f32x4s, Vector),
(Some(simd_v128_on_stack_relaxed), i32x4_relaxed_trunc_sat_f32x4u, Vector),
(Some(simd_v128_on_stack_relaxed), i32x4_relaxed_trunc_sat_f64x2s_zero, Vector),
(Some(simd_v128_on_stack_relaxed), i32x4_relaxed_trunc_sat_f64x2u_zero, Vector),
(Some(simd_v128_v128_v128_on_stack_relaxed), f32x4_fma, Vector),
(Some(simd_v128_v128_v128_on_stack_relaxed), f32x4_fnma, Vector),
(Some(simd_v128_v128_v128_on_stack_relaxed), f64x2_fma, Vector),
(Some(simd_v128_v128_v128_on_stack_relaxed), f64x2_fnma, Vector),
(Some(simd_v128_on_stack_relaxed), i32x4_relaxed_trunc_f32x4s, Vector),
(Some(simd_v128_on_stack_relaxed), i32x4_relaxed_trunc_f32x4u, Vector),
(Some(simd_v128_on_stack_relaxed), i32x4_relaxed_trunc_f64x2s_zero, Vector),
(Some(simd_v128_on_stack_relaxed), i32x4_relaxed_trunc_f64x2u_zero, Vector),
(Some(simd_v128_v128_v128_on_stack_relaxed), f32x4_relaxed_madd, Vector),
(Some(simd_v128_v128_v128_on_stack_relaxed), f32x4_relaxed_nmadd, Vector),
(Some(simd_v128_v128_v128_on_stack_relaxed), f64x2_relaxed_madd, Vector),
(Some(simd_v128_v128_v128_on_stack_relaxed), f64x2_relaxed_nmadd, Vector),
(Some(simd_v128_v128_on_stack_relaxed), f32x4_relaxed_min, Vector),
(Some(simd_v128_v128_on_stack_relaxed), f32x4_relaxed_max, Vector),
(Some(simd_v128_v128_on_stack_relaxed), f64x2_relaxed_min, Vector),
(Some(simd_v128_v128_on_stack_relaxed), f64x2_relaxed_max, Vector),
(Some(simd_v128_v128_on_stack_relaxed), i16x8_relaxed_q15mulr_s, Vector),
(Some(simd_v128_v128_on_stack_relaxed), i16x8_dot_i8x16_i7x16_s, Vector),
(Some(simd_v128_v128_v128_on_stack_relaxed), i32x4_dot_i8x16_i7x16_add_s, Vector),
(Some(simd_v128_v128_v128_on_stack_relaxed), f32x4_relaxed_dot_bf16x8_add_f32x4, Vector),
(Some(simd_v128_v128_on_stack_relaxed), i16x8_relaxed_dot_i8x16_i7x16_s, Vector),
(Some(simd_v128_v128_v128_on_stack_relaxed), i32x4_relaxed_dot_i8x16_i7x16_add_s, Vector),
}
pub(crate) struct CodeBuilderAllocations {
@ -694,7 +693,7 @@ impl CodeBuilderAllocations {
let mut table_tys = Vec::new();
for (i, table) in module.tables.iter().enumerate() {
table_tys.push(table.element_type);
if table.element_type == ValType::FuncRef {
if table.element_type == RefType::FUNCREF {
funcref_tables.push(i as u32);
}
}
@ -1107,8 +1106,10 @@ fn arbitrary_val(ty: ValType, u: &mut Unstructured<'_>) -> Instruction {
ValType::F32 => Instruction::F32Const(u.arbitrary().unwrap_or(0.0)),
ValType::F64 => Instruction::F64Const(u.arbitrary().unwrap_or(0.0)),
ValType::V128 => Instruction::V128Const(u.arbitrary().unwrap_or(0)),
ValType::ExternRef => Instruction::RefNull(ValType::ExternRef),
ValType::FuncRef => Instruction::RefNull(ValType::FuncRef),
ValType::Ref(ty) => {
assert!(ty.nullable);
Instruction::RefNull(ty.heap_type)
}
}
}
@ -1789,9 +1790,7 @@ fn select(
let ty = t.or(u);
builder.allocs.operands.push(ty);
match ty {
Some(ty @ ValType::ExternRef) | Some(ty @ ValType::FuncRef) => {
instructions.push(Instruction::TypedSelect(ty))
}
Some(ty @ ValType::Ref(_)) => instructions.push(Instruction::TypedSelect(ty)),
Some(ValType::I32) | Some(ValType::I64) | Some(ValType::F32) | Some(ValType::F64)
| Some(ValType::V128) | None => instructions.push(Instruction::Select),
}
@ -4510,9 +4509,9 @@ fn ref_null(
builder: &mut CodeBuilder,
instructions: &mut Vec<Instruction>,
) -> Result<()> {
let ty = *u.choose(&[ValType::ExternRef, ValType::FuncRef])?;
builder.push_operands(&[ty]);
instructions.push(Instruction::RefNull(ty));
let ty = *u.choose(&[RefType::EXTERNREF, RefType::FUNCREF])?;
builder.push_operands(&[ty.into()]);
instructions.push(Instruction::RefNull(ty.heap_type));
Ok(())
}
@ -4528,7 +4527,7 @@ fn ref_func(
instructions: &mut Vec<Instruction>,
) -> Result<()> {
let i = *u.choose(&builder.allocs.referenced_functions)?;
builder.push_operands(&[ValType::FuncRef]);
builder.push_operands(&[ValType::FUNCREF]);
instructions.push(Instruction::RefFunc(i));
Ok(())
}
@ -4536,7 +4535,7 @@ fn ref_func(
#[inline]
fn ref_is_null_valid(module: &Module, builder: &mut CodeBuilder) -> bool {
module.config.reference_types_enabled()
&& (builder.type_on_stack(ValType::ExternRef) || builder.type_on_stack(ValType::FuncRef))
&& (builder.type_on_stack(ValType::EXTERNREF) || builder.type_on_stack(ValType::FUNCREF))
}
fn ref_is_null(
@ -4556,9 +4555,9 @@ fn table_fill_valid(module: &Module, builder: &mut CodeBuilder) -> bool {
module.config.reference_types_enabled()
&& module.config.bulk_memory_enabled()
&& !module.config.disallow_traps() // Non-trapping table fill generation not yet implemented
&& [ValType::ExternRef, ValType::FuncRef].iter().any(|ty| {
&& [ValType::EXTERNREF, ValType::FUNCREF].iter().any(|ty| {
builder.types_on_stack(&[ValType::I32, *ty, ValType::I32])
&& module.tables.iter().any(|t| t.element_type == *ty)
&& module.tables.iter().any(|t| *ty == t.element_type.into())
})
}
@ -4580,9 +4579,9 @@ fn table_fill(
fn table_set_valid(module: &Module, builder: &mut CodeBuilder) -> bool {
module.config.reference_types_enabled()
&& !module.config.disallow_traps() // Non-trapping table.set generation not yet implemented
&& [ValType::ExternRef, ValType::FuncRef].iter().any(|ty| {
&& [ValType::EXTERNREF, ValType::FUNCREF].iter().any(|ty| {
builder.types_on_stack(&[ValType::I32, *ty])
&& module.tables.iter().any(|t| t.element_type == *ty)
&& module.tables.iter().any(|t| *ty == t.element_type.into())
})
}
@ -4616,7 +4615,7 @@ fn table_get(
builder.pop_operands(&[ValType::I32]);
let idx = u.int_in_range(0..=module.tables.len() - 1)?;
let ty = module.tables[idx].element_type;
builder.push_operands(&[ty]);
builder.push_operands(&[ty.into()]);
instructions.push(Instruction::TableGet(idx as u32));
Ok(())
}
@ -4641,9 +4640,9 @@ fn table_size(
#[inline]
fn table_grow_valid(module: &Module, builder: &mut CodeBuilder) -> bool {
module.config.reference_types_enabled()
&& [ValType::ExternRef, ValType::FuncRef].iter().any(|ty| {
&& [ValType::EXTERNREF, ValType::FUNCREF].iter().any(|ty| {
builder.types_on_stack(&[*ty, ValType::I32])
&& module.tables.iter().any(|t| t.element_type == *ty)
&& module.tables.iter().any(|t| *ty == t.element_type.into())
})
}
@ -4732,17 +4731,17 @@ fn elem_drop(
Ok(())
}
fn pop_reference_type(builder: &mut CodeBuilder) -> ValType {
if builder.type_on_stack(ValType::ExternRef) {
builder.pop_operands(&[ValType::ExternRef]);
ValType::ExternRef
fn pop_reference_type(builder: &mut CodeBuilder) -> RefType {
if builder.type_on_stack(ValType::EXTERNREF) {
builder.pop_operands(&[ValType::EXTERNREF]);
RefType::EXTERNREF
} else {
builder.pop_operands(&[ValType::FuncRef]);
ValType::FuncRef
builder.pop_operands(&[ValType::FUNCREF]);
RefType::FUNCREF
}
}
fn table_index(ty: ValType, u: &mut Unstructured, module: &Module) -> Result<u32> {
fn table_index(ty: RefType, u: &mut Unstructured, module: &Module) -> Result<u32> {
let tables = module
.tables
.iter()
@ -5332,32 +5331,25 @@ simd_unop!(F32x4DemoteF64x2Zero, f32x4_demote_f64x2_zero);
simd_unop!(F64x2PromoteLowF32x4, f64x2_promote_low_f32x4);
simd_ternop!(V128Bitselect, v128_bitselect);
simd_binop!(I8x16RelaxedSwizzle, i8x16_relaxed_swizzle);
simd_unop!(I32x4RelaxedTruncSatF32x4S, i32x4_relaxed_trunc_sat_f32x4s);
simd_unop!(I32x4RelaxedTruncSatF32x4U, i32x4_relaxed_trunc_sat_f32x4u);
simd_unop!(
I32x4RelaxedTruncSatF64x2SZero,
i32x4_relaxed_trunc_sat_f64x2s_zero
);
simd_unop!(
I32x4RelaxedTruncSatF64x2UZero,
i32x4_relaxed_trunc_sat_f64x2u_zero
);
simd_ternop!(F32x4RelaxedFma, f32x4_fma);
simd_ternop!(F32x4RelaxedFnma, f32x4_fnma);
simd_ternop!(F64x2RelaxedFma, f64x2_fma);
simd_ternop!(F64x2RelaxedFnma, f64x2_fnma);
simd_ternop!(I8x16RelaxedLaneselect, i8x16_laneselect);
simd_ternop!(I16x8RelaxedLaneselect, i16x8_laneselect);
simd_ternop!(I32x4RelaxedLaneselect, i32x4_laneselect);
simd_ternop!(I64x2RelaxedLaneselect, i64x2_laneselect);
simd_unop!(I32x4RelaxedTruncF32x4S, i32x4_relaxed_trunc_f32x4s);
simd_unop!(I32x4RelaxedTruncF32x4U, i32x4_relaxed_trunc_f32x4u);
simd_unop!(I32x4RelaxedTruncF64x2SZero, i32x4_relaxed_trunc_f64x2s_zero);
simd_unop!(I32x4RelaxedTruncF64x2UZero, i32x4_relaxed_trunc_f64x2u_zero);
simd_ternop!(F32x4RelaxedMadd, f32x4_relaxed_madd);
simd_ternop!(F32x4RelaxedNmadd, f32x4_relaxed_nmadd);
simd_ternop!(F64x2RelaxedMadd, f64x2_relaxed_madd);
simd_ternop!(F64x2RelaxedNmadd, f64x2_relaxed_nmadd);
simd_ternop!(I8x16RelaxedLaneselect, i8x16_relaxed_laneselect);
simd_ternop!(I16x8RelaxedLaneselect, i16x8_relaxed_laneselect);
simd_ternop!(I32x4RelaxedLaneselect, i32x4_relaxed_laneselect);
simd_ternop!(I64x2RelaxedLaneselect, i64x2_relaxed_laneselect);
simd_binop!(F32x4RelaxedMin, f32x4_relaxed_min);
simd_binop!(F32x4RelaxedMax, f32x4_relaxed_max);
simd_binop!(F64x2RelaxedMin, f64x2_relaxed_min);
simd_binop!(F64x2RelaxedMax, f64x2_relaxed_max);
simd_binop!(I16x8RelaxedQ15mulrS, i16x8_relaxed_q15mulr_s);
simd_binop!(I16x8DotI8x16I7x16S, i16x8_dot_i8x16_i7x16_s);
simd_ternop!(I32x4DotI8x16I7x16AddS, i32x4_dot_i8x16_i7x16_add_s);
simd_binop!(I16x8RelaxedDotI8x16I7x16S, i16x8_relaxed_dot_i8x16_i7x16_s);
simd_ternop!(
F32x4RelaxedDotBf16x8AddF32x4,
f32x4_relaxed_dot_bf16x8_add_f32x4
I32x4RelaxedDotI8x16I7x16AddS,
i32x4_relaxed_dot_i8x16_i7x16_add_s
);

Просмотреть файл

@ -399,7 +399,10 @@ fn dummy_value_inst<'a>(ty: ValType) -> Instruction<'a> {
ValType::F32 => Instruction::F32Const(0.0),
ValType::F64 => Instruction::F64Const(0.0),
ValType::V128 => Instruction::V128Const(0),
ValType::FuncRef | ValType::ExternRef => Instruction::RefNull(ty),
ValType::Ref(ty) => {
assert!(ty.nullable);
Instruction::RefNull(ty.heap_type)
}
}
}
@ -636,6 +639,6 @@ fn size_of_type_in_memory(ty: ValType) -> u64 {
ValType::F32 => 4,
ValType::F64 => 8,
ValType::V128 => 16,
ValType::FuncRef | ValType::ExternRef => panic!("not a memory type"),
ValType::Ref(_) => panic!("not a memory type"),
}
}

Просмотреть файл

@ -152,10 +152,10 @@ impl Module {
// TODO(nagisa): generate global.get of imported ref globals too.
match e {
Some(i) => match el.ty {
ValType::FuncRef => wasm_encoder::ConstExpr::ref_func(*i),
RefType::FUNCREF => wasm_encoder::ConstExpr::ref_func(*i),
_ => unreachable!(),
},
None => wasm_encoder::ConstExpr::ref_null(el.ty),
None => wasm_encoder::ConstExpr::ref_null(el.ty.heap_type),
}
}));
wasm_encoder::Elements::Expressions(&exps)

5
third_party/rust/wasm-smith/tests/core.rs поставляемый
Просмотреть файл

@ -151,7 +151,7 @@ fn smoke_test_imports_config() {
*seen = true
}
(Some((seen, I::Table(t))), TypeRef::Table(tt))
if *t == tt.element_type =>
if *t == ValType::Ref(tt.element_type) =>
{
*seen = true
}
@ -253,7 +253,7 @@ fn import_config(
("env", "pipo", Func(&[I32], &[I32])),
("env", "popo", Func(&[], &[I32, I32])),
("env", "mem", Memory),
("env", "tbl", Table(FuncRef)),
("env", "tbl", Table(ValType::FUNCREF)),
("vars", "g", Global(I64)),
("tags", "tag1", Tag(&[I32])),
]
@ -300,6 +300,7 @@ fn parser_features_from_config(config: &impl Config) -> WasmFeatures {
floats: true,
extended_const: false,
component_model: false,
function_references: false,
memory_control: false,
}
}

Просмотреть файл

@ -1 +1 @@
{"files":{"Cargo.lock":"430baae8cea83da0463cc95ec996de0437beb083ac5173cf876f6d7d12103429","Cargo.toml":"9261b35e9cdb0ee22b78849c060aafef729e356884aa6186be48acf8ca9fe015","LICENSE":"268872b9816f90fd8e85db5a28d33f8150ebb8dd016653fb39ef1f94f2686bc5","README.md":"1c3b4f8db61a673ee2f7dc66118b1008ce8d1a7d0f5197fbe87f1271b23de3bd","benches/benchmark.rs":"09254d9d4d19ec102e1e19ee025f0542b9b2b84e014adc49e51e9024274301ac","examples/simple.rs":"e9eb076367cc0932e2a32651372defa4a27ef800f47fad28c0ef840ba8ea7e08","src/binary_reader.rs":"84a18c2955ce3a76ebdc1eb1aa56087a97e9f0c24e2c2b0598078778ccae73b7","src/lib.rs":"2ebd0a6222060c7ae306b641ce1d11cbec389c3d1eda1b3219a53d80452e19e1","src/limits.rs":"f9590aba36c682a16b9036a151cd1140393624e54c7b4b190487639923b15a52","src/parser.rs":"b65b995296ed03a5b4d31c6459f2f3430ff685e50fec397c44f91b1364de5aaf","src/readers.rs":"406bf0cf694ed364c9c53cd25eb27a8e3fa97d099994f3e2a640747c49abf74b","src/readers/component.rs":"c259628ca3f09ff904f7e920aeec261b657f7a197c99b520a6a7d3e918b9fb3b","src/readers/component/aliases.rs":"72f3339cb452c1b055bd080281fe4923d132c280da112fcd1182594811b87494","src/readers/component/canonicals.rs":"c36e9bffc2e1ed752586189903eec77ea9897ae265e020096a9b92c467be26d9","src/readers/component/exports.rs":"f2c76e4be5045f1d099fd89dedf20e2f4817f046ea1e64bde7ca8f3ea9b2cdc6","src/readers/component/imports.rs":"725a688f2ab4306dbb421fe92ffff9373e3c88632557e352529f297bb2b96e0e","src/readers/component/instances.rs":"bca614178da3337e8c71a6ec431f12157a8cccc15411a0222bbc0106926a3ad5","src/readers/component/names.rs":"3f5dac9db8668b18cd6721cd780e6aba9b223b404c9d1173d09efe4e6b4d3a8a","src/readers/component/start.rs":"8e1e5d8aa5ece26d42251449cadcce0546c4d995f1641941b8a31ed4bc6ac761","src/readers/component/types.rs":"878fdf8f3d6a1c1387fd92b34838d8e79cee039710366bd5ea6739448d468a7a","src/readers/core.rs":"b1dbe0ffe61af1e6da4104de687009bcaa71fd3137300896159abbcfd903b800","src/readers/core/code.rs":"e14884ac83f5644c813c8196aabcb6a5539d3d2860f251c064481f61b0e0ffed","src/readers/core/custom.rs":"f80d3a994e8778a912319834228cbb772c65a4b6b1f25b41fe00d220d388831f","src/readers/core/data.rs":"c1fcda7b548b15be40b3dd1f667d97c30c543867f2dc4734b590846beefe3ae3","src/readers/core/elements.rs":"f3ed0c28b044f1fe51a576e3b5baf93f5aa896e7fefd8432eaf14b59073eb7f6","src/readers/core/exports.rs":"50dc1ee51b73f03f24077f7c290bca756966563cedbad9e49d735d60f60c91db","src/readers/core/functions.rs":"b5bbc7f7b7a429187376f63c695a9f1cbf92e515dba840ac876fa60f7290da34","src/readers/core/globals.rs":"d23f99a3adc9593652a5efd4dc81e8f014f57e776b49717dabbdcd0a811a96b1","src/readers/core/imports.rs":"4d247e8cac0b3cef7425d93f7a7f2412b2ae8979da944080d565415499e27e87","src/readers/core/init.rs":"ec6717063b0b7f2e9aa17ae52083019cee52594bf5a8b6858f2d77b10d7a0639","src/readers/core/memories.rs":"351f816d663b7d17546dc3b19ce0e43f406ce743289219a3758f7c837903fa6d","src/readers/core/names.rs":"408ebf052170bf0dc874b3158bb31089a891c3735cb35df2976e0b1e9791febb","src/readers/core/operators.rs":"46e927f6db9db9097217c5485da3a7b89e638730def809d177897f39356f5f52","src/readers/core/producers.rs":"4b42b7e1c9e22e7e2913d9da2291b491dc2d4fea417503d7ce99ad33c7beb439","src/readers/core/tables.rs":"87f11101c81c53ccbe5b112c1b49e008ebc651c6d18cd80a1bcd995051193cdf","src/readers/core/tags.rs":"c1dcfeb973195da9708549bcc2df4dd8ff282fe802c15a603bebc8a856f70949","src/readers/core/types.rs":"aa8cf5a56f5b2ad5155ab110ea1058a7f9d72729c0aac4bc87d870267949b9f8","src/resources.rs":"f87a31420b2e7f377e4ffe16d9d9eb23abbb377e35a75756425941aa707dc775","src/validator.rs":"e1e93bf6bfdfc5ec9d157c3cbb30ff704e4aa4e68911d0372e4bfe017b30d24b","src/validator/component.rs":"c91c15defdb84aeb73b356803df62cb8850776e6ecfbec858104fc67c12cd65a","src/validator/core.rs":"628bee96b2e3520f125ce0073f9ff9440320d96f9c5e6f4a13d667202270311b","src/validator/func.rs":"d98940cc1210bea6acbea514face78e23f8357ad3746c920fb32d17f169ba9dc","src/validator/operators.rs":"7b325c2e0e40dfc378cbfcf5f5c2f292de64a652ed7385f493a722e16dc8d392","src/validator/types.rs":"4f0edbe37c12e0c030069106437f38797f3f4e8af1312420b53de5f620b0a4f8"},"package":"64b20236ab624147dfbb62cf12a19aaf66af0e41b8398838b66e997d07d269d4"}
{"files":{"Cargo.lock":"ef76d24da3e4c9b0e0034844c4d3fa21f84ddb56af9f3134222046aaf26a48d3","Cargo.toml":"f1f05638e3da3d7304ccb0a41ef0a9889224bc5dc92352c634a553c6fa27d4bd","LICENSE":"268872b9816f90fd8e85db5a28d33f8150ebb8dd016653fb39ef1f94f2686bc5","README.md":"1c3b4f8db61a673ee2f7dc66118b1008ce8d1a7d0f5197fbe87f1271b23de3bd","benches/benchmark.rs":"b8417fbd86058b76f3ff15426075f9afee25b9f90155bbd9a2d774f4bad0af04","examples/simple.rs":"e9eb076367cc0932e2a32651372defa4a27ef800f47fad28c0ef840ba8ea7e08","src/binary_reader.rs":"1b1f0e1d831a716875ed578380f96b4b60245f0c6a4f43e2407c50fc94e50e6d","src/lib.rs":"d64774abb8d193f6a177130ffca94ce9fd199535fb6177dcb9910c4af7602082","src/limits.rs":"0c4dc6b96b35a320a8cff8269c0b55acd56f1f7b8a093c4885e04b9835441458","src/parser.rs":"b65b995296ed03a5b4d31c6459f2f3430ff685e50fec397c44f91b1364de5aaf","src/readers.rs":"406bf0cf694ed364c9c53cd25eb27a8e3fa97d099994f3e2a640747c49abf74b","src/readers/component.rs":"c259628ca3f09ff904f7e920aeec261b657f7a197c99b520a6a7d3e918b9fb3b","src/readers/component/aliases.rs":"72f3339cb452c1b055bd080281fe4923d132c280da112fcd1182594811b87494","src/readers/component/canonicals.rs":"c36e9bffc2e1ed752586189903eec77ea9897ae265e020096a9b92c467be26d9","src/readers/component/exports.rs":"f2c76e4be5045f1d099fd89dedf20e2f4817f046ea1e64bde7ca8f3ea9b2cdc6","src/readers/component/imports.rs":"725a688f2ab4306dbb421fe92ffff9373e3c88632557e352529f297bb2b96e0e","src/readers/component/instances.rs":"bca614178da3337e8c71a6ec431f12157a8cccc15411a0222bbc0106926a3ad5","src/readers/component/names.rs":"3f5dac9db8668b18cd6721cd780e6aba9b223b404c9d1173d09efe4e6b4d3a8a","src/readers/component/start.rs":"8e1e5d8aa5ece26d42251449cadcce0546c4d995f1641941b8a31ed4bc6ac761","src/readers/component/types.rs":"878fdf8f3d6a1c1387fd92b34838d8e79cee039710366bd5ea6739448d468a7a","src/readers/core.rs":"b1dbe0ffe61af1e6da4104de687009bcaa71fd3137300896159abbcfd903b800","src/readers/core/code.rs":"53f49986febb27f4cb67f4495e7b369fc80e2f70908e1e831750698dd15fe37f","src/readers/core/custom.rs":"f80d3a994e8778a912319834228cbb772c65a4b6b1f25b41fe00d220d388831f","src/readers/core/data.rs":"c1fcda7b548b15be40b3dd1f667d97c30c543867f2dc4734b590846beefe3ae3","src/readers/core/elements.rs":"197d3427fcf0fa8a3eb654e62dfa53159e6bc5cb160e75a06cf394f821bddef5","src/readers/core/exports.rs":"50dc1ee51b73f03f24077f7c290bca756966563cedbad9e49d735d60f60c91db","src/readers/core/functions.rs":"b5bbc7f7b7a429187376f63c695a9f1cbf92e515dba840ac876fa60f7290da34","src/readers/core/globals.rs":"d23f99a3adc9593652a5efd4dc81e8f014f57e776b49717dabbdcd0a811a96b1","src/readers/core/imports.rs":"4d247e8cac0b3cef7425d93f7a7f2412b2ae8979da944080d565415499e27e87","src/readers/core/init.rs":"ec6717063b0b7f2e9aa17ae52083019cee52594bf5a8b6858f2d77b10d7a0639","src/readers/core/memories.rs":"351f816d663b7d17546dc3b19ce0e43f406ce743289219a3758f7c837903fa6d","src/readers/core/names.rs":"408ebf052170bf0dc874b3158bb31089a891c3735cb35df2976e0b1e9791febb","src/readers/core/operators.rs":"46e927f6db9db9097217c5485da3a7b89e638730def809d177897f39356f5f52","src/readers/core/producers.rs":"4b42b7e1c9e22e7e2913d9da2291b491dc2d4fea417503d7ce99ad33c7beb439","src/readers/core/tables.rs":"cbe5b35893bd3929354b4487b344062ce6b540e6a70bde6eddf05a07a68574e9","src/readers/core/tags.rs":"c1dcfeb973195da9708549bcc2df4dd8ff282fe802c15a603bebc8a856f70949","src/readers/core/types.rs":"266a6c37ecdea656c235001b56b15564ad7777c23849a3f6e08ce63272347c7e","src/resources.rs":"b38b564ee425a392a30fb7440b50afa9e91be5ee933e4933b843e18c212a5871","src/validator.rs":"0dc406f1a61cf646719fa2d88675eae4d8c52c23cc3a4a222b6671cd25f84465","src/validator/component.rs":"4ca4d2d3c800e212a68e30577eead6bb69b2e7604f6d774d4f51f2aaa2f87084","src/validator/core.rs":"143f1a531485d411eb459fe608a64ca21f772740cbebe51e9f336e30ce3d1424","src/validator/func.rs":"63b66b7bb274be4115d8a26bce9b73128de0c079bd3318423288fadc1361fdb4","src/validator/operators.rs":"39b3bd04898b02b9dbd1d42c5727c79439593f5ef8fbf3c33fcc789d0b5be91a","src/validator/types.rs":"9ee9fb8a8afa0580c3e71bf9b39bd28c14b2a21f2d9acbb92e7d8ec14615ade2","tests/big-module.rs":"1f9241a4504d0421f6a5c759e3c688c87994fe04668b1d4e8912cedd98f2bd17"},"package":"48134de3d7598219ab9eaf6b91b15d8e50d31da76b8519fe4ecfcec2cf35104b"}

18
third_party/rust/wasmparser/Cargo.lock сгенерированный поставляемый
Просмотреть файл

@ -274,6 +274,12 @@ version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]]
name = "leb128"
version = "0.2.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "884e2677b40cc8c339eaefcb701c32ef1fd2493d71118dc0ca4b6a736c93bd67"
[[package]]
name = "libc"
version = "0.2.139"
@ -637,9 +643,18 @@ version = "0.2.84"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0046fef7e28c3804e5e38bfa31ea2a0f73905319b677e57ebe37e49358989b5d"
[[package]]
name = "wasm-encoder"
version = "0.25.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4eff853c4f09eec94d76af527eddad4e9de13b11d6286a1ef7134bc30135a2b7"
dependencies = [
"leb128",
]
[[package]]
name = "wasmparser"
version = "0.100.0"
version = "0.102.0"
dependencies = [
"anyhow",
"criterion",
@ -647,6 +662,7 @@ dependencies = [
"once_cell",
"rayon",
"url",
"wasm-encoder",
]
[[package]]

5
third_party/rust/wasmparser/Cargo.toml поставляемый
Просмотреть файл

@ -12,7 +12,7 @@
[package]
edition = "2021"
name = "wasmparser"
version = "0.100.0"
version = "0.102.0"
authors = ["Yury Delendik <ydelendik@mozilla.com>"]
exclude = ["benches/*.wasm"]
description = """
@ -49,3 +49,6 @@ version = "1.13.0"
[dev-dependencies.rayon]
version = "1.3"
[dev-dependencies.wasm-encoder]
version = "0.25.0"

Просмотреть файл

@ -4,7 +4,10 @@ use once_cell::unsync::Lazy;
use std::fs;
use std::path::Path;
use std::path::PathBuf;
use wasmparser::{DataKind, ElementKind, Parser, Payload, Validator, VisitOperator, WasmFeatures};
use wasmparser::{
DataKind, ElementKind, HeapType, Parser, Payload, ValType, Validator, VisitOperator,
WasmFeatures,
};
/// A benchmark input.
pub struct BenchmarkInput {
@ -251,6 +254,7 @@ fn define_benchmarks(c: &mut Criterion) {
mutable_global: true,
saturating_float_to_int: true,
sign_extension: true,
function_references: true,
memory_control: true,
})
}

Просмотреть файл

@ -686,21 +686,21 @@ impl<'a> BinaryReader<'a> {
}
// Check for a block type of form [] -> [t].
if let Some(ty) = ValType::from_byte(b) {
self.position += 1;
return Ok(BlockType::Type(ty));
if ValType::is_valtype_byte(b) {
return Ok(BlockType::Type(self.read()?));
}
// Not empty or a singular type, so read the function type index
let idx = self.read_var_s33()?;
if idx < 0 || idx > (std::u32::MAX as i64) {
return Err(BinaryReaderError::new(
"invalid function type",
self.original_position(),
));
match u32::try_from(idx) {
Ok(idx) => Ok(BlockType::FuncType(idx)),
Err(_) => {
return Err(BinaryReaderError::new(
"invalid function type",
self.original_position(),
));
}
}
Ok(BlockType::FuncType(idx as u32))
}
/// Visit the next available operator with the specified [`VisitOperator`] instance.
@ -778,6 +778,8 @@ impl<'a> BinaryReader<'a> {
}
0x12 => visitor.visit_return_call(self.read_var_u32()?),
0x13 => visitor.visit_return_call_indirect(self.read_var_u32()?, self.read_var_u32()?),
0x14 => visitor.visit_call_ref(self.read()?),
0x15 => visitor.visit_return_call_ref(self.read()?),
0x18 => visitor.visit_delegate(self.read_var_u32()?),
0x19 => visitor.visit_catch_all(),
0x1a => visitor.visit_drop(),
@ -971,6 +973,9 @@ impl<'a> BinaryReader<'a> {
0xd0 => visitor.visit_ref_null(self.read()?),
0xd1 => visitor.visit_ref_is_null(),
0xd2 => visitor.visit_ref_func(self.read_var_u32()?),
0xd3 => visitor.visit_ref_as_non_null(),
0xd4 => visitor.visit_br_on_null(self.read_var_u32()?),
0xd6 => visitor.visit_br_on_non_null(self.read_var_u32()?),
0xfc => self.visit_0xfc_operator(pos, visitor)?,
0xfd => self.visit_0xfd_operator(pos, visitor)?,
@ -1347,14 +1352,14 @@ impl<'a> BinaryReader<'a> {
0xfe => visitor.visit_f64x2_convert_low_i32x4_s(),
0xff => visitor.visit_f64x2_convert_low_i32x4_u(),
0x100 => visitor.visit_i8x16_relaxed_swizzle(),
0x101 => visitor.visit_i32x4_relaxed_trunc_sat_f32x4_s(),
0x102 => visitor.visit_i32x4_relaxed_trunc_sat_f32x4_u(),
0x103 => visitor.visit_i32x4_relaxed_trunc_sat_f64x2_s_zero(),
0x104 => visitor.visit_i32x4_relaxed_trunc_sat_f64x2_u_zero(),
0x105 => visitor.visit_f32x4_relaxed_fma(),
0x106 => visitor.visit_f32x4_relaxed_fnma(),
0x107 => visitor.visit_f64x2_relaxed_fma(),
0x108 => visitor.visit_f64x2_relaxed_fnma(),
0x101 => visitor.visit_i32x4_relaxed_trunc_f32x4_s(),
0x102 => visitor.visit_i32x4_relaxed_trunc_f32x4_u(),
0x103 => visitor.visit_i32x4_relaxed_trunc_f64x2_s_zero(),
0x104 => visitor.visit_i32x4_relaxed_trunc_f64x2_u_zero(),
0x105 => visitor.visit_f32x4_relaxed_madd(),
0x106 => visitor.visit_f32x4_relaxed_nmadd(),
0x107 => visitor.visit_f64x2_relaxed_madd(),
0x108 => visitor.visit_f64x2_relaxed_nmadd(),
0x109 => visitor.visit_i8x16_relaxed_laneselect(),
0x10a => visitor.visit_i16x8_relaxed_laneselect(),
0x10b => visitor.visit_i32x4_relaxed_laneselect(),
@ -1364,9 +1369,8 @@ impl<'a> BinaryReader<'a> {
0x10f => visitor.visit_f64x2_relaxed_min(),
0x110 => visitor.visit_f64x2_relaxed_max(),
0x111 => visitor.visit_i16x8_relaxed_q15mulr_s(),
0x112 => visitor.visit_i16x8_dot_i8x16_i7x16_s(),
0x113 => visitor.visit_i32x4_dot_i8x16_i7x16_add_s(),
0x114 => visitor.visit_f32x4_relaxed_dot_bf16x8_add_f32x4(),
0x112 => visitor.visit_i16x8_relaxed_dot_i8x16_i7x16_s(),
0x113 => visitor.visit_i32x4_relaxed_dot_i8x16_i7x16_add_s(),
_ => bail!(pos, "unknown 0xfd subopcode: 0x{code:x}"),
})

30
third_party/rust/wasmparser/src/lib.rs поставляемый
Просмотреть файл

@ -174,7 +174,7 @@ macro_rules! for_each_operator {
@mvp I64Const { value: i64 } => visit_i64_const
@mvp F32Const { value: $crate::Ieee32 } => visit_f32_const
@mvp F64Const { value: $crate::Ieee64 } => visit_f64_const
@reference_types RefNull { ty: $crate::ValType } => visit_ref_null
@reference_types RefNull { hty: $crate::HeapType } => visit_ref_null
@reference_types RefIsNull => visit_ref_is_null
@reference_types RefFunc { function_index: u32 } => visit_ref_func
@mvp I32Eqz => visit_i32_eqz
@ -658,14 +658,14 @@ macro_rules! for_each_operator {
// Relaxed SIMD operators
// https://github.com/WebAssembly/relaxed-simd
@relaxed_simd I8x16RelaxedSwizzle => visit_i8x16_relaxed_swizzle
@relaxed_simd I32x4RelaxedTruncSatF32x4S => visit_i32x4_relaxed_trunc_sat_f32x4_s
@relaxed_simd I32x4RelaxedTruncSatF32x4U => visit_i32x4_relaxed_trunc_sat_f32x4_u
@relaxed_simd I32x4RelaxedTruncSatF64x2SZero => visit_i32x4_relaxed_trunc_sat_f64x2_s_zero
@relaxed_simd I32x4RelaxedTruncSatF64x2UZero => visit_i32x4_relaxed_trunc_sat_f64x2_u_zero
@relaxed_simd F32x4RelaxedFma => visit_f32x4_relaxed_fma
@relaxed_simd F32x4RelaxedFnma => visit_f32x4_relaxed_fnma
@relaxed_simd F64x2RelaxedFma => visit_f64x2_relaxed_fma
@relaxed_simd F64x2RelaxedFnma => visit_f64x2_relaxed_fnma
@relaxed_simd I32x4RelaxedTruncF32x4S => visit_i32x4_relaxed_trunc_f32x4_s
@relaxed_simd I32x4RelaxedTruncF32x4U => visit_i32x4_relaxed_trunc_f32x4_u
@relaxed_simd I32x4RelaxedTruncF64x2SZero => visit_i32x4_relaxed_trunc_f64x2_s_zero
@relaxed_simd I32x4RelaxedTruncF64x2UZero => visit_i32x4_relaxed_trunc_f64x2_u_zero
@relaxed_simd F32x4RelaxedMadd => visit_f32x4_relaxed_madd
@relaxed_simd F32x4RelaxedNmadd => visit_f32x4_relaxed_nmadd
@relaxed_simd F64x2RelaxedMadd => visit_f64x2_relaxed_madd
@relaxed_simd F64x2RelaxedNmadd => visit_f64x2_relaxed_nmadd
@relaxed_simd I8x16RelaxedLaneselect => visit_i8x16_relaxed_laneselect
@relaxed_simd I16x8RelaxedLaneselect => visit_i16x8_relaxed_laneselect
@relaxed_simd I32x4RelaxedLaneselect => visit_i32x4_relaxed_laneselect
@ -675,9 +675,15 @@ macro_rules! for_each_operator {
@relaxed_simd F64x2RelaxedMin => visit_f64x2_relaxed_min
@relaxed_simd F64x2RelaxedMax => visit_f64x2_relaxed_max
@relaxed_simd I16x8RelaxedQ15mulrS => visit_i16x8_relaxed_q15mulr_s
@relaxed_simd I16x8DotI8x16I7x16S => visit_i16x8_dot_i8x16_i7x16_s
@relaxed_simd I32x4DotI8x16I7x16AddS => visit_i32x4_dot_i8x16_i7x16_add_s
@relaxed_simd F32x4RelaxedDotBf16x8AddF32x4 => visit_f32x4_relaxed_dot_bf16x8_add_f32x4
@relaxed_simd I16x8RelaxedDotI8x16I7x16S => visit_i16x8_relaxed_dot_i8x16_i7x16_s
@relaxed_simd I32x4RelaxedDotI8x16I7x16AddS => visit_i32x4_relaxed_dot_i8x16_i7x16_add_s
// Typed Function references
@function_references CallRef { hty: $crate::HeapType } => visit_call_ref
@function_references ReturnCallRef { hty: $crate::HeapType } => visit_return_call_ref
@function_references RefAsNonNull => visit_ref_as_non_null
@function_references BrOnNull { relative_depth: u32 } => visit_br_on_null
@function_references BrOnNonNull { relative_depth: u32 } => visit_br_on_non_null
}
};
}

8
third_party/rust/wasmparser/src/limits.rs поставляемый
Просмотреть файл

@ -37,9 +37,9 @@ pub const MAX_WASM_BR_TABLE_SIZE: usize = MAX_WASM_FUNCTION_SIZE;
// Component-related limits
pub const MAX_WASM_MODULE_SIZE: usize = 1024 * 1024 * 1024; //= 1 GiB
pub const MAX_WASM_MODULE_TYPE_DECLS: usize = 1000;
pub const MAX_WASM_COMPONENT_TYPE_DECLS: usize = 1000;
pub const MAX_WASM_INSTANCE_TYPE_DECLS: usize = 1000;
pub const MAX_WASM_MODULE_TYPE_DECLS: usize = 100_000;
pub const MAX_WASM_COMPONENT_TYPE_DECLS: usize = 100_000;
pub const MAX_WASM_INSTANCE_TYPE_DECLS: usize = 100_000;
pub const MAX_WASM_RECORD_FIELDS: usize = 1000;
pub const MAX_WASM_VARIANT_CASES: usize = 1000;
pub const MAX_WASM_TUPLE_TYPES: usize = 1000;
@ -50,7 +50,7 @@ pub const MAX_WASM_INSTANTIATION_EXPORTS: usize = 1000;
pub const MAX_WASM_CANONICAL_OPTIONS: usize = 10;
pub const MAX_WASM_INSTANTIATION_ARGS: usize = 1000;
pub const MAX_WASM_START_ARGS: usize = 1000;
pub const MAX_WASM_TYPE_SIZE: u32 = 100_000;
pub const MAX_WASM_TYPE_SIZE: u32 = 1_000_000;
pub const MAX_WASM_MODULES: usize = 1_000;
pub const MAX_WASM_COMPONENTS: usize = 1_000;
pub const MAX_WASM_INSTANCES: usize = 1_000;

Просмотреть файл

@ -51,7 +51,7 @@ impl<'a> FunctionBody<'a> {
let count = reader.read_var_u32()?;
for _ in 0..count {
reader.read_var_u32()?;
reader.read_var_u32()?;
reader.read::<ValType>()?;
}
Ok(())
}

Просмотреть файл

@ -14,8 +14,8 @@
*/
use crate::{
BinaryReader, BinaryReaderError, ConstExpr, ExternalKind, FromReader, Result, SectionLimited,
ValType,
BinaryReader, BinaryReaderError, ConstExpr, ExternalKind, FromReader, RefType, Result,
SectionLimited,
};
use std::ops::Range;
@ -27,7 +27,7 @@ pub struct Element<'a> {
/// The initial elements of the element segment.
pub items: ElementItems<'a>,
/// The type of the elements.
pub ty: ValType,
pub ty: RefType,
/// The range of the the element segment.
pub range: Range<usize>,
}
@ -107,7 +107,7 @@ impl<'a> FromReader<'a> for Element<'a> {
reader.read()?
} else {
match reader.read()? {
ExternalKind::Func => ValType::FuncRef,
ExternalKind::Func => RefType::FUNCREF,
_ => {
return Err(BinaryReaderError::new(
"only the function external type is supported in elem segment",
@ -117,7 +117,7 @@ impl<'a> FromReader<'a> for Element<'a> {
}
}
} else {
ValType::FuncRef
RefType::FUNCREF
};
// FIXME(#188) ideally wouldn't have to do skips here
let data = reader.skip(|reader| {

Просмотреть файл

@ -13,10 +13,55 @@
* limitations under the License.
*/
use crate::{BinaryReader, FromReader, Result, SectionLimited, TableType};
use crate::{BinaryReader, ConstExpr, FromReader, Result, SectionLimited, TableType};
/// A reader for the table section of a WebAssembly module.
pub type TableSectionReader<'a> = SectionLimited<'a, TableType>;
pub type TableSectionReader<'a> = SectionLimited<'a, Table<'a>>;
/// Type information about a table defined in the table section of a WebAssembly
/// module.
#[derive(Debug)]
pub struct Table<'a> {
/// The type of this table, including its element type and its limits.
pub ty: TableType,
/// The initialization expression for the table.
pub init: TableInit<'a>,
}
/// Different modes of initializing a table.
#[derive(Debug)]
pub enum TableInit<'a> {
/// The table is initialized to all null elements.
RefNull,
/// Each element in the table is initialized with the specified constant
/// expression.
Expr(ConstExpr<'a>),
}
impl<'a> FromReader<'a> for Table<'a> {
fn from_reader(reader: &mut BinaryReader<'a>) -> Result<Self> {
let has_init_expr = if reader.peek()? == 0x40 {
reader.read_u8()?;
true
} else {
false
};
if has_init_expr {
if reader.read_u8()? != 0x00 {
bail!(reader.original_position() - 1, "invalid table encoding");
}
}
let ty = reader.read::<TableType>()?;
let init = if has_init_expr {
TableInit::Expr(reader.read()?)
} else {
TableInit::RefNull
};
Ok(Table { ty, init })
}
}
impl<'a> FromReader<'a> for TableType {
fn from_reader(reader: &mut BinaryReader<'a>) -> Result<Self> {

Просмотреть файл

@ -30,43 +30,180 @@ pub enum ValType {
F64,
/// The value type is v128.
V128,
/// The value type is a function reference.
FuncRef,
/// The value type is an extern reference.
ExternRef,
/// The value type is a reference. Which type of reference is decided by
/// RefType. This is a change in syntax from the function references proposal,
/// which now provides FuncRef and ExternRef as sugar for the generic ref
/// construct.
Ref(RefType),
}
/// A reference type. When the function references feature is disabled, this
/// only represents funcref and externref, using the following format:
/// RefType { nullable: true, heap_type: Func | Extern })
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
#[repr(packed)]
pub struct RefType {
/// Whether it's nullable
pub nullable: bool,
/// The relevant heap type
pub heap_type: HeapType,
}
impl RefType {
/// Alias for the wasm `funcref` type.
pub const FUNCREF: RefType = RefType {
nullable: true,
heap_type: HeapType::Func,
};
/// Alias for the wasm `externref` type.
pub const EXTERNREF: RefType = RefType {
nullable: true,
heap_type: HeapType::Extern,
};
}
impl From<RefType> for ValType {
fn from(ty: RefType) -> ValType {
ValType::Ref(ty)
}
}
/// Used as a performance optimization in HeapType. Call `.into()` to get the u32
// A u16 forces 2-byte alignment, which forces HeapType to be 4 bytes,
// which forces ValType to 5 bytes. This newtype is annotated as unaligned to
// store the necessary bits compactly
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
#[repr(packed)]
pub struct PackedIndex(u16);
impl TryFrom<u32> for PackedIndex {
type Error = ();
fn try_from(idx: u32) -> Result<PackedIndex, ()> {
idx.try_into().map(PackedIndex).map_err(|_| ())
}
}
impl From<PackedIndex> for u32 {
fn from(x: PackedIndex) -> u32 {
x.0 as u32
}
}
/// A heap type from function references. When the proposal is disabled, Index
/// is an invalid type.
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum HeapType {
/// Function type index
/// Note: [PackedIndex] may need to be unpacked
TypedFunc(PackedIndex),
/// From reference types
Func,
/// From reference types
Extern,
}
impl ValType {
/// Alias for the wasm `funcref` type.
pub const FUNCREF: ValType = ValType::Ref(RefType::FUNCREF);
/// Alias for the wasm `externref` type.
pub const EXTERNREF: ValType = ValType::Ref(RefType::EXTERNREF);
/// Returns whether this value type is a "reference type".
///
/// Only reference types are allowed in tables, for example, and with some
/// instructions. Current reference types include `funcref` and `externref`.
pub fn is_reference_type(&self) -> bool {
matches!(self, ValType::FuncRef | ValType::ExternRef)
matches!(self, ValType::Ref(_))
}
/// Whether the type is defaultable according to function references
/// spec. This amounts to whether it's a non-nullable ref
pub fn is_defaultable(&self) -> bool {
!matches!(
self,
ValType::Ref(RefType {
nullable: false,
..
})
)
}
pub(crate) fn from_byte(byte: u8) -> Option<ValType> {
pub(crate) fn is_valtype_byte(byte: u8) -> bool {
match byte {
0x7F => Some(ValType::I32),
0x7E => Some(ValType::I64),
0x7D => Some(ValType::F32),
0x7C => Some(ValType::F64),
0x7B => Some(ValType::V128),
0x70 => Some(ValType::FuncRef),
0x6F => Some(ValType::ExternRef),
_ => None,
0x7F | 0x7E | 0x7D | 0x7C | 0x7B | 0x70 | 0x6F | 0x6B | 0x6C => true,
_ => false,
}
}
}
impl<'a> FromReader<'a> for ValType {
fn from_reader(reader: &mut BinaryReader<'a>) -> Result<Self> {
match ValType::from_byte(reader.peek()?) {
Some(ty) => {
match reader.peek()? {
0x7F => {
reader.position += 1;
Ok(ty)
Ok(ValType::I32)
}
0x7E => {
reader.position += 1;
Ok(ValType::I64)
}
0x7D => {
reader.position += 1;
Ok(ValType::F32)
}
0x7C => {
reader.position += 1;
Ok(ValType::F64)
}
0x7B => {
reader.position += 1;
Ok(ValType::V128)
}
0x70 | 0x6F | 0x6B | 0x6C => Ok(ValType::Ref(reader.read()?)),
_ => bail!(reader.original_position(), "invalid value type"),
}
}
}
impl<'a> FromReader<'a> for RefType {
fn from_reader(reader: &mut BinaryReader<'a>) -> Result<Self> {
match reader.read()? {
0x70 => Ok(RefType::FUNCREF),
0x6F => Ok(RefType::EXTERNREF),
byte @ (0x6B | 0x6C) => Ok(RefType {
nullable: byte == 0x6C,
heap_type: reader.read()?,
}),
_ => bail!(reader.original_position(), "malformed reference type"),
}
}
}
impl<'a> FromReader<'a> for HeapType {
fn from_reader(reader: &mut BinaryReader<'a>) -> Result<Self> {
match reader.peek()? {
0x70 => {
reader.position += 1;
Ok(HeapType::Func)
}
0x6F => {
reader.position += 1;
Ok(HeapType::Extern)
}
_ => {
let idx = match u32::try_from(reader.read_var_s33()?) {
Ok(idx) => idx,
Err(_) => {
bail!(reader.original_position(), "invalid function heap type",);
}
};
match idx.try_into() {
Ok(packed) => Ok(HeapType::TypedFunc(packed)),
Err(_) => {
bail!(reader.original_position(), "function index too large");
}
}
}
None => bail!(reader.original_position(), "invalid value type"),
}
}
}
@ -142,7 +279,7 @@ impl FuncType {
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub struct TableType {
/// The table's element type.
pub element_type: ValType,
pub element_type: RefType,
/// Initial size of this table, in elements.
pub initial: u32,
/// Optional maximum size of the table, in elements.

76
third_party/rust/wasmparser/src/resources.rs поставляемый
Просмотреть файл

@ -13,7 +13,10 @@
* limitations under the License.
*/
use crate::{FuncType, GlobalType, MemoryType, TableType, ValType};
use crate::{
BinaryReaderError, FuncType, GlobalType, HeapType, MemoryType, RefType, TableType, ValType,
WasmFeatures,
};
use std::ops::Range;
/// Types that qualify as Wasm function types for validation purposes.
@ -208,10 +211,44 @@ pub trait WasmModuleResources {
fn global_at(&self, at: u32) -> Option<GlobalType>;
/// Returns the `FuncType` associated with the given type index.
fn func_type_at(&self, type_idx: u32) -> Option<&Self::FuncType>;
/// Returns the type index associated with the given function
/// index. type_of_function = func_type_at(type_index_of_function)
fn type_index_of_function(&self, func_idx: u32) -> Option<u32>;
/// Returns the `FuncType` associated with the given function index.
fn type_of_function(&self, func_idx: u32) -> Option<&Self::FuncType>;
/// Returns the element type at the given index.
fn element_type_at(&self, at: u32) -> Option<ValType>;
fn element_type_at(&self, at: u32) -> Option<RefType>;
/// Under the function references proposal, returns whether t1 <=
/// t2. Otherwise, returns whether t1 == t2
fn matches(&self, t1: ValType, t2: ValType) -> bool;
/// Check a value type. This requires using func_type_at to check references
fn check_value_type(
&self,
t: ValType,
features: &WasmFeatures,
offset: usize,
) -> Result<(), BinaryReaderError>;
/// Checks that a `HeapType` is valid, notably its function index if one is
/// used.
fn check_heap_type(
&self,
heap_type: HeapType,
features: &WasmFeatures,
offset: usize,
) -> Result<(), BinaryReaderError> {
// Delegate to the generic value type validation which will have the
// same validity checks.
self.check_value_type(
RefType {
nullable: true,
heap_type,
}
.into(),
features,
offset,
)
}
/// Returns the number of elements.
fn element_count(&self) -> u32;
@ -243,12 +280,26 @@ where
fn func_type_at(&self, at: u32) -> Option<&Self::FuncType> {
T::func_type_at(self, at)
}
fn type_index_of_function(&self, func_idx: u32) -> Option<u32> {
T::type_index_of_function(self, func_idx)
}
fn type_of_function(&self, func_idx: u32) -> Option<&Self::FuncType> {
T::type_of_function(self, func_idx)
}
fn element_type_at(&self, at: u32) -> Option<ValType> {
fn check_value_type(
&self,
t: ValType,
features: &WasmFeatures,
offset: usize,
) -> Result<(), BinaryReaderError> {
T::check_value_type(self, t, features, offset)
}
fn element_type_at(&self, at: u32) -> Option<RefType> {
T::element_type_at(self, at)
}
fn matches(&self, t1: ValType, t2: ValType) -> bool {
T::matches(self, t1, t2)
}
fn element_count(&self) -> u32 {
T::element_count(self)
@ -287,14 +338,31 @@ where
T::func_type_at(self, type_idx)
}
fn type_index_of_function(&self, func_idx: u32) -> Option<u32> {
T::type_index_of_function(self, func_idx)
}
fn type_of_function(&self, func_idx: u32) -> Option<&Self::FuncType> {
T::type_of_function(self, func_idx)
}
fn element_type_at(&self, at: u32) -> Option<ValType> {
fn check_value_type(
&self,
t: ValType,
features: &WasmFeatures,
offset: usize,
) -> Result<(), BinaryReaderError> {
T::check_value_type(self, t, features, offset)
}
fn element_type_at(&self, at: u32) -> Option<RefType> {
T::element_type_at(self, at)
}
fn matches(&self, t1: ValType, t2: ValType) -> bool {
T::matches(self, t1, t2)
}
fn element_count(&self) -> u32 {
T::element_count(self)
}

48
third_party/rust/wasmparser/src/validator.rs поставляемый
Просмотреть файл

@ -14,8 +14,8 @@
*/
use crate::{
limits::*, BinaryReaderError, Encoding, FromReader, FunctionBody, Parser, Payload, Result,
SectionLimited, ValType, WASM_COMPONENT_VERSION, WASM_MODULE_VERSION,
limits::*, BinaryReaderError, Encoding, FromReader, FunctionBody, HeapType, Parser, Payload,
Result, SectionLimited, ValType, WASM_COMPONENT_VERSION, WASM_MODULE_VERSION,
};
use std::mem;
use std::ops::Range;
@ -240,11 +240,17 @@ pub struct WasmFeatures {
pub extended_const: bool,
/// The WebAssembly component model proposal.
pub component_model: bool,
/// The WebAssembly typed function references proposal
pub function_references: bool,
/// The WebAssembly memory control proposal
pub memory_control: bool,
}
impl WasmFeatures {
/// NOTE: This only checks that the value type corresponds to the feature set!!
///
/// To check that reference types are valid, we need access to the module
/// types. Use module.check_value_type.
pub(crate) fn check_value_type(&self, ty: ValType) -> Result<(), &'static str> {
match ty {
ValType::I32 | ValType::I64 => Ok(()),
@ -255,9 +261,21 @@ impl WasmFeatures {
Err("floating-point support is disabled")
}
}
ValType::FuncRef | ValType::ExternRef => {
ValType::Ref(r) => {
if self.reference_types {
Ok(())
if !self.function_references {
match (r.heap_type, r.nullable) {
(_, false) => {
Err("function references required for non-nullable types")
}
(HeapType::TypedFunc(_), _) => {
Err("function references required for index reference types")
}
_ => Ok(()),
}
} else {
Ok(())
}
} else {
Err("reference types support is not enabled")
}
@ -284,6 +302,7 @@ impl Default for WasmFeatures {
memory64: false,
extended_const: false,
component_model: false,
function_references: false,
memory_control: false,
// On-by-default features (phase 4 or greater).
@ -515,8 +534,9 @@ impl Validator {
if !self.features.component_model {
bail!(
range.start,
"unknown binary version: {num:#x}, \
note: the WebAssembly component model feature is not enabled",
"unknown binary version and encoding combination: {num:#x} and 0x1, \
note: encoded as a component but the WebAssembly component model feature \
is not enabled - enable the feature to allow component validation",
);
}
if num == WASM_COMPONENT_VERSION {
@ -623,9 +643,7 @@ impl Validator {
state.module.assert_mut().tables.reserve(count as usize);
Ok(())
},
|state, features, _, ty, offset| {
state.module.assert_mut().add_table(ty, features, offset)
},
|state, features, types, table, offset| state.add_table(table, features, types, offset),
)
}
@ -1169,13 +1187,13 @@ impl Validator {
|components, _, count, offset| {
let current = components.last_mut().unwrap();
check_max(
current.exports.len(),
current.externs.len(),
count,
MAX_WASM_EXPORTS,
"exports",
"imports and exports",
offset,
)?;
current.exports.reserve(count as usize);
current.externs.reserve(count as usize);
Ok(())
},
|components, types, _, export, offset| {
@ -1351,7 +1369,7 @@ impl Validator {
#[cfg(test)]
mod tests {
use crate::{GlobalType, MemoryType, TableType, ValType, Validator, WasmFeatures};
use crate::{GlobalType, MemoryType, RefType, TableType, ValType, Validator, WasmFeatures};
use anyhow::Result;
#[test]
@ -1420,7 +1438,7 @@ mod tests {
Some(TableType {
initial: 10,
maximum: None,
element_type: ValType::FuncRef,
element_type: RefType::FUNCREF,
})
);
@ -1448,7 +1466,7 @@ mod tests {
_ => unreachable!(),
}
assert_eq!(types.element_at(0), Some(ValType::FuncRef));
assert_eq!(types.element_at(0), Some(RefType::FUNCREF));
Ok(())
}

Просмотреть файл

@ -64,8 +64,8 @@ pub(crate) struct ComponentState {
pub instances: Vec<TypeId>,
pub components: Vec<TypeId>,
pub imports: IndexMap<KebabString, (Option<Url>, ComponentEntityType)>,
pub exports: IndexMap<KebabString, (Option<Url>, ComponentEntityType)>,
/// A set of all imports and exports since they share the same namespace.
pub externs: IndexMap<KebabString, (Option<Url>, ComponentEntityType, ExternKind)>,
// Note: URL validation requires unique URLs by byte comparison, so
// strings are used here and the URLs are not normalized.
@ -76,6 +76,20 @@ pub(crate) struct ComponentState {
type_size: u32,
}
pub enum ExternKind {
Import,
Export,
}
impl ExternKind {
fn desc(&self) -> &'static str {
match self {
ExternKind::Import => "import",
ExternKind::Export => "export",
}
}
}
impl ComponentState {
pub fn type_count(&self) -> usize {
self.core_types.len() + self.types.len()
@ -218,13 +232,14 @@ impl ComponentState {
self.add_entity(entity, false, offset)?;
let name = to_kebab_str(import.name, "import", offset)?;
match self.imports.entry(name.to_owned()) {
match self.externs.entry(name.to_owned()) {
Entry::Occupied(e) => {
bail!(
offset,
"import name `{name}` conflicts with previous import name `{prev}`",
"import name `{name}` conflicts with previous {desc} name `{prev}`",
name = import.name,
prev = e.key()
prev = e.key(),
desc = e.get().2.desc(),
);
}
Entry::Vacant(e) => {
@ -236,7 +251,7 @@ impl ComponentState {
}
self.type_size = combine_type_sizes(self.type_size, entity.type_size(), offset)?;
e.insert((url, entity));
e.insert((url, entity, ExternKind::Import));
}
}
@ -289,18 +304,25 @@ impl ComponentState {
check_limit: bool,
) -> Result<()> {
if check_limit {
check_max(self.exports.len(), 1, MAX_WASM_EXPORTS, "exports", offset)?;
check_max(
self.externs.len(),
1,
MAX_WASM_EXPORTS,
"imports and exports",
offset,
)?;
}
self.add_entity(ty, true, offset)?;
let name = to_kebab_str(name, "export", offset)?;
match self.exports.entry(name.to_owned()) {
match self.externs.entry(name.to_owned()) {
Entry::Occupied(e) => {
bail!(
offset,
"export name `{name}` conflicts with previous export name `{prev}`",
prev = e.key()
"export name `{name}` conflicts with previous {desc} name `{prev}`",
prev = e.key(),
desc = e.get().2.desc(),
);
}
Entry::Vacant(e) => {
@ -312,7 +334,7 @@ impl ComponentState {
}
self.type_size = combine_type_sizes(self.type_size, ty.type_size(), offset)?;
e.insert((url, ty));
e.insert((url, ty, ExternKind::Export));
}
}
@ -388,12 +410,7 @@ impl ComponentState {
}
pub fn add_component(&mut self, component: &mut Self, types: &mut TypeAlloc) {
let ty = Type::Component(ComponentType {
type_size: component.type_size,
imports: mem::take(&mut component.imports),
exports: mem::take(&mut component.exports),
});
let ty = Type::Component(component.take_component_type());
let id = types.push_anon(ty);
self.components.push(id);
}
@ -848,13 +865,9 @@ impl ComponentState {
};
}
let state = components.pop().unwrap();
let mut state = components.pop().unwrap();
Ok(ComponentType {
type_size: state.type_size,
imports: state.imports,
exports: state.exports,
})
Ok(state.take_component_type())
}
fn create_instance_type(
@ -889,7 +902,16 @@ impl ComponentState {
Ok(ComponentInstanceType {
type_size: state.type_size,
kind: ComponentInstanceTypeKind::Defined(state.exports),
kind: ComponentInstanceTypeKind::Defined(
state
.externs
.into_iter()
.filter_map(|(name, (url, ty, kind))| match kind {
ExternKind::Export => Some((name, (url, ty))),
ExternKind::Import => None,
})
.collect(),
),
})
}
@ -1134,7 +1156,16 @@ impl ComponentState {
)?;
}
ComponentExternalKind::Type => {
// Type arguments are ignored
let ty = self.type_at(component_arg.index, false, offset)?;
insert_arg(
component_arg.name,
ComponentEntityType::Type {
referenced: ty,
created: ty,
},
&mut args,
offset,
)?;
}
}
}
@ -1149,13 +1180,13 @@ impl ComponentState {
| (ComponentEntityType::Component(_), ComponentEntityType::Component(_))
| (ComponentEntityType::Instance(_), ComponentEntityType::Instance(_))
| (ComponentEntityType::Func(_), ComponentEntityType::Func(_))
| (ComponentEntityType::Value(_), ComponentEntityType::Value(_)) => {}
| (ComponentEntityType::Value(_), ComponentEntityType::Value(_))
| (ComponentEntityType::Type { .. }, ComponentEntityType::Type { .. }) => {}
_ => {
bail!(
offset,
"expected component instantiation argument \
`{name}` to be of type `{}`",
expected.desc()
"expected component instantiation argument `{name}` to be a {desc}",
desc = expected.desc()
)
}
};
@ -1163,8 +1194,7 @@ impl ComponentState {
if !ComponentEntityType::internal_is_subtype_of(arg, types, expected, types) {
bail!(
offset,
"{} type mismatch for component instantiation argument `{name}`",
expected.desc(),
"type mismatch for component instantiation argument `{name}`"
);
}
}
@ -2024,6 +2054,25 @@ impl ComponentState {
None => bail!(offset, "unknown memory {idx}: memory index out of bounds"),
}
}
fn take_component_type(&mut self) -> ComponentType {
let mut ty = ComponentType {
type_size: self.type_size,
imports: Default::default(),
exports: Default::default(),
};
for (name, (url, t, kind)) in mem::take(&mut self.externs) {
let map = match kind {
ExternKind::Import => &mut ty.imports,
ExternKind::Export => &mut ty.exports,
};
let prev = map.insert(name, (url, t));
assert!(prev.is_none());
}
ty
}
}
impl Default for ComponentState {
@ -2042,10 +2091,9 @@ impl Default for ComponentState {
values: Default::default(),
instances: Default::default(),
components: Default::default(),
imports: Default::default(),
exports: Default::default(),
import_urls: Default::default(),
externs: Default::default(),
export_urls: Default::default(),
import_urls: Default::default(),
has_start: Default::default(),
type_size: 1,
}

Просмотреть файл

@ -2,27 +2,20 @@
//!
use super::{
check_max, combine_type_sizes,
operators::{OperatorValidator, OperatorValidatorAllocations},
operators::{ty_to_str, OperatorValidator, OperatorValidatorAllocations},
types::{EntityType, Type, TypeAlloc, TypeId, TypeList},
};
use crate::limits::*;
use crate::validator::core::arc::MaybeOwned;
use crate::{
BinaryReaderError, ConstExpr, Data, DataKind, Element, ElementKind, ExternalKind, FuncType,
Global, GlobalType, MemoryType, Result, TableType, TagType, TypeRef, ValType, VisitOperator,
WasmFeatures, WasmModuleResources,
Global, GlobalType, HeapType, MemoryType, RefType, Result, Table, TableInit, TableType,
TagType, TypeRef, ValType, VisitOperator, WasmFeatures, WasmFuncType, WasmModuleResources,
};
use indexmap::IndexMap;
use std::mem;
use std::{collections::HashSet, sync::Arc};
fn check_value_type(ty: ValType, features: &WasmFeatures, offset: usize) -> Result<()> {
match features.check_value_type(ty) {
Ok(()) => Ok(()),
Err(e) => Err(BinaryReaderError::new(e, offset)),
}
}
// Section order for WebAssembly modules.
//
// Component sections are unordered and allow for duplicates,
@ -140,12 +133,43 @@ impl ModuleState {
offset: usize,
) -> Result<()> {
self.module
.check_global_type(&global.ty, features, offset)?;
.check_global_type(&global.ty, features, types, offset)?;
self.check_const_expr(&global.init_expr, global.ty.content_type, features, types)?;
self.module.assert_mut().globals.push(global.ty);
Ok(())
}
pub fn add_table(
&mut self,
table: Table<'_>,
features: &WasmFeatures,
types: &TypeList,
offset: usize,
) -> Result<()> {
self.module
.check_table_type(&table.ty, features, types, offset)?;
match &table.init {
TableInit::RefNull => {
if !table.ty.element_type.nullable {
bail!(offset, "type mismatch: non-defaultable element type");
}
}
TableInit::Expr(expr) => {
if !features.function_references {
bail!(
offset,
"tables with expression initializers require \
the function-references proposal"
);
}
self.check_const_expr(expr, table.ty.element_type.into(), features, types)?;
}
}
self.module.assert_mut().tables.push(table.ty);
Ok(())
}
pub fn add_data_segment(
&mut self,
data: Data,
@ -174,11 +198,9 @@ impl ModuleState {
) -> Result<()> {
// the `funcref` value type is allowed all the way back to the MVP, so
// don't check it here
if e.ty != ValType::FuncRef {
check_value_type(e.ty, features, offset)?;
}
if !e.ty.is_reference_type() {
return Err(BinaryReaderError::new("malformed reference type", offset));
if e.ty != RefType::FUNCREF {
self.module
.check_value_type(ValType::Ref(e.ty), features, types, offset)?;
}
match e.kind {
ElementKind::Active {
@ -186,9 +208,16 @@ impl ModuleState {
offset_expr,
} => {
let table = self.module.table_at(table_index, offset)?;
if e.ty != table.element_type {
if !self
.module
.matches(ValType::Ref(e.ty), ValType::Ref(table.element_type), types)
{
return Err(BinaryReaderError::new(
"invalid element type for table type",
format!(
"type mismatch: invalid element type `{}` for table type `{}`",
ty_to_str(e.ty.into()),
ty_to_str(table.element_type.into()),
),
offset,
));
}
@ -217,15 +246,16 @@ impl ModuleState {
};
match e.items {
crate::ElementItems::Functions(reader) => {
validate_count(reader.count())?;
let count = reader.count();
if !e.ty.nullable && count <= 0 {
return Err(BinaryReaderError::new(
"a non-nullable element must come with an initialization expression",
offset,
));
}
validate_count(count)?;
for f in reader.into_iter_with_offsets() {
let (offset, f) = f?;
if e.ty != ValType::FuncRef {
return Err(BinaryReaderError::new(
"type mismatch: segment does not have funcref type",
offset,
));
}
self.module.get_func_type(f, types, offset)?;
self.module.assert_mut().function_references.insert(f);
}
@ -233,7 +263,7 @@ impl ModuleState {
crate::ElementItems::Expressions(reader) => {
validate_count(reader.count())?;
for expr in reader {
self.check_const_expr(&expr?, e.ty, features, types)?;
self.check_const_expr(&expr?, ValType::Ref(e.ty), features, types)?;
}
}
}
@ -448,7 +478,7 @@ pub(crate) struct Module {
pub tables: Vec<TableType>,
pub memories: Vec<MemoryType>,
pub globals: Vec<GlobalType>,
pub element_types: Vec<ValType>,
pub element_types: Vec<RefType>,
pub data_count: Option<u32>,
// Stores indexes into `types`.
pub functions: Vec<u32>,
@ -473,7 +503,7 @@ impl Module {
let ty = match ty {
crate::Type::Func(t) => {
for ty in t.params().iter().chain(t.results()) {
check_value_type(*ty, features, offset)?;
self.check_value_type(*ty, features, types, offset)?;
}
if t.results().len() > 1 && !features.multi_value {
return Err(BinaryReaderError::new(
@ -586,17 +616,6 @@ impl Module {
Ok(())
}
pub fn add_table(
&mut self,
ty: TableType,
features: &WasmFeatures,
offset: usize,
) -> Result<()> {
self.check_table_type(&ty, features, offset)?;
self.tables.push(ty);
Ok(())
}
pub fn add_memory(
&mut self,
ty: MemoryType,
@ -651,7 +670,7 @@ impl Module {
EntityType::Func(self.types[*type_index as usize])
}
TypeRef::Table(t) => {
self.check_table_type(t, features, offset)?;
self.check_table_type(t, features, types, offset)?;
EntityType::Table(*t)
}
TypeRef::Memory(t) => {
@ -663,7 +682,7 @@ impl Module {
EntityType::Tag(self.types[t.func_type_idx as usize])
}
TypeRef::Global(t) => {
self.check_global_type(t, features, offset)?;
self.check_global_type(t, features, types, offset)?;
EntityType::Global(*t)
}
})
@ -673,20 +692,15 @@ impl Module {
&self,
ty: &TableType,
features: &WasmFeatures,
types: &TypeList,
offset: usize,
) -> Result<()> {
// the `funcref` value type is allowed all the way back to the MVP, so
// don't check it here
if ty.element_type != ValType::FuncRef {
check_value_type(ty.element_type, features, offset)?;
if ty.element_type != RefType::FUNCREF {
self.check_value_type(ValType::Ref(ty.element_type), features, types, offset)?
}
if !ty.element_type.is_reference_type() {
return Err(BinaryReaderError::new(
"element is not reference type",
offset,
));
}
self.check_limits(ty.initial, ty.maximum, offset)?;
if ty.initial > MAX_WASM_TABLE_ENTRIES as u32 {
return Err(BinaryReaderError::new(
@ -766,6 +780,100 @@ impl Module {
.collect::<Result<_>>()
}
fn check_value_type(
&self,
ty: ValType,
features: &WasmFeatures,
types: &TypeList,
offset: usize,
) -> Result<()> {
match features.check_value_type(ty) {
Ok(()) => Ok(()),
Err(e) => Err(BinaryReaderError::new(e, offset)),
}?;
// The above only checks the value type for features.
// We must check it if it's a reference.
match ty {
ValType::Ref(rt) => {
self.check_ref_type(rt, types, offset)?;
}
_ => (),
}
Ok(())
}
fn check_ref_type(&self, ty: RefType, types: &TypeList, offset: usize) -> Result<()> {
// Check that the heap type is valid
match ty.heap_type {
HeapType::Func | HeapType::Extern => (),
HeapType::TypedFunc(type_index) => {
// Just check that the index is valid
self.func_type_at(type_index.into(), types, offset)?;
}
}
Ok(())
}
fn eq_valtypes(&self, ty1: ValType, ty2: ValType, types: &TypeList) -> bool {
match (ty1, ty2) {
(ValType::Ref(rt1), ValType::Ref(rt2)) => {
rt1.nullable == rt2.nullable
&& match (rt1.heap_type, rt2.heap_type) {
(HeapType::Func, HeapType::Func) => true,
(HeapType::Extern, HeapType::Extern) => true,
(HeapType::TypedFunc(n1), HeapType::TypedFunc(n2)) => {
let n1 = self.func_type_at(n1.into(), types, 0).unwrap();
let n2 = self.func_type_at(n2.into(), types, 0).unwrap();
self.eq_fns(n1, n2, types)
}
(_, _) => false,
}
}
_ => ty1 == ty2,
}
}
fn eq_fns(&self, f1: &impl WasmFuncType, f2: &impl WasmFuncType, types: &TypeList) -> bool {
f1.len_inputs() == f2.len_inputs()
&& f2.len_outputs() == f2.len_outputs()
&& f1
.inputs()
.zip(f2.inputs())
.all(|(t1, t2)| self.eq_valtypes(t1, t2, types))
&& f1
.outputs()
.zip(f2.outputs())
.all(|(t1, t2)| self.eq_valtypes(t1, t2, types))
}
pub(crate) fn matches(&self, ty1: ValType, ty2: ValType, types: &TypeList) -> bool {
fn matches_null(null1: bool, null2: bool) -> bool {
(null1 == null2) || null2
}
let matches_heap = |ty1: HeapType, ty2: HeapType, types: &TypeList| -> bool {
match (ty1, ty2) {
(HeapType::TypedFunc(n1), HeapType::TypedFunc(n2)) => {
// Check whether the defined types are (structurally) equivalent.
let n1 = self.func_type_at(n1.into(), types, 0).unwrap();
let n2 = self.func_type_at(n2.into(), types, 0).unwrap();
self.eq_fns(n1, n2, types)
}
(HeapType::TypedFunc(_), HeapType::Func) => true,
(_, _) => ty1 == ty2,
}
};
let matches_ref = |ty1: RefType, ty2: RefType, types: &TypeList| -> bool {
matches_heap(ty1.heap_type, ty2.heap_type, types)
&& matches_null(ty1.nullable, ty2.nullable)
};
match (ty1, ty2) {
(ValType::Ref(rt1), ValType::Ref(rt2)) => matches_ref(rt1, rt2, types),
(_, _) => ty1 == ty2,
}
}
fn check_tag_type(
&self,
ty: &TagType,
@ -793,9 +901,10 @@ impl Module {
&self,
ty: &GlobalType,
features: &WasmFeatures,
types: &TypeList,
offset: usize,
) -> Result<()> {
check_value_type(ty.content_type, features, offset)
self.check_value_type(ty.content_type, features, types, offset)
}
fn check_limits<T>(&self, initial: T, maximum: Option<T>, offset: usize) -> Result<()>
@ -974,14 +1083,27 @@ impl WasmModuleResources for OperatorValidatorResources<'_> {
)
}
fn type_of_function(&self, at: u32) -> Option<&Self::FuncType> {
self.func_type_at(*self.module.functions.get(at as usize)?)
fn type_index_of_function(&self, at: u32) -> Option<u32> {
self.module.functions.get(at as usize).cloned()
}
fn element_type_at(&self, at: u32) -> Option<ValType> {
fn type_of_function(&self, at: u32) -> Option<&Self::FuncType> {
self.func_type_at(self.type_index_of_function(at)?)
}
fn check_value_type(&self, t: ValType, features: &WasmFeatures, offset: usize) -> Result<()> {
self.module
.check_value_type(t, features, self.types, offset)
}
fn element_type_at(&self, at: u32) -> Option<RefType> {
self.module.element_types.get(at as usize).cloned()
}
fn matches(&self, t1: ValType, t2: ValType) -> bool {
self.module.matches(t1, t2, self.types)
}
fn element_count(&self) -> u32 {
self.module.element_types.len() as u32
}
@ -1030,14 +1152,27 @@ impl WasmModuleResources for ValidatorResources {
)
}
fn type_of_function(&self, at: u32) -> Option<&Self::FuncType> {
self.func_type_at(*self.0.functions.get(at as usize)?)
fn type_index_of_function(&self, at: u32) -> Option<u32> {
self.0.functions.get(at as usize).cloned()
}
fn element_type_at(&self, at: u32) -> Option<ValType> {
fn type_of_function(&self, at: u32) -> Option<&Self::FuncType> {
self.func_type_at(self.type_index_of_function(at)?)
}
fn check_value_type(&self, t: ValType, features: &WasmFeatures, offset: usize) -> Result<()> {
self.0
.check_value_type(t, features, self.0.snapshot.as_ref().unwrap(), offset)
}
fn element_type_at(&self, at: u32) -> Option<RefType> {
self.0.element_types.get(at as usize).cloned()
}
fn matches(&self, t1: ValType, t2: ValType) -> bool {
self.0.matches(t1, t2, self.0.snapshot.as_ref().unwrap())
}
fn element_count(&self) -> u32 {
self.0.element_types.len() as u32
}

Просмотреть файл

@ -119,7 +119,8 @@ impl<T: WasmModuleResources> FuncValidator<T> {
/// This should be used if the application is already reading local
/// definitions and there's no need to re-parse the function again.
pub fn define_locals(&mut self, offset: usize, count: u32, ty: ValType) -> Result<()> {
self.validator.define_locals(offset, count, ty)
self.validator
.define_locals(offset, count, ty, &self.resources)
}
/// Validates the next operator in a function.
@ -269,10 +270,24 @@ mod tests {
fn func_type_at(&self, _type_idx: u32) -> Option<&Self::FuncType> {
Some(&EmptyFuncType)
}
fn type_index_of_function(&self, _at: u32) -> Option<u32> {
todo!()
}
fn type_of_function(&self, _func_idx: u32) -> Option<&Self::FuncType> {
todo!()
}
fn element_type_at(&self, _at: u32) -> Option<ValType> {
fn check_value_type(
&self,
_t: ValType,
_features: &WasmFeatures,
_offset: usize,
) -> Result<()> {
Ok(())
}
fn element_type_at(&self, _at: u32) -> Option<crate::RefType> {
todo!()
}
fn matches(&self, _t1: ValType, _t2: ValType) -> bool {
todo!()
}
fn element_count(&self) -> u32 {

Просмотреть файл

@ -23,25 +23,30 @@
// the various methods here.
use crate::{
limits::MAX_WASM_FUNCTION_LOCALS, BinaryReaderError, BlockType, BrTable, Ieee32, Ieee64,
MemArg, Result, ValType, VisitOperator, WasmFeatures, WasmFuncType, WasmModuleResources, V128,
limits::MAX_WASM_FUNCTION_LOCALS, BinaryReaderError, BlockType, BrTable, HeapType, Ieee32,
Ieee64, MemArg, RefType, Result, ValType, VisitOperator, WasmFeatures, WasmFuncType,
WasmModuleResources, V128,
};
use std::ops::{Deref, DerefMut};
pub(crate) struct OperatorValidator {
pub(super) locals: Locals,
pub(super) local_inits: Vec<bool>,
// This is a list of flags for wasm features which are used to gate various
// instructions.
pub(crate) features: WasmFeatures,
// Temporary storage used during the validation of `br_table`.
br_table_tmp: Vec<Option<ValType>>,
br_table_tmp: Vec<MaybeType>,
/// The `control` list is the list of blocks that we're currently in.
control: Vec<Frame>,
/// The `operands` is the current type stack.
operands: Vec<Option<ValType>>,
operands: Vec<MaybeType>,
/// When local_inits is modified, the relevant index is recorded here to be
/// undone when control pops
inits: Vec<u32>,
/// Offset of the `end` instruction which emptied the `control` stack, which
/// must be the end of the function.
@ -92,6 +97,8 @@ pub struct Frame {
pub height: usize,
/// Whether this frame is unreachable so far.
pub unreachable: bool,
/// The number of initializations in the stack at the time of its creation
pub init_height: usize,
}
/// The kind of a control flow [`Frame`].
@ -133,25 +140,55 @@ struct OperatorValidatorTemp<'validator, 'resources, T> {
#[derive(Default)]
pub struct OperatorValidatorAllocations {
br_table_tmp: Vec<Option<ValType>>,
br_table_tmp: Vec<MaybeType>,
control: Vec<Frame>,
operands: Vec<Option<ValType>>,
operands: Vec<MaybeType>,
local_inits: Vec<bool>,
inits: Vec<u32>,
locals_first: Vec<ValType>,
locals_all: Vec<(u32, ValType)>,
}
/// Type storage within the validator.
///
/// This is used to manage the operand stack and notably isn't just `ValType` to
/// handle unreachable code and the "bottom" type.
#[derive(Debug, Copy, Clone)]
enum MaybeType {
Bot,
HeapBot,
Type(ValType),
}
// The validator is pretty performance-sensitive and `MaybeType` is the main
// unit of storage, so assert that it doesn't exceed 4 bytes which is the
// current expected size.
const _: () = {
assert!(std::mem::size_of::<MaybeType>() == 4);
};
impl From<ValType> for MaybeType {
fn from(ty: ValType) -> MaybeType {
MaybeType::Type(ty)
}
}
impl OperatorValidator {
fn new(features: &WasmFeatures, allocs: OperatorValidatorAllocations) -> Self {
let OperatorValidatorAllocations {
br_table_tmp,
control,
operands,
local_inits,
inits,
locals_first,
locals_all,
} = allocs;
debug_assert!(br_table_tmp.is_empty());
debug_assert!(control.is_empty());
debug_assert!(operands.is_empty());
debug_assert!(local_inits.is_empty());
debug_assert!(inits.is_empty());
debug_assert!(locals_first.is_empty());
debug_assert!(locals_all.is_empty());
OperatorValidator {
@ -160,6 +197,8 @@ impl OperatorValidator {
first: locals_first,
all: locals_all,
},
local_inits,
inits,
features: *features,
br_table_tmp,
operands,
@ -189,6 +228,7 @@ impl OperatorValidator {
block_type: BlockType::FuncType(ty),
height: 0,
unreachable: false,
init_height: 0,
});
let params = OperatorValidatorTemp {
// This offset is used by the `func_type_at` and `inputs`.
@ -200,6 +240,7 @@ impl OperatorValidator {
.inputs();
for ty in params {
ret.locals.define(1, ty);
ret.local_inits.push(true);
}
Ok(ret)
}
@ -218,14 +259,19 @@ impl OperatorValidator {
block_type: BlockType::Type(ty),
height: 0,
unreachable: false,
init_height: 0,
});
ret
}
pub fn define_locals(&mut self, offset: usize, count: u32, ty: ValType) -> Result<()> {
self.features
.check_value_type(ty)
.map_err(|e| BinaryReaderError::new(e, offset))?;
pub fn define_locals(
&mut self,
offset: usize,
count: u32,
ty: ValType,
resources: &impl WasmModuleResources,
) -> Result<()> {
resources.check_value_type(ty, &self.features, offset)?;
if count == 0 {
return Ok(());
}
@ -235,6 +281,8 @@ impl OperatorValidator {
offset,
));
}
self.local_inits
.resize(self.local_inits.len() + count as usize, ty.is_defaultable());
Ok(())
}
@ -254,7 +302,10 @@ impl OperatorValidator {
///
/// A `depth` of 0 will refer to the last operand on the stack.
pub fn peek_operand_at(&self, depth: usize) -> Option<Option<ValType>> {
self.operands.iter().rev().nth(depth).copied()
Some(match self.operands.iter().rev().nth(depth)? {
MaybeType::Type(t) => Some(*t),
MaybeType::Bot | MaybeType::HeapBot => None,
})
}
/// Returns the number of frames on the control flow stack.
@ -314,6 +365,8 @@ impl OperatorValidator {
br_table_tmp: truncate(self.br_table_tmp),
control: truncate(self.control),
operands: truncate(self.operands),
local_inits: truncate(self.local_inits),
inits: truncate(self.inits),
locals_first: truncate(self.locals.first),
locals_all: truncate(self.locals.all),
}
@ -341,7 +394,7 @@ impl<'resources, R: WasmModuleResources> OperatorValidatorTemp<'_, 'resources, R
/// Otherwise the push operation always succeeds.
fn push_operand<T>(&mut self, ty: T) -> Result<()>
where
T: Into<Option<ValType>>,
T: Into<MaybeType>,
{
let maybe_ty = ty.into();
self.operands.push(maybe_ty);
@ -355,7 +408,7 @@ impl<'resources, R: WasmModuleResources> OperatorValidatorTemp<'_, 'resources, R
/// simply that something is needed to be popped.
///
/// If `expected` is `Some(T)` then this will be guaranteed to return
/// `Some(T)`, and it will only return success if the current block is
/// `T`, and it will only return success if the current block is
/// unreachable or if `T` was found at the top of the operand stack.
///
/// If `expected` is `None` then it indicates that something must be on the
@ -366,7 +419,7 @@ impl<'resources, R: WasmModuleResources> OperatorValidatorTemp<'_, 'resources, R
/// matches `expected`. If `None` is returned then it means that `None` was
/// expected and a type was successfully popped, but its exact type is
/// indeterminate because the current block is unreachable.
fn pop_operand(&mut self, expected: Option<ValType>) -> Result<Option<ValType>> {
fn pop_operand(&mut self, expected: Option<ValType>) -> Result<MaybeType> {
// This method is one of the hottest methods in the validator so to
// improve codegen this method contains a fast-path success case where
// if the top operand on the stack is as expected it's returned
@ -378,17 +431,18 @@ impl<'resources, R: WasmModuleResources> OperatorValidatorTemp<'_, 'resources, R
// matched against the state of the world to see if we could actually
// pop it. If we shouldn't have popped it then it's passed to the slow
// path to get pushed back onto the stack.
let popped = if let Some(actual_ty) = self.operands.pop() {
if actual_ty == expected {
if let Some(control) = self.control.last() {
if self.operands.len() >= control.height {
return Ok(actual_ty);
let popped = match self.operands.pop() {
Some(MaybeType::Type(actual_ty)) => {
if Some(actual_ty) == expected {
if let Some(control) = self.control.last() {
if self.operands.len() >= control.height {
return Ok(MaybeType::Type(actual_ty));
}
}
}
Some(MaybeType::Type(actual_ty))
}
Some(actual_ty)
} else {
None
other => other,
};
self._pop_operand(expected, popped)
@ -401,17 +455,17 @@ impl<'resources, R: WasmModuleResources> OperatorValidatorTemp<'_, 'resources, R
fn _pop_operand(
&mut self,
expected: Option<ValType>,
popped: Option<Option<ValType>>,
) -> Result<Option<ValType>> {
popped: Option<MaybeType>,
) -> Result<MaybeType> {
self.operands.extend(popped);
let control = match self.control.last() {
Some(c) => c,
None => return Err(self.err_beyond_end(self.offset)),
};
let actual = if self.operands.len() == control.height {
if control.unreachable {
None
} else {
let actual = if self.operands.len() == control.height && control.unreachable {
MaybeType::Bot
} else {
if self.operands.len() == control.height {
let desc = match expected {
Some(ty) => ty_to_str(ty),
None => "a type",
@ -420,23 +474,59 @@ impl<'resources, R: WasmModuleResources> OperatorValidatorTemp<'_, 'resources, R
self.offset,
"type mismatch: expected {desc} but nothing on stack"
)
} else {
self.operands.pop().unwrap()
}
} else {
self.operands.pop().unwrap()
};
if let (Some(actual_ty), Some(expected_ty)) = (actual, expected) {
if actual_ty != expected_ty {
bail!(
self.offset,
"type mismatch: expected {}, found {}",
ty_to_str(expected_ty),
ty_to_str(actual_ty)
)
if let Some(expected) = expected {
match (actual, expected) {
// The bottom type matches all expectations
(MaybeType::Bot, _)
// The "heap bottom" type only matches other references types,
// but not any integer types.
| (MaybeType::HeapBot, ValType::Ref(_)) => {}
// Use the `matches` predicate to test if a found type matches
// the expectation.
(MaybeType::Type(actual), expected) => {
if !self.resources.matches(actual, expected) {
bail!(
self.offset,
"type mismatch: expected {}, found {}",
ty_to_str(expected),
ty_to_str(actual)
);
}
}
// A "heap bottom" type cannot match any numeric types.
(
MaybeType::HeapBot,
ValType::I32 | ValType::I64 | ValType::F32 | ValType::F64 | ValType::V128,
) => {
bail!(
self.offset,
"type mismatche: expected {}, found heap type",
ty_to_str(expected)
)
}
}
}
Ok(actual)
}
fn pop_ref(&mut self) -> Result<Option<RefType>> {
match self.pop_operand(None)? {
MaybeType::Bot | MaybeType::HeapBot => Ok(None),
MaybeType::Type(ValType::Ref(rt)) => Ok(Some(rt)),
MaybeType::Type(ty) => bail!(
self.offset,
"type mismatch: expected ref but found {}",
ty_to_str(ty)
),
}
}
/// Fetches the type for the local at `idx`, returning an error if it's out
/// of bounds.
fn local(&self, idx: u32) -> Result<ValType> {
@ -473,11 +563,13 @@ impl<'resources, R: WasmModuleResources> OperatorValidatorTemp<'_, 'resources, R
// Push a new frame which has a snapshot of the height of the current
// operand stack.
let height = self.operands.len();
let init_height = self.inits.len();
self.control.push(Frame {
kind,
block_type: ty,
height,
unreachable: false,
init_height,
});
// All of the parameters are now also available in this control frame,
// so we push them here in order.
@ -500,6 +592,12 @@ impl<'resources, R: WasmModuleResources> OperatorValidatorTemp<'_, 'resources, R
};
let ty = frame.block_type;
let height = frame.height;
let init_height = frame.init_height;
// reset_locals in the spec
for init in self.inits.split_off(init_height) {
self.local_inits[init as usize] = false;
}
// Pop all the result types, in reverse order, from the operand stack.
// These types will, possibly, be transferred to the next frame.
@ -587,10 +685,9 @@ impl<'resources, R: WasmModuleResources> OperatorValidatorTemp<'_, 'resources, R
fn check_block_type(&self, ty: BlockType) -> Result<()> {
match ty {
BlockType::Empty => Ok(()),
BlockType::Type(ty) => self
.features
.check_value_type(ty)
.map_err(|e| BinaryReaderError::new(e, self.offset)),
BlockType::Type(t) => self
.resources
.check_value_type(t, &self.features, self.offset),
BlockType::FuncType(idx) => {
if !self.features.multi_value {
bail!(
@ -608,13 +705,25 @@ impl<'resources, R: WasmModuleResources> OperatorValidatorTemp<'_, 'resources, R
/// Validates a `call` instruction, ensuring that the function index is
/// in-bounds and the right types are on the stack to call the function.
fn check_call(&mut self, function_index: u32) -> Result<()> {
let ty = match self.resources.type_of_function(function_index) {
let ty = match self.resources.type_index_of_function(function_index) {
Some(i) => i,
None => {
bail!(
self.offset,
"unknown function {}: function index out of bounds",
function_index
"unknown function {function_index}: function index out of bounds",
);
}
};
self.check_call_ty(ty)
}
fn check_call_ty(&mut self, type_index: u32) -> Result<()> {
let ty = match self.resources.func_type_at(type_index) {
Some(i) => i,
None => {
bail!(
self.offset,
"unknown type {type_index}: type index out of bounds",
);
}
};
@ -634,10 +743,13 @@ impl<'resources, R: WasmModuleResources> OperatorValidatorTemp<'_, 'resources, R
bail!(self.offset, "unknown table: table index out of bounds");
}
Some(tab) => {
if tab.element_type != ValType::FuncRef {
if !self
.resources
.matches(ValType::Ref(tab.element_type), ValType::FUNCREF)
{
bail!(
self.offset,
"indirect calls must go through a table of funcref"
"indirect calls must go through a table with type <= funcref",
);
}
}
@ -780,14 +892,6 @@ impl<'resources, R: WasmModuleResources> OperatorValidatorTemp<'_, 'resources, R
self.check_v128_binary_op()
}
/// Checks a [`V128`] binary operator.
fn check_v128_relaxed_binary_op(&mut self) -> Result<()> {
self.pop_operand(Some(ValType::V128))?;
self.pop_operand(Some(ValType::V128))?;
self.push_operand(ValType::V128)?;
Ok(())
}
/// Checks a [`V128`] binary operator.
fn check_v128_unary_op(&mut self) -> Result<()> {
self.pop_operand(Some(ValType::V128))?;
@ -801,15 +905,8 @@ impl<'resources, R: WasmModuleResources> OperatorValidatorTemp<'_, 'resources, R
self.check_v128_unary_op()
}
/// Checks a [`V128`] binary operator.
fn check_v128_relaxed_unary_op(&mut self) -> Result<()> {
self.pop_operand(Some(ValType::V128))?;
self.push_operand(ValType::V128)?;
Ok(())
}
/// Checks a [`V128`] relaxed ternary operator.
fn check_v128_relaxed_ternary_op(&mut self) -> Result<()> {
fn check_v128_ternary_op(&mut self) -> Result<()> {
self.pop_operand(Some(ValType::V128))?;
self.pop_operand(Some(ValType::V128))?;
self.pop_operand(Some(ValType::V128))?;
@ -879,15 +976,31 @@ impl<'resources, R: WasmModuleResources> OperatorValidatorTemp<'_, 'resources, R
}
}
fn ty_to_str(ty: ValType) -> &'static str {
pub fn ty_to_str(ty: ValType) -> &'static str {
match ty {
ValType::I32 => "i32",
ValType::I64 => "i64",
ValType::F32 => "f32",
ValType::F64 => "f64",
ValType::V128 => "v128",
ValType::FuncRef => "funcref",
ValType::ExternRef => "externref",
ValType::FUNCREF => "funcref",
ValType::EXTERNREF => "externref",
ValType::Ref(RefType {
nullable: false,
heap_type: HeapType::Func,
}) => "(ref func)",
ValType::Ref(RefType {
nullable: false,
heap_type: HeapType::Extern,
}) => "(ref extern)",
ValType::Ref(RefType {
nullable: false,
heap_type: HeapType::TypedFunc(_),
}) => "(ref $type)",
ValType::Ref(RefType {
nullable: true,
heap_type: HeapType::TypedFunc(_),
}) => "(ref null $type)",
}
}
@ -936,6 +1049,7 @@ macro_rules! validate_proposal {
(desc sign_extension) => ("sign extension operations");
(desc exceptions) => ("exceptions");
(desc tail_call) => ("tail calls");
(desc function_references) => ("function references");
(desc memory_control) => ("memory control");
}
@ -1009,11 +1123,13 @@ where
}
// Start a new frame and push `exnref` value.
let height = self.operands.len();
let init_height = self.inits.len();
self.control.push(Frame {
kind: FrameKind::Catch,
block_type: frame.block_type,
height,
unreachable: false,
init_height,
});
// Push exception argument types.
let ty = self.tag_at(index)?;
@ -1071,11 +1187,13 @@ where
bail!(self.offset, "catch_all found outside of a `try` block");
}
let height = self.operands.len();
let init_height = self.inits.len();
self.control.push(Frame {
kind: FrameKind::CatchAll,
block_type: frame.block_type,
height,
unreachable: false,
init_height,
});
Ok(())
}
@ -1162,6 +1280,39 @@ where
self.check_return()?;
Ok(())
}
fn visit_call_ref(&mut self, hty: HeapType) -> Self::Output {
self.resources
.check_heap_type(hty, &self.features, self.offset)?;
// If `None` is popped then that means a "bottom" type was popped which
// is always considered equivalent to the `hty` tag.
if let Some(rt) = self.pop_ref()? {
let expected = RefType {
nullable: true,
heap_type: hty,
};
if !self
.resources
.matches(ValType::Ref(rt), ValType::Ref(expected))
{
bail!(
self.offset,
"type mismatch: funcref on stack does not match specified type",
);
}
}
match hty {
HeapType::TypedFunc(type_index) => self.check_call_ty(type_index.into())?,
_ => bail!(
self.offset,
"type mismatch: instruction requires function reference type",
),
}
Ok(())
}
fn visit_return_call_ref(&mut self, hty: HeapType) -> Self::Output {
self.visit_call_ref(hty)?;
self.check_return()
}
fn visit_call_indirect(
&mut self,
index: u32,
@ -1190,36 +1341,42 @@ where
self.pop_operand(Some(ValType::I32))?;
let ty1 = self.pop_operand(None)?;
let ty2 = self.pop_operand(None)?;
fn is_num(ty: Option<ValType>) -> bool {
matches!(
ty,
Some(ValType::I32)
| Some(ValType::I64)
| Some(ValType::F32)
| Some(ValType::F64)
| Some(ValType::V128)
| None
)
}
if !is_num(ty1) || !is_num(ty2) {
bail!(
self.offset,
"type mismatch: select only takes integral types"
)
}
if ty1 != ty2 && ty1.is_some() && ty2.is_some() {
bail!(
self.offset,
"type mismatch: select operands have different types"
)
}
self.push_operand(ty1.or(ty2))?;
let ty = match (ty1, ty2) {
// All heap-related types aren't allowed with the `select`
// instruction
(MaybeType::HeapBot, _)
| (_, MaybeType::HeapBot)
| (MaybeType::Type(ValType::Ref(_)), _)
| (_, MaybeType::Type(ValType::Ref(_))) => {
bail!(
self.offset,
"type mismatch: select only takes integral types"
)
}
// If one operand is the "bottom" type then whatever the other
// operand is is the result of the `select`
(MaybeType::Bot, t) | (t, MaybeType::Bot) => t,
// Otherwise these are two integral types and they must match for
// `select` to typecheck.
(t @ MaybeType::Type(t1), MaybeType::Type(t2)) => {
if t1 != t2 {
bail!(
self.offset,
"type mismatch: select operands have different types"
);
}
t
}
};
self.push_operand(ty)?;
Ok(())
}
fn visit_typed_select(&mut self, ty: ValType) -> Self::Output {
self.features
.check_value_type(ty)
.map_err(|e| BinaryReaderError::new(e, self.offset))?;
self.resources
.check_value_type(ty, &self.features, self.offset)?;
self.pop_operand(Some(ValType::I32))?;
self.pop_operand(Some(ty))?;
self.pop_operand(Some(ty))?;
@ -1228,17 +1385,29 @@ where
}
fn visit_local_get(&mut self, local_index: u32) -> Self::Output {
let ty = self.local(local_index)?;
if !self.local_inits[local_index as usize] {
bail!(self.offset, "uninitialized local: {}", local_index);
}
self.push_operand(ty)?;
Ok(())
}
fn visit_local_set(&mut self, local_index: u32) -> Self::Output {
let ty = self.local(local_index)?;
self.pop_operand(Some(ty))?;
if !self.local_inits[local_index as usize] {
self.local_inits[local_index as usize] = true;
self.inits.push(local_index);
}
Ok(())
}
fn visit_local_tee(&mut self, local_index: u32) -> Self::Output {
let ty = self.local(local_index)?;
self.pop_operand(Some(ty))?;
if !self.local_inits[local_index as usize] {
self.local_inits[local_index as usize] = true;
self.inits.push(local_index);
}
self.push_operand(ty)?;
Ok(())
}
@ -2049,43 +2218,119 @@ where
fn visit_atomic_fence(&mut self) -> Self::Output {
Ok(())
}
fn visit_ref_null(&mut self, ty: ValType) -> Self::Output {
self.features
.check_value_type(ty)
.map_err(|e| BinaryReaderError::new(e, self.offset))?;
if !ty.is_reference_type() {
bail!(self.offset, "invalid non-reference type in ref.null");
fn visit_ref_null(&mut self, heap_type: HeapType) -> Self::Output {
self.resources
.check_heap_type(heap_type, &self.features, self.offset)?;
self.push_operand(ValType::Ref(RefType {
nullable: true,
heap_type,
}))?;
Ok(())
}
fn visit_ref_as_non_null(&mut self) -> Self::Output {
let ty = match self.pop_ref()? {
Some(ty) => MaybeType::Type(ValType::Ref(RefType {
nullable: false,
heap_type: ty.heap_type,
})),
None => MaybeType::HeapBot,
};
self.push_operand(ty)?;
Ok(())
}
fn visit_br_on_null(&mut self, relative_depth: u32) -> Self::Output {
let ty = match self.pop_ref()? {
None => MaybeType::HeapBot,
Some(ty) => MaybeType::Type(ValType::Ref(RefType {
nullable: false,
heap_type: ty.heap_type,
})),
};
let (ft, kind) = self.jump(relative_depth)?;
for ty in self.label_types(ft, kind)?.rev() {
self.pop_operand(Some(ty))?;
}
for ty in self.label_types(ft, kind)? {
self.push_operand(ty)?;
}
self.push_operand(ty)?;
Ok(())
}
fn visit_ref_is_null(&mut self) -> Self::Output {
match self.pop_operand(None)? {
None => {}
Some(t) => {
if !t.is_reference_type() {
fn visit_br_on_non_null(&mut self, relative_depth: u32) -> Self::Output {
let ty = self.pop_ref()?;
let (ft, kind) = self.jump(relative_depth)?;
let mut lts = self.label_types(ft, kind)?;
match (lts.next_back(), ty) {
(None, _) => bail!(
self.offset,
"type mismatch: br_on_non_null target has no label types",
),
(Some(ValType::Ref(_)), None) => {}
(Some(rt1 @ ValType::Ref(_)), Some(rt0)) => {
// Switch rt0, our popped type, to a non-nullable type and
// perform the match because if the branch is taken it's a
// non-null value.
let ty = RefType {
nullable: false,
heap_type: rt0.heap_type,
};
if !self.resources.matches(ty.into(), rt1) {
bail!(
self.offset,
"type mismatch: invalid reference type in ref.is_null"
);
"type mismatch: expected {} but found {}",
ty_to_str(rt0.into()),
ty_to_str(rt1)
)
}
}
(Some(_), _) => bail!(
self.offset,
"type mismatch: br_on_non_null target does not end with heap type",
),
}
for ty in self.label_types(ft, kind)?.rev().skip(1) {
self.pop_operand(Some(ty))?;
}
for ty in lts {
self.push_operand(ty)?;
}
Ok(())
}
fn visit_ref_is_null(&mut self) -> Self::Output {
self.pop_ref()?;
self.push_operand(ValType::I32)?;
Ok(())
}
fn visit_ref_func(&mut self, function_index: u32) -> Self::Output {
if self.resources.type_of_function(function_index).is_none() {
bail!(
let type_index = match self.resources.type_index_of_function(function_index) {
Some(idx) => idx,
None => bail!(
self.offset,
"unknown function {}: function index out of bounds",
function_index,
);
}
),
};
if !self.resources.is_function_referenced(function_index) {
bail!(self.offset, "undeclared function reference");
}
self.push_operand(ValType::FuncRef)?;
// FIXME(#924) this should not be conditional based on enabled
// proposals.
if self.features.function_references {
let heap_type = HeapType::TypedFunc(match type_index.try_into() {
Ok(packed) => packed,
Err(_) => {
bail!(self.offset, "type index of `ref.func` target too large")
}
});
self.push_operand(ValType::Ref(RefType {
nullable: false,
heap_type,
}))?;
} else {
self.push_operand(ValType::FUNCREF)?;
}
Ok(())
}
fn visit_v128_load(&mut self, memarg: MemArg) -> Self::Output {
@ -2296,24 +2541,6 @@ where
fn visit_f64x2_pmax(&mut self) -> Self::Output {
self.check_v128_fbinary_op()
}
fn visit_f32x4_relaxed_min(&mut self) -> Self::Output {
self.check_v128_relaxed_binary_op()
}
fn visit_f32x4_relaxed_max(&mut self) -> Self::Output {
self.check_v128_relaxed_binary_op()
}
fn visit_f64x2_relaxed_min(&mut self) -> Self::Output {
self.check_v128_relaxed_binary_op()
}
fn visit_f64x2_relaxed_max(&mut self) -> Self::Output {
self.check_v128_relaxed_binary_op()
}
fn visit_i16x8_relaxed_q15mulr_s(&mut self) -> Self::Output {
self.check_v128_relaxed_binary_op()
}
fn visit_i16x8_dot_i8x16_i7x16_s(&mut self) -> Self::Output {
self.check_v128_relaxed_binary_op()
}
fn visit_i8x16_eq(&mut self) -> Self::Output {
self.check_v128_binary_op()
}
@ -2737,18 +2964,6 @@ where
fn visit_i32x4_extadd_pairwise_i16x8_u(&mut self) -> Self::Output {
self.check_v128_unary_op()
}
fn visit_i32x4_relaxed_trunc_sat_f32x4_s(&mut self) -> Self::Output {
self.check_v128_relaxed_unary_op()
}
fn visit_i32x4_relaxed_trunc_sat_f32x4_u(&mut self) -> Self::Output {
self.check_v128_relaxed_unary_op()
}
fn visit_i32x4_relaxed_trunc_sat_f64x2_s_zero(&mut self) -> Self::Output {
self.check_v128_relaxed_unary_op()
}
fn visit_i32x4_relaxed_trunc_sat_f64x2_u_zero(&mut self) -> Self::Output {
self.check_v128_relaxed_unary_op()
}
fn visit_v128_bitselect(&mut self) -> Self::Output {
self.pop_operand(Some(ValType::V128))?;
self.pop_operand(Some(ValType::V128))?;
@ -2756,35 +2971,68 @@ where
self.push_operand(ValType::V128)?;
Ok(())
}
fn visit_f32x4_relaxed_fma(&mut self) -> Self::Output {
self.check_v128_relaxed_ternary_op()
fn visit_i8x16_relaxed_swizzle(&mut self) -> Self::Output {
self.pop_operand(Some(ValType::V128))?;
self.pop_operand(Some(ValType::V128))?;
self.push_operand(ValType::V128)?;
Ok(())
}
fn visit_f32x4_relaxed_fnma(&mut self) -> Self::Output {
self.check_v128_relaxed_ternary_op()
fn visit_i32x4_relaxed_trunc_f32x4_s(&mut self) -> Self::Output {
self.check_v128_unary_op()
}
fn visit_f64x2_relaxed_fma(&mut self) -> Self::Output {
self.check_v128_relaxed_ternary_op()
fn visit_i32x4_relaxed_trunc_f32x4_u(&mut self) -> Self::Output {
self.check_v128_unary_op()
}
fn visit_f64x2_relaxed_fnma(&mut self) -> Self::Output {
self.check_v128_relaxed_ternary_op()
fn visit_i32x4_relaxed_trunc_f64x2_s_zero(&mut self) -> Self::Output {
self.check_v128_unary_op()
}
fn visit_i32x4_relaxed_trunc_f64x2_u_zero(&mut self) -> Self::Output {
self.check_v128_unary_op()
}
fn visit_f32x4_relaxed_madd(&mut self) -> Self::Output {
self.check_v128_ternary_op()
}
fn visit_f32x4_relaxed_nmadd(&mut self) -> Self::Output {
self.check_v128_ternary_op()
}
fn visit_f64x2_relaxed_madd(&mut self) -> Self::Output {
self.check_v128_ternary_op()
}
fn visit_f64x2_relaxed_nmadd(&mut self) -> Self::Output {
self.check_v128_ternary_op()
}
fn visit_i8x16_relaxed_laneselect(&mut self) -> Self::Output {
self.check_v128_relaxed_ternary_op()
self.check_v128_ternary_op()
}
fn visit_i16x8_relaxed_laneselect(&mut self) -> Self::Output {
self.check_v128_relaxed_ternary_op()
self.check_v128_ternary_op()
}
fn visit_i32x4_relaxed_laneselect(&mut self) -> Self::Output {
self.check_v128_relaxed_ternary_op()
self.check_v128_ternary_op()
}
fn visit_i64x2_relaxed_laneselect(&mut self) -> Self::Output {
self.check_v128_relaxed_ternary_op()
self.check_v128_ternary_op()
}
fn visit_i32x4_dot_i8x16_i7x16_add_s(&mut self) -> Self::Output {
self.check_v128_relaxed_ternary_op()
fn visit_f32x4_relaxed_min(&mut self) -> Self::Output {
self.check_v128_binary_op()
}
fn visit_f32x4_relaxed_dot_bf16x8_add_f32x4(&mut self) -> Self::Output {
self.check_v128_relaxed_ternary_op()
fn visit_f32x4_relaxed_max(&mut self) -> Self::Output {
self.check_v128_binary_op()
}
fn visit_f64x2_relaxed_min(&mut self) -> Self::Output {
self.check_v128_binary_op()
}
fn visit_f64x2_relaxed_max(&mut self) -> Self::Output {
self.check_v128_binary_op()
}
fn visit_i16x8_relaxed_q15mulr_s(&mut self) -> Self::Output {
self.check_v128_binary_op()
}
fn visit_i16x8_relaxed_dot_i8x16_i7x16_s(&mut self) -> Self::Output {
self.check_v128_binary_op()
}
fn visit_i32x4_relaxed_dot_i8x16_i7x16_add_s(&mut self) -> Self::Output {
self.check_v128_ternary_op()
}
fn visit_v128_any_true(&mut self) -> Self::Output {
self.check_v128_bitmask_op()
@ -2855,12 +3103,6 @@ where
self.push_operand(ValType::V128)?;
Ok(())
}
fn visit_i8x16_relaxed_swizzle(&mut self) -> Self::Output {
self.pop_operand(Some(ValType::V128))?;
self.pop_operand(Some(ValType::V128))?;
self.push_operand(ValType::V128)?;
Ok(())
}
fn visit_i8x16_shuffle(&mut self, lanes: [u8; 16]) -> Self::Output {
self.pop_operand(Some(ValType::V128))?;
self.pop_operand(Some(ValType::V128))?;
@ -3070,7 +3312,10 @@ where
(Some(a), Some(b)) => (a, b),
_ => bail!(self.offset, "table index out of bounds"),
};
if src.element_type != dst.element_type {
if !self.resources.matches(
ValType::Ref(src.element_type),
ValType::Ref(dst.element_type),
) {
bail!(self.offset, "type mismatch");
}
self.pop_operand(Some(ValType::I32))?;
@ -3084,7 +3329,7 @@ where
None => bail!(self.offset, "table index out of bounds"),
};
self.pop_operand(Some(ValType::I32))?;
self.push_operand(ty)?;
self.push_operand(ValType::Ref(ty))?;
Ok(())
}
fn visit_table_set(&mut self, table: u32) -> Self::Output {
@ -3092,7 +3337,7 @@ where
Some(ty) => ty.element_type,
None => bail!(self.offset, "table index out of bounds"),
};
self.pop_operand(Some(ty))?;
self.pop_operand(Some(ValType::Ref(ty)))?;
self.pop_operand(Some(ValType::I32))?;
Ok(())
}
@ -3102,7 +3347,7 @@ where
None => bail!(self.offset, "table index out of bounds"),
};
self.pop_operand(Some(ValType::I32))?;
self.pop_operand(Some(ty))?;
self.pop_operand(Some(ValType::Ref(ty)))?;
self.push_operand(ValType::I32)?;
Ok(())
}
@ -3119,7 +3364,7 @@ where
None => bail!(self.offset, "table index out of bounds"),
};
self.pop_operand(Some(ValType::I32))?;
self.pop_operand(Some(ty))?;
self.pop_operand(Some(ValType::Ref(ty)))?;
self.pop_operand(Some(ValType::I32))?;
Ok(())
}

Просмотреть файл

@ -2,8 +2,8 @@
use super::{component::ComponentState, core::Module};
use crate::{
ComponentExport, ComponentImport, Export, ExternalKind, FuncType, GlobalType, Import,
MemoryType, PrimitiveValType, TableType, TypeRef, ValType,
Export, ExternalKind, FuncType, GlobalType, Import, MemoryType, PrimitiveValType, RefType,
TableType, TypeRef, ValType,
};
use indexmap::{IndexMap, IndexSet};
use std::collections::HashMap;
@ -1477,7 +1477,7 @@ impl<'a> TypesRef<'a> {
///
/// Returns `None` if the type index is out of bounds or the type has not
/// been parsed yet.
pub fn element_at(&self, index: u32) -> Option<ValType> {
pub fn element_at(&self, index: u32) -> Option<RefType> {
match &self.kind {
TypesRefKind::Module(module) => module.element_types.get(index as usize).copied(),
TypesRefKind::Component(_) => None,
@ -1615,29 +1615,12 @@ impl<'a> TypesRef<'a> {
}
/// Gets the component entity type for the given component import.
pub fn component_entity_type_from_import(
&self,
import: &ComponentImport,
) -> Option<ComponentEntityType> {
pub fn component_entity_type_of_extern(&self, name: &str) -> Option<ComponentEntityType> {
match &self.kind {
TypesRefKind::Module(_) => None,
TypesRefKind::Component(component) => {
let key = KebabStr::new(import.name)?;
Some(component.imports.get(key)?.1)
}
}
}
/// Gets the component entity type from the given component export.
pub fn component_entity_type_from_export(
&self,
export: &ComponentExport,
) -> Option<ComponentEntityType> {
match &self.kind {
TypesRefKind::Module(_) => None,
TypesRefKind::Component(component) => {
let key = KebabStr::new(export.name)?;
Some(component.exports.get(key)?.1)
let key = KebabStr::new(name)?;
Some(component.externs.get(key)?.1)
}
}
}
@ -1785,8 +1768,11 @@ impl Types {
/// Gets the type of an element segment at the given element segment index.
///
/// Returns `None` if the index is out of bounds.
pub fn element_at(&self, index: u32) -> Option<ValType> {
self.as_ref().element_at(index)
pub fn element_at(&self, index: u32) -> Option<RefType> {
match &self.kind {
TypesKind::Module(module) => module.element_types.get(index as usize).copied(),
TypesKind::Component(_) => None,
}
}
/// Gets the count of element segments.
@ -1897,20 +1883,10 @@ impl Types {
self.as_ref().entity_type_from_export(export)
}
/// Gets the component entity type for the given component import.
pub fn component_entity_type_from_import(
&self,
import: &ComponentImport,
) -> Option<ComponentEntityType> {
self.as_ref().component_entity_type_from_import(import)
}
/// Gets the component entity type from the given component export.
pub fn component_entity_type_from_export(
&self,
export: &ComponentExport,
) -> Option<ComponentEntityType> {
self.as_ref().component_entity_type_from_export(export)
/// Gets the component entity type for the given component import or export
/// name.
pub fn component_entity_type_of_extern(&self, name: &str) -> Option<ComponentEntityType> {
self.as_ref().component_entity_type_of_extern(name)
}
/// Attempts to lookup the type id that `ty` is an alias of.

32
third_party/rust/wasmparser/tests/big-module.rs поставляемый Normal file
Просмотреть файл

@ -0,0 +1,32 @@
use wasm_encoder::*;
#[test]
fn big_type_indices() {
const N: u32 = 100_000;
let mut module = Module::new();
let mut types = TypeSection::new();
for _ in 0..N {
types.function([], []);
}
module.section(&types);
let mut funcs = FunctionSection::new();
funcs.function(N - 1);
module.section(&funcs);
let mut elems = ElementSection::new();
elems.declared(RefType::FUNCREF, Elements::Functions(&[0]));
module.section(&elems);
let mut code = CodeSection::new();
let mut body = Function::new([]);
body.instruction(&Instruction::RefFunc(0));
body.instruction(&Instruction::Drop);
body.instruction(&Instruction::End);
code.function(&body);
module.section(&code);
let wasm = module.finish();
wasmparser::Validator::default()
.validate_all(&wasm)
.unwrap();
}

2
third_party/rust/wast/.cargo-checksum.json поставляемый

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

4
third_party/rust/wast/Cargo.toml поставляемый
Просмотреть файл

@ -12,7 +12,7 @@
[package]
edition = "2021"
name = "wast"
version = "53.0.0"
version = "55.0.0"
authors = ["Alex Crichton <alex@alexcrichton.com>"]
description = """
Customizable Rust parsers for the WebAssembly Text formats WAT and WAST
@ -37,7 +37,7 @@ version = "2.4.1"
version = "0.1.9"
[dependencies.wasm-encoder]
version = "0.23.0"
version = "0.25.0"
[dev-dependencies.anyhow]
version = "1.0.58"

27
third_party/rust/wast/src/component/binary.rs поставляемый
Просмотреть файл

@ -552,17 +552,32 @@ impl From<core::ValType<'_>> for wasm_encoder::ValType {
core::ValType::F32 => Self::F32,
core::ValType::F64 => Self::F64,
core::ValType::V128 => Self::V128,
core::ValType::Ref(r) => r.into(),
core::ValType::Ref(r) => Self::Ref(r.into()),
}
}
}
impl From<core::RefType<'_>> for wasm_encoder::ValType {
impl From<core::RefType<'_>> for wasm_encoder::RefType {
fn from(r: core::RefType<'_>) -> Self {
match r.heap {
core::HeapType::Func => Self::FuncRef,
core::HeapType::Extern => Self::ExternRef,
_ => {
wasm_encoder::RefType {
nullable: r.nullable,
heap_type: r.heap.into(),
}
}
}
impl From<core::HeapType<'_>> for wasm_encoder::HeapType {
fn from(r: core::HeapType<'_>) -> Self {
match r {
core::HeapType::Func => Self::Func,
core::HeapType::Extern => Self::Extern,
core::HeapType::Index(Index::Num(i, _)) => Self::TypedFunc(i),
core::HeapType::Index(_) => panic!("unresolved index"),
core::HeapType::Any
| core::HeapType::Eq
| core::HeapType::Struct
| core::HeapType::Array
| core::HeapType::I31 => {
todo!("encoding of GC proposal types not yet implemented")
}
}

17
third_party/rust/wast/src/core/binary.rs поставляемый
Просмотреть файл

@ -241,8 +241,11 @@ impl<'a> Encode for HeapType<'a> {
HeapType::Struct => e.push(0x67),
HeapType::Array => e.push(0x66),
HeapType::I31 => e.push(0x6a),
HeapType::Index(index) => {
index.encode(e);
// Note that this is encoded as a signed leb128 so be sure to cast
// to an i64 first
HeapType::Index(Index::Num(n, _)) => i64::from(*n).encode(e),
HeapType::Index(Index::Id(n)) => {
panic!("unresolved index in emission: {:?}", n)
}
}
}
@ -427,8 +430,14 @@ impl Encode for Table<'_> {
fn encode(&self, e: &mut Vec<u8>) {
assert!(self.exports.names.is_empty());
match &self.kind {
TableKind::Normal { ty, init_expr: None } => ty.encode(e),
TableKind::Normal { ty, init_expr: Some(init_expr) } => {
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);

21
third_party/rust/wast/src/core/expr.rs поставляемый
Просмотреть файл

@ -1145,14 +1145,14 @@ instructions! {
// Relaxed SIMD proposal
I8x16RelaxedSwizzle : [0xfd, 0x100]: "i8x16.relaxed_swizzle",
I32x4RelaxedTruncSatF32x4S : [0xfd, 0x101]: "i32x4.relaxed_trunc_sat_f32x4_s" | "i32x4.relaxed_trunc_f32x4_s",
I32x4RelaxedTruncSatF32x4U : [0xfd, 0x102]: "i32x4.relaxed_trunc_sat_f32x4_u" | "i32x4.relaxed_trunc_f32x4_u",
I32x4RelaxedTruncSatF64x2SZero : [0xfd, 0x103]: "i32x4.relaxed_trunc_sat_f64x2_s_zero" | "i32x4.relaxed_trunc_f64x2_s_zero",
I32x4RelaxedTruncSatF64x2UZero : [0xfd, 0x104]: "i32x4.relaxed_trunc_sat_f64x2_u_zero" | "i32x4.relaxed_trunc_f64x2_u_zero",
F32x4RelaxedFma : [0xfd, 0x105]: "f32x4.relaxed_fma",
F32x4RelaxedFnma : [0xfd, 0x106]: "f32x4.relaxed_fnma",
F64x2RelaxedFma : [0xfd, 0x107]: "f64x2.relaxed_fma",
F64x2RelaxedFnma : [0xfd, 0x108]: "f64x2.relaxed_fnma",
I32x4RelaxedTruncF32x4S : [0xfd, 0x101]: "i32x4.relaxed_trunc_f32x4_s",
I32x4RelaxedTruncF32x4U : [0xfd, 0x102]: "i32x4.relaxed_trunc_f32x4_u",
I32x4RelaxedTruncF64x2SZero : [0xfd, 0x103]: "i32x4.relaxed_trunc_f64x2_s_zero",
I32x4RelaxedTruncF64x2UZero : [0xfd, 0x104]: "i32x4.relaxed_trunc_f64x2_u_zero",
F32x4RelaxedMadd : [0xfd, 0x105]: "f32x4.relaxed_madd",
F32x4RelaxedNmadd : [0xfd, 0x106]: "f32x4.relaxed_nmadd",
F64x2RelaxedMadd : [0xfd, 0x107]: "f64x2.relaxed_madd",
F64x2RelaxedNmadd : [0xfd, 0x108]: "f64x2.relaxed_nmadd",
I8x16RelaxedLaneselect : [0xfd, 0x109]: "i8x16.relaxed_laneselect",
I16x8RelaxedLaneselect : [0xfd, 0x10A]: "i16x8.relaxed_laneselect",
I32x4RelaxedLaneselect : [0xfd, 0x10B]: "i32x4.relaxed_laneselect",
@ -1162,9 +1162,8 @@ instructions! {
F64x2RelaxedMin : [0xfd, 0x10F]: "f64x2.relaxed_min",
F64x2RelaxedMax : [0xfd, 0x110]: "f64x2.relaxed_max",
I16x8RelaxedQ15mulrS: [0xfd, 0x111]: "i16x8.relaxed_q15mulr_s",
I16x8DotI8x16I7x16S: [0xfd, 0x112]: "i16x8.dot_i8x16_i7x16_s",
I32x4DotI8x16I7x16AddS: [0xfd, 0x113]: "i32x4.dot_i8x16_i7x16_add_s",
F32x4RelaxedDotBf16x8AddF32x4: [0xfd, 0x114]: "f32x4.relaxed_dot_bf16x8_add_f32x4",
I16x8RelaxedDotI8x16I7x16S: [0xfd, 0x112]: "i16x8.relaxed_dot_i8x16_i7x16_s",
I32x4RelaxedDotI8x16I7x16AddS: [0xfd, 0x113]: "i32x4.relaxed_dot_i8x16_i7x16_add_s",
}
}

2
third_party/rust/wast/src/core/table.rs поставляемый
Просмотреть файл

@ -75,7 +75,7 @@ impl<'a> Parse<'a> for Table<'a> {
} else if l.peek::<u32>() {
TableKind::Normal {
ty: parser.parse()?,
init_expr: if parser.peek::<LParen>() {
init_expr: if !parser.is_empty() {
Some(parser.parse::<Expression>()?)
} else {
None