From d699e610832ef4149529f6e4d56a2f4980b1dbf0 Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Thu, 6 May 2021 09:07:51 -0700 Subject: [PATCH] Implement bulk memory instructions in compiler-llvm --- lib/compiler-llvm/src/translator/code.rs | 82 ++++++++++++++++++ .../src/translator/intrinsics.rs | 83 +++++++++++++++++++ tests/ignores.txt | 7 -- 3 files changed, 165 insertions(+), 7 deletions(-) diff --git a/lib/compiler-llvm/src/translator/code.rs b/lib/compiler-llvm/src/translator/code.rs index 742ec81a8f4..f74fe59a4a7 100644 --- a/lib/compiler-llvm/src/translator/code.rs +++ b/lib/compiler-llvm/src/translator/code.rs @@ -9388,6 +9388,88 @@ impl<'ctx, 'a> LLVMFunctionCodeGenerator<'ctx, 'a> { size.add_attribute(AttributeLoc::Function, self.intrinsics.readonly); self.state.push1(size.try_as_basic_value().left().unwrap()); } + Operator::MemoryInit { segment, mem } => { + let (dest, src, len) = self.state.pop3()?; + let mem = self + .intrinsics + .i32_ty + .const_int(mem.into(), false) + .as_basic_value_enum(); + let segment = self + .intrinsics + .i32_ty + .const_int(segment.into(), false) + .as_basic_value_enum(); + self.builder.build_call( + self.intrinsics.memory_init, + &[vmctx.as_basic_value_enum(), mem, segment, dest, src, len], + "", + ); + } + Operator::DataDrop { segment } => { + let segment = self + .intrinsics + .i32_ty + .const_int(segment.into(), false) + .as_basic_value_enum(); + self.builder.build_call( + self.intrinsics.data_drop, + &[vmctx.as_basic_value_enum(), segment], + "", + ); + } + Operator::MemoryCopy { src, dst } => { + // ignored until we support multiple memories + let _dst = dst; + let (memory_copy, src) = if let Some(local_memory_index) = self + .wasm_module + .local_memory_index(MemoryIndex::from_u32(src)) + { + (self.intrinsics.memory_copy, local_memory_index.as_u32()) + } else { + (self.intrinsics.imported_memory_copy, src) + }; + + let (dest_pos, src_pos, len) = self.state.pop3()?; + let src_index = self + .intrinsics + .i32_ty + .const_int(src.into(), false) + .as_basic_value_enum(); + self.builder.build_call( + memory_copy, + &[ + vmctx.as_basic_value_enum(), + src_index, + dest_pos, + src_pos, + len, + ], + "", + ); + } + Operator::MemoryFill { mem } => { + let (memory_fill, mem) = if let Some(local_memory_index) = self + .wasm_module + .local_memory_index(MemoryIndex::from_u32(mem)) + { + (self.intrinsics.memory_fill, local_memory_index.as_u32()) + } else { + (self.intrinsics.imported_memory_fill, mem) + }; + + let (dst, val, len) = self.state.pop3()?; + let mem_index = self + .intrinsics + .i32_ty + .const_int(mem.into(), false) + .as_basic_value_enum(); + self.builder.build_call( + memory_fill, + &[vmctx.as_basic_value_enum(), mem_index, dst, val, len], + "", + ); + } /*************************** * Reference types. * https://github.com/WebAssembly/reference-types/blob/master/proposals/reference-types/Overview.md diff --git a/lib/compiler-llvm/src/translator/intrinsics.rs b/lib/compiler-llvm/src/translator/intrinsics.rs index a2274cac5a7..ecc4d059e09 100644 --- a/lib/compiler-llvm/src/translator/intrinsics.rs +++ b/lib/compiler-llvm/src/translator/intrinsics.rs @@ -181,8 +181,15 @@ pub struct Intrinsics<'ctx> { pub imported_table_set: FunctionValue<'ctx>, pub table_grow: FunctionValue<'ctx>, pub imported_table_grow: FunctionValue<'ctx>, + pub memory_init: FunctionValue<'ctx>, + pub data_drop: FunctionValue<'ctx>, pub func_ref: FunctionValue<'ctx>, pub elem_drop: FunctionValue<'ctx>, + pub memory_copy: FunctionValue<'ctx>, + pub imported_memory_copy: FunctionValue<'ctx>, + pub memory_fill: FunctionValue<'ctx>, + pub imported_memory_fill: FunctionValue<'ctx>, + pub throw_trap: FunctionValue<'ctx>, // VM builtins. @@ -594,6 +601,82 @@ impl<'ctx> Intrinsics<'ctx> { ), None, ), + memory_init: module.add_function( + "wasmer_vm_memory32_init", + void_ty.fn_type( + &[ + ctx_ptr_ty.as_basic_type_enum(), + i32_ty_basic, + i32_ty_basic, + i32_ty_basic, + i32_ty_basic, + i32_ty_basic, + ], + false, + ), + None, + ), + memory_copy: module.add_function( + "wasmer_vm_memory32_copy", + void_ty.fn_type( + &[ + ctx_ptr_ty.as_basic_type_enum(), + i32_ty_basic, + i32_ty_basic, + i32_ty_basic, + i32_ty_basic, + ], + false, + ), + None, + ), + imported_memory_copy: module.add_function( + "wasmer_vm_imported_memory32_copy", + void_ty.fn_type( + &[ + ctx_ptr_ty.as_basic_type_enum(), + i32_ty_basic, + i32_ty_basic, + i32_ty_basic, + i32_ty_basic, + ], + false, + ), + None, + ), + memory_fill: module.add_function( + "wasmer_vm_memory32_fill", + void_ty.fn_type( + &[ + ctx_ptr_ty.as_basic_type_enum(), + i32_ty_basic, + i32_ty_basic, + i32_ty_basic, + i32_ty_basic, + ], + false, + ), + None, + ), + imported_memory_fill: module.add_function( + "wasmer_vm_imported_memory32_fill", + void_ty.fn_type( + &[ + ctx_ptr_ty.as_basic_type_enum(), + i32_ty_basic, + i32_ty_basic, + i32_ty_basic, + i32_ty_basic, + ], + false, + ), + None, + ), + data_drop: module.add_function( + "wasmer_vm_data_drop", + void_ty.fn_type(&[ctx_ptr_ty.as_basic_type_enum(), i32_ty_basic], false), + None, + ), func_ref: module.add_function( "wasmer_vm_func_ref", funcref_ty.fn_type(&[ctx_ptr_ty.as_basic_type_enum(), i32_ty_basic], false), diff --git a/tests/ignores.txt b/tests/ignores.txt index add4976cb9d..416ee1ac939 100644 --- a/tests/ignores.txt +++ b/tests/ignores.txt @@ -97,8 +97,6 @@ wasitests::snapshot1::unix_open_special_files on windows # Updated spectests -# bulk memory -cranelift::spec::bulk # new simd cranelift::spec::simd::simd_align cranelift::spec::simd::simd_conversions @@ -134,11 +132,6 @@ cranelift::spec::simd::simd_store32_lane cranelift::spec::simd::simd_store64_lane cranelift::spec::simd::simd_store8_lane -# bulk memory -llvm::spec::bulk -llvm::spec::memory_copy -llvm::spec::memory_fill -llvm::spec::memory_init # new simd llvm::spec::simd::simd_align llvm::spec::simd::simd_conversions