summaryrefslogtreecommitdiffstats
path: root/third_party/rust/wast/src/core
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/rust/wast/src/core')
-rw-r--r--third_party/rust/wast/src/core/binary.rs84
-rw-r--r--third_party/rust/wast/src/core/expr.rs158
-rw-r--r--third_party/rust/wast/src/core/memory.rs11
-rw-r--r--third_party/rust/wast/src/core/resolve/deinline_import_export.rs6
-rw-r--r--third_party/rust/wast/src/core/resolve/names.rs28
-rw-r--r--third_party/rust/wast/src/core/resolve/types.rs4
-rw-r--r--third_party/rust/wast/src/core/types.rs78
-rw-r--r--third_party/rust/wast/src/core/wast.rs18
8 files changed, 241 insertions, 146 deletions
diff --git a/third_party/rust/wast/src/core/binary.rs b/third_party/rust/wast/src/core/binary.rs
index da94da0241..769e120112 100644
--- a/third_party/rust/wast/src/core/binary.rs
+++ b/third_party/rust/wast/src/core/binary.rs
@@ -295,6 +295,7 @@ impl<'a> Encode for HeapType<'a> {
HeapType::I31 => e.push(0x6c),
HeapType::NoFunc => e.push(0x73),
HeapType::NoExtern => e.push(0x72),
+ HeapType::NoExn => e.push(0x74),
HeapType::None => e.push(0x71),
// Note that this is encoded as a signed leb128 so be sure to cast
// to an i64 first
@@ -349,6 +350,11 @@ impl<'a> Encode for RefType<'a> {
nullable: true,
heap: HeapType::NoExtern,
} => e.push(0x72),
+ // The 'nullexnref' binary abbreviation
+ RefType {
+ nullable: true,
+ heap: HeapType::NoExn,
+ } => e.push(0x74),
// The 'nullref' binary abbreviation
RefType {
nullable: true,
@@ -466,25 +472,45 @@ impl Encode for Limits {
impl Encode for MemoryType {
fn encode(&self, e: &mut Vec<u8>) {
match self {
- MemoryType::B32 { limits, shared } => {
+ MemoryType::B32 {
+ limits,
+ shared,
+ page_size_log2,
+ } => {
let flag_max = limits.max.is_some() as u8;
let flag_shared = *shared as u8;
- let flags = flag_max | (flag_shared << 1);
+ let flag_page_size = page_size_log2.is_some() as u8;
+ let flags = flag_max | (flag_shared << 1) | (flag_page_size << 3);
e.push(flags);
limits.min.encode(e);
if let Some(max) = limits.max {
max.encode(e);
}
+ if let Some(p) = page_size_log2 {
+ p.encode(e);
+ }
}
- MemoryType::B64 { limits, shared } => {
- let flag_max = limits.max.is_some() as u8;
- let flag_shared = *shared as u8;
- let flags = flag_max | (flag_shared << 1) | 0x04;
+ MemoryType::B64 {
+ limits,
+ shared,
+ page_size_log2,
+ } => {
+ let flag_max = limits.max.is_some();
+ let flag_shared = *shared;
+ let flag_mem64 = true;
+ let flag_page_size = page_size_log2.is_some();
+ let flags = ((flag_max as u8) << 0)
+ | ((flag_shared as u8) << 1)
+ | ((flag_mem64 as u8) << 2)
+ | ((flag_page_size as u8) << 3);
e.push(flags);
limits.min.encode(e);
if let Some(max) = limits.max {
max.encode(e);
}
+ if let Some(p) = page_size_log2 {
+ p.encode(e);
+ }
}
}
}
@@ -493,11 +519,14 @@ impl Encode for MemoryType {
impl<'a> Encode for GlobalType<'a> {
fn encode(&self, e: &mut Vec<u8>) {
self.ty.encode(e);
+ let mut flags = 0;
if self.mutable {
- e.push(0x01);
- } else {
- e.push(0x00);
+ flags |= 0b01;
+ }
+ if self.shared {
+ flags |= 0b10;
}
+ e.push(flags);
}
}
@@ -749,19 +778,6 @@ impl Encode for BlockType<'_> {
}
}
-impl Encode for FuncBindType<'_> {
- fn encode(&self, e: &mut Vec<u8>) {
- self.ty.encode(e);
- }
-}
-
-impl Encode for LetType<'_> {
- fn encode(&self, e: &mut Vec<u8>) {
- self.block.encode(e);
- self.locals.encode(e);
- }
-}
-
impl Encode for LaneArg {
fn encode(&self, e: &mut Vec<u8>) {
self.lane.encode(e);
@@ -784,6 +800,23 @@ impl Encode for MemArg<'_> {
}
}
+impl Encode for Ordering {
+ fn encode(&self, buf: &mut Vec<u8>) {
+ let flag: u8 = match self {
+ Ordering::SeqCst => 0,
+ Ordering::AcqRel => 1,
+ };
+ flag.encode(buf);
+ }
+}
+
+impl Encode for OrderedAccess<'_> {
+ fn encode(&self, buf: &mut Vec<u8>) {
+ self.ordering.encode(buf);
+ self.index.encode(buf);
+ }
+}
+
impl Encode for LoadOrStoreLane<'_> {
fn encode(&self, e: &mut Vec<u8>) {
self.memarg.encode(e);
@@ -845,13 +878,13 @@ impl Encode for BrTableIndices<'_> {
}
}
-impl Encode for Float32 {
+impl Encode for F32 {
fn encode(&self, e: &mut Vec<u8>) {
e.extend_from_slice(&self.bits.to_le_bytes());
}
}
-impl Encode for Float64 {
+impl Encode for F64 {
fn encode(&self, e: &mut Vec<u8>) {
e.extend_from_slice(&self.bits.to_le_bytes());
}
@@ -994,8 +1027,7 @@ fn find_names<'a>(
| Instruction::Block(block)
| Instruction::Loop(block)
| Instruction::Try(block)
- | Instruction::TryTable(TryTable { block, .. })
- | Instruction::Let(LetType { block, .. }) => {
+ | Instruction::TryTable(TryTable { block, .. }) => {
if let Some(name) = get_name(&block.label, &block.label_name) {
label_names.push((label_idx, name));
}
diff --git a/third_party/rust/wast/src/core/expr.rs b/third_party/rust/wast/src/core/expr.rs
index b45950b896..df0abb7cd0 100644
--- a/third_party/rust/wast/src/core/expr.rs
+++ b/third_party/rust/wast/src/core/expr.rs
@@ -184,7 +184,6 @@ impl<'a> ExpressionParser<'a> {
// seen
i @ Instruction::Block(_)
| i @ Instruction::Loop(_)
- | i @ Instruction::Let(_)
| i @ Instruction::TryTable(_) => {
self.instrs.push(i);
self.stack.push(Level::EndWith(Instruction::End(None)));
@@ -350,7 +349,7 @@ macro_rules! instructions {
}) => (
/// A listing of all WebAssembly instructions that can be in a module
/// that this crate currently parses.
- #[derive(Debug)]
+ #[derive(Debug, Clone)]
#[allow(missing_docs)]
pub enum Instruction<'a> {
$(
@@ -468,8 +467,6 @@ instructions! {
// function-references proposal
CallRef(Index<'a>) : [0x14] : "call_ref",
ReturnCallRef(Index<'a>) : [0x15] : "return_call_ref",
- FuncBind(FuncBindType<'a>) : [0x16] : "func.bind",
- Let(LetType<'a>) : [0x17] : "let",
Drop : [0x1a] : "drop",
Select(SelectTypes<'a>) : [] : "select",
@@ -574,8 +571,8 @@ instructions! {
I32Const(i32) : [0x41] : "i32.const",
I64Const(i64) : [0x42] : "i64.const",
- F32Const(Float32) : [0x43] : "f32.const",
- F64Const(Float64) : [0x44] : "f64.const",
+ F32Const(F32) : [0x43] : "f32.const",
+ F64Const(F64) : [0x44] : "f64.const",
I32Clz : [0x67] : "i32.clz",
I32Ctz : [0x68] : "i32.ctz",
@@ -803,6 +800,10 @@ instructions! {
I64AtomicRmw16CmpxchgU(MemArg<2>) : [0xfe, 0x4d] : "i64.atomic.rmw16.cmpxchg_u",
I64AtomicRmw32CmpxchgU(MemArg<4>) : [0xfe, 0x4e] : "i64.atomic.rmw32.cmpxchg_u",
+ // proposal: shared-everything-threads
+ GlobalAtomicGet(OrderedAccess<'a>) : [0xfe, 0x4f] : "global.atomic.get",
+ GlobalAtomicSet(OrderedAccess<'a>) : [0xfe, 0x50] : "global.atomic.set",
+
// proposal: simd
//
// https://webassembly.github.io/simd/core/binary/instructions.html
@@ -1123,7 +1124,7 @@ impl<'a> Instruction<'a> {
///
/// This is used to label blocks and also annotate what types are expected for
/// the block.
-#[derive(Debug)]
+#[derive(Debug, Clone)]
#[allow(missing_docs)]
pub struct BlockType<'a> {
pub label: Option<Id<'a>>,
@@ -1143,7 +1144,7 @@ impl<'a> Parse<'a> for BlockType<'a> {
}
}
-#[derive(Debug)]
+#[derive(Debug, Clone)]
#[allow(missing_docs)]
pub struct TryTable<'a> {
pub block: Box<BlockType<'a>>,
@@ -1187,7 +1188,7 @@ impl<'a> Parse<'a> for TryTable<'a> {
}
}
-#[derive(Debug)]
+#[derive(Debug, Clone)]
#[allow(missing_docs)]
pub enum TryTableCatchKind<'a> {
// Catch a tagged exception, do not capture an exnref.
@@ -1210,50 +1211,16 @@ impl<'a> TryTableCatchKind<'a> {
}
}
-#[derive(Debug)]
+#[derive(Debug, Clone)]
#[allow(missing_docs)]
pub struct TryTableCatch<'a> {
pub kind: TryTableCatchKind<'a>,
pub label: Index<'a>,
}
-/// Extra information associated with the func.bind instruction.
-#[derive(Debug)]
-#[allow(missing_docs)]
-pub struct FuncBindType<'a> {
- pub ty: TypeUse<'a, FunctionType<'a>>,
-}
-
-impl<'a> Parse<'a> for FuncBindType<'a> {
- fn parse(parser: Parser<'a>) -> Result<Self> {
- Ok(FuncBindType {
- ty: parser
- .parse::<TypeUse<'a, FunctionTypeNoNames<'a>>>()?
- .into(),
- })
- }
-}
-
-/// Extra information associated with the let instruction.
-#[derive(Debug)]
-#[allow(missing_docs)]
-pub struct LetType<'a> {
- pub block: Box<BlockType<'a>>,
- pub locals: Box<[Local<'a>]>,
-}
-
-impl<'a> Parse<'a> for LetType<'a> {
- fn parse(parser: Parser<'a>) -> Result<Self> {
- Ok(LetType {
- block: parser.parse()?,
- locals: Local::parse_remainder(parser)?.into(),
- })
- }
-}
-
/// Extra information associated with the `br_table` instruction.
#[allow(missing_docs)]
-#[derive(Debug)]
+#[derive(Debug, Clone)]
pub struct BrTableIndices<'a> {
pub labels: Vec<Index<'a>>,
pub default: Index<'a>,
@@ -1271,7 +1238,7 @@ impl<'a> Parse<'a> for BrTableIndices<'a> {
}
/// Payload for lane-related instructions. Unsigned with no + prefix.
-#[derive(Debug)]
+#[derive(Debug, Clone)]
pub struct LaneArg {
/// The lane argument.
pub lane: u8,
@@ -1299,7 +1266,7 @@ impl<'a> Parse<'a> for LaneArg {
/// Payload for memory-related instructions indicating offset/alignment of
/// memory accesses.
-#[derive(Debug)]
+#[derive(Debug, Clone)]
pub struct MemArg<'a> {
/// The alignment of this access.
///
@@ -1374,7 +1341,7 @@ impl<'a> MemArg<'a> {
}
/// Extra data associated with the `loadN_lane` and `storeN_lane` instructions.
-#[derive(Debug)]
+#[derive(Debug, Clone)]
pub struct LoadOrStoreLane<'a> {
/// The memory argument for this instruction.
pub memarg: MemArg<'a>,
@@ -1428,7 +1395,7 @@ impl<'a> LoadOrStoreLane<'a> {
}
/// Extra data associated with the `call_indirect` instruction.
-#[derive(Debug)]
+#[derive(Debug, Clone)]
pub struct CallIndirect<'a> {
/// The table that this call is going to be indexing.
pub table: Index<'a>,
@@ -1449,7 +1416,7 @@ impl<'a> Parse<'a> for CallIndirect<'a> {
}
/// Extra data associated with the `table.init` instruction
-#[derive(Debug)]
+#[derive(Debug, Clone)]
pub struct TableInit<'a> {
/// The index of the table we're copying into.
pub table: Index<'a>,
@@ -1471,7 +1438,7 @@ impl<'a> Parse<'a> for TableInit<'a> {
}
/// Extra data associated with the `table.copy` instruction.
-#[derive(Debug)]
+#[derive(Debug, Clone)]
pub struct TableCopy<'a> {
/// The index of the destination table to copy into.
pub dst: Index<'a>,
@@ -1493,7 +1460,7 @@ impl<'a> Parse<'a> for TableCopy<'a> {
}
/// Extra data associated with unary table instructions.
-#[derive(Debug)]
+#[derive(Debug, Clone)]
pub struct TableArg<'a> {
/// The index of the table argument.
pub dst: Index<'a>,
@@ -1511,7 +1478,7 @@ impl<'a> Parse<'a> for TableArg<'a> {
}
/// Extra data associated with unary memory instructions.
-#[derive(Debug)]
+#[derive(Debug, Clone)]
pub struct MemoryArg<'a> {
/// The index of the memory space.
pub mem: Index<'a>,
@@ -1529,7 +1496,7 @@ impl<'a> Parse<'a> for MemoryArg<'a> {
}
/// Extra data associated with the `memory.init` instruction
-#[derive(Debug)]
+#[derive(Debug, Clone)]
pub struct MemoryInit<'a> {
/// The index of the data segment we're copying into memory.
pub data: Index<'a>,
@@ -1551,7 +1518,7 @@ impl<'a> Parse<'a> for MemoryInit<'a> {
}
/// Extra data associated with the `memory.copy` instruction
-#[derive(Debug)]
+#[derive(Debug, Clone)]
pub struct MemoryCopy<'a> {
/// The index of the memory we're copying from.
pub src: Index<'a>,
@@ -1573,7 +1540,7 @@ impl<'a> Parse<'a> for MemoryCopy<'a> {
}
/// Extra data associated with the `struct.get/set` instructions
-#[derive(Debug)]
+#[derive(Debug, Clone)]
pub struct StructAccess<'a> {
/// The index of the struct type we're accessing.
pub r#struct: Index<'a>,
@@ -1591,7 +1558,7 @@ impl<'a> Parse<'a> for StructAccess<'a> {
}
/// Extra data associated with the `array.fill` instruction
-#[derive(Debug)]
+#[derive(Debug, Clone)]
pub struct ArrayFill<'a> {
/// The index of the array type we're filling.
pub array: Index<'a>,
@@ -1606,7 +1573,7 @@ impl<'a> Parse<'a> for ArrayFill<'a> {
}
/// Extra data associated with the `array.copy` instruction
-#[derive(Debug)]
+#[derive(Debug, Clone)]
pub struct ArrayCopy<'a> {
/// The index of the array type we're copying to.
pub dest_array: Index<'a>,
@@ -1624,7 +1591,7 @@ impl<'a> Parse<'a> for ArrayCopy<'a> {
}
/// Extra data associated with the `array.init_[data/elem]` instruction
-#[derive(Debug)]
+#[derive(Debug, Clone)]
pub struct ArrayInit<'a> {
/// The index of the array type we're initializing.
pub array: Index<'a>,
@@ -1642,7 +1609,7 @@ impl<'a> Parse<'a> for ArrayInit<'a> {
}
/// Extra data associated with the `array.new_fixed` instruction
-#[derive(Debug)]
+#[derive(Debug, Clone)]
pub struct ArrayNewFixed<'a> {
/// The index of the array type we're accessing.
pub array: Index<'a>,
@@ -1660,7 +1627,7 @@ impl<'a> Parse<'a> for ArrayNewFixed<'a> {
}
/// Extra data associated with the `array.new_data` instruction
-#[derive(Debug)]
+#[derive(Debug, Clone)]
pub struct ArrayNewData<'a> {
/// The index of the array type we're accessing.
pub array: Index<'a>,
@@ -1678,7 +1645,7 @@ impl<'a> Parse<'a> for ArrayNewData<'a> {
}
/// Extra data associated with the `array.new_elem` instruction
-#[derive(Debug)]
+#[derive(Debug, Clone)]
pub struct ArrayNewElem<'a> {
/// The index of the array type we're accessing.
pub array: Index<'a>,
@@ -1696,7 +1663,7 @@ impl<'a> Parse<'a> for ArrayNewElem<'a> {
}
/// Extra data associated with the `ref.cast` instruction
-#[derive(Debug)]
+#[derive(Debug, Clone)]
pub struct RefCast<'a> {
/// The type to cast to.
pub r#type: RefType<'a>,
@@ -1711,7 +1678,7 @@ impl<'a> Parse<'a> for RefCast<'a> {
}
/// Extra data associated with the `ref.test` instruction
-#[derive(Debug)]
+#[derive(Debug, Clone)]
pub struct RefTest<'a> {
/// The type to test for.
pub r#type: RefType<'a>,
@@ -1726,7 +1693,7 @@ impl<'a> Parse<'a> for RefTest<'a> {
}
/// Extra data associated with the `br_on_cast` instruction
-#[derive(Debug)]
+#[derive(Debug, Clone)]
pub struct BrOnCast<'a> {
/// The label to branch to.
pub label: Index<'a>,
@@ -1747,7 +1714,7 @@ impl<'a> Parse<'a> for BrOnCast<'a> {
}
/// Extra data associated with the `br_on_cast_fail` instruction
-#[derive(Debug)]
+#[derive(Debug, Clone)]
pub struct BrOnCastFail<'a> {
/// The label to branch to.
pub label: Index<'a>,
@@ -1767,16 +1734,65 @@ impl<'a> Parse<'a> for BrOnCastFail<'a> {
}
}
+/// The memory ordering for atomic instructions.
+///
+/// For an in-depth explanation of memory orderings, see the C++ documentation
+/// for [`memory_order`] or the Rust documentation for [`atomic::Ordering`].
+///
+/// [`memory_order`]: https://en.cppreference.com/w/cpp/atomic/memory_order
+/// [`atomic::Ordering`]: https://doc.rust-lang.org/std/sync/atomic/enum.Ordering.html
+#[derive(Clone, Debug)]
+pub enum Ordering {
+ /// Like `AcqRel` but all threads see all sequentially consistent operations
+ /// in the same order.
+ AcqRel,
+ /// For a load, it acquires; this orders all operations before the last
+ /// "releasing" store. For a store, it releases; this orders all operations
+ /// before it at the next "acquiring" load.
+ SeqCst,
+}
+
+impl<'a> Parse<'a> for Ordering {
+ fn parse(parser: Parser<'a>) -> Result<Self> {
+ if parser.peek::<kw::seq_cst>()? {
+ parser.parse::<kw::seq_cst>()?;
+ Ok(Ordering::SeqCst)
+ } else if parser.peek::<kw::acq_rel>()? {
+ parser.parse::<kw::acq_rel>()?;
+ Ok(Ordering::AcqRel)
+ } else {
+ Err(parser.error("expected a memory ordering: `seq_cst` or `acq_rel`"))
+ }
+ }
+}
+
+/// Extra data associated with the `global.atomic.*` instructions.
+#[derive(Clone, Debug)]
+pub struct OrderedAccess<'a> {
+ /// The memory ordering for this atomic instruction.
+ pub ordering: Ordering,
+ /// The index of the global to access.
+ pub index: Index<'a>,
+}
+
+impl<'a> Parse<'a> for OrderedAccess<'a> {
+ fn parse(parser: Parser<'a>) -> Result<Self> {
+ let ordering = parser.parse()?;
+ let index = parser.parse()?;
+ Ok(OrderedAccess { ordering, index })
+ }
+}
+
/// Different ways to specify a `v128.const` instruction
-#[derive(Debug)]
+#[derive(Clone, Debug)]
#[allow(missing_docs)]
pub enum V128Const {
I8x16([i8; 16]),
I16x8([i16; 8]),
I32x4([i32; 4]),
I64x2([i64; 2]),
- F32x4([Float32; 4]),
- F64x2([Float64; 2]),
+ F32x4([F32; 4]),
+ F64x2([F64; 2]),
}
impl V128Const {
@@ -1934,7 +1950,7 @@ impl<'a> Parse<'a> for V128Const {
}
/// Lanes being shuffled in the `i8x16.shuffle` instruction
-#[derive(Debug)]
+#[derive(Debug, Clone)]
pub struct I8x16Shuffle {
#[allow(missing_docs)]
pub lanes: [u8; 16],
@@ -1966,7 +1982,7 @@ impl<'a> Parse<'a> for I8x16Shuffle {
}
/// Payload of the `select` instructions
-#[derive(Debug)]
+#[derive(Debug, Clone)]
pub struct SelectTypes<'a> {
#[allow(missing_docs)]
pub tys: Option<Vec<ValType<'a>>>,
diff --git a/third_party/rust/wast/src/core/memory.rs b/third_party/rust/wast/src/core/memory.rs
index eb1baa1a95..5f5f051109 100644
--- a/third_party/rust/wast/src/core/memory.rs
+++ b/third_party/rust/wast/src/core/memory.rs
@@ -59,7 +59,10 @@ impl<'a> Parse<'a> for Memory<'a> {
import,
ty: parser.parse()?,
}
- } else if l.peek::<LParen>()? || parser.peek2::<LParen>()? {
+ } else if l.peek::<LParen>()?
+ || ((parser.peek::<kw::i32>()? || parser.peek::<kw::i64>()?)
+ && parser.peek2::<LParen>()?)
+ {
let is_32 = if parser.parse::<Option<kw::i32>>()?.is_some() {
true
} else {
@@ -133,7 +136,7 @@ impl<'a> Parse<'a> for Data<'a> {
let id = parser.parse()?;
let name = parser.parse()?;
- let kind = if parser.peek::<&[u8]>()? {
+ let kind = if parser.peek::<&[u8]>()? || parser.peek::<RParen>()? {
DataKind::Passive
// ... and otherwise we must be attached to a particular memory as well
@@ -248,8 +251,8 @@ impl<'a> Parse<'a> for DataVal<'a> {
|| consume::<kw::i16, i16, _>(p, l, r, |u, v| v.extend(&u.to_le_bytes()))?
|| consume::<kw::i32, i32, _>(p, l, r, |u, v| v.extend(&u.to_le_bytes()))?
|| consume::<kw::i64, i64, _>(p, l, r, |u, v| v.extend(&u.to_le_bytes()))?
- || consume::<kw::f32, Float32, _>(p, l, r, |u, v| v.extend(&u.bits.to_le_bytes()))?
- || consume::<kw::f64, Float64, _>(p, l, r, |u, v| v.extend(&u.bits.to_le_bytes()))?
+ || consume::<kw::f32, F32, _>(p, l, r, |u, v| v.extend(&u.bits.to_le_bytes()))?
+ || consume::<kw::f64, F64, _>(p, l, r, |u, v| v.extend(&u.bits.to_le_bytes()))?
|| consume::<kw::v128, V128Const, _>(p, l, r, |u, v| v.extend(&u.to_le_bytes()))?
{
Ok(DataVal::Integral(result))
diff --git a/third_party/rust/wast/src/core/resolve/deinline_import_export.rs b/third_party/rust/wast/src/core/resolve/deinline_import_export.rs
index 98e680b58a..f2d12e9a52 100644
--- a/third_party/rust/wast/src/core/resolve/deinline_import_export.rs
+++ b/third_party/rust/wast/src/core/resolve/deinline_import_export.rs
@@ -50,7 +50,7 @@ pub fn run(fields: &mut Vec<ModuleField>) {
// field here instead, switching this to a `Normal` memory.
MemoryKind::Inline { is_32, ref data } => {
let len = data.iter().map(|l| l.len()).sum::<usize>() as u32;
- let pages = (len + page_size() - 1) / page_size();
+ let pages = (len + default_page_size() - 1) / default_page_size();
let kind = MemoryKind::Normal(if is_32 {
MemoryType::B32 {
limits: Limits {
@@ -58,6 +58,7 @@ pub fn run(fields: &mut Vec<ModuleField>) {
max: Some(pages),
},
shared: false,
+ page_size_log2: None,
}
} else {
MemoryType::B64 {
@@ -66,6 +67,7 @@ pub fn run(fields: &mut Vec<ModuleField>) {
max: Some(u64::from(pages)),
},
shared: false,
+ page_size_log2: None,
}
});
let data = match mem::replace(&mut m.kind, kind) {
@@ -212,7 +214,7 @@ pub fn run(fields: &mut Vec<ModuleField>) {
fields.push(item);
}
- fn page_size() -> u32 {
+ fn default_page_size() -> u32 {
1 << 16
}
}
diff --git a/third_party/rust/wast/src/core/resolve/names.rs b/third_party/rust/wast/src/core/resolve/names.rs
index 05894e9a1e..f17590bbd1 100644
--- a/third_party/rust/wast/src/core/resolve/names.rs
+++ b/third_party/rust/wast/src/core/resolve/names.rs
@@ -457,6 +457,10 @@ impl<'a, 'b> ExprResolver<'a, 'b> {
self.resolver.resolve(i, Ns::Global)?;
}
+ GlobalAtomicSet(i) | GlobalAtomicGet(i) => {
+ self.resolver.resolve(&mut i.index, Ns::Global)?;
+ }
+
LocalSet(i) | LocalGet(i) | LocalTee(i) => {
assert!(self.scopes.len() > 0);
// Resolve a local by iterating over scopes from most recent
@@ -490,30 +494,6 @@ impl<'a, 'b> ExprResolver<'a, 'b> {
self.resolver.resolve(i, Ns::Type)?;
}
- FuncBind(b) => {
- self.resolver.resolve_type_use(&mut b.ty)?;
- }
-
- Let(t) => {
- // Resolve (ref T) in locals
- for local in t.locals.iter_mut() {
- self.resolver.resolve_valtype(&mut local.ty)?;
- }
-
- // Register all locals defined in this let
- let mut scope = Namespace::default();
- for local in t.locals.iter() {
- scope.register(local.id, "local")?;
- }
- self.scopes.push(scope);
- self.blocks.push(ExprBlock {
- label: t.block.label,
- pushed_scope: true,
- });
-
- self.resolve_block_type(&mut t.block)?;
- }
-
Block(bt) | If(bt) | Loop(bt) | Try(bt) => {
self.blocks.push(ExprBlock {
label: bt.label,
diff --git a/third_party/rust/wast/src/core/resolve/types.rs b/third_party/rust/wast/src/core/resolve/types.rs
index bfb996b4b6..84b0e516e4 100644
--- a/third_party/rust/wast/src/core/resolve/types.rs
+++ b/third_party/rust/wast/src/core/resolve/types.rs
@@ -139,7 +139,6 @@ impl<'a> Expander<'a> {
Instruction::Block(bt)
| Instruction::If(bt)
| Instruction::Loop(bt)
- | Instruction::Let(LetType { block: bt, .. })
| Instruction::Try(bt)
| Instruction::TryTable(TryTable { block: bt, .. }) => {
// No expansion necessary, a type reference is already here.
@@ -174,9 +173,6 @@ impl<'a> Expander<'a> {
}
self.expand_type_use(&mut bt.ty);
}
- Instruction::FuncBind(b) => {
- self.expand_type_use(&mut b.ty);
- }
Instruction::CallIndirect(c) | Instruction::ReturnCallIndirect(c) => {
self.expand_type_use(&mut c.ty);
}
diff --git a/third_party/rust/wast/src/core/types.rs b/third_party/rust/wast/src/core/types.rs
index 179a62b9b8..160317c1c3 100644
--- a/third_party/rust/wast/src/core/types.rs
+++ b/third_party/rust/wast/src/core/types.rs
@@ -2,6 +2,7 @@ use crate::core::*;
use crate::kw;
use crate::parser::{Cursor, Parse, Parser, Peek, Result};
use crate::token::{Id, Index, LParen, NameAnnotation, Span};
+use crate::Error;
use std::mem;
/// The value types for a wasm module.
@@ -86,6 +87,8 @@ pub enum HeapType<'a> {
NoExtern,
/// The bottom type of the anyref hierarchy. Part of the GC proposal.
None,
+ /// The bottom type of the exnref hierarchy. Part of the exceptions proposal.
+ NoExn,
/// A reference to a concrete function, struct, or array type defined by
/// Wasm: `ref T`. This is part of the function references and GC proposals.
Concrete(Index<'a>),
@@ -124,6 +127,9 @@ impl<'a> Parse<'a> for HeapType<'a> {
} else if l.peek::<kw::noextern>()? {
parser.parse::<kw::noextern>()?;
Ok(HeapType::NoExtern)
+ } else if l.peek::<kw::noexn>()? {
+ parser.parse::<kw::noexn>()?;
+ Ok(HeapType::NoExn)
} else if l.peek::<kw::none>()? {
parser.parse::<kw::none>()?;
Ok(HeapType::None)
@@ -147,6 +153,7 @@ impl<'a> Peek for HeapType<'a> {
|| kw::i31::peek(cursor)?
|| kw::nofunc::peek(cursor)?
|| kw::noextern::peek(cursor)?
+ || kw::noexn::peek(cursor)?
|| kw::none::peek(cursor)?
|| (LParen::peek(cursor)? && kw::r#type::peek2(cursor)?))
}
@@ -251,6 +258,14 @@ impl<'a> RefType<'a> {
heap: HeapType::None,
}
}
+
+ /// A `nullexnref` as an abbreviation for `(ref null noexn)`.
+ pub fn nullexnref() -> Self {
+ RefType {
+ nullable: true,
+ heap: HeapType::NoExn,
+ }
+ }
}
impl<'a> Parse<'a> for RefType<'a> {
@@ -286,6 +301,9 @@ impl<'a> Parse<'a> for RefType<'a> {
} else if l.peek::<kw::nullexternref>()? {
parser.parse::<kw::nullexternref>()?;
Ok(RefType::nullexternref())
+ } else if l.peek::<kw::nullexnref>()? {
+ parser.parse::<kw::nullexnref>()?;
+ Ok(RefType::nullexnref())
} else if l.peek::<kw::nullref>()? {
parser.parse::<kw::nullref>()?;
Ok(RefType::nullref())
@@ -327,6 +345,7 @@ impl<'a> Peek for RefType<'a> {
|| kw::i31ref::peek(cursor)?
|| kw::nullfuncref::peek(cursor)?
|| kw::nullexternref::peek(cursor)?
+ || kw::nullexnref::peek(cursor)?
|| kw::nullref::peek(cursor)?
|| (LParen::peek(cursor)? && kw::r#ref::peek2(cursor)?))
}
@@ -368,22 +387,35 @@ pub struct GlobalType<'a> {
pub ty: ValType<'a>,
/// Whether or not the global is mutable or not.
pub mutable: bool,
+ /// Whether or not the global is shared.
+ pub shared: bool,
}
impl<'a> Parse<'a> for GlobalType<'a> {
fn parse(parser: Parser<'a>) -> Result<Self> {
- if parser.peek2::<kw::r#mut>()? {
+ if parser.peek2::<kw::shared>()? || parser.peek2::<kw::r#mut>()? {
parser.parens(|p| {
- p.parse::<kw::r#mut>()?;
+ let mut shared = false;
+ let mut mutable = false;
+ if p.peek::<kw::shared>()? {
+ p.parse::<kw::shared>()?;
+ shared = true;
+ }
+ if p.peek::<kw::r#mut>()? {
+ p.parse::<kw::r#mut>()?;
+ mutable = true;
+ }
Ok(GlobalType {
- ty: parser.parse()?,
- mutable: true,
+ ty: p.parse()?,
+ mutable,
+ shared,
})
})
} else {
Ok(GlobalType {
ty: parser.parse()?,
mutable: false,
+ shared: false,
})
}
}
@@ -458,6 +490,8 @@ pub enum MemoryType {
limits: Limits,
/// Whether or not this is a shared (atomic) memory type
shared: bool,
+ /// The custom page size for this memory, if any.
+ page_size_log2: Option<u32>,
},
/// A 64-bit memory
B64 {
@@ -465,21 +499,53 @@ pub enum MemoryType {
limits: Limits64,
/// Whether or not this is a shared (atomic) memory type
shared: bool,
+ /// The custom page size for this memory, if any.
+ page_size_log2: Option<u32>,
},
}
+fn page_size(parser: Parser<'_>) -> Result<Option<u32>> {
+ if parser.peek::<LParen>()? {
+ Ok(Some(parser.parens(|parser| {
+ parser.parse::<kw::pagesize>()?;
+ let span = parser.cur_span();
+ let size = parser.parse::<u32>()?;
+ if size.is_power_of_two() {
+ Ok(size.ilog2())
+ } else {
+ Err(Error::new(
+ span,
+ format!("invalid custom page size: {size}"),
+ ))
+ }
+ })?))
+ } else {
+ Ok(None)
+ }
+}
+
impl<'a> Parse<'a> for MemoryType {
fn parse(parser: Parser<'a>) -> Result<Self> {
if parser.peek::<kw::i64>()? {
parser.parse::<kw::i64>()?;
let limits = parser.parse()?;
let shared = parser.parse::<Option<kw::shared>>()?.is_some();
- Ok(MemoryType::B64 { limits, shared })
+ let page_size = page_size(parser)?;
+ Ok(MemoryType::B64 {
+ limits,
+ shared,
+ page_size_log2: page_size,
+ })
} else {
parser.parse::<Option<kw::i32>>()?;
let limits = parser.parse()?;
let shared = parser.parse::<Option<kw::shared>>()?.is_some();
- Ok(MemoryType::B32 { limits, shared })
+ let page_size = page_size(parser)?;
+ Ok(MemoryType::B32 {
+ limits,
+ shared,
+ page_size_log2: page_size,
+ })
}
}
}
diff --git a/third_party/rust/wast/src/core/wast.rs b/third_party/rust/wast/src/core/wast.rs
index 2d3b51b061..9dd9a92391 100644
--- a/third_party/rust/wast/src/core/wast.rs
+++ b/third_party/rust/wast/src/core/wast.rs
@@ -1,7 +1,7 @@
use crate::core::{HeapType, V128Const};
use crate::kw;
use crate::parser::{Cursor, Parse, Parser, Peek, Result};
-use crate::token::{Float32, Float64, Index};
+use crate::token::{Index, F32, F64};
/// Expression that can be used inside of `invoke` expressions for core wasm
/// functions.
@@ -10,8 +10,8 @@ use crate::token::{Float32, Float64, Index};
pub enum WastArgCore<'a> {
I32(i32),
I64(i64),
- F32(Float32),
- F64(Float64),
+ F32(F32),
+ F64(F64),
V128(V128Const),
RefNull(HeapType<'a>),
RefExtern(u32),
@@ -67,8 +67,8 @@ impl Peek for WastArgCore<'_> {
pub enum WastRetCore<'a> {
I32(i32),
I64(i64),
- F32(NanPattern<Float32>),
- F64(NanPattern<Float64>),
+ F32(NanPattern<F32>),
+ F64(NanPattern<F64>),
V128(V128Pattern),
/// A null reference is expected, optionally with a specified type.
@@ -151,7 +151,7 @@ impl Peek for WastRetCore<'_> {
}
/// Either a NaN pattern (`nan:canonical`, `nan:arithmetic`) or a value of type `T`.
-#[derive(Debug, PartialEq)]
+#[derive(Copy, Clone, Debug, PartialEq)]
#[allow(missing_docs)]
pub enum NanPattern<T> {
CanonicalNan,
@@ -181,15 +181,15 @@ where
///
/// This implementation is necessary because only float types can include NaN patterns; otherwise
/// it is largely similar to the implementation of `V128Const`.
-#[derive(Debug)]
+#[derive(Clone, Debug)]
#[allow(missing_docs)]
pub enum V128Pattern {
I8x16([i8; 16]),
I16x8([i16; 8]),
I32x4([i32; 4]),
I64x2([i64; 2]),
- F32x4([NanPattern<Float32>; 4]),
- F64x2([NanPattern<Float64>; 2]),
+ F32x4([NanPattern<F32>; 4]),
+ F64x2([NanPattern<F64>; 2]),
}
impl<'a> Parse<'a> for V128Pattern {