diff options
Diffstat (limited to 'third_party/rust/wast/src/core')
-rw-r--r-- | third_party/rust/wast/src/core/binary.rs | 84 | ||||
-rw-r--r-- | third_party/rust/wast/src/core/expr.rs | 158 | ||||
-rw-r--r-- | third_party/rust/wast/src/core/memory.rs | 11 | ||||
-rw-r--r-- | third_party/rust/wast/src/core/resolve/deinline_import_export.rs | 6 | ||||
-rw-r--r-- | third_party/rust/wast/src/core/resolve/names.rs | 28 | ||||
-rw-r--r-- | third_party/rust/wast/src/core/resolve/types.rs | 4 | ||||
-rw-r--r-- | third_party/rust/wast/src/core/types.rs | 78 | ||||
-rw-r--r-- | third_party/rust/wast/src/core/wast.rs | 18 |
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 { |