diff --git a/Cargo.lock b/Cargo.lock index 76e9d096e8b..247f9017179 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2527,9 +2527,9 @@ dependencies = [ [[package]] name = "wasmparser" -version = "0.57.0" +version = "0.65.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32fddd575d477c6e9702484139cf9f23dcd554b06d185ed0f56c857dd3a47aa6" +checksum = "87cc2fe6350834b4e528ba0901e7aa405d78b89dc1fa3145359eb4de0e323fcf" [[package]] name = "wast" diff --git a/lib/compiler-cranelift/src/sink.rs b/lib/compiler-cranelift/src/sink.rs index 8a2b39eb3b6..faa6e2807db 100644 --- a/lib/compiler-cranelift/src/sink.rs +++ b/lib/compiler-cranelift/src/sink.rs @@ -3,7 +3,7 @@ use crate::translator::{irlibcall_to_libcall, irreloc_to_relocationkind}; use cranelift_codegen::binemit; use cranelift_codegen::ir::{self, ExternalName}; -use wasmer_compiler::{JumpTable, Relocation, RelocationTarget, SourceLoc, TrapInformation}; +use wasmer_compiler::{JumpTable, Relocation, RelocationTarget, TrapInformation}; use wasmer_types::entity::EntityRef; use wasmer_types::{FunctionIndex, LocalFunctionIndex}; use wasmer_vm::{ModuleInfo, TrapCode}; diff --git a/lib/compiler-cranelift/src/translator/code_translator.rs b/lib/compiler-cranelift/src/translator/code_translator.rs index 6d3e9867061..f324ef8b458 100644 --- a/lib/compiler-cranelift/src/translator/code_translator.rs +++ b/lib/compiler-cranelift/src/translator/code_translator.rs @@ -386,9 +386,13 @@ pub fn translate_operator( } Operator::BrIf { relative_depth } => translate_br_if(*relative_depth, builder, state), Operator::BrTable { table } => { - let (depths, default) = table.read_table().map_err(to_wasm_error)?; + let mut depths = table + .targets() + .collect::, _>>() + .map_err(to_wasm_error)?; + let default = depths.pop().unwrap().0; let mut min_depth = default; - for depth in &*depths { + for (depth, _) in &*depths { if *depth < min_depth { min_depth = *depth; } @@ -406,7 +410,7 @@ pub fn translate_operator( let mut data = JumpTableData::with_capacity(depths.len()); if jump_args_count == 0 { // No jump arguments - for depth in &*depths { + for (depth, _) in &*depths { let block = { let i = state.control_stack.len() - 1 - (*depth as usize); let frame = &mut state.control_stack[i]; @@ -429,7 +433,7 @@ pub fn translate_operator( let return_count = jump_args_count; let mut dest_block_sequence = vec![]; let mut dest_block_map = HashMap::new(); - for depth in &*depths { + for (depth, _) in &*depths { let branch_block = match dest_block_map.entry(*depth as usize) { hash_map::Entry::Occupied(entry) => *entry.get(), hash_map::Entry::Vacant(entry) => { @@ -569,17 +573,17 @@ pub fn translate_operator( * Memory management is handled by environment. It is usually translated into calls to * special functions. ************************************************************************************/ - Operator::MemoryGrow { reserved } => { + Operator::MemoryGrow { mem, mem_byte: _ } => { // The WebAssembly MVP only supports one linear memory, but we expect the reserved // argument to be a memory index. - let heap_index = MemoryIndex::from_u32(*reserved); - let heap = state.get_heap(builder.func, *reserved, environ)?; + let heap_index = MemoryIndex::from_u32(*mem); + let heap = state.get_heap(builder.func, *mem, environ)?; let val = state.pop1(); state.push1(environ.translate_memory_grow(builder.cursor(), heap_index, heap, val)?) } - Operator::MemorySize { reserved } => { - let heap_index = MemoryIndex::from_u32(*reserved); - let heap = state.get_heap(builder.func, *reserved, environ)?; + Operator::MemorySize { mem, mem_byte: _ } => { + let heap_index = MemoryIndex::from_u32(*mem); + let heap = state.get_heap(builder.func, *mem, environ)?; state.push1(environ.translate_memory_size(builder.cursor(), heap_index, heap)?); } /******************************* Load instructions *********************************** @@ -587,117 +591,117 @@ pub fn translate_operator( * The memory base address is provided by the environment. ************************************************************************************/ Operator::I32Load8U { - memarg: MemoryImmediate { flags: _, offset }, + memarg: MemoryImmediate { offset, .. }, } => { translate_load(*offset, ir::Opcode::Uload8, I32, builder, state, environ)?; } Operator::I32Load16U { - memarg: MemoryImmediate { flags: _, offset }, + memarg: MemoryImmediate { offset, .. }, } => { translate_load(*offset, ir::Opcode::Uload16, I32, builder, state, environ)?; } Operator::I32Load8S { - memarg: MemoryImmediate { flags: _, offset }, + memarg: MemoryImmediate { offset, .. }, } => { translate_load(*offset, ir::Opcode::Sload8, I32, builder, state, environ)?; } Operator::I32Load16S { - memarg: MemoryImmediate { flags: _, offset }, + memarg: MemoryImmediate { offset, .. }, } => { translate_load(*offset, ir::Opcode::Sload16, I32, builder, state, environ)?; } Operator::I64Load8U { - memarg: MemoryImmediate { flags: _, offset }, + memarg: MemoryImmediate { offset, .. }, } => { translate_load(*offset, ir::Opcode::Uload8, I64, builder, state, environ)?; } Operator::I64Load16U { - memarg: MemoryImmediate { flags: _, offset }, + memarg: MemoryImmediate { offset, .. }, } => { translate_load(*offset, ir::Opcode::Uload16, I64, builder, state, environ)?; } Operator::I64Load8S { - memarg: MemoryImmediate { flags: _, offset }, + memarg: MemoryImmediate { offset, .. }, } => { translate_load(*offset, ir::Opcode::Sload8, I64, builder, state, environ)?; } Operator::I64Load16S { - memarg: MemoryImmediate { flags: _, offset }, + memarg: MemoryImmediate { offset, .. }, } => { translate_load(*offset, ir::Opcode::Sload16, I64, builder, state, environ)?; } Operator::I64Load32S { - memarg: MemoryImmediate { flags: _, offset }, + memarg: MemoryImmediate { offset, .. }, } => { translate_load(*offset, ir::Opcode::Sload32, I64, builder, state, environ)?; } Operator::I64Load32U { - memarg: MemoryImmediate { flags: _, offset }, + memarg: MemoryImmediate { offset, .. }, } => { translate_load(*offset, ir::Opcode::Uload32, I64, builder, state, environ)?; } Operator::I32Load { - memarg: MemoryImmediate { flags: _, offset }, + memarg: MemoryImmediate { offset, .. }, } => { translate_load(*offset, ir::Opcode::Load, I32, builder, state, environ)?; } Operator::F32Load { - memarg: MemoryImmediate { flags: _, offset }, + memarg: MemoryImmediate { offset, .. }, } => { translate_load(*offset, ir::Opcode::Load, F32, builder, state, environ)?; } Operator::I64Load { - memarg: MemoryImmediate { flags: _, offset }, + memarg: MemoryImmediate { offset, .. }, } => { translate_load(*offset, ir::Opcode::Load, I64, builder, state, environ)?; } Operator::F64Load { - memarg: MemoryImmediate { flags: _, offset }, + memarg: MemoryImmediate { offset, .. }, } => { translate_load(*offset, ir::Opcode::Load, F64, builder, state, environ)?; } Operator::V128Load { - memarg: MemoryImmediate { flags: _, offset }, + memarg: MemoryImmediate { offset, .. }, } => { translate_load(*offset, ir::Opcode::Load, I8X16, builder, state, environ)?; } - Operator::I16x8Load8x8S { - memarg: MemoryImmediate { flags: _, offset }, + Operator::V128Load8x8S { + memarg: MemoryImmediate { offset, .. }, } => { let (flags, base, offset) = prepare_load(*offset, 8, builder, state, environ)?; let loaded = builder.ins().sload8x8(flags, base, offset); state.push1(loaded); } - Operator::I16x8Load8x8U { - memarg: MemoryImmediate { flags: _, offset }, + Operator::V128Load8x8U { + memarg: MemoryImmediate { offset, .. }, } => { let (flags, base, offset) = prepare_load(*offset, 8, builder, state, environ)?; let loaded = builder.ins().uload8x8(flags, base, offset); state.push1(loaded); } - Operator::I32x4Load16x4S { - memarg: MemoryImmediate { flags: _, offset }, + Operator::V128Load16x4S { + memarg: MemoryImmediate { offset, .. }, } => { let (flags, base, offset) = prepare_load(*offset, 8, builder, state, environ)?; let loaded = builder.ins().sload16x4(flags, base, offset); state.push1(loaded); } - Operator::I32x4Load16x4U { - memarg: MemoryImmediate { flags: _, offset }, + Operator::V128Load16x4U { + memarg: MemoryImmediate { offset, .. }, } => { let (flags, base, offset) = prepare_load(*offset, 8, builder, state, environ)?; let loaded = builder.ins().uload16x4(flags, base, offset); state.push1(loaded); } - Operator::I64x2Load32x2S { - memarg: MemoryImmediate { flags: _, offset }, + Operator::V128Load32x2S { + memarg: MemoryImmediate { offset, .. }, } => { let (flags, base, offset) = prepare_load(*offset, 8, builder, state, environ)?; let loaded = builder.ins().sload32x2(flags, base, offset); state.push1(loaded); } - Operator::I64x2Load32x2U { - memarg: MemoryImmediate { flags: _, offset }, + Operator::V128Load32x2U { + memarg: MemoryImmediate { offset, .. }, } => { let (flags, base, offset) = prepare_load(*offset, 8, builder, state, environ)?; let loaded = builder.ins().uload32x2(flags, base, offset); @@ -708,42 +712,42 @@ pub fn translate_operator( * The memory base address is provided by the environment. ************************************************************************************/ Operator::I32Store { - memarg: MemoryImmediate { flags: _, offset }, + memarg: MemoryImmediate { offset, .. }, } | Operator::I64Store { - memarg: MemoryImmediate { flags: _, offset }, + memarg: MemoryImmediate { offset, .. }, } | Operator::F32Store { - memarg: MemoryImmediate { flags: _, offset }, + memarg: MemoryImmediate { offset, .. }, } | Operator::F64Store { - memarg: MemoryImmediate { flags: _, offset }, + memarg: MemoryImmediate { offset, .. }, } => { translate_store(*offset, ir::Opcode::Store, builder, state, environ)?; } Operator::I32Store8 { - memarg: MemoryImmediate { flags: _, offset }, + memarg: MemoryImmediate { offset, .. }, } | Operator::I64Store8 { - memarg: MemoryImmediate { flags: _, offset }, + memarg: MemoryImmediate { offset, .. }, } => { translate_store(*offset, ir::Opcode::Istore8, builder, state, environ)?; } Operator::I32Store16 { - memarg: MemoryImmediate { flags: _, offset }, + memarg: MemoryImmediate { offset, .. }, } | Operator::I64Store16 { - memarg: MemoryImmediate { flags: _, offset }, + memarg: MemoryImmediate { offset, .. }, } => { translate_store(*offset, ir::Opcode::Istore16, builder, state, environ)?; } Operator::I64Store32 { - memarg: MemoryImmediate { flags: _, offset }, + memarg: MemoryImmediate { offset, .. }, } => { translate_store(*offset, ir::Opcode::Istore32, builder, state, environ)?; } Operator::V128Store { - memarg: MemoryImmediate { flags: _, offset }, + memarg: MemoryImmediate { offset, .. }, } => { translate_store(*offset, ir::Opcode::Store, builder, state, environ)?; } @@ -1043,7 +1047,7 @@ pub fn translate_operator( translate_fcmp(FloatCC::LessThanOrEqual, builder, state) } Operator::RefNull { ty: _ } => state.push1(builder.ins().null(environ.reference_type())), - Operator::RefIsNull { ty: _ } => { + Operator::RefIsNull => { let arg = state.pop1(); let val = builder.ins().is_null(arg); let val_int = builder.ins().bint(I32, val); @@ -1052,9 +1056,9 @@ pub fn translate_operator( Operator::RefFunc { function_index } => { state.push1(environ.translate_ref_func(builder.cursor(), *function_index)?); } - Operator::AtomicNotify { .. } - | Operator::I32AtomicWait { .. } - | Operator::I64AtomicWait { .. } + Operator::MemoryAtomicNotify { .. } + | Operator::MemoryAtomicWait32 { .. } + | Operator::MemoryAtomicWait64 { .. } | Operator::I32AtomicLoad { .. } | Operator::I64AtomicLoad { .. } | Operator::I32AtomicLoad8U { .. } @@ -1121,7 +1125,7 @@ pub fn translate_operator( | Operator::AtomicFence { .. } => { return Err(wasm_unsupported!("proposed thread operator {:?}", op)); } - Operator::MemoryCopy => { + Operator::MemoryCopy { .. } => { // The WebAssembly MVP only supports one linear memory and // wasmparser will ensure that the memory indices specified are // zero. @@ -1132,7 +1136,7 @@ pub fn translate_operator( let dest = state.pop1(); environ.translate_memory_copy(builder.cursor(), heap_index, heap, dest, src, len)?; } - Operator::MemoryFill => { + Operator::MemoryFill { .. } => { // The WebAssembly MVP only supports one linear memory and // wasmparser will ensure that the memory index specified is // zero. @@ -1143,7 +1147,7 @@ pub fn translate_operator( let dest = state.pop1(); environ.translate_memory_fill(builder.cursor(), heap_index, heap, dest, val, len)?; } - Operator::MemoryInit { segment } => { + Operator::MemoryInit { segment, mem: _ } => { // The WebAssembly MVP only supports one linear memory and // wasmparser will ensure that the memory index specified is // zero. @@ -1262,17 +1266,17 @@ pub fn translate_operator( let splatted = builder.ins().splat(type_of(op), state.pop1()); state.push1(splatted) } - Operator::V8x16LoadSplat { - memarg: MemoryImmediate { flags: _, offset }, + Operator::V128Load8Splat { + memarg: MemoryImmediate { offset, .. }, } - | Operator::V16x8LoadSplat { - memarg: MemoryImmediate { flags: _, offset }, + | Operator::V128Load16Splat { + memarg: MemoryImmediate { offset, .. }, } - | Operator::V32x4LoadSplat { - memarg: MemoryImmediate { flags: _, offset }, + | Operator::V128Load32Splat { + memarg: MemoryImmediate { offset, .. }, } - | Operator::V64x2LoadSplat { - memarg: MemoryImmediate { flags: _, offset }, + | Operator::V128Load64Splat { + memarg: MemoryImmediate { offset, .. }, } => { // TODO: For spec compliance, this is initially implemented as a combination of `load + // splat` but could be implemented eventually as a single instruction (`load_splat`). @@ -1323,7 +1327,7 @@ pub fn translate_operator( let vector = optionally_bitcast_vector(vector, type_of(op), builder); state.push1(builder.ins().insertlane(vector, replacement, *lane)) } - Operator::V8x16Shuffle { lanes, .. } => { + Operator::I8x16Shuffle { lanes, .. } => { let (a, b) = pop2_with_bitcast(state, I8X16, builder); let lanes = ConstantData::from(lanes.as_ref()); let mask = builder.func.dfg.immediates.push(lanes); @@ -1334,7 +1338,7 @@ pub fn translate_operator( // to WASM using the less specific v128 type for certain operations and more specific // types (e.g. i8x16) for others. } - Operator::V8x16Swizzle => { + Operator::I8x16Swizzle => { let (a, b) = pop2_with_bitcast(state, I8X16, builder); state.push1(builder.ins().swizzle(I8X16, a, b)) } @@ -1342,11 +1346,11 @@ pub fn translate_operator( let (a, b) = pop2_with_bitcast(state, type_of(op), builder); state.push1(builder.ins().iadd(a, b)) } - Operator::I8x16AddSaturateS | Operator::I16x8AddSaturateS => { + Operator::I8x16AddSatS | Operator::I16x8AddSatS => { let (a, b) = pop2_with_bitcast(state, type_of(op), builder); state.push1(builder.ins().sadd_sat(a, b)) } - Operator::I8x16AddSaturateU | Operator::I16x8AddSaturateU => { + Operator::I8x16AddSatU | Operator::I16x8AddSatU => { let (a, b) = pop2_with_bitcast(state, type_of(op), builder); state.push1(builder.ins().uadd_sat(a, b)) } @@ -1354,11 +1358,11 @@ pub fn translate_operator( let (a, b) = pop2_with_bitcast(state, type_of(op), builder); state.push1(builder.ins().isub(a, b)) } - Operator::I8x16SubSaturateS | Operator::I16x8SubSaturateS => { + Operator::I8x16SubSatS | Operator::I16x8SubSatS => { let (a, b) = pop2_with_bitcast(state, type_of(op), builder); state.push1(builder.ins().ssub_sat(a, b)) } - Operator::I8x16SubSaturateU | Operator::I16x8SubSaturateU => { + Operator::I8x16SubSatU | Operator::I16x8SubSatU => { let (a, b) = pop2_with_bitcast(state, type_of(op), builder); state.push1(builder.ins().usub_sat(a, b)) } @@ -1556,6 +1560,7 @@ pub fn translate_operator( | Operator::I8x16Abs | Operator::I16x8Abs | Operator::I32x4Abs + | Operator::I32x4DotI16x8S | Operator::I8x16NarrowI16x8S { .. } | Operator::I8x16NarrowI16x8U { .. } | Operator::I16x8NarrowI32x4S { .. } @@ -1567,7 +1572,24 @@ pub fn translate_operator( | Operator::I32x4WidenLowI16x8S { .. } | Operator::I32x4WidenHighI16x8S { .. } | Operator::I32x4WidenLowI16x8U { .. } - | Operator::I32x4WidenHighI16x8U { .. } => { + | Operator::I32x4WidenHighI16x8U { .. } + | Operator::I8x16Bitmask + | Operator::I16x8Bitmask + | Operator::I32x4Bitmask + | Operator::F32x4Ceil + | Operator::F32x4Floor + | Operator::F32x4Trunc + | Operator::F32x4Nearest + | Operator::F64x2Ceil + | Operator::F64x2Floor + | Operator::F64x2Trunc + | Operator::F64x2Nearest + | Operator::F32x4PMin + | Operator::F32x4PMax + | Operator::F64x2PMin + | Operator::F64x2PMax + | Operator::V128Load32Zero { .. } + | Operator::V128Load64Zero { .. } => { return Err(wasm_unsupported!("proposed SIMD operator {:?}", op)); } @@ -1967,9 +1989,9 @@ fn type_of(operator: &Operator) -> Type { | Operator::V128Xor | Operator::V128Bitselect => I8X16, // default type representing V128 - Operator::V8x16Shuffle { .. } + Operator::I8x16Shuffle { .. } | Operator::I8x16Splat - | Operator::V8x16LoadSplat { .. } + | Operator::V128Load8Splat { .. } | Operator::I8x16ExtractLaneS { .. } | Operator::I8x16ExtractLaneU { .. } | Operator::I8x16ReplaceLane { .. } @@ -1990,11 +2012,11 @@ fn type_of(operator: &Operator) -> Type { | Operator::I8x16ShrS | Operator::I8x16ShrU | Operator::I8x16Add - | Operator::I8x16AddSaturateS - | Operator::I8x16AddSaturateU + | Operator::I8x16AddSatS + | Operator::I8x16AddSatU | Operator::I8x16Sub - | Operator::I8x16SubSaturateS - | Operator::I8x16SubSaturateU + | Operator::I8x16SubSatS + | Operator::I8x16SubSatU | Operator::I8x16MinS | Operator::I8x16MinU | Operator::I8x16MaxS @@ -2002,7 +2024,7 @@ fn type_of(operator: &Operator) -> Type { | Operator::I8x16RoundingAverageU => I8X16, Operator::I16x8Splat - | Operator::V16x8LoadSplat { .. } + | Operator::V128Load16Splat { .. } | Operator::I16x8ExtractLaneS { .. } | Operator::I16x8ExtractLaneU { .. } | Operator::I16x8ReplaceLane { .. } @@ -2023,11 +2045,11 @@ fn type_of(operator: &Operator) -> Type { | Operator::I16x8ShrS | Operator::I16x8ShrU | Operator::I16x8Add - | Operator::I16x8AddSaturateS - | Operator::I16x8AddSaturateU + | Operator::I16x8AddSatS + | Operator::I16x8AddSatU | Operator::I16x8Sub - | Operator::I16x8SubSaturateS - | Operator::I16x8SubSaturateU + | Operator::I16x8SubSatS + | Operator::I16x8SubSatU | Operator::I16x8MinS | Operator::I16x8MinU | Operator::I16x8MaxS @@ -2036,7 +2058,7 @@ fn type_of(operator: &Operator) -> Type { | Operator::I16x8Mul => I16X8, Operator::I32x4Splat - | Operator::V32x4LoadSplat { .. } + | Operator::V128Load32Splat { .. } | Operator::I32x4ExtractLane { .. } | Operator::I32x4ReplaceLane { .. } | Operator::I32x4Eq @@ -2066,7 +2088,7 @@ fn type_of(operator: &Operator) -> Type { | Operator::F32x4ConvertI32x4U => I32X4, Operator::I64x2Splat - | Operator::V64x2LoadSplat { .. } + | Operator::V128Load64Splat { .. } | Operator::I64x2ExtractLane { .. } | Operator::I64x2ReplaceLane { .. } | Operator::I64x2Neg diff --git a/lib/compiler-llvm/src/translator/code.rs b/lib/compiler-llvm/src/translator/code.rs index 6195b023fb1..b20f3f779a2 100644 --- a/lib/compiler-llvm/src/translator/code.rs +++ b/lib/compiler-llvm/src/translator/code.rs @@ -1110,21 +1110,13 @@ impl<'ctx, 'a> LLVMFunctionCodeGenerator<'ctx, 'a> { } fn trap_if_misaligned(&self, memarg: &MemoryImmediate, ptr: PointerValue<'ctx>) { - let align = match memarg.flags & 3 { - 0 => { - return; /* No alignment to check. */ - } - 1 => 2, - 2 => 4, - 3 => 8, - _ => unreachable!("this match is fully covered"), - }; + let align = memarg.align; let value = self .builder .build_ptr_to_int(ptr, self.intrinsics.i64_ty, ""); let and = self.builder.build_and( value, - self.intrinsics.i64_ty.const_int(align - 1, false), + self.intrinsics.i64_ty.const_int((align - 1).into(), false), "misaligncheck", ); let aligned = @@ -1541,7 +1533,11 @@ impl<'ctx, 'a> LLVMFunctionCodeGenerator<'ctx, 'a> { .get_insert_block() .ok_or_else(|| CompileError::Codegen("not currently in a block".to_string()))?; - let (label_depths, default_depth) = table.read_table().map_err(to_wasm_error)?; + let mut label_depths = table + .targets() + .collect::, _>>() + .map_err(to_wasm_error)?; + let default_depth = label_depths.pop().unwrap().0; let index = self.state.pop1()?; @@ -1561,7 +1557,7 @@ impl<'ctx, 'a> LLVMFunctionCodeGenerator<'ctx, 'a> { let cases: Vec<_> = label_depths .iter() .enumerate() - .map(|(case_index, &depth)| { + .map(|(case_index, &(depth, _))| { let frame_result: Result<&ControlFrame, CompileError> = self.state.frame_at_depth(depth); let frame = match frame_result { @@ -2495,7 +2491,7 @@ impl<'ctx, 'a> LLVMFunctionCodeGenerator<'ctx, 'a> { let res = self.builder.build_bitcast(res, self.intrinsics.i128_ty, ""); self.state.push1(res); } - Operator::I8x16AddSaturateS => { + Operator::I8x16AddSatS => { let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?; let (v1, _) = self.v128_into_i8x16(v1, i1); let (v2, _) = self.v128_into_i8x16(v2, i2); @@ -2512,7 +2508,7 @@ impl<'ctx, 'a> LLVMFunctionCodeGenerator<'ctx, 'a> { let res = self.builder.build_bitcast(res, self.intrinsics.i128_ty, ""); self.state.push1(res); } - Operator::I16x8AddSaturateS => { + Operator::I16x8AddSatS => { let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?; let (v1, _) = self.v128_into_i16x8(v1, i1); let (v2, _) = self.v128_into_i16x8(v2, i2); @@ -2529,7 +2525,7 @@ impl<'ctx, 'a> LLVMFunctionCodeGenerator<'ctx, 'a> { let res = self.builder.build_bitcast(res, self.intrinsics.i128_ty, ""); self.state.push1(res); } - Operator::I8x16AddSaturateU => { + Operator::I8x16AddSatU => { let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?; let (v1, _) = self.v128_into_i8x16(v1, i1); let (v2, _) = self.v128_into_i8x16(v2, i2); @@ -2546,7 +2542,7 @@ impl<'ctx, 'a> LLVMFunctionCodeGenerator<'ctx, 'a> { let res = self.builder.build_bitcast(res, self.intrinsics.i128_ty, ""); self.state.push1(res); } - Operator::I16x8AddSaturateU => { + Operator::I16x8AddSatU => { let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?; let (v1, _) = self.v128_into_i16x8(v1, i1); let (v2, _) = self.v128_into_i16x8(v2, i2); @@ -2603,7 +2599,7 @@ impl<'ctx, 'a> LLVMFunctionCodeGenerator<'ctx, 'a> { let res = self.builder.build_bitcast(res, self.intrinsics.i128_ty, ""); self.state.push1(res); } - Operator::I8x16SubSaturateS => { + Operator::I8x16SubSatS => { let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?; let (v1, _) = self.v128_into_i8x16(v1, i1); let (v2, _) = self.v128_into_i8x16(v2, i2); @@ -2620,7 +2616,7 @@ impl<'ctx, 'a> LLVMFunctionCodeGenerator<'ctx, 'a> { let res = self.builder.build_bitcast(res, self.intrinsics.i128_ty, ""); self.state.push1(res); } - Operator::I16x8SubSaturateS => { + Operator::I16x8SubSatS => { let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?; let (v1, _) = self.v128_into_i16x8(v1, i1); let (v2, _) = self.v128_into_i16x8(v2, i2); @@ -2637,7 +2633,7 @@ impl<'ctx, 'a> LLVMFunctionCodeGenerator<'ctx, 'a> { let res = self.builder.build_bitcast(res, self.intrinsics.i128_ty, ""); self.state.push1(res); } - Operator::I8x16SubSaturateU => { + Operator::I8x16SubSatU => { let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?; let (v1, _) = self.v128_into_i8x16(v1, i1); let (v2, _) = self.v128_into_i8x16(v2, i2); @@ -2654,7 +2650,7 @@ impl<'ctx, 'a> LLVMFunctionCodeGenerator<'ctx, 'a> { let res = self.builder.build_bitcast(res, self.intrinsics.i128_ty, ""); self.state.push1(res); } - Operator::I16x8SubSaturateU => { + Operator::I16x8SubSatU => { let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?; let (v1, _) = self.v128_into_i16x8(v1, i1); let (v2, _) = self.v128_into_i16x8(v2, i2); @@ -6975,7 +6971,7 @@ impl<'ctx, 'a> LLVMFunctionCodeGenerator<'ctx, 'a> { }; self.state.push1_extra(res, info); } - Operator::V8x16Swizzle => { + Operator::I8x16Swizzle => { let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?; let v1 = self.apply_pending_canonicalization(v1, i1); let v1 = self @@ -7043,7 +7039,7 @@ impl<'ctx, 'a> LLVMFunctionCodeGenerator<'ctx, 'a> { let res = self.builder.build_bitcast(res, self.intrinsics.i128_ty, ""); self.state.push1(res); } - Operator::V8x16Shuffle { lanes } => { + Operator::I8x16Shuffle { lanes } => { let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?; let v1 = self.apply_pending_canonicalization(v1, i1); let v1 = self @@ -7066,7 +7062,7 @@ impl<'ctx, 'a> LLVMFunctionCodeGenerator<'ctx, 'a> { let res = self.builder.build_bitcast(res, self.intrinsics.i128_ty, ""); self.state.push1(res); } - Operator::I16x8Load8x8S { ref memarg } => { + Operator::V128Load8x8S { ref memarg } => { let offset = self.state.pop1()?.into_int_value(); let memory_index = MemoryIndex::from_u32(0); let effective_address = self.resolve_memory_ptr( @@ -7087,7 +7083,7 @@ impl<'ctx, 'a> LLVMFunctionCodeGenerator<'ctx, 'a> { let res = self.builder.build_bitcast(res, self.intrinsics.i128_ty, ""); self.state.push1(res); } - Operator::I16x8Load8x8U { ref memarg } => { + Operator::V128Load8x8U { ref memarg } => { let offset = self.state.pop1()?.into_int_value(); let memory_index = MemoryIndex::from_u32(0); let effective_address = self.resolve_memory_ptr( @@ -7108,7 +7104,7 @@ impl<'ctx, 'a> LLVMFunctionCodeGenerator<'ctx, 'a> { let res = self.builder.build_bitcast(res, self.intrinsics.i128_ty, ""); self.state.push1(res); } - Operator::I32x4Load16x4S { ref memarg } => { + Operator::V128Load16x4S { ref memarg } => { let offset = self.state.pop1()?.into_int_value(); let memory_index = MemoryIndex::from_u32(0); let effective_address = self.resolve_memory_ptr( @@ -7129,7 +7125,7 @@ impl<'ctx, 'a> LLVMFunctionCodeGenerator<'ctx, 'a> { let res = self.builder.build_bitcast(res, self.intrinsics.i128_ty, ""); self.state.push1(res); } - Operator::I32x4Load16x4U { ref memarg } => { + Operator::V128Load16x4U { ref memarg } => { let offset = self.state.pop1()?.into_int_value(); let memory_index = MemoryIndex::from_u32(0); let effective_address = self.resolve_memory_ptr( @@ -7150,7 +7146,7 @@ impl<'ctx, 'a> LLVMFunctionCodeGenerator<'ctx, 'a> { let res = self.builder.build_bitcast(res, self.intrinsics.i128_ty, ""); self.state.push1(res); } - Operator::I64x2Load32x2S { ref memarg } => { + Operator::V128Load32x2S { ref memarg } => { let offset = self.state.pop1()?.into_int_value(); let memory_index = MemoryIndex::from_u32(0); let effective_address = self.resolve_memory_ptr( @@ -7171,7 +7167,7 @@ impl<'ctx, 'a> LLVMFunctionCodeGenerator<'ctx, 'a> { let res = self.builder.build_bitcast(res, self.intrinsics.i128_ty, ""); self.state.push1(res); } - Operator::I64x2Load32x2U { ref memarg } => { + Operator::V128Load32x2U { ref memarg } => { let offset = self.state.pop1()?.into_int_value(); let memory_index = MemoryIndex::from_u32(0); let effective_address = self.resolve_memory_ptr( @@ -7192,7 +7188,7 @@ impl<'ctx, 'a> LLVMFunctionCodeGenerator<'ctx, 'a> { let res = self.builder.build_bitcast(res, self.intrinsics.i128_ty, ""); self.state.push1(res); } - Operator::V8x16LoadSplat { ref memarg } => { + Operator::V128Load8Splat { ref memarg } => { let offset = self.state.pop1()?.into_int_value(); let memory_index = MemoryIndex::from_u32(0); let effective_address = self.resolve_memory_ptr( @@ -7213,7 +7209,7 @@ impl<'ctx, 'a> LLVMFunctionCodeGenerator<'ctx, 'a> { let res = self.builder.build_bitcast(res, self.intrinsics.i128_ty, ""); self.state.push1(res); } - Operator::V16x8LoadSplat { ref memarg } => { + Operator::V128Load16Splat { ref memarg } => { let offset = self.state.pop1()?.into_int_value(); let memory_index = MemoryIndex::from_u32(0); let effective_address = self.resolve_memory_ptr( @@ -7234,7 +7230,7 @@ impl<'ctx, 'a> LLVMFunctionCodeGenerator<'ctx, 'a> { let res = self.builder.build_bitcast(res, self.intrinsics.i128_ty, ""); self.state.push1(res); } - Operator::V32x4LoadSplat { ref memarg } => { + Operator::V128Load32Splat { ref memarg } => { let offset = self.state.pop1()?.into_int_value(); let memory_index = MemoryIndex::from_u32(0); let effective_address = self.resolve_memory_ptr( @@ -7255,7 +7251,7 @@ impl<'ctx, 'a> LLVMFunctionCodeGenerator<'ctx, 'a> { let res = self.builder.build_bitcast(res, self.intrinsics.i128_ty, ""); self.state.push1(res); } - Operator::V64x2LoadSplat { ref memarg } => { + Operator::V128Load64Splat { ref memarg } => { let offset = self.state.pop1()?.into_int_value(); let memory_index = MemoryIndex::from_u32(0); let effective_address = self.resolve_memory_ptr( @@ -9246,8 +9242,8 @@ impl<'ctx, 'a> LLVMFunctionCodeGenerator<'ctx, 'a> { self.state.push1(old); } - Operator::MemoryGrow { reserved } => { - let memory_index = MemoryIndex::from_u32(reserved); + Operator::MemoryGrow { mem, mem_byte: _ } => { + let memory_index = MemoryIndex::from_u32(mem); let delta = self.state.pop1()?; let grow_fn_ptr = self.ctx.memory_grow(memory_index, self.intrinsics); let grow = self.builder.build_call( @@ -9257,15 +9253,15 @@ impl<'ctx, 'a> LLVMFunctionCodeGenerator<'ctx, 'a> { delta, self.intrinsics .i32_ty - .const_int(reserved.into(), false) + .const_int(mem.into(), false) .as_basic_value_enum(), ], "", ); self.state.push1(grow.try_as_basic_value().left().unwrap()); } - Operator::MemorySize { reserved } => { - let memory_index = MemoryIndex::from_u32(reserved); + Operator::MemorySize { mem, mem_byte: _ } => { + let memory_index = MemoryIndex::from_u32(mem); let size_fn_ptr = self.ctx.memory_size(memory_index, self.intrinsics); let size = self.builder.build_call( size_fn_ptr, @@ -9273,7 +9269,7 @@ impl<'ctx, 'a> LLVMFunctionCodeGenerator<'ctx, 'a> { vmctx.as_basic_value_enum(), self.intrinsics .i32_ty - .const_int(reserved.into(), false) + .const_int(mem.into(), false) .as_basic_value_enum(), ], "", diff --git a/lib/compiler-singlepass/src/codegen_x64.rs b/lib/compiler-singlepass/src/codegen_x64.rs index aad3854ed58..a4f8dc9b4d1 100644 --- a/lib/compiler-singlepass/src/codegen_x64.rs +++ b/lib/compiler-singlepass/src/codegen_x64.rs @@ -1316,17 +1316,7 @@ impl<'a> FuncGen<'a> { self.machine.release_temp_gpr(tmp_bound); self.machine.release_temp_gpr(tmp_base); - let align = match memarg.flags & 3 { - 0 => 1, - 1 => 2, - 2 => 4, - 3 => 8, - _ => { - return Err(CodegenError { - message: "emit_memory_op align: unreachable value".to_string(), - }) - } - }; + let align = memarg.align; if check_alignment && align != 1 { let tmp_aligncheck = self.machine.acquire_temp_gpr().unwrap(); self.assembler.emit_mov( @@ -1336,7 +1326,7 @@ impl<'a> FuncGen<'a> { ); self.assembler.emit_and( Size::S64, - Location::Imm32(align - 1), + Location::Imm32((align - 1).into()), Location::GPR(tmp_aligncheck), ); self.assembler @@ -5615,8 +5605,8 @@ impl<'a> FuncGen<'a> { // TODO: Re-enable interrupt signal check without branching } Operator::Nop => {} - Operator::MemorySize { reserved } => { - let memory_index = MemoryIndex::new(reserved as usize); + Operator::MemorySize { mem, mem_byte: _ } => { + let memory_index = MemoryIndex::new(mem as usize); self.assembler.emit_mov( Size::S64, Location::Memory( @@ -5653,8 +5643,8 @@ impl<'a> FuncGen<'a> { self.assembler .emit_mov(Size::S64, Location::GPR(GPR::RAX), ret); } - Operator::MemoryGrow { reserved } => { - let memory_index = MemoryIndex::new(reserved as usize); + Operator::MemoryGrow { mem, mem_byte: _ } => { + let memory_index = MemoryIndex::new(mem as usize); let param_pages = self.value_stack.pop().unwrap(); self.machine.release_locations_only_regs(&[param_pages]); @@ -6304,9 +6294,13 @@ impl<'a> FuncGen<'a> { self.assembler.emit_label(after); } Operator::BrTable { ref table } => { - let (targets, default_target) = table.read_table().map_err(|e| CodegenError { - message: format!("BrTable read_table: {:?}", e), - })?; + let mut targets = table + .targets() + .collect::, _>>() + .map_err(|e| CodegenError { + message: format!("BrTable read_table: {:?}", e), + })?; + let default_target = targets.pop().unwrap().0; let cond = self.pop_value_released(); let table_label = self.assembler.get_label(); let mut table: Vec = vec![]; @@ -6334,7 +6328,7 @@ impl<'a> FuncGen<'a> { ); self.assembler.emit_jmp_location(Location::GPR(GPR::RDX)); - for target in targets.iter() { + for (target, _) in targets.iter() { let label = self.assembler.get_label(); self.assembler.emit_label(label); table.push(label); diff --git a/lib/compiler/Cargo.toml b/lib/compiler/Cargo.toml index fc830edcda2..e96816410ee 100644 --- a/lib/compiler/Cargo.toml +++ b/lib/compiler/Cargo.toml @@ -13,7 +13,7 @@ edition = "2018" [dependencies] wasmer-vm = { path = "../vm", version = "1.0.0-alpha4" } wasmer-types = { path = "../wasmer-types", version = "1.0.0-alpha4", default-features = false } -wasmparser = { version = "0.57", optional = true, default-features = false } +wasmparser = { version = "0.65", optional = true, default-features = false } target-lexicon = { version = "0.10", default-features = false } enumset = "1.0" hashbrown = { version = "0.8", optional = true } diff --git a/lib/compiler/src/compiler.rs b/lib/compiler/src/compiler.rs index 75b3b081138..d94df768e5f 100644 --- a/lib/compiler/src/compiler.rs +++ b/lib/compiler/src/compiler.rs @@ -13,7 +13,7 @@ use crate::ModuleTranslationState; use crate::SectionIndex; use wasmer_types::entity::PrimaryMap; use wasmer_types::{Features, FunctionIndex, LocalFunctionIndex, SignatureIndex}; -use wasmparser::{validate, OperatorValidatorConfig, ValidatingParserConfig}; +use wasmparser::{Validator, WasmFeatures}; /// The compiler configuration options. pub trait CompilerConfig { @@ -58,17 +58,24 @@ pub trait Compiler { features: &Features, data: &'data [u8], ) -> Result<(), CompileError> { - let config = ValidatingParserConfig { - operator_config: OperatorValidatorConfig { - enable_threads: features.threads, - enable_reference_types: features.reference_types, - enable_bulk_memory: features.bulk_memory, - enable_tail_call: false, - enable_simd: features.simd, - enable_multi_value: features.multi_value, - }, + let mut validator = Validator::new(); + let wasm_features = WasmFeatures { + bulk_memory: features.bulk_memory, + threads: features.threads, + reference_types: features.reference_types, + multi_value: features.multi_value, + simd: features.simd, + tail_call: features.tail_call, + module_linking: features.module_linking, + multi_memory: features.multi_memory, + memory64: features.memory64, + deterministic_only: false, }; - validate(data, Some(config)).map_err(|e| CompileError::Validate(format!("{}", e))) + validator.wasm_features(wasm_features); + validator + .validate_all(data) + .map_err(|e| CompileError::Validate(format!("{}", e)))?; + Ok(()) } /// Compiles a parsed module. diff --git a/lib/compiler/src/translator/middleware.rs b/lib/compiler/src/translator/middleware.rs index 1c1672c8430..1bc329bab32 100644 --- a/lib/compiler/src/translator/middleware.rs +++ b/lib/compiler/src/translator/middleware.rs @@ -94,13 +94,15 @@ impl<'a> MiddlewareBinaryReader<'a> { } /// Read a `count` indicating the number of times to call `read_local_decl`. - pub fn read_local_count(&mut self) -> WpResult { - self.state.inner.read_local_count() + pub fn read_local_count(&mut self) -> WpResult { + self.state.inner.read_var_u32() } /// Read a `(count, value_type)` declaration of local variables of the same type. pub fn read_local_decl(&mut self, locals_total: &mut usize) -> WpResult<(u32, Type)> { - self.state.inner.read_local_decl(locals_total) + let count = self.state.inner.read_var_u32()?; + let ty = self.state.inner.read_type()?; + Ok((count, ty)) } /// Reads the next available `Operator`. diff --git a/lib/compiler/src/translator/module.rs b/lib/compiler/src/translator/module.rs index c28f0d32676..8855a7a5f54 100644 --- a/lib/compiler/src/translator/module.rs +++ b/lib/compiler/src/translator/module.rs @@ -6,13 +6,13 @@ use super::environ::ModuleEnvironment; use super::error::to_wasm_error; use super::sections::{ - parse_code_section, parse_data_section, parse_element_section, parse_export_section, - parse_function_section, parse_global_section, parse_import_section, parse_memory_section, - parse_name_section, parse_start_section, parse_table_section, parse_type_section, + parse_data_section, parse_element_section, parse_export_section, parse_function_section, + parse_global_section, parse_import_section, parse_memory_section, parse_name_section, + parse_start_section, parse_table_section, parse_type_section, }; use super::state::ModuleTranslationState; use crate::WasmResult; -use wasmparser::{CustomSectionContent, ModuleReader, SectionContent}; +use wasmparser::{NameSectionReader, Parser, Payload}; /// Translate a sequence of bytes forming a valid Wasm binary into a /// parsed ModuleInfo `ModuleTranslationState`. @@ -20,75 +20,88 @@ pub fn translate_module<'data>( data: &'data [u8], environ: &mut ModuleEnvironment<'data>, ) -> WasmResult { - let mut reader = ModuleReader::new(data).map_err(to_wasm_error)?; let mut module_translation_state = ModuleTranslationState::new(); - while !reader.eof() { - let section = reader.read().map_err(to_wasm_error)?; - match section.content().map_err(to_wasm_error)? { - SectionContent::Type(types) => { + for payload in Parser::new(0).parse_all(data) { + match payload.map_err(to_wasm_error)? { + Payload::Version { .. } | Payload::End => {} + + Payload::TypeSection(types) => { parse_type_section(types, &mut module_translation_state, environ)?; } - SectionContent::Import(imports) => { + Payload::ImportSection(imports) => { parse_import_section(imports, environ)?; } - SectionContent::Function(functions) => { + Payload::FunctionSection(functions) => { parse_function_section(functions, environ)?; } - SectionContent::Table(tables) => { + Payload::TableSection(tables) => { parse_table_section(tables, environ)?; } - SectionContent::Memory(memories) => { + Payload::MemorySection(memories) => { parse_memory_section(memories, environ)?; } - SectionContent::Global(globals) => { + Payload::GlobalSection(globals) => { parse_global_section(globals, environ)?; } - SectionContent::Export(exports) => { + Payload::ExportSection(exports) => { parse_export_section(exports, environ)?; } - SectionContent::Start(start) => { - parse_start_section(start, environ)?; + Payload::StartSection { func, .. } => { + parse_start_section(func, environ)?; } - SectionContent::Element(elements) => { + Payload::ElementSection(elements) => { parse_element_section(elements, environ)?; } - SectionContent::Code(code) => { - parse_code_section(code, &module_translation_state, environ)?; + Payload::CodeSectionStart { .. } => {} + Payload::CodeSectionEntry(code) => { + let mut code = code.get_binary_reader(); + let size = code.bytes_remaining(); + let offset = code.original_position(); + environ.define_function_body( + &module_translation_state, + code.read_bytes(size).map_err(to_wasm_error)?, + offset, + )?; } - SectionContent::Data(data) => { + Payload::DataSection(data) => { parse_data_section(data, environ)?; } - SectionContent::DataCount(count) => { + Payload::DataCountSection { count, .. } => { environ.reserve_passive_data(count)?; } - SectionContent::Custom { - name, - binary, - content, - } => match content { - Some(CustomSectionContent::Name(names)) => { - parse_name_section(names, environ)?; - } - _ => { - let mut reader = binary.clone(); - let len = reader.bytes_remaining(); - let payload = reader.read_bytes(len).map_err(to_wasm_error)?; - environ.custom_section(name, payload)?; - } - }, + Payload::ModuleSection(_) + | Payload::InstanceSection(_) + | Payload::AliasSection(_) + | Payload::ModuleCodeSectionStart { .. } + | Payload::ModuleCodeSectionEntry { .. } => { + unimplemented!("module linking not implemented yet") + } + + Payload::CustomSection { + name: "name", + data, + data_offset, + } => parse_name_section( + NameSectionReader::new(data, data_offset).map_err(to_wasm_error)?, + environ, + )?, + + Payload::CustomSection { name, data, .. } => environ.custom_section(name, data)?, + + Payload::UnknownSection { .. } => unreachable!(), } } diff --git a/lib/compiler/src/translator/sections.rs b/lib/compiler/src/translator/sections.rs index a361c8b0c56..00721d6a9f0 100644 --- a/lib/compiler/src/translator/sections.rs +++ b/lib/compiler/src/translator/sections.rs @@ -26,12 +26,11 @@ use wasmer_types::{ MemoryIndex, MemoryType, Pages, SignatureIndex, TableIndex, TableType, Type, V128, }; use wasmparser::{ - self, CodeSectionReader, Data, DataKind, DataSectionReader, Element, ElementItem, ElementItems, - ElementKind, ElementSectionReader, Export, ExportSectionReader, ExternalKind, - FuncType as WPFunctionType, FunctionSectionReader, GlobalSectionReader, - GlobalType as WPGlobalType, ImportSectionEntryType, ImportSectionReader, MemorySectionReader, - MemoryType as WPMemoryType, NameSectionReader, Naming, NamingReader, Operator, - TableSectionReader, TypeSectionReader, + self, Data, DataKind, DataSectionReader, Element, ElementItem, ElementItems, ElementKind, + ElementSectionReader, Export, ExportSectionReader, ExternalKind, FuncType as WPFunctionType, + FunctionSectionReader, GlobalSectionReader, GlobalType as WPGlobalType, ImportSectionEntryType, + ImportSectionReader, MemorySectionReader, MemoryType as WPMemoryType, NameSectionReader, + Naming, NamingReader, Operator, TableSectionReader, TypeDef, TypeSectionReader, }; /// Helper function translating wasmparser types to Wasm Type. @@ -61,25 +60,29 @@ pub fn parse_type_section( environ.reserve_signatures(count)?; for entry in types { - let WPFunctionType { params, returns } = entry.map_err(to_wasm_error)?; - let sig_params: Vec = params - .iter() - .map(|ty| { - wptype_to_type(*ty) - .expect("only numeric types are supported in function signatures") - }) - .collect(); - let sig_returns: Vec = returns - .iter() - .map(|ty| { - wptype_to_type(*ty) - .expect("only numeric types are supported in function signatures") - }) - .collect(); - let sig = FunctionType::new(sig_params, sig_returns); - environ.declare_signature(sig)?; - module_translation_state.wasm_types.push((params, returns)); + if let Ok(TypeDef::Func(WPFunctionType { params, returns })) = entry { + let sig_params: Vec = params + .iter() + .map(|ty| { + wptype_to_type(*ty) + .expect("only numeric types are supported in function signatures") + }) + .collect(); + let sig_returns: Vec = returns + .iter() + .map(|ty| { + wptype_to_type(*ty) + .expect("only numeric types are supported in function signatures") + }) + .collect(); + let sig = FunctionType::new(sig_params, sig_returns); + environ.declare_signature(sig)?; + module_translation_state.wasm_types.push((params, returns)); + } else { + unimplemented!("module linking not implemented yet") + } } + Ok(()) } @@ -100,10 +103,13 @@ pub fn parse_import_section<'data>( environ.declare_func_import( SignatureIndex::from_u32(sig), module_name, - field_name, + field_name.unwrap_or_default(), )?; } - ImportSectionEntryType::Memory(WPMemoryType { + ImportSectionEntryType::Module(_sig) | ImportSectionEntryType::Instance(_sig) => { + unimplemented!("module linking not implemented yet") + } + ImportSectionEntryType::Memory(WPMemoryType::M32 { limits: ref memlimits, shared, }) => { @@ -114,9 +120,12 @@ pub fn parse_import_section<'data>( shared, }, module_name, - field_name, + field_name.unwrap_or_default(), )?; } + ImportSectionEntryType::Memory(WPMemoryType::M64 { .. }) => { + unimplemented!("64bit memory not implemented yet") + } ImportSectionEntryType::Global(ref ty) => { environ.declare_global_import( GlobalType { @@ -124,7 +133,7 @@ pub fn parse_import_section<'data>( mutability: ty.mutable.into(), }, module_name, - field_name, + field_name.unwrap_or_default(), )?; } ImportSectionEntryType::Table(ref tab) => { @@ -135,7 +144,7 @@ pub fn parse_import_section<'data>( maximum: tab.limits.maximum, }, module_name, - field_name, + field_name.unwrap_or_default(), )?; } } @@ -194,11 +203,16 @@ pub fn parse_memory_section( for entry in memories { let memory = entry.map_err(to_wasm_error)?; - environ.declare_memory(MemoryType { - minimum: Pages(memory.limits.initial), - maximum: memory.limits.maximum.map(Pages), - shared: memory.shared, - })?; + match memory { + WPMemoryType::M32 { limits, shared } => { + environ.declare_memory(MemoryType { + minimum: Pages(limits.initial), + maximum: limits.maximum.map(Pages), + shared: shared, + })?; + } + WPMemoryType::M64 { .. } => unimplemented!("64bit memory not implemented yet"), + } } Ok(()) @@ -281,6 +295,9 @@ pub fn parse_export_section<'data>( ExternalKind::Global => { environ.declare_global_export(GlobalIndex::new(index), field)? } + ExternalKind::Type | ExternalKind::Module | ExternalKind::Instance => { + unimplemented!("module linking not implemented yet") + } } } @@ -359,25 +376,6 @@ pub fn parse_element_section<'data>( Ok(()) } -/// Parses the Code section of the wasm module. -pub fn parse_code_section<'data>( - code: CodeSectionReader<'data>, - module_translation_state: &ModuleTranslationState, - environ: &mut ModuleEnvironment<'data>, -) -> WasmResult<()> { - for body in code { - let mut reader = body.map_err(to_wasm_error)?.get_binary_reader(); - let size = reader.bytes_remaining(); - let offset = reader.original_position(); - environ.define_function_body( - module_translation_state, - reader.read_bytes(size).map_err(to_wasm_error)?, - offset, - )?; - } - Ok(()) -} - /// Parses the Data section of the wasm module. pub fn parse_data_section<'data>( data: DataSectionReader<'data>, diff --git a/lib/compiler/src/trap.rs b/lib/compiler/src/trap.rs index d49d04fb7af..058f7e21c2e 100644 --- a/lib/compiler/src/trap.rs +++ b/lib/compiler/src/trap.rs @@ -1,4 +1,3 @@ -use crate::sourceloc::SourceLoc; use crate::CodeOffset; #[cfg(feature = "enable-serde")] use serde::{Deserialize, Serialize}; diff --git a/lib/wasmer-types/src/features.rs b/lib/wasmer-types/src/features.rs index 6b1169a3be5..545e7f58cbc 100644 --- a/lib/wasmer-types/src/features.rs +++ b/lib/wasmer-types/src/features.rs @@ -18,6 +18,14 @@ pub struct Features { pub bulk_memory: bool, /// Multi Value proposal should be enabled pub multi_value: bool, + /// Tail call proposal should be enabled + pub tail_call: bool, + /// Module Linking proposal should be enabled + pub module_linking: bool, + /// Multi Memory proposal should be enabled + pub multi_memory: bool, + /// 64-bit Memory proposal should be enabled + pub memory64: bool, } impl Features { @@ -31,6 +39,10 @@ impl Features { bulk_memory: true, // Multivalue should be on by default multi_value: true, + tail_call: false, + module_linking: false, + multi_memory: false, + memory64: false, } } @@ -136,6 +148,81 @@ impl Features { self.multi_value = enable; self } + + /// Configures whether the WebAssembly tail-call proposal will + /// be enabled. + /// + /// The [WebAssembly tail-call proposal][proposal] is not + /// currently fully standardized and is undergoing development. + /// Support for this feature can be enabled through this method for + /// appropriate WebAssembly modules. + /// + /// This feature gates tail-call functions in WebAssembly. + /// + /// This is `false` by default. + /// + /// [proposal]: https://github.com/webassembly/tail-call + pub fn tail_call(&mut self, enable: bool) -> &mut Self { + self.tail_call = enable; + self + } + + /// Configures whether the WebAssembly tail-call proposal will + /// be enabled. + /// + /// The [WebAssembly tail-call proposal][proposal] is not + /// currently fully standardized and is undergoing development. + /// Support for this feature can be enabled through this method for + /// appropriate WebAssembly modules. + /// + /// This feature allows WebAssembly modules to define, import and + /// export modules and instances. + /// + /// This is `false` by default. + /// + /// [proposal]: https://github.com/webassembly/module-linking + pub fn module_linking(&mut self, enable: bool) -> &mut Self { + self.module_linking = enable; + self + } + + /// Configures whether the WebAssembly multi-memory proposal will + /// be enabled. + /// + /// The [WebAssembly multi-memory proposal][proposal] is not + /// currently fully standardized and is undergoing development. + /// Support for this feature can be enabled through this method for + /// appropriate WebAssembly modules. + /// + /// This feature adds the ability to use multiple memories within a + /// single Wasm module. + /// + /// This is `false` by default. + /// + /// [proposal]: https://github.com/WebAssembly/multi-memory + pub fn multi_memory(&mut self, enable: bool) -> &mut Self { + self.multi_memory = enable; + self + } + + /// Configures whether the WebAssembly 64-bit memory proposal will + /// be enabled. + /// + /// The [WebAssembly 64-bit memory proposal][proposal] is not + /// currently fully standardized and is undergoing development. + /// Support for this feature can be enabled through this method for + /// appropriate WebAssembly modules. + /// + /// This feature gates support for linear memory of sizes larger than + /// 2^32 bits. + /// + /// This is `false` by default. + /// + /// [proposal]: https://github.com/WebAssembly/memory64 + pub fn memory64(&mut self, enable: bool) -> &mut Self { + self.memory64 = enable; + self + } } impl Default for Features { @@ -158,6 +245,10 @@ mod test_features { simd: false, bulk_memory: true, multi_value: true, + tail_call: false, + module_linking: false, + multi_memory: false, + memory64: false, } ); } @@ -209,4 +300,32 @@ mod test_features { assert!(!features.bulk_memory); assert!(!features.reference_types); } + + #[test] + fn enable_tail_call() { + let mut features = Features::new(); + features.tail_call(true); + assert!(features.tail_call); + } + + #[test] + fn enable_module_linking() { + let mut features = Features::new(); + features.module_linking(true); + assert!(features.module_linking); + } + + #[test] + fn enable_multi_memory() { + let mut features = Features::new(); + features.multi_memory(true); + assert!(features.multi_memory); + } + + #[test] + fn enable_memory64() { + let mut features = Features::new(); + features.memory64(true); + assert!(features.memory64); + } } diff --git a/tests/compilers/wast.rs b/tests/compilers/wast.rs index 76fb8a95e06..548c21605df 100644 --- a/tests/compilers/wast.rs +++ b/tests/compilers/wast.rs @@ -84,7 +84,7 @@ pub fn run_wast(wast_path: &str, compiler: &str) -> anyhow::Result<()> { if is_simd { // We allow this, so tests can be run properly for `simd_const` test. wast.allow_instantiation_failures(&[ - "Validation error: multiple tables: tables count must be at most 1", + "Validation error: multiple tables", "Validation error: unknown memory 0", "Validation error: Invalid var_u32", ]); diff --git a/tests/lib/engine-dummy/src/engine.rs b/tests/lib/engine-dummy/src/engine.rs index 14c5c0beceb..900a97c5495 100644 --- a/tests/lib/engine-dummy/src/engine.rs +++ b/tests/lib/engine-dummy/src/engine.rs @@ -59,22 +59,27 @@ impl Engine for DummyEngine { #[cfg(feature = "compiler")] /// Validates a WebAssembly module fn validate(&self, binary: &[u8]) -> Result<(), CompileError> { - use wasmer_compiler::wasmparser::{ - validate, OperatorValidatorConfig, ValidatingParserConfig, - }; + use wasmer_compiler::wasmparser::{Validator, WasmFeatures}; let features = self.features(); - let config = ValidatingParserConfig { - operator_config: OperatorValidatorConfig { - enable_threads: features.threads, - enable_reference_types: features.reference_types, - enable_bulk_memory: features.bulk_memory, - enable_simd: features.simd, - enable_tail_call: false, - enable_multi_value: features.multi_value, - }, + let mut validator = Validator::new(); + let wasm_features = WasmFeatures { + bulk_memory: features.bulk_memory, + threads: features.threads, + reference_types: features.reference_types, + multi_value: features.multi_value, + simd: features.simd, + tail_call: features.tail_call, + module_linking: features.module_linking, + multi_memory: features.multi_memory, + memory64: features.memory64, + deterministic_only: false, }; - validate(binary, Some(config)).map_err(|e| CompileError::Validate(format!("{}", e))) + validator.wasm_features(wasm_features); + validator + .validate_all(binary) + .map_err(|e| CompileError::Validate(format!("{}", e)))?; + Ok(()) } #[cfg(not(feature = "compiler"))]