From 28aead6a507b326808121bfa8778b0a6716b6d44 Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Wed, 26 Aug 2020 13:49:47 -0700 Subject: [PATCH 001/281] Add engine object-file (WIP) --- Cargo.lock | 21 + Cargo.toml | 11 +- Makefile | 5 + lib/api/src/instance.rs | 7 +- lib/c-api/Cargo.toml | 5 + lib/c-api/src/wasm_c_api/mod.rs | 74 +++- lib/cli/Cargo.toml | 9 +- lib/cli/src/commands/compile.rs | 47 ++- lib/cli/src/store.rs | 33 +- lib/compiler-llvm/src/compiler.rs | 147 +++++++ lib/compiler-llvm/src/trampoline/wasm.rs | 12 +- lib/compiler-llvm/src/translator/code.rs | 2 +- lib/compiler/src/compiler.rs | 18 + lib/engine-object-file/Cargo.toml | 35 ++ lib/engine-object-file/src/artifact.rs | 512 +++++++++++++++++++++++ lib/engine-object-file/src/builder.rs | 113 +++++ lib/engine-object-file/src/engine.rs | 250 +++++++++++ lib/engine-object-file/src/lib.rs | 34 ++ lib/engine-object-file/src/serialize.rs | 66 +++ 19 files changed, 1359 insertions(+), 42 deletions(-) create mode 100644 lib/engine-object-file/Cargo.toml create mode 100644 lib/engine-object-file/src/artifact.rs create mode 100644 lib/engine-object-file/src/builder.rs create mode 100644 lib/engine-object-file/src/engine.rs create mode 100644 lib/engine-object-file/src/lib.rs create mode 100644 lib/engine-object-file/src/serialize.rs diff --git a/Cargo.lock b/Cargo.lock index df229d420..1ce610259 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2181,6 +2181,7 @@ dependencies = [ "wasmer-engine", "wasmer-engine-jit", "wasmer-engine-native", + "wasmer-engine-object-file", "wasmer-types", "wasmer-wasi", ] @@ -2219,6 +2220,7 @@ dependencies = [ "wasmer-engine", "wasmer-engine-jit", "wasmer-engine-native", + "wasmer-engine-object-file", "wasmer-types", "wasmer-wasi", "wasmer-wasi-experimental-io-devices", @@ -2379,6 +2381,24 @@ dependencies = [ "wasmer-vm", ] +[[package]] +name = "wasmer-engine-object-file" +version = "1.0.0-alpha01.0" +dependencies = [ + "bincode", + "cfg-if", + "leb128", + "libloading 0.6.2", + "serde", + "tempfile", + "tracing", + "wasmer-compiler", + "wasmer-engine", + "wasmer-object", + "wasmer-types", + "wasmer-vm", +] + [[package]] name = "wasmer-object" version = "1.0.0-alpha01.0" @@ -2483,6 +2503,7 @@ dependencies = [ "wasmer-engine-dummy", "wasmer-engine-jit", "wasmer-engine-native", + "wasmer-engine-object-file", "wasmer-types", "wasmer-wasi", "wasmer-wast", diff --git a/Cargo.toml b/Cargo.toml index ecb6bb32d..92c86ab6a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,6 +18,7 @@ wasmer-compiler-llvm = { version = "1.0.0-alpha01.0", path = "lib/compiler-llvm" wasmer-engine = { version = "1.0.0-alpha01.0", path = "lib/engine" } wasmer-engine-jit = { version = "1.0.0-alpha01.0", path = "lib/engine-jit", optional = true } wasmer-engine-native = { version = "1.0.0-alpha01.0", path = "lib/engine-native", optional = true } +wasmer-engine-object-file = { version = "1.0.0-alpha01.0", path = "lib/engine-object-file", optional = true } wasmer-wasi = { version = "1.0.0-alpha01.0", path = "lib/wasi", optional = true } wasmer-wast = { version = "1.0.0-alpha01.0", path = "tests/lib/wast", optional = true } wasmer-cache = { version = "1.0.0-alpha01.0", path = "lib/cache", optional = true } @@ -38,6 +39,7 @@ members = [ "lib/engine", "lib/engine-jit", "lib/engine-native", + "lib/engine-object-file", "lib/object", "lib/vm", "lib/wasi", @@ -72,6 +74,7 @@ default = [ "wast", "jit", "native", + "object-file", "cache", "wasi", # "emscripten", @@ -85,6 +88,10 @@ native = [ "wasmer-engine-native", "engine", ] +object-file = [ + "wasmer-engine-object-file", + "engine", +] cache = ["wasmer-cache"] wast = ["wasmer-wast"] wasi = ["wasmer-wasi"] @@ -94,7 +101,9 @@ compiler = [ "wasmer/compiler", "wasmer-compiler/translator", "wasmer-engine-jit/compiler", - "wasmer-engine-native/compiler" + "wasmer-engine-native/compiler", + # TODO: does this make sense? + "wasmer-engine-object-file/compiler", ] singlepass = [ "wasmer-compiler-singlepass", diff --git a/Makefile b/Makefile index c2a96b244..6ffe7ebfe 100644 --- a/Makefile +++ b/Makefile @@ -86,6 +86,11 @@ build-capi-llvm: cargo build --manifest-path lib/c-api/Cargo.toml --release \ --no-default-features --features jit,llvm,wasi +# this is debug code; we probably shouldn't ship it like this +build-capi-native: + cargo build --manifest-path lib/c-api/Cargo.toml --release \ + --no-default-features --features object-file,wasi + ########### # Testing # diff --git a/lib/api/src/instance.rs b/lib/api/src/instance.rs index 481210a43..efb3bbdef 100644 --- a/lib/api/src/instance.rs +++ b/lib/api/src/instance.rs @@ -5,7 +5,7 @@ use crate::store::Store; use crate::InstantiationError; use std::fmt; use wasmer_engine::Resolver; -use wasmer_vm::InstanceHandle; +use wasmer_vm::{InstanceHandle, VMContext}; /// A WebAssembly Instance is a stateful, executable /// instance of a WebAssembly [`Module`]. @@ -101,6 +101,11 @@ impl Instance { pub fn store(&self) -> &Store { self.module.store() } + + #[doc(hidden)] + pub fn vmctx_ptr(&self) -> *mut VMContext { + self.handle.vmctx_ptr() + } } impl fmt::Debug for Instance { diff --git a/lib/c-api/Cargo.toml b/lib/c-api/Cargo.toml index dd8a55129..d1f7a02c5 100644 --- a/lib/c-api/Cargo.toml +++ b/lib/c-api/Cargo.toml @@ -24,6 +24,7 @@ wasmer-emscripten = { version = "1.0.0-alpha01.0", path = "../emscripten", optio wasmer-engine = { version = "1.0.0-alpha01.0", path = "../engine" } wasmer-engine-jit = { version = "1.0.0-alpha01.0", path = "../engine-jit", optional = true } wasmer-engine-native = { version = "1.0.0-alpha01.0", path = "../engine-native", optional = true } +wasmer-engine-object-file = { version = "1.0.0-alpha01.0", path = "../engine-object-file", optional = true } wasmer-wasi = { version = "1.0.0-alpha01.0", path = "../wasi", optional = true } wasmer-types = { version = "1.0.0-alpha01.0", path = "../wasmer-types" } cfg-if = "0.1" @@ -53,6 +54,10 @@ native = [ "wasmer-engine-native", "engine", ] +object-file = [ + "wasmer-engine-object-file", + "engine", +] compiler = [ "wasmer-engine-jit/compiler", "wasmer-engine-native/compiler" diff --git a/lib/c-api/src/wasm_c_api/mod.rs b/lib/c-api/src/wasm_c_api/mod.rs index 8e14c34cd..cbb38ee2f 100644 --- a/lib/c-api/src/wasm_c_api/mod.rs +++ b/lib/c-api/src/wasm_c_api/mod.rs @@ -23,6 +23,10 @@ use wasmer::{ }; #[cfg(feature = "jit")] use wasmer_engine_jit::JIT; +#[cfg(feature = "native")] +use wasmer_engine_native::Native; +#[cfg(feature = "object-file")] +use wasmer_engine_object_file::ObjectFile; /// this can be a wasmer-specific type with wasmer-specific functions for manipulating it #[repr(C)] @@ -39,24 +43,26 @@ pub struct wasm_engine_t { pub(crate) inner: Arc, } +// Compiler JIT +#[cfg(feature = "compiler")] +use wasmer_compiler::CompilerConfig; +#[cfg(feature = "compiler")] +fn get_default_compiler_config() -> Box { + cfg_if! { + if #[cfg(feature = "cranelift")] { + Box::new(wasmer_compiler_cranelift::Cranelift::default()) + } else if #[cfg(feature = "llvm")] { + Box::new(wasmer_compiler_llvm::LLVM::default()) + } else if #[cfg(feature = "singlepass")] { + Box::new(wasmer_compiler_singlepass::Singlepass::default()) + } else { + compile_error!("Please enable one of the compiler backends") + } + } +} + cfg_if! { if #[cfg(all(feature = "jit", feature = "compiler"))] { - // Compiler JIT - use wasmer_compiler::CompilerConfig; - fn get_default_compiler_config() -> Box { - cfg_if! { - if #[cfg(feature = "cranelift")] { - Box::new(wasmer_compiler_cranelift::Cranelift::default()) - } else if #[cfg(feature = "llvm")] { - Box::new(wasmer_compiler_llvm::LLVM::default()) - } else if #[cfg(feature = "singlepass")] { - Box::new(wasmer_compiler_singlepass::Singlepass::default()) - } else { - compile_error!("Please enable one of the compiler backends") - } - } - } - #[no_mangle] pub extern "C" fn wasm_engine_new() -> Box { let compiler_config: Box = get_default_compiler_config(); @@ -72,6 +78,36 @@ cfg_if! { Box::new(wasm_engine_t { inner: engine }) } } + else if #[cfg(all(feature = "native", feature = "compiler"))] { + #[no_mangle] + pub extern "C" fn wasm_engine_new() -> Box { + let mut compiler_config: Box = get_default_compiler_config(); + let engine: Arc = Arc::new(Native::new(&mut *compiler_config).engine()); + Box::new(wasm_engine_t { inner: engine }) + } + } + else if #[cfg(feature = "native")] { + #[no_mangle] + pub extern "C" fn wasm_engine_new() -> Box { + let engine: Arc = Arc::new(Native::headless().engine()); + Box::new(wasm_engine_t { inner: engine }) + } + } + else if #[cfg(all(feature = "object-file", feature = "compiler"))] { + #[no_mangle] + pub extern "C" fn wasm_engine_new() -> Box { + let mut compiler_config: Box = get_default_compiler_config(); + let engine: Arc = Arc::new(ObjectFile::new(&mut *compiler_config).engine()); + Box::new(wasm_engine_t { inner: engine }) + } + } + else if #[cfg(feature = "object-file")] { + #[no_mangle] + pub extern "C" fn wasm_engine_new() -> Box { + let engine: Arc = Arc::new(ObjectFile::headless().engine()); + Box::new(wasm_engine_t { inner: engine }) + } + } else { #[no_mangle] pub extern "C" fn wasm_engine_new() -> Box { @@ -120,6 +156,12 @@ pub unsafe extern "C" fn wasm_instance_new( #[no_mangle] pub unsafe extern "C" fn wasm_instance_delete(_instance: Option>) {} +// TODO: NOT part of the standard Wasm C API +#[no_mangle] +pub unsafe extern "C" fn wasm_instance_get_vmctx_ptr(instance: &wasm_instance_t) -> *mut c_void { + instance.inner.vmctx_ptr() as _ +} + struct CArrayIter { cur_entry: *const *const T, } diff --git a/lib/cli/Cargo.toml b/lib/cli/Cargo.toml index 501449416..c2543bae1 100644 --- a/lib/cli/Cargo.toml +++ b/lib/cli/Cargo.toml @@ -31,6 +31,7 @@ wasmer-emscripten = { version = "1.0.0-alpha01.0", path = "../emscripten", optio wasmer-engine = { version = "1.0.0-alpha01.0", path = "../engine" } wasmer-engine-jit = { version = "1.0.0-alpha01.0", path = "../engine-jit", optional = true } wasmer-engine-native = { version = "1.0.0-alpha01.0", path = "../engine-native", optional = true } +wasmer-engine-object-file = { version = "1.0.0-alpha01.0", path = "../engine-object-file", optional = true } wasmer-wasi = { version = "1.0.0-alpha01.0", path = "../wasi", optional = true } wasmer-wasi-experimental-io-devices = { version = "1.0.0-alpha01.0", path = "../wasi-experimental-io-devices", optional = true } wasmer-wast = { version = "1.0.0-alpha01.0", path = "../../tests/lib/wast", optional = true } @@ -57,6 +58,7 @@ default = [ "wast", "jit", "native", + "object-file", "cache", "wasi", "emscripten", @@ -70,6 +72,10 @@ native = [ "wasmer-engine-native", "engine", ] +object-file = [ + "wasmer-engine-object-file", + "engine", +] cache = ["wasmer-cache"] wast = ["wasmer-wast"] wasi = ["wasmer-wasi"] @@ -78,7 +84,8 @@ wat = ["wasmer/wat"] compiler = [ "wasmer-compiler/translator", "wasmer-engine-jit/compiler", - "wasmer-engine-native/compiler" + "wasmer-engine-native/compiler", + "wasmer-engine-object-file/compiler", ] experimental-io-devices = [ "wasmer-wasi-experimental-io-devices", diff --git a/lib/cli/src/commands/compile.rs b/lib/cli/src/commands/compile.rs index 4d5d5cea4..75bd712da 100644 --- a/lib/cli/src/commands/compile.rs +++ b/lib/cli/src/commands/compile.rs @@ -33,6 +33,28 @@ impl Compile { self.inner_execute() .context(format!("failed to compile `{}`", self.path.display())) } + + fn get_recommend_extension( + &self, + engine_type: &EngineType, + target_triple: &Triple, + ) -> &'static str { + match engine_type { + #[cfg(feature = "native")] + EngineType::Native => { + wasmer_engine_native::NativeArtifact::get_default_extension(target_triple) + } + #[cfg(feature = "jit")] + EngineType::JIT => wasmer_engine_jit::JITArtifact::get_default_extension(target_triple), + #[cfg(feature = "object-file")] + EngineType::ObjectFile => { + wasmer_engine_object_file::ObjectFileArtifact::get_default_extension(target_triple) + } + #[cfg(not(all(feature = "native", feature = "jit", feature = "object-file")))] + _ => bail!("selected engine type is not compiled in"), + } + } + fn inner_execute(&self) -> Result<()> { let target = self .target_triple @@ -56,18 +78,7 @@ impl Compile { .file_stem() .map(|osstr| osstr.to_string_lossy().to_string()) .unwrap_or_default(); - let recommended_extension = match engine_type { - #[cfg(feature = "native")] - EngineType::Native => { - wasmer_engine_native::NativeArtifact::get_default_extension(target.triple()) - } - #[cfg(feature = "jit")] - EngineType::JIT => { - wasmer_engine_jit::JITArtifact::get_default_extension(target.triple()) - } - #[cfg(not(all(feature = "native", feature = "jit")))] - _ => bail!("selected engine type is not compiled in"), - }; + let recommended_extension = self.get_recommend_extension(&engine_type, target.triple()); match self.output.extension() { Some(ext) => { if ext != recommended_extension { @@ -83,6 +94,18 @@ impl Compile { println!("Target: {}", target.triple()); let module = Module::from_file(&store, &self.path)?; let _ = module.serialize_to_file(&self.output)?; + // for C code + let module_bytes = module.serialize()?; + let mut header = std::fs::OpenOptions::new() + .create(true) + .truncate(true) + .write(true) + .open("test.h")?; + use std::io::Write; + header + .write(format!("const int module_bytes_len = {};\n", module_bytes.len()).as_bytes())?; + header.write(b"extern const char WASMER_METADATA[];\n")?; + // end c gen eprintln!( "✔ File compiled successfully to `{}`.", self.output.display(), diff --git a/lib/cli/src/store.rs b/lib/cli/src/store.rs index baa9d81ae..8bfaf5ac8 100644 --- a/lib/cli/src/store.rs +++ b/lib/cli/src/store.rs @@ -37,13 +37,17 @@ pub struct StoreOptions { llvm_debug_dir: Option, /// Use JIT Engine. - #[structopt(long, conflicts_with_all = &["native"])] + #[structopt(long, conflicts_with_all = &["native", "object_file"])] jit: bool, /// Use Native Engine. - #[structopt(long, conflicts_with_all = &["jit"])] + #[structopt(long, conflicts_with_all = &["jit", "object_file"])] native: bool, + /// Use ObjectFile Engine. + #[structopt(long, conflicts_with_all = &["jit", "native"])] + object_file: bool, + /// The deprecated backend flag - Please not use #[structopt(long = "backend", hidden = true, conflicts_with_all = &["singlepass", "cranelift", "llvm"])] backend: Option, @@ -110,6 +114,8 @@ pub enum EngineType { JIT, /// Native Engine Native, + /// Object File Engine + ObjectFile, } impl ToString for EngineType { @@ -117,6 +123,7 @@ impl ToString for EngineType { match self { Self::JIT => "jit".to_string(), Self::Native => "native".to_string(), + Self::ObjectFile => "objectfile".to_string(), } } } @@ -350,7 +357,17 @@ impl StoreOptions { .engine(), ) } - #[cfg(not(all(feature = "jit", feature = "native")))] + #[cfg(feature = "object-file")] + EngineType::ObjectFile => { + let mut compiler_config = compiler_config; + Box::new( + wasmer_engine_object_file::ObjectFile::new(&mut *compiler_config) + .target(target) + .features(features) + .engine(), + ) + } + #[cfg(not(all(feature = "jit", feature = "native", feature = "object-file")))] engine => bail!( "The `{}` engine is not included in this binary.", engine.to_string() @@ -367,12 +384,16 @@ impl StoreOptions { Ok(EngineType::JIT) } else if self.native { Ok(EngineType::Native) + } else if self.object_file { + Ok(EngineType::ObjectFile) } else { // Auto mode, we choose the best engine for that platform if cfg!(feature = "jit") { Ok(EngineType::JIT) } else if cfg!(feature = "native") { Ok(EngineType::Native) + } else if cfg!(feature = "object-file") { + Ok(EngineType::ObjectFile) } else { bail!("There are no available engines for your architecture") } @@ -390,7 +411,11 @@ impl StoreOptions { EngineType::JIT => Arc::new(wasmer_engine_jit::JIT::headless().engine()), #[cfg(feature = "native")] EngineType::Native => Arc::new(wasmer_engine_native::Native::headless().engine()), - #[cfg(not(all(feature = "jit", feature = "native",)))] + #[cfg(feature = "object-file")] + EngineType::ObjectFile => { + Arc::new(wasmer_engine_object_file::ObjectFile::headless().engine()) + } + #[cfg(not(all(feature = "jit", feature = "native", feature = "object-file")))] engine => bail!( "The `{}` engine is not included in this binary.", engine.to_string() diff --git a/lib/compiler-llvm/src/compiler.rs b/lib/compiler-llvm/src/compiler.rs index 24f401bbc..07963de39 100644 --- a/lib/compiler-llvm/src/compiler.rs +++ b/lib/compiler-llvm/src/compiler.rs @@ -197,6 +197,132 @@ impl LLVMCompiler { Ok(memory_buffer.as_slice().to_vec()) } + + fn compile_to_object_file<'data, 'module>( + &self, + target: &Target, + compile_info: &'module CompileModuleInfo, + module_translation: &ModuleTranslationState, + function_body_inputs: &PrimaryMap>, + symbol_registry: &dyn SymbolRegistry, + wasmer_metadata: &[u8], + ) -> Result, CompileError> { + let target_machine = self.config().target_machine(target); + let ctx = Context::create(); + let merged_module = ctx.create_module(""); + + // TODO: make these steps run in parallel instead of in three phases + // with a serial step in between them. + + function_body_inputs + .into_iter() + .collect::>() + .par_iter() + .map_init( + || { + let target_machine = self.config().target_machine(target); + FuncTranslator::new(target_machine) + }, + |func_translator, (i, input)| { + let module = func_translator.translate_to_module( + &compile_info.module, + module_translation, + i, + input, + self.config(), + &compile_info.memory_styles, + &compile_info.table_styles, + symbol_registry, + )?; + Ok(module.write_bitcode_to_memory().as_slice().to_vec()) + }, + ) + .collect::, CompileError>>()? + .into_iter() + .for_each(|bc| { + let membuf = MemoryBuffer::create_from_memory_range(&bc, ""); + let m = Module::parse_bitcode_from_buffer(&membuf, &ctx).unwrap(); + merged_module.link_in_module(m).unwrap(); + }); + + compile_info + .module + .signatures + .into_iter() + .collect::>() + .par_iter() + .map_init( + || { + let target_machine = self.config().target_machine(target); + FuncTrampoline::new(target_machine) + }, + |func_trampoline, (i, sig)| { + let name = symbol_registry.symbol_to_name(Symbol::FunctionCallTrampoline(*i)); + let module = func_trampoline.trampoline_to_module(sig, self.config(), &name)?; + Ok(module.write_bitcode_to_memory().as_slice().to_vec()) + }, + ) + .collect::, CompileError>>()? + .into_iter() + .for_each(|bc| { + let membuf = MemoryBuffer::create_from_memory_range(&bc, ""); + let m = Module::parse_bitcode_from_buffer(&membuf, &ctx).unwrap(); + merged_module.link_in_module(m).unwrap(); + }); + + compile_info + .module + .functions + .into_iter() + .collect::>() + .par_iter() + .map_init( + || { + let target_machine = self.config().target_machine(target); + ( + FuncTrampoline::new(target_machine), + &compile_info.module.signatures, + ) + }, + |(func_trampoline, signatures), (i, sig)| { + let sig = &signatures[**sig]; + let name = + symbol_registry.symbol_to_name(Symbol::DynamicFunctionTrampoline(*i)); + let module = + func_trampoline.dynamic_trampoline_to_module(sig, self.config(), &name)?; + Ok(module.write_bitcode_to_memory().as_slice().to_vec()) + }, + ) + .collect::, CompileError>>()? + .into_iter() + .for_each(|bc| { + let membuf = MemoryBuffer::create_from_memory_range(&bc, ""); + let m = Module::parse_bitcode_from_buffer(&membuf, &ctx).unwrap(); + merged_module.link_in_module(m).unwrap(); + }); + + let i8_ty = ctx.i8_type(); + let metadata_init = i8_ty.const_array( + wasmer_metadata + .iter() + .map(|v| i8_ty.const_int(*v as u64, false)) + .collect::>() + .as_slice(), + ); + let metadata_gv = + merged_module.add_global(metadata_init.get_type(), None, "WASMER_METADATA"); + metadata_gv.set_initializer(&metadata_init); + + if self.config().enable_verifier { + merged_module.verify().unwrap(); + } + + let memory_buffer = target_machine + .write_to_memory_buffer(&merged_module, FileType::Object) + .unwrap(); + + Ok(memory_buffer.as_slice().to_vec()) + } } impl Compiler for LLVMCompiler { @@ -221,6 +347,27 @@ impl Compiler for LLVMCompiler { )) } + fn experimental_object_file_compile_module<'data, 'module>( + &self, + target: &Target, + module: &'module CompileModuleInfo, + module_translation: &ModuleTranslationState, + // The list of function bodies + function_body_inputs: &PrimaryMap>, + symbol_registry: &dyn SymbolRegistry, + // The metadata to inject into the wasmer_metadata section of the object file. + wasmer_metadata: &[u8], + ) -> Option, CompileError>> { + Some(self.compile_to_object_file( + target, + module, + module_translation, + function_body_inputs, + symbol_registry, + wasmer_metadata, + )) + } + /// Compile the module using LLVM, producing a compilation result with /// associated relocations. fn compile_module<'data, 'module>( diff --git a/lib/compiler-llvm/src/trampoline/wasm.rs b/lib/compiler-llvm/src/trampoline/wasm.rs index a954919df..ccbf0fcbd 100644 --- a/lib/compiler-llvm/src/trampoline/wasm.rs +++ b/lib/compiler-llvm/src/trampoline/wasm.rs @@ -63,9 +63,9 @@ impl FuncTrampoline { ); let trampoline_func = module.add_function(name, trampoline_ty, Some(Linkage::External)); - trampoline_func - .as_global_value() - .set_section(FUNCTION_SECTION); + /*trampoline_func + .as_global_value() + .set_section(FUNCTION_SECTION);*/ generate_trampoline(trampoline_func, ty, &callee_attrs, &self.ctx, &intrinsics)?; if let Some(ref callbacks) = config.callbacks { @@ -179,9 +179,9 @@ impl FuncTrampoline { for (attr, attr_loc) in trampoline_attrs { trampoline_func.add_attribute(attr_loc, attr); } - trampoline_func - .as_global_value() - .set_section(FUNCTION_SECTION); + /*trampoline_func + .as_global_value() + .set_section(FUNCTION_SECTION);*/ generate_dynamic_trampoline(trampoline_func, ty, &self.ctx, &intrinsics)?; if let Some(ref callbacks) = config.callbacks { diff --git a/lib/compiler-llvm/src/translator/code.rs b/lib/compiler-llvm/src/translator/code.rs index 836bb7864..d419a3aed 100644 --- a/lib/compiler-llvm/src/translator/code.rs +++ b/lib/compiler-llvm/src/translator/code.rs @@ -111,7 +111,7 @@ impl FuncTranslator { // TODO: mark vmctx nofree func.add_attribute(AttributeLoc::Function, intrinsics.stack_probe); func.set_personality_function(intrinsics.personality); - func.as_global_value().set_section(FUNCTION_SECTION); + //func.as_global_value().set_section(FUNCTION_SECTION); let entry = self.ctx.append_basic_block(func, "entry"); let start_of_code = self.ctx.append_basic_block(func, "start_of_code"); diff --git a/lib/compiler/src/compiler.rs b/lib/compiler/src/compiler.rs index 75b3b0811..cbfa0220e 100644 --- a/lib/compiler/src/compiler.rs +++ b/lib/compiler/src/compiler.rs @@ -99,6 +99,24 @@ pub trait Compiler { ) -> Option, CompileError>> { None } + + /// Compiles a module into an object file that can be built with libwasmer + /// into a stand-alone executable. + /// + /// It returns the bytes as a `&[u8]` or a [`CompileError`]. + fn experimental_object_file_compile_module<'data, 'module>( + &self, + _target: &Target, + _module: &'module CompileModuleInfo, + _module_translation: &ModuleTranslationState, + // The list of function bodies + _function_body_inputs: &PrimaryMap>, + _symbol_registry: &dyn SymbolRegistry, + // The metadata to inject into the wasmer_metadata section of the object file. + _wasmer_metadata: &[u8], + ) -> Option, CompileError>> { + None + } } /// The kinds of wasmer_types objects that might be found in a native object file. diff --git a/lib/engine-object-file/Cargo.toml b/lib/engine-object-file/Cargo.toml new file mode 100644 index 000000000..34a812068 --- /dev/null +++ b/lib/engine-object-file/Cargo.toml @@ -0,0 +1,35 @@ +[package] +name = "wasmer-engine-object-file" +version = "1.0.0-alpha01.0" +authors = ["Wasmer Engineering Team "] +description = "Wasmer Object File Engine" +categories = ["wasm"] +keywords = ["webassembly", "wasm"] +repository = "https://github.com/wasmerio/wasmer" +# TODO: make a readme explaining what this crate is +# readme = "README.md" +edition = "2018" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +wasmer-types = { path = "../wasmer-types", version = "1.0.0-alpha01.0" } +wasmer-compiler = { path = "../compiler", version = "1.0.0-alpha01.0" } +wasmer-vm = { path = "../vm", version = "1.0.0-alpha01.0" } +wasmer-engine = { path = "../engine", version = "1.0.0-alpha01.0" } +wasmer-object = { path = "../object", version = "1.0.0-alpha01.0" } +serde = { version = "1.0", features = ["derive", "rc"] } +cfg-if = "0.1" +tracing = "0.1" +bincode = "1.3" +leb128 = "0.2" +libloading = "0.6" +tempfile = "3.1" + +[features] +# Enable the `compiler` feature if you want the engine to compile +# and not be only on headless mode. +compiler = [] + +[badges] +maintenance = { status = "actively-developed" } diff --git a/lib/engine-object-file/src/artifact.rs b/lib/engine-object-file/src/artifact.rs new file mode 100644 index 000000000..c4dede427 --- /dev/null +++ b/lib/engine-object-file/src/artifact.rs @@ -0,0 +1,512 @@ +//! Define `ObjectFileArtifact` to allow compiling and instantiating to be +//! done as separate steps. + +use crate::engine::{ObjectFileEngine, ObjectFileEngineInner}; +use crate::serialize::ModuleMetadata; +use std::error::Error; +use std::fs::File; +use std::io::{Read, Write}; +use std::path::{Path, PathBuf}; +#[cfg(feature = "compiler")] +use std::process::Command; +use std::sync::Arc; +use tempfile::NamedTempFile; +#[cfg(feature = "compiler")] +use tracing::trace; +use wasmer_compiler::{CompileError, Features, OperatingSystem, Symbol, SymbolRegistry, Triple}; +#[cfg(feature = "compiler")] +use wasmer_compiler::{ + CompileModuleInfo, FunctionBodyData, ModuleEnvironment, ModuleTranslationState, +}; +use wasmer_engine::{ + Artifact, DeserializeError, InstantiationError, LinkError, RuntimeError, SerializeError, +}; +#[cfg(feature = "compiler")] +use wasmer_engine::{Engine, Tunables}; +#[cfg(feature = "compiler")] +use wasmer_object::{emit_compilation, emit_data, get_object_for_target}; +use wasmer_types::entity::{BoxedSlice, PrimaryMap}; +#[cfg(feature = "compiler")] +use wasmer_types::DataInitializer; +use wasmer_types::{ + FunctionIndex, LocalFunctionIndex, MemoryIndex, OwnedDataInitializer, SignatureIndex, + TableIndex, +}; +use wasmer_vm::{ + FunctionBodyPtr, MemoryStyle, ModuleInfo, TableStyle, VMFunctionBody, VMSharedSignatureIndex, + VMTrampoline, +}; + +/// A compiled wasm module, ready to be instantiated. +pub struct ObjectFileArtifact { + metadata: ModuleMetadata, + module_bytes: Vec, + finished_functions: BoxedSlice, + finished_dynamic_function_trampolines: BoxedSlice, + signatures: BoxedSlice, +} + +fn to_compile_error(err: impl Error) -> CompileError { + CompileError::Codegen(format!("{}", err)) +} + +const WASMER_METADATA_SYMBOL: &[u8] = b"WASMER_METADATA"; + +impl ObjectFileArtifact { + // Mach-O header in Mac + #[allow(dead_code)] + const MAGIC_HEADER_MH_CIGAM_64: &'static [u8] = &[207, 250, 237, 254]; + + // ELF Magic header for Linux (32 bit) + #[allow(dead_code)] + const MAGIC_HEADER_ELF_32: &'static [u8] = &[0x7f, b'E', b'L', b'F', 1]; + + // ELF Magic header for Linux (64 bit) + #[allow(dead_code)] + const MAGIC_HEADER_ELF_64: &'static [u8] = &[0x7f, b'E', b'L', b'F', 2]; + + // COFF Magic header for Windows (64 bit) + #[allow(dead_code)] + const MAGIC_HEADER_COFF_64: &'static [u8] = &[b'M', b'Z']; + + /// Check if the provided bytes look like `ObjectFileArtifact`. + /// + /// This means, if the bytes look like a shared object file in the target + /// system. + pub fn is_deserializable(bytes: &[u8]) -> bool { + cfg_if::cfg_if! { + if #[cfg(all(target_pointer_width = "64", target_os="macos"))] { + bytes.starts_with(Self::MAGIC_HEADER_MH_CIGAM_64) + } + else if #[cfg(all(target_pointer_width = "64", target_os="linux"))] { + bytes.starts_with(Self::MAGIC_HEADER_ELF_64) + } + else if #[cfg(all(target_pointer_width = "32", target_os="linux"))] { + bytes.starts_with(Self::MAGIC_HEADER_ELF_32) + } + else if #[cfg(all(target_pointer_width = "64", target_os="windows"))] { + bytes.starts_with(Self::MAGIC_HEADER_COFF_64) + } + else { + false + } + } + } + + #[cfg(feature = "compiler")] + /// Generate a compilation + fn generate_metadata<'data>( + data: &'data [u8], + features: &Features, + tunables: &dyn Tunables, + ) -> Result< + ( + CompileModuleInfo, + PrimaryMap>, + Vec>, + Option, + ), + CompileError, + > { + let environ = ModuleEnvironment::new(); + let translation = environ.translate(data).map_err(CompileError::Wasm)?; + let memory_styles: PrimaryMap = translation + .module + .memories + .values() + .map(|memory_type| tunables.memory_style(memory_type)) + .collect(); + let table_styles: PrimaryMap = translation + .module + .tables + .values() + .map(|table_type| tunables.table_style(table_type)) + .collect(); + + let compile_info = CompileModuleInfo { + module: Arc::new(translation.module), + features: features.clone(), + memory_styles, + table_styles, + }; + Ok(( + compile_info, + translation.function_body_inputs, + translation.data_initializers, + translation.module_translation, + )) + } + + /// Compile a data buffer into a `ObjectFileArtifact`, which can be statically linked against + /// and run later. + #[cfg(feature = "compiler")] + pub fn new( + engine: &ObjectFileEngine, + data: &[u8], + tunables: &dyn Tunables, + ) -> Result { + let mut engine_inner = engine.inner_mut(); + let target = engine.target(); + let compiler = engine_inner.compiler()?; + let (compile_info, function_body_inputs, data_initializers, module_translation) = + Self::generate_metadata(data, engine_inner.features(), tunables)?; + + let data_initializers = data_initializers + .iter() + .map(OwnedDataInitializer::new) + .collect::>() + .into_boxed_slice(); + + let target_triple = target.triple(); + + /* + // We construct the function body lengths + let function_body_lengths = compilation + .get_function_bodies() + .values() + .map(|function_body| function_body.body.len() as u64) + .map(|_function_body| 0u64) + .collect::>(); + */ + + // TODO: we currently supply all-zero function body lengths. + // We don't know the lengths until they're compiled, yet we have to + // supply the metadata as an input to the compile. + let function_body_lengths = function_body_inputs + .keys() + .map(|_function_body| 0u64) + .collect::>(); + + let metadata = ModuleMetadata { + compile_info, + prefix: engine_inner.get_prefix(&data), + data_initializers, + function_body_lengths, + }; + + // let wasm_info = generate_data_structures_for_c(&metadata); + // generate_c(wasm_info); + /* + In the C file we need: + - imports + - exports + + to construct an api::Module which is a Store (can be passed in via argument) and an + Arc which means this struct which includes: + - CompileModuleInfo + - Features + - ModuleInfo + - MemoryIndex -> MemoryStyle + - TableIndex -> TableStyle + - LocalFunctionIndex -> FunctionBodyPtr // finished functions + - FunctionIndex -> FunctionBodyPtr // finished dynamic function trampolines + - SignatureIndex -> VMSharedSignatureindextureIndex // signatures + */ + + let serialized_data = bincode::serialize(&metadata).map_err(to_compile_error)?; + let mut metadata_binary = vec![0; 10]; + let mut writable = &mut metadata_binary[..]; + leb128::write::unsigned(&mut writable, serialized_data.len() as u64) + .expect("Should write number"); + metadata_binary.extend(serialized_data); + + let maybe_obj_bytes = compiler.experimental_object_file_compile_module( + &target, + &metadata.compile_info, + module_translation.as_ref().unwrap(), + &function_body_inputs, + &metadata, + &metadata_binary, + ); + + let obj_bytes = if let Some(obj_bytes) = maybe_obj_bytes { + obj_bytes? + } else { + let compilation = compiler.compile_module( + &target, + &metadata.compile_info, + module_translation.as_ref().unwrap(), + function_body_inputs, + )?; + let mut obj = get_object_for_target(&target_triple).map_err(to_compile_error)?; + emit_data(&mut obj, WASMER_METADATA_SYMBOL, &metadata_binary) + .map_err(to_compile_error)?; + emit_compilation(&mut obj, compilation, &metadata, &target_triple) + .map_err(to_compile_error)?; + obj.write().map_err(to_compile_error)? + }; + + //let host_target = Triple::host(); + //let is_cross_compiling = target_triple != &host_target; + + Self::from_parts_crosscompiled(metadata, obj_bytes) + } + + /// Get the default extension when serializing this artifact + pub fn get_default_extension(triple: &Triple) -> &'static str { + match triple.operating_system { + OperatingSystem::Windows => "obj", + _ => "o", + } + } + + /// Construct a `ObjectFileArtifact` from component parts. + pub fn from_parts_crosscompiled( + metadata: ModuleMetadata, + module_bytes: Vec, + ) -> Result { + let finished_functions: PrimaryMap = PrimaryMap::new(); + let finished_dynamic_function_trampolines: PrimaryMap = + PrimaryMap::new(); + let signatures: PrimaryMap = PrimaryMap::new(); + Ok(Self { + metadata, + module_bytes, + finished_functions: finished_functions.into_boxed_slice(), + finished_dynamic_function_trampolines: finished_dynamic_function_trampolines + .into_boxed_slice(), + signatures: signatures.into_boxed_slice(), + }) + } + + /// Construct a `ObjectFileArtifact` from component parts. + pub fn from_parts( + engine_inner: &mut ObjectFileEngineInner, + metadata: ModuleMetadata, + ) -> Result { + let mut finished_functions: PrimaryMap = + PrimaryMap::new(); + for (function_local_index, function_len) in metadata.function_body_lengths.iter() { + let function_name = + metadata.symbol_to_name(Symbol::LocalFunction(function_local_index)); + /* + unsafe { + // We use a fake function signature `fn()` because we just + // want to get the function address. + let func: LibrarySymbol = lib + .get(function_name.as_bytes()) + .map_err(to_compile_error)?; + let raw = *func.into_raw(); + // The function pointer is a fat pointer, however this information + // is only used when retrieving the trap information which is not yet + // implemented in this engine. + let func_pointer = + std::slice::from_raw_parts(raw as *const (), *function_len as usize); + let func_pointer = func_pointer as *const [()] as *mut [VMFunctionBody]; + finished_functions.push(FunctionBodyPtr(func_pointer)); + } + */ + todo!("objectfileartifact:from_parts"); + } + + // Retrieve function call trampolines (for all signatures in the module) + for (sig_index, func_type) in metadata.compile_info.module.signatures.iter() { + let function_name = metadata.symbol_to_name(Symbol::FunctionCallTrampoline(sig_index)); + unsafe { + let trampoline = todo!("Get tramploine in ObjectFileArtifact::from_parts"); + //engine_inner.add_trampoline(&func_type, *trampoline); + } + } + + // Retrieve dynamic function trampolines (only for imported functions) + let mut finished_dynamic_function_trampolines: PrimaryMap = + PrimaryMap::with_capacity(metadata.compile_info.module.num_imported_functions); + for func_index in metadata + .compile_info + .module + .functions + .keys() + .take(metadata.compile_info.module.num_imported_functions) + { + let function_name = + metadata.symbol_to_name(Symbol::DynamicFunctionTrampoline(func_index)); + unsafe { + /*let trampoline: LibrarySymbol = lib + .get(function_name.as_bytes()) + .map_err(to_compile_error)?;*/ + todo!("Get trampoline in from_parts"); + /*let raw = *trampoline.into_raw(); + let trampoline_pointer = std::slice::from_raw_parts(raw as *const (), 0); + let trampoline_pointer = + trampoline_pointer as *const [()] as *mut [VMFunctionBody]; + finished_dynamic_function_trampolines.push(FunctionBodyPtr(trampoline_pointer));*/ + } + } + + // Leaving frame infos from now, as they are not yet used + // however they might be useful for the future. + // let frame_infos = compilation + // .get_frame_info() + // .values() + // .map(|frame_info| SerializableFunctionFrameInfo::Processed(frame_info.clone())) + // .collect::>(); + // Self::from_parts(&mut engine_inner, lib, metadata, ) + // let frame_info_registration = register_frame_info( + // serializable.module.clone(), + // &finished_functions, + // serializable.compilation.function_frame_info.clone(), + // ); + + // Compute indices into the shared signature table. + let signatures = { + let signature_registry = engine_inner.signatures(); + metadata + .compile_info + .module + .signatures + .values() + .map(|sig| signature_registry.register(sig)) + .collect::>() + }; + + Ok(Self { + metadata, + // TOOD: + module_bytes: vec![], + finished_functions: finished_functions.into_boxed_slice(), + finished_dynamic_function_trampolines: finished_dynamic_function_trampolines + .into_boxed_slice(), + signatures: signatures.into_boxed_slice(), + }) + } + + /// Compile a data buffer into a `ObjectFileArtifact`, which may then be instantiated. + #[cfg(not(feature = "compiler"))] + pub fn new(_engine: &ObjectFileEngine, _data: &[u8]) -> Result { + Err(CompileError::Codegen( + "Compilation is not enabled in the engine".to_string(), + )) + } + + /// Deserialize a `ObjectFileArtifact` from bytes. + /// + /// # Safety + /// + /// The bytes must represent a serialized WebAssembly module. + pub unsafe fn deserialize( + engine: &ObjectFileEngine, + bytes: &[u8], + ) -> Result { + let mut reader = bytes; + let data_len = leb128::read::unsigned(&mut reader).unwrap() as usize; + + let metadata: ModuleMetadata = bincode::deserialize(&bytes[10..(data_len + 10)]).unwrap(); + + // read finished functions in order now... + // read dynamic function trampolines in order now... + // read signatures in order now... + + Ok(Self { + metadata, + // TODO: review + module_bytes: vec![], + finished_functions: PrimaryMap::new().into_boxed_slice(), + finished_dynamic_function_trampolines: PrimaryMap::new().into_boxed_slice(), + signatures: PrimaryMap::new().into_boxed_slice(), + }) + + /*if !Self::is_deserializable(&bytes) { + return Err(DeserializeError::Incompatible( + "The provided bytes are not in any object file format Wasmer can understand" + .to_string(), + )); + }*/ + } + + /// Deserialize a `ObjectFileArtifact` from a file path. + /// + /// # Safety + /// + /// The file's content must represent a serialized WebAssembly module. + pub unsafe fn deserialize_from_file( + engine: &ObjectFileEngine, + path: &Path, + ) -> Result { + let mut file = File::open(&path)?; + let mut buffer = [0; 5]; + // read up to 5 bytes + file.read_exact(&mut buffer)?; + if !Self::is_deserializable(&buffer) { + return Err(DeserializeError::Incompatible( + "The provided bytes are not in any object file format Wasmer can understand" + .to_string(), + )); + } + Self::deserialize_from_file_unchecked(&engine, &path) + } + + /// Deserialize a `ObjectFileArtifact` from a file path (unchecked). + /// + /// # Safety + /// + /// The file's content must represent a serialized WebAssembly module. + pub unsafe fn deserialize_from_file_unchecked( + engine: &ObjectFileEngine, + path: &Path, + ) -> Result { + todo!("ObjectFileArtifact::deserialize_from_file_unchecked"); + /*Self::from_parts(&mut engine_inner, metadata, shared_path) + .map_err(DeserializeError::Compiler)*/ + } +} + +impl Artifact for ObjectFileArtifact { + fn module(&self) -> Arc { + self.metadata.compile_info.module.clone() + } + + fn module_ref(&self) -> &ModuleInfo { + &self.metadata.compile_info.module + } + + fn module_mut(&mut self) -> Option<&mut ModuleInfo> { + Arc::get_mut(&mut self.metadata.compile_info.module) + } + + fn register_frame_info(&self) { + // Do nothing for now + } + + fn features(&self) -> &Features { + &self.metadata.compile_info.features + } + + fn data_initializers(&self) -> &[OwnedDataInitializer] { + &*self.metadata.data_initializers + } + + fn memory_styles(&self) -> &PrimaryMap { + &self.metadata.compile_info.memory_styles + } + + fn table_styles(&self) -> &PrimaryMap { + &self.metadata.compile_info.table_styles + } + + fn finished_functions(&self) -> &BoxedSlice { + &self.finished_functions + } + + fn finished_dynamic_function_trampolines(&self) -> &BoxedSlice { + &self.finished_dynamic_function_trampolines + } + + fn signatures(&self) -> &BoxedSlice { + &self.signatures + } + + fn preinstantiate(&self) -> Result<(), InstantiationError> { + /*if self.library.is_none() { + return Err(InstantiationError::Link(LinkError::Trap( + RuntimeError::new("Cross compiled artifacts can't be instantiated."), + ))); + } + Ok(())*/ + todo!("figure out what preinstantiate means here"); + } + + /// Serialize a ObjectFileArtifact + fn serialize(&self) -> Result, SerializeError> { + Ok(self.module_bytes.clone()) + } +} diff --git a/lib/engine-object-file/src/builder.rs b/lib/engine-object-file/src/builder.rs new file mode 100644 index 000000000..809ee8bb0 --- /dev/null +++ b/lib/engine-object-file/src/builder.rs @@ -0,0 +1,113 @@ +use crate::ObjectFileEngine; +use wasmer_compiler::{CompilerConfig, Features, Target}; + +/// The ObjectFile builder +pub struct ObjectFile<'a> { + compiler_config: Option<&'a dyn CompilerConfig>, + target: Option, + features: Option, +} + +impl<'a> ObjectFile<'a> { + #[cfg(feature = "compiler")] + /// Create a new ObjectFile + pub fn new(compiler_config: &'a mut dyn CompilerConfig) -> Self { + compiler_config.enable_pic(); + + Self { + compiler_config: Some(compiler_config), + target: None, + features: None, + } + } + + /// Create a new headless ObjectFile + pub fn headless() -> Self { + Self { + compiler_config: None, + target: None, + features: None, + } + } + + /// Set the target + pub fn target(mut self, target: Target) -> Self { + self.target = Some(target); + self + } + + /// Set the features + pub fn features(mut self, features: Features) -> Self { + self.features = Some(features); + self + } + + /// Build the `ObjectFileEngine` for this configuration + pub fn engine(self) -> ObjectFileEngine { + if let Some(_compiler_config) = self.compiler_config { + #[cfg(feature = "compiler")] + { + let compiler_config = _compiler_config; + let target = self.target.unwrap_or_default(); + let features = self + .features + .unwrap_or_else(|| compiler_config.default_features_for_target(&target)); + let compiler = compiler_config.compiler(); + ObjectFileEngine::new(compiler, target, features) + } + + #[cfg(not(feature = "compiler"))] + { + unreachable!("Cannot call `ObjectFileEngine::new` without the `compiler` feature") + } + } else { + ObjectFileEngine::headless() + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + #[cfg(feature = "compiler")] + use std::sync::Arc; + #[cfg(feature = "compiler")] + use wasmer_compiler::{Compiler, FunctionMiddlewareGenerator}; + + #[cfg(feature = "compiler")] + #[derive(Default)] + pub struct TestCompilerConfig { + pub enabled_pic: bool, + pub middlewares: Vec>, + } + + #[cfg(feature = "compiler")] + impl CompilerConfig for TestCompilerConfig { + fn enable_pic(&mut self) { + self.enabled_pic = true; + } + + fn compiler(&self) -> Box { + unimplemented!("compiler not implemented"); + } + + fn push_middleware(&mut self, middleware: Arc) { + self.middlewares.push(middleware); + } + } + + #[cfg(feature = "compiler")] + #[test] + #[should_panic(expected = "compiler not implemented")] + fn build_engine() { + let mut compiler_config = TestCompilerConfig::default(); + let object_file = ObjectFile::new(&mut compiler_config); + let _engine = object_file.engine(); + } + + #[test] + fn build_headless_engine() { + let object_file = ObjectFile::headless(); + let _engine = object_file.engine(); + } +} diff --git a/lib/engine-object-file/src/engine.rs b/lib/engine-object-file/src/engine.rs new file mode 100644 index 000000000..26d85d210 --- /dev/null +++ b/lib/engine-object-file/src/engine.rs @@ -0,0 +1,250 @@ +use crate::ObjectFileArtifact; +use std::collections::HashMap; +use std::path::Path; +use std::sync::Arc; +use std::sync::Mutex; +#[cfg(feature = "compiler")] +use wasmer_compiler::Compiler; +use wasmer_compiler::{CompileError, Target}; +use wasmer_engine::{Artifact, DeserializeError, Engine, EngineId, Tunables}; +#[cfg(feature = "compiler")] +use wasmer_types::Features; +use wasmer_types::FunctionType; +use wasmer_vm::{SignatureRegistry, VMSharedSignatureIndex, VMTrampoline}; + +/// A WebAssembly `ObjectFile` Engine. +#[derive(Clone)] +pub struct ObjectFileEngine { + inner: Arc>, + /// The target for the compiler + target: Arc, + engine_id: EngineId, +} + +impl ObjectFileEngine { + /// Create a new `ObjectFileEngine` with the given config + #[cfg(feature = "compiler")] + pub fn new(compiler: Box, target: Target, features: Features) -> Self { + Self { + inner: Arc::new(Mutex::new(ObjectFileEngineInner { + compiler: Some(compiler), + trampolines: HashMap::new(), + signatures: SignatureRegistry::new(), + prefixer: None, + features, + })), + target: Arc::new(target), + engine_id: EngineId::default(), + } + } + + /// Create a headless `ObjectFileEngine` + /// + /// A headless engine is an engine without any compiler attached. + /// This is useful for assuring a minimal runtime for running + /// WebAssembly modules. + /// + /// For example, for running in IoT devices where compilers are very + /// expensive, or also to optimize startup speed. + /// + /// # Important + /// + /// Headless engines can't compile or validate any modules, + /// they just take already processed Modules (via `Module::serialize`). + pub fn headless() -> Self { + Self { + inner: Arc::new(Mutex::new(ObjectFileEngineInner { + #[cfg(feature = "compiler")] + compiler: None, + #[cfg(feature = "compiler")] + features: Features::default(), + trampolines: HashMap::new(), + signatures: SignatureRegistry::new(), + prefixer: None, + })), + target: Arc::new(Target::default()), + engine_id: EngineId::default(), + } + } + + /// Sets a prefixer for the wasm module, so we can avoid any collisions + /// in the exported function names on the generated shared object. + /// + /// This, allows us to rather than have functions named `wasmer_function_1` + /// to be named `wasmer_function_PREFIX_1`. + /// + /// # Important + /// + /// This prefixer function should be deterministic, so the compilation + /// remains deterministic. + pub fn set_deterministic_prefixer(&mut self, prefixer: F) + where + F: Fn(&[u8]) -> String + Send + 'static, + { + let mut inner = self.inner_mut(); + inner.prefixer = Some(Box::new(prefixer)); + } + + pub(crate) fn inner(&self) -> std::sync::MutexGuard<'_, ObjectFileEngineInner> { + self.inner.lock().unwrap() + } + + pub(crate) fn inner_mut(&self) -> std::sync::MutexGuard<'_, ObjectFileEngineInner> { + self.inner.lock().unwrap() + } +} + +impl Engine for ObjectFileEngine { + /// The target + fn target(&self) -> &Target { + &self.target + } + + /// Register a signature + fn register_signature(&self, func_type: &FunctionType) -> VMSharedSignatureIndex { + let compiler = self.inner(); + compiler.signatures().register(func_type) + } + + /// Lookup a signature + fn lookup_signature(&self, sig: VMSharedSignatureIndex) -> Option { + let compiler = self.inner(); + compiler.signatures().lookup(sig) + } + + /// Retrieves a trampoline given a signature + fn function_call_trampoline(&self, sig: VMSharedSignatureIndex) -> Option { + self.inner().trampoline(sig) + } + + /// Validates a WebAssembly module + fn validate(&self, binary: &[u8]) -> Result<(), CompileError> { + self.inner().validate(binary) + } + + /// Compile a WebAssembly binary + #[cfg(feature = "compiler")] + fn compile( + &self, + binary: &[u8], + tunables: &dyn Tunables, + ) -> Result, CompileError> { + Ok(Arc::new(ObjectFileArtifact::new(&self, binary, tunables)?)) + } + + /// Compile a WebAssembly binary (it will fail because the `compiler` flag is disabled). + #[cfg(not(feature = "compiler"))] + fn compile( + &self, + _binary: &[u8], + _tunables: &dyn Tunables, + ) -> Result, CompileError> { + Err(CompileError::Codegen( + "The `ObjectFileEngine` is operating in headless mode, so it cannot compile a module." + .to_string(), + )) + } + + /// Deserializes a WebAssembly module (binary content of a Shared Object file) + unsafe fn deserialize(&self, bytes: &[u8]) -> Result, DeserializeError> { + Ok(Arc::new(ObjectFileArtifact::deserialize(&self, &bytes)?)) + } + + /// Deserializes a WebAssembly module from a path + /// It should point to a Shared Object file generated by this engine. + unsafe fn deserialize_from_file( + &self, + file_ref: &Path, + ) -> Result, DeserializeError> { + Ok(Arc::new(ObjectFileArtifact::deserialize_from_file( + &self, &file_ref, + )?)) + } + + fn id(&self) -> &EngineId { + &self.engine_id + } + + fn cloned(&self) -> Arc { + Arc::new(self.clone()) + } +} + +/// The inner contents of `ObjectFileEngine` +pub struct ObjectFileEngineInner { + /// The compiler + #[cfg(feature = "compiler")] + compiler: Option>, + /// The WebAssembly features to use + #[cfg(feature = "compiler")] + features: Features, + /// Pointers to trampoline functions used to enter particular signatures + trampolines: HashMap, + /// The signature registry is used mainly to operate with trampolines + /// performantly. + signatures: SignatureRegistry, + /// The prefixer returns the a String to prefix each of + /// the functions in the shared object generated by the `ObjectFileEngine`, + /// so we can assure no collisions. + prefixer: Option String + Send>>, +} + +impl ObjectFileEngineInner { + /// Gets the compiler associated to this engine. + #[cfg(feature = "compiler")] + pub fn compiler(&self) -> Result<&dyn Compiler, CompileError> { + if self.compiler.is_none() { + return Err(CompileError::Codegen("The `ObjectFileEngine` is operating in headless mode, so it can only execute already compiled Modules.".to_string())); + } + Ok(&**self + .compiler + .as_ref() + .expect("Can't get compiler reference")) + } + + #[cfg(feature = "compiler")] + pub(crate) fn get_prefix(&self, bytes: &[u8]) -> String { + if let Some(prefixer) = &self.prefixer { + prefixer(&bytes) + } else { + "".to_string() + } + } + + #[cfg(feature = "compiler")] + pub(crate) fn features(&self) -> &Features { + &self.features + } + + /// Validate the module + #[cfg(feature = "compiler")] + pub fn validate<'data>(&self, data: &'data [u8]) -> Result<(), CompileError> { + self.compiler()?.validate_module(self.features(), data) + } + + /// Validate the module + #[cfg(not(feature = "compiler"))] + pub fn validate<'data>(&self, _data: &'data [u8]) -> Result<(), CompileError> { + Err(CompileError::Validate( + "The `ObjectFileEngine` is not compiled with compiler support, which is required for validating".to_string(), + )) + } + + /// Shared signature registry. + pub fn signatures(&self) -> &SignatureRegistry { + &self.signatures + } + + /// Gets the trampoline pre-registered for a particular signature + pub fn trampoline(&self, sig: VMSharedSignatureIndex) -> Option { + self.trampolines.get(&sig).cloned() + } + + pub(crate) fn add_trampoline(&mut self, func_type: &FunctionType, trampoline: VMTrampoline) { + let index = self.signatures.register(&func_type); + // We always use (for now) the latest trampoline compiled + // TODO: we need to deallocate trampolines as the compiled modules + // where they belong become unallocated. + self.trampolines.insert(index, trampoline); + } +} diff --git a/lib/engine-object-file/src/lib.rs b/lib/engine-object-file/src/lib.rs new file mode 100644 index 000000000..e3f607811 --- /dev/null +++ b/lib/engine-object-file/src/lib.rs @@ -0,0 +1,34 @@ +//! Object file backend for Wasmer compilers. +//! +//! Given a compiler (such as `CraneliftCompiler` or `LLVMCompiler`) +//! it generates a object file (.o file) and metadata which can be used +//! to access it from other programming languages static. + +#![deny(missing_docs, trivial_numeric_casts, unused_extern_crates)] +#![warn(unused_import_braces)] +#![cfg_attr(feature = "cargo-clippy", allow(clippy::new_without_default))] +#![cfg_attr( + feature = "cargo-clippy", + warn( + clippy::float_arithmetic, + clippy::mut_mut, + clippy::nonminimal_bool, + clippy::option_map_unwrap_or, + clippy::option_map_unwrap_or_else, + clippy::print_stdout, + clippy::unicode_not_nfc, + clippy::use_self + ) +)] + +mod artifact; +mod builder; +mod engine; +mod serialize; + +pub use crate::artifact::ObjectFileArtifact; +pub use crate::builder::ObjectFile; +pub use crate::engine::ObjectFileEngine; + +/// Version number of this crate. +pub const VERSION: &str = env!("CARGO_PKG_VERSION"); diff --git a/lib/engine-object-file/src/serialize.rs b/lib/engine-object-file/src/serialize.rs new file mode 100644 index 000000000..644b63d03 --- /dev/null +++ b/lib/engine-object-file/src/serialize.rs @@ -0,0 +1,66 @@ +use serde::{Deserialize, Serialize}; +use wasmer_compiler::{CompileModuleInfo, SectionIndex, Symbol, SymbolRegistry}; +use wasmer_types::entity::{EntityRef, PrimaryMap}; +use wasmer_types::{FunctionIndex, LocalFunctionIndex, OwnedDataInitializer, SignatureIndex}; + +/// Serializable struct that represents the compiled metadata. +#[derive(Serialize, Deserialize, Debug)] +pub struct ModuleMetadata { + pub compile_info: CompileModuleInfo, + pub prefix: String, + pub data_initializers: Box<[OwnedDataInitializer]>, + // The function body lengths (used to find function by address) + pub function_body_lengths: PrimaryMap, +} + +impl SymbolRegistry for ModuleMetadata { + fn symbol_to_name(&self, symbol: Symbol) -> String { + match symbol { + Symbol::LocalFunction(index) => { + format!("wasmer_function_{}_{}", self.prefix, index.index()) + } + Symbol::Section(index) => format!("wasmer_section_{}_{}", self.prefix, index.index()), + Symbol::FunctionCallTrampoline(index) => format!( + "wasmer_trampoline_function_call_{}_{}", + self.prefix, + index.index() + ), + Symbol::DynamicFunctionTrampoline(index) => format!( + "wasmer_trampoline_dynamic_function_{}_{}", + self.prefix, + index.index() + ), + } + } + + fn name_to_symbol(&self, name: &str) -> Option { + if let Some(index) = name.strip_prefix(&format!("wasmer_function_{}_", self.prefix)) { + index + .parse::() + .ok() + .map(|index| Symbol::LocalFunction(LocalFunctionIndex::from_u32(index))) + } else if let Some(index) = name.strip_prefix(&format!("wasmer_section_{}_", self.prefix)) { + index + .parse::() + .ok() + .map(|index| Symbol::Section(SectionIndex::from_u32(index))) + } else if let Some(index) = + name.strip_prefix(&format!("wasmer_trampoline_function_call_{}_", self.prefix)) + { + index + .parse::() + .ok() + .map(|index| Symbol::FunctionCallTrampoline(SignatureIndex::from_u32(index))) + } else if let Some(index) = name.strip_prefix(&format!( + "wasmer_trampoline_dynamic_function_{}_", + self.prefix + )) { + index + .parse::() + .ok() + .map(|index| Symbol::DynamicFunctionTrampoline(FunctionIndex::from_u32(index))) + } else { + None + } + } +} From 485cc1dc7eb1bf741f9a85e75d0cd544d9639dcd Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Fri, 28 Aug 2020 14:54:20 -0700 Subject: [PATCH 002/281] Fix things up, get things working --- Makefile | 3 + lib/api/src/module.rs | 7 + lib/c-api/src/wasm_c_api/mod.rs | 4 +- lib/cli/src/commands/compile.rs | 25 +- lib/engine-object-file/src/artifact.rs | 433 +++++++++++++++---------- lib/engine-object-file/src/engine.rs | 12 +- lib/engine/src/artifact.rs | 5 + 7 files changed, 292 insertions(+), 197 deletions(-) diff --git a/Makefile b/Makefile index 6ffe7ebfe..4ca4ff68f 100644 --- a/Makefile +++ b/Makefile @@ -90,6 +90,9 @@ build-capi-llvm: build-capi-native: cargo build --manifest-path lib/c-api/Cargo.toml --release \ --no-default-features --features object-file,wasi +build-capi-native-debug: + cargo build --manifest-path lib/c-api/Cargo.toml \ + --no-default-features --features object-file,wasi ########### diff --git a/lib/api/src/module.rs b/lib/api/src/module.rs index 1f3902bb6..7ec3955a8 100644 --- a/lib/api/src/module.rs +++ b/lib/api/src/module.rs @@ -410,6 +410,13 @@ impl Module { pub fn info(&self) -> &ModuleInfo { &self.artifact.module_ref() } + + /// Temporary function to implement this; we probably want to implement the functionality + /// dependent on the `Artifact` as individual hidden methods on the `Module`. + #[doc(hidden)] + pub fn artifact(&self) -> &Arc { + &self.artifact + } } impl fmt::Debug for Module { diff --git a/lib/c-api/src/wasm_c_api/mod.rs b/lib/c-api/src/wasm_c_api/mod.rs index cbb38ee2f..ee0a4a64a 100644 --- a/lib/c-api/src/wasm_c_api/mod.rs +++ b/lib/c-api/src/wasm_c_api/mod.rs @@ -26,7 +26,7 @@ use wasmer_engine_jit::JIT; #[cfg(feature = "native")] use wasmer_engine_native::Native; #[cfg(feature = "object-file")] -use wasmer_engine_object_file::ObjectFile; +use wasmer_engine_object_file::{ObjectFile, ObjectFileArtifact}; /// this can be a wasmer-specific type with wasmer-specific functions for manipulating it #[repr(C)] @@ -265,6 +265,7 @@ pub unsafe extern "C" fn wasm_module_exports( .map(Box::new) .map(Box::into_raw) .collect::>(); + exports.shrink_to_fit(); debug_assert_eq!(exports.len(), exports.capacity()); out.size = exports.len(); @@ -284,6 +285,7 @@ pub unsafe extern "C" fn wasm_module_imports( .map(Box::new) .map(Box::into_raw) .collect::>(); + imports.shrink_to_fit(); debug_assert_eq!(imports.len(), imports.capacity()); out.size = imports.len(); diff --git a/lib/cli/src/commands/compile.rs b/lib/cli/src/commands/compile.rs index 75bd712da..1748bcfc1 100644 --- a/lib/cli/src/commands/compile.rs +++ b/lib/cli/src/commands/compile.rs @@ -94,18 +94,19 @@ impl Compile { println!("Target: {}", target.triple()); let module = Module::from_file(&store, &self.path)?; let _ = module.serialize_to_file(&self.output)?; - // for C code - let module_bytes = module.serialize()?; - let mut header = std::fs::OpenOptions::new() - .create(true) - .truncate(true) - .write(true) - .open("test.h")?; - use std::io::Write; - header - .write(format!("const int module_bytes_len = {};\n", module_bytes.len()).as_bytes())?; - header.write(b"extern const char WASMER_METADATA[];\n")?; - // end c gen + #[cfg(feature = "object-file")] + if let Some(header_file_src) = module.artifact().create_header_file() { + // for C code + let mut header = std::fs::OpenOptions::new() + .create(true) + .truncate(true) + .write(true) + .open("test.h")?; + + use std::io::Write; + header.write(header_file_src.as_bytes())?; + // end c gen + } eprintln!( "✔ File compiled successfully to `{}`.", self.output.display(), diff --git a/lib/engine-object-file/src/artifact.rs b/lib/engine-object-file/src/artifact.rs index c4dede427..a23b35c6b 100644 --- a/lib/engine-object-file/src/artifact.rs +++ b/lib/engine-object-file/src/artifact.rs @@ -3,28 +3,21 @@ use crate::engine::{ObjectFileEngine, ObjectFileEngineInner}; use crate::serialize::ModuleMetadata; +use std::collections::BTreeMap; use std::error::Error; -use std::fs::File; -use std::io::{Read, Write}; -use std::path::{Path, PathBuf}; -#[cfg(feature = "compiler")] -use std::process::Command; +use std::mem; use std::sync::Arc; -use tempfile::NamedTempFile; -#[cfg(feature = "compiler")] -use tracing::trace; use wasmer_compiler::{CompileError, Features, OperatingSystem, Symbol, SymbolRegistry, Triple}; #[cfg(feature = "compiler")] use wasmer_compiler::{ CompileModuleInfo, FunctionBodyData, ModuleEnvironment, ModuleTranslationState, }; -use wasmer_engine::{ - Artifact, DeserializeError, InstantiationError, LinkError, RuntimeError, SerializeError, -}; +use wasmer_engine::{Artifact, DeserializeError, InstantiationError, SerializeError}; #[cfg(feature = "compiler")] use wasmer_engine::{Engine, Tunables}; #[cfg(feature = "compiler")] use wasmer_object::{emit_compilation, emit_data, get_object_for_target}; +use wasmer_types::entity::EntityRef; use wasmer_types::entity::{BoxedSlice, PrimaryMap}; #[cfg(feature = "compiler")] use wasmer_types::DataInitializer; @@ -33,8 +26,7 @@ use wasmer_types::{ TableIndex, }; use wasmer_vm::{ - FunctionBodyPtr, MemoryStyle, ModuleInfo, TableStyle, VMFunctionBody, VMSharedSignatureIndex, - VMTrampoline, + FunctionBodyPtr, MemoryStyle, ModuleInfo, TableStyle, VMSharedSignatureIndex, VMTrampoline, }; /// A compiled wasm module, ready to be instantiated. @@ -44,6 +36,8 @@ pub struct ObjectFileArtifact { finished_functions: BoxedSlice, finished_dynamic_function_trampolines: BoxedSlice, signatures: BoxedSlice, + /// Length of the serialized metadata + metadata_length: usize, } fn to_compile_error(err: impl Error) -> CompileError { @@ -162,11 +156,11 @@ impl ObjectFileArtifact { /* // We construct the function body lengths let function_body_lengths = compilation - .get_function_bodies() - .values() - .map(|function_body| function_body.body.len() as u64) - .map(|_function_body| 0u64) - .collect::>(); + .get_function_bodies() + .values() + .map(|function_body| function_body.body.len() as u64) + .map(|_function_body| 0u64) + .collect::>(); */ // TODO: we currently supply all-zero function body lengths. @@ -194,10 +188,10 @@ impl ObjectFileArtifact { to construct an api::Module which is a Store (can be passed in via argument) and an Arc which means this struct which includes: - CompileModuleInfo - - Features - - ModuleInfo - - MemoryIndex -> MemoryStyle - - TableIndex -> TableStyle + - Features + - ModuleInfo + - MemoryIndex -> MemoryStyle + - TableIndex -> TableStyle - LocalFunctionIndex -> FunctionBodyPtr // finished functions - FunctionIndex -> FunctionBodyPtr // finished dynamic function trampolines - SignatureIndex -> VMSharedSignatureindextureIndex // signatures @@ -209,6 +203,7 @@ impl ObjectFileArtifact { leb128::write::unsigned(&mut writable, serialized_data.len() as u64) .expect("Should write number"); metadata_binary.extend(serialized_data); + let metadata_length = metadata_binary.len(); let maybe_obj_bytes = compiler.experimental_object_file_compile_module( &target, @@ -239,7 +234,111 @@ impl ObjectFileArtifact { //let host_target = Triple::host(); //let is_cross_compiling = target_triple != &host_target; - Self::from_parts_crosscompiled(metadata, obj_bytes) + Self::from_parts_crosscompiled(&mut *engine_inner, metadata, obj_bytes, metadata_length) + } + + /// Generate the header file that goes with the generated object file. + pub fn generate_header_file(&self) -> String { + let mut out = String::new(); + use std::fmt::Write; + // TODO: double check this length (it's probably off by 10 or so) + write!( + &mut out, + "const int module_bytes_len = {};\n", + self.metadata_length + ) + .unwrap(); + write!(&mut out, "extern const char WASMER_METADATA[];\n\n").unwrap(); + for (function_local_index, _function_len) in self.metadata.function_body_lengths.iter() { + let function_name = self + .metadata + .symbol_to_name(Symbol::LocalFunction(function_local_index)); + // TODO: figure out the signtaure here too + write!(&mut out, "void {}(void);\n", function_name).unwrap(); + } + + // function pointer array + { + write!(&mut out, "const void* function_pointers[] = {{\n").unwrap(); + for (function_local_index, _function_len) in self.metadata.function_body_lengths.iter() + { + let function_name = self + .metadata + .symbol_to_name(Symbol::LocalFunction(function_local_index)); + // TODO: figure out the signtaure here too + write!(&mut out, "\t{},\n", function_name).unwrap(); + //write!(&mut out, "\t{},\n", function_len).unwrap(); + } + write!(&mut out, "}};\n").unwrap(); + } + + write!(&mut out, "\n").unwrap(); + + for (sig_index, _func_type) in self.metadata.compile_info.module.signatures.iter() { + let function_name = self + .metadata + .symbol_to_name(Symbol::FunctionCallTrampoline(sig_index)); + + write!(&mut out, "void {}(void*, void*, void*);\n", function_name).unwrap(); + } + + write!(&mut out, "\n").unwrap(); + + // function trampolines + { + write!(&mut out, "const void* function_trampolines[] = {{\n").unwrap(); + for (sig_index, _vm_shared_index) in self.metadata.compile_info.module.signatures.iter() + { + let function_name = self + .metadata + .symbol_to_name(Symbol::FunctionCallTrampoline(sig_index)); + write!(&mut out, "\t{},\n", function_name).unwrap(); + } + write!(&mut out, "}};\n").unwrap(); + } + + write!(&mut out, "\n").unwrap(); + + for func_index in self + .metadata + .compile_info + .module + .functions + .keys() + .take(self.metadata.compile_info.module.num_imported_functions) + { + let function_name = self + .metadata + .symbol_to_name(Symbol::DynamicFunctionTrampoline(func_index)); + // TODO: figure out the signature here + write!(&mut out, "void {}(void*, void*, void*);\n", function_name).unwrap(); + } + + // dynamic function trampoline pointer array + { + write!( + &mut out, + "const void* dynamic_function_trampoline_pointers[] = {{\n" + ) + .unwrap(); + for func_index in self + .metadata + .compile_info + .module + .functions + .keys() + .take(self.metadata.compile_info.module.num_imported_functions) + { + let function_name = self + .metadata + .symbol_to_name(Symbol::DynamicFunctionTrampoline(func_index)); + // TODO: figure out the signature here + write!(&mut out, "\t{},\n", function_name).unwrap(); + } + write!(&mut out, "}};\n").unwrap(); + } + + out } /// Get the default extension when serializing this artifact @@ -252,13 +351,24 @@ impl ObjectFileArtifact { /// Construct a `ObjectFileArtifact` from component parts. pub fn from_parts_crosscompiled( + engine_inner: &mut ObjectFileEngineInner, metadata: ModuleMetadata, module_bytes: Vec, + metadata_length: usize, ) -> Result { let finished_functions: PrimaryMap = PrimaryMap::new(); let finished_dynamic_function_trampolines: PrimaryMap = PrimaryMap::new(); - let signatures: PrimaryMap = PrimaryMap::new(); + //let signatures: PrimaryMap = PrimaryMap::new(); + let signature_registry = engine_inner.signatures(); + let signatures = metadata + .compile_info + .module + .signatures + .values() + .map(|sig| signature_registry.register(sig)) + .collect::>(); + Ok(Self { metadata, module_bytes, @@ -266,107 +376,7 @@ impl ObjectFileArtifact { finished_dynamic_function_trampolines: finished_dynamic_function_trampolines .into_boxed_slice(), signatures: signatures.into_boxed_slice(), - }) - } - - /// Construct a `ObjectFileArtifact` from component parts. - pub fn from_parts( - engine_inner: &mut ObjectFileEngineInner, - metadata: ModuleMetadata, - ) -> Result { - let mut finished_functions: PrimaryMap = - PrimaryMap::new(); - for (function_local_index, function_len) in metadata.function_body_lengths.iter() { - let function_name = - metadata.symbol_to_name(Symbol::LocalFunction(function_local_index)); - /* - unsafe { - // We use a fake function signature `fn()` because we just - // want to get the function address. - let func: LibrarySymbol = lib - .get(function_name.as_bytes()) - .map_err(to_compile_error)?; - let raw = *func.into_raw(); - // The function pointer is a fat pointer, however this information - // is only used when retrieving the trap information which is not yet - // implemented in this engine. - let func_pointer = - std::slice::from_raw_parts(raw as *const (), *function_len as usize); - let func_pointer = func_pointer as *const [()] as *mut [VMFunctionBody]; - finished_functions.push(FunctionBodyPtr(func_pointer)); - } - */ - todo!("objectfileartifact:from_parts"); - } - - // Retrieve function call trampolines (for all signatures in the module) - for (sig_index, func_type) in metadata.compile_info.module.signatures.iter() { - let function_name = metadata.symbol_to_name(Symbol::FunctionCallTrampoline(sig_index)); - unsafe { - let trampoline = todo!("Get tramploine in ObjectFileArtifact::from_parts"); - //engine_inner.add_trampoline(&func_type, *trampoline); - } - } - - // Retrieve dynamic function trampolines (only for imported functions) - let mut finished_dynamic_function_trampolines: PrimaryMap = - PrimaryMap::with_capacity(metadata.compile_info.module.num_imported_functions); - for func_index in metadata - .compile_info - .module - .functions - .keys() - .take(metadata.compile_info.module.num_imported_functions) - { - let function_name = - metadata.symbol_to_name(Symbol::DynamicFunctionTrampoline(func_index)); - unsafe { - /*let trampoline: LibrarySymbol = lib - .get(function_name.as_bytes()) - .map_err(to_compile_error)?;*/ - todo!("Get trampoline in from_parts"); - /*let raw = *trampoline.into_raw(); - let trampoline_pointer = std::slice::from_raw_parts(raw as *const (), 0); - let trampoline_pointer = - trampoline_pointer as *const [()] as *mut [VMFunctionBody]; - finished_dynamic_function_trampolines.push(FunctionBodyPtr(trampoline_pointer));*/ - } - } - - // Leaving frame infos from now, as they are not yet used - // however they might be useful for the future. - // let frame_infos = compilation - // .get_frame_info() - // .values() - // .map(|frame_info| SerializableFunctionFrameInfo::Processed(frame_info.clone())) - // .collect::>(); - // Self::from_parts(&mut engine_inner, lib, metadata, ) - // let frame_info_registration = register_frame_info( - // serializable.module.clone(), - // &finished_functions, - // serializable.compilation.function_frame_info.clone(), - // ); - - // Compute indices into the shared signature table. - let signatures = { - let signature_registry = engine_inner.signatures(); - metadata - .compile_info - .module - .signatures - .values() - .map(|sig| signature_registry.register(sig)) - .collect::>() - }; - - Ok(Self { - metadata, - // TOOD: - module_bytes: vec![], - finished_functions: finished_functions.into_boxed_slice(), - finished_dynamic_function_trampolines: finished_dynamic_function_trampolines - .into_boxed_slice(), - signatures: signatures.into_boxed_slice(), + metadata_length, }) } @@ -392,61 +402,127 @@ impl ObjectFileArtifact { let metadata: ModuleMetadata = bincode::deserialize(&bytes[10..(data_len + 10)]).unwrap(); + const WORD_SIZE: usize = mem::size_of::(); + let mut byte_buffer = [0u8; WORD_SIZE]; + + let mut cur_offset = data_len + 10; + for i in 0..WORD_SIZE { + byte_buffer[i] = bytes[cur_offset + i]; + } + cur_offset += WORD_SIZE; + + let num_finished_functions = usize::from_ne_bytes(byte_buffer); + let mut finished_functions = PrimaryMap::new(); + + #[repr(C)] + struct SlicePtr { + ptr: usize, + len: usize, + } + + dbg!(num_finished_functions); + + let mut engine_inner = engine.inner_mut(); + let signature_registry = engine_inner.signatures(); + let mut sig_map: BTreeMap = BTreeMap::new(); + // read finished functions in order now... + for i in 0..num_finished_functions { + let sig_idx = metadata.compile_info.module.functions[FunctionIndex::new(i)]; + let func_type = &metadata.compile_info.module.signatures[sig_idx]; + let vm_shared_idx = signature_registry.register(&func_type); + sig_map.insert(sig_idx, vm_shared_idx); + + let mut sp = SlicePtr { ptr: 0, len: 0 }; + for j in 0..WORD_SIZE { + byte_buffer[j] = bytes[cur_offset + j]; + } + sp.ptr = usize::from_ne_bytes(byte_buffer); + cur_offset += WORD_SIZE; + // REVIEW: we can also serialize and read back lengths, do we want to do this? + /*for j in 0..WORD_SIZE { + byte_buffer[j] = bytes[cur_offset + j]; + } + sp.len = usize::from_ne_bytes(byte_buffer); + cur_offset += WORD_SIZE;*/ + + let fp = FunctionBodyPtr(mem::transmute(sp)); + finished_functions.push(fp); + } + + let mut signatures: PrimaryMap<_, VMSharedSignatureIndex> = PrimaryMap::new(); + for i in 0..(sig_map.len()) { + if let Some(shared_idx) = sig_map.get(&SignatureIndex::new(i)) { + signatures.push(*shared_idx); + } else { + panic!("Invalid data, missing sig idx; TODO: handle this error"); + } + } + + // read trampolines in order + for i in 0..WORD_SIZE { + byte_buffer[i] = bytes[cur_offset + i]; + } + cur_offset += WORD_SIZE; + let num_function_trampolines = usize::from_ne_bytes(byte_buffer); + dbg!(&num_function_trampolines); + for i in 0..num_function_trampolines { + for j in 0..WORD_SIZE { + byte_buffer[j] = bytes[cur_offset + j]; + } + cur_offset += WORD_SIZE; + let trampoline_ptr_bytes = usize::from_ne_bytes(byte_buffer); + let trampoline = mem::transmute::(trampoline_ptr_bytes); + + let func_type = &metadata.compile_info.module.signatures[SignatureIndex::new(i)]; + + engine_inner.add_trampoline(func_type, trampoline); + // REVIEW: we can also serialize and read back lengths, do we want to do this? + /*for j in 0..WORD_SIZE { + byte_buffer[j] = bytes[cur_offset + j]; + } + sp.len = usize::from_ne_bytes(byte_buffer); + cur_offset += WORD_SIZE;*/ + } + // read dynamic function trampolines in order now... - // read signatures in order now... + let mut finished_dynamic_function_trampolines = PrimaryMap::new(); + for i in 0..WORD_SIZE { + byte_buffer[i] = bytes[cur_offset + i]; + } + cur_offset += WORD_SIZE; + let num_dynamic_trampoline_functions = usize::from_ne_bytes(byte_buffer); + dbg!(&num_dynamic_trampoline_functions); + for _i in 0..num_dynamic_trampoline_functions { + let mut sp = SlicePtr { ptr: 0, len: 0 }; + for j in 0..WORD_SIZE { + byte_buffer[j] = bytes[cur_offset + j]; + } + sp.ptr = usize::from_ne_bytes(byte_buffer); + cur_offset += WORD_SIZE; + + // REVIEW: we can also serialize and read back lengths, do we want to do this? + /*for j in 0..WORD_SIZE { + byte_buffer[j] = bytes[cur_offset + j]; + } + sp.len = usize::from_ne_bytes(byte_buffer); + cur_offset += WORD_SIZE;*/ + + let fp = FunctionBodyPtr(mem::transmute(sp)); + + finished_dynamic_function_trampolines.push(fp); + } Ok(Self { metadata, // TODO: review module_bytes: vec![], - finished_functions: PrimaryMap::new().into_boxed_slice(), - finished_dynamic_function_trampolines: PrimaryMap::new().into_boxed_slice(), - signatures: PrimaryMap::new().into_boxed_slice(), + finished_functions: finished_functions.into_boxed_slice(), + finished_dynamic_function_trampolines: finished_dynamic_function_trampolines + .into_boxed_slice(), + signatures: signatures.into_boxed_slice(), + metadata_length: 0, }) - - /*if !Self::is_deserializable(&bytes) { - return Err(DeserializeError::Incompatible( - "The provided bytes are not in any object file format Wasmer can understand" - .to_string(), - )); - }*/ - } - - /// Deserialize a `ObjectFileArtifact` from a file path. - /// - /// # Safety - /// - /// The file's content must represent a serialized WebAssembly module. - pub unsafe fn deserialize_from_file( - engine: &ObjectFileEngine, - path: &Path, - ) -> Result { - let mut file = File::open(&path)?; - let mut buffer = [0; 5]; - // read up to 5 bytes - file.read_exact(&mut buffer)?; - if !Self::is_deserializable(&buffer) { - return Err(DeserializeError::Incompatible( - "The provided bytes are not in any object file format Wasmer can understand" - .to_string(), - )); - } - Self::deserialize_from_file_unchecked(&engine, &path) - } - - /// Deserialize a `ObjectFileArtifact` from a file path (unchecked). - /// - /// # Safety - /// - /// The file's content must represent a serialized WebAssembly module. - pub unsafe fn deserialize_from_file_unchecked( - engine: &ObjectFileEngine, - path: &Path, - ) -> Result { - todo!("ObjectFileArtifact::deserialize_from_file_unchecked"); - /*Self::from_parts(&mut engine_inner, metadata, shared_path) - .map_err(DeserializeError::Compiler)*/ } } @@ -495,14 +571,13 @@ impl Artifact for ObjectFileArtifact { &self.signatures } + fn create_header_file(&self) -> Option { + Some(self.generate_header_file()) + } + fn preinstantiate(&self) -> Result<(), InstantiationError> { - /*if self.library.is_none() { - return Err(InstantiationError::Link(LinkError::Trap( - RuntimeError::new("Cross compiled artifacts can't be instantiated."), - ))); - } - Ok(())*/ - todo!("figure out what preinstantiate means here"); + //todo!("figure out what preinstantiate means here"); + Ok(()) } /// Serialize a ObjectFileArtifact diff --git a/lib/engine-object-file/src/engine.rs b/lib/engine-object-file/src/engine.rs index 26d85d210..3c83a275f 100644 --- a/lib/engine-object-file/src/engine.rs +++ b/lib/engine-object-file/src/engine.rs @@ -1,8 +1,8 @@ use crate::ObjectFileArtifact; use std::collections::HashMap; +use std::io::Read; use std::path::Path; -use std::sync::Arc; -use std::sync::Mutex; +use std::sync::{Arc, Mutex}; #[cfg(feature = "compiler")] use wasmer_compiler::Compiler; use wasmer_compiler::{CompileError, Target}; @@ -156,9 +156,11 @@ impl Engine for ObjectFileEngine { &self, file_ref: &Path, ) -> Result, DeserializeError> { - Ok(Arc::new(ObjectFileArtifact::deserialize_from_file( - &self, &file_ref, - )?)) + let mut f = std::fs::File::open(file_ref)?; + let mut vec = vec![]; + f.read_to_end(&mut vec)?; + + self.deserialize(&vec[..]) } fn id(&self) -> &EngineId { diff --git a/lib/engine/src/artifact.rs b/lib/engine/src/artifact.rs index 9da00f6ef..cc7ef812f 100644 --- a/lib/engine/src/artifact.rs +++ b/lib/engine/src/artifact.rs @@ -71,6 +71,11 @@ pub trait Artifact: Send + Sync { Ok(()) } + /// Create a header file for use with a native object file; + fn create_header_file(&self) -> Option { + None + } + /// Do preinstantiation logic that is executed before instantiating fn preinstantiate(&self) -> Result<(), InstantiationError> { Ok(()) From 2a366e7de93f973c92cd8de7783b5a2ad4d61fad Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Fri, 28 Aug 2020 14:56:49 -0700 Subject: [PATCH 003/281] Clean up --- lib/c-api/src/wasm_c_api/mod.rs | 2 +- lib/engine-object-file/src/artifact.rs | 4 ---- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/lib/c-api/src/wasm_c_api/mod.rs b/lib/c-api/src/wasm_c_api/mod.rs index ee0a4a64a..fcef3e566 100644 --- a/lib/c-api/src/wasm_c_api/mod.rs +++ b/lib/c-api/src/wasm_c_api/mod.rs @@ -26,7 +26,7 @@ use wasmer_engine_jit::JIT; #[cfg(feature = "native")] use wasmer_engine_native::Native; #[cfg(feature = "object-file")] -use wasmer_engine_object_file::{ObjectFile, ObjectFileArtifact}; +use wasmer_engine_object_file::ObjectFile; /// this can be a wasmer-specific type with wasmer-specific functions for manipulating it #[repr(C)] diff --git a/lib/engine-object-file/src/artifact.rs b/lib/engine-object-file/src/artifact.rs index a23b35c6b..97552e384 100644 --- a/lib/engine-object-file/src/artifact.rs +++ b/lib/engine-object-file/src/artifact.rs @@ -420,8 +420,6 @@ impl ObjectFileArtifact { len: usize, } - dbg!(num_finished_functions); - let mut engine_inner = engine.inner_mut(); let signature_registry = engine_inner.signatures(); let mut sig_map: BTreeMap = BTreeMap::new(); @@ -465,7 +463,6 @@ impl ObjectFileArtifact { } cur_offset += WORD_SIZE; let num_function_trampolines = usize::from_ne_bytes(byte_buffer); - dbg!(&num_function_trampolines); for i in 0..num_function_trampolines { for j in 0..WORD_SIZE { byte_buffer[j] = bytes[cur_offset + j]; @@ -492,7 +489,6 @@ impl ObjectFileArtifact { } cur_offset += WORD_SIZE; let num_dynamic_trampoline_functions = usize::from_ne_bytes(byte_buffer); - dbg!(&num_dynamic_trampoline_functions); for _i in 0..num_dynamic_trampoline_functions { let mut sp = SlicePtr { ptr: 0, len: 0 }; for j in 0..WORD_SIZE { From eedbc0f0afdf9b2913a05c844379d81c31df5b64 Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Fri, 28 Aug 2020 16:27:59 -0700 Subject: [PATCH 004/281] Clean up header file generation logic --- lib/engine-object-file/src/artifact.rs | 136 +++++++++++---- lib/engine-object-file/src/header.rs | 233 +++++++++++++++++++++++++ lib/engine-object-file/src/lib.rs | 1 + 3 files changed, 334 insertions(+), 36 deletions(-) create mode 100644 lib/engine-object-file/src/header.rs diff --git a/lib/engine-object-file/src/artifact.rs b/lib/engine-object-file/src/artifact.rs index 97552e384..c6ca42f53 100644 --- a/lib/engine-object-file/src/artifact.rs +++ b/lib/engine-object-file/src/artifact.rs @@ -239,65 +239,113 @@ impl ObjectFileArtifact { /// Generate the header file that goes with the generated object file. pub fn generate_header_file(&self) -> String { - let mut out = String::new(); - use std::fmt::Write; - // TODO: double check this length (it's probably off by 10 or so) - write!( - &mut out, - "const int module_bytes_len = {};\n", - self.metadata_length - ) - .unwrap(); - write!(&mut out, "extern const char WASMER_METADATA[];\n\n").unwrap(); + use crate::header::*; + let mut c_statements = vec![]; + c_statements.push(CStatement::Declaration { + name: "module_bytes_len".to_string(), + array: false, + is_extern: false, + is_const: true, + ctype: CType::U32, + definition: Some(Box::new(CStatement::LiteralConstant { + value: format!("{}", self.metadata_length), + })), + }); + c_statements.push(CStatement::Declaration { + name: "WASMER_METADATA".to_string(), + array: true, + is_extern: true, + is_const: true, + ctype: CType::U8, + definition: None, + }); for (function_local_index, _function_len) in self.metadata.function_body_lengths.iter() { let function_name = self .metadata .symbol_to_name(Symbol::LocalFunction(function_local_index)); // TODO: figure out the signtaure here too - write!(&mut out, "void {}(void);\n", function_name).unwrap(); + c_statements.push(CStatement::Declaration { + name: function_name.clone(), + array: false, + is_extern: false, + is_const: false, + ctype: CType::Function { + arguments: vec![CType::Void], + return_value: None, + }, + definition: None, + }); } // function pointer array { - write!(&mut out, "const void* function_pointers[] = {{\n").unwrap(); + let mut function_pointer_array_statements = vec![]; for (function_local_index, _function_len) in self.metadata.function_body_lengths.iter() { let function_name = self .metadata .symbol_to_name(Symbol::LocalFunction(function_local_index)); // TODO: figure out the signtaure here too - write!(&mut out, "\t{},\n", function_name).unwrap(); - //write!(&mut out, "\t{},\n", function_len).unwrap(); - } - write!(&mut out, "}};\n").unwrap(); - } - write!(&mut out, "\n").unwrap(); + function_pointer_array_statements.push(CStatement::LiteralConstant { + value: function_name.clone(), + }); + } + + c_statements.push(CStatement::Declaration { + name: "function_pointers".to_string(), + array: true, + is_extern: false, + is_const: true, + ctype: CType::void_ptr(), + definition: Some(Box::new(CStatement::LiteralArray { + items: function_pointer_array_statements, + })), + }); + } for (sig_index, _func_type) in self.metadata.compile_info.module.signatures.iter() { let function_name = self .metadata .symbol_to_name(Symbol::FunctionCallTrampoline(sig_index)); - write!(&mut out, "void {}(void*, void*, void*);\n", function_name).unwrap(); + c_statements.push(CStatement::Declaration { + name: function_name.clone(), + array: false, + is_extern: false, + is_const: false, + ctype: CType::Function { + arguments: vec![CType::void_ptr(), CType::void_ptr(), CType::void_ptr()], + return_value: None, + }, + definition: None, + }); } - write!(&mut out, "\n").unwrap(); - // function trampolines { - write!(&mut out, "const void* function_trampolines[] = {{\n").unwrap(); + let mut function_trampoline_statements = vec![]; for (sig_index, _vm_shared_index) in self.metadata.compile_info.module.signatures.iter() { let function_name = self .metadata .symbol_to_name(Symbol::FunctionCallTrampoline(sig_index)); - write!(&mut out, "\t{},\n", function_name).unwrap(); + function_trampoline_statements.push(CStatement::LiteralConstant { + value: function_name, + }); } - write!(&mut out, "}};\n").unwrap(); - } - write!(&mut out, "\n").unwrap(); + c_statements.push(CStatement::Declaration { + name: "function_trampolines".to_string(), + array: true, + is_extern: false, + is_const: true, + ctype: CType::void_ptr(), + definition: Some(Box::new(CStatement::LiteralArray { + items: function_trampoline_statements, + })), + }); + } for func_index in self .metadata @@ -311,16 +359,22 @@ impl ObjectFileArtifact { .metadata .symbol_to_name(Symbol::DynamicFunctionTrampoline(func_index)); // TODO: figure out the signature here - write!(&mut out, "void {}(void*, void*, void*);\n", function_name).unwrap(); + c_statements.push(CStatement::Declaration { + name: function_name, + array: false, + is_extern: false, + is_const: false, + ctype: CType::Function { + arguments: vec![CType::void_ptr(), CType::void_ptr(), CType::void_ptr()], + return_value: None, + }, + definition: None, + }); } // dynamic function trampoline pointer array { - write!( - &mut out, - "const void* dynamic_function_trampoline_pointers[] = {{\n" - ) - .unwrap(); + let mut dynamic_function_trampoline_statements = vec![]; for func_index in self .metadata .compile_info @@ -332,13 +386,23 @@ impl ObjectFileArtifact { let function_name = self .metadata .symbol_to_name(Symbol::DynamicFunctionTrampoline(func_index)); - // TODO: figure out the signature here - write!(&mut out, "\t{},\n", function_name).unwrap(); + dynamic_function_trampoline_statements.push(CStatement::LiteralConstant { + value: function_name, + }); } - write!(&mut out, "}};\n").unwrap(); + c_statements.push(CStatement::Declaration { + name: "dynamic_function_trampoline_pointers".to_string(), + array: true, + is_extern: false, + is_const: true, + ctype: CType::void_ptr(), + definition: Some(Box::new(CStatement::LiteralArray { + items: dynamic_function_trampoline_statements, + })), + }); } - out + generate_c(&c_statements) } /// Get the default extension when serializing this artifact diff --git a/lib/engine-object-file/src/header.rs b/lib/engine-object-file/src/header.rs new file mode 100644 index 000000000..13de25f73 --- /dev/null +++ b/lib/engine-object-file/src/header.rs @@ -0,0 +1,233 @@ +#[derive(Debug, Clone)] +pub enum CType { + Void, + PointerTo { + is_const: bool, + inner: Box, + }, + U8, + U16, + U32, + U64, + USize, + I8, + I16, + I32, + I64, + ISize, + Function { + arguments: Vec, + return_value: Option>, + }, +} + +impl CType { + pub fn void_ptr() -> Self { + CType::PointerTo { + is_const: false, + inner: Box::new(CType::Void), + } + } + + pub fn const_void_ptr() -> Self { + CType::PointerTo { + is_const: false, + inner: Box::new(CType::Void), + } + } + + fn generate_c(&self, w: &mut String) { + match &self { + Self::Void => { + w.push_str("void"); + } + Self::PointerTo { is_const, inner } => { + if *is_const { + w.push_str("const "); + } + inner.generate_c(w); + w.push_str("*"); + } + Self::U8 => { + w.push_str("unsigned char"); + } + Self::U16 => { + w.push_str("unsigned short"); + } + Self::U32 => { + w.push_str("unsigned int"); + } + Self::U64 => { + w.push_str("unsigned long long"); + } + Self::USize => { + w.push_str("unsigned size_t"); + } + Self::I8 => { + w.push_str("char"); + } + Self::I16 => { + w.push_str("short"); + } + Self::I32 => { + w.push_str("int"); + } + Self::I64 => { + w.push_str("long long"); + } + Self::ISize => { + w.push_str("size_t"); + } + Self::Function { + arguments, + return_value, + } => { + // function with no, name, assume it's a function pointer + let ret: CType = return_value + .as_ref() + .map(|i: &Box| (&**i).clone()) + .unwrap_or_default(); + ret.generate_c(w); + w.push(' '); + w.push_str("(*)"); + w.push('('); + if arguments.len() > 1 { + for arg in &arguments[..arguments.len() - 1] { + arg.generate_c(w); + w.push_str(", "); + } + arguments.last().unwrap().generate_c(w); + } else if arguments.len() == 1 { + arguments[0].generate_c(w); + } + w.push(')'); + } + } + } + + fn generate_c_with_name(&self, name: &String, w: &mut String) { + match &self { + Self::PointerTo { .. } + | Self::Void + | Self::U8 + | Self::U16 + | Self::U32 + | Self::U64 + | Self::USize + | Self::I8 + | Self::I16 + | Self::I32 + | Self::I64 + | Self::ISize => { + self.generate_c(w); + w.push(' '); + w.push_str(name); + } + Self::Function { + arguments, + return_value, + } => { + let ret: CType = return_value + .as_ref() + .map(|i: &Box| (&**i).clone()) + .unwrap_or_default(); + ret.generate_c(w); + w.push(' '); + w.push_str(&name); + w.push('('); + if arguments.len() > 1 { + for arg in &arguments[..arguments.len() - 1] { + arg.generate_c(w); + w.push_str(", "); + } + arguments.last().unwrap().generate_c(w); + } else if arguments.len() == 1 { + arguments[0].generate_c(w); + } + w.push(')'); + } + } + } +} + +impl Default for CType { + fn default() -> CType { + CType::Void + } +} + +#[derive(Debug, Clone)] +pub enum CStatement { + Declaration { + name: String, + array: bool, + is_extern: bool, + is_const: bool, + ctype: CType, + definition: Option>, + }, + LiteralArray { + items: Vec, + }, + LiteralConstant { + value: String, + }, +} + +impl CStatement { + fn generate_c(&self, w: &mut String) { + match &self { + Self::Declaration { + name, + array, + is_extern, + is_const, + ctype, + definition, + } => { + if *is_const { + w.push_str("const "); + } + if *is_extern { + w.push_str("extern "); + } + ctype.generate_c_with_name(name, w); + // TODO: array should be part of the type + if *array { + w.push_str("[]"); + } + if let Some(def) = definition { + w.push_str(" = "); + def.generate_c(w); + } + w.push(';'); + w.push('\n'); + } + Self::LiteralArray { items } => { + w.push('{'); + if !items.is_empty() { + w.push('\n'); + } + for item in items { + w.push('\t'); + item.generate_c(w); + w.push(','); + w.push('\n'); + } + w.push('}'); + } + Self::LiteralConstant { value } => { + w.push_str(&value); + } + } + } +} + +// TODO: add config section +pub fn generate_c(statements: &[CStatement]) -> String { + let mut out = String::new(); + for statement in statements { + statement.generate_c(&mut out); + } + out +} diff --git a/lib/engine-object-file/src/lib.rs b/lib/engine-object-file/src/lib.rs index e3f607811..f8b5ee86e 100644 --- a/lib/engine-object-file/src/lib.rs +++ b/lib/engine-object-file/src/lib.rs @@ -24,6 +24,7 @@ mod artifact; mod builder; mod engine; +pub(crate) mod header; mod serialize; pub use crate::artifact::ObjectFileArtifact; From e123b4c889ae278e964a1857b981dfc83ecfe2b0 Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Tue, 1 Sep 2020 12:10:09 -0700 Subject: [PATCH 005/281] Clean up changes to Compiler and compiler-llvm for object file engine --- lib/compiler-llvm/src/compiler.rs | 147 ----------------------- lib/compiler-llvm/src/trampoline/wasm.rs | 12 +- lib/compiler-llvm/src/translator/code.rs | 2 +- lib/compiler/src/compiler.rs | 18 --- lib/engine-object-file/src/artifact.rs | 2 +- lib/engine-object-file/src/header.rs | 1 + 6 files changed, 9 insertions(+), 173 deletions(-) diff --git a/lib/compiler-llvm/src/compiler.rs b/lib/compiler-llvm/src/compiler.rs index 07963de39..24f401bbc 100644 --- a/lib/compiler-llvm/src/compiler.rs +++ b/lib/compiler-llvm/src/compiler.rs @@ -197,132 +197,6 @@ impl LLVMCompiler { Ok(memory_buffer.as_slice().to_vec()) } - - fn compile_to_object_file<'data, 'module>( - &self, - target: &Target, - compile_info: &'module CompileModuleInfo, - module_translation: &ModuleTranslationState, - function_body_inputs: &PrimaryMap>, - symbol_registry: &dyn SymbolRegistry, - wasmer_metadata: &[u8], - ) -> Result, CompileError> { - let target_machine = self.config().target_machine(target); - let ctx = Context::create(); - let merged_module = ctx.create_module(""); - - // TODO: make these steps run in parallel instead of in three phases - // with a serial step in between them. - - function_body_inputs - .into_iter() - .collect::>() - .par_iter() - .map_init( - || { - let target_machine = self.config().target_machine(target); - FuncTranslator::new(target_machine) - }, - |func_translator, (i, input)| { - let module = func_translator.translate_to_module( - &compile_info.module, - module_translation, - i, - input, - self.config(), - &compile_info.memory_styles, - &compile_info.table_styles, - symbol_registry, - )?; - Ok(module.write_bitcode_to_memory().as_slice().to_vec()) - }, - ) - .collect::, CompileError>>()? - .into_iter() - .for_each(|bc| { - let membuf = MemoryBuffer::create_from_memory_range(&bc, ""); - let m = Module::parse_bitcode_from_buffer(&membuf, &ctx).unwrap(); - merged_module.link_in_module(m).unwrap(); - }); - - compile_info - .module - .signatures - .into_iter() - .collect::>() - .par_iter() - .map_init( - || { - let target_machine = self.config().target_machine(target); - FuncTrampoline::new(target_machine) - }, - |func_trampoline, (i, sig)| { - let name = symbol_registry.symbol_to_name(Symbol::FunctionCallTrampoline(*i)); - let module = func_trampoline.trampoline_to_module(sig, self.config(), &name)?; - Ok(module.write_bitcode_to_memory().as_slice().to_vec()) - }, - ) - .collect::, CompileError>>()? - .into_iter() - .for_each(|bc| { - let membuf = MemoryBuffer::create_from_memory_range(&bc, ""); - let m = Module::parse_bitcode_from_buffer(&membuf, &ctx).unwrap(); - merged_module.link_in_module(m).unwrap(); - }); - - compile_info - .module - .functions - .into_iter() - .collect::>() - .par_iter() - .map_init( - || { - let target_machine = self.config().target_machine(target); - ( - FuncTrampoline::new(target_machine), - &compile_info.module.signatures, - ) - }, - |(func_trampoline, signatures), (i, sig)| { - let sig = &signatures[**sig]; - let name = - symbol_registry.symbol_to_name(Symbol::DynamicFunctionTrampoline(*i)); - let module = - func_trampoline.dynamic_trampoline_to_module(sig, self.config(), &name)?; - Ok(module.write_bitcode_to_memory().as_slice().to_vec()) - }, - ) - .collect::, CompileError>>()? - .into_iter() - .for_each(|bc| { - let membuf = MemoryBuffer::create_from_memory_range(&bc, ""); - let m = Module::parse_bitcode_from_buffer(&membuf, &ctx).unwrap(); - merged_module.link_in_module(m).unwrap(); - }); - - let i8_ty = ctx.i8_type(); - let metadata_init = i8_ty.const_array( - wasmer_metadata - .iter() - .map(|v| i8_ty.const_int(*v as u64, false)) - .collect::>() - .as_slice(), - ); - let metadata_gv = - merged_module.add_global(metadata_init.get_type(), None, "WASMER_METADATA"); - metadata_gv.set_initializer(&metadata_init); - - if self.config().enable_verifier { - merged_module.verify().unwrap(); - } - - let memory_buffer = target_machine - .write_to_memory_buffer(&merged_module, FileType::Object) - .unwrap(); - - Ok(memory_buffer.as_slice().to_vec()) - } } impl Compiler for LLVMCompiler { @@ -347,27 +221,6 @@ impl Compiler for LLVMCompiler { )) } - fn experimental_object_file_compile_module<'data, 'module>( - &self, - target: &Target, - module: &'module CompileModuleInfo, - module_translation: &ModuleTranslationState, - // The list of function bodies - function_body_inputs: &PrimaryMap>, - symbol_registry: &dyn SymbolRegistry, - // The metadata to inject into the wasmer_metadata section of the object file. - wasmer_metadata: &[u8], - ) -> Option, CompileError>> { - Some(self.compile_to_object_file( - target, - module, - module_translation, - function_body_inputs, - symbol_registry, - wasmer_metadata, - )) - } - /// Compile the module using LLVM, producing a compilation result with /// associated relocations. fn compile_module<'data, 'module>( diff --git a/lib/compiler-llvm/src/trampoline/wasm.rs b/lib/compiler-llvm/src/trampoline/wasm.rs index ccbf0fcbd..a954919df 100644 --- a/lib/compiler-llvm/src/trampoline/wasm.rs +++ b/lib/compiler-llvm/src/trampoline/wasm.rs @@ -63,9 +63,9 @@ impl FuncTrampoline { ); let trampoline_func = module.add_function(name, trampoline_ty, Some(Linkage::External)); - /*trampoline_func - .as_global_value() - .set_section(FUNCTION_SECTION);*/ + trampoline_func + .as_global_value() + .set_section(FUNCTION_SECTION); generate_trampoline(trampoline_func, ty, &callee_attrs, &self.ctx, &intrinsics)?; if let Some(ref callbacks) = config.callbacks { @@ -179,9 +179,9 @@ impl FuncTrampoline { for (attr, attr_loc) in trampoline_attrs { trampoline_func.add_attribute(attr_loc, attr); } - /*trampoline_func - .as_global_value() - .set_section(FUNCTION_SECTION);*/ + trampoline_func + .as_global_value() + .set_section(FUNCTION_SECTION); generate_dynamic_trampoline(trampoline_func, ty, &self.ctx, &intrinsics)?; if let Some(ref callbacks) = config.callbacks { diff --git a/lib/compiler-llvm/src/translator/code.rs b/lib/compiler-llvm/src/translator/code.rs index d419a3aed..836bb7864 100644 --- a/lib/compiler-llvm/src/translator/code.rs +++ b/lib/compiler-llvm/src/translator/code.rs @@ -111,7 +111,7 @@ impl FuncTranslator { // TODO: mark vmctx nofree func.add_attribute(AttributeLoc::Function, intrinsics.stack_probe); func.set_personality_function(intrinsics.personality); - //func.as_global_value().set_section(FUNCTION_SECTION); + func.as_global_value().set_section(FUNCTION_SECTION); let entry = self.ctx.append_basic_block(func, "entry"); let start_of_code = self.ctx.append_basic_block(func, "start_of_code"); diff --git a/lib/compiler/src/compiler.rs b/lib/compiler/src/compiler.rs index cbfa0220e..75b3b0811 100644 --- a/lib/compiler/src/compiler.rs +++ b/lib/compiler/src/compiler.rs @@ -99,24 +99,6 @@ pub trait Compiler { ) -> Option, CompileError>> { None } - - /// Compiles a module into an object file that can be built with libwasmer - /// into a stand-alone executable. - /// - /// It returns the bytes as a `&[u8]` or a [`CompileError`]. - fn experimental_object_file_compile_module<'data, 'module>( - &self, - _target: &Target, - _module: &'module CompileModuleInfo, - _module_translation: &ModuleTranslationState, - // The list of function bodies - _function_body_inputs: &PrimaryMap>, - _symbol_registry: &dyn SymbolRegistry, - // The metadata to inject into the wasmer_metadata section of the object file. - _wasmer_metadata: &[u8], - ) -> Option, CompileError>> { - None - } } /// The kinds of wasmer_types objects that might be found in a native object file. diff --git a/lib/engine-object-file/src/artifact.rs b/lib/engine-object-file/src/artifact.rs index c6ca42f53..77c9ed1e2 100644 --- a/lib/engine-object-file/src/artifact.rs +++ b/lib/engine-object-file/src/artifact.rs @@ -205,7 +205,7 @@ impl ObjectFileArtifact { metadata_binary.extend(serialized_data); let metadata_length = metadata_binary.len(); - let maybe_obj_bytes = compiler.experimental_object_file_compile_module( + let maybe_obj_bytes = compiler.experimental_native_compile_module( &target, &metadata.compile_info, module_translation.as_ref().unwrap(), diff --git a/lib/engine-object-file/src/header.rs b/lib/engine-object-file/src/header.rs index 13de25f73..ad5ee20c1 100644 --- a/lib/engine-object-file/src/header.rs +++ b/lib/engine-object-file/src/header.rs @@ -29,6 +29,7 @@ impl CType { } } + #[allow(dead_code)] pub fn const_void_ptr() -> Self { CType::PointerTo { is_const: false, From fdfdeeb94a9c6b157cc7b03a0a2981e446c6578f Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Tue, 1 Sep 2020 14:25:45 -0700 Subject: [PATCH 006/281] Improve some of the UX of the compile command, add docs --- lib/cli/src/commands/compile.rs | 32 ++++- lib/engine-object-file/Cargo.toml | 2 +- lib/engine-object-file/README.md | 186 ++++++++++++++++++++++++++++++ 3 files changed, 213 insertions(+), 7 deletions(-) create mode 100644 lib/engine-object-file/README.md diff --git a/lib/cli/src/commands/compile.rs b/lib/cli/src/commands/compile.rs index 1748bcfc1..a353956d2 100644 --- a/lib/cli/src/commands/compile.rs +++ b/lib/cli/src/commands/compile.rs @@ -13,9 +13,13 @@ pub struct Compile { path: PathBuf, /// Output file - #[structopt(name = "OUTPUT", short = "o", parse(from_os_str))] + #[structopt(name = "OUTPUT PATH", short = "o", parse(from_os_str))] output: PathBuf, + /// Output path for generated header filefile + #[structopt(name = "HEADER PATH", long = "header", parse(from_os_str))] + header_path: Option, + /// Compilation Target triple #[structopt(long = "target")] target_triple: Option, @@ -94,23 +98,39 @@ impl Compile { println!("Target: {}", target.triple()); let module = Module::from_file(&store, &self.path)?; let _ = module.serialize_to_file(&self.output)?; + eprintln!( + "✔ File compiled successfully to `{}`.", + self.output.display(), + ); #[cfg(feature = "object-file")] if let Some(header_file_src) = module.artifact().create_header_file() { + let header_path = self.header_path.as_ref().cloned().unwrap_or_else(|| { + let mut hp = PathBuf::from( + self.path + .file_stem() + .map(|fs| fs.to_string_lossy().to_string()) + .unwrap_or_else(|| "wasm_out".to_string()), + ); + hp.set_extension("h"); + hp + }); // for C code let mut header = std::fs::OpenOptions::new() .create(true) .truncate(true) .write(true) - .open("test.h")?; + .open(&header_path)?; use std::io::Write; header.write(header_file_src.as_bytes())?; + eprintln!( + "✔ Header file generated successfully at `{}`.", + header_path.display(), + ); + // end c gen } - eprintln!( - "✔ File compiled successfully to `{}`.", - self.output.display(), - ); + Ok(()) } } diff --git a/lib/engine-object-file/Cargo.toml b/lib/engine-object-file/Cargo.toml index 34a812068..4a02fdd03 100644 --- a/lib/engine-object-file/Cargo.toml +++ b/lib/engine-object-file/Cargo.toml @@ -7,7 +7,7 @@ categories = ["wasm"] keywords = ["webassembly", "wasm"] repository = "https://github.com/wasmerio/wasmer" # TODO: make a readme explaining what this crate is -# readme = "README.md" +readme = "README.md" edition = "2018" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/lib/engine-object-file/README.md b/lib/engine-object-file/README.md new file mode 100644 index 000000000..8aefd4a02 --- /dev/null +++ b/lib/engine-object-file/README.md @@ -0,0 +1,186 @@ +# Wasmer Engine Object File + +This is an [engine](https://crates.io/crates/wasmer-engine) for the [wasmer](https://crates.io/crates/wasmer/1.0.0-alpha01.0) WebAssembly VM. + +This engine is used to produce native code that can be linked against providing +a sandboxed WebAssembly runtime environment for the compiled module with no need +for runtime compilation. + +## Example of use + +First we compile our WebAssembly file with Wasmer +```sh +wasmer compile path/to/wasm/file.wasm --llvm --object-file -o my_wasm.o --header my_wasm.h +``` + +You will then see output like: +``` +Engine: objectfile +Compiler: llvm +Target: x86_64-apple-darwin +✔ File compiled successfully to `my_wasm.o`. +✔ Header file generated successfully at `my_wasm.h`. +``` + +Now lets create a program to link with this object file. + +```C +#include "wasmer_wasm.h" +#include "wasm.h" +#include "my_wasm.h" + +#include +#include + +void wasmer_function__1(void); +void wasmer_trampoline_function_call__1(void*, void*, void*); + +// todo: add to wasmer_wasm.h or something +void* wasm_instance_get_vmctx_ptr(wasm_instance_t*); + +// a bit of a hack; TODO: clean this up +typedef struct my_byte_vec_t { + size_t size; + char* data; +} my_byte_vec_t; + + +void print_wasmer_error() +{ + int error_len = wasmer_last_error_length(); + printf("Error len: `%d`\n", error_len); + char *error_str = malloc(error_len); + wasmer_last_error_message(error_str, error_len); + printf("Error str: `%s`\n", error_str); +} + + +int main() { + printf("Initializing...\n"); + wasm_engine_t* engine = wasm_engine_new(); + wasm_store_t* store = wasm_store_new(engine); + + char* byte_ptr = (char*)&WASMER_METADATA[0]; + + // We need to pass all the bytes as one big buffer so we have to do all this logic to memcpy + // the various pieces together from the generated header file. + // + // We should provide a `deseralize_vectored` function to avoid requiring this extra work. + + size_t num_function_pointers + = sizeof(function_pointers) / sizeof(void*); + size_t num_function_trampolines + = sizeof(function_trampolines) / sizeof(void*); + size_t num_dynamic_function_trampoline_pointers + = sizeof(dynamic_function_trampoline_pointers) / sizeof(void*); + + + size_t buffer_size = module_bytes_len + + sizeof(size_t) + sizeof(function_pointers) + + sizeof(size_t) + sizeof(function_trampolines) + + sizeof(size_t) + sizeof(dynamic_function_trampoline_pointers); + + char* memory_buffer = (char*) malloc(buffer_size); + size_t current_offset = 0; + printf("Buffer size: %d\n", buffer_size); + + memcpy(memory_buffer + current_offset, byte_ptr, module_bytes_len); + current_offset += module_bytes_len; + + memcpy(memory_buffer + current_offset, (void*)&num_function_pointers, sizeof(size_t)); + current_offset += sizeof(size_t); + + memcpy(memory_buffer + current_offset, (void*)&function_pointers[0], sizeof(function_pointers)); + current_offset += sizeof(function_pointers); + + memcpy(memory_buffer + current_offset, (void*)&num_function_trampolines, sizeof(size_t)); + current_offset += sizeof(size_t); + + memcpy(memory_buffer + current_offset, (void*)&function_trampolines[0], sizeof(function_trampolines)); + current_offset += sizeof(function_trampolines); + + memcpy(memory_buffer + current_offset, (void*)&num_dynamic_function_trampoline_pointers, sizeof(size_t)); + current_offset += sizeof(size_t); + + memcpy(memory_buffer + current_offset, (void*)&dynamic_function_trampoline_pointers[0], sizeof(dynamic_function_trampoline_pointers)); + current_offset += sizeof(dynamic_function_trampoline_pointers); + + my_byte_vec_t module_byte_vec = { + .size = buffer_size, + .data = memory_buffer, + }; + + wasm_module_t* module = wasm_module_deserialize(store, (wasm_byte_vec_t*) &module_byte_vec); + if (! module) { + printf("Failed to create module\n"); + print_wasmer_error(); + return -1; + } + free(memory_buffer); + + // We have now finished the memory buffer book keeping and we have a valid Module. + + // In this example we're passing some JavaScript source code as a command line argumnet + // to a WASI module that can evaluate JavaScript. + wasi_config_t* config = wasi_config_new("constant_value_here"); + const char* js_string = "function greet(name) { return JSON.stringify('Hello, ' + name); }; print(greet('World'));"; + wasi_config_arg(config, "--eval"); + wasi_config_arg(config, js_string); + wasi_env_t* wasi_env = wasi_env_new(config); + if (!wasi_env) { + printf("> Error building WASI env!\n"); + print_wasmer_error(); + return 1; + } + + wasm_importtype_vec_t import_types; + wasm_module_imports(module, &import_types); + int num_imports = import_types.size; + wasm_extern_t** imports = malloc(num_imports * sizeof(wasm_extern_t*)); + wasm_importtype_vec_delete(&import_types); + + bool get_imports_result = wasi_get_imports(store, module, wasi_env, imports); + if (!get_imports_result) { + printf("> Error getting WASI imports!\n"); + print_wasmer_error(); + return 1; + } + + wasm_instance_t* instance = wasm_instance_new(store, module, (const wasm_extern_t* const*) imports, NULL); + if (! instance) { + printf("Failed to create instance\n"); + print_wasmer_error(); + return -1; + } + wasi_env_set_instance(wasi_env, instance); + + // WASI is now set up. + + void* vmctx = wasm_instance_get_vmctx_ptr(instance); + wasm_val_t* inout[2] = { NULL, NULL }; + + // We're able to call our compiled functions directly through their trampolines. + wasmer_trampoline_function_call__1(vmctx, wasmer_function__1, &inout); + + wasm_instance_delete(instance); + wasm_module_delete(module); + wasm_store_delete(store); + wasm_engine_delete(engine); + return 0; +} +``` + +We save that source code into `test.c` and run: + +```sh +gcc -O2 -c test.c -o test.o +``` + +Now we just need to link everything together: + +```sh +g++ -O2 test.o my_wasm.o libwasmer.a +``` + +We link the object file we created with our C code, the object file we generated with Wasmer, +and libwasmer together and produce an executable that can call into our compiled WebAssembly! From 3f109bf5c7168d10290f2718b2f2c0d457cc20a0 Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Wed, 2 Sep 2020 15:58:51 -0700 Subject: [PATCH 007/281] Add downcast method to `Artifact` remove `create_header` method --- Cargo.lock | 2 +- lib/cli/src/commands/compile.rs | 59 ++++++++++++++------------ lib/cli/src/store.rs | 2 +- lib/engine-object-file/src/artifact.rs | 8 +--- lib/engine/src/artifact.rs | 44 ++++++++++++++++--- 5 files changed, 75 insertions(+), 40 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 921128ed4..d57b83d61 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2395,7 +2395,7 @@ dependencies = [ "bincode", "cfg-if", "leb128", - "libloading 0.6.2", + "libloading 0.6.3", "serde", "tempfile", "tracing", diff --git a/lib/cli/src/commands/compile.rs b/lib/cli/src/commands/compile.rs index a353956d2..a407eebf2 100644 --- a/lib/cli/src/commands/compile.rs +++ b/lib/cli/src/commands/compile.rs @@ -96,41 +96,48 @@ impl Compile { println!("Engine: {}", engine_type.to_string()); println!("Compiler: {}", compiler_type.to_string()); println!("Target: {}", target.triple()); + let module = Module::from_file(&store, &self.path)?; let _ = module.serialize_to_file(&self.output)?; eprintln!( "✔ File compiled successfully to `{}`.", self.output.display(), ); + #[cfg(feature = "object-file")] - if let Some(header_file_src) = module.artifact().create_header_file() { - let header_path = self.header_path.as_ref().cloned().unwrap_or_else(|| { - let mut hp = PathBuf::from( - self.path - .file_stem() - .map(|fs| fs.to_string_lossy().to_string()) - .unwrap_or_else(|| "wasm_out".to_string()), + if engine_type == EngineType::ObjectFile { + use wasmer_engine_object_file::ObjectFileArtifact; + + if let Some(obj_file) = module.artifact().downcast_ref::() { + let header_file_src = obj_file.generate_header_file(); + let header_path = self.header_path.as_ref().cloned().unwrap_or_else(|| { + let mut hp = PathBuf::from( + self.path + .file_stem() + .map(|fs| fs.to_string_lossy().to_string()) + .unwrap_or_else(|| "wasm_out".to_string()), + ); + hp.set_extension("h"); + hp + }); + // for C code + let mut header = std::fs::OpenOptions::new() + .create(true) + .truncate(true) + .write(true) + .open(&header_path)?; + + use std::io::Write; + header.write(header_file_src.as_bytes())?; + eprintln!( + "✔ Header file generated successfully at `{}`.", + header_path.display(), ); - hp.set_extension("h"); - hp - }); - // for C code - let mut header = std::fs::OpenOptions::new() - .create(true) - .truncate(true) - .write(true) - .open(&header_path)?; - - use std::io::Write; - header.write(header_file_src.as_bytes())?; - eprintln!( - "✔ Header file generated successfully at `{}`.", - header_path.display(), - ); - - // end c gen + } else { + // TODO: handle error + panic!("Downcast failed!") + } } - Ok(()) } } diff --git a/lib/cli/src/store.rs b/lib/cli/src/store.rs index ac225c11c..795fcf792 100644 --- a/lib/cli/src/store.rs +++ b/lib/cli/src/store.rs @@ -183,7 +183,7 @@ impl StoreOptions { /// Get the Compiler Config for the current options #[allow(unused_variables)] - fn get_compiler_config(&self) -> Result<(Box, CompilerType)> { + pub(crate) fn get_compiler_config(&self) -> Result<(Box, CompilerType)> { let compiler = self.get_compiler()?; let compiler_config: Box = match compiler { CompilerType::Headless => bail!("The headless engine can't be chosen"), diff --git a/lib/engine-object-file/src/artifact.rs b/lib/engine-object-file/src/artifact.rs index 77c9ed1e2..f78d67e0f 100644 --- a/lib/engine-object-file/src/artifact.rs +++ b/lib/engine-object-file/src/artifact.rs @@ -263,7 +263,7 @@ impl ObjectFileArtifact { let function_name = self .metadata .symbol_to_name(Symbol::LocalFunction(function_local_index)); - // TODO: figure out the signtaure here too + // TODO: figure out the signature here too c_statements.push(CStatement::Declaration { name: function_name.clone(), array: false, @@ -285,7 +285,7 @@ impl ObjectFileArtifact { let function_name = self .metadata .symbol_to_name(Symbol::LocalFunction(function_local_index)); - // TODO: figure out the signtaure here too + // TODO: figure out the signature here too function_pointer_array_statements.push(CStatement::LiteralConstant { value: function_name.clone(), @@ -631,10 +631,6 @@ impl Artifact for ObjectFileArtifact { &self.signatures } - fn create_header_file(&self) -> Option { - Some(self.generate_header_file()) - } - fn preinstantiate(&self) -> Result<(), InstantiationError> { //todo!("figure out what preinstantiate means here"); Ok(()) diff --git a/lib/engine/src/artifact.rs b/lib/engine/src/artifact.rs index cc7ef812f..b7fef4c3b 100644 --- a/lib/engine/src/artifact.rs +++ b/lib/engine/src/artifact.rs @@ -21,7 +21,7 @@ use wasmer_vm::{ /// The `Artifact` contains the compiled data for a given /// module as well as extra information needed to run the /// module at runtime, such as [`ModuleInfo`] and [`Features`]. -pub trait Artifact: Send + Sync { +pub trait Artifact: Send + Sync + 'static + Upcastable { /// Return a reference-counted pointer to the module fn module(&self) -> Arc; @@ -71,11 +71,6 @@ pub trait Artifact: Send + Sync { Ok(()) } - /// Create a header file for use with a native object file; - fn create_header_file(&self) -> Option { - None - } - /// Do preinstantiation logic that is executed before instantiating fn preinstantiate(&self) -> Result<(), InstantiationError> { Ok(()) @@ -154,3 +149,40 @@ pub trait Artifact: Send + Sync { .map_err(|trap| InstantiationError::Start(RuntimeError::from_trap(trap))) } } + +// Implementation of `Upcastable` taken from https://users.rust-lang.org/t/why-does-downcasting-not-work-for-subtraits/33286/7 . +/// Trait needed to get downcasting from `Artifact` to work. +pub trait Upcastable { + fn upcast_any_ref(self: &'_ Self) -> &'_ dyn Any; + fn upcast_any_mut(self: &'_ mut Self) -> &'_ mut dyn Any; + fn upcast_any_box(self: Box) -> Box; +} + +impl Upcastable for T { + #[inline] + fn upcast_any_ref(self: &'_ Self) -> &'_ dyn Any { + self + } + #[inline] + fn upcast_any_mut(self: &'_ mut Self) -> &'_ mut dyn Any { + self + } + #[inline] + fn upcast_any_box(self: Box) -> Box { + self + } +} + +impl dyn Artifact + 'static { + /// Downcast a reference to an `Artifact` into a specific implementor. + #[inline] + pub fn downcast_ref(self: &'_ Self) -> Option<&'_ T> { + self.upcast_any_ref().downcast_ref::() + } + + /// Downcast a mutable reference to an `Artifact` into a specific implementor. + #[inline] + pub fn downcast_mut(self: &'_ mut Self) -> Option<&'_ mut T> { + self.upcast_any_mut().downcast_mut::() + } +} From 86e934a7557ef98975f77a9ca5f56b7a53cfd6a1 Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Thu, 3 Sep 2020 17:45:27 -0700 Subject: [PATCH 008/281] Move header file generation logic WIP, still need to get the length of the metadat object, but otherwise everything should be working. --- Cargo.lock | 1 + lib/cli/Cargo.toml | 1 + lib/cli/src/commands/compile.rs | 55 ++- lib/cli/src/header_file_generation/mod.rs | 456 ++++++++++++++++++++++ lib/cli/src/lib.rs | 1 + lib/engine-jit/src/artifact.rs | 6 +- lib/engine-native/src/artifact.rs | 4 + lib/engine-object-file/src/artifact.rs | 172 +------- lib/engine-object-file/src/header.rs | 234 ----------- lib/engine-object-file/src/lib.rs | 1 - lib/engine/src/artifact.rs | 42 +- 11 files changed, 502 insertions(+), 471 deletions(-) create mode 100644 lib/cli/src/header_file_generation/mod.rs delete mode 100644 lib/engine-object-file/src/header.rs diff --git a/Cargo.lock b/Cargo.lock index d57b83d61..9601cfec7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2229,6 +2229,7 @@ dependencies = [ "wasmer-engine-native", "wasmer-engine-object-file", "wasmer-types", + "wasmer-vm", "wasmer-wasi", "wasmer-wasi-experimental-io-devices", "wasmer-wast", diff --git a/lib/cli/Cargo.toml b/lib/cli/Cargo.toml index c2543bae1..dd1eae600 100644 --- a/lib/cli/Cargo.toml +++ b/lib/cli/Cargo.toml @@ -35,6 +35,7 @@ wasmer-engine-object-file = { version = "1.0.0-alpha01.0", path = "../engine-obj wasmer-wasi = { version = "1.0.0-alpha01.0", path = "../wasi", optional = true } wasmer-wasi-experimental-io-devices = { version = "1.0.0-alpha01.0", path = "../wasi-experimental-io-devices", optional = true } wasmer-wast = { version = "1.0.0-alpha01.0", path = "../../tests/lib/wast", optional = true } +wasmer-vm = { version = "1.0.0-alpha01.0", path = "../vm" } wasmer-cache = { version = "1.0.0-alpha01.0", path = "../cache", optional = true } wasmer-types = { version = "1.0.0-alpha01.0", path = "../wasmer-types" } atty = "0.2" diff --git a/lib/cli/src/commands/compile.rs b/lib/cli/src/commands/compile.rs index a407eebf2..6cace1e96 100644 --- a/lib/cli/src/commands/compile.rs +++ b/lib/cli/src/commands/compile.rs @@ -106,37 +106,34 @@ impl Compile { #[cfg(feature = "object-file")] if engine_type == EngineType::ObjectFile { - use wasmer_engine_object_file::ObjectFileArtifact; + let symbol_registry = module.artifact().symbol_registry(); + let module_info = module.info(); + let header_file_src = + crate::header_file_generation::generate_header_file(module_info, symbol_registry); - if let Some(obj_file) = module.artifact().downcast_ref::() { - let header_file_src = obj_file.generate_header_file(); - let header_path = self.header_path.as_ref().cloned().unwrap_or_else(|| { - let mut hp = PathBuf::from( - self.path - .file_stem() - .map(|fs| fs.to_string_lossy().to_string()) - .unwrap_or_else(|| "wasm_out".to_string()), - ); - hp.set_extension("h"); - hp - }); - // for C code - let mut header = std::fs::OpenOptions::new() - .create(true) - .truncate(true) - .write(true) - .open(&header_path)?; - - use std::io::Write; - header.write(header_file_src.as_bytes())?; - eprintln!( - "✔ Header file generated successfully at `{}`.", - header_path.display(), + let header_path = self.header_path.as_ref().cloned().unwrap_or_else(|| { + let mut hp = PathBuf::from( + self.path + .file_stem() + .map(|fs| fs.to_string_lossy().to_string()) + .unwrap_or_else(|| "wasm_out".to_string()), ); - } else { - // TODO: handle error - panic!("Downcast failed!") - } + hp.set_extension("h"); + hp + }); + // for C code + let mut header = std::fs::OpenOptions::new() + .create(true) + .truncate(true) + .write(true) + .open(&header_path)?; + + use std::io::Write; + header.write(header_file_src.as_bytes())?; + eprintln!( + "✔ Header file generated successfully at `{}`.", + header_path.display(), + ); } Ok(()) } diff --git a/lib/cli/src/header_file_generation/mod.rs b/lib/cli/src/header_file_generation/mod.rs new file mode 100644 index 000000000..14870cf70 --- /dev/null +++ b/lib/cli/src/header_file_generation/mod.rs @@ -0,0 +1,456 @@ +//! A convenient little abstraction for building up C expressions and generating +//! simple C code. + +/// A Type in the C language. +#[derive(Debug, Clone)] +pub enum CType { + /// C `void` type. + Void, + /// A pointer to some other type. + PointerTo { + /// Whether the pointer is `const`. + is_const: bool, + /// The type that the pointer points to. + inner: Box, + }, + /// C 8 bit unsigned integer type. + U8, + /// C 16 bit unsigned integer type. + U16, + /// C 32 bit unsigned integer type. + U32, + /// C 64 bit unsigned integer type. + U64, + /// C pointer sized unsigned integer type. + USize, + /// C 8 bit signed integer type. + I8, + /// C 16 bit signed integer type. + I16, + /// C 32 bit signed integer type. + I32, + /// C 64 bit signed integer type. + I64, + /// C pointer sized signed integer type. + ISize, + /// A function or function pointer. + Function { + /// The arguments the function takes. + arguments: Vec, + /// The return value if it has one + /// + /// None is equivalent to Some(Box(Ctype::Void)). + return_value: Option>, + }, +} + +impl CType { + /// Convenience function to get a mutable void pointer type. + pub fn void_ptr() -> Self { + CType::PointerTo { + is_const: false, + inner: Box::new(CType::Void), + } + } + + /// Convenience function to get a const void pointer type. + #[allow(dead_code)] + pub fn const_void_ptr() -> Self { + CType::PointerTo { + is_const: false, + inner: Box::new(CType::Void), + } + } + + /// Generate the C source code for a type into the given `String`. + fn generate_c(&self, w: &mut String) { + match &self { + Self::Void => { + w.push_str("void"); + } + Self::PointerTo { is_const, inner } => { + if *is_const { + w.push_str("const "); + } + inner.generate_c(w); + w.push_str("*"); + } + Self::U8 => { + w.push_str("unsigned char"); + } + Self::U16 => { + w.push_str("unsigned short"); + } + Self::U32 => { + w.push_str("unsigned int"); + } + Self::U64 => { + w.push_str("unsigned long long"); + } + Self::USize => { + w.push_str("unsigned size_t"); + } + Self::I8 => { + w.push_str("char"); + } + Self::I16 => { + w.push_str("short"); + } + Self::I32 => { + w.push_str("int"); + } + Self::I64 => { + w.push_str("long long"); + } + Self::ISize => { + w.push_str("size_t"); + } + Self::Function { + arguments, + return_value, + } => { + // function with no, name, assume it's a function pointer + let ret: CType = return_value + .as_ref() + .map(|i: &Box| (&**i).clone()) + .unwrap_or_default(); + ret.generate_c(w); + w.push(' '); + w.push_str("(*)"); + w.push('('); + if arguments.len() > 1 { + for arg in &arguments[..arguments.len() - 1] { + arg.generate_c(w); + w.push_str(", "); + } + arguments.last().unwrap().generate_c(w); + } else if arguments.len() == 1 { + arguments[0].generate_c(w); + } + w.push(')'); + } + } + } + + /// Generate the C source code for a type with a nameinto the given `String`. + fn generate_c_with_name(&self, name: &String, w: &mut String) { + match &self { + Self::PointerTo { .. } + | Self::Void + | Self::U8 + | Self::U16 + | Self::U32 + | Self::U64 + | Self::USize + | Self::I8 + | Self::I16 + | Self::I32 + | Self::I64 + | Self::ISize => { + self.generate_c(w); + w.push(' '); + w.push_str(name); + } + Self::Function { + arguments, + return_value, + } => { + let ret: CType = return_value + .as_ref() + .map(|i: &Box| (&**i).clone()) + .unwrap_or_default(); + ret.generate_c(w); + w.push(' '); + w.push_str(&name); + w.push('('); + if arguments.len() > 1 { + for arg in &arguments[..arguments.len() - 1] { + arg.generate_c(w); + w.push_str(", "); + } + arguments.last().unwrap().generate_c(w); + } else if arguments.len() == 1 { + arguments[0].generate_c(w); + } + w.push(')'); + } + } + } +} + +impl Default for CType { + fn default() -> CType { + CType::Void + } +} + +/// A statement in the C programming language. This may not be exact to what an +/// AST would look like or what the C standard says about the C language, it's +/// simply a structed way to organize data for generating C code. +#[derive(Debug, Clone)] +pub enum CStatement { + /// A declaration of some kind. + Declaration { + /// The name of the thing being declared. + name: String, + /// Whether the thing being declared is an array. + // TODO: probably make this part of CType + array: bool, + /// Whether the thing being declared is `extern`. + is_extern: bool, + /// Whether the thing being declared is `const`. + is_const: bool, + /// The type of the thing being declared. + ctype: CType, + /// The definition of the thing being declared. + /// + /// This is useful for initializing constant arrays, for example. + definition: Option>, + }, + /// A literal array of CStatements. + LiteralArray { + /// The contents of the array. + items: Vec, + }, + + /// A literal constant value, passed through directly as a string. + LiteralConstant { + /// The raw value acting as a constant. + value: String, + }, +} + +impl CStatement { + /// Generate C source code for the given CStatement. + fn generate_c(&self, w: &mut String) { + match &self { + Self::Declaration { + name, + array, + is_extern, + is_const, + ctype, + definition, + } => { + if *is_const { + w.push_str("const "); + } + if *is_extern { + w.push_str("extern "); + } + ctype.generate_c_with_name(name, w); + // TODO: array should be part of the type + if *array { + w.push_str("[]"); + } + if let Some(def) = definition { + w.push_str(" = "); + def.generate_c(w); + } + w.push(';'); + w.push('\n'); + } + Self::LiteralArray { items } => { + w.push('{'); + if !items.is_empty() { + w.push('\n'); + } + for item in items { + w.push('\t'); + item.generate_c(w); + w.push(','); + w.push('\n'); + } + w.push('}'); + } + Self::LiteralConstant { value } => { + w.push_str(&value); + } + } + } +} + +/// Generate C source code from some `CStatements` into a String. +// TODO: add config section +pub fn generate_c(statements: &[CStatement]) -> String { + let mut out = String::new(); + for statement in statements { + statement.generate_c(&mut out); + } + out +} + +// TODO: split the bottom part into its own file + +use wasmer_compiler::{Symbol, SymbolRegistry}; +use wasmer_vm::ModuleInfo; + +/// Generate the header file that goes with the generated object file. +pub fn generate_header_file( + module_info: &ModuleInfo, + symbol_registry: &dyn SymbolRegistry, +) -> String { + let mut c_statements = vec![]; + c_statements.push(CStatement::Declaration { + name: "module_bytes_len".to_string(), + array: false, + is_extern: false, + is_const: true, + ctype: CType::U32, + definition: Some(Box::new(CStatement::LiteralConstant { + value: "0".to_string(), //todo!("get the metadata length from somewhere"), //format!("{}", self.metadata_length), + })), + }); + c_statements.push(CStatement::Declaration { + name: "WASMER_METADATA".to_string(), + array: true, + is_extern: true, + is_const: true, + ctype: CType::U8, + definition: None, + }); + for (function_local_index, _sig_index) in + module_info + .functions + .iter() + .filter_map(|(f_index, sig_index)| { + Some((module_info.local_func_index(f_index)?, sig_index)) + }) + { + let function_name = + symbol_registry.symbol_to_name(Symbol::LocalFunction(function_local_index)); + // TODO: figure out the signature here too + c_statements.push(CStatement::Declaration { + name: function_name.clone(), + array: false, + is_extern: false, + is_const: false, + ctype: CType::Function { + arguments: vec![CType::Void], + return_value: None, + }, + definition: None, + }); + } + + // function pointer array + { + let mut function_pointer_array_statements = vec![]; + for (function_local_index, _sig_index) in + module_info + .functions + .iter() + .filter_map(|(f_index, sig_index)| { + Some((module_info.local_func_index(f_index)?, sig_index)) + }) + { + let function_name = + symbol_registry.symbol_to_name(Symbol::LocalFunction(function_local_index)); + // TODO: figure out the signature here too + + function_pointer_array_statements.push(CStatement::LiteralConstant { + value: function_name.clone(), + }); + } + + c_statements.push(CStatement::Declaration { + name: "function_pointers".to_string(), + array: true, + is_extern: false, + is_const: true, + ctype: CType::void_ptr(), + definition: Some(Box::new(CStatement::LiteralArray { + items: function_pointer_array_statements, + })), + }); + } + + for (sig_index, _func_type) in module_info.signatures.iter() { + let function_name = + symbol_registry.symbol_to_name(Symbol::FunctionCallTrampoline(sig_index)); + + c_statements.push(CStatement::Declaration { + name: function_name.clone(), + array: false, + is_extern: false, + is_const: false, + ctype: CType::Function { + arguments: vec![CType::void_ptr(), CType::void_ptr(), CType::void_ptr()], + return_value: None, + }, + definition: None, + }); + } + + // function trampolines + { + let mut function_trampoline_statements = vec![]; + for (sig_index, _vm_shared_index) in module_info.signatures.iter() { + let function_name = + symbol_registry.symbol_to_name(Symbol::FunctionCallTrampoline(sig_index)); + function_trampoline_statements.push(CStatement::LiteralConstant { + value: function_name, + }); + } + + c_statements.push(CStatement::Declaration { + name: "function_trampolines".to_string(), + array: true, + is_extern: false, + is_const: true, + ctype: CType::void_ptr(), + definition: Some(Box::new(CStatement::LiteralArray { + items: function_trampoline_statements, + })), + }); + } + + for func_index in module_info + .functions + .keys() + .take(module_info.num_imported_functions) + { + let function_name = + symbol_registry.symbol_to_name(Symbol::DynamicFunctionTrampoline(func_index)); + // TODO: figure out the signature here + c_statements.push(CStatement::Declaration { + name: function_name, + array: false, + is_extern: false, + is_const: false, + ctype: CType::Function { + arguments: vec![CType::void_ptr(), CType::void_ptr(), CType::void_ptr()], + return_value: None, + }, + definition: None, + }); + } + + // dynamic function trampoline pointer array + { + let mut dynamic_function_trampoline_statements = vec![]; + for func_index in module_info + .functions + .keys() + .take(module_info.num_imported_functions) + { + let function_name = + symbol_registry.symbol_to_name(Symbol::DynamicFunctionTrampoline(func_index)); + dynamic_function_trampoline_statements.push(CStatement::LiteralConstant { + value: function_name, + }); + } + c_statements.push(CStatement::Declaration { + name: "dynamic_function_trampoline_pointers".to_string(), + array: true, + is_extern: false, + is_const: true, + ctype: CType::void_ptr(), + definition: Some(Box::new(CStatement::LiteralArray { + items: dynamic_function_trampoline_statements, + })), + }); + } + + generate_c(&c_statements) +} diff --git a/lib/cli/src/lib.rs b/lib/cli/src/lib.rs index ce0d42754..9a08d404a 100644 --- a/lib/cli/src/lib.rs +++ b/lib/cli/src/lib.rs @@ -20,6 +20,7 @@ pub mod commands; pub mod common; #[macro_use] pub mod error; +pub mod header_file_generation; #[cfg(feature = "debug")] pub mod logging; pub mod store; diff --git a/lib/engine-jit/src/artifact.rs b/lib/engine-jit/src/artifact.rs index 767b7f55a..3cfa34ec7 100644 --- a/lib/engine-jit/src/artifact.rs +++ b/lib/engine-jit/src/artifact.rs @@ -8,7 +8,7 @@ use crate::serialize::SerializableCompilation; use crate::serialize::SerializableModule; use crate::unwind::UnwindRegistry; use std::sync::{Arc, Mutex}; -use wasmer_compiler::{CompileError, Features, Triple}; +use wasmer_compiler::{CompileError, Features, SymbolRegistry, Triple}; #[cfg(feature = "compiler")] use wasmer_compiler::{CompileModuleInfo, ModuleEnvironment}; use wasmer_engine::{ @@ -303,4 +303,8 @@ impl Artifact for JITArtifact { serialized.extend(bytes); Ok(serialized) } + + fn symbol_registry(&self) -> &dyn SymbolRegistry { + unimplemented!("TODO: figure out why engine JIT doesn't have a SymbolRegistry") + } } diff --git a/lib/engine-native/src/artifact.rs b/lib/engine-native/src/artifact.rs index 237e6b2d7..1470e7684 100644 --- a/lib/engine-native/src/artifact.rs +++ b/lib/engine-native/src/artifact.rs @@ -598,4 +598,8 @@ impl Artifact for NativeArtifact { fn serialize(&self) -> Result, SerializeError> { Ok(std::fs::read(&self.sharedobject_path)?) } + + fn symbol_registry(&self) -> &dyn SymbolRegistry { + &self.metadata + } } diff --git a/lib/engine-object-file/src/artifact.rs b/lib/engine-object-file/src/artifact.rs index f78d67e0f..8cb4ca0d7 100644 --- a/lib/engine-object-file/src/artifact.rs +++ b/lib/engine-object-file/src/artifact.rs @@ -237,174 +237,6 @@ impl ObjectFileArtifact { Self::from_parts_crosscompiled(&mut *engine_inner, metadata, obj_bytes, metadata_length) } - /// Generate the header file that goes with the generated object file. - pub fn generate_header_file(&self) -> String { - use crate::header::*; - let mut c_statements = vec![]; - c_statements.push(CStatement::Declaration { - name: "module_bytes_len".to_string(), - array: false, - is_extern: false, - is_const: true, - ctype: CType::U32, - definition: Some(Box::new(CStatement::LiteralConstant { - value: format!("{}", self.metadata_length), - })), - }); - c_statements.push(CStatement::Declaration { - name: "WASMER_METADATA".to_string(), - array: true, - is_extern: true, - is_const: true, - ctype: CType::U8, - definition: None, - }); - for (function_local_index, _function_len) in self.metadata.function_body_lengths.iter() { - let function_name = self - .metadata - .symbol_to_name(Symbol::LocalFunction(function_local_index)); - // TODO: figure out the signature here too - c_statements.push(CStatement::Declaration { - name: function_name.clone(), - array: false, - is_extern: false, - is_const: false, - ctype: CType::Function { - arguments: vec![CType::Void], - return_value: None, - }, - definition: None, - }); - } - - // function pointer array - { - let mut function_pointer_array_statements = vec![]; - for (function_local_index, _function_len) in self.metadata.function_body_lengths.iter() - { - let function_name = self - .metadata - .symbol_to_name(Symbol::LocalFunction(function_local_index)); - // TODO: figure out the signature here too - - function_pointer_array_statements.push(CStatement::LiteralConstant { - value: function_name.clone(), - }); - } - - c_statements.push(CStatement::Declaration { - name: "function_pointers".to_string(), - array: true, - is_extern: false, - is_const: true, - ctype: CType::void_ptr(), - definition: Some(Box::new(CStatement::LiteralArray { - items: function_pointer_array_statements, - })), - }); - } - - for (sig_index, _func_type) in self.metadata.compile_info.module.signatures.iter() { - let function_name = self - .metadata - .symbol_to_name(Symbol::FunctionCallTrampoline(sig_index)); - - c_statements.push(CStatement::Declaration { - name: function_name.clone(), - array: false, - is_extern: false, - is_const: false, - ctype: CType::Function { - arguments: vec![CType::void_ptr(), CType::void_ptr(), CType::void_ptr()], - return_value: None, - }, - definition: None, - }); - } - - // function trampolines - { - let mut function_trampoline_statements = vec![]; - for (sig_index, _vm_shared_index) in self.metadata.compile_info.module.signatures.iter() - { - let function_name = self - .metadata - .symbol_to_name(Symbol::FunctionCallTrampoline(sig_index)); - function_trampoline_statements.push(CStatement::LiteralConstant { - value: function_name, - }); - } - - c_statements.push(CStatement::Declaration { - name: "function_trampolines".to_string(), - array: true, - is_extern: false, - is_const: true, - ctype: CType::void_ptr(), - definition: Some(Box::new(CStatement::LiteralArray { - items: function_trampoline_statements, - })), - }); - } - - for func_index in self - .metadata - .compile_info - .module - .functions - .keys() - .take(self.metadata.compile_info.module.num_imported_functions) - { - let function_name = self - .metadata - .symbol_to_name(Symbol::DynamicFunctionTrampoline(func_index)); - // TODO: figure out the signature here - c_statements.push(CStatement::Declaration { - name: function_name, - array: false, - is_extern: false, - is_const: false, - ctype: CType::Function { - arguments: vec![CType::void_ptr(), CType::void_ptr(), CType::void_ptr()], - return_value: None, - }, - definition: None, - }); - } - - // dynamic function trampoline pointer array - { - let mut dynamic_function_trampoline_statements = vec![]; - for func_index in self - .metadata - .compile_info - .module - .functions - .keys() - .take(self.metadata.compile_info.module.num_imported_functions) - { - let function_name = self - .metadata - .symbol_to_name(Symbol::DynamicFunctionTrampoline(func_index)); - dynamic_function_trampoline_statements.push(CStatement::LiteralConstant { - value: function_name, - }); - } - c_statements.push(CStatement::Declaration { - name: "dynamic_function_trampoline_pointers".to_string(), - array: true, - is_extern: false, - is_const: true, - ctype: CType::void_ptr(), - definition: Some(Box::new(CStatement::LiteralArray { - items: dynamic_function_trampoline_statements, - })), - }); - } - - generate_c(&c_statements) - } - /// Get the default extension when serializing this artifact pub fn get_default_extension(triple: &Triple) -> &'static str { match triple.operating_system { @@ -640,4 +472,8 @@ impl Artifact for ObjectFileArtifact { fn serialize(&self) -> Result, SerializeError> { Ok(self.module_bytes.clone()) } + + fn symbol_registry(&self) -> &dyn SymbolRegistry { + &self.metadata + } } diff --git a/lib/engine-object-file/src/header.rs b/lib/engine-object-file/src/header.rs deleted file mode 100644 index ad5ee20c1..000000000 --- a/lib/engine-object-file/src/header.rs +++ /dev/null @@ -1,234 +0,0 @@ -#[derive(Debug, Clone)] -pub enum CType { - Void, - PointerTo { - is_const: bool, - inner: Box, - }, - U8, - U16, - U32, - U64, - USize, - I8, - I16, - I32, - I64, - ISize, - Function { - arguments: Vec, - return_value: Option>, - }, -} - -impl CType { - pub fn void_ptr() -> Self { - CType::PointerTo { - is_const: false, - inner: Box::new(CType::Void), - } - } - - #[allow(dead_code)] - pub fn const_void_ptr() -> Self { - CType::PointerTo { - is_const: false, - inner: Box::new(CType::Void), - } - } - - fn generate_c(&self, w: &mut String) { - match &self { - Self::Void => { - w.push_str("void"); - } - Self::PointerTo { is_const, inner } => { - if *is_const { - w.push_str("const "); - } - inner.generate_c(w); - w.push_str("*"); - } - Self::U8 => { - w.push_str("unsigned char"); - } - Self::U16 => { - w.push_str("unsigned short"); - } - Self::U32 => { - w.push_str("unsigned int"); - } - Self::U64 => { - w.push_str("unsigned long long"); - } - Self::USize => { - w.push_str("unsigned size_t"); - } - Self::I8 => { - w.push_str("char"); - } - Self::I16 => { - w.push_str("short"); - } - Self::I32 => { - w.push_str("int"); - } - Self::I64 => { - w.push_str("long long"); - } - Self::ISize => { - w.push_str("size_t"); - } - Self::Function { - arguments, - return_value, - } => { - // function with no, name, assume it's a function pointer - let ret: CType = return_value - .as_ref() - .map(|i: &Box| (&**i).clone()) - .unwrap_or_default(); - ret.generate_c(w); - w.push(' '); - w.push_str("(*)"); - w.push('('); - if arguments.len() > 1 { - for arg in &arguments[..arguments.len() - 1] { - arg.generate_c(w); - w.push_str(", "); - } - arguments.last().unwrap().generate_c(w); - } else if arguments.len() == 1 { - arguments[0].generate_c(w); - } - w.push(')'); - } - } - } - - fn generate_c_with_name(&self, name: &String, w: &mut String) { - match &self { - Self::PointerTo { .. } - | Self::Void - | Self::U8 - | Self::U16 - | Self::U32 - | Self::U64 - | Self::USize - | Self::I8 - | Self::I16 - | Self::I32 - | Self::I64 - | Self::ISize => { - self.generate_c(w); - w.push(' '); - w.push_str(name); - } - Self::Function { - arguments, - return_value, - } => { - let ret: CType = return_value - .as_ref() - .map(|i: &Box| (&**i).clone()) - .unwrap_or_default(); - ret.generate_c(w); - w.push(' '); - w.push_str(&name); - w.push('('); - if arguments.len() > 1 { - for arg in &arguments[..arguments.len() - 1] { - arg.generate_c(w); - w.push_str(", "); - } - arguments.last().unwrap().generate_c(w); - } else if arguments.len() == 1 { - arguments[0].generate_c(w); - } - w.push(')'); - } - } - } -} - -impl Default for CType { - fn default() -> CType { - CType::Void - } -} - -#[derive(Debug, Clone)] -pub enum CStatement { - Declaration { - name: String, - array: bool, - is_extern: bool, - is_const: bool, - ctype: CType, - definition: Option>, - }, - LiteralArray { - items: Vec, - }, - LiteralConstant { - value: String, - }, -} - -impl CStatement { - fn generate_c(&self, w: &mut String) { - match &self { - Self::Declaration { - name, - array, - is_extern, - is_const, - ctype, - definition, - } => { - if *is_const { - w.push_str("const "); - } - if *is_extern { - w.push_str("extern "); - } - ctype.generate_c_with_name(name, w); - // TODO: array should be part of the type - if *array { - w.push_str("[]"); - } - if let Some(def) = definition { - w.push_str(" = "); - def.generate_c(w); - } - w.push(';'); - w.push('\n'); - } - Self::LiteralArray { items } => { - w.push('{'); - if !items.is_empty() { - w.push('\n'); - } - for item in items { - w.push('\t'); - item.generate_c(w); - w.push(','); - w.push('\n'); - } - w.push('}'); - } - Self::LiteralConstant { value } => { - w.push_str(&value); - } - } - } -} - -// TODO: add config section -pub fn generate_c(statements: &[CStatement]) -> String { - let mut out = String::new(); - for statement in statements { - statement.generate_c(&mut out); - } - out -} diff --git a/lib/engine-object-file/src/lib.rs b/lib/engine-object-file/src/lib.rs index f8b5ee86e..e3f607811 100644 --- a/lib/engine-object-file/src/lib.rs +++ b/lib/engine-object-file/src/lib.rs @@ -24,7 +24,6 @@ mod artifact; mod builder; mod engine; -pub(crate) mod header; mod serialize; pub use crate::artifact::ObjectFileArtifact; diff --git a/lib/engine/src/artifact.rs b/lib/engine/src/artifact.rs index b7fef4c3b..da8a93eaa 100644 --- a/lib/engine/src/artifact.rs +++ b/lib/engine/src/artifact.rs @@ -5,7 +5,7 @@ use std::any::Any; use std::fs; use std::path::Path; use std::sync::Arc; -use wasmer_compiler::Features; +use wasmer_compiler::{Features, SymbolRegistry}; use wasmer_types::entity::{BoxedSlice, PrimaryMap}; use wasmer_types::{ DataInitializer, FunctionIndex, LocalFunctionIndex, MemoryIndex, OwnedDataInitializer, @@ -21,7 +21,7 @@ use wasmer_vm::{ /// The `Artifact` contains the compiled data for a given /// module as well as extra information needed to run the /// module at runtime, such as [`ModuleInfo`] and [`Features`]. -pub trait Artifact: Send + Sync + 'static + Upcastable { +pub trait Artifact: Send + Sync { /// Return a reference-counted pointer to the module fn module(&self) -> Arc; @@ -148,41 +148,7 @@ pub trait Artifact: Send + Sync + 'static + Upcastable { .finish_instantiation(is_bulk_memory, &data_initializers) .map_err(|trap| InstantiationError::Start(RuntimeError::from_trap(trap))) } -} -// Implementation of `Upcastable` taken from https://users.rust-lang.org/t/why-does-downcasting-not-work-for-subtraits/33286/7 . -/// Trait needed to get downcasting from `Artifact` to work. -pub trait Upcastable { - fn upcast_any_ref(self: &'_ Self) -> &'_ dyn Any; - fn upcast_any_mut(self: &'_ mut Self) -> &'_ mut dyn Any; - fn upcast_any_box(self: Box) -> Box; -} - -impl Upcastable for T { - #[inline] - fn upcast_any_ref(self: &'_ Self) -> &'_ dyn Any { - self - } - #[inline] - fn upcast_any_mut(self: &'_ mut Self) -> &'_ mut dyn Any { - self - } - #[inline] - fn upcast_any_box(self: Box) -> Box { - self - } -} - -impl dyn Artifact + 'static { - /// Downcast a reference to an `Artifact` into a specific implementor. - #[inline] - pub fn downcast_ref(self: &'_ Self) -> Option<&'_ T> { - self.upcast_any_ref().downcast_ref::() - } - - /// Downcast a mutable reference to an `Artifact` into a specific implementor. - #[inline] - pub fn downcast_mut(self: &'_ mut Self) -> Option<&'_ mut T> { - self.upcast_any_mut().downcast_mut::() - } + /// Get the `SymbolRegistry` used to generate the names used in the Artifact. + fn symbol_registry(&self) -> &dyn SymbolRegistry; } From 4e7f0d52e281adfb06b04709818718d87dfced3f Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Fri, 4 Sep 2020 11:41:50 -0700 Subject: [PATCH 009/281] Clean up generating C code; pass in metadata length Add some unit tests for the C code generation --- Makefile | 1 + .../{header_file_generation => c_gen}/mod.rs | 327 +++++++++--------- lib/cli/src/c_gen/object_file_header.rs | 176 ++++++++++ lib/cli/src/commands/compile.rs | 8 +- lib/cli/src/lib.rs | 2 +- lib/engine-jit/src/artifact.rs | 5 + lib/engine-native/src/artifact.rs | 6 + lib/engine-object-file/src/artifact.rs | 6 +- lib/engine/src/artifact.rs | 3 + 9 files changed, 371 insertions(+), 163 deletions(-) rename lib/cli/src/{header_file_generation => c_gen}/mod.rs (58%) create mode 100644 lib/cli/src/c_gen/object_file_header.rs diff --git a/Makefile b/Makefile index 4ca4ff68f..b1f3fc14b 100644 --- a/Makefile +++ b/Makefile @@ -117,6 +117,7 @@ test-packages: cargo test -p wasmer-wasi --release cargo test -p wasmer-object --release cargo test -p wasmer-engine-native --release --no-default-features + cargo test -p wasmer-cli --release test-capi-singlepass: build-capi-singlepass cargo test --manifest-path lib/c-api/Cargo.toml --release \ diff --git a/lib/cli/src/header_file_generation/mod.rs b/lib/cli/src/c_gen/mod.rs similarity index 58% rename from lib/cli/src/header_file_generation/mod.rs rename to lib/cli/src/c_gen/mod.rs index 14870cf70..c650c1438 100644 --- a/lib/cli/src/header_file_generation/mod.rs +++ b/lib/cli/src/c_gen/mod.rs @@ -1,6 +1,8 @@ //! A convenient little abstraction for building up C expressions and generating //! simple C code. +pub mod object_file_header; + /// A Type in the C language. #[derive(Debug, Clone)] pub enum CType { @@ -57,7 +59,7 @@ impl CType { #[allow(dead_code)] pub fn const_void_ptr() -> Self { CType::PointerTo { - is_const: false, + is_const: true, inner: Box::new(CType::Void), } } @@ -133,7 +135,7 @@ impl CType { } /// Generate the C source code for a type with a nameinto the given `String`. - fn generate_c_with_name(&self, name: &String, w: &mut String) { + fn generate_c_with_name(&self, name: &str, w: &mut String) { match &self { Self::PointerTo { .. } | Self::Void @@ -280,177 +282,184 @@ pub fn generate_c(statements: &[CStatement]) -> String { out } -// TODO: split the bottom part into its own file +#[cfg(test)] +mod test { + use super::*; -use wasmer_compiler::{Symbol, SymbolRegistry}; -use wasmer_vm::ModuleInfo; + #[test] + fn generate_types() { + macro_rules! assert_c_type { + ($ctype:expr, $expected:expr) => { + let mut w = String::new(); + let ctype = $ctype; + ctype.generate_c(&mut w); + assert_eq!(w, $expected); + }; + } -/// Generate the header file that goes with the generated object file. -pub fn generate_header_file( - module_info: &ModuleInfo, - symbol_registry: &dyn SymbolRegistry, -) -> String { - let mut c_statements = vec![]; - c_statements.push(CStatement::Declaration { - name: "module_bytes_len".to_string(), - array: false, - is_extern: false, - is_const: true, - ctype: CType::U32, - definition: Some(Box::new(CStatement::LiteralConstant { - value: "0".to_string(), //todo!("get the metadata length from somewhere"), //format!("{}", self.metadata_length), - })), - }); - c_statements.push(CStatement::Declaration { - name: "WASMER_METADATA".to_string(), - array: true, - is_extern: true, - is_const: true, - ctype: CType::U8, - definition: None, - }); - for (function_local_index, _sig_index) in - module_info - .functions - .iter() - .filter_map(|(f_index, sig_index)| { - Some((module_info.local_func_index(f_index)?, sig_index)) - }) - { - let function_name = - symbol_registry.symbol_to_name(Symbol::LocalFunction(function_local_index)); - // TODO: figure out the signature here too - c_statements.push(CStatement::Declaration { - name: function_name.clone(), - array: false, - is_extern: false, - is_const: false, - ctype: CType::Function { - arguments: vec![CType::Void], + assert_c_type!(CType::Void, "void"); + assert_c_type!(CType::void_ptr(), "void*"); + assert_c_type!(CType::const_void_ptr(), "const void*"); + assert_c_type!(CType::U8, "unsigned char"); + assert_c_type!(CType::U16, "unsigned short"); + assert_c_type!(CType::U32, "unsigned int"); + assert_c_type!(CType::U64, "unsigned long long"); + assert_c_type!(CType::USize, "unsigned size_t"); + assert_c_type!(CType::I8, "char"); + assert_c_type!(CType::I16, "short"); + assert_c_type!(CType::I32, "int"); + assert_c_type!(CType::I64, "long long"); + assert_c_type!(CType::ISize, "size_t"); + assert_c_type!( + CType::Function { + arguments: vec![CType::U8, CType::ISize], return_value: None, }, - definition: None, - }); - } + "void (*)(unsigned char, size_t)" + ); + assert_c_type!( + CType::Function { + arguments: vec![], + return_value: Some(Box::new(CType::ISize)), + }, + "size_t (*)()" + ); - // function pointer array - { - let mut function_pointer_array_statements = vec![]; - for (function_local_index, _sig_index) in - module_info - .functions - .iter() - .filter_map(|(f_index, sig_index)| { - Some((module_info.local_func_index(f_index)?, sig_index)) + assert_c_type!( + CType::PointerTo { + is_const: true, + inner: Box::new(CType::PointerTo { + is_const: false, + inner: Box::new(CType::U32), }) - { - let function_name = - symbol_registry.symbol_to_name(Symbol::LocalFunction(function_local_index)); - // TODO: figure out the signature here too - - function_pointer_array_statements.push(CStatement::LiteralConstant { - value: function_name.clone(), - }); - } - - c_statements.push(CStatement::Declaration { - name: "function_pointers".to_string(), - array: true, - is_extern: false, - is_const: true, - ctype: CType::void_ptr(), - definition: Some(Box::new(CStatement::LiteralArray { - items: function_pointer_array_statements, - })), - }); + }, + "const unsigned int**" + ); + // TODO: test more complicated const correctness rules: there are bugs relating to it. } - for (sig_index, _func_type) in module_info.signatures.iter() { - let function_name = - symbol_registry.symbol_to_name(Symbol::FunctionCallTrampoline(sig_index)); + #[test] + fn generate_types_with_names() { + macro_rules! assert_c_type { + ($ctype:expr, $name:literal, $expected:expr) => { + let mut w = String::new(); + let ctype = $ctype; + ctype.generate_c_with_name($name, &mut w); + assert_eq!(w, $expected); + }; + } - c_statements.push(CStatement::Declaration { - name: function_name.clone(), - array: false, - is_extern: false, - is_const: false, - ctype: CType::Function { - arguments: vec![CType::void_ptr(), CType::void_ptr(), CType::void_ptr()], + assert_c_type!(CType::Void, "main", "void main"); + assert_c_type!(CType::void_ptr(), "data", "void* data"); + assert_c_type!(CType::const_void_ptr(), "data", "const void* data"); + assert_c_type!(CType::U8, "data", "unsigned char data"); + assert_c_type!(CType::U16, "data", "unsigned short data"); + assert_c_type!(CType::U32, "data", "unsigned int data"); + assert_c_type!(CType::U64, "data", "unsigned long long data"); + assert_c_type!(CType::USize, "data", "unsigned size_t data"); + assert_c_type!(CType::I8, "data", "char data"); + assert_c_type!(CType::I16, "data", "short data"); + assert_c_type!(CType::I32, "data", "int data"); + assert_c_type!(CType::I64, "data", "long long data"); + assert_c_type!(CType::ISize, "data", "size_t data"); + assert_c_type!( + CType::Function { + arguments: vec![CType::U8, CType::ISize], return_value: None, }, - definition: None, - }); - } - - // function trampolines - { - let mut function_trampoline_statements = vec![]; - for (sig_index, _vm_shared_index) in module_info.signatures.iter() { - let function_name = - symbol_registry.symbol_to_name(Symbol::FunctionCallTrampoline(sig_index)); - function_trampoline_statements.push(CStatement::LiteralConstant { - value: function_name, - }); - } - - c_statements.push(CStatement::Declaration { - name: "function_trampolines".to_string(), - array: true, - is_extern: false, - is_const: true, - ctype: CType::void_ptr(), - definition: Some(Box::new(CStatement::LiteralArray { - items: function_trampoline_statements, - })), - }); - } - - for func_index in module_info - .functions - .keys() - .take(module_info.num_imported_functions) - { - let function_name = - symbol_registry.symbol_to_name(Symbol::DynamicFunctionTrampoline(func_index)); - // TODO: figure out the signature here - c_statements.push(CStatement::Declaration { - name: function_name, - array: false, - is_extern: false, - is_const: false, - ctype: CType::Function { - arguments: vec![CType::void_ptr(), CType::void_ptr(), CType::void_ptr()], - return_value: None, + "my_func", + "void my_func(unsigned char, size_t)" + ); + assert_c_type!( + CType::Function { + arguments: vec![], + return_value: Some(Box::new(CType::ISize)), }, - definition: None, - }); + "my_func", + "size_t my_func()" + ); + + assert_c_type!( + CType::PointerTo { + is_const: true, + inner: Box::new(CType::PointerTo { + is_const: false, + inner: Box::new(CType::U32), + }) + }, + "data", + "const unsigned int** data" + ); + // TODO: test more complicated const correctness rules: there are bugs relating to it. } - // dynamic function trampoline pointer array - { - let mut dynamic_function_trampoline_statements = vec![]; - for func_index in module_info - .functions - .keys() - .take(module_info.num_imported_functions) - { - let function_name = - symbol_registry.symbol_to_name(Symbol::DynamicFunctionTrampoline(func_index)); - dynamic_function_trampoline_statements.push(CStatement::LiteralConstant { - value: function_name, - }); + #[test] + fn generate_expressions_works() { + macro_rules! assert_c_expr { + ($cexpr:expr, $expected:expr) => { + let mut w = String::new(); + let cexpr = $cexpr; + cexpr.generate_c(&mut w); + assert_eq!(w, $expected); + }; } - c_statements.push(CStatement::Declaration { - name: "dynamic_function_trampoline_pointers".to_string(), - array: true, - is_extern: false, - is_const: true, - ctype: CType::void_ptr(), - definition: Some(Box::new(CStatement::LiteralArray { - items: dynamic_function_trampoline_statements, - })), - }); - } - generate_c(&c_statements) + assert_c_expr!( + CStatement::LiteralConstant { + value: "\"Hello, world!\"".to_string(), + }, + "\"Hello, world!\"" + ); + assert_c_expr!( + CStatement::LiteralArray { + items: vec![ + CStatement::LiteralConstant { + value: "1".to_string() + }, + CStatement::LiteralConstant { + value: "2".to_string() + }, + CStatement::LiteralConstant { + value: "3".to_string() + }, + ] + }, + "{\n\t1,\n\t2,\n\t3,\n}" + ); + assert_c_expr!(CStatement::LiteralArray { items: vec![] }, "{}"); + assert_c_expr!( + CStatement::Declaration { + name: "my_array".to_string(), + array: true, + is_extern: false, + is_const: true, + ctype: CType::I32, + definition: Some(Box::new(CStatement::LiteralArray { + items: vec![ + CStatement::LiteralConstant { + value: "1".to_string() + }, + CStatement::LiteralConstant { + value: "2".to_string() + }, + CStatement::LiteralConstant { + value: "3".to_string() + }, + ] + })) + }, + "const int my_array[] = {\n\t1,\n\t2,\n\t3,\n};\n" + ); + assert_c_expr!( + CStatement::Declaration { + name: "my_array".to_string(), + array: true, + is_extern: true, + is_const: true, + ctype: CType::I32, + definition: None, + }, + "const extern int my_array[];\n" + ); + } } diff --git a/lib/cli/src/c_gen/object_file_header.rs b/lib/cli/src/c_gen/object_file_header.rs new file mode 100644 index 000000000..7d3dd4b14 --- /dev/null +++ b/lib/cli/src/c_gen/object_file_header.rs @@ -0,0 +1,176 @@ +//! Generate a header file for the object file produced by the ObjectFile engine. + +use super::{generate_c, CStatement, CType}; +use wasmer_compiler::{Symbol, SymbolRegistry}; +use wasmer_vm::ModuleInfo; + +/// Generate the header file that goes with the generated object file. +pub fn generate_header_file( + module_info: &ModuleInfo, + symbol_registry: &dyn SymbolRegistry, + metadata_length: usize, +) -> String { + let mut c_statements = vec![]; + c_statements.push(CStatement::Declaration { + name: "module_bytes_len".to_string(), + array: false, + is_extern: false, + is_const: true, + ctype: CType::U32, + definition: Some(Box::new(CStatement::LiteralConstant { + value: format!("{}", metadata_length), + })), + }); + c_statements.push(CStatement::Declaration { + name: "WASMER_METADATA".to_string(), + array: true, + is_extern: true, + is_const: true, + ctype: CType::U8, + definition: None, + }); + for (function_local_index, _sig_index) in + module_info + .functions + .iter() + .filter_map(|(f_index, sig_index)| { + Some((module_info.local_func_index(f_index)?, sig_index)) + }) + { + let function_name = + symbol_registry.symbol_to_name(Symbol::LocalFunction(function_local_index)); + // TODO: figure out the signature here too + c_statements.push(CStatement::Declaration { + name: function_name.clone(), + array: false, + is_extern: false, + is_const: false, + ctype: CType::Function { + arguments: vec![CType::Void], + return_value: None, + }, + definition: None, + }); + } + + // function pointer array + { + let mut function_pointer_array_statements = vec![]; + for (function_local_index, _sig_index) in + module_info + .functions + .iter() + .filter_map(|(f_index, sig_index)| { + Some((module_info.local_func_index(f_index)?, sig_index)) + }) + { + let function_name = + symbol_registry.symbol_to_name(Symbol::LocalFunction(function_local_index)); + // TODO: figure out the signature here too + + function_pointer_array_statements.push(CStatement::LiteralConstant { + value: function_name.clone(), + }); + } + + c_statements.push(CStatement::Declaration { + name: "function_pointers".to_string(), + array: true, + is_extern: false, + is_const: true, + ctype: CType::void_ptr(), + definition: Some(Box::new(CStatement::LiteralArray { + items: function_pointer_array_statements, + })), + }); + } + + for (sig_index, _func_type) in module_info.signatures.iter() { + let function_name = + symbol_registry.symbol_to_name(Symbol::FunctionCallTrampoline(sig_index)); + + c_statements.push(CStatement::Declaration { + name: function_name.clone(), + array: false, + is_extern: false, + is_const: false, + ctype: CType::Function { + arguments: vec![CType::void_ptr(), CType::void_ptr(), CType::void_ptr()], + return_value: None, + }, + definition: None, + }); + } + + // function trampolines + { + let mut function_trampoline_statements = vec![]; + for (sig_index, _vm_shared_index) in module_info.signatures.iter() { + let function_name = + symbol_registry.symbol_to_name(Symbol::FunctionCallTrampoline(sig_index)); + function_trampoline_statements.push(CStatement::LiteralConstant { + value: function_name, + }); + } + + c_statements.push(CStatement::Declaration { + name: "function_trampolines".to_string(), + array: true, + is_extern: false, + is_const: true, + ctype: CType::void_ptr(), + definition: Some(Box::new(CStatement::LiteralArray { + items: function_trampoline_statements, + })), + }); + } + + for func_index in module_info + .functions + .keys() + .take(module_info.num_imported_functions) + { + let function_name = + symbol_registry.symbol_to_name(Symbol::DynamicFunctionTrampoline(func_index)); + // TODO: figure out the signature here + c_statements.push(CStatement::Declaration { + name: function_name, + array: false, + is_extern: false, + is_const: false, + ctype: CType::Function { + arguments: vec![CType::void_ptr(), CType::void_ptr(), CType::void_ptr()], + return_value: None, + }, + definition: None, + }); + } + + // dynamic function trampoline pointer array + { + let mut dynamic_function_trampoline_statements = vec![]; + for func_index in module_info + .functions + .keys() + .take(module_info.num_imported_functions) + { + let function_name = + symbol_registry.symbol_to_name(Symbol::DynamicFunctionTrampoline(func_index)); + dynamic_function_trampoline_statements.push(CStatement::LiteralConstant { + value: function_name, + }); + } + c_statements.push(CStatement::Declaration { + name: "dynamic_function_trampoline_pointers".to_string(), + array: true, + is_extern: false, + is_const: true, + ctype: CType::void_ptr(), + definition: Some(Box::new(CStatement::LiteralArray { + items: dynamic_function_trampoline_statements, + })), + }); + } + + generate_c(&c_statements) +} diff --git a/lib/cli/src/commands/compile.rs b/lib/cli/src/commands/compile.rs index 6cace1e96..43bc44524 100644 --- a/lib/cli/src/commands/compile.rs +++ b/lib/cli/src/commands/compile.rs @@ -107,9 +107,13 @@ impl Compile { #[cfg(feature = "object-file")] if engine_type == EngineType::ObjectFile { let symbol_registry = module.artifact().symbol_registry(); + let metadata_length = module.artifact().metadata_length(); let module_info = module.info(); - let header_file_src = - crate::header_file_generation::generate_header_file(module_info, symbol_registry); + let header_file_src = crate::c_gen::object_file_header::generate_header_file( + module_info, + symbol_registry, + metadata_length, + ); let header_path = self.header_path.as_ref().cloned().unwrap_or_else(|| { let mut hp = PathBuf::from( diff --git a/lib/cli/src/lib.rs b/lib/cli/src/lib.rs index 9a08d404a..8ee5e428b 100644 --- a/lib/cli/src/lib.rs +++ b/lib/cli/src/lib.rs @@ -20,7 +20,7 @@ pub mod commands; pub mod common; #[macro_use] pub mod error; -pub mod header_file_generation; +pub mod c_gen; #[cfg(feature = "debug")] pub mod logging; pub mod store; diff --git a/lib/engine-jit/src/artifact.rs b/lib/engine-jit/src/artifact.rs index 3cfa34ec7..42b9f27bc 100644 --- a/lib/engine-jit/src/artifact.rs +++ b/lib/engine-jit/src/artifact.rs @@ -307,4 +307,9 @@ impl Artifact for JITArtifact { fn symbol_registry(&self) -> &dyn SymbolRegistry { unimplemented!("TODO: figure out why engine JIT doesn't have a SymbolRegistry") } + + fn metadata_length(&self) -> usize { + // TODO: figure out what to do here + 0 + } } diff --git a/lib/engine-native/src/artifact.rs b/lib/engine-native/src/artifact.rs index 1470e7684..b96ee30f9 100644 --- a/lib/engine-native/src/artifact.rs +++ b/lib/engine-native/src/artifact.rs @@ -602,4 +602,10 @@ impl Artifact for NativeArtifact { fn symbol_registry(&self) -> &dyn SymbolRegistry { &self.metadata } + + fn metadata_length(&self) -> usize { + // TODO: figure out what to do here; + // we could easily store this data and return it... so we probably should + 0 + } } diff --git a/lib/engine-object-file/src/artifact.rs b/lib/engine-object-file/src/artifact.rs index 8cb4ca0d7..4550081bd 100644 --- a/lib/engine-object-file/src/artifact.rs +++ b/lib/engine-object-file/src/artifact.rs @@ -7,7 +7,7 @@ use std::collections::BTreeMap; use std::error::Error; use std::mem; use std::sync::Arc; -use wasmer_compiler::{CompileError, Features, OperatingSystem, Symbol, SymbolRegistry, Triple}; +use wasmer_compiler::{CompileError, Features, OperatingSystem, SymbolRegistry, Triple}; #[cfg(feature = "compiler")] use wasmer_compiler::{ CompileModuleInfo, FunctionBodyData, ModuleEnvironment, ModuleTranslationState, @@ -476,4 +476,8 @@ impl Artifact for ObjectFileArtifact { fn symbol_registry(&self) -> &dyn SymbolRegistry { &self.metadata } + + fn metadata_length(&self) -> usize { + self.metadata_length + } } diff --git a/lib/engine/src/artifact.rs b/lib/engine/src/artifact.rs index da8a93eaa..ccb96987d 100644 --- a/lib/engine/src/artifact.rs +++ b/lib/engine/src/artifact.rs @@ -151,4 +151,7 @@ pub trait Artifact: Send + Sync { /// Get the `SymbolRegistry` used to generate the names used in the Artifact. fn symbol_registry(&self) -> &dyn SymbolRegistry; + + /// The length in bytes of the metadata in the serialized output. + fn metadata_length(&self) -> usize; } From d07b9eef85f87a06193780b10d1f54ad50813419 Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Fri, 4 Sep 2020 13:47:10 -0700 Subject: [PATCH 010/281] Add methods to dummy engine so tests can run --- tests/lib/engine-dummy/src/artifact.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/tests/lib/engine-dummy/src/artifact.rs b/tests/lib/engine-dummy/src/artifact.rs index 42cda621a..e624979c4 100644 --- a/tests/lib/engine-dummy/src/artifact.rs +++ b/tests/lib/engine-dummy/src/artifact.rs @@ -240,4 +240,12 @@ impl Artifact for DummyArtifact { "The serializer feature is not enabled in the DummyEngine", )) } + + fn symbol_registry(&self) -> &dyn wasmer_compiler::SymbolRegistry { + unimplemented!("dummy engine does not hav ea symbol registry") + } + + fn metadata_length(&self) -> usize { + 0 + } } From 24445b92553eadd3c6d3a0c3ca4fe0840b975eda Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Thu, 10 Sep 2020 16:33:56 -0700 Subject: [PATCH 011/281] Add ARM64 Linux to CI matrix --- .github/workflows/main.yaml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/main.yaml b/.github/workflows/main.yaml index 8ecabd69a..6a0de7dc1 100644 --- a/.github/workflows/main.yaml +++ b/.github/workflows/main.yaml @@ -30,7 +30,7 @@ jobs: strategy: fail-fast: false matrix: - build: [linux, macos, windows] + build: [linux, macos, windows, linux-arm] include: - build: linux os: ubuntu-latest @@ -41,6 +41,9 @@ jobs: - build: windows os: windows-latest rust: 1.45.0 + - build: linux-arm + os: [self-hosted, linux, ARM64] + rust: 1.45.2 env: CARGO_SCCACHE_VERSION: 0.2.13 SCCACHE_AZURE_BLOB_CONTAINER: wasmerstoragesccacheblob From 45b6baaa4f497c335c9f3ea14939a1dcf2524721 Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Thu, 17 Sep 2020 15:01:25 -0700 Subject: [PATCH 012/281] Install LLVM on ARM Linux CI --- .github/workflows/main.yaml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/.github/workflows/main.yaml b/.github/workflows/main.yaml index d7a35b0f4..dbc72c5ff 100644 --- a/.github/workflows/main.yaml +++ b/.github/workflows/main.yaml @@ -125,6 +125,14 @@ jobs: tar xf llvm.tar.xz --strip-components=1 -C /opt/llvm-10 echo ::add-path::/opt/llvm-10/bin echo ::set-env name=LLVM_SYS_100_PREFIX::/opt/llvm-10 + - name: Install LLVM (Linux ARM64) + if: matrix.os == [self-hosted, linux, ARM64] + run: | + curl --proto '=https' --tlsv1.2 -sSf https://github.com/llvm/llvm-project/releases/download/llvmorg-10.0.0/clang+llvm-10.0.0-aarch64-linux-gnu.tar.xz -L -o llvm.tar.xz + mkdir -p /opt/llvm-10 + tar xf llvm.tar.xz --strip-components=1 -C /opt/llvm-10 + echo ::add-path::/opt/llvm-10/bin + echo ::set-env name=LLVM_SYS_100_PREFIX::/opt/llvm-10 - name: Set up dependencies for Mac OS run: brew install automake if: matrix.os == 'macos-latest' From 7ed6e1892ff46f3810661015659007f8a8e0ff8b Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Thu, 17 Sep 2020 15:30:55 -0700 Subject: [PATCH 013/281] Testing matching on a custom tag in matrix.os --- .github/workflows/main.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/main.yaml b/.github/workflows/main.yaml index dbc72c5ff..0f4f9d6c2 100644 --- a/.github/workflows/main.yaml +++ b/.github/workflows/main.yaml @@ -126,7 +126,7 @@ jobs: echo ::add-path::/opt/llvm-10/bin echo ::set-env name=LLVM_SYS_100_PREFIX::/opt/llvm-10 - name: Install LLVM (Linux ARM64) - if: matrix.os == [self-hosted, linux, ARM64] + if: matrix.os == 'ARM64' run: | curl --proto '=https' --tlsv1.2 -sSf https://github.com/llvm/llvm-project/releases/download/llvmorg-10.0.0/clang+llvm-10.0.0-aarch64-linux-gnu.tar.xz -L -o llvm.tar.xz mkdir -p /opt/llvm-10 From d3525b6da0e8bb2508149023cd72c2c1863a9d92 Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Thu, 17 Sep 2020 15:44:01 -0700 Subject: [PATCH 014/281] Simplify LLVM install logic on Unix in CI --- .github/workflows/main.yaml | 25 ++++++------------------- 1 file changed, 6 insertions(+), 19 deletions(-) diff --git a/.github/workflows/main.yaml b/.github/workflows/main.yaml index 0f4f9d6c2..7eae7abbf 100644 --- a/.github/workflows/main.yaml +++ b/.github/workflows/main.yaml @@ -43,15 +43,18 @@ jobs: - build: linux os: ubuntu-latest rust: 1.45.2 + llvm_url: 'https://github.com/llvm/llvm-project/releases/download/llvmorg-10.0.0/clang+llvm-10.0.0-x86_64-linux-gnu-ubuntu-18.04.tar.xz' - build: macos os: macos-latest rust: 1.45.2 + llvm_url: 'https://github.com/llvm/llvm-project/releases/download/llvmorg-10.0.0/clang+llvm-10.0.0-x86_64-apple-darwin.tar.xz' - build: windows os: windows-latest rust: 1.45.2 - build: linux-arm os: [self-hosted, linux, ARM64] rust: 1.45.2 + llvm_url: 'https://github.com/llvm/llvm-project/releases/download/llvmorg-10.0.0/clang+llvm-10.0.0-aarch64-linux-gnu.tar.xz' env: CARGO_SCCACHE_VERSION: 0.2.13 SCCACHE_AZURE_BLOB_CONTAINER: wasmerstoragesccacheblob @@ -107,32 +110,16 @@ jobs: # echo ::add-path::C:/llvm-10/bin # echo ::set-env name=LLVM_SYS_100_PREFIX::C:/llvm-10 # echo ::set-env name=LIBCLANG_PATH::C:/llvm-10/bin/libclang.dll - - name: Install LLVM (macOS) - if: matrix.os == 'macos-latest' + - name: Install LLVM (Unix) + if: matrix.os != 'windows-latest' run: | - curl --proto '=https' --tlsv1.2 -sSf https://github.com/llvm/llvm-project/releases/download/llvmorg-10.0.0/clang+llvm-10.0.0-x86_64-apple-darwin.tar.xz -L -o llvm.tar.xz + curl --proto '=https' --tlsv1.2 -sSf ${{ matrix.llvm_url }} -L -o llvm.tar.xz mkdir -p ${{ env.LLVM_DIR }} tar xf llvm.tar.xz --strip-components=1 -C ${{ env.LLVM_DIR }} echo "::add-path::${{ env.LLVM_DIR }}/bin" echo "::set-env name=LLVM_SYS_100_PREFIX::${{ env.LLVM_DIR }}" env: LLVM_DIR: ${{ github.workspace }}/llvm-10 - - name: Install LLVM (Linux) - if: matrix.os == 'ubuntu-latest' - run: | - curl --proto '=https' --tlsv1.2 -sSf https://github.com/llvm/llvm-project/releases/download/llvmorg-10.0.0/clang+llvm-10.0.0-x86_64-linux-gnu-ubuntu-18.04.tar.xz -L -o llvm.tar.xz - mkdir -p /opt/llvm-10 - tar xf llvm.tar.xz --strip-components=1 -C /opt/llvm-10 - echo ::add-path::/opt/llvm-10/bin - echo ::set-env name=LLVM_SYS_100_PREFIX::/opt/llvm-10 - - name: Install LLVM (Linux ARM64) - if: matrix.os == 'ARM64' - run: | - curl --proto '=https' --tlsv1.2 -sSf https://github.com/llvm/llvm-project/releases/download/llvmorg-10.0.0/clang+llvm-10.0.0-aarch64-linux-gnu.tar.xz -L -o llvm.tar.xz - mkdir -p /opt/llvm-10 - tar xf llvm.tar.xz --strip-components=1 -C /opt/llvm-10 - echo ::add-path::/opt/llvm-10/bin - echo ::set-env name=LLVM_SYS_100_PREFIX::/opt/llvm-10 - name: Set up dependencies for Mac OS run: brew install automake if: matrix.os == 'macos-latest' From da69eca99b2d77512b276a8882e164c0ec2ce918 Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Fri, 18 Sep 2020 10:11:09 +0200 Subject: [PATCH 015/281] test(c-api) Update `CMake` to match all Wasm C API examples. --- lib/c-api/tests/CMakeLists.txt | 128 ++++++++++++++++++++------------- 1 file changed, 77 insertions(+), 51 deletions(-) diff --git a/lib/c-api/tests/CMakeLists.txt b/lib/c-api/tests/CMakeLists.txt index 17b4eb8c6..728e11181 100644 --- a/lib/c-api/tests/CMakeLists.txt +++ b/lib/c-api/tests/CMakeLists.txt @@ -4,8 +4,6 @@ project (WasmerRuntimeCApiTests) add_executable(test-exported-memory test-exported-memory.c) add_executable(test-exports test-exports.c) add_executable(test-globals test-globals.c) -# trampoline functionality not yet implemented -#add_executable(test-import-function test-import-function.c) add_executable(test-import-trap test-import-trap.c) add_executable(test-imports test-imports.c) add_executable(test-import-object test-import-object.c) @@ -20,17 +18,20 @@ add_executable(test-validate test-validate.c) add_executable(test-context test-context.c) add_executable(test-module-import-instantiate test-module-import-instantiate.c) - # Wasm C API tests -add_executable(wasm-c-api-hello wasm-c-api/example/hello.c) -add_executable(wasm-c-api-memory wasm-c-api/example/memory.c) -add_executable(wasm-c-api-global wasm-c-api/example/global.c) -#add_executable(wasm-c-api-table wasm-c-api/example/table.c) -add_executable(wasm-c-api-serialize wasm-c-api/example/serialize.c) add_executable(wasm-c-api-callback wasm-c-api/example/callback.c) #add_executable(wasm-c-api-finalize wasm-c-api/example/finalize.c) +add_executable(wasm-c-api-global wasm-c-api/example/global.c) +add_executable(wasm-c-api-hello wasm-c-api/example/hello.c) +#add_executable(wasm-c-api-hostref wasm-c-api/example/hostref.c) +add_executable(wasm-c-api-memory wasm-c-api/example/memory.c) +#add_executable(wasm-c-api-multi wasm-c-api/example/multi.c) add_executable(wasm-c-api-reflect wasm-c-api/example/reflect.c) +add_executable(wasm-c-api-serialize wasm-c-api/example/serialize.c) #add_executable(wasm-c-api-start wasm-c-api/example/start.c) +#add_executable(wasm-c-api-table wasm-c-api/example/table.c) +#add_executable(wasm-c-api-threads wasm-c-api/example/threads.c) +#add_executable(wasm-c-api-trap wasm-c-api/example/trap.c) # Custom Wasm C API tests add_executable(wasm-c-api-wasi wasm-c-api-wasi.c) @@ -46,7 +47,6 @@ endif() include_directories(wasm-c-api/include) include_directories(..) - find_library( WASMER_LIB NAMES libwasmer_c_api.dylib libwasmer_c_api.so wasmer_c_api.dll PATHS ${CMAKE_SOURCE_DIR}/../../../target/release/ @@ -151,75 +151,101 @@ target_link_libraries(test-module-import-instantiate general ${WASMER_LIB}) target_compile_options(test-module-import-instantiate PRIVATE ${COMPILER_OPTIONS}) add_test(test-module-import-instantiate test-module-import-instantiate) -target_link_libraries(wasm-c-api-hello general ${WASMER_LIB}) -target_compile_options(wasm-c-api-hello PRIVATE ${COMPILER_OPTIONS}) -add_test(NAME wasm-c-api-hello - COMMAND wasm-c-api-hello - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/wasm-c-api/example -) - -target_link_libraries(wasm-c-api-memory general ${WASMER_LIB}) -target_compile_options(wasm-c-api-memory PRIVATE ${COMPILER_OPTIONS}) -add_test(NAME wasm-c-api-memory - COMMAND wasm-c-api-memory - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/wasm-c-api/example -) - -target_link_libraries(wasm-c-api-global general ${WASMER_LIB}) -target_compile_options(wasm-c-api-global PRIVATE ${COMPILER_OPTIONS}) -add_test(NAME wasm-c-api-global - COMMAND wasm-c-api-global - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/wasm-c-api/example -) - -#target_link_libraries(wasm-c-api-table general ${WASMER_LIB}) -#target_compile_options(wasm-c-api-table PRIVATE ${COMPILER_OPTIONS}) -#add_test(NAME wasm-c-api-table -# COMMAND wasm-c-api-table -# WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/wasm-c-api/example -#) - -target_link_libraries(wasm-c-api-serialize general ${WASMER_LIB}) -target_compile_options(wasm-c-api-serialize PRIVATE ${COMPILER_OPTIONS}) -add_test(NAME wasm-c-api-serialize - COMMAND wasm-c-api-serialize - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/wasm-c-api/example -) +# Wasm C API tests target_link_libraries(wasm-c-api-callback general ${WASMER_LIB}) target_compile_options(wasm-c-api-callback PRIVATE ${COMPILER_OPTIONS}) add_test(NAME wasm-c-api-callback COMMAND wasm-c-api-callback - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/wasm-c-api/example + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/wasm-c-api/example/ ) #target_link_libraries(wasm-c-api-finalize general ${WASMER_LIB}) #target_compile_options(wasm-c-api-finalize PRIVATE ${COMPILER_OPTIONS}) #add_test(NAME wasm-c-api-finalize # COMMAND wasm-c-api-finalize -# WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/wasm-c-api/example +# WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/wasm-c-api/example/ +#) + +target_link_libraries(wasm-c-api-global general ${WASMER_LIB}) +target_compile_options(wasm-c-api-global PRIVATE ${COMPILER_OPTIONS}) +add_test(NAME wasm-c-api-global + COMMAND wasm-c-api-global + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/wasm-c-api/example/ +) + +target_link_libraries(wasm-c-api-hello general ${WASMER_LIB}) +target_compile_options(wasm-c-api-hello PRIVATE ${COMPILER_OPTIONS}) +add_test(NAME wasm-c-api-hello + COMMAND wasm-c-api-hello + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/wasm-c-api/example/ +) + +#target_link_libraries(wasm-c-api-hostref general ${WASMER_LIB}) +#target_compile_options(wasm-c-api-hostref PRIVATE ${COMPILER_OPTIONS}) +#add_test(NAME wasm-c-api-hostref +# COMMAND wasm-c-api-hostref +# WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/wasm-c-api/example/ +#) + +target_link_libraries(wasm-c-api-memory general ${WASMER_LIB}) +target_compile_options(wasm-c-api-memory PRIVATE ${COMPILER_OPTIONS}) +add_test(NAME wasm-c-api-memory + COMMAND wasm-c-api-memory + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/wasm-c-api/example/ +) + +#target_link_libraries(wasm-c-api-multi general ${WASMER_LIB}) +#target_compile_options(wasm-c-api-multi PRIVATE ${COMPILER_OPTIONS}) +#add_test(NAME wasm-c-api-multi +# COMMAND wasm-c-api-multi +# WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/wasm-c-api/example/ #) target_link_libraries(wasm-c-api-reflect general ${WASMER_LIB}) target_compile_options(wasm-c-api-reflect PRIVATE ${COMPILER_OPTIONS}) add_test(NAME wasm-c-api-reflect COMMAND wasm-c-api-reflect - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/wasm-c-api/example + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/wasm-c-api/example/ +) + +target_link_libraries(wasm-c-api-serialize general ${WASMER_LIB}) +target_compile_options(wasm-c-api-serialize PRIVATE ${COMPILER_OPTIONS}) +add_test(NAME wasm-c-api-serialize + COMMAND wasm-c-api-serialize + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/wasm-c-api/example/ ) #target_link_libraries(wasm-c-api-start general ${WASMER_LIB}) #target_compile_options(wasm-c-api-start PRIVATE ${COMPILER_OPTIONS}) #add_test(NAME wasm-c-api-start # COMMAND wasm-c-api-start -# WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/wasm-c-api/example +# WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/wasm-c-api/example/ #) +#target_link_libraries(wasm-c-api-table general ${WASMER_LIB}) +#target_compile_options(wasm-c-api-table PRIVATE ${COMPILER_OPTIONS}) +#add_test(NAME wasm-c-api-table +# COMMAND wasm-c-api-table +# WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/wasm-c-api/example/ +#) + +#target_link_libraries(wasm-c-api-threads general ${WASMER_LIB}) +#target_compile_options(wasm-c-api-threads PRIVATE ${COMPILER_OPTIONS}) +#add_test(NAME wasm-c-api-threads +# COMMAND wasm-c-api-threads +# WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/wasm-c-api/example/ +#) + +#target_link_libraries(wasm-c-api-trap general ${WASMER_LIB}) +#target_compile_options(wasm-c-api-trap PRIVATE ${COMPILER_OPTIONS}) +#add_test(NAME wasm-c-api-trap +# COMMAND wasm-c-api-trap +# WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/wasm-c-api/example/ +#) set_property(TARGET wasm-c-api-wasi PROPERTY C_STANDARD 11) target_link_libraries(wasm-c-api-wasi general ${WASMER_LIB}) target_compile_options(wasm-c-api-wasi PRIVATE ${COMPILER_OPTIONS}) -add_test(NAME wasm-c-api-wasi - COMMAND wasm-c-api-wasi - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} #/wasm-c-api/example -) +add_test(wasm-c-api-wasi wasm-c-api-wasi) From 7e681c6091469f3b6491734056ba4121a31ae2e5 Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Fri, 18 Sep 2020 11:52:22 -0700 Subject: [PATCH 016/281] Add aarch64 linux binary to release --- .github/workflows/main.yaml | 24 +++++++++++++++++++----- bors.toml | 1 + 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/.github/workflows/main.yaml b/.github/workflows/main.yaml index 7eae7abbf..1d2630688 100644 --- a/.github/workflows/main.yaml +++ b/.github/workflows/main.yaml @@ -44,17 +44,21 @@ jobs: os: ubuntu-latest rust: 1.45.2 llvm_url: 'https://github.com/llvm/llvm-project/releases/download/llvmorg-10.0.0/clang+llvm-10.0.0-x86_64-linux-gnu-ubuntu-18.04.tar.xz' + artifact_name: 'wasmer-linux-amd64' - build: macos os: macos-latest rust: 1.45.2 llvm_url: 'https://github.com/llvm/llvm-project/releases/download/llvmorg-10.0.0/clang+llvm-10.0.0-x86_64-apple-darwin.tar.xz' + artifact_name: 'wasmer-macos-amd64' - build: windows os: windows-latest rust: 1.45.2 + artifact_name: 'wasmer-windows-amd64' - build: linux-arm os: [self-hosted, linux, ARM64] rust: 1.45.2 llvm_url: 'https://github.com/llvm/llvm-project/releases/download/llvmorg-10.0.0/clang+llvm-10.0.0-aarch64-linux-gnu.tar.xz' + artifact_name: 'wasmer-linux-aarch64' env: CARGO_SCCACHE_VERSION: 0.2.13 SCCACHE_AZURE_BLOB_CONTAINER: wasmerstoragesccacheblob @@ -147,7 +151,7 @@ jobs: uses: actions/upload-artifact@v2 if: needs.setup.outputs.DOING_RELEASE == '1' with: - name: wasmer-${{ matrix.os }} + name: ${{ matrix.artifact_name }} path: dist release: @@ -176,17 +180,17 @@ jobs: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: upload_url: ${{ steps.create_release.outputs.upload_url }} # This pulls from the CREATE RELEASE step above, referencing it's ID to get its outputs object, which include a `upload_url`. See this blog post for more info: https://jasonet.co/posts/new-features-of-github-actions/#passing-data-to-future-steps - asset_path: artifacts/wasmer-windows-latest/wasmer-windows.exe + asset_path: artifacts/wasmer-windows-amd64/wasmer-windows.exe asset_name: wasmer-windows.exe asset_content_type: application/vnd.microsoft.portable-executable - - name: Upload Release Asset Linux + - name: Upload Release Asset Linux amd64 id: upload-release-asset-linux uses: actions/upload-release-asset@v1 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: upload_url: ${{ steps.create_release.outputs.upload_url }} - asset_path: artifacts/wasmer-ubuntu-latest/wasmer-linux-amd64.tar.gz + asset_path: artifacts/wasmer-linux-amd64/wasmer-linux-amd64.tar.gz asset_name: wasmer-linux-amd64.tar.gz asset_content_type: application/gzip - name: Upload Release Asset Mac @@ -196,9 +200,19 @@ jobs: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: upload_url: ${{ steps.create_release.outputs.upload_url }} - asset_path: artifacts/wasmer-macos-latest/wasmer-darwin-amd64.tar.gz + asset_path: artifacts/wasmer-macos-amd64/wasmer-darwin-amd64.tar.gz asset_name: wasmer-darwin-amd64.tar.gz asset_content_type: application/gzip + - name: Upload Release Asset Linux aarch64 + id: upload-release-asset-linux + uses: actions/upload-release-asset@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + upload_url: ${{ steps.create_release.outputs.upload_url }} + asset_path: artifacts/wasmer-linux-aarch64/wasmer-linux-aarch64.tar.gz + asset_name: wasmer-linux-aarch64.tar.gz + asset_content_type: application/gzip audit: name: Audit diff --git a/bors.toml b/bors.toml index 9f5dcadd6..78ca5a2f9 100644 --- a/bors.toml +++ b/bors.toml @@ -2,6 +2,7 @@ status = [ "Audit", "Code lint", "Test on linux", + "Test on linux-arm", "Test on macos", "Test on windows" ] From 2f532524a8ef0964d9f69a36f88bcb554ec5cb66 Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Fri, 18 Sep 2020 11:57:39 -0700 Subject: [PATCH 017/281] Deduplicate IDs for linux release steps --- .github/workflows/main.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/main.yaml b/.github/workflows/main.yaml index 1d2630688..e8faa233f 100644 --- a/.github/workflows/main.yaml +++ b/.github/workflows/main.yaml @@ -184,7 +184,7 @@ jobs: asset_name: wasmer-windows.exe asset_content_type: application/vnd.microsoft.portable-executable - name: Upload Release Asset Linux amd64 - id: upload-release-asset-linux + id: upload-release-asset-linux-amd64 uses: actions/upload-release-asset@v1 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} @@ -204,7 +204,7 @@ jobs: asset_name: wasmer-darwin-amd64.tar.gz asset_content_type: application/gzip - name: Upload Release Asset Linux aarch64 - id: upload-release-asset-linux + id: upload-release-asset-linux-aarch64 uses: actions/upload-release-asset@v1 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} From e38f8ba0bb7073130b26cfc90f247c0ad5df3988 Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Fri, 18 Sep 2020 14:27:36 -0700 Subject: [PATCH 018/281] Replace uses of `arm` with `aarch64` --- .github/workflows/main.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/main.yaml b/.github/workflows/main.yaml index e8faa233f..eae48e621 100644 --- a/.github/workflows/main.yaml +++ b/.github/workflows/main.yaml @@ -38,7 +38,7 @@ jobs: strategy: fail-fast: false matrix: - build: [linux, macos, windows, linux-arm] + build: [linux, macos, windows, linux-aarch64] include: - build: linux os: ubuntu-latest @@ -54,7 +54,7 @@ jobs: os: windows-latest rust: 1.45.2 artifact_name: 'wasmer-windows-amd64' - - build: linux-arm + - build: linux-aarch64 os: [self-hosted, linux, ARM64] rust: 1.45.2 llvm_url: 'https://github.com/llvm/llvm-project/releases/download/llvmorg-10.0.0/clang+llvm-10.0.0-aarch64-linux-gnu.tar.xz' From 6d4206a3c7b41502febbc761545378f427937348 Mon Sep 17 00:00:00 2001 From: Mark McCaskey <5770194+MarkMcCaskey@users.noreply.github.com> Date: Fri, 18 Sep 2020 14:30:15 -0700 Subject: [PATCH 019/281] Update bors.toml Co-authored-by: nlewycky --- bors.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bors.toml b/bors.toml index 78ca5a2f9..202fcf76c 100644 --- a/bors.toml +++ b/bors.toml @@ -2,7 +2,7 @@ status = [ "Audit", "Code lint", "Test on linux", - "Test on linux-arm", + "Test on linux-aarch64", "Test on macos", "Test on windows" ] From 921622451a2d3ba5bdb02cce21a0199d4dd6c02e Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 21 Sep 2020 07:10:47 +0000 Subject: [PATCH 020/281] Bump cbindgen from 0.14.4 to 0.14.5 Bumps [cbindgen](https://github.com/eqrion/cbindgen) from 0.14.4 to 0.14.5. - [Release notes](https://github.com/eqrion/cbindgen/releases) - [Changelog](https://github.com/eqrion/cbindgen/blob/master/CHANGES) - [Commits](https://github.com/eqrion/cbindgen/compare/v0.14.4...v0.14.5) Signed-off-by: dependabot-preview[bot] --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 99c06ddd1..8288ab4b1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -205,9 +205,9 @@ dependencies = [ [[package]] name = "cbindgen" -version = "0.14.4" +version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e783d38a7700989e0209d0b0ed224c34ade92d3603da0cf15dc502ebada685a6" +checksum = "0ddecdc62f915fce487fae1f599cc4cdccd6588d3402c537b77510afea66f7b2" dependencies = [ "clap", "heck", From 2e4e98500ed4c979aef753e2901c7f07cb2f2e9a Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 21 Sep 2020 07:11:46 +0000 Subject: [PATCH 021/281] Bump memoffset from 0.5.5 to 0.5.6 Bumps [memoffset](https://github.com/Gilnaa/memoffset) from 0.5.5 to 0.5.6. - [Release notes](https://github.com/Gilnaa/memoffset/releases) - [Commits](https://github.com/Gilnaa/memoffset/compare/v0.5.5...v0.5.6) Signed-off-by: dependabot-preview[bot] --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 99c06ddd1..e7ac6f314 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1052,9 +1052,9 @@ dependencies = [ [[package]] name = "memoffset" -version = "0.5.5" +version = "0.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c198b026e1bbf08a937e94c6c60f9ec4a2267f5b0d2eec9c1b21b061ce2be55f" +checksum = "043175f069eda7b85febe4a74abbaeff828d9f8b448515d3151a14a3542811aa" dependencies = [ "autocfg 1.0.0", ] From dfd50ee6ec43d09152ba5c275562d57364a690bd Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Mon, 21 Sep 2020 15:20:26 +0200 Subject: [PATCH 022/281] feat(c-api) Implement `wasm_importtype_delete`. --- lib/c-api/src/wasm_c_api/mod.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/c-api/src/wasm_c_api/mod.rs b/lib/c-api/src/wasm_c_api/mod.rs index 8e14c34cd..79737d3ac 100644 --- a/lib/c-api/src/wasm_c_api/mod.rs +++ b/lib/c-api/src/wasm_c_api/mod.rs @@ -1869,6 +1869,9 @@ pub extern "C" fn wasm_importtype_type( unsafe { et.extern_type.as_ref() } } +#[no_mangle] +pub unsafe extern "C" fn wasm_importtype_delete(_importtype: Option>) {} + impl From for wasm_importtype_t { fn from(other: ImportType) -> Self { (&other).into() From 7cafae2b96bcc566b6f0415b349d19d6aee8e9fe Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Tue, 22 Sep 2020 09:35:01 +0200 Subject: [PATCH 023/281] feat(c-api) Reorganize the crate to put the Wasmer C API as deprecated code. --- lib/c-api/src/{ => deprecated}/export.rs | 10 +- lib/c-api/src/{ => deprecated}/global.rs | 7 +- .../src/{ => deprecated}/import/emscripten.rs | 2 +- lib/c-api/src/{ => deprecated}/import/mod.rs | 7 +- lib/c-api/src/{ => deprecated}/import/wasi.rs | 6 +- lib/c-api/src/{ => deprecated}/instance.rs | 7 +- lib/c-api/src/{ => deprecated}/memory.rs | 8 +- lib/c-api/src/deprecated/mod.rs | 180 ++++++++++++++++ lib/c-api/src/{ => deprecated}/module.rs | 11 +- lib/c-api/src/{ => deprecated}/table.rs | 5 +- lib/c-api/src/{ => deprecated}/trampoline.rs | 0 lib/c-api/src/{ => deprecated}/value.rs | 0 lib/c-api/src/lib.rs | 192 +----------------- lib/c-api/src/wasm_c_api/mod.rs | 2 + 14 files changed, 219 insertions(+), 218 deletions(-) rename lib/c-api/src/{ => deprecated}/export.rs (98%) rename lib/c-api/src/{ => deprecated}/global.rs (94%) rename lib/c-api/src/{ => deprecated}/import/emscripten.rs (99%) rename lib/c-api/src/{ => deprecated}/import/mod.rs (99%) rename lib/c-api/src/{ => deprecated}/import/wasi.rs (98%) rename lib/c-api/src/{ => deprecated}/instance.rs (99%) rename lib/c-api/src/{ => deprecated}/memory.rs (97%) create mode 100644 lib/c-api/src/deprecated/mod.rs rename lib/c-api/src/{ => deprecated}/module.rs (98%) rename lib/c-api/src/{ => deprecated}/table.rs (95%) rename lib/c-api/src/{ => deprecated}/trampoline.rs (100%) rename lib/c-api/src/{ => deprecated}/value.rs (100%) diff --git a/lib/c-api/src/export.rs b/lib/c-api/src/deprecated/export.rs similarity index 98% rename from lib/c-api/src/export.rs rename to lib/c-api/src/deprecated/export.rs index d2cb31469..f9a39670a 100644 --- a/lib/c-api/src/export.rs +++ b/lib/c-api/src/deprecated/export.rs @@ -1,8 +1,7 @@ //! Create, read, destroy export definitions (function, global, memory //! and table) on an instance. -use crate::{ - error::{update_last_error, CApiError}, +use crate::deprecated::{ global::wasmer_global_t, import::wasmer_import_func_t, instance::CAPIInstance, @@ -12,6 +11,7 @@ use crate::{ value::{wasmer_value, wasmer_value_t, wasmer_value_tag}, wasmer_byte_array, wasmer_result_t, }; +use crate::error::{update_last_error, CApiError}; use libc::{c_int, c_uint}; use std::ptr::{self, NonNull}; use std::slice; @@ -41,9 +41,9 @@ pub struct wasmer_export_func_t; /// exposed to C. pub(crate) struct NamedExports(pub Vec); -/// Opaque pointer to the opaque structure `crate::NamedExports`, -/// which is a wrapper around a vector of the opaque structure -/// `crate::NamedExport`. +/// Opaque pointer to the opaque structure +/// `crate::deprecated::NamedExports`, which is a wrapper around a +/// vector of the opaque structure `crate::deprecated::NamedExport`. /// /// Check the `wasmer_instance_exports()` function to learn more. #[repr(C)] diff --git a/lib/c-api/src/global.rs b/lib/c-api/src/deprecated/global.rs similarity index 94% rename from lib/c-api/src/global.rs rename to lib/c-api/src/deprecated/global.rs index 694bce40b..b6d007fd7 100644 --- a/lib/c-api/src/global.rs +++ b/lib/c-api/src/deprecated/global.rs @@ -1,7 +1,10 @@ //! Create, set, get and destroy global variables of an instance. +use crate::deprecated::{ + get_global_store, + value::{wasmer_value_t, wasmer_value_tag}, +}; use crate::error::update_last_error; -use crate::value::{wasmer_value_t, wasmer_value_tag}; use std::ptr::NonNull; use wasmer::Global; @@ -20,7 +23,7 @@ pub struct wasmer_global_t; /// The caller owns the object and should call `wasmer_global_destroy` to free it. #[no_mangle] pub extern "C" fn wasmer_global_new(value: wasmer_value_t, mutable: bool) -> *mut wasmer_global_t { - let store = crate::get_global_store(); + let store = get_global_store(); let global = if mutable { Global::new_mut(store, value.into()) } else { diff --git a/lib/c-api/src/import/emscripten.rs b/lib/c-api/src/deprecated/import/emscripten.rs similarity index 99% rename from lib/c-api/src/import/emscripten.rs rename to lib/c-api/src/deprecated/import/emscripten.rs index 771c8f6c9..4f7ca5f6d 100644 --- a/lib/c-api/src/import/emscripten.rs +++ b/lib/c-api/src/deprecated/import/emscripten.rs @@ -1,7 +1,7 @@ //! Functions and types for dealing with Emscripten imports use super::*; -use crate::{ +use crate::deprecated::{ get_slice_checked, instance::{wasmer_instance_t, CAPIInstance}, module::wasmer_module_t, diff --git a/lib/c-api/src/import/mod.rs b/lib/c-api/src/deprecated/import/mod.rs similarity index 99% rename from lib/c-api/src/import/mod.rs rename to lib/c-api/src/deprecated/import/mod.rs index d9fab34ee..09eb562c0 100644 --- a/lib/c-api/src/import/mod.rs +++ b/lib/c-api/src/deprecated/import/mod.rs @@ -1,14 +1,15 @@ //! Create, read, destroy import definitions (function, global, memory //! and table) on an instance. -use crate::{ - error::{update_last_error, CApiError}, +use crate::deprecated::{ export::{wasmer_import_export_kind, wasmer_import_export_value}, + get_global_store, instance::{wasmer_instance_context_t, CAPIInstance}, module::wasmer_module_t, value::wasmer_value_tag, wasmer_byte_array, wasmer_result_t, }; +use crate::error::{update_last_error, CApiError}; use libc::c_uint; use std::ffi::{c_void, CStr}; use std::os::raw::c_char; @@ -687,7 +688,7 @@ pub unsafe extern "C" fn wasmer_import_func_new( let returns: Vec = returns.iter().cloned().map(|x| x.into()).collect(); let func_type = FunctionType::new(params, &returns[..]); - let store = crate::get_global_store(); + let store = get_global_store(); let env_ptr = Box::into_raw(Box::new(LegacyEnv::default())); diff --git a/lib/c-api/src/import/wasi.rs b/lib/c-api/src/deprecated/import/wasi.rs similarity index 98% rename from lib/c-api/src/import/wasi.rs rename to lib/c-api/src/deprecated/import/wasi.rs index d1d131894..77196a60e 100644 --- a/lib/c-api/src/import/wasi.rs +++ b/lib/c-api/src/deprecated/import/wasi.rs @@ -1,5 +1,5 @@ use super::*; -use crate::get_slice_checked; +use crate::deprecated::{get_global_store, get_slice_checked}; use libc::c_uchar; use std::path::PathBuf; use std::ptr; @@ -174,7 +174,7 @@ fn wasmer_wasi_generate_import_object_inner( _ => panic!("Version {:?} is invalid.", version), }; - let store = crate::get_global_store(); + let store = get_global_store(); let mut wasi_state_builder = wasi::WasiState::new( arg_vec @@ -209,7 +209,7 @@ fn wasmer_wasi_generate_import_object_inner( #[no_mangle] pub unsafe extern "C" fn wasmer_wasi_generate_default_import_object() -> *mut wasmer_import_object_t { - let store = crate::get_global_store(); + let store = get_global_store(); let mut wasi_state_builder = wasi::WasiState::new("wasmer-wasi-default-program-name"); let wasi_state = wasi_state_builder.build().unwrap(); let mut wasi_env = wasi::WasiEnv::new(wasi_state); diff --git a/lib/c-api/src/instance.rs b/lib/c-api/src/deprecated/instance.rs similarity index 99% rename from lib/c-api/src/instance.rs rename to lib/c-api/src/deprecated/instance.rs index 0790cefab..50efc3c03 100644 --- a/lib/c-api/src/instance.rs +++ b/lib/c-api/src/deprecated/instance.rs @@ -1,13 +1,14 @@ //! Instantiate a module, call functions, and read exports. -use crate::{ - error::{update_last_error, CApiError}, +use crate::deprecated::{ export::{wasmer_exports_t, wasmer_import_export_kind, NamedExport, NamedExports}, + get_global_store, import::{wasmer_import_t, FunctionWrapper}, memory::wasmer_memory_t, value::{wasmer_value, wasmer_value_t, wasmer_value_tag}, wasmer_result_t, }; +use crate::error::{update_last_error, CApiError}; use libc::{c_char, c_int, c_void}; use std::collections::HashMap; use std::ffi::CStr; @@ -191,7 +192,7 @@ pub unsafe extern "C" fn wasmer_instantiate( } let bytes: &[u8] = slice::from_raw_parts_mut(wasm_bytes.as_ptr(), wasm_bytes_len as usize); - let store = crate::get_global_store(); + let store = get_global_store(); let module_result = Module::from_binary(store, bytes); let module = match module_result { diff --git a/lib/c-api/src/memory.rs b/lib/c-api/src/deprecated/memory.rs similarity index 97% rename from lib/c-api/src/memory.rs rename to lib/c-api/src/deprecated/memory.rs index 8f0e92005..1c5393930 100644 --- a/lib/c-api/src/memory.rs +++ b/lib/c-api/src/deprecated/memory.rs @@ -1,9 +1,7 @@ //! Create, read, write, grow, destroy memory of an instance. -use crate::{ - error::{update_last_error, CApiError}, - wasmer_limits_t, wasmer_result_t, -}; +use crate::deprecated::{get_global_store, wasmer_limits_t, wasmer_result_t}; +use crate::error::{update_last_error, CApiError}; use std::{cell::Cell, ptr}; use wasmer::{Bytes, Memory, MemoryType, Pages}; @@ -67,7 +65,7 @@ pub unsafe extern "C" fn wasmer_memory_new( } else { None }; - let store = crate::get_global_store(); + let store = get_global_store(); let desc = MemoryType::new(Pages(limits.min), max, false); match Memory::new(store, desc) { Ok(new_memory) => { diff --git a/lib/c-api/src/deprecated/mod.rs b/lib/c-api/src/deprecated/mod.rs new file mode 100644 index 000000000..1c5e33d0a --- /dev/null +++ b/lib/c-api/src/deprecated/mod.rs @@ -0,0 +1,180 @@ +//! # Wasmer Runtime C API +//! +//! Wasmer is a standalone JIT WebAssembly runtime, aiming to be fully +//! compatible with Emscripten, Rust and Go. [Learn +//! more](https://github.com/wasmerio/wasmer). +//! +//! This crate exposes a C and C++ API for the Wasmer runtime. +//! +//! # Usage +//! +//! The C and C++ header files can be found in the source tree of this +//! crate, respectively [`wasmer.h`][wasmer_h] and +//! [`wasmer.hh`][wasmer_hh]. They are automatically generated, and always +//! up-to-date in this repository. +//! +//! Here is a simple example to use the C API: +//! +//! ```c +//! #include +//! #include "wasmer.h" +//! #include +//! #include +//! +//! int main() +//! { +//! // Read the Wasm file bytes. +//! FILE *file = fopen("sum.wasm", "r"); +//! fseek(file, 0, SEEK_END); +//! long len = ftell(file); +//! uint8_t *bytes = malloc(len); +//! fseek(file, 0, SEEK_SET); +//! fread(bytes, 1, len, file); +//! fclose(file); +//! +//! // Prepare the imports. +//! wasmer_import_t imports[] = {}; +//! +//! // Instantiate! +//! wasmer_instance_t *instance = NULL; +//! wasmer_result_t instantiation_result = wasmer_instantiate(&instance, bytes, len, imports, 0); +//! +//! assert(instantiation_result == WASMER_OK); +//! +//! // Let's call a function. +//! // Start by preparing the arguments. +//! +//! // Value of argument #1 is `7i32`. +//! wasmer_value_t argument_one; +//! argument_one.tag = WASM_I32; +//! argument_one.value.I32 = 7; +//! +//! // Value of argument #2 is `8i32`. +//! wasmer_value_t argument_two; +//! argument_two.tag = WASM_I32; +//! argument_two.value.I32 = 8; +//! +//! // Prepare the arguments. +//! wasmer_value_t arguments[] = {argument_one, argument_two}; +//! +//! // Prepare the return value. +//! wasmer_value_t result_one; +//! wasmer_value_t results[] = {result_one}; +//! +//! // Call the `sum` function with the prepared arguments and the return value. +//! wasmer_result_t call_result = wasmer_instance_call(instance, "sum", arguments, 2, results, 1); +//! +//! // Let's display the result. +//! printf("Call result: %d\n", call_result); +//! printf("Result: %d\n", results[0].value.I32); +//! +//! // `sum(7, 8) == 15`. +//! assert(results[0].value.I32 == 15); +//! assert(call_result == WASMER_OK); +//! +//! wasmer_instance_destroy(instance); +//! +//! return 0; +//! } +//! ``` +//! +//! [wasmer_h]: ./wasmer.h +//! [wasmer_hh]: ./wasmer.hh + +use lazy_static::lazy_static; + +pub mod export; +pub mod global; +pub mod import; +pub mod instance; +pub mod memory; +pub mod module; +pub mod table; +// `not(target_family = "windows")` is simpler than `unix`. See build.rs +// if you want to change the meaning of these `cfg`s in the header file. +/* +TODO: reenable `trampoline` module when the refactor gains feature parity with Wasmer master +#[cfg(all(not(target_family = "windows"), target_arch = "x86_64"))] +pub mod trampoline;*/ +pub mod value; + +/// The `wasmer_result_t` enum is a type that represents either a +/// success, or a failure. +#[allow(non_camel_case_types)] +#[repr(C)] +pub enum wasmer_result_t { + /// Represents a success. + WASMER_OK = 1, + + /// Represents a failure. + WASMER_ERROR = 2, +} + +/// The `wasmer_limits_t` struct is a type that describes the limits of something +/// such as a memory or a table. See the `wasmer_memory_new()` function to get +/// more information. +#[repr(C)] +pub struct wasmer_limits_t { + /// The minimum number of allowed pages. + pub min: u32, + + /// The maximum number of allowed pages. + pub max: wasmer_limit_option_t, +} + +/// The `wasmer_limit_option_t` struct represents an optional limit +/// for `wasmer_limits_t`. +#[repr(C)] +pub struct wasmer_limit_option_t { + /// Whether the limit is set. + pub has_some: bool, + + /// The limit value. + pub some: u32, +} + +#[repr(C)] +pub struct wasmer_byte_array { + pub bytes: *const u8, + pub bytes_len: u32, +} + +impl wasmer_byte_array { + /// Get the data as a slice + pub unsafe fn as_slice<'a>(&self) -> &'a [u8] { + get_slice_checked(self.bytes, self.bytes_len as usize) + } + + /// Copy the data into an owned Vec + pub unsafe fn as_vec(&self) -> Vec { + let mut out = Vec::with_capacity(self.bytes_len as usize); + out.extend_from_slice(self.as_slice()); + + out + } + + /// Read the data as a &str, returns an error if the string is not valid UTF8 + pub unsafe fn as_str<'a>(&self) -> Result<&'a str, std::str::Utf8Error> { + std::str::from_utf8(self.as_slice()) + } +} + +/// Gets a slice from a pointer and a length, returning an empty slice if the +/// pointer is null +#[inline] +pub(crate) unsafe fn get_slice_checked<'a, T>(ptr: *const T, len: usize) -> &'a [T] { + if ptr.is_null() { + &[] + } else { + std::slice::from_raw_parts(ptr, len) + } +} + +lazy_static! { + pub(crate) static ref GLOBAL_STORE: wasmer::Store = + wasmer::Store::new(&*crate::wasm_c_api::wasm_engine_new().inner); +} + +pub(crate) fn get_global_store() -> &'static wasmer::Store { + &*GLOBAL_STORE +} diff --git a/lib/c-api/src/module.rs b/lib/c-api/src/deprecated/module.rs similarity index 98% rename from lib/c-api/src/module.rs rename to lib/c-api/src/deprecated/module.rs index dd07594b7..4a160898b 100644 --- a/lib/c-api/src/module.rs +++ b/lib/c-api/src/deprecated/module.rs @@ -1,12 +1,13 @@ //! Compile, validate, instantiate, serialize, and destroy modules. -use crate::{ - error::{update_last_error, CApiError}, +use crate::deprecated::{ export::wasmer_import_export_kind, + get_global_store, import::{wasmer_import_object_t, wasmer_import_t, CAPIImportObject}, instance::{wasmer_instance_t, CAPIInstance}, wasmer_byte_array, wasmer_result_t, }; +use crate::error::{update_last_error, CApiError}; use libc::c_int; use std::collections::HashMap; use std::ptr::NonNull; @@ -33,7 +34,7 @@ pub unsafe extern "C" fn wasmer_compile( wasm_bytes_len: u32, ) -> wasmer_result_t { let bytes: &[u8] = slice::from_raw_parts_mut(wasm_bytes, wasm_bytes_len as usize); - let store = crate::get_global_store(); + let store = get_global_store(); let result = Module::from_binary(store, bytes); let new_module = match result { Ok(instance) => instance, @@ -68,7 +69,7 @@ pub unsafe extern "C" fn wasmer_validate(wasm_bytes: *const u8, wasm_bytes_len: let bytes: &[u8] = slice::from_raw_parts(wasm_bytes, wasm_bytes_len as usize); - let store = crate::get_global_store(); + let store = get_global_store(); Module::validate(store, bytes).is_ok() } @@ -297,7 +298,7 @@ pub unsafe extern "C" fn wasmer_module_deserialize( return wasmer_result_t::WASMER_ERROR; }; - let store = crate::get_global_store(); + let store = get_global_store(); match Module::deserialize(store, serialized_module) { Ok(deserialized_module) => { diff --git a/lib/c-api/src/table.rs b/lib/c-api/src/deprecated/table.rs similarity index 95% rename from lib/c-api/src/table.rs rename to lib/c-api/src/deprecated/table.rs index 1861daf1f..d6da3fce1 100644 --- a/lib/c-api/src/table.rs +++ b/lib/c-api/src/deprecated/table.rs @@ -1,6 +1,7 @@ //! Create, grow, destroy tables of an instance. -use crate::{error::update_last_error, wasmer_limits_t, wasmer_result_t}; +use crate::deprecated::{get_global_store, wasmer_limits_t, wasmer_result_t}; +use crate::error::update_last_error; use std::ptr::NonNull; use wasmer::{ExternRef, Table, TableType, Val, ValType}; @@ -45,7 +46,7 @@ pub unsafe extern "C" fn wasmer_table_new( minimum: limits.min, maximum: max, }; - let store = crate::get_global_store(); + let store = get_global_store(); let result = Table::new(store, desc, get_default_table_value(ValType::FuncRef)); let new_table = match result { Ok(table) => table, diff --git a/lib/c-api/src/trampoline.rs b/lib/c-api/src/deprecated/trampoline.rs similarity index 100% rename from lib/c-api/src/trampoline.rs rename to lib/c-api/src/deprecated/trampoline.rs diff --git a/lib/c-api/src/value.rs b/lib/c-api/src/deprecated/value.rs similarity index 100% rename from lib/c-api/src/value.rs rename to lib/c-api/src/deprecated/value.rs diff --git a/lib/c-api/src/lib.rs b/lib/c-api/src/lib.rs index 3e6808c5f..21f8d496a 100644 --- a/lib/c-api/src/lib.rs +++ b/lib/c-api/src/lib.rs @@ -2,89 +2,6 @@ #![doc(html_logo_url = "https://avatars3.githubusercontent.com/u/44205449?s=200&v=4")] // temporary while in transition #![allow(unused_variables)] - -//! # Wasmer Runtime C API -//! -//! Wasmer is a standalone JIT WebAssembly runtime, aiming to be fully -//! compatible with Emscripten, Rust and Go. [Learn -//! more](https://github.com/wasmerio/wasmer). -//! -//! This crate exposes a C and C++ API for the Wasmer runtime. -//! -//! # Usage -//! -//! The C and C++ header files can be found in the source tree of this -//! crate, respectively [`wasmer.h`][wasmer_h] and -//! [`wasmer.hh`][wasmer_hh]. They are automatically generated, and always -//! up-to-date in this repository. -//! -//! Here is a simple example to use the C API: -//! -//! ```c -//! #include -//! #include "wasmer.h" -//! #include -//! #include -//! -//! int main() -//! { -//! // Read the Wasm file bytes. -//! FILE *file = fopen("sum.wasm", "r"); -//! fseek(file, 0, SEEK_END); -//! long len = ftell(file); -//! uint8_t *bytes = malloc(len); -//! fseek(file, 0, SEEK_SET); -//! fread(bytes, 1, len, file); -//! fclose(file); -//! -//! // Prepare the imports. -//! wasmer_import_t imports[] = {}; -//! -//! // Instantiate! -//! wasmer_instance_t *instance = NULL; -//! wasmer_result_t instantiation_result = wasmer_instantiate(&instance, bytes, len, imports, 0); -//! -//! assert(instantiation_result == WASMER_OK); -//! -//! // Let's call a function. -//! // Start by preparing the arguments. -//! -//! // Value of argument #1 is `7i32`. -//! wasmer_value_t argument_one; -//! argument_one.tag = WASM_I32; -//! argument_one.value.I32 = 7; -//! -//! // Value of argument #2 is `8i32`. -//! wasmer_value_t argument_two; -//! argument_two.tag = WASM_I32; -//! argument_two.value.I32 = 8; -//! -//! // Prepare the arguments. -//! wasmer_value_t arguments[] = {argument_one, argument_two}; -//! -//! // Prepare the return value. -//! wasmer_value_t result_one; -//! wasmer_value_t results[] = {result_one}; -//! -//! // Call the `sum` function with the prepared arguments and the return value. -//! wasmer_result_t call_result = wasmer_instance_call(instance, "sum", arguments, 2, results, 1); -//! -//! // Let's display the result. -//! printf("Call result: %d\n", call_result); -//! printf("Result: %d\n", results[0].value.I32); -//! -//! // `sum(7, 8) == 15`. -//! assert(results[0].value.I32 == 15); -//! assert(call_result == WASMER_OK); -//! -//! wasmer_instance_destroy(instance); -//! -//! return 0; -//! } -//! ``` -//! -//! [wasmer_h]: ./wasmer.h -//! [wasmer_hh]: ./wasmer.hh #![deny( dead_code, unused_imports, @@ -94,111 +11,8 @@ unreachable_patterns )] -#[allow(unused_imports)] -#[macro_use] -extern crate cfg_if; -#[macro_use] -extern crate lazy_static; -#[macro_use] -extern crate thiserror; - +pub mod deprecated; +pub mod error; +mod ordered_resolver; /// cbindgen:ignore pub mod wasm_c_api; - -pub mod error; -pub mod export; -pub mod global; -pub mod import; -pub mod instance; -pub mod memory; -pub mod module; -mod ordered_resolver; -pub mod table; -// `not(target_family = "windows")` is simpler than `unix`. See build.rs -// if you want to change the meaning of these `cfg`s in the header file. -/* -TODO: reenable `trampoline` module when the refactor gains feature parity with Wasmer master -#[cfg(all(not(target_family = "windows"), target_arch = "x86_64"))] -pub mod trampoline;*/ -pub mod value; - -/// The `wasmer_result_t` enum is a type that represents either a -/// success, or a failure. -#[allow(non_camel_case_types)] -#[repr(C)] -pub enum wasmer_result_t { - /// Represents a success. - WASMER_OK = 1, - - /// Represents a failure. - WASMER_ERROR = 2, -} - -/// The `wasmer_limits_t` struct is a type that describes the limits of something -/// such as a memory or a table. See the `wasmer_memory_new()` function to get -/// more information. -#[repr(C)] -pub struct wasmer_limits_t { - /// The minimum number of allowed pages. - pub min: u32, - - /// The maximum number of allowed pages. - pub max: wasmer_limit_option_t, -} - -/// The `wasmer_limit_option_t` struct represents an optional limit -/// for `wasmer_limits_t`. -#[repr(C)] -pub struct wasmer_limit_option_t { - /// Whether the limit is set. - pub has_some: bool, - - /// The limit value. - pub some: u32, -} - -#[repr(C)] -pub struct wasmer_byte_array { - pub bytes: *const u8, - pub bytes_len: u32, -} - -impl wasmer_byte_array { - /// Get the data as a slice - pub unsafe fn as_slice<'a>(&self) -> &'a [u8] { - get_slice_checked(self.bytes, self.bytes_len as usize) - } - - /// Copy the data into an owned Vec - pub unsafe fn as_vec(&self) -> Vec { - let mut out = Vec::with_capacity(self.bytes_len as usize); - out.extend_from_slice(self.as_slice()); - - out - } - - /// Read the data as a &str, returns an error if the string is not valid UTF8 - pub unsafe fn as_str<'a>(&self) -> Result<&'a str, std::str::Utf8Error> { - std::str::from_utf8(self.as_slice()) - } -} - -/// Gets a slice from a pointer and a length, returning an empty slice if the -/// pointer is null -#[inline] -pub(crate) unsafe fn get_slice_checked<'a, T>(ptr: *const T, len: usize) -> &'a [T] { - if ptr.is_null() { - &[] - } else { - std::slice::from_raw_parts(ptr, len) - } -} - -lazy_static! { - pub(crate) static ref GLOBAL_STORE: wasmer::Store = - wasmer::Store::new(&*crate::wasm_c_api::wasm_engine_new().inner); -} - -pub(crate) fn get_global_store() -> &'static wasmer::Store { - &*GLOBAL_STORE -} diff --git a/lib/c-api/src/wasm_c_api/mod.rs b/lib/c-api/src/wasm_c_api/mod.rs index 8e14c34cd..232484138 100644 --- a/lib/c-api/src/wasm_c_api/mod.rs +++ b/lib/c-api/src/wasm_c_api/mod.rs @@ -1,11 +1,13 @@ //! entrypoints for the standard C API +use cfg_if::cfg_if; use std::convert::{TryFrom, TryInto}; use std::ffi::c_void; use std::mem; use std::ptr::{self, NonNull}; use std::slice; use std::sync::Arc; +use thiserror::Error; pub(crate) mod utils; #[cfg(feature = "wasi")] From a6e06278d8a6d7c8a2c61b5127c064f509c8921d Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Tue, 22 Sep 2020 09:35:57 +0200 Subject: [PATCH 024/281] doc(c-api) Reorganize the documentation. --- lib/c-api/doc/{ => deprecated}/index.md | 0 lib/c-api/doc/{ => deprecated}/theme/css/wasmer.css | 0 lib/c-api/doc/{ => deprecated}/theme/footer.html | 0 lib/c-api/doc/{ => deprecated}/theme/header.html | 0 4 files changed, 0 insertions(+), 0 deletions(-) rename lib/c-api/doc/{ => deprecated}/index.md (100%) rename lib/c-api/doc/{ => deprecated}/theme/css/wasmer.css (100%) rename lib/c-api/doc/{ => deprecated}/theme/footer.html (100%) rename lib/c-api/doc/{ => deprecated}/theme/header.html (100%) diff --git a/lib/c-api/doc/index.md b/lib/c-api/doc/deprecated/index.md similarity index 100% rename from lib/c-api/doc/index.md rename to lib/c-api/doc/deprecated/index.md diff --git a/lib/c-api/doc/theme/css/wasmer.css b/lib/c-api/doc/deprecated/theme/css/wasmer.css similarity index 100% rename from lib/c-api/doc/theme/css/wasmer.css rename to lib/c-api/doc/deprecated/theme/css/wasmer.css diff --git a/lib/c-api/doc/theme/footer.html b/lib/c-api/doc/deprecated/theme/footer.html similarity index 100% rename from lib/c-api/doc/theme/footer.html rename to lib/c-api/doc/deprecated/theme/footer.html diff --git a/lib/c-api/doc/theme/header.html b/lib/c-api/doc/deprecated/theme/header.html similarity index 100% rename from lib/c-api/doc/theme/header.html rename to lib/c-api/doc/deprecated/theme/header.html From 40db7d6efc67894da838a0f438998caba16e1551 Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Tue, 22 Sep 2020 09:44:11 +0200 Subject: [PATCH 025/281] doc(c-api) Reorganize doxygen. --- lib/c-api/.gitignore | 2 +- lib/c-api/doc/deprecated/README.md | 8 ++++++++ lib/c-api/{ => doc/deprecated}/doxyfile | 16 ++++++++-------- 3 files changed, 17 insertions(+), 9 deletions(-) create mode 100644 lib/c-api/doc/deprecated/README.md rename lib/c-api/{ => doc/deprecated}/doxyfile (97%) diff --git a/lib/c-api/.gitignore b/lib/c-api/.gitignore index baf7545df..66de34fca 100644 --- a/lib/c-api/.gitignore +++ b/lib/c-api/.gitignore @@ -1 +1 @@ -doc/html/ \ No newline at end of file +doc/deprecated/html/ \ No newline at end of file diff --git a/lib/c-api/doc/deprecated/README.md b/lib/c-api/doc/deprecated/README.md new file mode 100644 index 000000000..f3d38e2af --- /dev/null +++ b/lib/c-api/doc/deprecated/README.md @@ -0,0 +1,8 @@ +# Compile the documentation + +Run `doxygen` in this directory: + +```sh +$ doxygen +$ open html/index.html +``` diff --git a/lib/c-api/doxyfile b/lib/c-api/doc/deprecated/doxyfile similarity index 97% rename from lib/c-api/doxyfile rename to lib/c-api/doc/deprecated/doxyfile index 1ff7911ba..fa289b1e6 100644 --- a/lib/c-api/doxyfile +++ b/lib/c-api/doc/deprecated/doxyfile @@ -7,8 +7,8 @@ DOXYFILE_ENCODING = UTF-8 PROJECT_NAME = "wasmer-c-api" PROJECT_NUMBER = PROJECT_BRIEF = -PROJECT_LOGO = ../../assets/logo.png -OUTPUT_DIRECTORY = doc/ +PROJECT_LOGO = ../../../../assets/logo.png +OUTPUT_DIRECTORY = . CREATE_SUBDIRS = NO ALLOW_UNICODE_NAMES = NO OUTPUT_LANGUAGE = English @@ -116,8 +116,8 @@ WARN_LOGFILE = #--------------------------------------------------------------------------- # Configuration options related to the input files #--------------------------------------------------------------------------- -INPUT = doc/index.md -INPUT += wasmer.h +INPUT = index.md +INPUT += ../../wasmer.h INPUT_ENCODING = UTF-8 FILE_PATTERNS = *.h \ *.hh @@ -134,7 +134,7 @@ INPUT_FILTER = FILTER_PATTERNS = FILTER_SOURCE_FILES = NO FILTER_SOURCE_PATTERNS = -USE_MDFILE_AS_MAINPAGE = doc/index.md +USE_MDFILE_AS_MAINPAGE = index.md #--------------------------------------------------------------------------- # Configuration options related to source browsing #--------------------------------------------------------------------------- @@ -159,10 +159,10 @@ IGNORE_PREFIX = GENERATE_HTML = YES HTML_OUTPUT = html HTML_FILE_EXTENSION = .html -HTML_HEADER = doc/theme/header.html -HTML_FOOTER = doc/theme/footer.html +HTML_HEADER = theme/header.html +HTML_FOOTER = theme/footer.html HTML_STYLESHEET = -HTML_EXTRA_STYLESHEET = doc/theme/css/wasmer.css +HTML_EXTRA_STYLESHEET = theme/css/wasmer.css HTML_EXTRA_FILES = HTML_COLORSTYLE_HUE = 220 HTML_COLORSTYLE_SAT = 100 From 2ac20265a460a4791ca1e16361d62f8e1a563d35 Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Tue, 22 Sep 2020 09:44:42 +0200 Subject: [PATCH 026/281] chore(c-api) Update header files. --- lib/c-api/wasmer.h | 6 +++--- lib/c-api/wasmer.hh | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/c-api/wasmer.h b/lib/c-api/wasmer.h index 807a1f177..a3d2a0910 100644 --- a/lib/c-api/wasmer.h +++ b/lib/c-api/wasmer.h @@ -255,9 +255,9 @@ typedef struct { } wasmer_memory_t; /** - * Opaque pointer to the opaque structure `crate::NamedExports`, - * which is a wrapper around a vector of the opaque structure - * `crate::NamedExport`. + * Opaque pointer to the opaque structure + * `crate::deprecated::NamedExports`, which is a wrapper around a + * vector of the opaque structure `crate::deprecated::NamedExport`. * * Check the `wasmer_instance_exports()` function to learn more. */ diff --git a/lib/c-api/wasmer.hh b/lib/c-api/wasmer.hh index 3ca704f8a..c44a7d60c 100644 --- a/lib/c-api/wasmer.hh +++ b/lib/c-api/wasmer.hh @@ -195,9 +195,9 @@ struct wasmer_memory_t { }; -/// Opaque pointer to the opaque structure `crate::NamedExports`, -/// which is a wrapper around a vector of the opaque structure -/// `crate::NamedExport`. +/// Opaque pointer to the opaque structure +/// `crate::deprecated::NamedExports`, which is a wrapper around a +/// vector of the opaque structure `crate::deprecated::NamedExport`. /// /// Check the `wasmer_instance_exports()` function to learn more. struct wasmer_exports_t { From 8c03da87a987c1609bbb5de9c310b65043d8fe43 Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Tue, 22 Sep 2020 13:14:48 +0200 Subject: [PATCH 027/281] feat(c-api) Reorganize the `build.rs` script. --- lib/c-api/build.rs | 165 +++++++++++++++++++++++++++------------------ 1 file changed, 101 insertions(+), 64 deletions(-) diff --git a/lib/c-api/build.rs b/lib/c-api/build.rs index 25d2d531f..b8fa9fe03 100644 --- a/lib/c-api/build.rs +++ b/lib/c-api/build.rs @@ -1,22 +1,7 @@ -extern crate cbindgen; - use cbindgen::{Builder, Language}; use std::{env, fs, path::PathBuf}; -fn main() { - let crate_dir = env::var("CARGO_MANIFEST_DIR").unwrap(); - let mut crate_wasmer_header_file = PathBuf::from(&crate_dir); - crate_wasmer_header_file.push("wasmer"); - - let out_dir = env::var("OUT_DIR").unwrap(); - let mut out_wasmer_header_file = PathBuf::from(&out_dir); - out_wasmer_header_file.push("wasmer"); - - let mut pre_header = r#" -#if !defined(WASMER_H_MACROS) - -#define WASMER_H_MACROS - +const PRE_HEADER: &'static str = r#" // Define the `ARCH_X86_X64` constant. #if defined(MSVC) && defined(_M_AMD64) # define ARCH_X86_64 @@ -40,67 +25,119 @@ fn main() { #elif defined(MSVC) || __has_declspec_attribute(deprecated) # define DEPRECATED(message) __declspec(deprecated(message)) #endif +"#; -"# - .to_string(); +const WASI_FEATURE_AS_C_DEFINE: &'static str = "WASMER_WASI_ENABLED"; +const EMSCRIPTEN_FEATURE_AS_C_DEFINE: &'static str = "WASMER_EMSCRIPTEN_ENABLED"; + +fn main() { + let crate_dir = env::var("CARGO_MANIFEST_DIR").unwrap(); + let out_dir = env::var("OUT_DIR").unwrap(); + + build_wasmer_headers(&crate_dir, &out_dir); +} + +fn build_wasmer_headers(crate_dir: &str, out_dir: &str) { + let mut crate_header_file = PathBuf::from(crate_dir); + crate_header_file.push("wasmer"); + + let mut out_header_file = PathBuf::from(out_dir); + out_header_file.push("wasmer"); + + let mut pre_header = format!( + r#"// The Wasmer C/C++ header file. + +#if !defined(WASMER_H_MACROS) + +#define WASMER_H_MACROS +{pre_header}"#, + pre_header = PRE_HEADER + ); #[cfg(feature = "wasi")] { - pre_header += "#define WASMER_WASI_ENABLED\n"; + pre_header.push_str(&format!( + r#" +// The `wasi` feature has been enabled for this build. +#define {define} + +"#, + define = WASI_FEATURE_AS_C_DEFINE + )); } #[cfg(feature = "emscripten")] { - pre_header += "#define WASMER_EMSCRIPTEN_ENABLED\n"; + pre_header.push_str(&format!( + r#" +// The `emscripten` feature has been enabled for this build. +#define {define} + +"#, + define = EMSCRIPTEN_FEATURE_AS_C_DEFINE + )); } // Close pre header. - pre_header += "#endif // WASMER_H_MACROS\n"; + pre_header.push_str( + r#"#endif // WASMER_H_MACROS - // Generate the C bindings in the `OUT_DIR`. - out_wasmer_header_file.set_extension("h"); - Builder::new() - .with_crate(crate_dir.clone()) - .with_language(Language::C) - .with_include_guard("WASMER_H") - .with_header(&pre_header) - .with_define("target_family", "windows", "_WIN32") - .with_define("target_arch", "x86_64", "ARCH_X86_64") - .with_define("feature", "wasi", "WASMER_WASI_ENABLED") - .with_define("feature", "emscripten", "WASMER_EMSCRIPTEN_ENABLED") - .generate() - .expect("Unable to generate C bindings") - .write_to_file(out_wasmer_header_file.as_path()); - // Generate the C++ bindings in the `OUT_DIR`. - out_wasmer_header_file.set_extension("hh"); - Builder::new() - .with_crate(crate_dir) - .with_language(Language::Cxx) - .with_include_guard("WASMER_H") - .with_header(&pre_header) - .with_define("target_family", "windows", "_WIN32") - .with_define("target_arch", "x86_64", "ARCH_X86_64") - .with_define("feature", "wasi", "WASMER_WASI_ENABLED") - .with_define("feature", "emscripten", "WASMER_EMSCRIPTEN_ENABLED") - .generate() - .expect("Unable to generate C++ bindings") - .write_to_file(out_wasmer_header_file.as_path()); +// +// OK, here we go. The code below is automatically generated. +// +"#, + ); - // Copy the generated C bindings from `OUT_DIR` to - // `CARGO_MANIFEST_DIR`. - crate_wasmer_header_file.set_extension("h"); - out_wasmer_header_file.set_extension("h"); - fs::copy( - out_wasmer_header_file.as_path(), - crate_wasmer_header_file.as_path(), - ) - .expect("Unable to copy the generated C bindings"); + // C bindings. + { + // Generate the bindings in the `OUT_DIR`. + out_header_file.set_extension("h"); - // Copy the generated C++ bindings from `OUT_DIR` to - // `CARGO_MANIFEST_DIR`. - crate_wasmer_header_file.set_extension("hh"); - out_wasmer_header_file.set_extension("hh"); - fs::copy(out_wasmer_header_file, crate_wasmer_header_file) - .expect("Unable to copy the generated C++ bindings"); + Builder::new() + .with_language(Language::C) + .with_crate(crate_dir) + .with_include_guard("WASMER_H") + .with_header(&pre_header) + .with_define("target_family", "windows", "_WIN32") + .with_define("target_arch", "x86_64", "ARCH_X86_64") + .with_define("feature", "wasi", WASI_FEATURE_AS_C_DEFINE) + .with_define("feature", "emscripten", EMSCRIPTEN_FEATURE_AS_C_DEFINE) + .generate() + .expect("Unable to generate C bindings") + .write_to_file(out_header_file.as_path()); + + // Copy the generated bindings from `OUT_DIR` to + // `CARGO_MANIFEST_DIR`. + crate_header_file.set_extension("h"); + + fs::copy(out_header_file.as_path(), crate_header_file.as_path()) + .expect("Unable to copy the generated C bindings"); + } + + // C++ bindings. + { + // Generate the bindings in the `OUT_DIR`. + out_header_file.set_extension("hh"); + + Builder::new() + .with_language(Language::Cxx) + .with_crate(crate_dir) + .with_include_guard("WASMER_H") + .with_header(&pre_header) + .with_define("target_family", "windows", "_WIN32") + .with_define("target_arch", "x86_64", "ARCH_X86_64") + .with_define("feature", "wasi", WASI_FEATURE_AS_C_DEFINE) + .with_define("feature", "emscripten", EMSCRIPTEN_FEATURE_AS_C_DEFINE) + .generate() + .expect("Unable to generate C++ bindings") + .write_to_file(out_header_file.as_path()); + + // Copy the generated bindings from `OUT_DIR` to + // `CARGO_MANIFEST_DIR`. + crate_header_file.set_extension("hh"); + + fs::copy(out_header_file, crate_header_file) + .expect("Unable to copy the generated C++ bindings"); + } } From a2ae54b446f868d4f2e46e52e534fd8f6f2671fd Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Tue, 22 Sep 2020 13:15:12 +0200 Subject: [PATCH 028/281] chore(c-api) Update the header files. --- lib/c-api/wasmer.h | 8 ++++++++ lib/c-api/wasmer.hh | 8 ++++++++ 2 files changed, 16 insertions(+) diff --git a/lib/c-api/wasmer.h b/lib/c-api/wasmer.h index a3d2a0910..6f5b60a1d 100644 --- a/lib/c-api/wasmer.h +++ b/lib/c-api/wasmer.h @@ -1,3 +1,4 @@ +// The Wasmer C/C++ header file. #if !defined(WASMER_H_MACROS) @@ -27,10 +28,17 @@ # define DEPRECATED(message) __declspec(deprecated(message)) #endif +// The `wasi` feature has been enabled for this build. #define WASMER_WASI_ENABLED + #endif // WASMER_H_MACROS +// +// OK, here we go. The code below is automatically generated. +// + + #ifndef WASMER_H #define WASMER_H diff --git a/lib/c-api/wasmer.hh b/lib/c-api/wasmer.hh index c44a7d60c..3d47face2 100644 --- a/lib/c-api/wasmer.hh +++ b/lib/c-api/wasmer.hh @@ -1,3 +1,4 @@ +// The Wasmer C/C++ header file. #if !defined(WASMER_H_MACROS) @@ -27,10 +28,17 @@ # define DEPRECATED(message) __declspec(deprecated(message)) #endif +// The `wasi` feature has been enabled for this build. #define WASMER_WASI_ENABLED + #endif // WASMER_H_MACROS +// +// OK, here we go. The code below is automatically generated. +// + + #ifndef WASMER_H #define WASMER_H From 9e8b80c2f6ab59f06b9bacb6c69951cdcfa7c024 Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Tue, 22 Sep 2020 13:18:18 +0200 Subject: [PATCH 029/281] feat(c-api) Ensure Rust documentation is used as C's. --- lib/c-api/build.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/c-api/build.rs b/lib/c-api/build.rs index b8fa9fe03..dd76b1186 100644 --- a/lib/c-api/build.rs +++ b/lib/c-api/build.rs @@ -103,6 +103,7 @@ fn build_wasmer_headers(crate_dir: &str, out_dir: &str) { .with_define("target_arch", "x86_64", "ARCH_X86_64") .with_define("feature", "wasi", WASI_FEATURE_AS_C_DEFINE) .with_define("feature", "emscripten", EMSCRIPTEN_FEATURE_AS_C_DEFINE) + .with_documentation(true) .generate() .expect("Unable to generate C bindings") .write_to_file(out_header_file.as_path()); @@ -129,6 +130,7 @@ fn build_wasmer_headers(crate_dir: &str, out_dir: &str) { .with_define("target_arch", "x86_64", "ARCH_X86_64") .with_define("feature", "wasi", WASI_FEATURE_AS_C_DEFINE) .with_define("feature", "emscripten", EMSCRIPTEN_FEATURE_AS_C_DEFINE) + .with_documentation(true) .generate() .expect("Unable to generate C++ bindings") .write_to_file(out_header_file.as_path()); From 3514988462809ce6d3febfa44a7af37677aba870 Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Tue, 22 Sep 2020 16:54:22 +0200 Subject: [PATCH 030/281] feat(c-api) Generate `wasmer_wasm.h` automatically. First draft. --- Cargo.lock | 233 ++++++++-------- lib/c-api/Cargo.toml | 6 +- lib/c-api/build.rs | 276 +++++++++++++++++-- lib/c-api/src/lib.rs | 2 +- lib/c-api/wasmer.h | 487 +++++++++++++++++++++++++++++++- lib/c-api/wasmer.hh | 425 +++++++++++++++++++++++++++- lib/c-api/wasmer_wasm.h | 595 ++++++++++++++++++++++++++++++++++------ 7 files changed, 1797 insertions(+), 227 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ea89be7d8..c6d2ad432 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -47,9 +47,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.31" +version = "1.0.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85bb70cc08ec97ca5450e6eba421deeea5f172c0fc61f78b5357b2a8e8be195f" +checksum = "6b602bfe940d21c130f3895acd65221e8a61270debe89d628b9cb4e3ccb8569b" [[package]] name = "arrayref" @@ -82,9 +82,9 @@ checksum = "1d49d90015b3c36167a20fe2810c5cd875ad504b39cff3d4eae7977e6b7c1cb2" [[package]] name = "autocfg" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8aac770f1885fd7e387acedd76065302551364496e46b3dd00860b2f8359b9d" +checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" [[package]] name = "backtrace" @@ -142,9 +142,9 @@ checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" [[package]] name = "blake3" -version = "0.3.5" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59f88a20f7dc23e3896bcbd85add056543c87215de721468b90e0c85d5a9f365" +checksum = "ce4f9586c9a3151c4b49b19e82ba163dd073614dd057e53c969e1a4db5b52720" dependencies = [ "arrayref", "arrayvec", @@ -205,9 +205,9 @@ dependencies = [ [[package]] name = "cbindgen" -version = "0.14.5" +version = "0.14.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ddecdc62f915fce487fae1f599cc4cdccd6588d3402c537b77510afea66f7b2" +checksum = "afa64e93023395ee316490cf013f07f753bc88d116eb1aec1bcee7d63fbcca53" dependencies = [ "clap", "heck", @@ -223,9 +223,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.0.59" +version = "1.0.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "66120af515773fb005778dc07c261bd201ec8ce50bd6e7144c927753fe013381" +checksum = "ef611cc68ff783f18535d77ddd080185275713d852c4f5cbb6122c462a7a825c" [[package]] name = "cexpr" @@ -255,9 +255,9 @@ dependencies = [ [[package]] name = "clap" -version = "2.33.1" +version = "2.33.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bdfa80d47f954d53a35a64987ca1422f495b8d6483c0fe9f7117b36c2a792129" +checksum = "37e58ac78573c40708d45522f0d80fa2f01cc4f9b4e2bf749807255454312002" dependencies = [ "ansi_term", "atty", @@ -429,12 +429,12 @@ dependencies = [ [[package]] name = "crossbeam-channel" -version = "0.4.3" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09ee0cc8804d5393478d743b035099520087a5186f3b93fa58cec08fa62407b6" +checksum = "b153fe7cbef478c567df0f972e02e6d736db11affe43dfc9c56a9374d1adfb87" dependencies = [ - "cfg-if", "crossbeam-utils", + "maybe-uninit", ] [[package]] @@ -454,7 +454,7 @@ version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "058ed274caafc1f60c4997b5fc07bf7dc7cca454af7c6e81edffe5f33f70dace" dependencies = [ - "autocfg 1.0.0", + "autocfg 1.0.1", "cfg-if", "crossbeam-utils", "lazy_static", @@ -469,7 +469,7 @@ version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c3c7c73a2d1e9fc0886a08b93e98eb643461230d5f1925e4036204d5f2e261a8" dependencies = [ - "autocfg 1.0.0", + "autocfg 1.0.1", "cfg-if", "lazy_static", ] @@ -508,9 +508,9 @@ dependencies = [ [[package]] name = "ctor" -version = "0.1.15" +version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39858aa5bac06462d4dd4b9164848eb81ffc4aa5c479746393598fd193afa227" +checksum = "7fbaabec2c953050352311293be5c6aba8e141ba19d6811862b232d6fd020484" dependencies = [ "quote", "syn", @@ -609,9 +609,9 @@ dependencies = [ [[package]] name = "either" -version = "1.5.3" +version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb1f6b1ce1c140482ea30ddd3335fc0024ac7ee112895426e0a629a6c20adfe3" +checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" [[package]] name = "enumset" @@ -697,9 +697,9 @@ dependencies = [ [[package]] name = "generic-array" -version = "0.14.3" +version = "0.14.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60fb4bb6bba52f78a471264d9a3b7d026cc0af47b22cd2cffbc0b787ca003e63" +checksum = "501466ecc8a30d1d3b7fc9229b122b2ce8ed6e9d9223f1138d4babb253e51817" dependencies = [ "typenum", "version_check 0.9.2", @@ -707,9 +707,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.1.14" +version = "0.1.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7abc8dd8451921606d809ba32e95b6111925cd2906060d2dcc29c070220503eb" +checksum = "fc587bc0ec293155d5bfa6b9891ec18a1e330c234f896ea47fbada4cadbe47e6" dependencies = [ "cfg-if", "libc", @@ -774,7 +774,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "96282e96bfcd3da0d3aa9938bedf1e50df3269b6db08b4876d2da0bb1a0841cf" dependencies = [ "ahash", - "autocfg 1.0.0", + "autocfg 1.0.1", ] [[package]] @@ -784,9 +784,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e91b62f79061a0bc2e046024cb7ba44b08419ed238ecbd9adbd787434b9e8c25" dependencies = [ "ahash", - "autocfg 1.0.0", + "autocfg 1.0.1", ] +[[package]] +name = "hashbrown" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00d63df3d41950fb462ed38308eea019113ad1508da725bbedcd0fa5a85ef5f7" + [[package]] name = "heck" version = "0.3.1" @@ -798,9 +804,9 @@ dependencies = [ [[package]] name = "hermit-abi" -version = "0.1.15" +version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3deed196b6e7f9e44a2ae8d94225d80302d81208b1bb673fd21fe634645c85a9" +checksum = "4c30f6d0bc6b00693347368a67d41b58f2fb851215ff1da49e90fe2c5c667151" dependencies = [ "libc", ] @@ -828,12 +834,12 @@ checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" [[package]] name = "indexmap" -version = "1.5.0" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b88cd59ee5f71fea89a62248fc8f387d44400cefe05ef548466d61ced9029a7" +checksum = "55e2e4c765aa53a0424761bf9f41aa7a6ac1efa87238f59560640e27fca028f2" dependencies = [ - "autocfg 1.0.0", - "hashbrown 0.8.2", + "autocfg 1.0.1", + "hashbrown 0.9.0", "serde", ] @@ -865,15 +871,18 @@ dependencies = [ [[package]] name = "instant" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b141fdc7836c525d4d594027d318c84161ca17aaf8113ab1f81ab93ae897485" +checksum = "63312a18f7ea8760cdd0a7c5aac1a619752a246b833545e3e36d1f81f7cd9e66" +dependencies = [ + "cfg-if", +] [[package]] name = "inventory" -version = "0.1.7" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "621b50c176968fd3b0bd71f821a28a0ea98db2b5aea966b2fbb8bd1b7d310328" +checksum = "fedd49de24d8c263613701406611410687148ae8c37cd6452650b250f753a0dd" dependencies = [ "ctor", "ghost", @@ -882,9 +891,9 @@ dependencies = [ [[package]] name = "inventory-impl" -version = "0.1.7" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f99a4111304bade76468d05beab3487c226e4fe4c4de1c4e8f006e815762db73" +checksum = "ddead8880bc50f57fcd3b5869a7f6ff92570bb4e8f6870c22e2483272f2256da" dependencies = [ "proc-macro2", "quote", @@ -908,9 +917,9 @@ checksum = "dc6f3ad7b9d11a0c00842ff8de1b60ee58661048eb8049ed33c73594f359d7e6" [[package]] name = "js-sys" -version = "0.3.42" +version = "0.3.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52732a3d3ad72c58ad2dc70624f9c17b46ecd0943b9a4f1ee37c4c18c5d983e2" +checksum = "ca059e81d9486668f12d455a4ea6daa600bd408134cd17e3d3fb5a32d1f016f8" dependencies = [ "wasm-bindgen", ] @@ -923,9 +932,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "lazycell" -version = "1.2.1" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b294d6fa9ee409a054354afc4352b0b9ef7ca222c69b8812cbea9e7d2bf3783f" +checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" [[package]] name = "leb128" @@ -935,9 +944,9 @@ checksum = "3576a87f2ba00f6f106fdfcd16db1d698d648a26ad8e0573cad8537c3c362d2a" [[package]] name = "libc" -version = "0.2.76" +version = "0.2.77" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "755456fae044e6fa1ebbbd1b3e902ae19e73097ed4ed87bb79934a867c007bc3" +checksum = "f2f96b10ec2560088a8e76961b00d47107b3a625fecb76dedb29ee7ccbf98235" [[package]] name = "libffi" @@ -984,9 +993,9 @@ dependencies = [ [[package]] name = "llvm-sys" -version = "100.1.0" +version = "100.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5545bf9a09267c644e4d0ac68f37ac200af6579ae2e82aebce382654eb4abab1" +checksum = "9109e19fbfac3458f2970189719fa19f1007c6fd4e08c44fdebf4be0ddbe261d" dependencies = [ "cc", "lazy_static", @@ -1056,7 +1065,7 @@ version = "0.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "043175f069eda7b85febe4a74abbaeff828d9f8b448515d3151a14a3542811aa" dependencies = [ - "autocfg 1.0.0", + "autocfg 1.0.1", ] [[package]] @@ -1082,11 +1091,12 @@ dependencies = [ [[package]] name = "miniz_oxide" -version = "0.4.0" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be0f75932c1f6cfae3c04000e40114adf955636e19040f9c0a2c380702aa1c7f" +checksum = "c60c0dfe32c10b43a144bad8fc83538c52f58302c92300ea7ec7bf7b38d5a7b9" dependencies = [ "adler", + "autocfg 1.0.1", ] [[package]] @@ -1135,7 +1145,7 @@ version = "0.1.43" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8d59457e662d541ba17869cf51cf177c0b5f0cbf476c66bdc90bf1edac4f875b" dependencies = [ - "autocfg 1.0.0", + "autocfg 1.0.1", "num-traits", ] @@ -1145,7 +1155,7 @@ version = "0.1.41" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a6e6b7c748f995c4c29c5f5ae0248536e04a5739927c74ec0fa564805094b9f" dependencies = [ - "autocfg 1.0.0", + "autocfg 1.0.1", "num-integer", "num-traits", ] @@ -1156,7 +1166,7 @@ version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ac267bcc07f48ee5f8935ab0d24f316fb722d7a1292e2913f0cc196b29ffd611" dependencies = [ - "autocfg 1.0.0", + "autocfg 1.0.1", ] [[package]] @@ -1187,9 +1197,9 @@ checksum = "1ab52be62400ca80aa00285d25253d7f7c437b7375c4de678f5405d3afe82ca5" [[package]] name = "once_cell" -version = "1.4.0" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b631f7e854af39a1739f401cf34a8a013dfe09eac4fa4dba91e9768bd28168d" +checksum = "260e51e7efe62b592207e9e13a68e43692a7a279171d6ba57abd208bf23645ad" [[package]] name = "oorandom" @@ -1284,15 +1294,15 @@ dependencies = [ [[package]] name = "ppv-lite86" -version = "0.2.8" +version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "237a5ed80e274dbc66f86bd59c1e25edc039660be53194b5fe0a482e0f2612ea" +checksum = "c36fa947111f5c62a733b652544dd0016a43ce89619538a8ef92724a6f501a20" [[package]] name = "proc-macro-error" -version = "1.0.3" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc175e9777c3116627248584e8f8b3e2987405cabe1c0adf7d1dd28f09dc7880" +checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" dependencies = [ "proc-macro-error-attr", "proc-macro2", @@ -1303,28 +1313,26 @@ dependencies = [ [[package]] name = "proc-macro-error-attr" -version = "1.0.3" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3cc9795ca17eb581285ec44936da7fc2335a3f34f2ddd13118b6f4d515435c50" +checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" dependencies = [ "proc-macro2", "quote", - "syn", - "syn-mid", "version_check 0.9.2", ] [[package]] name = "proc-macro-hack" -version = "0.5.16" +version = "0.5.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e0456befd48169b9f13ef0f0ad46d492cf9d2dbb918bcf38e01eed4ce3ec5e4" +checksum = "99c605b9a0adc77b7211c6b1f722dcb613d68d66859a44f3d485a6da332b0598" [[package]] name = "proc-macro2" -version = "1.0.19" +version = "1.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04f5f085b5d71e2188cb8271e5da0161ad52c3f227a661a3c135fdf28e258b12" +checksum = "36e28516df94f3dd551a587da5357459d9b36d945a7c37c3557928c1c2ff2a2c" dependencies = [ "unicode-xid", ] @@ -1517,7 +1525,7 @@ version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cfd016f0c045ad38b5251be2c9c0ab806917f82da4d36b2a327e5166adad9270" dependencies = [ - "autocfg 1.0.0", + "autocfg 1.0.1", "crossbeam-deque", "either", "rayon-core", @@ -1525,9 +1533,9 @@ dependencies = [ [[package]] name = "rayon-core" -version = "1.8.0" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91739a34c4355b5434ce54c9086c5895604a9c278586d1f1aa95e04f66b525a0" +checksum = "e8c4fec834fb6e6d2dd5eece3c7b432a52f0ba887cf40e595190c4107edc08bf" dependencies = [ "crossbeam-channel", "crossbeam-deque", @@ -1725,9 +1733,9 @@ checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" [[package]] name = "serde" -version = "1.0.115" +version = "1.0.116" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e54c9a88f2da7238af84b5101443f0c0d0a3bbdc455e34a5c9497b1903ed55d5" +checksum = "96fe57af81d28386a513cbc6858332abc6117cfdb5999647c6444b8f43a370a5" dependencies = [ "serde_derive", ] @@ -1753,9 +1761,9 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.115" +version = "1.0.116" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "609feed1d0a73cc36a0182a840a9b37b4a82f0b1150369f0536a9e3f2a31dc48" +checksum = "f630a6370fd8e457873b4bd2ffdae75408bc291ba72be773772a4c2a065d9ae8" dependencies = [ "proc-macro2", "quote", @@ -1764,9 +1772,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.56" +version = "1.0.57" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3433e879a558dde8b5e8feb2a04899cf34fdde1fafb894687e52105fc1162ac3" +checksum = "164eacbdb13512ec2745fb09d51fd5b22b0d65ed294a1dcf7285a360c80a675c" dependencies = [ "itoa", "ryu", @@ -1829,32 +1837,21 @@ dependencies = [ [[package]] name = "subtle" -version = "2.2.3" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "502d53007c02d7605a05df1c1a73ee436952781653da5d0bf57ad608f66932c1" +checksum = "343f3f510c2915908f155e94f17220b19ccfacf2a64a2a5d8004f2c3e311e7fd" [[package]] name = "syn" -version = "1.0.35" +version = "1.0.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb7f4c519df8c117855e19dd8cc851e89eb746fe7a73f0157e0d95fdec5369b0" +checksum = "6690e3e9f692504b941dc6c3b188fd28df054f7fb8469ab40680df52fdcc842b" dependencies = [ "proc-macro2", "quote", "unicode-xid", ] -[[package]] -name = "syn-mid" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7be3539f6c128a931cf19dcee741c1af532c7fd387baa739c03dd2e96479338a" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "target-lexicon" version = "0.10.0" @@ -1962,9 +1959,9 @@ dependencies = [ [[package]] name = "tracing" -version = "0.1.16" +version = "0.1.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2e2a2de6b0d5cbb13fc21193a2296888eaab62b6044479aafb3c54c01c29fcd" +checksum = "6d79ca061b032d6ce30c660fded31189ca0b9922bf483cd70759f13a2d86786c" dependencies = [ "cfg-if", "log", @@ -1974,9 +1971,9 @@ dependencies = [ [[package]] name = "tracing-attributes" -version = "0.1.9" +version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0693bf8d6f2bf22c690fc61a9d21ac69efdbb894a17ed596b9af0f01e64b84b" +checksum = "80e0ccfc3378da0cce270c946b676a376943f5cd16aeba64568e7939806f4ada" dependencies = [ "proc-macro2", "quote", @@ -1985,9 +1982,9 @@ dependencies = [ [[package]] name = "tracing-core" -version = "0.1.11" +version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94ae75f0d28ae10786f3b1895c55fe72e79928fd5ccdebb5438c75e93fec178f" +checksum = "5bcf46c1f1f06aeea2d6b81f3c863d0930a596c86ad1920d4e5bad6dd1d7119a" dependencies = [ "lazy_static", ] @@ -2000,9 +1997,9 @@ checksum = "373c8a200f9e67a0c95e62a4f52fbf80c23b4381c05a17845531982fa99e6b33" [[package]] name = "typetag" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9275125decb5d75fe57ebfe92debd119b15757aae27c56d7cb61ecab871960bc" +checksum = "83b97b107d25d29de6879ac4f676ac5bfea92bdd01f206e995794493f1fc2e32" dependencies = [ "erased-serde", "inventory", @@ -2013,9 +2010,9 @@ dependencies = [ [[package]] name = "typetag-impl" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc232cda3b1d82664153e6c95d1071809aa0f1011f306c3d6989f33d8c6ede17" +checksum = "3f2466fc87b07b800a5060f89ba579d6882f7a03ac21363e4737764aaf9f99f9" dependencies = [ "proc-macro2", "quote", @@ -2089,9 +2086,9 @@ checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f" [[package]] name = "wasm-bindgen" -version = "0.2.65" +version = "0.2.68" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3edbcc9536ab7eababcc6d2374a0b7bfe13a2b6d562c5e07f370456b1a8f33d" +checksum = "1ac64ead5ea5f05873d7c12b545865ca2b8d28adfc50a49b84770a3a97265d42" dependencies = [ "cfg-if", "wasm-bindgen-macro", @@ -2099,9 +2096,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.65" +version = "0.2.68" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89ed2fb8c84bfad20ea66b26a3743f3e7ba8735a69fe7d95118c33ec8fc1244d" +checksum = "f22b422e2a757c35a73774860af8e112bff612ce6cb604224e8e47641a9e4f68" dependencies = [ "bumpalo", "lazy_static", @@ -2114,9 +2111,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.65" +version = "0.2.68" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb071268b031a64d92fc6cf691715ca5a40950694d8f683c5bb43db7c730929e" +checksum = "6b13312a745c08c469f0b292dd2fcd6411dba5f7160f593da6ef69b64e407038" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -2124,9 +2121,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.65" +version = "0.2.68" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf592c807080719d1ff2f245a687cbadb3ed28b2077ed7084b47aba8b691f2c6" +checksum = "f249f06ef7ee334cc3b8ff031bfc11ec99d00f34d86da7498396dc1e3b1498fe" dependencies = [ "proc-macro2", "quote", @@ -2137,9 +2134,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.65" +version = "0.2.68" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b6c0220ded549d63860c78c38f3bcc558d1ca3f4efa74942c536ddbbb55e87" +checksum = "1d649a3145108d7d3fbcde896a468d1bd636791823c9921135218ad89be08307" [[package]] name = "wasmer" @@ -2513,20 +2510,20 @@ dependencies = [ [[package]] name = "wast" -version = "23.0.0" +version = "24.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26b080a48623c1b15193eac2e28c7b8d0e6b2e1c6c67ed46ddcd86063e78e504" +checksum = "6ff1e3bd3ad0b2ee7784add89c30dc96b89a54b43e5d6d95d774eda1863b3500" dependencies = [ "leb128", ] [[package]] name = "wat" -version = "1.0.24" +version = "1.0.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c350d7431aa486488d28cdf75b57d59c02fab9cde20d93c52424510afe18ecc" +checksum = "c7c0bb2872ae453f98cec6ff1bf1a71cde1da6041fce8b0ac39d51eb033e9ec0" dependencies = [ - "wast 23.0.0", + "wast 24.0.0", ] [[package]] @@ -2601,9 +2598,9 @@ dependencies = [ [[package]] name = "web-sys" -version = "0.3.42" +version = "0.3.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8be2398f326b7ba09815d0b403095f34dd708579220d099caae89be0b32137b2" +checksum = "4bf6ef87ad7ae8008e15a355ce696bed26012b7caa21605188cfd8214ab51e2d" dependencies = [ "js-sys", "wasm-bindgen", diff --git a/lib/c-api/Cargo.toml b/lib/c-api/Cargo.toml index bc525a831..1196ae318 100644 --- a/lib/c-api/Cargo.toml +++ b/lib/c-api/Cargo.toml @@ -69,10 +69,8 @@ llvm = [ "wasmer-compiler-llvm", "compiler", ] - #emscripten = ["wasmer-emscripten"] -# used to avoid generating standard Wasm C API types in our header files -ignore-wasm-c-api = [] +include-deprecated = [] # This is for compatibility for old usage singlepass-backend = ["singlepass"] @@ -80,4 +78,4 @@ cranelift-backend = ["cranelift"] llvm-backend = ["llvm"] [build-dependencies] -cbindgen = { version = "0.14.3" } +cbindgen = { version = "0.14.6" } diff --git a/lib/c-api/build.rs b/lib/c-api/build.rs index dd76b1186..10309c6ac 100644 --- a/lib/c-api/build.rs +++ b/lib/c-api/build.rs @@ -27,16 +27,267 @@ const PRE_HEADER: &'static str = r#" #endif "#; +#[allow(unused)] +const JIT_FEATURE_AS_C_DEFINE: &'static str = "WASMER_JIT_ENABLED"; + +#[allow(unused)] +const COMPILER_FEATURE_AS_C_DEFINE: &'static str = "WASMER_COMPILER_ENABLED"; + +#[allow(unused)] const WASI_FEATURE_AS_C_DEFINE: &'static str = "WASMER_WASI_ENABLED"; + +#[allow(unused)] const EMSCRIPTEN_FEATURE_AS_C_DEFINE: &'static str = "WASMER_EMSCRIPTEN_ENABLED"; +#[allow(unused)] +const INCLUDE_DEPRECATED_FEATURE_AS_C_DEFINE: &'static str = "WASMER_DEPRECATED_ENABLED"; + +macro_rules! map_feature_as_c_define { + ($feature:expr, $c_define:ident, $accumulator:ident) => { + #[cfg(feature = $feature)] + { + $accumulator.push_str(&format!( + r#" +// The `{feature}` feature has been enabled for this build. +#define {define} +"#, + feature = $feature, + define = $c_define, + )); + } + }; +} + fn main() { let crate_dir = env::var("CARGO_MANIFEST_DIR").unwrap(); let out_dir = env::var("OUT_DIR").unwrap(); + build_wasm_c_api_headers(&crate_dir, &out_dir); build_wasmer_headers(&crate_dir, &out_dir); } +fn build_wasm_c_api_headers(crate_dir: &str, out_dir: &str) { + let mut crate_header_file = PathBuf::from(crate_dir); + crate_header_file.push("wasmer_wasm"); + + let mut out_header_file = PathBuf::from(out_dir); + out_header_file.push("wasmer_wasm"); + + let mut pre_header = format!( + r#"// The Wasmer C/C++ header file compatible with the `wasm-c-api` standard API. + +#if !defined(WASMER_WASM_H_MACROS) + +#define WASMER_WASM_H_MACROS +{pre_header}"#, + pre_header = PRE_HEADER + ); + + map_feature_as_c_define!("jit", JIT_FEATURE_AS_C_DEFINE, pre_header); + map_feature_as_c_define!("compiler", COMPILER_FEATURE_AS_C_DEFINE, pre_header); + map_feature_as_c_define!("wasi", WASI_FEATURE_AS_C_DEFINE, pre_header); + map_feature_as_c_define!("emscripten", EMSCRIPTEN_FEATURE_AS_C_DEFINE, pre_header); + map_feature_as_c_define!( + "include-deprecated", + INCLUDE_DEPRECATED_FEATURE_AS_C_DEFINE, + pre_header + ); + + // Close pre header. + pre_header.push_str( + r#" +#endif // WASMER_WASM_H_MACROS + + +// +// OK, here we go. The code below is automatically generated. +// +"#, + ); + + // C bindings. + { + // Generate the bindings in the `OUT_DIR`. + out_header_file.set_extension("h"); + + #[allow(unused_mut)] + let mut builder = Builder::new() + .with_language(Language::C) + .with_crate(crate_dir) + .with_include_guard("WASMER_WASM_H") + .with_header(&pre_header) + .with_define("target_family", "windows", "_WIN32") + .with_define("target_arch", "x86_64", "ARCH_X86_64") + .with_define("feature", "jit", JIT_FEATURE_AS_C_DEFINE) + .with_define("feature", "compiler", COMPILER_FEATURE_AS_C_DEFINE) + .with_define("feature", "wasi", WASI_FEATURE_AS_C_DEFINE) + .with_define("feature", "emscripten", EMSCRIPTEN_FEATURE_AS_C_DEFINE) + .with_define( + "feature", + "include-deprecated", + INCLUDE_DEPRECATED_FEATURE_AS_C_DEFINE, + ) + .with_include("wasm.h") + .with_documentation(true); + + #[cfg(not(feature = "include-deprecated"))] + { + // List of all functions to exclude given by: + // + // `rg 'extern "C" fn' deprecated/` builder = builder + builder = builder + .exclude_item("wasmer_compile") + .exclude_item("wasmer_emscripten_call_main") + .exclude_item("wasmer_emscripten_destroy_globals") + .exclude_item("wasmer_emscripten_generate_import_object") + .exclude_item("wasmer_emscripten_get_globals") + .exclude_item("wasmer_emscripten_set_up") + .exclude_item("wasmer_export_descriptor_kind") + .exclude_item("wasmer_export_descriptor_name") + .exclude_item("wasmer_export_descriptors") + .exclude_item("wasmer_export_descriptors_destroy") + .exclude_item("wasmer_export_descriptors_get") + .exclude_item("wasmer_export_descriptors_len") + .exclude_item("wasmer_export_func_call") + .exclude_item("wasmer_export_func_params") + .exclude_item("wasmer_export_func_params_arity") + .exclude_item("wasmer_export_func_returns") + .exclude_item("wasmer_export_func_returns_arity") + .exclude_item("wasmer_export_kind") + .exclude_item("wasmer_export_name") + .exclude_item("wasmer_export_to_func") + .exclude_item("wasmer_export_to_memory") + .exclude_item("wasmer_exports_destroy") + .exclude_item("wasmer_exports_get") + .exclude_item("wasmer_exports_len") + .exclude_item("wasmer_global_destroy") + .exclude_item("wasmer_global_get") + .exclude_item("wasmer_global_get_descriptor") + .exclude_item("wasmer_global_new") + .exclude_item("wasmer_global_set") + .exclude_item("wasmer_import_descriptor_kind") + .exclude_item("wasmer_import_descriptor_module_name") + .exclude_item("wasmer_import_descriptor_name") + .exclude_item("wasmer_import_descriptors") + .exclude_item("wasmer_import_descriptors_destroy") + .exclude_item("wasmer_import_descriptors_get") + .exclude_item("wasmer_import_descriptors_len") + .exclude_item("wasmer_import_func_destroy") + .exclude_item("wasmer_import_func_new") + .exclude_item("wasmer_import_func_params") + .exclude_item("wasmer_import_func_params_arity") + .exclude_item("wasmer_import_func_returns") + .exclude_item("wasmer_import_func_returns_arity") + .exclude_item("wasmer_import_object_destroy") + .exclude_item("wasmer_import_object_extend") + .exclude_item("wasmer_import_object_get_import") + .exclude_item("wasmer_import_object_imports_destroy") + .exclude_item("wasmer_import_object_iter_at_end") + .exclude_item("wasmer_import_object_iter_destroy") + .exclude_item("wasmer_import_object_iter_next") + .exclude_item("wasmer_import_object_iterate_functions") + .exclude_item("wasmer_import_object_new") + .exclude_item("wasmer_import_object_new") + .exclude_item("wasmer_instance_call") + .exclude_item("wasmer_instance_context_data_get") + .exclude_item("wasmer_instance_context_data_set") + .exclude_item("wasmer_instance_context_get") + .exclude_item("wasmer_instance_context_memory") + .exclude_item("wasmer_instance_destroy") + .exclude_item("wasmer_instance_exports") + .exclude_item("wasmer_instantiate") + .exclude_item("wasmer_memory_data") + .exclude_item("wasmer_memory_data_length") + .exclude_item("wasmer_memory_destroy") + .exclude_item("wasmer_memory_grow") + .exclude_item("wasmer_memory_length") + .exclude_item("wasmer_memory_new") + .exclude_item("wasmer_module_deserialize") + .exclude_item("wasmer_module_destroy") + .exclude_item("wasmer_module_import_instantiate") + .exclude_item("wasmer_module_instantiate") + .exclude_item("wasmer_module_serialize") + .exclude_item("wasmer_serialized_module_bytes") + .exclude_item("wasmer_serialized_module_destroy") + .exclude_item("wasmer_serialized_module_from_bytes") + .exclude_item("wasmer_table_destroy") + .exclude_item("wasmer_table_grow") + .exclude_item("wasmer_table_length") + .exclude_item("wasmer_table_new") + .exclude_item("wasmer_trampoline_buffer_builder_add_callinfo_trampoline") + .exclude_item("wasmer_trampoline_buffer_builder_add_context_trampoline") + .exclude_item("wasmer_trampoline_buffer_builder_build") + .exclude_item("wasmer_trampoline_buffer_builder_new") + .exclude_item("wasmer_trampoline_buffer_destroy") + .exclude_item("wasmer_trampoline_buffer_get_trampoline") + .exclude_item("wasmer_trampoline_get_context") + .exclude_item("wasmer_trap") + .exclude_item("wasmer_validate") + .exclude_item("wasmer_wasi_generate_default_import_object") + .exclude_item("wasmer_wasi_generate_import_object") + .exclude_item("wasmer_wasi_generate_import_object_for_version") + .exclude_item("wasmer_wasi_get_version"); + + // List of all structs and enums to exclude given by: + // + // `rg 'pub (enum|struct)' deprecated/` + builder = builder + .exclude_item("NamedExportDescriptors(Vec)") + .exclude_item("NamedImportDescriptors(Vec)") + .exclude_item("Version") + .exclude_item("WasmerImportObjectIterator") + .exclude_item("wasmer_byte_array") + .exclude_item("wasmer_emscripten_globals_t") + .exclude_item("wasmer_export_descriptor_t") + .exclude_item("wasmer_export_descriptors_t") + .exclude_item("wasmer_export_func_t") + .exclude_item("wasmer_export_t") + .exclude_item("wasmer_exports_t") + .exclude_item("wasmer_global_descriptor_t") + .exclude_item("wasmer_global_t") + .exclude_item("wasmer_import_descriptor_t") + .exclude_item("wasmer_import_descriptors_t") + .exclude_item("wasmer_import_export_kind") + .exclude_item("wasmer_import_func_t") + .exclude_item("wasmer_import_object_iter_t") + .exclude_item("wasmer_import_object_t") + .exclude_item("wasmer_import_t") + .exclude_item("wasmer_instance_context_t") + .exclude_item("wasmer_instance_t") + .exclude_item("wasmer_limit_option_t") + .exclude_item("wasmer_limits_t") + .exclude_item("wasmer_memory_t") + .exclude_item("wasmer_module_t") + .exclude_item("wasmer_result_t") + .exclude_item("wasmer_serialized_module_t") + .exclude_item("wasmer_table_t") + .exclude_item("wasmer_trampoline_buffer_builder_t") + .exclude_item("wasmer_trampoline_buffer_t") + .exclude_item("wasmer_trampoline_callable_t") + .exclude_item("wasmer_value_t") + .exclude_item("wasmer_value_tag") + .exclude_item("wasmer_wasi_map_dir_entry_t"); + } + + builder + .exclude_item("Version") + .generate() + .expect("Unable to generate C bindings") + .write_to_file(out_header_file.as_path()); + + // Copy the generated bindings from `OUT_DIR` to + // `CARGO_MANIFEST_DIR`. + crate_header_file.set_extension("h"); + + fs::copy(out_header_file.as_path(), crate_header_file.as_path()) + .expect("Unable to copy the generated C bindings"); + } +} + +#[cfg(not(feature = "include-deprecated"))] +fn build_wasmer_headers(_crate_dir: &str, _out_dir: &str) {} + +#[cfg(feature = "include-deprecated")] fn build_wasmer_headers(crate_dir: &str, out_dir: &str) { let mut crate_header_file = PathBuf::from(crate_dir); crate_header_file.push("wasmer"); @@ -54,29 +305,8 @@ fn build_wasmer_headers(crate_dir: &str, out_dir: &str) { pre_header = PRE_HEADER ); - #[cfg(feature = "wasi")] - { - pre_header.push_str(&format!( - r#" -// The `wasi` feature has been enabled for this build. -#define {define} - -"#, - define = WASI_FEATURE_AS_C_DEFINE - )); - } - - #[cfg(feature = "emscripten")] - { - pre_header.push_str(&format!( - r#" -// The `emscripten` feature has been enabled for this build. -#define {define} - -"#, - define = EMSCRIPTEN_FEATURE_AS_C_DEFINE - )); - } + map_feature_as_c_define!("wasi", WASI_FEATURE_AS_C_DEFINE, pre_header); + map_feature_as_c_define!("emscritpen", EMSCRIPTEN_FEATURE_AS_C_DEFINE, pre_header); // Close pre header. pre_header.push_str( diff --git a/lib/c-api/src/lib.rs b/lib/c-api/src/lib.rs index 21f8d496a..3f2222985 100644 --- a/lib/c-api/src/lib.rs +++ b/lib/c-api/src/lib.rs @@ -11,8 +11,8 @@ unreachable_patterns )] +#[cfg(feature = "include-deprecated")] pub mod deprecated; pub mod error; mod ordered_resolver; -/// cbindgen:ignore pub mod wasm_c_api; diff --git a/lib/c-api/wasmer.h b/lib/c-api/wasmer.h index 6f5b60a1d..3fa18e7ef 100644 --- a/lib/c-api/wasmer.h +++ b/lib/c-api/wasmer.h @@ -30,7 +30,6 @@ // The `wasi` feature has been enabled for this build. #define WASMER_WASI_ENABLED - #endif // WASMER_H_MACROS @@ -78,6 +77,16 @@ enum Version { typedef uint8_t Version; #endif +enum wasm_valkind_enum { + WASM_I32 = 0, + WASM_I64 = 1, + WASM_F32 = 2, + WASM_F64 = 3, + WASM_ANYREF = 128, + WASM_FUNCREF = 129, +}; +typedef uint8_t wasm_valkind_enum; + /** * List of export/import kinds. */ @@ -141,6 +150,200 @@ enum wasmer_value_tag { }; typedef uint32_t wasmer_value_tag; +typedef struct Arc_Instance Arc_Instance; + +typedef struct Arc_Module Arc_Module; + +typedef struct Box_wasi_config_t Box_wasi_config_t; + +typedef struct Box_wasm_engine_t Box_wasm_engine_t; + +typedef struct Box_wasm_exporttype_t Box_wasm_exporttype_t; + +typedef struct Box_wasm_externtype_t Box_wasm_externtype_t; + +typedef struct Box_wasm_global_t Box_wasm_global_t; + +typedef struct Box_wasm_importtype_t Box_wasm_importtype_t; + +typedef struct Box_wasm_memory_t Box_wasm_memory_t; + +typedef struct Box_wasm_memorytype_t Box_wasm_memorytype_t; + +typedef struct Box_wasm_table_t Box_wasm_table_t; + +typedef struct Box_wasm_tabletype_t Box_wasm_tabletype_t; + +typedef struct Box_wasm_valtype_t Box_wasm_valtype_t; + +typedef struct Option_Arc_Instance Option_Arc_Instance; + +typedef struct Option_Box_wasi_config_t Option_Box_wasi_config_t; + +typedef struct Option_Box_wasi_env_t Option_Box_wasi_env_t; + +typedef struct Option_Box_wasm_engine_t Option_Box_wasm_engine_t; + +typedef struct Option_Box_wasm_extern_t Option_Box_wasm_extern_t; + +typedef struct Option_Box_wasm_externtype_t Option_Box_wasm_externtype_t; + +typedef struct Option_Box_wasm_func_t Option_Box_wasm_func_t; + +typedef struct Option_Box_wasm_functype_t Option_Box_wasm_functype_t; + +typedef struct Option_Box_wasm_global_t Option_Box_wasm_global_t; + +typedef struct Option_Box_wasm_globaltype_t Option_Box_wasm_globaltype_t; + +typedef struct Option_Box_wasm_importtype_t Option_Box_wasm_importtype_t; + +typedef struct Option_Box_wasm_instance_t Option_Box_wasm_instance_t; + +typedef struct Option_Box_wasm_memory_t Option_Box_wasm_memory_t; + +typedef struct Option_Box_wasm_memorytype_t Option_Box_wasm_memorytype_t; + +typedef struct Option_Box_wasm_module_t Option_Box_wasm_module_t; + +typedef struct Option_Box_wasm_table_t Option_Box_wasm_table_t; + +typedef struct Option_Box_wasm_tabletype_t Option_Box_wasm_tabletype_t; + +typedef struct Option_Box_wasm_valtype_t Option_Box_wasm_valtype_t; + +#if defined(WASMER_WASI_ENABLED) +typedef struct wasi_version_t wasi_version_t; +#endif + +typedef struct wasm_engine_t wasm_engine_t; + +typedef struct wasm_ref_t wasm_ref_t; + +#if defined(WASMER_WASI_ENABLED) +typedef struct { + bool inherit_stdout; + bool inherit_stderr; + bool inherit_stdin; + WasiStateBuilder state_builder; +} wasi_config_t; +#endif + +#if defined(WASMER_WASI_ENABLED) +typedef struct { + WasiEnv inner; +} wasi_env_t; +#endif + +typedef struct { + Arc_Instance inner; +} wasm_instance_t; + +typedef struct { + Memory inner; +} wasm_memory_t; + +/** + * Opaque wrapper around `Store` + */ +typedef struct { + +} wasm_store_t; + +typedef struct { + Arc_Module inner; +} wasm_module_t; + +typedef struct { + Option_Arc_Instance instance; + Extern inner; +} wasm_extern_t; + +/** + * this can be a wasmer-specific type with wasmer-specific functions for manipulating it + */ +typedef struct { + +} wasm_config_t; + +typedef wasm_byte_vec_t wasm_name_t; + +typedef ExternType wasm_externtype_t; + +typedef struct { + wasm_name_t *name; + wasm_externtype_t *extern_type; +} wasm_exporttype_t; + +typedef uint8_t wasm_externkind_t; + +typedef wasm_externtype_t wasm_functype_t; + +typedef wasm_externtype_t wasm_globaltype_t; + +typedef wasm_externtype_t wasm_memorytype_t; + +typedef struct { + wasm_externtype_t extern_; +} wasm_tabletype_t; + +typedef struct { + Function inner; + Option_Arc_Instance instance; +} wasm_func_t; + +typedef struct { + +} wasm_trap_t; + +typedef uint8_t wasm_valkind_t; + +typedef union { + int32_t int32_t; + int64_t int64_t; + float float32_t; + double float64_t; + wasm_ref_t *wref; +} wasm_val_inner; + +typedef struct { + wasm_valkind_t kind; + wasm_val_inner of; +} wasm_val_t; + +typedef wasm_trap_t *(*wasm_func_callback_t)(const wasm_val_t *args, wasm_val_t *results); + +typedef wasm_trap_t *(*wasm_func_callback_with_env_t)(void*, const wasm_val_t *args, wasm_val_t *results); + +typedef void (*wasm_env_finalizer_t)(void); + +typedef struct { + Global inner; +} wasm_global_t; + +typedef struct { + wasm_valkind_enum valkind; +} wasm_valtype_t; + +typedef uint8_t wasm_mutability_t; + +typedef struct { + wasm_name_t *module; + wasm_name_t *name; + wasm_externtype_t *extern_type; +} wasm_importtype_t; + +typedef struct { + uint32_t min; + uint32_t max; +} wasm_limits_t; + +typedef struct { + Table inner; +} wasm_table_t; + +typedef uint32_t wasm_table_size_t; + typedef struct { } wasmer_module_t; @@ -402,6 +605,288 @@ typedef struct { } wasmer_wasi_map_dir_entry_t; #endif +#if defined(WASMER_WASI_ENABLED) +void wasi_config_arg(wasi_config_t *config, const char *arg); +#endif + +#if defined(WASMER_WASI_ENABLED) +void wasi_config_env(wasi_config_t *config, const char *key, const char *value); +#endif + +#if defined(WASMER_WASI_ENABLED) +void wasi_config_inherit_stderr(wasi_config_t *config); +#endif + +#if defined(WASMER_WASI_ENABLED) +void wasi_config_inherit_stdin(wasi_config_t *config); +#endif + +#if defined(WASMER_WASI_ENABLED) +void wasi_config_inherit_stdout(wasi_config_t *config); +#endif + +#if defined(WASMER_WASI_ENABLED) +Option_Box_wasi_config_t wasi_config_new(const char *program_name); +#endif + +#if defined(WASMER_WASI_ENABLED) +void wasi_env_delete(Option_Box_wasi_env_t _state); +#endif + +#if defined(WASMER_WASI_ENABLED) +/** + * Takes ownership over the `wasi_config_t`. + */ +Option_Box_wasi_env_t wasi_env_new(Box_wasi_config_t config); +#endif + +#if defined(WASMER_WASI_ENABLED) +intptr_t wasi_env_read_stderr(wasi_env_t *env, char *buffer, uintptr_t buffer_len); +#endif + +#if defined(WASMER_WASI_ENABLED) +intptr_t wasi_env_read_stdout(wasi_env_t *env, char *buffer, uintptr_t buffer_len); +#endif + +#if defined(WASMER_WASI_ENABLED) +bool wasi_env_set_instance(wasi_env_t *env, const wasm_instance_t *instance); +#endif + +#if defined(WASMER_WASI_ENABLED) +void wasi_env_set_memory(wasi_env_t *env, const wasm_memory_t *memory); +#endif + +#if defined(WASMER_WASI_ENABLED) +/** + * Takes ownership of `wasi_env_t`. + */ +bool wasi_get_imports(wasm_store_t *store, + const wasm_module_t *module, + const wasi_env_t *wasi_env, + wasm_extern_t **imports); +#endif + +#if defined(WASMER_WASI_ENABLED) +wasi_version_t wasi_get_wasi_version(const wasm_module_t *module); +#endif + +wasm_config_t *wasm_config_new(void); + +void wasm_engine_delete(Option_Box_wasm_engine_t _wasm_engine_address); + +Box_wasm_engine_t wasm_engine_new_with_config(wasm_config_t *_config_ptr); + +const wasm_name_t *wasm_exporttype_name(const wasm_exporttype_t *et); + +Box_wasm_exporttype_t wasm_exporttype_new(wasm_name_t *name, wasm_externtype_t *extern_type); + +const wasm_externtype_t *wasm_exporttype_type(const wasm_exporttype_t *et); + +Option_Box_wasm_func_t wasm_extern_as_func(wasm_extern_t *extern_ptr); + +Option_Box_wasm_global_t wasm_extern_as_global(wasm_extern_t *extern_ptr); + +Option_Box_wasm_memory_t wasm_extern_as_memory(wasm_extern_t *extern_ptr); + +Option_Box_wasm_table_t wasm_extern_as_table(wasm_extern_t *extern_ptr); + +wasm_externkind_t wasm_extern_kind(const wasm_extern_t *e); + +Box_wasm_externtype_t wasm_extern_type(const wasm_extern_t *e); + +const wasm_functype_t *wasm_externtype_as_functype(const wasm_externtype_t *et); + +const wasm_functype_t *wasm_externtype_as_functype_const(const wasm_externtype_t *et); + +const wasm_globaltype_t *wasm_externtype_as_globaltype(const wasm_externtype_t *et); + +const wasm_globaltype_t *wasm_externtype_as_globaltype_const(const wasm_externtype_t *et); + +const wasm_memorytype_t *wasm_externtype_as_memorytype(const wasm_externtype_t *et); + +const wasm_memorytype_t *wasm_externtype_as_memorytype_const(const wasm_externtype_t *et); + +const wasm_tabletype_t *wasm_externtype_as_tabletype(const wasm_externtype_t *et); + +const wasm_tabletype_t *wasm_externtype_as_tabletype_const(const wasm_externtype_t *et); + +void wasm_externtype_delete(Option_Box_wasm_externtype_t _et); + +wasm_externkind_t wasm_externtype_kind(const wasm_externtype_t *et); + +Option_Box_wasm_extern_t wasm_func_as_extern(wasm_func_t *func_ptr); + +wasm_trap_t *wasm_func_call(const wasm_func_t *func, const wasm_val_t *args, wasm_val_t *results); + +void wasm_func_delete(Option_Box_wasm_func_t _func); + +Option_Box_wasm_func_t wasm_func_new(wasm_store_t *store, + const wasm_functype_t *ft, + wasm_func_callback_t callback); + +Option_Box_wasm_func_t wasm_func_new_with_env(wasm_store_t *store, + const wasm_functype_t *ft, + wasm_func_callback_with_env_t callback, + void *env, + wasm_env_finalizer_t finalizer); + +uintptr_t wasm_func_param_arity(const wasm_func_t *func); + +uintptr_t wasm_func_result_arity(const wasm_func_t *func); + +const wasm_externtype_t *wasm_functype_as_externtype(const wasm_functype_t *ft); + +const wasm_externtype_t *wasm_functype_as_externtype_const(const wasm_functype_t *ft); + +Option_Box_wasm_functype_t wasm_functype_copy(wasm_functype_t *arg); + +void wasm_functype_delete(Option_Box_wasm_functype_t _ft); + +Option_Box_wasm_functype_t wasm_functype_new(wasm_valtype_vec_t *params, + wasm_valtype_vec_t *results); + +const wasm_valtype_vec_t *wasm_functype_params(const wasm_functype_t *ft); + +const wasm_valtype_vec_t *wasm_functype_results(const wasm_functype_t *ft); + +Option_Box_wasm_extern_t wasm_global_as_extern(wasm_global_t *global_ptr); + +Box_wasm_global_t wasm_global_copy(const wasm_global_t *wasm_global); + +void wasm_global_delete(Option_Box_wasm_global_t _global); + +void wasm_global_get(const wasm_global_t *wasm_global, wasm_val_t *out); + +Option_Box_wasm_global_t wasm_global_new(wasm_store_t *store_ptr, + const wasm_globaltype_t *gt, + const wasm_val_t *val); + +bool wasm_global_same(const wasm_global_t *wasm_global1, const wasm_global_t *wasm_global2); + +void wasm_global_set(wasm_global_t *wasm_global, const wasm_val_t *val); + +const wasm_externtype_t *wasm_globaltype_as_externtype(const wasm_globaltype_t *gt); + +const wasm_externtype_t *wasm_globaltype_as_externtype_const(const wasm_globaltype_t *gt); + +const wasm_valtype_t *wasm_globaltype_content(const wasm_globaltype_t *globaltype); + +void wasm_globaltype_delete(Option_Box_wasm_globaltype_t _globaltype); + +wasm_mutability_t wasm_globaltype_mutability(const wasm_globaltype_t *globaltype); + +Option_Box_wasm_globaltype_t wasm_globaltype_new(Option_Box_wasm_valtype_t valtype, + wasm_mutability_t mutability); + +void wasm_importtype_delete(Option_Box_wasm_importtype_t _importtype); + +const wasm_name_t *wasm_importtype_module(const wasm_importtype_t *et); + +const wasm_name_t *wasm_importtype_name(const wasm_importtype_t *et); + +Box_wasm_importtype_t wasm_importtype_new(wasm_name_t *module, + wasm_name_t *name, + wasm_externtype_t *extern_type); + +const wasm_externtype_t *wasm_importtype_type(const wasm_importtype_t *et); + +void wasm_instance_delete(Option_Box_wasm_instance_t _instance); + +void wasm_instance_exports(const wasm_instance_t *instance, wasm_extern_vec_t *out); + +Option_Box_wasm_instance_t wasm_instance_new(wasm_store_t *store, + const wasm_module_t *module, + const wasm_extern_t *const *imports, + wasm_trap_t **_traps); + +Option_Box_wasm_extern_t wasm_memory_as_extern(wasm_memory_t *memory_ptr); + +Box_wasm_memory_t wasm_memory_copy(const wasm_memory_t *wasm_memory); + +uint8_t *wasm_memory_data(wasm_memory_t *memory); + +uintptr_t wasm_memory_data_size(const wasm_memory_t *memory); + +void wasm_memory_delete(Option_Box_wasm_memory_t _memory); + +bool wasm_memory_grow(wasm_memory_t *memory, uint32_t delta); + +Option_Box_wasm_memory_t wasm_memory_new(wasm_store_t *store_ptr, const wasm_memorytype_t *mt); + +bool wasm_memory_same(const wasm_memory_t *wasm_memory1, const wasm_memory_t *wasm_memory2); + +uint32_t wasm_memory_size(const wasm_memory_t *memory); + +wasm_memorytype_t *wasm_memory_type(const wasm_memory_t *_memory_ptr); + +const wasm_externtype_t *wasm_memorytype_as_externtype(const wasm_memorytype_t *mt); + +const wasm_externtype_t *wasm_memorytype_as_externtype_const(const wasm_memorytype_t *mt); + +void wasm_memorytype_delete(Option_Box_wasm_memorytype_t _memorytype); + +const wasm_limits_t *wasm_memorytype_limits(const wasm_memorytype_t *mt); + +Box_wasm_memorytype_t wasm_memorytype_new(const wasm_limits_t *limits); + +void wasm_module_delete(Option_Box_wasm_module_t _module); + +wasm_module_t *wasm_module_deserialize(wasm_store_t *store_ptr, const wasm_byte_vec_t *bytes); + +void wasm_module_exports(const wasm_module_t *module, wasm_exporttype_vec_t *out); + +void wasm_module_imports(const wasm_module_t *module, wasm_importtype_vec_t *out); + +Option_Box_wasm_module_t wasm_module_new(wasm_store_t *store_ptr, const wasm_byte_vec_t *bytes); + +void wasm_module_serialize(const wasm_module_t *module, wasm_byte_vec_t *out_ptr); + +void wasm_store_delete(wasm_store_t *wasm_store); + +wasm_store_t *wasm_store_new(wasm_engine_t *wasm_engine_ptr); + +Option_Box_wasm_extern_t wasm_table_as_extern(wasm_table_t *table_ptr); + +Box_wasm_table_t wasm_table_copy(const wasm_table_t *wasm_table); + +void wasm_table_delete(Option_Box_wasm_table_t _table); + +bool wasm_table_grow(wasm_table_t *_wasm_table, wasm_table_size_t _delta, wasm_ref_t *_init); + +Option_Box_wasm_table_t wasm_table_new(wasm_store_t *store_ptr, + const wasm_tabletype_t *tt, + const wasm_ref_t *init); + +bool wasm_table_same(const wasm_table_t *wasm_table1, const wasm_table_t *wasm_table2); + +uintptr_t wasm_table_size(const wasm_table_t *wasm_table); + +const wasm_externtype_t *wasm_tabletype_as_externtype(const wasm_tabletype_t *tt); + +const wasm_externtype_t *wasm_tabletype_as_externtype_const(const wasm_tabletype_t *tt); + +void wasm_tabletype_delete(Option_Box_wasm_tabletype_t _tabletype); + +const wasm_valtype_t *wasm_tabletype_element(const wasm_tabletype_t *tabletype); + +const wasm_limits_t *wasm_tabletype_limits(const wasm_tabletype_t *tabletype); + +Box_wasm_tabletype_t wasm_tabletype_new(Box_wasm_valtype_t valtype, const wasm_limits_t *limits); + +void wasm_trap_delete(wasm_trap_t *trap); + +void wasm_trap_message(const wasm_trap_t *trap, wasm_byte_vec_t *out_ptr); + +void wasm_val_copy(wasm_val_t *out_ptr, const wasm_val_t *val); + +void wasm_val_delete(wasm_val_t *val); + +void wasm_valtype_delete(Option_Box_wasm_valtype_t _valtype); + +wasm_valkind_t wasm_valtype_kind(const wasm_valtype_t *valtype); + +Option_Box_wasm_valtype_t wasm_valtype_new(wasm_valkind_t kind); + /** * Creates a new Module from the given wasm bytes. * diff --git a/lib/c-api/wasmer.hh b/lib/c-api/wasmer.hh index 3d47face2..0401d50d7 100644 --- a/lib/c-api/wasmer.hh +++ b/lib/c-api/wasmer.hh @@ -30,7 +30,6 @@ // The `wasi` feature has been enabled for this build. #define WASMER_WASI_ENABLED - #endif // WASMER_H_MACROS @@ -69,6 +68,15 @@ enum class Version : uint8_t { }; #endif +enum class wasm_valkind_enum : uint8_t { + WASM_I32 = 0, + WASM_I64 = 1, + WASM_F32 = 2, + WASM_F64 = 3, + WASM_ANYREF = 128, + WASM_FUNCREF = 129, +}; + /// List of export/import kinds. enum class wasmer_import_export_kind : uint32_t { /// The export/import is a function. @@ -104,6 +112,143 @@ enum class wasmer_value_tag : uint32_t { WASM_F64, }; +template +struct Arc; + +template +struct Box; + +template +struct Option; + +#if defined(WASMER_WASI_ENABLED) +struct wasi_version_t; +#endif + +struct wasm_engine_t; + +struct wasm_ref_t; + +#if defined(WASMER_WASI_ENABLED) +struct wasi_config_t { + bool inherit_stdout; + bool inherit_stderr; + bool inherit_stdin; + WasiStateBuilder state_builder; +}; +#endif + +#if defined(WASMER_WASI_ENABLED) +struct wasi_env_t { + WasiEnv inner; +}; +#endif + +struct wasm_instance_t { + Arc inner; +}; + +struct wasm_memory_t { + Memory inner; +}; + +/// Opaque wrapper around `Store` +struct wasm_store_t { + +}; + +struct wasm_module_t { + Arc inner; +}; + +struct wasm_extern_t { + Option> instance; + Extern inner; +}; + +/// this can be a wasmer-specific type with wasmer-specific functions for manipulating it +struct wasm_config_t { + +}; + +using wasm_name_t = wasm_byte_vec_t; + +using wasm_externtype_t = ExternType; + +struct wasm_exporttype_t { + wasm_name_t *name; + wasm_externtype_t *extern_type; +}; + +struct wasm_func_t { + Function inner; + Option> instance; +}; + +struct wasm_global_t { + Global inner; +}; + +struct wasm_table_t { + Table inner; +}; + +using wasm_externkind_t = uint8_t; + +using wasm_functype_t = wasm_externtype_t; + +using wasm_globaltype_t = wasm_externtype_t; + +using wasm_memorytype_t = wasm_externtype_t; + +struct wasm_tabletype_t { + wasm_externtype_t extern_; +}; + +struct wasm_trap_t { + +}; + +using wasm_valkind_t = uint8_t; + +union wasm_val_inner { + int32_t int32_t; + int64_t int64_t; + float float32_t; + double float64_t; + wasm_ref_t *wref; +}; + +struct wasm_val_t { + wasm_valkind_t kind; + wasm_val_inner of; +}; + +using wasm_func_callback_t = wasm_trap_t*(*)(const wasm_val_t *args, wasm_val_t *results); + +using wasm_func_callback_with_env_t = wasm_trap_t*(*)(void*, const wasm_val_t *args, wasm_val_t *results); + +using wasm_env_finalizer_t = void(*)(void); + +struct wasm_valtype_t { + wasm_valkind_enum valkind; +}; + +using wasm_mutability_t = uint8_t; + +struct wasm_importtype_t { + wasm_name_t *module; + wasm_name_t *name; + wasm_externtype_t *extern_type; +}; + +struct wasm_limits_t { + uint32_t min; + uint32_t max; +}; + +using wasm_table_size_t = uint32_t; + struct wasmer_module_t { }; @@ -321,6 +466,284 @@ struct wasmer_wasi_map_dir_entry_t { extern "C" { +#if defined(WASMER_WASI_ENABLED) +void wasi_config_arg(wasi_config_t *config, const char *arg); +#endif + +#if defined(WASMER_WASI_ENABLED) +void wasi_config_env(wasi_config_t *config, const char *key, const char *value); +#endif + +#if defined(WASMER_WASI_ENABLED) +void wasi_config_inherit_stderr(wasi_config_t *config); +#endif + +#if defined(WASMER_WASI_ENABLED) +void wasi_config_inherit_stdin(wasi_config_t *config); +#endif + +#if defined(WASMER_WASI_ENABLED) +void wasi_config_inherit_stdout(wasi_config_t *config); +#endif + +#if defined(WASMER_WASI_ENABLED) +Option> wasi_config_new(const char *program_name); +#endif + +#if defined(WASMER_WASI_ENABLED) +void wasi_env_delete(Option> _state); +#endif + +#if defined(WASMER_WASI_ENABLED) +/// Takes ownership over the `wasi_config_t`. +Option> wasi_env_new(Box config); +#endif + +#if defined(WASMER_WASI_ENABLED) +intptr_t wasi_env_read_stderr(wasi_env_t *env, char *buffer, uintptr_t buffer_len); +#endif + +#if defined(WASMER_WASI_ENABLED) +intptr_t wasi_env_read_stdout(wasi_env_t *env, char *buffer, uintptr_t buffer_len); +#endif + +#if defined(WASMER_WASI_ENABLED) +bool wasi_env_set_instance(wasi_env_t *env, const wasm_instance_t *instance); +#endif + +#if defined(WASMER_WASI_ENABLED) +void wasi_env_set_memory(wasi_env_t *env, const wasm_memory_t *memory); +#endif + +#if defined(WASMER_WASI_ENABLED) +/// Takes ownership of `wasi_env_t`. +bool wasi_get_imports(wasm_store_t *store, + const wasm_module_t *module, + const wasi_env_t *wasi_env, + wasm_extern_t **imports); +#endif + +#if defined(WASMER_WASI_ENABLED) +wasi_version_t wasi_get_wasi_version(const wasm_module_t *module); +#endif + +wasm_config_t *wasm_config_new(); + +void wasm_engine_delete(Option> _wasm_engine_address); + +Box wasm_engine_new_with_config(wasm_config_t *_config_ptr); + +const wasm_name_t *wasm_exporttype_name(const wasm_exporttype_t *et); + +Box wasm_exporttype_new(wasm_name_t *name, wasm_externtype_t *extern_type); + +const wasm_externtype_t *wasm_exporttype_type(const wasm_exporttype_t *et); + +Option> wasm_extern_as_func(wasm_extern_t *extern_ptr); + +Option> wasm_extern_as_global(wasm_extern_t *extern_ptr); + +Option> wasm_extern_as_memory(wasm_extern_t *extern_ptr); + +Option> wasm_extern_as_table(wasm_extern_t *extern_ptr); + +wasm_externkind_t wasm_extern_kind(const wasm_extern_t *e); + +Box wasm_extern_type(const wasm_extern_t *e); + +const wasm_functype_t *wasm_externtype_as_functype(const wasm_externtype_t *et); + +const wasm_functype_t *wasm_externtype_as_functype_const(const wasm_externtype_t *et); + +const wasm_globaltype_t *wasm_externtype_as_globaltype(const wasm_externtype_t *et); + +const wasm_globaltype_t *wasm_externtype_as_globaltype_const(const wasm_externtype_t *et); + +const wasm_memorytype_t *wasm_externtype_as_memorytype(const wasm_externtype_t *et); + +const wasm_memorytype_t *wasm_externtype_as_memorytype_const(const wasm_externtype_t *et); + +const wasm_tabletype_t *wasm_externtype_as_tabletype(const wasm_externtype_t *et); + +const wasm_tabletype_t *wasm_externtype_as_tabletype_const(const wasm_externtype_t *et); + +void wasm_externtype_delete(Option> _et); + +wasm_externkind_t wasm_externtype_kind(const wasm_externtype_t *et); + +Option> wasm_func_as_extern(wasm_func_t *func_ptr); + +wasm_trap_t *wasm_func_call(const wasm_func_t *func, const wasm_val_t *args, wasm_val_t *results); + +void wasm_func_delete(Option> _func); + +Option> wasm_func_new(wasm_store_t *store, + const wasm_functype_t *ft, + wasm_func_callback_t callback); + +Option> wasm_func_new_with_env(wasm_store_t *store, + const wasm_functype_t *ft, + wasm_func_callback_with_env_t callback, + void *env, + wasm_env_finalizer_t finalizer); + +uintptr_t wasm_func_param_arity(const wasm_func_t *func); + +uintptr_t wasm_func_result_arity(const wasm_func_t *func); + +const wasm_externtype_t *wasm_functype_as_externtype(const wasm_functype_t *ft); + +const wasm_externtype_t *wasm_functype_as_externtype_const(const wasm_functype_t *ft); + +Option> wasm_functype_copy(wasm_functype_t *arg); + +void wasm_functype_delete(Option> _ft); + +Option> wasm_functype_new(wasm_valtype_vec_t *params, + wasm_valtype_vec_t *results); + +const wasm_valtype_vec_t *wasm_functype_params(const wasm_functype_t *ft); + +const wasm_valtype_vec_t *wasm_functype_results(const wasm_functype_t *ft); + +Option> wasm_global_as_extern(wasm_global_t *global_ptr); + +Box wasm_global_copy(const wasm_global_t *wasm_global); + +void wasm_global_delete(Option> _global); + +void wasm_global_get(const wasm_global_t *wasm_global, wasm_val_t *out); + +Option> wasm_global_new(wasm_store_t *store_ptr, + const wasm_globaltype_t *gt, + const wasm_val_t *val); + +bool wasm_global_same(const wasm_global_t *wasm_global1, const wasm_global_t *wasm_global2); + +void wasm_global_set(wasm_global_t *wasm_global, const wasm_val_t *val); + +const wasm_externtype_t *wasm_globaltype_as_externtype(const wasm_globaltype_t *gt); + +const wasm_externtype_t *wasm_globaltype_as_externtype_const(const wasm_globaltype_t *gt); + +const wasm_valtype_t *wasm_globaltype_content(const wasm_globaltype_t *globaltype); + +void wasm_globaltype_delete(Option> _globaltype); + +wasm_mutability_t wasm_globaltype_mutability(const wasm_globaltype_t *globaltype); + +Option> wasm_globaltype_new(Option> valtype, + wasm_mutability_t mutability); + +void wasm_importtype_delete(Option> _importtype); + +const wasm_name_t *wasm_importtype_module(const wasm_importtype_t *et); + +const wasm_name_t *wasm_importtype_name(const wasm_importtype_t *et); + +Box wasm_importtype_new(wasm_name_t *module, + wasm_name_t *name, + wasm_externtype_t *extern_type); + +const wasm_externtype_t *wasm_importtype_type(const wasm_importtype_t *et); + +void wasm_instance_delete(Option> _instance); + +void wasm_instance_exports(const wasm_instance_t *instance, wasm_extern_vec_t *out); + +Option> wasm_instance_new(wasm_store_t *store, + const wasm_module_t *module, + const wasm_extern_t *const *imports, + wasm_trap_t **_traps); + +Option> wasm_memory_as_extern(wasm_memory_t *memory_ptr); + +Box wasm_memory_copy(const wasm_memory_t *wasm_memory); + +uint8_t *wasm_memory_data(wasm_memory_t *memory); + +uintptr_t wasm_memory_data_size(const wasm_memory_t *memory); + +void wasm_memory_delete(Option> _memory); + +bool wasm_memory_grow(wasm_memory_t *memory, uint32_t delta); + +Option> wasm_memory_new(wasm_store_t *store_ptr, const wasm_memorytype_t *mt); + +bool wasm_memory_same(const wasm_memory_t *wasm_memory1, const wasm_memory_t *wasm_memory2); + +uint32_t wasm_memory_size(const wasm_memory_t *memory); + +wasm_memorytype_t *wasm_memory_type(const wasm_memory_t *_memory_ptr); + +const wasm_externtype_t *wasm_memorytype_as_externtype(const wasm_memorytype_t *mt); + +const wasm_externtype_t *wasm_memorytype_as_externtype_const(const wasm_memorytype_t *mt); + +void wasm_memorytype_delete(Option> _memorytype); + +const wasm_limits_t *wasm_memorytype_limits(const wasm_memorytype_t *mt); + +Box wasm_memorytype_new(const wasm_limits_t *limits); + +void wasm_module_delete(Option> _module); + +wasm_module_t *wasm_module_deserialize(wasm_store_t *store_ptr, const wasm_byte_vec_t *bytes); + +void wasm_module_exports(const wasm_module_t *module, wasm_exporttype_vec_t *out); + +void wasm_module_imports(const wasm_module_t *module, wasm_importtype_vec_t *out); + +Option> wasm_module_new(wasm_store_t *store_ptr, const wasm_byte_vec_t *bytes); + +void wasm_module_serialize(const wasm_module_t *module, wasm_byte_vec_t *out_ptr); + +void wasm_store_delete(wasm_store_t *wasm_store); + +wasm_store_t *wasm_store_new(wasm_engine_t *wasm_engine_ptr); + +Option> wasm_table_as_extern(wasm_table_t *table_ptr); + +Box wasm_table_copy(const wasm_table_t *wasm_table); + +void wasm_table_delete(Option> _table); + +bool wasm_table_grow(wasm_table_t *_wasm_table, wasm_table_size_t _delta, wasm_ref_t *_init); + +Option> wasm_table_new(wasm_store_t *store_ptr, + const wasm_tabletype_t *tt, + const wasm_ref_t *init); + +bool wasm_table_same(const wasm_table_t *wasm_table1, const wasm_table_t *wasm_table2); + +uintptr_t wasm_table_size(const wasm_table_t *wasm_table); + +const wasm_externtype_t *wasm_tabletype_as_externtype(const wasm_tabletype_t *tt); + +const wasm_externtype_t *wasm_tabletype_as_externtype_const(const wasm_tabletype_t *tt); + +void wasm_tabletype_delete(Option> _tabletype); + +const wasm_valtype_t *wasm_tabletype_element(const wasm_tabletype_t *tabletype); + +const wasm_limits_t *wasm_tabletype_limits(const wasm_tabletype_t *tabletype); + +Box wasm_tabletype_new(Box valtype, const wasm_limits_t *limits); + +void wasm_trap_delete(wasm_trap_t *trap); + +void wasm_trap_message(const wasm_trap_t *trap, wasm_byte_vec_t *out_ptr); + +void wasm_val_copy(wasm_val_t *out_ptr, const wasm_val_t *val); + +void wasm_val_delete(wasm_val_t *val); + +void wasm_valtype_delete(Option> _valtype); + +wasm_valkind_t wasm_valtype_kind(const wasm_valtype_t *valtype); + +Option> wasm_valtype_new(wasm_valkind_t kind); + /// Creates a new Module from the given wasm bytes. /// /// Returns `wasmer_result_t::WASMER_OK` upon success. diff --git a/lib/c-api/wasmer_wasm.h b/lib/c-api/wasmer_wasm.h index 56260c91f..b6f6f1c8c 100644 --- a/lib/c-api/wasmer_wasm.h +++ b/lib/c-api/wasmer_wasm.h @@ -1,105 +1,542 @@ -// This header file is for Wasmer APIs intended to be used with the standard Wasm C API. +// The Wasmer C/C++ header file compatible with the `wasm-c-api` standard API. + +#if !defined(WASMER_WASM_H_MACROS) + +#define WASMER_WASM_H_MACROS + +// Define the `ARCH_X86_X64` constant. +#if defined(MSVC) && defined(_M_AMD64) +# define ARCH_X86_64 +#elif (defined(GCC) || defined(__GNUC__) || defined(__clang__)) && defined(__x86_64__) +# define ARCH_X86_64 +#endif + +// Compatibility with non-Clang compilers. +#if !defined(__has_attribute) +# define __has_attribute(x) 0 +#endif + +// Compatibility with non-Clang compilers. +#if !defined(__has_declspec_attribute) +# define __has_declspec_attribute(x) 0 +#endif + +// Define the `DEPRECATED` macro. +#if defined(GCC) || defined(__GNUC__) || __has_attribute(deprecated) +# define DEPRECATED(message) __attribute__((deprecated(message))) +#elif defined(MSVC) || __has_declspec_attribute(deprecated) +# define DEPRECATED(message) __declspec(deprecated(message)) +#endif + +// The `compiler` feature has been enabled for this build. +#define WASMER_COMPILER_ENABLED + +// The `wasi` feature has been enabled for this build. +#define WASMER_WASI_ENABLED + +#endif // WASMER_WASM_H_MACROS + + +// +// OK, here we go. The code below is automatically generated. +// + #ifndef WASMER_WASM_H #define WASMER_WASM_H +#include +#include #include +#include #include "wasm.h" -#define own - -// In order to use WASI, we need a `wasi_env_t`, but first we need to configure it with -// a `wasi_config_t`. -// -// We get a `wasi_config_t` by building it with the `wasi_config_new` function and -// from there we can set arguments, environment variables, and standard file behavior. -// Then we can call `wasi_env_new` with the `wasi_config_t` and get a `wasi_env_t`. -// -// Once we have a `wasi_env_t` we must: -// - set it up with `wasi_env_set_memory` to expose a memory to the WASI host functions -// - call `wasi_get_imports` to get an array of imports needed to instantiate the Wasm module. - -// Used to build a `wasi_env_t`. -typedef struct wasi_config_t wasi_config_t; -// This type is passed to the WASI host functions owns the data core to the -// functioning of WASI. -typedef struct wasi_env_t wasi_env_t; - -// The version of WASI to use. -typedef uint32_t wasi_version_t; - -enum { - WASI_VERSION_LATEST = 0, - WASI_VERSION_SNAPSHOT0 = 1, - WASI_VERSION_SNAPSHOT1 = 2, - WASI_VERSION_INVALID = ~0 +enum wasm_valkind_enum { + WASM_I32 = 0, + WASM_I64 = 1, + WASM_F32 = 2, + WASM_F64 = 3, + WASM_ANYREF = 128, + WASM_FUNCREF = 129, }; +typedef uint8_t wasm_valkind_enum; -// Create a `wasi_config_t`. -// -// Takes as an argument the name of the Wasm program to execute (will show up -// as argv[0] to the Wasm program). -own wasi_config_t* wasi_config_new(const char* program_name); +typedef struct Arc_Instance Arc_Instance; -// Add an argument to be passed to the Wasi program. -void wasi_config_arg(wasi_config_t*, const char* arg); +typedef struct Arc_Module Arc_Module; -// Add an environment variable to be passed to the Wasi program. -void wasi_config_env(wasi_config_t*, const char* key, const char* value); +typedef struct Box_wasi_config_t Box_wasi_config_t; -// Have the WASI program print directly to stdout -void wasi_config_inherit_stdout(wasi_config_t*); +typedef struct Box_wasm_engine_t Box_wasm_engine_t; -// Have the WASI program print directly to stderr -void wasi_config_inherit_stderr(wasi_config_t*); +typedef struct Box_wasm_exporttype_t Box_wasm_exporttype_t; -// Have the WASI program read directly to stdin -//void wasi_config_inherit_stdin(wasi_config_t*); +typedef struct Box_wasm_externtype_t Box_wasm_externtype_t; -// Create a `wasi_env_t`. -own wasi_env_t* wasi_env_new(own wasi_config_t*); +typedef struct Box_wasm_global_t Box_wasm_global_t; -// Delete the `wasi_env_t`, used to clean up all the resources used by WASI. -void wasi_env_delete(own wasi_env_t*); +typedef struct Box_wasm_importtype_t Box_wasm_importtype_t; -// Get an array of imports that can be used to instantiate the given module. -bool wasi_get_imports(wasm_store_t* store, - const wasm_module_t* module, - wasi_env_t* wasi_env, - wasm_extern_t** imports); +typedef struct Box_wasm_memory_t Box_wasm_memory_t; -// Set up the `wasi_env_t` so that the WASI host functions can access WASI's memory. -// Returns whether or not it succeeded. -bool wasi_env_set_instance(wasi_env_t*, const wasm_instance_t*); +typedef struct Box_wasm_memorytype_t Box_wasm_memorytype_t; -// Set the memory in the `wasi_env_t` so that the WASI host functions can access WASI's memory. -// Returns whether or not it succeeded. -void wasi_env_set_memory(wasi_env_t*, const wasm_memory_t*); +typedef struct Box_wasm_table_t Box_wasm_table_t; -// Read from WASI's buffered stdout if stdout has not been inherited with -// `wasi_config_inherit_stdout`. -size_t wasi_env_read_stdout(wasi_env_t* env, - char* buffer, - size_t buffer_len); +typedef struct Box_wasm_tabletype_t Box_wasm_tabletype_t; -// Read from WASI's buffered stderr if stdout has not been inherited with -// `wasi_config_inherit_stderr`. -size_t wasi_env_read_stderr(wasi_env_t* env, - char* buffer, - size_t buffer_len); +typedef struct Box_wasm_valtype_t Box_wasm_valtype_t; -// Get the version of WASI needed by the given Wasm module. -wasi_version_t wasi_get_wasi_version(wasm_module_t*); +typedef struct Option_Arc_Instance Option_Arc_Instance; -// Get the start function which initializes the WASI state and calls main. -// -// The start function takes 0 arguments and returns 0 values. -own wasm_func_t* wasi_get_start_function(wasm_instance_t*); +typedef struct Option_Box_wasi_config_t Option_Box_wasi_config_t; -// Delete a `wasm_extern_t` allocated by the API. -void wasm_extern_delete(own wasm_extern_t*); +typedef struct Option_Box_wasi_env_t Option_Box_wasi_env_t; + +typedef struct Option_Box_wasm_engine_t Option_Box_wasm_engine_t; + +typedef struct Option_Box_wasm_extern_t Option_Box_wasm_extern_t; + +typedef struct Option_Box_wasm_externtype_t Option_Box_wasm_externtype_t; + +typedef struct Option_Box_wasm_func_t Option_Box_wasm_func_t; + +typedef struct Option_Box_wasm_functype_t Option_Box_wasm_functype_t; + +typedef struct Option_Box_wasm_global_t Option_Box_wasm_global_t; + +typedef struct Option_Box_wasm_globaltype_t Option_Box_wasm_globaltype_t; + +typedef struct Option_Box_wasm_importtype_t Option_Box_wasm_importtype_t; + +typedef struct Option_Box_wasm_instance_t Option_Box_wasm_instance_t; + +typedef struct Option_Box_wasm_memory_t Option_Box_wasm_memory_t; + +typedef struct Option_Box_wasm_memorytype_t Option_Box_wasm_memorytype_t; + +typedef struct Option_Box_wasm_module_t Option_Box_wasm_module_t; + +typedef struct Option_Box_wasm_table_t Option_Box_wasm_table_t; + +typedef struct Option_Box_wasm_tabletype_t Option_Box_wasm_tabletype_t; + +typedef struct Option_Box_wasm_valtype_t Option_Box_wasm_valtype_t; + +#if defined(WASMER_WASI_ENABLED) +typedef struct wasi_version_t wasi_version_t; +#endif + +typedef struct wasm_engine_t wasm_engine_t; + +typedef struct wasm_ref_t wasm_ref_t; + +#if defined(WASMER_WASI_ENABLED) +typedef struct { + bool inherit_stdout; + bool inherit_stderr; + bool inherit_stdin; + WasiStateBuilder state_builder; +} wasi_config_t; +#endif + +#if defined(WASMER_WASI_ENABLED) +typedef struct { + WasiEnv inner; +} wasi_env_t; +#endif + +typedef struct { + Arc_Instance inner; +} wasm_instance_t; + +typedef struct { + Memory inner; +} wasm_memory_t; + +/** + * Opaque wrapper around `Store` + */ +typedef struct { + +} wasm_store_t; + +typedef struct { + Arc_Module inner; +} wasm_module_t; + +typedef struct { + Option_Arc_Instance instance; + Extern inner; +} wasm_extern_t; + +/** + * this can be a wasmer-specific type with wasmer-specific functions for manipulating it + */ +typedef struct { + +} wasm_config_t; + +typedef wasm_byte_vec_t wasm_name_t; + +typedef ExternType wasm_externtype_t; + +typedef struct { + wasm_name_t *name; + wasm_externtype_t *extern_type; +} wasm_exporttype_t; + +typedef uint8_t wasm_externkind_t; + +typedef wasm_externtype_t wasm_functype_t; + +typedef wasm_externtype_t wasm_globaltype_t; + +typedef wasm_externtype_t wasm_memorytype_t; + +typedef struct { + wasm_externtype_t extern_; +} wasm_tabletype_t; + +typedef struct { + Function inner; + Option_Arc_Instance instance; +} wasm_func_t; + +typedef struct { + +} wasm_trap_t; + +typedef uint8_t wasm_valkind_t; + +typedef union { + int32_t int32_t; + int64_t int64_t; + float float32_t; + double float64_t; + wasm_ref_t *wref; +} wasm_val_inner; + +typedef struct { + wasm_valkind_t kind; + wasm_val_inner of; +} wasm_val_t; + +typedef wasm_trap_t *(*wasm_func_callback_t)(const wasm_val_t *args, wasm_val_t *results); + +typedef wasm_trap_t *(*wasm_func_callback_with_env_t)(void*, const wasm_val_t *args, wasm_val_t *results); + +typedef void (*wasm_env_finalizer_t)(void); + +typedef struct { + Global inner; +} wasm_global_t; + +typedef struct { + wasm_valkind_enum valkind; +} wasm_valtype_t; + +typedef uint8_t wasm_mutability_t; + +typedef struct { + wasm_name_t *module; + wasm_name_t *name; + wasm_externtype_t *extern_type; +} wasm_importtype_t; + +typedef struct { + uint32_t min; + uint32_t max; +} wasm_limits_t; + +typedef struct { + Table inner; +} wasm_table_t; + +typedef uint32_t wasm_table_size_t; + +#if defined(WASMER_WASI_ENABLED) +void wasi_config_arg(wasi_config_t *config, const char *arg); +#endif + +#if defined(WASMER_WASI_ENABLED) +void wasi_config_env(wasi_config_t *config, const char *key, const char *value); +#endif + +#if defined(WASMER_WASI_ENABLED) +void wasi_config_inherit_stderr(wasi_config_t *config); +#endif + +#if defined(WASMER_WASI_ENABLED) +void wasi_config_inherit_stdin(wasi_config_t *config); +#endif + +#if defined(WASMER_WASI_ENABLED) +void wasi_config_inherit_stdout(wasi_config_t *config); +#endif + +#if defined(WASMER_WASI_ENABLED) +Option_Box_wasi_config_t wasi_config_new(const char *program_name); +#endif + +#if defined(WASMER_WASI_ENABLED) +void wasi_env_delete(Option_Box_wasi_env_t _state); +#endif + +#if defined(WASMER_WASI_ENABLED) +/** + * Takes ownership over the `wasi_config_t`. + */ +Option_Box_wasi_env_t wasi_env_new(Box_wasi_config_t config); +#endif + +#if defined(WASMER_WASI_ENABLED) +intptr_t wasi_env_read_stderr(wasi_env_t *env, char *buffer, uintptr_t buffer_len); +#endif + +#if defined(WASMER_WASI_ENABLED) +intptr_t wasi_env_read_stdout(wasi_env_t *env, char *buffer, uintptr_t buffer_len); +#endif + +#if defined(WASMER_WASI_ENABLED) +bool wasi_env_set_instance(wasi_env_t *env, const wasm_instance_t *instance); +#endif + +#if defined(WASMER_WASI_ENABLED) +void wasi_env_set_memory(wasi_env_t *env, const wasm_memory_t *memory); +#endif + +#if defined(WASMER_WASI_ENABLED) +/** + * Takes ownership of `wasi_env_t`. + */ +bool wasi_get_imports(wasm_store_t *store, + const wasm_module_t *module, + const wasi_env_t *wasi_env, + wasm_extern_t **imports); +#endif + +#if defined(WASMER_WASI_ENABLED) +wasi_version_t wasi_get_wasi_version(const wasm_module_t *module); +#endif + +wasm_config_t *wasm_config_new(void); + +void wasm_engine_delete(Option_Box_wasm_engine_t _wasm_engine_address); + +Box_wasm_engine_t wasm_engine_new_with_config(wasm_config_t *_config_ptr); + +const wasm_name_t *wasm_exporttype_name(const wasm_exporttype_t *et); + +Box_wasm_exporttype_t wasm_exporttype_new(wasm_name_t *name, wasm_externtype_t *extern_type); + +const wasm_externtype_t *wasm_exporttype_type(const wasm_exporttype_t *et); + +Option_Box_wasm_func_t wasm_extern_as_func(wasm_extern_t *extern_ptr); + +Option_Box_wasm_global_t wasm_extern_as_global(wasm_extern_t *extern_ptr); + +Option_Box_wasm_memory_t wasm_extern_as_memory(wasm_extern_t *extern_ptr); + +Option_Box_wasm_table_t wasm_extern_as_table(wasm_extern_t *extern_ptr); + +wasm_externkind_t wasm_extern_kind(const wasm_extern_t *e); + +Box_wasm_externtype_t wasm_extern_type(const wasm_extern_t *e); + +const wasm_functype_t *wasm_externtype_as_functype(const wasm_externtype_t *et); + +const wasm_functype_t *wasm_externtype_as_functype_const(const wasm_externtype_t *et); + +const wasm_globaltype_t *wasm_externtype_as_globaltype(const wasm_externtype_t *et); + +const wasm_globaltype_t *wasm_externtype_as_globaltype_const(const wasm_externtype_t *et); + +const wasm_memorytype_t *wasm_externtype_as_memorytype(const wasm_externtype_t *et); + +const wasm_memorytype_t *wasm_externtype_as_memorytype_const(const wasm_externtype_t *et); + +const wasm_tabletype_t *wasm_externtype_as_tabletype(const wasm_externtype_t *et); + +const wasm_tabletype_t *wasm_externtype_as_tabletype_const(const wasm_externtype_t *et); + +void wasm_externtype_delete(Option_Box_wasm_externtype_t _et); + +wasm_externkind_t wasm_externtype_kind(const wasm_externtype_t *et); + +Option_Box_wasm_extern_t wasm_func_as_extern(wasm_func_t *func_ptr); + +wasm_trap_t *wasm_func_call(const wasm_func_t *func, const wasm_val_t *args, wasm_val_t *results); + +void wasm_func_delete(Option_Box_wasm_func_t _func); + +Option_Box_wasm_func_t wasm_func_new(wasm_store_t *store, + const wasm_functype_t *ft, + wasm_func_callback_t callback); + +Option_Box_wasm_func_t wasm_func_new_with_env(wasm_store_t *store, + const wasm_functype_t *ft, + wasm_func_callback_with_env_t callback, + void *env, + wasm_env_finalizer_t finalizer); + +uintptr_t wasm_func_param_arity(const wasm_func_t *func); + +uintptr_t wasm_func_result_arity(const wasm_func_t *func); + +const wasm_externtype_t *wasm_functype_as_externtype(const wasm_functype_t *ft); + +const wasm_externtype_t *wasm_functype_as_externtype_const(const wasm_functype_t *ft); + +Option_Box_wasm_functype_t wasm_functype_copy(wasm_functype_t *arg); + +void wasm_functype_delete(Option_Box_wasm_functype_t _ft); + +Option_Box_wasm_functype_t wasm_functype_new(wasm_valtype_vec_t *params, + wasm_valtype_vec_t *results); + +const wasm_valtype_vec_t *wasm_functype_params(const wasm_functype_t *ft); + +const wasm_valtype_vec_t *wasm_functype_results(const wasm_functype_t *ft); + +Option_Box_wasm_extern_t wasm_global_as_extern(wasm_global_t *global_ptr); + +Box_wasm_global_t wasm_global_copy(const wasm_global_t *wasm_global); + +void wasm_global_delete(Option_Box_wasm_global_t _global); + +void wasm_global_get(const wasm_global_t *wasm_global, wasm_val_t *out); + +Option_Box_wasm_global_t wasm_global_new(wasm_store_t *store_ptr, + const wasm_globaltype_t *gt, + const wasm_val_t *val); + +bool wasm_global_same(const wasm_global_t *wasm_global1, const wasm_global_t *wasm_global2); + +void wasm_global_set(wasm_global_t *wasm_global, const wasm_val_t *val); + +const wasm_externtype_t *wasm_globaltype_as_externtype(const wasm_globaltype_t *gt); + +const wasm_externtype_t *wasm_globaltype_as_externtype_const(const wasm_globaltype_t *gt); + +const wasm_valtype_t *wasm_globaltype_content(const wasm_globaltype_t *globaltype); + +void wasm_globaltype_delete(Option_Box_wasm_globaltype_t _globaltype); + +wasm_mutability_t wasm_globaltype_mutability(const wasm_globaltype_t *globaltype); + +Option_Box_wasm_globaltype_t wasm_globaltype_new(Option_Box_wasm_valtype_t valtype, + wasm_mutability_t mutability); + +void wasm_importtype_delete(Option_Box_wasm_importtype_t _importtype); + +const wasm_name_t *wasm_importtype_module(const wasm_importtype_t *et); + +const wasm_name_t *wasm_importtype_name(const wasm_importtype_t *et); + +Box_wasm_importtype_t wasm_importtype_new(wasm_name_t *module, + wasm_name_t *name, + wasm_externtype_t *extern_type); + +const wasm_externtype_t *wasm_importtype_type(const wasm_importtype_t *et); + +void wasm_instance_delete(Option_Box_wasm_instance_t _instance); + +void wasm_instance_exports(const wasm_instance_t *instance, wasm_extern_vec_t *out); + +Option_Box_wasm_instance_t wasm_instance_new(wasm_store_t *store, + const wasm_module_t *module, + const wasm_extern_t *const *imports, + wasm_trap_t **_traps); + +Option_Box_wasm_extern_t wasm_memory_as_extern(wasm_memory_t *memory_ptr); + +Box_wasm_memory_t wasm_memory_copy(const wasm_memory_t *wasm_memory); + +uint8_t *wasm_memory_data(wasm_memory_t *memory); + +uintptr_t wasm_memory_data_size(const wasm_memory_t *memory); + +void wasm_memory_delete(Option_Box_wasm_memory_t _memory); + +bool wasm_memory_grow(wasm_memory_t *memory, uint32_t delta); + +Option_Box_wasm_memory_t wasm_memory_new(wasm_store_t *store_ptr, const wasm_memorytype_t *mt); + +bool wasm_memory_same(const wasm_memory_t *wasm_memory1, const wasm_memory_t *wasm_memory2); + +uint32_t wasm_memory_size(const wasm_memory_t *memory); + +wasm_memorytype_t *wasm_memory_type(const wasm_memory_t *_memory_ptr); + +const wasm_externtype_t *wasm_memorytype_as_externtype(const wasm_memorytype_t *mt); + +const wasm_externtype_t *wasm_memorytype_as_externtype_const(const wasm_memorytype_t *mt); + +void wasm_memorytype_delete(Option_Box_wasm_memorytype_t _memorytype); + +const wasm_limits_t *wasm_memorytype_limits(const wasm_memorytype_t *mt); + +Box_wasm_memorytype_t wasm_memorytype_new(const wasm_limits_t *limits); + +void wasm_module_delete(Option_Box_wasm_module_t _module); + +wasm_module_t *wasm_module_deserialize(wasm_store_t *store_ptr, const wasm_byte_vec_t *bytes); + +void wasm_module_exports(const wasm_module_t *module, wasm_exporttype_vec_t *out); + +void wasm_module_imports(const wasm_module_t *module, wasm_importtype_vec_t *out); + +Option_Box_wasm_module_t wasm_module_new(wasm_store_t *store_ptr, const wasm_byte_vec_t *bytes); + +void wasm_module_serialize(const wasm_module_t *module, wasm_byte_vec_t *out_ptr); + +void wasm_store_delete(wasm_store_t *wasm_store); + +wasm_store_t *wasm_store_new(wasm_engine_t *wasm_engine_ptr); + +Option_Box_wasm_extern_t wasm_table_as_extern(wasm_table_t *table_ptr); + +Box_wasm_table_t wasm_table_copy(const wasm_table_t *wasm_table); + +void wasm_table_delete(Option_Box_wasm_table_t _table); + +bool wasm_table_grow(wasm_table_t *_wasm_table, wasm_table_size_t _delta, wasm_ref_t *_init); + +Option_Box_wasm_table_t wasm_table_new(wasm_store_t *store_ptr, + const wasm_tabletype_t *tt, + const wasm_ref_t *init); + +bool wasm_table_same(const wasm_table_t *wasm_table1, const wasm_table_t *wasm_table2); + +uintptr_t wasm_table_size(const wasm_table_t *wasm_table); + +const wasm_externtype_t *wasm_tabletype_as_externtype(const wasm_tabletype_t *tt); + +const wasm_externtype_t *wasm_tabletype_as_externtype_const(const wasm_tabletype_t *tt); + +void wasm_tabletype_delete(Option_Box_wasm_tabletype_t _tabletype); + +const wasm_valtype_t *wasm_tabletype_element(const wasm_tabletype_t *tabletype); + +const wasm_limits_t *wasm_tabletype_limits(const wasm_tabletype_t *tabletype); + +Box_wasm_tabletype_t wasm_tabletype_new(Box_wasm_valtype_t valtype, const wasm_limits_t *limits); + +void wasm_trap_delete(wasm_trap_t *trap); + +void wasm_trap_message(const wasm_trap_t *trap, wasm_byte_vec_t *out_ptr); + +void wasm_val_copy(wasm_val_t *out_ptr, const wasm_val_t *val); + +void wasm_val_delete(wasm_val_t *val); + +void wasm_valtype_delete(Option_Box_wasm_valtype_t _valtype); + +wasm_valkind_t wasm_valtype_kind(const wasm_valtype_t *valtype); + +Option_Box_wasm_valtype_t wasm_valtype_new(wasm_valkind_t kind); -// TODO: figure out if we can do less duplication. /** * Gets the length in bytes of the last error if any. * @@ -108,7 +545,7 @@ void wasm_extern_delete(own wasm_extern_t*); * * See `wasmer_last_error_message()` to get a full example. */ -int wasmer_last_error_length(); +int wasmer_last_error_length(void); /** * Gets the last error message if any into the provided buffer @@ -140,6 +577,6 @@ int wasmer_last_error_length(); * } * ``` */ -int wasmer_last_error_message(char* buffer, int length); +int wasmer_last_error_message(char *buffer, int length); #endif /* WASMER_WASM_H */ From d0de895efccea53dbc592852c3dc75e52d94bb6f Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Tue, 22 Sep 2020 17:02:12 +0200 Subject: [PATCH 031/281] doc(c-api) Clear `README.md` and symlink `wasm.h`. --- lib/c-api/README.md | 134 -------------------------------------------- lib/c-api/wasm.h | 1 + 2 files changed, 1 insertion(+), 134 deletions(-) create mode 120000 lib/c-api/wasm.h diff --git a/lib/c-api/README.md b/lib/c-api/README.md index 880845271..ceb9ef9eb 100644 --- a/lib/c-api/README.md +++ b/lib/c-api/README.md @@ -1,136 +1,2 @@ # `wasmer-c-api` [![Build Status](https://github.com/wasmerio/wasmer/workflows/build/badge.svg?style=flat-square)](https://github.com/wasmerio/wasmer/actions?query=workflow%3Abuild) [![Join Wasmer Slack](https://img.shields.io/static/v1?label=Slack&message=join%20chat&color=brighgreen&style=flat-square)](https://slack.wasmer.io) [![MIT License](https://img.shields.io/github/license/wasmerio/wasmer.svg?style=flat-square)](https://github.com/wasmerio/wasmer/blob/master/LICENSE) -This crate exposes a C and a C++ API for the Wasmer runtime. It also fully supports the [wasm-c-api common API](https://github.com/WebAssembly/wasm-c-api). - -## Usage - -Once you [install Wasmer in your system](https://github.com/wasmerio/wasmer-install), the *shared object files* and the *headers* will be automatically available **inside the Wasmer installed path**. - -The C ([`wasmer.h`][wasmer_h]) and C++ ([`wasmer.hh`][wasmer_hh]) header -files can be found in the Wasmer `include` directory: - -```bash -wasmer config --includedir -``` - -The runtime shared libraries (`.so`, `.dylib`, `.dll`) can be found in the Wasmer -`lib` directory: - -```bash -wasmer config --libdir -``` - -> Note: You can also download the libraries or header files directly -from [Wasmer release page]. - -The full C API documentation can be found here: -https://wasmerio.github.io/wasmer/c-api/ - -Here is a simple example to use the C API: - -```c -#include -#include "../wasmer.h" -#include -#include - -int main() -{ - // Read the Wasm file bytes. - FILE *file = fopen("sum.wasm", "r"); - fseek(file, 0, SEEK_END); - long len = ftell(file); - uint8_t *bytes = malloc(len); - fseek(file, 0, SEEK_SET); - fread(bytes, 1, len, file); - fclose(file); - - // Prepare the imports. - wasmer_import_t imports[] = {}; - - // Instantiate! - wasmer_instance_t *instance = NULL; - wasmer_result_t instantiation_result = wasmer_instantiate(&instance, bytes, len, imports, 0); - - assert(instantiation_result == WASMER_OK); - - // Let's call a function. - // Start by preparing the arguments. - - // Value of argument #1 is `7i32`. - wasmer_value_t argument_one; - argument_one.tag = WASM_I32; - argument_one.value.I32 = 7; - - // Value of argument #2 is `8i32`. - wasmer_value_t argument_two; - argument_two.tag = WASM_I32; - argument_two.value.I32 = 8; - - // Prepare the arguments. - wasmer_value_t arguments[] = {argument_one, argument_two}; - - // Prepare the return value. - wasmer_value_t result_one; - wasmer_value_t results[] = {result_one}; - - // Call the `sum` function with the prepared arguments and the return value. - wasmer_result_t call_result = wasmer_instance_call(instance, "sum", arguments, 2, results, 1); - - // Let's display the result. - printf("Call result: %d\n", call_result); - printf("Result: %d\n", results[0].value.I32); - - // `sum(7, 8) == 15`. - assert(results[0].value.I32 == 15); - assert(call_result == WASMER_OK); - - wasmer_instance_destroy(instance); - - return 0; -} -``` - -# Testing - -Tests are run using the release build of the library. If you make -changes or compile with non-default features, please ensure you -rebuild in release mode for the tests to see the changes. - -The tests can be run via `cargo test`, such as: - -```sh -$ cargo test --release -- --nocapture -``` - -To run tests manually, enter the `lib/c-api/tests` directory -and run the following commands: - -```sh -$ cmake . -$ make -$ make test -``` - -## pkg-config - -The Wasmer binary ships with an utility tool that outputs config -in the `pkg-config` format. - -You can use it like: - -```bash -wasmer config --pkg-config > $PKG_CONFIG_PATH/wasmer.pc -``` - -# License - -Wasmer is primarily distributed under the terms of the [MIT -license][mit-license] ([LICENSE][license]). - - -[wasmer_h]: ./wasmer.h -[wasmer_hh]: ./wasmer.hh -[mit-license]: http://opensource.org/licenses/MIT -[license]: https://github.com/wasmerio/wasmer/blob/master/LICENSE -[Wasmer release page]: https://github.com/wasmerio/wasmer/releases diff --git a/lib/c-api/wasm.h b/lib/c-api/wasm.h new file mode 120000 index 000000000..14a531199 --- /dev/null +++ b/lib/c-api/wasm.h @@ -0,0 +1 @@ +tests/wasm-c-api/include/wasm.h \ No newline at end of file From 5b72815a00180d79a5d9bbd303fc01c4fa80938f Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Tue, 22 Sep 2020 17:08:57 +0200 Subject: [PATCH 032/281] feat(c-api) Extract `engine` and `store` into their own module. --- lib/c-api/src/wasm_c_api/engine.rs | 69 +++++++++++++++++++ lib/c-api/src/wasm_c_api/mod.rs | 107 +++-------------------------- lib/c-api/src/wasm_c_api/store.rs | 28 ++++++++ 3 files changed, 105 insertions(+), 99 deletions(-) create mode 100644 lib/c-api/src/wasm_c_api/engine.rs create mode 100644 lib/c-api/src/wasm_c_api/store.rs diff --git a/lib/c-api/src/wasm_c_api/engine.rs b/lib/c-api/src/wasm_c_api/engine.rs new file mode 100644 index 000000000..e869f6744 --- /dev/null +++ b/lib/c-api/src/wasm_c_api/engine.rs @@ -0,0 +1,69 @@ +use cfg_if::cfg_if; +use std::sync::Arc; +use wasmer::Engine; + +/// this can be a wasmer-specific type with wasmer-specific functions for manipulating it +#[repr(C)] +pub struct wasm_config_t {} + +#[no_mangle] +pub extern "C" fn wasm_config_new() -> *mut wasm_config_t { + todo!("wasm_config_new") + //ptr::null_mut() +} + +#[repr(C)] +pub struct wasm_engine_t { + pub(crate) inner: Arc, +} + +cfg_if! { + if #[cfg(all(feature = "jit", feature = "compiler"))] { + // Compiler JIT + use wasmer_compiler::CompilerConfig; + fn get_default_compiler_config() -> Box { + cfg_if! { + if #[cfg(feature = "cranelift")] { + Box::new(wasmer_compiler_cranelift::Cranelift::default()) + } else if #[cfg(feature = "llvm")] { + Box::new(wasmer_compiler_llvm::LLVM::default()) + } else if #[cfg(feature = "singlepass")] { + Box::new(wasmer_compiler_singlepass::Singlepass::default()) + } else { + compile_error!("Please enable one of the compiler backends") + } + } + } + + #[no_mangle] + pub extern "C" fn wasm_engine_new() -> Box { + let compiler_config: Box = get_default_compiler_config(); + let engine: Arc = Arc::new(JIT::new(&*compiler_config).engine()); + Box::new(wasm_engine_t { inner: engine }) + } + } + else if #[cfg(feature = "jit")] { + // Headless JIT + #[no_mangle] + pub extern "C" fn wasm_engine_new() -> Box { + let engine: Arc = Arc::new(JIT::headless().engine()); + Box::new(wasm_engine_t { inner: engine }) + } + } + else { + #[no_mangle] + pub extern "C" fn wasm_engine_new() -> Box { + unimplemented!("The JITEngine is not attached"); + } + } +} + +#[no_mangle] +pub unsafe extern "C" fn wasm_engine_delete(_wasm_engine_address: Option>) {} + +#[no_mangle] +pub extern "C" fn wasm_engine_new_with_config( + _config_ptr: *mut wasm_config_t, +) -> Box { + wasm_engine_new() +} diff --git a/lib/c-api/src/wasm_c_api/mod.rs b/lib/c-api/src/wasm_c_api/mod.rs index 2d0ba26d0..2435ea518 100644 --- a/lib/c-api/src/wasm_c_api/mod.rs +++ b/lib/c-api/src/wasm_c_api/mod.rs @@ -1,97 +1,31 @@ //! entrypoints for the standard C API -use cfg_if::cfg_if; +pub mod engine; +pub mod store; +pub(crate) mod utils; +#[cfg(feature = "wasi")] +pub mod wasi; + use std::convert::{TryFrom, TryInto}; use std::ffi::c_void; use std::mem; use std::ptr::{self, NonNull}; use std::slice; use std::sync::Arc; +use store::wasm_store_t; use thiserror::Error; - -pub(crate) mod utils; -#[cfg(feature = "wasi")] -pub mod wasi; - // required due to really weird Rust resolution rules // https://github.com/rust-lang/rust/issues/57966 use crate::c_try; - use crate::ordered_resolver::OrderedResolver; use wasmer::{ - Engine, ExportType, Extern, ExternType, Function, FunctionType, Global, GlobalType, ImportType, + ExportType, Extern, ExternType, Function, FunctionType, Global, GlobalType, ImportType, Instance, Memory, MemoryType, Module, Mutability, Pages, RuntimeError, Store, Table, TableType, Val, ValType, }; #[cfg(feature = "jit")] use wasmer_engine_jit::JIT; -/// this can be a wasmer-specific type with wasmer-specific functions for manipulating it -#[repr(C)] -pub struct wasm_config_t {} - -#[no_mangle] -pub extern "C" fn wasm_config_new() -> *mut wasm_config_t { - todo!("wasm_config_new") - //ptr::null_mut() -} - -#[repr(C)] -pub struct wasm_engine_t { - pub(crate) inner: Arc, -} - -cfg_if! { - if #[cfg(all(feature = "jit", feature = "compiler"))] { - // Compiler JIT - use wasmer_compiler::CompilerConfig; - fn get_default_compiler_config() -> Box { - cfg_if! { - if #[cfg(feature = "cranelift")] { - Box::new(wasmer_compiler_cranelift::Cranelift::default()) - } else if #[cfg(feature = "llvm")] { - Box::new(wasmer_compiler_llvm::LLVM::default()) - } else if #[cfg(feature = "singlepass")] { - Box::new(wasmer_compiler_singlepass::Singlepass::default()) - } else { - compile_error!("Please enable one of the compiler backends") - } - } - } - - #[no_mangle] - pub extern "C" fn wasm_engine_new() -> Box { - let compiler_config: Box = get_default_compiler_config(); - let engine: Arc = Arc::new(JIT::new(&*compiler_config).engine()); - Box::new(wasm_engine_t { inner: engine }) - } - } - else if #[cfg(feature = "jit")] { - // Headless JIT - #[no_mangle] - pub extern "C" fn wasm_engine_new() -> Box { - let engine: Arc = Arc::new(JIT::headless().engine()); - Box::new(wasm_engine_t { inner: engine }) - } - } - else { - #[no_mangle] - pub extern "C" fn wasm_engine_new() -> Box { - unimplemented!("The JITEngine is not attached"); - } - } -} - -#[no_mangle] -pub unsafe extern "C" fn wasm_engine_delete(_wasm_engine_address: Option>) {} - -#[no_mangle] -pub extern "C" fn wasm_engine_new_with_config( - _config_ptr: *mut wasm_config_t, -) -> Box { - wasm_engine_new() -} - #[repr(C)] pub struct wasm_instance_t { inner: Arc, @@ -296,31 +230,6 @@ pub unsafe extern "C" fn wasm_module_serialize( mem::forget(byte_vec); } -/// Opaque wrapper around `Store` -#[repr(C)] -pub struct wasm_store_t {} - -#[no_mangle] -pub unsafe extern "C" fn wasm_store_new( - wasm_engine_ptr: Option>, -) -> Option> { - let wasm_engine_ptr = wasm_engine_ptr?; - let wasm_engine = wasm_engine_ptr.as_ref(); - let store = Store::new(&*wasm_engine.inner); - Some(NonNull::new_unchecked( - Box::into_raw(Box::new(store)) as *mut wasm_store_t - )) -} - -#[no_mangle] -pub unsafe extern "C" fn wasm_store_delete(wasm_store: Option>) { - if let Some(s_inner) = wasm_store { - // this should not leak memory: - // we should double check it to make sure though - let _: Box = Box::from_raw(s_inner.cast::().as_ptr()); - } -} - #[no_mangle] pub unsafe extern "C" fn wasm_func_as_extern( func_ptr: Option>, diff --git a/lib/c-api/src/wasm_c_api/store.rs b/lib/c-api/src/wasm_c_api/store.rs new file mode 100644 index 000000000..6eaa78bd8 --- /dev/null +++ b/lib/c-api/src/wasm_c_api/store.rs @@ -0,0 +1,28 @@ +use super::engine::wasm_engine_t; +use std::ptr::NonNull; +use wasmer::Store; + +/// Opaque wrapper around `Store` +#[repr(C)] +pub struct wasm_store_t {} + +#[no_mangle] +pub unsafe extern "C" fn wasm_store_new( + wasm_engine_ptr: Option>, +) -> Option> { + let wasm_engine_ptr = wasm_engine_ptr?; + let wasm_engine = wasm_engine_ptr.as_ref(); + let store = Store::new(&*wasm_engine.inner); + Some(NonNull::new_unchecked( + Box::into_raw(Box::new(store)) as *mut wasm_store_t + )) +} + +#[no_mangle] +pub unsafe extern "C" fn wasm_store_delete(wasm_store: Option>) { + if let Some(s_inner) = wasm_store { + // this should not leak memory: + // we should double check it to make sure though + let _: Box = Box::from_raw(s_inner.cast::().as_ptr()); + } +} From b63ce6e2cf5881a3a0cae0bf7ee9e4f3b4e542df Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Tue, 22 Sep 2020 17:15:52 +0200 Subject: [PATCH 033/281] feat(c-api) Extract `global` into its own module. --- lib/c-api/src/wasm_c_api/externals/global.rs | 61 ++++++++++++++++++ lib/c-api/src/wasm_c_api/externals/mod.rs | 1 + lib/c-api/src/wasm_c_api/mod.rs | 65 ++------------------ 3 files changed, 67 insertions(+), 60 deletions(-) create mode 100644 lib/c-api/src/wasm_c_api/externals/global.rs create mode 100644 lib/c-api/src/wasm_c_api/externals/mod.rs diff --git a/lib/c-api/src/wasm_c_api/externals/global.rs b/lib/c-api/src/wasm_c_api/externals/global.rs new file mode 100644 index 000000000..a89bf96e4 --- /dev/null +++ b/lib/c-api/src/wasm_c_api/externals/global.rs @@ -0,0 +1,61 @@ +use super::super::{store::wasm_store_t, wasm_globaltype_t, wasm_val_t}; +use std::convert::TryInto; +use std::ptr::NonNull; +use wasmer::{Global, Store, Val}; + +#[repr(C)] +pub struct wasm_global_t { + // maybe needs to hold onto instance + pub(crate) inner: Global, +} + +#[no_mangle] +pub unsafe extern "C" fn wasm_global_new( + store_ptr: Option>, + gt: &wasm_globaltype_t, + val: &wasm_val_t, +) -> Option> { + let gt = gt.as_globaltype(); + let wasm_val = val.try_into().ok()?; + let store_ptr: NonNull = store_ptr?.cast::(); + let store = store_ptr.as_ref(); + let global = if gt.mutability.is_mutable() { + Global::new_mut(store, wasm_val) + } else { + Global::new(store, wasm_val) + }; + + Some(Box::new(wasm_global_t { inner: global })) +} + +#[no_mangle] +pub unsafe extern "C" fn wasm_global_delete(_global: Option>) {} + +// TODO: figure out if these should be deep or shallow copies +#[no_mangle] +pub unsafe extern "C" fn wasm_global_copy(wasm_global: &wasm_global_t) -> Box { + // do shallow copy + Box::new(wasm_global_t { + inner: wasm_global.inner.clone(), + }) +} + +#[no_mangle] +pub unsafe extern "C" fn wasm_global_get(wasm_global: &wasm_global_t, out: &mut wasm_val_t) { + let value = wasm_global.inner.get(); + *out = value.try_into().unwrap(); +} + +#[no_mangle] +pub unsafe extern "C" fn wasm_global_set(wasm_global: &mut wasm_global_t, val: &wasm_val_t) { + let value: Val = val.try_into().unwrap(); + wasm_global.inner.set(value); +} + +#[no_mangle] +pub unsafe extern "C" fn wasm_global_same( + wasm_global1: &wasm_global_t, + wasm_global2: &wasm_global_t, +) -> bool { + wasm_global1.inner.same(&wasm_global2.inner) +} diff --git a/lib/c-api/src/wasm_c_api/externals/mod.rs b/lib/c-api/src/wasm_c_api/externals/mod.rs new file mode 100644 index 000000000..cdcd83a14 --- /dev/null +++ b/lib/c-api/src/wasm_c_api/externals/mod.rs @@ -0,0 +1 @@ +pub mod global; diff --git a/lib/c-api/src/wasm_c_api/mod.rs b/lib/c-api/src/wasm_c_api/mod.rs index 2435ea518..7b5da4200 100644 --- a/lib/c-api/src/wasm_c_api/mod.rs +++ b/lib/c-api/src/wasm_c_api/mod.rs @@ -1,6 +1,7 @@ //! entrypoints for the standard C API pub mod engine; +pub mod externals; pub mod store; pub(crate) mod utils; #[cfg(feature = "wasi")] @@ -18,10 +19,11 @@ use thiserror::Error; // https://github.com/rust-lang/rust/issues/57966 use crate::c_try; use crate::ordered_resolver::OrderedResolver; +use externals::global::wasm_global_t; use wasmer::{ - ExportType, Extern, ExternType, Function, FunctionType, Global, GlobalType, ImportType, - Instance, Memory, MemoryType, Module, Mutability, Pages, RuntimeError, Store, Table, TableType, - Val, ValType, + ExportType, Extern, ExternType, Function, FunctionType, GlobalType, ImportType, Instance, + Memory, MemoryType, Module, Mutability, Pages, RuntimeError, Store, Table, TableType, Val, + ValType, }; #[cfg(feature = "jit")] use wasmer_engine_jit::JIT; @@ -723,63 +725,6 @@ pub unsafe extern "C" fn wasm_func_result_arity(func: &wasm_func_t) -> usize { func.inner.ty().results().len() } -#[repr(C)] -pub struct wasm_global_t { - // maybe needs to hold onto instance - inner: Global, -} - -#[no_mangle] -pub unsafe extern "C" fn wasm_global_new( - store_ptr: Option>, - gt: &wasm_globaltype_t, - val: &wasm_val_t, -) -> Option> { - let gt = gt.as_globaltype(); - let wasm_val = val.try_into().ok()?; - let store_ptr: NonNull = store_ptr?.cast::(); - let store = store_ptr.as_ref(); - let global = if gt.mutability.is_mutable() { - Global::new_mut(store, wasm_val) - } else { - Global::new(store, wasm_val) - }; - - Some(Box::new(wasm_global_t { inner: global })) -} - -#[no_mangle] -pub unsafe extern "C" fn wasm_global_delete(_global: Option>) {} - -// TODO: figure out if these should be deep or shallow copies -#[no_mangle] -pub unsafe extern "C" fn wasm_global_copy(wasm_global: &wasm_global_t) -> Box { - // do shallow copy - Box::new(wasm_global_t { - inner: wasm_global.inner.clone(), - }) -} - -#[no_mangle] -pub unsafe extern "C" fn wasm_global_get(wasm_global: &wasm_global_t, out: &mut wasm_val_t) { - let value = wasm_global.inner.get(); - *out = value.try_into().unwrap(); -} - -#[no_mangle] -pub unsafe extern "C" fn wasm_global_set(wasm_global: &mut wasm_global_t, val: &wasm_val_t) { - let value: Val = val.try_into().unwrap(); - wasm_global.inner.set(value); -} - -#[no_mangle] -pub unsafe extern "C" fn wasm_global_same( - wasm_global1: &wasm_global_t, - wasm_global2: &wasm_global_t, -) -> bool { - wasm_global1.inner.same(&wasm_global2.inner) -} - #[repr(C)] pub struct wasm_memory_t { // maybe needs to hold onto instance From bc664b011d25ff2d430dce24579592945af24ba5 Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Tue, 22 Sep 2020 17:21:19 +0200 Subject: [PATCH 034/281] feat(c-api) Move `memory` into its own module. --- lib/c-api/src/wasm_c_api/externals/memory.rs | 74 +++++++++++++++++ lib/c-api/src/wasm_c_api/externals/mod.rs | 1 + lib/c-api/src/wasm_c_api/mod.rs | 83 ++------------------ lib/c-api/src/wasm_c_api/wasi/mod.rs | 3 +- 4 files changed, 84 insertions(+), 77 deletions(-) create mode 100644 lib/c-api/src/wasm_c_api/externals/memory.rs diff --git a/lib/c-api/src/wasm_c_api/externals/memory.rs b/lib/c-api/src/wasm_c_api/externals/memory.rs new file mode 100644 index 000000000..7933a3141 --- /dev/null +++ b/lib/c-api/src/wasm_c_api/externals/memory.rs @@ -0,0 +1,74 @@ +use super::super::{store::wasm_store_t, wasm_memorytype_t}; +use crate::c_try; +use std::mem; +use std::ptr::NonNull; +use wasmer::{Memory, Pages, Store}; + +#[repr(C)] +pub struct wasm_memory_t { + // maybe needs to hold onto instance + pub(crate) inner: Memory, +} + +#[no_mangle] +pub unsafe extern "C" fn wasm_memory_new( + store_ptr: Option>, + mt: &wasm_memorytype_t, +) -> Option> { + let md = mt.as_memorytype().clone(); + let store_ptr: NonNull = store_ptr?.cast::(); + let store = store_ptr.as_ref(); + + let memory = c_try!(Memory::new(store, md)); + Some(Box::new(wasm_memory_t { inner: memory })) +} + +#[no_mangle] +pub unsafe extern "C" fn wasm_memory_delete(_memory: Option>) {} + +// TODO: figure out if these should be deep or shallow copies +#[no_mangle] +pub unsafe extern "C" fn wasm_memory_copy(wasm_memory: &wasm_memory_t) -> Box { + // do shallow copy + Box::new(wasm_memory_t { + inner: wasm_memory.inner.clone(), + }) +} + +#[no_mangle] +pub unsafe extern "C" fn wasm_memory_type(_memory_ptr: &wasm_memory_t) -> *mut wasm_memorytype_t { + todo!("wasm_memory_type") +} + +// get a raw pointer into bytes +#[no_mangle] +pub unsafe extern "C" fn wasm_memory_data(memory: &mut wasm_memory_t) -> *mut u8 { + mem::transmute::<&[std::cell::Cell], &[u8]>(&memory.inner.view()[..]) as *const [u8] + as *const u8 as *mut u8 +} + +// size in bytes +#[no_mangle] +pub unsafe extern "C" fn wasm_memory_data_size(memory: &wasm_memory_t) -> usize { + memory.inner.size().bytes().0 +} + +// size in pages +#[no_mangle] +pub unsafe extern "C" fn wasm_memory_size(memory: &wasm_memory_t) -> u32 { + memory.inner.size().0 as _ +} + +// delta is in pages +#[no_mangle] +pub unsafe extern "C" fn wasm_memory_grow(memory: &mut wasm_memory_t, delta: u32) -> bool { + memory.inner.grow(Pages(delta)).is_ok() +} + +#[no_mangle] +pub unsafe extern "C" fn wasm_memory_same( + wasm_memory1: &wasm_memory_t, + wasm_memory2: &wasm_memory_t, +) -> bool { + wasm_memory1.inner.same(&wasm_memory2.inner) +} diff --git a/lib/c-api/src/wasm_c_api/externals/mod.rs b/lib/c-api/src/wasm_c_api/externals/mod.rs index cdcd83a14..15b8122e7 100644 --- a/lib/c-api/src/wasm_c_api/externals/mod.rs +++ b/lib/c-api/src/wasm_c_api/externals/mod.rs @@ -1 +1,2 @@ pub mod global; +pub mod memory; diff --git a/lib/c-api/src/wasm_c_api/mod.rs b/lib/c-api/src/wasm_c_api/mod.rs index 7b5da4200..465131687 100644 --- a/lib/c-api/src/wasm_c_api/mod.rs +++ b/lib/c-api/src/wasm_c_api/mod.rs @@ -7,6 +7,12 @@ pub(crate) mod utils; #[cfg(feature = "wasi")] pub mod wasi; +// required due to really weird Rust resolution rules +// https://github.com/rust-lang/rust/issues/57966 +use crate::c_try; +use crate::ordered_resolver::OrderedResolver; +use externals::global::wasm_global_t; +use externals::memory::wasm_memory_t; use std::convert::{TryFrom, TryInto}; use std::ffi::c_void; use std::mem; @@ -15,15 +21,9 @@ use std::slice; use std::sync::Arc; use store::wasm_store_t; use thiserror::Error; -// required due to really weird Rust resolution rules -// https://github.com/rust-lang/rust/issues/57966 -use crate::c_try; -use crate::ordered_resolver::OrderedResolver; -use externals::global::wasm_global_t; use wasmer::{ ExportType, Extern, ExternType, Function, FunctionType, GlobalType, ImportType, Instance, - Memory, MemoryType, Module, Mutability, Pages, RuntimeError, Store, Table, TableType, Val, - ValType, + MemoryType, Module, Mutability, Pages, RuntimeError, Store, Table, TableType, Val, ValType, }; #[cfg(feature = "jit")] use wasmer_engine_jit::JIT; @@ -725,75 +725,6 @@ pub unsafe extern "C" fn wasm_func_result_arity(func: &wasm_func_t) -> usize { func.inner.ty().results().len() } -#[repr(C)] -pub struct wasm_memory_t { - // maybe needs to hold onto instance - pub(crate) inner: Memory, -} - -#[no_mangle] -pub unsafe extern "C" fn wasm_memory_new( - store_ptr: Option>, - mt: &wasm_memorytype_t, -) -> Option> { - let md = mt.as_memorytype().clone(); - let store_ptr: NonNull = store_ptr?.cast::(); - let store = store_ptr.as_ref(); - - let memory = c_try!(Memory::new(store, md)); - Some(Box::new(wasm_memory_t { inner: memory })) -} - -#[no_mangle] -pub unsafe extern "C" fn wasm_memory_delete(_memory: Option>) {} - -// TODO: figure out if these should be deep or shallow copies -#[no_mangle] -pub unsafe extern "C" fn wasm_memory_copy(wasm_memory: &wasm_memory_t) -> Box { - // do shallow copy - Box::new(wasm_memory_t { - inner: wasm_memory.inner.clone(), - }) -} - -#[no_mangle] -pub unsafe extern "C" fn wasm_memory_type(_memory_ptr: &wasm_memory_t) -> *mut wasm_memorytype_t { - todo!("wasm_memory_type") -} - -// get a raw pointer into bytes -#[no_mangle] -pub unsafe extern "C" fn wasm_memory_data(memory: &mut wasm_memory_t) -> *mut u8 { - mem::transmute::<&[std::cell::Cell], &[u8]>(&memory.inner.view()[..]) as *const [u8] - as *const u8 as *mut u8 -} - -// size in bytes -#[no_mangle] -pub unsafe extern "C" fn wasm_memory_data_size(memory: &wasm_memory_t) -> usize { - memory.inner.size().bytes().0 -} - -// size in pages -#[no_mangle] -pub unsafe extern "C" fn wasm_memory_size(memory: &wasm_memory_t) -> u32 { - memory.inner.size().0 as _ -} - -// delta is in pages -#[no_mangle] -pub unsafe extern "C" fn wasm_memory_grow(memory: &mut wasm_memory_t, delta: u32) -> bool { - memory.inner.grow(Pages(delta)).is_ok() -} - -#[no_mangle] -pub unsafe extern "C" fn wasm_memory_same( - wasm_memory1: &wasm_memory_t, - wasm_memory2: &wasm_memory_t, -) -> bool { - wasm_memory1.inner.same(&wasm_memory2.inner) -} - #[repr(C)] pub struct wasm_table_t { // maybe needs to hold onto instance diff --git a/lib/c-api/src/wasm_c_api/wasi/mod.rs b/lib/c-api/src/wasm_c_api/wasi/mod.rs index 9b6d4529a..4a51240e7 100644 --- a/lib/c-api/src/wasm_c_api/wasi/mod.rs +++ b/lib/c-api/src/wasm_c_api/wasi/mod.rs @@ -5,7 +5,8 @@ mod capture_files; use super::{ - wasm_extern_t, wasm_func_t, wasm_instance_t, wasm_memory_t, wasm_module_t, wasm_store_t, + externals::memory::wasm_memory_t, wasm_extern_t, wasm_func_t, wasm_instance_t, wasm_module_t, + wasm_store_t, }; // required due to really weird Rust resolution rules for macros // https://github.com/rust-lang/rust/issues/57966 From c1056447f3526e9f0218361212fa564fb8cefe4e Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Tue, 22 Sep 2020 13:23:42 -0700 Subject: [PATCH 035/281] Fix up aarch64 release logic --- .github/workflows/main.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/main.yaml b/.github/workflows/main.yaml index eae48e621..78a49a006 100644 --- a/.github/workflows/main.yaml +++ b/.github/workflows/main.yaml @@ -210,7 +210,7 @@ jobs: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: upload_url: ${{ steps.create_release.outputs.upload_url }} - asset_path: artifacts/wasmer-linux-aarch64/wasmer-linux-aarch64.tar.gz + asset_path: artifacts/wasmer-linux-aarch64/wasmer-linux-arm64.tar.gz asset_name: wasmer-linux-aarch64.tar.gz asset_content_type: application/gzip From ac5627039d515d4223caa686a2c13471e64f4af3 Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Tue, 22 Sep 2020 15:26:00 -0700 Subject: [PATCH 036/281] Add C API to publish.py script Also update the amount of time we sleep between published crates, 10 seconds has proven to not be enough so we bump it to 16. --- scripts/publish.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/scripts/publish.py b/scripts/publish.py index 01b093f5b..7a1001a2d 100644 --- a/scripts/publish.py +++ b/scripts/publish.py @@ -21,7 +21,7 @@ except ImportError: # TODO: find this automatically -target_version = "1.0.0-alpha02.1" +target_version = "1.0.0-alpha3" # TODO: generate this by parsing toml files dep_graph = { @@ -43,6 +43,9 @@ dep_graph = { "wasmer-wasi": set(["wasmer"]), "wasmer-wasi-experimental-io-devices": set(["wasmer-wasi"]), "wasmer-emscripten": set(["wasmer"]), + "wasmer-c-api": set(["wasmer", "wasmer-compiler", "wasmer-compiler-cranelift", "wasmer-compiler-singlepass", + "wasmer-compiler-llvm", "wasmer-emscripten", "wasmer-engine", "wasmer-engine-jit", + "wasmer-engine-native", "wasmer-wasi", "wasmer-types"]), } # where each crate is located in the `lib` directory @@ -64,6 +67,7 @@ location = { "wasmer-wasi": "wasi", "wasmer-emscripten": "emscripten", "wasmer-wasi-experimental-io-devices": "wasi-experimental-io-devices", + "wasmer-c-api": "c-api", } no_dry_run = False @@ -116,11 +120,11 @@ def main(): else: print("`{}` was already published!".format(crate)) continue - # sleep for 10 seconds between crates to ensure the crates.io index has time to update + # sleep for 16 seconds between crates to ensure the crates.io index has time to update # this can be optimized with knowledge of our dep graph via toposort; we can even publish # crates in parallel; however this is out of scope for the first version of this script - print("Sleeping for 10 seconds to allow the `crates.io` index to update...") - time.sleep(10) + print("Sleeping for 16 seconds to allow the `crates.io` index to update...") + time.sleep(16) if __name__ == "__main__": From 9dc280f992b0fb6fee4420e1a32765b1b466e5dd Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Tue, 22 Sep 2020 15:29:37 -0700 Subject: [PATCH 037/281] Update binary-name.sh to be consistent and use aarch64 --- .github/workflows/main.yaml | 2 +- scripts/binary-name.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/main.yaml b/.github/workflows/main.yaml index 78a49a006..eae48e621 100644 --- a/.github/workflows/main.yaml +++ b/.github/workflows/main.yaml @@ -210,7 +210,7 @@ jobs: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: upload_url: ${{ steps.create_release.outputs.upload_url }} - asset_path: artifacts/wasmer-linux-aarch64/wasmer-linux-arm64.tar.gz + asset_path: artifacts/wasmer-linux-aarch64/wasmer-linux-aarch64.tar.gz asset_name: wasmer-linux-aarch64.tar.gz asset_content_type: application/gzip diff --git a/scripts/binary-name.sh b/scripts/binary-name.sh index 79e1ff5c6..af7f63c47 100755 --- a/scripts/binary-name.sh +++ b/scripts/binary-name.sh @@ -8,7 +8,7 @@ initArch() { # If you modify this list, please also modify install.sh case $ARCH in amd64|x86_64) ARCH="amd64";; - aarch64) ARCH="arm64";; + aarch64) ARCH="aarch64";; # i386) ARCH="386";; *) echo "Architecture ${ARCH} is not supported by this installation script"; exit 1;; esac From 79392e5d3359ca730c23c6d18c91356f8102c798 Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Tue, 22 Sep 2020 17:18:30 -0700 Subject: [PATCH 038/281] Fix bug with `default-native` feature in store.rs --- lib/api/src/store.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/api/src/store.rs b/lib/api/src/store.rs index bedf0415e..1fa44d333 100644 --- a/lib/api/src/store.rs +++ b/lib/api/src/store.rs @@ -94,14 +94,14 @@ impl Default for Store { } } - #[allow(unreachable_code)] - fn get_engine(config: impl CompilerConfig + Send + Sync) -> impl Engine + Send + Sync { + #[allow(unreachable_code, unused_mut)] + fn get_engine(mut config: impl CompilerConfig + Send + Sync) -> impl Engine + Send + Sync { cfg_if::cfg_if! { if #[cfg(feature = "default-jit")] { wasmer_engine_jit::JIT::new(&config) .engine() } else if #[cfg(feature = "default-native")] { - wasmer_engine_native::Native::new(&config) + wasmer_engine_native::Native::new(&mut config) .engine() } else { compile_error!("No default engine chosen") From 26f1f92dcc9a69b3778ba6e0b90c36cca8ca6b3d Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Wed, 23 Sep 2020 16:59:34 -0700 Subject: [PATCH 039/281] Remove install script from wasmer repo We're hosting it at github.com/wasmerio/wasmer-install now --- CHANGELOG.md | 1 + scripts/install.sh | 474 --------------------------------------------- 2 files changed, 1 insertion(+), 474 deletions(-) delete mode 100755 scripts/install.sh diff --git a/CHANGELOG.md b/CHANGELOG.md index 5a1863669..ea7288f06 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ # Changelog ## **[Unreleased]** +- [#1645](https://github.com/wasmerio/wasmer/pull/1645) Move the install script to https://github.com/wasmerio/wasmer-install ## 1.0.0-alpha3 - 2020-09-14 - [#1620](https://github.com/wasmerio/wasmer/pull/1620) Fix bug causing the Wapm binary to not be packaged with the release diff --git a/scripts/install.sh b/scripts/install.sh deleted file mode 100755 index 0e2f4f481..000000000 --- a/scripts/install.sh +++ /dev/null @@ -1,474 +0,0 @@ -#!/bin/sh - -# This install script is intended to download and install the latest available -# release of Wasmer. -# Installer script inspired by: -# 1) https://raw.githubusercontent.com/golang/dep/master/install.sh -# 2) https://sh.rustup.rs -# 3) https://yarnpkg.com/install.sh -# 4) https://raw.githubusercontent.com/brainsik/virtualenv-burrito/master/virtualenv-burrito.sh -# -# It attempts to identify the current platform and an error will be thrown if -# the platform is not supported. -# -# Environment variables: -# - INSTALL_DIRECTORY (optional): defaults to $HOME/.wasmer -# - WASMER_RELEASE_TAG (optional): defaults to fetching the latest release -# - WASMER_OS (optional): use a specific value for OS (mostly for testing) -# - WASMER_ARCH (optional): use a specific value for ARCH (mostly for testing) -# -# You can install using this script: -# $ curl https://raw.githubusercontent.com/wasmerio/wasmer/master/install.sh | sh - -set -e - -reset="\033[0m" -red="\033[31m" -green="\033[32m" -yellow="\033[33m" -cyan="\033[36m" -white="\033[37m" -bold="\e[1m" -dim="\e[2m" - -# Warning: Remove this on the public repo -RELEASES_URL="https://github.com/wasmerio/wasmer/releases" - -WASMER_VERBOSE="verbose" -if [ -z "$WASMER_INSTALL_LOG" ]; then - WASMER_INSTALL_LOG="$WASMER_VERBOSE" -fi - -wasmer_download_json() { - url="$2" - - # echo "Fetching $url.." - if test -x "$(command -v curl)"; then - response=$(curl --proto '=https' --tlsv1.2 -S -s -L -w 'HTTPSTATUS:%{http_code}' -H 'Accept: application/json' "$url") - body=$(echo "$response" | sed -e 's/HTTPSTATUS\:.*//g') - code=$(echo "$response" | tr -d '\n' | sed -e 's/.*HTTPSTATUS://') - elif test -x "$(command -v wget)"; then - temp=$(mktemp) - body=$(wget --https-only -q --header='Accept: application/json' -O - --server-response "$url" 2> "$temp") - code=$(awk '/^ HTTP/{print $2}' < "$temp" | tail -1) - rm "$temp" - else - printf "$red> Neither curl nor wget was available to perform http requests.$reset\n" - exit 1 - fi - if [ "$code" != 200 ]; then - printf "$red>File download failed with code $code.$reset\n" - exit 1 - fi - - eval "$1='$body'" -} - -wasmer_download_file() { - url="$1" - destination="$2" - - # echo "Fetching $url.." - if test -x "$(command -v curl)"; then - if [ "$WASMER_INSTALL_LOG" = "$WASMER_VERBOSE" ]; then - code=$(curl --progress-bar -w '%{http_code}' -L "$url" -o "$destination") - printf "\033[K\n\033[1A" - else - code=$(curl -s -w '%{http_code}' -L "$url" -o "$destination") - fi - elif test -x "$(command -v wget)"; then - if [ "$WASMER_INSTALL_LOG" = "$WASMER_VERBOSE" ]; then - code=$(wget --show-progress --progress=bar:force:noscroll -q -O "$destination" --server-response "$url" 2>&1 | awk '/^ HTTP/{print $2}' | tail -1) - printf "\033[K\n\033[1A"; - else - code=$(wget --quiet -O "$destination" --server-response "$url" 2>&1 | awk '/^ HTTP/{print $2}' | tail -1) - fi - else - printf "$red> Neither curl nor wget was available to perform http requests.$reset\n" - exit 1 - fi - - if [ "$code" = 404 ]; then - printf "$red> Your architecture is not yet supported ($OS-$ARCH).$reset\n" - echo "> Please open an issue on the project if you would like to use wasmer in your project: https://github.com/wasmerio/wasmer" - exit 1 - elif [ "$code" != 200 ]; then - printf "$red>File download failed with code $code.$reset\n" - exit 1 - fi -} - - -wasmer_detect_profile() { - if [ -n "${PROFILE}" ] && [ -f "${PROFILE}" ]; then - echo "${PROFILE}" - return - fi - - local DETECTED_PROFILE - DETECTED_PROFILE='' - local SHELLTYPE - SHELLTYPE="$(basename "/$SHELL")" - - if [ "$SHELLTYPE" = "bash" ]; then - if [ -f "$HOME/.bashrc" ]; then - DETECTED_PROFILE="$HOME/.bashrc" - elif [ -f "$HOME/.bash_profile" ]; then - DETECTED_PROFILE="$HOME/.bash_profile" - fi - elif [ "$SHELLTYPE" = "zsh" ]; then - DETECTED_PROFILE="$HOME/.zshrc" - elif [ "$SHELLTYPE" = "fish" ]; then - DETECTED_PROFILE="$HOME/.config/fish/config.fish" - fi - - if [ -z "$DETECTED_PROFILE" ]; then - if [ -f "$HOME/.profile" ]; then - DETECTED_PROFILE="$HOME/.profile" - elif [ -f "$HOME/.bashrc" ]; then - DETECTED_PROFILE="$HOME/.bashrc" - elif [ -f "$HOME/.bash_profile" ]; then - DETECTED_PROFILE="$HOME/.bash_profile" - elif [ -f "$HOME/.zshrc" ]; then - DETECTED_PROFILE="$HOME/.zshrc" - elif [ -f "$HOME/.config/fish/config.fish" ]; then - DETECTED_PROFILE="$HOME/.config/fish/config.fish" - fi - fi - - if [ ! -z "$DETECTED_PROFILE" ]; then - echo "$DETECTED_PROFILE" - fi -} - -wasmer_link() { - printf "$cyan> Adding to bash profile...$reset\n" - WASMER_PROFILE="$(wasmer_detect_profile)" - LOAD_STR="\n# Wasmer\nexport WASMER_DIR=\"$INSTALL_DIRECTORY\"\n[ -s \"\$WASMER_DIR/wasmer.sh\" ] && source \"\$WASMER_DIR/wasmer.sh\"\n" - SOURCE_STR="# Wasmer config\nexport WASMER_DIR=\"$INSTALL_DIRECTORY\"\nexport WASMER_CACHE_DIR=\"\$WASMER_DIR/cache\"\nexport PATH=\"\$WASMER_DIR/bin:\$PATH:\$WASMER_DIR/globals/wapm_packages/.bin\"\n" - - # We create the wasmer.sh file - printf "$SOURCE_STR" > "$INSTALL_DIRECTORY/wasmer.sh" - - if [ -z "${WASMER_PROFILE-}" ] ; then - printf "${red}Profile not found. Tried:\n* ${WASMER_PROFILE} (as defined in \$PROFILE)\n* ~/.bashrc\n* ~/.bash_profile\n* ~/.zshrc\n* ~/.profile.\n" - echo "\nHow to solve this issue?\n* Create one of them and run this script again" - echo "* Create it (touch ${WASMER_PROFILE}) and run this script again" - echo " OR" - printf "* Append the following lines to the correct file yourself:$reset\n" - command printf "${SOURCE_STR}" - else - if ! grep -q 'wasmer.sh' "$WASMER_PROFILE"; then - # if [[ $WASMER_PROFILE = *"fish"* ]]; then - # command fish -c 'set -U fish_user_paths $fish_user_paths ~/.wasmer/bin' - # else - command printf "$LOAD_STR" >> "$WASMER_PROFILE" - # fi - fi - printf "\033[1A$cyan> Adding to bash profile... ✓$reset\n" - if [ "$WASMER_INSTALL_LOG" = "$WASMER_VERBOSE" ]; then - printf "${dim}Note: We've added the following to your $WASMER_PROFILE\n" - echo "If you have a different profile please add the following:" - printf "$LOAD_STR$reset\n" - fi - - version=`$INSTALL_DIRECTORY/bin/wasmer --version` || ( - printf "$red> wasmer was installed, but doesn't seem to be working :($reset\n" - exit 1; - ) - - printf "$green> Successfully installed $version!\n" - if [ "$WASMER_INSTALL_LOG" = "$WASMER_VERBOSE" ]; then - printf "${reset}${dim}wasmer & wapm will be available the next time you open the terminal.\n" - printf "${reset}${dim}If you want to have the commands available now please execute:\n${reset}source $INSTALL_DIRECTORY/wasmer.sh$reset\n" - fi - fi -} - - -# findWasmerBinDirectory() { -# EFFECTIVE_WASMERPATH=$(wasmer env WASMERPATH) -# if [ -z "$EFFECTIVE_WASMERPATH" ]; then -# echo "Installation could not determine your \$WASMERPATH." -# exit 1 -# fi -# if [ -z "$WASMERBIN" ]; then -# WASMERBIN=$(echo "${EFFECTIVE_WASMERPATH%%:*}/bin" | sed s#//*#/#g) -# fi -# if [ ! -d "$WASMERBIN" ]; then -# echo "Installation requires your WASMERBIN directory $WASMERBIN to exist. Please create it." -# exit 1 -# fi -# eval "$1='$WASMERBIN'" -# } - -initArch() { - ARCH=$(uname -m) - if [ -n "$WASMER_ARCH" ]; then - printf "$cyan> Using WASMER_ARCH ($WASMER_ARCH).$reset\n" - ARCH="$WASMER_ARCH" - fi - # If you modify this list, please also modify scripts/binary-name.sh - case $ARCH in - amd64|x86_64) ARCH="amd64";; - aarch64) ARCH="arm64";; - # i386) ARCH="386";; - *) printf "$red> The system architecture (${ARCH}) is not supported by this installation script.$reset\n"; exit 1;; - esac - # echo "ARCH = $ARCH" -} - -initOS() { - OS=$(uname | tr '[:upper:]' '[:lower:]') - if [ -n "$WASMER_OS" ]; then - printf "$cyan> Using WASMER_OS ($WASMER_OS).$reset\n" - OS="$WASMER_OS" - fi - case "$OS" in - darwin) OS='darwin';; - linux) OS='linux';; - freebsd) OS='freebsd';; - # mingw*) OS='windows';; - # msys*) OS='windows';; - *) printf "$red> The OS (${OS}) is not supported by this installation script.$reset\n"; exit 1;; - esac - # echo "OS = $OS" -} - - -# unset profile -# test -z "$exclude_profile" && modify_profile -# if [ -n "$profile" ]; then -# if [ -e $HOME/${profile}.pre-wasmer ]; then -# backup=" The original\nwas saved to ~/$profile.pre-wasmer." -# fi -# fi - -# source $WASMERPATH/startup.sh - -wasmer_install() { - magenta1="${reset}\033[34;1m" - magenta2="" - magenta3="" - - if which wasmer >/dev/null; then - printf "${reset}Updating Wasmer and WAPM$reset\n" - else - printf "${reset}Installing Wasmer and WAPM!$reset\n" - if [ "$WASMER_INSTALL_LOG" = "$WASMER_VERBOSE" ]; then - printf " -${magenta1} ww -${magenta1} wwwww -${magenta1} ww wwwwww w -${magenta1} wwwww wwwwwwwww -${magenta1}ww wwwwww w wwwwwww -${magenta1}wwwww wwwwwwwwww wwwww -${magenta1}wwwwww w wwwwwww wwwww -${magenta1}wwwwwwwwwwwwww wwwww wwwww -${magenta1}wwwwwwwwwwwwwww wwwww wwwww -${magenta1}wwwwwwwwwwwwwww wwwww wwwww -${magenta1}wwwwwwwwwwwwwww wwwww wwwww -${magenta1}wwwwwwwwwwwwwww wwwww wwww -${magenta1}wwwwwwwwwwwwwww wwwww -${magenta1} wwwwwwwwwwww wwww -${magenta1} wwwwwwww -${magenta1} wwww -${reset} -" - fi - fi - -# if [ -d "$INSTALL_DIRECTORY" ]; then -# if which wasmer; then -# local latest_url -# local specified_version -# local version_type -# if [ "$1" = '--nightly' ]; then -# latest_url=https://nightly.wasmerpkg.com/latest-tar-version -# specified_version=`curl -sS $latest_url` -# version_type='latest' -# elif [ "$1" = '--version' ]; then -# specified_version=$2 -# version_type='specified' -# elif [ "$1" = '--rc' ]; then -# latest_url=https://wasmerpkg.com/latest-rc-version -# specified_version=`curl -sS $latest_url` -# version_type='rc' -# else -# latest_url=https://wasmerpkg.com/latest-version -# specified_version=`curl -sS $latest_url` -# version_type='latest' -# fi -# wasmer_version=`wasmer -V` -# wasmer_alt_version=`wasmer --version` - -# if [ "$specified_version" = "$wasmer_version" -o "$specified_version" = "$wasmer_alt_version" ]; then -# printf "$green> Wasmer is already at the $specified_version version.$reset\n" -# exit 0 -# else -# printf "$yellow> $wasmer_alt_version is already installed, Specified version: $specified_version.$reset\n" -# rm -rf "$INSTALL_DIRECTORY" -# fi -# else -# printf "$red> $INSTALL_DIRECTORY already exists, possibly from a past Wasmer install.$reset\n" -# printf "$red> Remove it (rm -rf $INSTALL_DIRECTORY) and run this script again.$reset\n" -# exit 0 -# fi -# fi - wasmer_download # $1 $2 - wasmer_link - wasmer_reset -} - - -wasmer_reset() { - unset -f wasmer_install wasmer_compareversions wasmer_reset wasmer_download_json wasmer_link wasmer_detect_profile wasmer_download_file wasmer_download wasmer_verify_or_quit -} - -# Example taken from -# https://stackoverflow.com/questions/4023830/how-to-compare-two-strings-in-dot-separated-version-format-in-bash -# wasmer_compareversions () { -# if [[ $1 = $2 ]] -# then -# echo "=" -# return 0 -# fi -# local IFS=. -# local i ver1=($1) ver2=($2) -# # fill empty fields in ver1 with zeros -# for ((i=${#ver1[@]}; i<${#ver2[@]}; i++)) -# do -# ver1[i]=0 -# done -# for ((i=0; i<${#ver1[@]}; i++)) -# do -# if [[ -z ${ver2[i]} ]] -# then -# # fill empty fields in ver2 with zeros -# ver2[i]=0 -# fi -# if ((10#${ver1[i]} > 10#${ver2[i]})) -# then -# echo ">" -# return 0 -# fi -# if ((10#${ver1[i]} < 10#${ver2[i]})) -# then -# echo "<" -# return 0 -# fi -# done -# echo "=" -# return 0 -# } - -version() { - echo "$@" | awk -F. '{ printf("%d%03d%03d%03d\n", $1,$2,$3,$4); }'; -} - -# TODO: Does not support versions with characters in them yet. Won't work for wasmer_compareversions "1.4.5-rc4" "1.4.5-r5" -wasmer_compareversions () { - WASMER_VERSION=$(version $1) - WASMER_COMPARE=$(version $2) - if [ $WASMER_VERSION = $WASMER_COMPARE ]; then - echo "=" - elif [ $WASMER_VERSION -gt $WASMER_COMPARE ]; then - echo ">" - elif [ $WASMER_VERSION -lt $WASMER_COMPARE ]; then - echo "<" - fi -} - -wasmer_download() { - # identify platform based on uname output - initArch - initOS - - # determine install directory if required - if [ -z "$INSTALL_DIRECTORY" ]; then - if [ -z "$WASMER_DIR" ]; then - # If WASMER_DIR is not present - INSTALL_DIRECTORY="$HOME/.wasmer" - else - # If WASMER_DIR is present - INSTALL_DIRECTORY="${WASMER_DIR}" - fi - fi - - # assemble expected release artifact name - BINARY="wasmer-${OS}-${ARCH}.tar.gz" - - # add .exe if on windows - # if [ "$OS" = "windows" ]; then - # BINARY="$BINARY.exe" - # fi - - # if WASMER_RELEASE_TAG was not provided, assume latest - if [ -z "$WASMER_RELEASE_TAG" ]; then - printf "$cyan> Getting wasmer releases...$reset\n" - wasmer_download_json LATEST_RELEASE "$RELEASES_URL/latest" - WASMER_RELEASE_TAG=$(echo "${LATEST_RELEASE}" | tr -s '\n' ' ' | sed 's/.*"tag_name":"//' | sed 's/".*//' ) - printf "\033[1A$cyan> Getting wasmer releases... ✓$reset\n" - fi - - if which wasmer >/dev/null; then - WASMER_VERSION=$(wasmer --version | sed 's/[a-z[:blank:]]//g') - WASMER_COMPARE=$(wasmer_compareversions $WASMER_VERSION $WASMER_RELEASE_TAG) - # printf "version: $WASMER_COMPARE\n" - case $WASMER_COMPARE in - # WASMER_VERSION = WASMER_RELEASE_TAG - "=") - printf "You are already on the latest release of wasmer: ${WASMER_RELEASE_TAG}\n"; - exit 0 - ;; - # WASMER_VERSION > WASMER_RELEASE_TAG - ">") - printf "You are on a more recent version ($WASMER_VERSION) than the published one (${WASMER_RELEASE_TAG})\n"; - exit 0 - ;; - # WASMER_VERSION < WASMER_RELEASE_TAG (we continue) - "<") - ;; - esac - fi - # fetch the real release data to make sure it exists before we attempt a download - wasmer_download_json RELEASE_DATA "$RELEASES_URL/tag/$WASMER_RELEASE_TAG" - - BINARY_URL="$RELEASES_URL/download/$WASMER_RELEASE_TAG/$BINARY" - DOWNLOAD_FILE=$(mktemp -t wasmer.XXXXXXXXXX) - - printf "$cyan> Downloading $WASMER_RELEASE_TAG release...$reset\n" - wasmer_download_file "$BINARY_URL" "$DOWNLOAD_FILE" - # echo -en "\b\b" - printf "\033[1A$cyan> Downloading $WASMER_RELEASE_TAG release... ✓$reset\n" - printf "\033[K\n\033[1A" - # printf "\033[1A$cyan> Downloaded$reset\033[K\n" - # echo "Setting executable permissions." - - # windows not supported yet - # if [ "$OS" = "windows" ]; then - # INSTALL_NAME="$INSTALL_NAME.exe" - # fi - - # echo "Moving executable to $INSTALL_DIRECTORY/$INSTALL_NAME" - - printf "$cyan> Unpacking contents...$reset\n" - - mkdir -p $INSTALL_DIRECTORY - # Untar the wasmer contents in the install directory - tar -C $INSTALL_DIRECTORY -zxf $DOWNLOAD_FILE - printf "\033[1A$cyan> Unpacking contents... ✓$reset\n" -} - -wasmer_verify_or_quit() { - read -p "$1 [y/N] " -n 1 -r - echo - if [[ ! $REPLY =~ ^[Yy]$ ]] - then - printf "$red> Aborting$reset\n" - exit 1 - fi -} - -# cd ~ -wasmer_install # $1 $2 From 95fa49d92dcbb3e5462fa20e333b51630d463683 Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Thu, 24 Sep 2020 08:51:37 +0200 Subject: [PATCH 040/281] feat(c-api) Move `table` into its own module. --- lib/c-api/src/wasm_c_api/externals/mod.rs | 1 + lib/c-api/src/wasm_c_api/externals/table.rs | 61 +++++++++++++++++++++ lib/c-api/src/wasm_c_api/mod.rs | 60 +------------------- 3 files changed, 64 insertions(+), 58 deletions(-) create mode 100644 lib/c-api/src/wasm_c_api/externals/table.rs diff --git a/lib/c-api/src/wasm_c_api/externals/mod.rs b/lib/c-api/src/wasm_c_api/externals/mod.rs index 15b8122e7..f81e700af 100644 --- a/lib/c-api/src/wasm_c_api/externals/mod.rs +++ b/lib/c-api/src/wasm_c_api/externals/mod.rs @@ -1,2 +1,3 @@ pub mod global; pub mod memory; +pub mod table; diff --git a/lib/c-api/src/wasm_c_api/externals/table.rs b/lib/c-api/src/wasm_c_api/externals/table.rs new file mode 100644 index 000000000..53472f37a --- /dev/null +++ b/lib/c-api/src/wasm_c_api/externals/table.rs @@ -0,0 +1,61 @@ +use super::super::{wasm_ref_t, wasm_store_t, wasm_table_size_t, wasm_tabletype_t}; +use crate::c_try; +use std::ptr::NonNull; +use wasmer::{Store, Table}; + +#[repr(C)] +pub struct wasm_table_t { + // maybe needs to hold onto instance + pub(crate) inner: Table, +} + +#[no_mangle] +pub unsafe extern "C" fn wasm_table_new( + store_ptr: Option>, + tt: &wasm_tabletype_t, + init: *const wasm_ref_t, +) -> Option> { + let tt = tt.as_tabletype().clone(); + let store_ptr: NonNull = store_ptr?.cast::(); + let store = store_ptr.as_ref(); + + let init_val = todo!("get val from init somehow"); + + let table = c_try!(Table::new(store, tt, init_val)); + Some(Box::new(wasm_table_t { inner: table })) +} + +#[no_mangle] +pub unsafe extern "C" fn wasm_table_delete(_table: Option>) {} + +#[no_mangle] +pub unsafe extern "C" fn wasm_table_copy(wasm_table: &wasm_table_t) -> Box { + // do shallow copy + Box::new(wasm_table_t { + inner: wasm_table.inner.clone(), + }) +} + +#[no_mangle] +pub unsafe extern "C" fn wasm_table_same( + wasm_table1: &wasm_table_t, + wasm_table2: &wasm_table_t, +) -> bool { + wasm_table1.inner.same(&wasm_table2.inner) +} + +#[no_mangle] +pub unsafe extern "C" fn wasm_table_size(wasm_table: &wasm_table_t) -> usize { + wasm_table.inner.size() as _ +} + +#[no_mangle] +pub unsafe extern "C" fn wasm_table_grow( + _wasm_table: &mut wasm_table_t, + _delta: wasm_table_size_t, + _init: *mut wasm_ref_t, +) -> bool { + // TODO: maybe need to look at result to return `true`; also maybe report error here + //wasm_table.inner.grow(delta, init).is_ok() + todo!("Blocked on transforming ExternRef into a val type") +} diff --git a/lib/c-api/src/wasm_c_api/mod.rs b/lib/c-api/src/wasm_c_api/mod.rs index 465131687..8bb3a450a 100644 --- a/lib/c-api/src/wasm_c_api/mod.rs +++ b/lib/c-api/src/wasm_c_api/mod.rs @@ -13,6 +13,7 @@ use crate::c_try; use crate::ordered_resolver::OrderedResolver; use externals::global::wasm_global_t; use externals::memory::wasm_memory_t; +use externals::table::wasm_table_t; use std::convert::{TryFrom, TryInto}; use std::ffi::c_void; use std::mem; @@ -23,7 +24,7 @@ use store::wasm_store_t; use thiserror::Error; use wasmer::{ ExportType, Extern, ExternType, Function, FunctionType, GlobalType, ImportType, Instance, - MemoryType, Module, Mutability, Pages, RuntimeError, Store, Table, TableType, Val, ValType, + MemoryType, Module, Mutability, Pages, RuntimeError, Store, TableType, Val, ValType, }; #[cfg(feature = "jit")] use wasmer_engine_jit::JIT; @@ -725,63 +726,6 @@ pub unsafe extern "C" fn wasm_func_result_arity(func: &wasm_func_t) -> usize { func.inner.ty().results().len() } -#[repr(C)] -pub struct wasm_table_t { - // maybe needs to hold onto instance - inner: Table, -} - -#[no_mangle] -pub unsafe extern "C" fn wasm_table_new( - store_ptr: Option>, - tt: &wasm_tabletype_t, - init: *const wasm_ref_t, -) -> Option> { - let tt = tt.as_tabletype().clone(); - let store_ptr: NonNull = store_ptr?.cast::(); - let store = store_ptr.as_ref(); - - let init_val = todo!("get val from init somehow"); - - let table = c_try!(Table::new(store, tt, init_val)); - Some(Box::new(wasm_table_t { inner: table })) -} - -#[no_mangle] -pub unsafe extern "C" fn wasm_table_delete(_table: Option>) {} - -#[no_mangle] -pub unsafe extern "C" fn wasm_table_copy(wasm_table: &wasm_table_t) -> Box { - // do shallow copy - Box::new(wasm_table_t { - inner: wasm_table.inner.clone(), - }) -} - -#[no_mangle] -pub unsafe extern "C" fn wasm_table_same( - wasm_table1: &wasm_table_t, - wasm_table2: &wasm_table_t, -) -> bool { - wasm_table1.inner.same(&wasm_table2.inner) -} - -#[no_mangle] -pub unsafe extern "C" fn wasm_table_size(wasm_table: &wasm_table_t) -> usize { - wasm_table.inner.size() as _ -} - -#[no_mangle] -pub unsafe extern "C" fn wasm_table_grow( - _wasm_table: &mut wasm_table_t, - _delta: wasm_table_size_t, - _init: *mut wasm_ref_t, -) -> bool { - // TODO: maybe need to look at result to return `true`; also maybe report error here - //wasm_table.inner.grow(delta, init).is_ok() - todo!("Blocked on transforming ExternRef into a val type") -} - macro_rules! wasm_declare_own { ($name:ident) => { paste::item! { From e7f06330c6164fc3769475bf0dee38f3416d45d5 Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Thu, 24 Sep 2020 08:56:28 +0200 Subject: [PATCH 041/281] feat(c-api) Move `function` into its own module. --- .../src/wasm_c_api/externals/function.rs | 169 ++++++++++++++++++ lib/c-api/src/wasm_c_api/externals/mod.rs | 1 + lib/c-api/src/wasm_c_api/mod.rs | 163 +---------------- 3 files changed, 173 insertions(+), 160 deletions(-) create mode 100644 lib/c-api/src/wasm_c_api/externals/function.rs diff --git a/lib/c-api/src/wasm_c_api/externals/function.rs b/lib/c-api/src/wasm_c_api/externals/function.rs new file mode 100644 index 000000000..bf31d852c --- /dev/null +++ b/lib/c-api/src/wasm_c_api/externals/function.rs @@ -0,0 +1,169 @@ +use super::super::{ + wasm_functype_t, wasm_store_t, wasm_trap_t, wasm_val_inner, wasm_val_t, wasm_valkind_enum, +}; +use std::convert::TryInto; +use std::ffi::c_void; +use std::ptr::NonNull; +use std::sync::Arc; +use wasmer::{Function, Instance, RuntimeError, Store, Val}; + +#[repr(C)] +pub struct wasm_func_t { + pub(crate) inner: Function, + // this is how we ensure the instance stays alive + pub(crate) instance: Option>, +} + +#[allow(non_camel_case_types)] +pub type wasm_func_callback_t = + unsafe extern "C" fn(args: *const wasm_val_t, results: *mut wasm_val_t) -> *mut wasm_trap_t; + +#[allow(non_camel_case_types)] +pub type wasm_func_callback_with_env_t = unsafe extern "C" fn( + *mut c_void, + args: *const wasm_val_t, + results: *mut wasm_val_t, +) -> *mut wasm_trap_t; + +#[allow(non_camel_case_types)] +pub type wasm_env_finalizer_t = unsafe extern "C" fn(c_void); + +#[no_mangle] +pub unsafe extern "C" fn wasm_func_new( + store: Option>, + ft: &wasm_functype_t, + callback: wasm_func_callback_t, +) -> Option> { + // TODO: handle null pointers? + let store_ptr = store?.cast::(); + let store = store_ptr.as_ref(); + let func_sig = ft.sig(); + let num_rets = func_sig.results().len(); + let inner_callback = move |args: &[Val]| -> Result, RuntimeError> { + let processed_args = args + .into_iter() + .map(TryInto::try_into) + .collect::, _>>() + .expect("Argument conversion failed"); + + let mut results = vec![ + wasm_val_t { + kind: wasm_valkind_enum::WASM_I64 as _, + of: wasm_val_inner { int64_t: 0 }, + }; + num_rets + ]; + + let _traps = callback(processed_args.as_ptr(), results.as_mut_ptr()); + // TODO: do something with `traps` + + let processed_results = results + .into_iter() + .map(TryInto::try_into) + .collect::, _>>() + .expect("Result conversion failed"); + Ok(processed_results) + }; + let f = Function::new(store, &func_sig, inner_callback); + Some(Box::new(wasm_func_t { + instance: None, + inner: f, + })) +} + +#[no_mangle] +pub unsafe extern "C" fn wasm_func_new_with_env( + store: Option>, + ft: &wasm_functype_t, + callback: wasm_func_callback_with_env_t, + env: *mut c_void, + finalizer: wasm_env_finalizer_t, +) -> Option> { + // TODO: handle null pointers? + let store_ptr = store?.cast::(); + let store = store_ptr.as_ref(); + let func_sig = ft.sig(); + let num_rets = func_sig.results().len(); + let inner_callback = + move |env: &mut *mut c_void, args: &[Val]| -> Result, RuntimeError> { + let processed_args = args + .into_iter() + .map(TryInto::try_into) + .collect::, _>>() + .expect("Argument conversion failed"); + + let mut results = vec![ + wasm_val_t { + kind: wasm_valkind_enum::WASM_I64 as _, + of: wasm_val_inner { int64_t: 0 }, + }; + num_rets + ]; + + let _traps = callback(*env, processed_args.as_ptr(), results.as_mut_ptr()); + // TODO: do something with `traps` + + let processed_results = results + .into_iter() + .map(TryInto::try_into) + .collect::, _>>() + .expect("Result conversion failed"); + Ok(processed_results) + }; + let f = Function::new_with_env(store, &func_sig, env, inner_callback); + Some(Box::new(wasm_func_t { + instance: None, + inner: f, + })) +} + +#[no_mangle] +pub unsafe extern "C" fn wasm_func_delete(_func: Option>) {} + +#[no_mangle] +pub unsafe extern "C" fn wasm_func_call( + func: &wasm_func_t, + args: *const wasm_val_t, + results: *mut wasm_val_t, +) -> Option> { + let num_params = func.inner.ty().params().len(); + let params: Vec = (0..num_params) + .map(|i| (&(*args.add(i))).try_into()) + .collect::>() + .ok()?; + + match func.inner.call(¶ms) { + Ok(wasm_results) => { + for (i, actual_result) in wasm_results.iter().enumerate() { + let result_loc = &mut (*results.add(i)); + *result_loc = (&*actual_result).try_into().ok()?; + } + None + } + Err(e) => Some(NonNull::new_unchecked(Box::into_raw(Box::new(e)) as _)), + } +} + +#[no_mangle] +pub unsafe extern "C" fn wasm_func_param_arity(func: &wasm_func_t) -> usize { + func.inner.ty().params().len() +} + +#[no_mangle] +pub unsafe extern "C" fn wasm_func_result_arity(func: &wasm_func_t) -> usize { + func.inner.ty().results().len() +} + +macro_rules! wasm_declare_own { + ($name:ident) => { + paste::item! { + #[repr(C)] + pub struct [] {} + + #[no_mangle] + pub extern "C" fn [](_arg: *mut []) { + todo!("in generated delete") + } + } + }; +} diff --git a/lib/c-api/src/wasm_c_api/externals/mod.rs b/lib/c-api/src/wasm_c_api/externals/mod.rs index f81e700af..6f39bfe81 100644 --- a/lib/c-api/src/wasm_c_api/externals/mod.rs +++ b/lib/c-api/src/wasm_c_api/externals/mod.rs @@ -1,3 +1,4 @@ +pub mod function; pub mod global; pub mod memory; pub mod table; diff --git a/lib/c-api/src/wasm_c_api/mod.rs b/lib/c-api/src/wasm_c_api/mod.rs index 8bb3a450a..1ac143845 100644 --- a/lib/c-api/src/wasm_c_api/mod.rs +++ b/lib/c-api/src/wasm_c_api/mod.rs @@ -11,6 +11,7 @@ pub mod wasi; // https://github.com/rust-lang/rust/issues/57966 use crate::c_try; use crate::ordered_resolver::OrderedResolver; +use externals::function::wasm_func_t; use externals::global::wasm_global_t; use externals::memory::wasm_memory_t; use externals::table::wasm_table_t; @@ -23,8 +24,8 @@ use std::sync::Arc; use store::wasm_store_t; use thiserror::Error; use wasmer::{ - ExportType, Extern, ExternType, Function, FunctionType, GlobalType, ImportType, Instance, - MemoryType, Module, Mutability, Pages, RuntimeError, Store, TableType, Val, ValType, + ExportType, Extern, ExternType, FunctionType, GlobalType, ImportType, Instance, MemoryType, + Module, Mutability, Pages, RuntimeError, Store, TableType, Val, ValType, }; #[cfg(feature = "jit")] use wasmer_engine_jit::JIT; @@ -579,167 +580,9 @@ impl TryFrom<&Val> for wasm_val_t { } } -#[allow(non_camel_case_types)] -pub type wasm_func_callback_t = - unsafe extern "C" fn(args: *const wasm_val_t, results: *mut wasm_val_t) -> *mut wasm_trap_t; - -#[allow(non_camel_case_types)] -pub type wasm_func_callback_with_env_t = unsafe extern "C" fn( - *mut c_void, - args: *const wasm_val_t, - results: *mut wasm_val_t, -) -> *mut wasm_trap_t; - #[allow(non_camel_case_types)] pub type wasm_env_finalizer_t = unsafe extern "C" fn(c_void); -#[repr(C)] -pub struct wasm_func_t { - inner: Function, - // this is how we ensure the instance stays alive - instance: Option>, -} - -#[no_mangle] -pub unsafe extern "C" fn wasm_func_new( - store: Option>, - ft: &wasm_functype_t, - callback: wasm_func_callback_t, -) -> Option> { - // TODO: handle null pointers? - let store_ptr = store?.cast::(); - let store = store_ptr.as_ref(); - let func_sig = ft.sig(); - let num_rets = func_sig.results().len(); - let inner_callback = move |args: &[Val]| -> Result, RuntimeError> { - let processed_args = args - .into_iter() - .map(TryInto::try_into) - .collect::, _>>() - .expect("Argument conversion failed"); - - let mut results = vec![ - wasm_val_t { - kind: wasm_valkind_enum::WASM_I64 as _, - of: wasm_val_inner { int64_t: 0 }, - }; - num_rets - ]; - - let _traps = callback(processed_args.as_ptr(), results.as_mut_ptr()); - // TODO: do something with `traps` - - let processed_results = results - .into_iter() - .map(TryInto::try_into) - .collect::, _>>() - .expect("Result conversion failed"); - Ok(processed_results) - }; - let f = Function::new(store, &func_sig, inner_callback); - Some(Box::new(wasm_func_t { - instance: None, - inner: f, - })) -} - -#[no_mangle] -pub unsafe extern "C" fn wasm_func_new_with_env( - store: Option>, - ft: &wasm_functype_t, - callback: wasm_func_callback_with_env_t, - env: *mut c_void, - finalizer: wasm_env_finalizer_t, -) -> Option> { - // TODO: handle null pointers? - let store_ptr = store?.cast::(); - let store = store_ptr.as_ref(); - let func_sig = ft.sig(); - let num_rets = func_sig.results().len(); - let inner_callback = - move |env: &mut *mut c_void, args: &[Val]| -> Result, RuntimeError> { - let processed_args = args - .into_iter() - .map(TryInto::try_into) - .collect::, _>>() - .expect("Argument conversion failed"); - - let mut results = vec![ - wasm_val_t { - kind: wasm_valkind_enum::WASM_I64 as _, - of: wasm_val_inner { int64_t: 0 }, - }; - num_rets - ]; - - let _traps = callback(*env, processed_args.as_ptr(), results.as_mut_ptr()); - // TODO: do something with `traps` - - let processed_results = results - .into_iter() - .map(TryInto::try_into) - .collect::, _>>() - .expect("Result conversion failed"); - Ok(processed_results) - }; - let f = Function::new_with_env(store, &func_sig, env, inner_callback); - Some(Box::new(wasm_func_t { - instance: None, - inner: f, - })) -} - -#[no_mangle] -pub unsafe extern "C" fn wasm_func_delete(_func: Option>) {} - -#[no_mangle] -pub unsafe extern "C" fn wasm_func_call( - func: &wasm_func_t, - args: *const wasm_val_t, - results: *mut wasm_val_t, -) -> Option> { - let num_params = func.inner.ty().params().len(); - let params: Vec = (0..num_params) - .map(|i| (&(*args.add(i))).try_into()) - .collect::>() - .ok()?; - - match func.inner.call(¶ms) { - Ok(wasm_results) => { - for (i, actual_result) in wasm_results.iter().enumerate() { - let result_loc = &mut (*results.add(i)); - *result_loc = (&*actual_result).try_into().ok()?; - } - None - } - Err(e) => Some(NonNull::new_unchecked(Box::into_raw(Box::new(e)) as _)), - } -} - -#[no_mangle] -pub unsafe extern "C" fn wasm_func_param_arity(func: &wasm_func_t) -> usize { - func.inner.ty().params().len() -} - -#[no_mangle] -pub unsafe extern "C" fn wasm_func_result_arity(func: &wasm_func_t) -> usize { - func.inner.ty().results().len() -} - -macro_rules! wasm_declare_own { - ($name:ident) => { - paste::item! { - #[repr(C)] - pub struct [] {} - - #[no_mangle] - pub extern "C" fn [](_arg: *mut []) { - todo!("in generated delete") - } - } - }; -} - macro_rules! wasm_declare_vec_inner { ($name:ident) => { paste::item! { From 7bb7684823962dca23ba81d89b76ea665bb8cdf5 Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Thu, 24 Sep 2020 09:06:37 +0200 Subject: [PATCH 042/281] feat(c-api) Move `value` into its own module. --- .../src/wasm_c_api/externals/function.rs | 5 +- lib/c-api/src/wasm_c_api/externals/global.rs | 3 +- lib/c-api/src/wasm_c_api/mod.rs | 133 +----------------- lib/c-api/src/wasm_c_api/value.rs | 129 +++++++++++++++++ 4 files changed, 136 insertions(+), 134 deletions(-) create mode 100644 lib/c-api/src/wasm_c_api/value.rs diff --git a/lib/c-api/src/wasm_c_api/externals/function.rs b/lib/c-api/src/wasm_c_api/externals/function.rs index bf31d852c..e6389ac85 100644 --- a/lib/c-api/src/wasm_c_api/externals/function.rs +++ b/lib/c-api/src/wasm_c_api/externals/function.rs @@ -1,6 +1,5 @@ -use super::super::{ - wasm_functype_t, wasm_store_t, wasm_trap_t, wasm_val_inner, wasm_val_t, wasm_valkind_enum, -}; +use super::super::value::{wasm_val_inner, wasm_val_t}; +use super::super::{wasm_functype_t, wasm_store_t, wasm_trap_t, wasm_valkind_enum}; use std::convert::TryInto; use std::ffi::c_void; use std::ptr::NonNull; diff --git a/lib/c-api/src/wasm_c_api/externals/global.rs b/lib/c-api/src/wasm_c_api/externals/global.rs index a89bf96e4..26d882815 100644 --- a/lib/c-api/src/wasm_c_api/externals/global.rs +++ b/lib/c-api/src/wasm_c_api/externals/global.rs @@ -1,4 +1,5 @@ -use super::super::{store::wasm_store_t, wasm_globaltype_t, wasm_val_t}; +use super::super::value::wasm_val_t; +use super::super::{store::wasm_store_t, wasm_globaltype_t}; use std::convert::TryInto; use std::ptr::NonNull; use wasmer::{Global, Store, Val}; diff --git a/lib/c-api/src/wasm_c_api/mod.rs b/lib/c-api/src/wasm_c_api/mod.rs index 1ac143845..94dd30591 100644 --- a/lib/c-api/src/wasm_c_api/mod.rs +++ b/lib/c-api/src/wasm_c_api/mod.rs @@ -4,6 +4,7 @@ pub mod engine; pub mod externals; pub mod store; pub(crate) mod utils; +pub mod value; #[cfg(feature = "wasi")] pub mod wasi; @@ -16,16 +17,16 @@ use externals::global::wasm_global_t; use externals::memory::wasm_memory_t; use externals::table::wasm_table_t; use std::convert::{TryFrom, TryInto}; -use std::ffi::c_void; use std::mem; use std::ptr::{self, NonNull}; use std::slice; use std::sync::Arc; use store::wasm_store_t; use thiserror::Error; +use value::wasm_valkind_t; use wasmer::{ ExportType, Extern, ExternType, FunctionType, GlobalType, ImportType, Instance, MemoryType, - Module, Mutability, Pages, RuntimeError, Store, TableType, Val, ValType, + Module, Mutability, Pages, RuntimeError, Store, TableType, ValType, }; #[cfg(feature = "jit")] use wasmer_engine_jit::JIT; @@ -401,9 +402,6 @@ impl From for wasm_mutability_enum { } } -#[allow(non_camel_case_types)] -pub type wasm_valkind_t = u8; - impl From for ValType { fn from(other: wasm_valkind_enum) -> Self { use wasm_valkind_enum::*; @@ -458,131 +456,6 @@ impl From for wasm_valkind_enum { } } -#[repr(C)] -#[derive(Clone, Copy)] -pub union wasm_val_inner { - int32_t: i32, - int64_t: i64, - float32_t: f32, - float64_t: f64, - wref: *mut wasm_ref_t, -} - -#[repr(C)] -pub struct wasm_val_t { - kind: wasm_valkind_t, - of: wasm_val_inner, -} - -impl Clone for wasm_val_t { - fn clone(&self) -> Self { - wasm_val_t { - kind: self.kind, - of: self.of.clone(), - } - } -} - -#[no_mangle] -pub unsafe extern "C" fn wasm_val_copy(out_ptr: *mut wasm_val_t, val: &wasm_val_t) { - (*out_ptr).kind = val.kind; - (*out_ptr).of = - // TODO: handle this error - match val.kind.try_into().unwrap() { - wasm_valkind_enum::WASM_I32 => wasm_val_inner { int32_t: val.of.int32_t }, - wasm_valkind_enum::WASM_I64 => wasm_val_inner { int64_t: val.of.int64_t }, - wasm_valkind_enum::WASM_F32 => wasm_val_inner { float32_t: val.of.float32_t }, - wasm_valkind_enum::WASM_F64 => wasm_val_inner { float64_t: val.of.float64_t }, - wasm_valkind_enum::WASM_ANYREF => wasm_val_inner { wref: val.of.wref }, - wasm_valkind_enum::WASM_FUNCREF => wasm_val_inner { wref: val.of.wref }, - }; -} - -#[no_mangle] -pub unsafe extern "C" fn wasm_val_delete(val: Option>) { - if let Some(v_inner) = val { - // TODO: figure out where wasm_val is allocated first... - let _ = Box::from_raw(v_inner.as_ptr()); - } -} - -impl TryFrom for wasm_valkind_enum { - type Error = &'static str; - - fn try_from(item: wasm_valkind_t) -> Result { - Ok(match item { - 0 => wasm_valkind_enum::WASM_I32, - 1 => wasm_valkind_enum::WASM_I64, - 2 => wasm_valkind_enum::WASM_F32, - 3 => wasm_valkind_enum::WASM_F64, - 128 => wasm_valkind_enum::WASM_ANYREF, - 129 => wasm_valkind_enum::WASM_FUNCREF, - _ => return Err("valkind value out of bounds"), - }) - } -} - -impl TryFrom for Val { - type Error = &'static str; - - fn try_from(item: wasm_val_t) -> Result { - (&item).try_into() - } -} - -impl TryFrom<&wasm_val_t> for Val { - type Error = &'static str; - - fn try_from(item: &wasm_val_t) -> Result { - Ok(match item.kind.try_into()? { - wasm_valkind_enum::WASM_I32 => Val::I32(unsafe { item.of.int32_t }), - wasm_valkind_enum::WASM_I64 => Val::I64(unsafe { item.of.int64_t }), - wasm_valkind_enum::WASM_F32 => Val::F32(unsafe { item.of.float32_t }), - wasm_valkind_enum::WASM_F64 => Val::F64(unsafe { item.of.float64_t }), - wasm_valkind_enum::WASM_ANYREF => return Err("ANYREF not supported at this time"), - wasm_valkind_enum::WASM_FUNCREF => return Err("FUNCREF not supported at this time"), - }) - } -} - -impl TryFrom for wasm_val_t { - type Error = &'static str; - - fn try_from(item: Val) -> Result { - wasm_val_t::try_from(&item) - } -} - -impl TryFrom<&Val> for wasm_val_t { - type Error = &'static str; - - fn try_from(item: &Val) -> Result { - Ok(match *item { - Val::I32(v) => wasm_val_t { - of: wasm_val_inner { int32_t: v }, - kind: wasm_valkind_enum::WASM_I32 as _, - }, - Val::I64(v) => wasm_val_t { - of: wasm_val_inner { int64_t: v }, - kind: wasm_valkind_enum::WASM_I64 as _, - }, - Val::F32(v) => wasm_val_t { - of: wasm_val_inner { float32_t: v }, - kind: wasm_valkind_enum::WASM_F32 as _, - }, - Val::F64(v) => wasm_val_t { - of: wasm_val_inner { float64_t: v }, - kind: wasm_valkind_enum::WASM_F64 as _, - }, - Val::V128(_) => return Err("128bit SIMD types not yet supported in Wasm C API"), - _ => todo!("Handle these values in TryFrom for wasm_val_t"), - }) - } -} - -#[allow(non_camel_case_types)] -pub type wasm_env_finalizer_t = unsafe extern "C" fn(c_void); - macro_rules! wasm_declare_vec_inner { ($name:ident) => { paste::item! { diff --git a/lib/c-api/src/wasm_c_api/value.rs b/lib/c-api/src/wasm_c_api/value.rs new file mode 100644 index 000000000..0fc7071ad --- /dev/null +++ b/lib/c-api/src/wasm_c_api/value.rs @@ -0,0 +1,129 @@ +use super::{wasm_ref_t, wasm_valkind_enum}; +use std::convert::{TryFrom, TryInto}; +use std::ptr::NonNull; +use wasmer::Val; + +#[allow(non_camel_case_types)] +pub type wasm_valkind_t = u8; + +#[repr(C)] +#[derive(Clone, Copy)] +pub union wasm_val_inner { + pub(crate) int32_t: i32, + pub(crate) int64_t: i64, + pub(crate) float32_t: f32, + pub(crate) float64_t: f64, + pub(crate) wref: *mut wasm_ref_t, +} + +#[repr(C)] +pub struct wasm_val_t { + pub(crate) kind: wasm_valkind_t, + pub(crate) of: wasm_val_inner, +} + +impl Clone for wasm_val_t { + fn clone(&self) -> Self { + wasm_val_t { + kind: self.kind, + of: self.of.clone(), + } + } +} + +#[no_mangle] +pub unsafe extern "C" fn wasm_val_copy(out_ptr: *mut wasm_val_t, val: &wasm_val_t) { + (*out_ptr).kind = val.kind; + (*out_ptr).of = + // TODO: handle this error + match val.kind.try_into().unwrap() { + wasm_valkind_enum::WASM_I32 => wasm_val_inner { int32_t: val.of.int32_t }, + wasm_valkind_enum::WASM_I64 => wasm_val_inner { int64_t: val.of.int64_t }, + wasm_valkind_enum::WASM_F32 => wasm_val_inner { float32_t: val.of.float32_t }, + wasm_valkind_enum::WASM_F64 => wasm_val_inner { float64_t: val.of.float64_t }, + wasm_valkind_enum::WASM_ANYREF => wasm_val_inner { wref: val.of.wref }, + wasm_valkind_enum::WASM_FUNCREF => wasm_val_inner { wref: val.of.wref }, + }; +} + +#[no_mangle] +pub unsafe extern "C" fn wasm_val_delete(val: Option>) { + if let Some(v_inner) = val { + // TODO: figure out where wasm_val is allocated first... + let _ = Box::from_raw(v_inner.as_ptr()); + } +} + +impl TryFrom for wasm_valkind_enum { + type Error = &'static str; + + fn try_from(item: wasm_valkind_t) -> Result { + Ok(match item { + 0 => wasm_valkind_enum::WASM_I32, + 1 => wasm_valkind_enum::WASM_I64, + 2 => wasm_valkind_enum::WASM_F32, + 3 => wasm_valkind_enum::WASM_F64, + 128 => wasm_valkind_enum::WASM_ANYREF, + 129 => wasm_valkind_enum::WASM_FUNCREF, + _ => return Err("valkind value out of bounds"), + }) + } +} + +impl TryFrom for Val { + type Error = &'static str; + + fn try_from(item: wasm_val_t) -> Result { + (&item).try_into() + } +} + +impl TryFrom<&wasm_val_t> for Val { + type Error = &'static str; + + fn try_from(item: &wasm_val_t) -> Result { + Ok(match item.kind.try_into()? { + wasm_valkind_enum::WASM_I32 => Val::I32(unsafe { item.of.int32_t }), + wasm_valkind_enum::WASM_I64 => Val::I64(unsafe { item.of.int64_t }), + wasm_valkind_enum::WASM_F32 => Val::F32(unsafe { item.of.float32_t }), + wasm_valkind_enum::WASM_F64 => Val::F64(unsafe { item.of.float64_t }), + wasm_valkind_enum::WASM_ANYREF => return Err("ANYREF not supported at this time"), + wasm_valkind_enum::WASM_FUNCREF => return Err("FUNCREF not supported at this time"), + }) + } +} + +impl TryFrom for wasm_val_t { + type Error = &'static str; + + fn try_from(item: Val) -> Result { + wasm_val_t::try_from(&item) + } +} + +impl TryFrom<&Val> for wasm_val_t { + type Error = &'static str; + + fn try_from(item: &Val) -> Result { + Ok(match *item { + Val::I32(v) => wasm_val_t { + of: wasm_val_inner { int32_t: v }, + kind: wasm_valkind_enum::WASM_I32 as _, + }, + Val::I64(v) => wasm_val_t { + of: wasm_val_inner { int64_t: v }, + kind: wasm_valkind_enum::WASM_I64 as _, + }, + Val::F32(v) => wasm_val_t { + of: wasm_val_inner { float32_t: v }, + kind: wasm_valkind_enum::WASM_F32 as _, + }, + Val::F64(v) => wasm_val_t { + of: wasm_val_inner { float64_t: v }, + kind: wasm_valkind_enum::WASM_F64 as _, + }, + Val::V128(_) => return Err("128bit SIMD types not yet supported in Wasm C API"), + _ => todo!("Handle these values in TryFrom for wasm_val_t"), + }) + } +} From 9b292ad9a7f523d9131382383af5e8fa784ad403 Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Thu, 24 Sep 2020 09:10:03 +0200 Subject: [PATCH 043/281] feat(c-api) Move `module` into its own module. --- lib/c-api/src/wasm_c_api/mod.rs | 111 +-------------------------- lib/c-api/src/wasm_c_api/module.rs | 117 +++++++++++++++++++++++++++++ 2 files changed, 120 insertions(+), 108 deletions(-) create mode 100644 lib/c-api/src/wasm_c_api/module.rs diff --git a/lib/c-api/src/wasm_c_api/mod.rs b/lib/c-api/src/wasm_c_api/mod.rs index 94dd30591..4a6a62aaa 100644 --- a/lib/c-api/src/wasm_c_api/mod.rs +++ b/lib/c-api/src/wasm_c_api/mod.rs @@ -2,6 +2,7 @@ pub mod engine; pub mod externals; +pub mod module; pub mod store; pub(crate) mod utils; pub mod value; @@ -16,6 +17,7 @@ use externals::function::wasm_func_t; use externals::global::wasm_global_t; use externals::memory::wasm_memory_t; use externals::table::wasm_table_t; +use module::wasm_module_t; use std::convert::{TryFrom, TryInto}; use std::mem; use std::ptr::{self, NonNull}; @@ -26,7 +28,7 @@ use thiserror::Error; use value::wasm_valkind_t; use wasmer::{ ExportType, Extern, ExternType, FunctionType, GlobalType, ImportType, Instance, MemoryType, - Module, Mutability, Pages, RuntimeError, Store, TableType, ValType, + Mutability, Pages, RuntimeError, TableType, ValType, }; #[cfg(feature = "jit")] use wasmer_engine_jit::JIT; @@ -128,113 +130,6 @@ pub unsafe extern "C" fn wasm_instance_exports( mem::forget(extern_vec); } -#[repr(C)] -pub struct wasm_module_t { - pub(crate) inner: Arc, -} - -#[no_mangle] -pub unsafe extern "C" fn wasm_module_new( - store_ptr: Option>, - bytes: &wasm_byte_vec_t, -) -> Option> { - // TODO: review lifetime of byte slice - let wasm_byte_slice: &[u8] = slice::from_raw_parts_mut(bytes.data, bytes.size); - let store_ptr: NonNull = store_ptr?.cast::(); - let store = store_ptr.as_ref(); - let module = c_try!(Module::from_binary(store, wasm_byte_slice)); - - Some(Box::new(wasm_module_t { - inner: Arc::new(module), - })) -} - -#[no_mangle] -pub unsafe extern "C" fn wasm_module_delete(_module: Option>) {} - -#[no_mangle] -pub unsafe extern "C" fn wasm_module_exports( - module: &wasm_module_t, - out: &mut wasm_exporttype_vec_t, -) { - let mut exports = module - .inner - .exports() - .map(Into::into) - .map(Box::new) - .map(Box::into_raw) - .collect::>(); - - debug_assert_eq!(exports.len(), exports.capacity()); - out.size = exports.len(); - out.data = exports.as_mut_ptr(); - mem::forget(exports); -} - -#[no_mangle] -pub unsafe extern "C" fn wasm_module_imports( - module: &wasm_module_t, - out: &mut wasm_importtype_vec_t, -) { - let mut imports = module - .inner - .imports() - .map(Into::into) - .map(Box::new) - .map(Box::into_raw) - .collect::>(); - - debug_assert_eq!(imports.len(), imports.capacity()); - out.size = imports.len(); - out.data = imports.as_mut_ptr(); - mem::forget(imports); -} - -#[no_mangle] -pub unsafe extern "C" fn wasm_module_deserialize( - store_ptr: Option>, - bytes: *const wasm_byte_vec_t, -) -> Option> { - // TODO: read config from store and use that to decide which compiler to use - - let byte_slice = if bytes.is_null() || (&*bytes).into_slice().is_none() { - // TODO: error handling here - return None; - } else { - (&*bytes).into_slice().unwrap() - }; - - let store_ptr: NonNull = store_ptr?.cast::(); - let store = store_ptr.as_ref(); - let module = c_try!(Module::deserialize(store, byte_slice)); - - Some(NonNull::new_unchecked(Box::into_raw(Box::new( - wasm_module_t { - inner: Arc::new(module), - }, - )))) -} - -#[no_mangle] -pub unsafe extern "C" fn wasm_module_serialize( - module: &wasm_module_t, - out_ptr: &mut wasm_byte_vec_t, -) { - let mut byte_vec = match module.inner.serialize() { - Ok(mut byte_vec) => { - byte_vec.shrink_to_fit(); - byte_vec - } - Err(_) => return, - }; - // ensure we won't leak memory - // TODO: use `Vec::into_raw_parts` when it becomes stable - debug_assert_eq!(byte_vec.capacity(), byte_vec.len()); - out_ptr.size = byte_vec.len(); - out_ptr.data = byte_vec.as_mut_ptr(); - mem::forget(byte_vec); -} - #[no_mangle] pub unsafe extern "C" fn wasm_func_as_extern( func_ptr: Option>, diff --git a/lib/c-api/src/wasm_c_api/module.rs b/lib/c-api/src/wasm_c_api/module.rs new file mode 100644 index 000000000..f2c8f9741 --- /dev/null +++ b/lib/c-api/src/wasm_c_api/module.rs @@ -0,0 +1,117 @@ +use super::{ + wasm_byte_vec_t, wasm_exporttype_t, wasm_exporttype_vec_t, wasm_importtype_t, + wasm_importtype_vec_t, wasm_store_t, +}; +use crate::c_try; +use std::mem; +use std::ptr::NonNull; +use std::slice; +use std::sync::Arc; +use wasmer::{Module, Store}; + +#[repr(C)] +pub struct wasm_module_t { + pub(crate) inner: Arc, +} + +#[no_mangle] +pub unsafe extern "C" fn wasm_module_new( + store_ptr: Option>, + bytes: &wasm_byte_vec_t, +) -> Option> { + // TODO: review lifetime of byte slice + let wasm_byte_slice: &[u8] = slice::from_raw_parts_mut(bytes.data, bytes.size); + let store_ptr: NonNull = store_ptr?.cast::(); + let store = store_ptr.as_ref(); + let module = c_try!(Module::from_binary(store, wasm_byte_slice)); + + Some(Box::new(wasm_module_t { + inner: Arc::new(module), + })) +} + +#[no_mangle] +pub unsafe extern "C" fn wasm_module_delete(_module: Option>) {} + +#[no_mangle] +pub unsafe extern "C" fn wasm_module_exports( + module: &wasm_module_t, + out: &mut wasm_exporttype_vec_t, +) { + let mut exports = module + .inner + .exports() + .map(Into::into) + .map(Box::new) + .map(Box::into_raw) + .collect::>(); + + debug_assert_eq!(exports.len(), exports.capacity()); + out.size = exports.len(); + out.data = exports.as_mut_ptr(); + mem::forget(exports); +} + +#[no_mangle] +pub unsafe extern "C" fn wasm_module_imports( + module: &wasm_module_t, + out: &mut wasm_importtype_vec_t, +) { + let mut imports = module + .inner + .imports() + .map(Into::into) + .map(Box::new) + .map(Box::into_raw) + .collect::>(); + + debug_assert_eq!(imports.len(), imports.capacity()); + out.size = imports.len(); + out.data = imports.as_mut_ptr(); + mem::forget(imports); +} + +#[no_mangle] +pub unsafe extern "C" fn wasm_module_deserialize( + store_ptr: Option>, + bytes: *const wasm_byte_vec_t, +) -> Option> { + // TODO: read config from store and use that to decide which compiler to use + + let byte_slice = if bytes.is_null() || (&*bytes).into_slice().is_none() { + // TODO: error handling here + return None; + } else { + (&*bytes).into_slice().unwrap() + }; + + let store_ptr: NonNull = store_ptr?.cast::(); + let store = store_ptr.as_ref(); + let module = c_try!(Module::deserialize(store, byte_slice)); + + Some(NonNull::new_unchecked(Box::into_raw(Box::new( + wasm_module_t { + inner: Arc::new(module), + }, + )))) +} + +#[no_mangle] +pub unsafe extern "C" fn wasm_module_serialize( + module: &wasm_module_t, + out_ptr: &mut wasm_byte_vec_t, +) { + let mut byte_vec = match module.inner.serialize() { + Ok(mut byte_vec) => { + byte_vec.shrink_to_fit(); + byte_vec + } + Err(_) => return, + }; + // ensure we won't leak memory + // TODO: use `Vec::into_raw_parts` when it becomes stable + debug_assert_eq!(byte_vec.capacity(), byte_vec.len()); + out_ptr.size = byte_vec.len(); + out_ptr.data = byte_vec.as_mut_ptr(); + mem::forget(byte_vec); +} From 50fbb9766d3ba592d29e6996d4d69dd9ddaa383f Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Thu, 24 Sep 2020 09:19:53 +0200 Subject: [PATCH 044/281] feat(c-api) Move `instance` into its own module. --- lib/c-api/src/wasm_c_api/instance.rs | 104 +++++++++++++++++++++++++++ lib/c-api/src/wasm_c_api/mod.rs | 99 +------------------------ lib/c-api/src/wasm_c_api/wasi/mod.rs | 4 +- 3 files changed, 107 insertions(+), 100 deletions(-) create mode 100644 lib/c-api/src/wasm_c_api/instance.rs diff --git a/lib/c-api/src/wasm_c_api/instance.rs b/lib/c-api/src/wasm_c_api/instance.rs new file mode 100644 index 000000000..d58336e62 --- /dev/null +++ b/lib/c-api/src/wasm_c_api/instance.rs @@ -0,0 +1,104 @@ +use super::{wasm_extern_t, wasm_extern_vec_t, wasm_module_t, wasm_store_t, wasm_trap_t}; +use crate::c_try; +use crate::ordered_resolver::OrderedResolver; +use std::mem; +use std::ptr::NonNull; +use std::sync::Arc; +use wasmer::{Extern, Instance}; + +#[repr(C)] +pub struct wasm_instance_t { + pub(crate) inner: Arc, +} + +struct CArrayIter { + cur_entry: *const *const T, +} + +impl CArrayIter { + fn new(array: *const *const T) -> Option { + if array.is_null() { + None + } else { + Some(CArrayIter { cur_entry: array }) + } + } +} + +impl Iterator for CArrayIter { + type Item = &'static T; + + fn next(&mut self) -> Option { + let next_entry_candidate = unsafe { *self.cur_entry }; + if next_entry_candidate.is_null() { + None + } else { + self.cur_entry = unsafe { self.cur_entry.add(1) }; + Some(unsafe { &*next_entry_candidate }) + } + } +} + +// reads from null-terminated array of `wasm_extern_t`s +unsafe fn argument_import_iter( + imports: *const *const wasm_extern_t, +) -> Box> { + CArrayIter::new(imports) + .map(|it| Box::new(it) as _) + .unwrap_or_else(|| Box::new(std::iter::empty()) as _) +} + +#[no_mangle] +pub unsafe extern "C" fn wasm_instance_new( + store: Option>, + module: &wasm_module_t, + imports: *const *const wasm_extern_t, + // own + _traps: *mut *mut wasm_trap_t, +) -> Option> { + let wasm_module = &module.inner; + let module_imports = wasm_module.imports(); + let module_import_count = module_imports.len(); + let imports = argument_import_iter(imports); + let resolver: OrderedResolver = imports + .map(|imp| &imp.inner) + .take(module_import_count) + .cloned() + .collect(); + + let instance = Arc::new(c_try!(Instance::new(wasm_module, &resolver))); + Some(Box::new(wasm_instance_t { inner: instance })) +} + +#[no_mangle] +pub unsafe extern "C" fn wasm_instance_delete(_instance: Option>) {} + +#[no_mangle] +pub unsafe extern "C" fn wasm_instance_exports( + instance: &wasm_instance_t, + // TODO: review types on wasm_declare_vec, handle the optional pointer part properly + out: &mut wasm_extern_vec_t, +) { + let instance = &instance.inner; + let mut extern_vec = instance + .exports + .iter() + .map(|(name, r#extern)| { + let function = if let Extern::Function { .. } = r#extern { + instance.exports.get_function(&name).ok().cloned() + } else { + None + }; + Box::into_raw(Box::new(wasm_extern_t { + instance: Some(Arc::clone(instance)), + inner: r#extern.clone(), + })) + }) + .collect::>(); + extern_vec.shrink_to_fit(); + + out.size = extern_vec.len(); + out.data = extern_vec.as_mut_ptr(); + // TODO: double check that the destructor will work correctly here + mem::forget(extern_vec); +} diff --git a/lib/c-api/src/wasm_c_api/mod.rs b/lib/c-api/src/wasm_c_api/mod.rs index 4a6a62aaa..a84d315d1 100644 --- a/lib/c-api/src/wasm_c_api/mod.rs +++ b/lib/c-api/src/wasm_c_api/mod.rs @@ -2,6 +2,7 @@ pub mod engine; pub mod externals; +pub mod instance; pub mod module; pub mod store; pub(crate) mod utils; @@ -12,7 +13,6 @@ pub mod wasi; // required due to really weird Rust resolution rules // https://github.com/rust-lang/rust/issues/57966 use crate::c_try; -use crate::ordered_resolver::OrderedResolver; use externals::function::wasm_func_t; use externals::global::wasm_global_t; use externals::memory::wasm_memory_t; @@ -33,103 +33,6 @@ use wasmer::{ #[cfg(feature = "jit")] use wasmer_engine_jit::JIT; -#[repr(C)] -pub struct wasm_instance_t { - inner: Arc, -} - -#[no_mangle] -pub unsafe extern "C" fn wasm_instance_new( - store: Option>, - module: &wasm_module_t, - imports: *const *const wasm_extern_t, - // own - _traps: *mut *mut wasm_trap_t, -) -> Option> { - let wasm_module = &module.inner; - let module_imports = wasm_module.imports(); - let module_import_count = module_imports.len(); - let imports = argument_import_iter(imports); - let resolver: OrderedResolver = imports - .map(|imp| &imp.inner) - .take(module_import_count) - .cloned() - .collect(); - - let instance = Arc::new(c_try!(Instance::new(wasm_module, &resolver))); - Some(Box::new(wasm_instance_t { inner: instance })) -} - -#[no_mangle] -pub unsafe extern "C" fn wasm_instance_delete(_instance: Option>) {} - -struct CArrayIter { - cur_entry: *const *const T, -} - -impl CArrayIter { - fn new(array: *const *const T) -> Option { - if array.is_null() { - None - } else { - Some(CArrayIter { cur_entry: array }) - } - } -} - -impl Iterator for CArrayIter { - type Item = &'static T; - - fn next(&mut self) -> Option { - let next_entry_candidate = unsafe { *self.cur_entry }; - if next_entry_candidate.is_null() { - None - } else { - self.cur_entry = unsafe { self.cur_entry.add(1) }; - Some(unsafe { &*next_entry_candidate }) - } - } -} - -// reads from null-terminated array of `wasm_extern_t`s -unsafe fn argument_import_iter( - imports: *const *const wasm_extern_t, -) -> Box> { - CArrayIter::new(imports) - .map(|it| Box::new(it) as _) - .unwrap_or_else(|| Box::new(std::iter::empty()) as _) -} - -#[no_mangle] -pub unsafe extern "C" fn wasm_instance_exports( - instance: &wasm_instance_t, - // TODO: review types on wasm_declare_vec, handle the optional pointer part properly - out: &mut wasm_extern_vec_t, -) { - let instance = &instance.inner; - let mut extern_vec = instance - .exports - .iter() - .map(|(name, r#extern)| { - let function = if let Extern::Function { .. } = r#extern { - instance.exports.get_function(&name).ok().cloned() - } else { - None - }; - Box::into_raw(Box::new(wasm_extern_t { - instance: Some(Arc::clone(instance)), - inner: r#extern.clone(), - })) - }) - .collect::>(); - extern_vec.shrink_to_fit(); - - out.size = extern_vec.len(); - out.data = extern_vec.as_mut_ptr(); - // TODO: double check that the destructor will work correctly here - mem::forget(extern_vec); -} - #[no_mangle] pub unsafe extern "C" fn wasm_func_as_extern( func_ptr: Option>, diff --git a/lib/c-api/src/wasm_c_api/wasi/mod.rs b/lib/c-api/src/wasm_c_api/wasi/mod.rs index 4a51240e7..ad18010b4 100644 --- a/lib/c-api/src/wasm_c_api/wasi/mod.rs +++ b/lib/c-api/src/wasm_c_api/wasi/mod.rs @@ -5,8 +5,8 @@ mod capture_files; use super::{ - externals::memory::wasm_memory_t, wasm_extern_t, wasm_func_t, wasm_instance_t, wasm_module_t, - wasm_store_t, + externals::memory::wasm_memory_t, instance::wasm_instance_t, wasm_extern_t, wasm_func_t, + wasm_module_t, wasm_store_t, }; // required due to really weird Rust resolution rules for macros // https://github.com/rust-lang/rust/issues/57966 From ebcd59de2b254cb7626a11bd2febd6ef8b67f482 Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Thu, 24 Sep 2020 09:48:39 +0200 Subject: [PATCH 045/281] feat(c-api) Extract all macros into their own module. --- lib/c-api/src/wasm_c_api/macros.rs | 157 +++++++++++++++++++++++++++++ 1 file changed, 157 insertions(+) create mode 100644 lib/c-api/src/wasm_c_api/macros.rs diff --git a/lib/c-api/src/wasm_c_api/macros.rs b/lib/c-api/src/wasm_c_api/macros.rs new file mode 100644 index 000000000..abc64711e --- /dev/null +++ b/lib/c-api/src/wasm_c_api/macros.rs @@ -0,0 +1,157 @@ +#[doc(hidden)] +#[macro_export] +macro_rules! wasm_declare_vec_inner { + ($name:ident) => { + paste::item! { + #[no_mangle] + pub unsafe extern "C" fn [](out: *mut []) { + // TODO: actually implement this + [](out, 0); + } + + #[no_mangle] + pub unsafe extern "C" fn [](ptr: *mut []) { + let vec = &mut *ptr; + if !vec.data.is_null() { + Vec::from_raw_parts(vec.data, vec.size, vec.size); + vec.data = ::std::ptr::null_mut(); + vec.size = 0; + } + } + } + } +} + +#[doc(hidden)] +#[macro_export] +macro_rules! wasm_declare_vec { + ($name:ident) => { + paste::item! { + #[repr(C)] + pub struct [] { + pub size: usize, + pub data: *mut [], + } + + impl [] { + pub unsafe fn into_slice(&self) -> Option<&[[]]>{ + if self.data.is_null() { + return None; + } + + Some(::std::slice::from_raw_parts(self.data, self.size)) + } + } + + // TODO: investigate possible memory leak on `init` (owned pointer) + #[no_mangle] + pub unsafe extern "C" fn [](out: *mut [], length: usize, init: *mut []) { + let mut bytes: Vec<[]> = Vec::with_capacity(length); + for i in 0..length { + bytes.push(::std::ptr::read(init.add(i))); + } + let pointer = bytes.as_mut_ptr(); + debug_assert!(bytes.len() == bytes.capacity()); + (*out).data = pointer; + (*out).size = length; + ::std::mem::forget(bytes); + } + + #[no_mangle] + pub unsafe extern "C" fn [](out: *mut [], length: usize) { + let mut bytes: Vec<[]> = Vec::with_capacity(length); + let pointer = bytes.as_mut_ptr(); + (*out).data = pointer; + (*out).size = length; + ::std::mem::forget(bytes); + } + } + + wasm_declare_vec_inner!($name); + }; +} + +#[doc(hidden)] +#[macro_export] +macro_rules! wasm_declare_boxed_vec { + ($name:ident) => { + paste::item! { + #[repr(C)] + pub struct [] { + pub size: usize, + pub data: *mut *mut [], + } + + // TODO: do this properly + impl [] { + pub unsafe fn into_slice(&self) -> Option<&[*mut []]>{ + if self.data.is_null() { + return None; + } + + Some(::std::slice::from_raw_parts(self.data, self.size)) + } + } + + // TODO: investigate possible memory leak on `init` (owned pointer) + #[no_mangle] + pub unsafe extern "C" fn [](out: *mut [], length: usize, init: *const *mut []) { + let mut bytes: Vec<*mut []> = Vec::with_capacity(length); + for i in 0..length { + bytes.push(*init.add(i)); + } + let pointer = bytes.as_mut_ptr(); + debug_assert!(bytes.len() == bytes.capacity()); + (*out).data = pointer; + (*out).size = length; + ::std::mem::forget(bytes); + } + + #[no_mangle] + pub unsafe extern "C" fn [](out: *mut [], length: usize) { + let mut bytes: Vec<*mut []> = Vec::with_capacity(length); + let pointer = bytes.as_mut_ptr(); + (*out).data = pointer; + (*out).size = length; + ::std::mem::forget(bytes); + } + } + + wasm_declare_vec_inner!($name); + }; +} + +#[doc(hidden)] +#[macro_export] +macro_rules! wasm_declare_ref_base { + ($name:ident) => { + wasm_declare_own!($name); + + paste::item! { + #[no_mangle] + pub extern "C" fn [](_arg: *const []) -> *mut [] { + todo!("in generated declare ref base"); + //ptr::null_mut() + } + + // TODO: finish this... + + } + }; +} + +#[doc(hidden)] +#[macro_export] +macro_rules! wasm_declare_own { + ($name:ident) => { + paste::item! { + #[repr(C)] + pub struct [] {} + + #[no_mangle] + pub extern "C" fn [](_arg: *mut []) { + todo!("in generated delete") + } + } + }; +} From 44559a9f045ad9f598f379eba22af147c0e65441 Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Thu, 24 Sep 2020 09:48:56 +0200 Subject: [PATCH 046/281] feat(c-api) Move `as_extern` APIs into the `externals` module. --- .../src/wasm_c_api/externals/function.rs | 17 +- lib/c-api/src/wasm_c_api/externals/global.rs | 3 +- lib/c-api/src/wasm_c_api/externals/memory.rs | 3 +- lib/c-api/src/wasm_c_api/externals/mod.rs | 135 ++++++++- lib/c-api/src/wasm_c_api/externals/table.rs | 3 +- lib/c-api/src/wasm_c_api/instance.rs | 7 +- lib/c-api/src/wasm_c_api/mod.rs | 267 +----------------- lib/c-api/src/wasm_c_api/module.rs | 3 +- lib/c-api/src/wasm_c_api/wasi/mod.rs | 6 +- 9 files changed, 158 insertions(+), 286 deletions(-) diff --git a/lib/c-api/src/wasm_c_api/externals/function.rs b/lib/c-api/src/wasm_c_api/externals/function.rs index e6389ac85..361009415 100644 --- a/lib/c-api/src/wasm_c_api/externals/function.rs +++ b/lib/c-api/src/wasm_c_api/externals/function.rs @@ -1,5 +1,6 @@ +use super::super::store::wasm_store_t; use super::super::value::{wasm_val_inner, wasm_val_t}; -use super::super::{wasm_functype_t, wasm_store_t, wasm_trap_t, wasm_valkind_enum}; +use super::super::{wasm_functype_t, wasm_trap_t, wasm_valkind_enum}; use std::convert::TryInto; use std::ffi::c_void; use std::ptr::NonNull; @@ -152,17 +153,3 @@ pub unsafe extern "C" fn wasm_func_param_arity(func: &wasm_func_t) -> usize { pub unsafe extern "C" fn wasm_func_result_arity(func: &wasm_func_t) -> usize { func.inner.ty().results().len() } - -macro_rules! wasm_declare_own { - ($name:ident) => { - paste::item! { - #[repr(C)] - pub struct [] {} - - #[no_mangle] - pub extern "C" fn [](_arg: *mut []) { - todo!("in generated delete") - } - } - }; -} diff --git a/lib/c-api/src/wasm_c_api/externals/global.rs b/lib/c-api/src/wasm_c_api/externals/global.rs index 26d882815..9c8f64ed0 100644 --- a/lib/c-api/src/wasm_c_api/externals/global.rs +++ b/lib/c-api/src/wasm_c_api/externals/global.rs @@ -1,5 +1,6 @@ +use super::super::store::wasm_store_t; use super::super::value::wasm_val_t; -use super::super::{store::wasm_store_t, wasm_globaltype_t}; +use super::super::wasm_globaltype_t; use std::convert::TryInto; use std::ptr::NonNull; use wasmer::{Global, Store, Val}; diff --git a/lib/c-api/src/wasm_c_api/externals/memory.rs b/lib/c-api/src/wasm_c_api/externals/memory.rs index 7933a3141..12bb666a5 100644 --- a/lib/c-api/src/wasm_c_api/externals/memory.rs +++ b/lib/c-api/src/wasm_c_api/externals/memory.rs @@ -1,4 +1,5 @@ -use super::super::{store::wasm_store_t, wasm_memorytype_t}; +use super::super::store::wasm_store_t; +use super::super::wasm_memorytype_t; use crate::c_try; use std::mem; use std::ptr::NonNull; diff --git a/lib/c-api/src/wasm_c_api/externals/mod.rs b/lib/c-api/src/wasm_c_api/externals/mod.rs index 6f39bfe81..174a2a9f3 100644 --- a/lib/c-api/src/wasm_c_api/externals/mod.rs +++ b/lib/c-api/src/wasm_c_api/externals/mod.rs @@ -1,4 +1,131 @@ -pub mod function; -pub mod global; -pub mod memory; -pub mod table; +mod function; +mod global; +mod memory; +mod table; + +pub use function::*; +pub use global::*; +pub use memory::*; +use std::ptr::NonNull; +use std::sync::Arc; +pub use table::*; +use wasmer::{Extern, Instance}; + +#[repr(C)] +pub struct wasm_extern_t { + // this is how we ensure the instance stays alive + pub(crate) instance: Option>, + pub(crate) inner: Extern, +} + +wasm_declare_boxed_vec!(extern); + +#[no_mangle] +pub unsafe extern "C" fn wasm_func_as_extern( + func_ptr: Option>, +) -> Option> { + let func_ptr = func_ptr?; + let func = func_ptr.as_ref(); + + Some(Box::new(wasm_extern_t { + instance: func.instance.clone(), + inner: Extern::Function(func.inner.clone()), + })) +} + +#[no_mangle] +pub unsafe extern "C" fn wasm_global_as_extern( + global_ptr: Option>, +) -> Option> { + let global_ptr = global_ptr?; + let global = global_ptr.as_ref(); + + Some(Box::new(wasm_extern_t { + // update this if global does hold onto an `instance` + instance: None, + inner: Extern::Global(global.inner.clone()), + })) +} + +#[no_mangle] +pub unsafe extern "C" fn wasm_memory_as_extern( + memory_ptr: Option>, +) -> Option> { + let memory_ptr = memory_ptr?; + let memory = memory_ptr.as_ref(); + + Some(Box::new(wasm_extern_t { + // update this if global does hold onto an `instance` + instance: None, + inner: Extern::Memory(memory.inner.clone()), + })) +} + +#[no_mangle] +pub unsafe extern "C" fn wasm_table_as_extern( + table_ptr: Option>, +) -> Option> { + let table_ptr = table_ptr?; + let table = table_ptr.as_ref(); + + Some(Box::new(wasm_extern_t { + // update this if global does hold onto an `instance` + instance: None, + inner: Extern::Table(table.inner.clone()), + })) +} + +#[no_mangle] +pub unsafe extern "C" fn wasm_extern_as_func( + extern_ptr: Option>, +) -> Option> { + let extern_ptr = extern_ptr?; + let r#extern = extern_ptr.as_ref(); + if let Extern::Function(f) = &r#extern.inner { + Some(Box::new(wasm_func_t { + inner: f.clone(), + instance: r#extern.instance.clone(), + })) + } else { + None + } +} + +#[no_mangle] +pub unsafe extern "C" fn wasm_extern_as_global( + extern_ptr: Option>, +) -> Option> { + let extern_ptr = extern_ptr?; + let r#extern = extern_ptr.as_ref(); + if let Extern::Global(g) = &r#extern.inner { + Some(Box::new(wasm_global_t { inner: g.clone() })) + } else { + None + } +} + +#[no_mangle] +pub unsafe extern "C" fn wasm_extern_as_memory( + extern_ptr: Option>, +) -> Option> { + let extern_ptr = extern_ptr?; + let r#extern = extern_ptr.as_ref(); + if let Extern::Memory(m) = &r#extern.inner { + Some(Box::new(wasm_memory_t { inner: m.clone() })) + } else { + None + } +} + +#[no_mangle] +pub unsafe extern "C" fn wasm_extern_as_table( + extern_ptr: Option>, +) -> Option> { + let extern_ptr = extern_ptr?; + let r#extern = extern_ptr.as_ref(); + if let Extern::Table(t) = &r#extern.inner { + Some(Box::new(wasm_table_t { inner: t.clone() })) + } else { + None + } +} diff --git a/lib/c-api/src/wasm_c_api/externals/table.rs b/lib/c-api/src/wasm_c_api/externals/table.rs index 53472f37a..6cb5faf61 100644 --- a/lib/c-api/src/wasm_c_api/externals/table.rs +++ b/lib/c-api/src/wasm_c_api/externals/table.rs @@ -1,4 +1,5 @@ -use super::super::{wasm_ref_t, wasm_store_t, wasm_table_size_t, wasm_tabletype_t}; +use super::super::store::wasm_store_t; +use super::super::{wasm_ref_t, wasm_table_size_t, wasm_tabletype_t}; use crate::c_try; use std::ptr::NonNull; use wasmer::{Store, Table}; diff --git a/lib/c-api/src/wasm_c_api/instance.rs b/lib/c-api/src/wasm_c_api/instance.rs index d58336e62..617413811 100644 --- a/lib/c-api/src/wasm_c_api/instance.rs +++ b/lib/c-api/src/wasm_c_api/instance.rs @@ -1,4 +1,9 @@ -use super::{wasm_extern_t, wasm_extern_vec_t, wasm_module_t, wasm_store_t, wasm_trap_t}; +use super::{ + externals::{wasm_extern_t, wasm_extern_vec_t}, + module::wasm_module_t, + store::wasm_store_t, + wasm_trap_t, +}; use crate::c_try; use crate::ordered_resolver::OrderedResolver; use std::mem; diff --git a/lib/c-api/src/wasm_c_api/mod.rs b/lib/c-api/src/wasm_c_api/mod.rs index a84d315d1..1e24d7d63 100644 --- a/lib/c-api/src/wasm_c_api/mod.rs +++ b/lib/c-api/src/wasm_c_api/mod.rs @@ -1,5 +1,8 @@ //! entrypoints for the standard C API +#[macro_use] +pub mod macros; + pub mod engine; pub mod externals; pub mod instance; @@ -13,136 +16,19 @@ pub mod wasi; // required due to really weird Rust resolution rules // https://github.com/rust-lang/rust/issues/57966 use crate::c_try; -use externals::function::wasm_func_t; -use externals::global::wasm_global_t; -use externals::memory::wasm_memory_t; -use externals::table::wasm_table_t; -use module::wasm_module_t; +use externals::wasm_extern_t; use std::convert::{TryFrom, TryInto}; use std::mem; -use std::ptr::{self, NonNull}; -use std::slice; -use std::sync::Arc; -use store::wasm_store_t; +use std::ptr::NonNull; use thiserror::Error; use value::wasm_valkind_t; use wasmer::{ - ExportType, Extern, ExternType, FunctionType, GlobalType, ImportType, Instance, MemoryType, - Mutability, Pages, RuntimeError, TableType, ValType, + ExportType, ExternType, FunctionType, GlobalType, ImportType, MemoryType, Mutability, Pages, + RuntimeError, TableType, ValType, }; #[cfg(feature = "jit")] use wasmer_engine_jit::JIT; -#[no_mangle] -pub unsafe extern "C" fn wasm_func_as_extern( - func_ptr: Option>, -) -> Option> { - let func_ptr = func_ptr?; - let func = func_ptr.as_ref(); - - Some(Box::new(wasm_extern_t { - instance: func.instance.clone(), - inner: Extern::Function(func.inner.clone()), - })) -} - -#[no_mangle] -pub unsafe extern "C" fn wasm_global_as_extern( - global_ptr: Option>, -) -> Option> { - let global_ptr = global_ptr?; - let global = global_ptr.as_ref(); - - Some(Box::new(wasm_extern_t { - // update this if global does hold onto an `instance` - instance: None, - inner: Extern::Global(global.inner.clone()), - })) -} - -#[no_mangle] -pub unsafe extern "C" fn wasm_memory_as_extern( - memory_ptr: Option>, -) -> Option> { - let memory_ptr = memory_ptr?; - let memory = memory_ptr.as_ref(); - - Some(Box::new(wasm_extern_t { - // update this if global does hold onto an `instance` - instance: None, - inner: Extern::Memory(memory.inner.clone()), - })) -} - -#[no_mangle] -pub unsafe extern "C" fn wasm_table_as_extern( - table_ptr: Option>, -) -> Option> { - let table_ptr = table_ptr?; - let table = table_ptr.as_ref(); - - Some(Box::new(wasm_extern_t { - // update this if global does hold onto an `instance` - instance: None, - inner: Extern::Table(table.inner.clone()), - })) -} - -#[no_mangle] -pub unsafe extern "C" fn wasm_extern_as_func( - extern_ptr: Option>, -) -> Option> { - let extern_ptr = extern_ptr?; - let r#extern = extern_ptr.as_ref(); - if let Extern::Function(f) = &r#extern.inner { - Some(Box::new(wasm_func_t { - inner: f.clone(), - instance: r#extern.instance.clone(), - })) - } else { - None - } -} - -#[no_mangle] -pub unsafe extern "C" fn wasm_extern_as_global( - extern_ptr: Option>, -) -> Option> { - let extern_ptr = extern_ptr?; - let r#extern = extern_ptr.as_ref(); - if let Extern::Global(g) = &r#extern.inner { - Some(Box::new(wasm_global_t { inner: g.clone() })) - } else { - None - } -} - -#[no_mangle] -pub unsafe extern "C" fn wasm_extern_as_memory( - extern_ptr: Option>, -) -> Option> { - let extern_ptr = extern_ptr?; - let r#extern = extern_ptr.as_ref(); - if let Extern::Memory(m) = &r#extern.inner { - Some(Box::new(wasm_memory_t { inner: m.clone() })) - } else { - None - } -} - -#[no_mangle] -pub unsafe extern "C" fn wasm_extern_as_table( - extern_ptr: Option>, -) -> Option> { - let extern_ptr = extern_ptr?; - let r#extern = extern_ptr.as_ref(); - if let Extern::Table(t) = &r#extern.inner { - Some(Box::new(wasm_table_t { inner: t.clone() })) - } else { - None - } -} - #[allow(non_camel_case_types)] pub type wasm_table_size_t = u32; @@ -254,137 +140,6 @@ impl From for wasm_valkind_enum { } } -macro_rules! wasm_declare_vec_inner { - ($name:ident) => { - paste::item! { - #[no_mangle] - pub unsafe extern "C" fn [](out: *mut []) { - // TODO: actually implement this - [](out, 0); - } - - #[no_mangle] - pub unsafe extern "C" fn [](ptr: *mut []) { - let vec = &mut *ptr; - if !vec.data.is_null() { - Vec::from_raw_parts(vec.data, vec.size, vec.size); - vec.data = ptr::null_mut(); - vec.size = 0; - } - } - } - } -} - -macro_rules! wasm_declare_vec { - ($name:ident) => { - paste::item! { - #[repr(C)] - pub struct [] { - pub size: usize, - pub data: *mut [], - } - - impl [] { - pub unsafe fn into_slice(&self) -> Option<&[[]]>{ - if self.data.is_null() { - return None; - } - - Some(slice::from_raw_parts(self.data, self.size)) - } - } - - // TODO: investigate possible memory leak on `init` (owned pointer) - #[no_mangle] - pub unsafe extern "C" fn [](out: *mut [], length: usize, init: *mut []) { - let mut bytes: Vec<[]> = Vec::with_capacity(length); - for i in 0..length { - bytes.push(ptr::read(init.add(i))); - } - let pointer = bytes.as_mut_ptr(); - debug_assert!(bytes.len() == bytes.capacity()); - (*out).data = pointer; - (*out).size = length; - mem::forget(bytes); - } - - #[no_mangle] - pub unsafe extern "C" fn [](out: *mut [], length: usize) { - let mut bytes: Vec<[]> = Vec::with_capacity(length); - let pointer = bytes.as_mut_ptr(); - (*out).data = pointer; - (*out).size = length; - mem::forget(bytes); - } - } - wasm_declare_vec_inner!($name); - }; -} - -macro_rules! wasm_declare_boxed_vec { - ($name:ident) => { - paste::item! { - #[repr(C)] - pub struct [] { - pub size: usize, - pub data: *mut *mut [], - } - - // TODO: do this properly - impl [] { - pub unsafe fn into_slice(&self) -> Option<&[*mut []]>{ - if self.data.is_null() { - return None; - } - - Some(slice::from_raw_parts(self.data, self.size)) - } - } - - // TODO: investigate possible memory leak on `init` (owned pointer) - #[no_mangle] - pub unsafe extern "C" fn [](out: *mut [], length: usize, init: *const *mut []) { - let mut bytes: Vec<*mut []> = Vec::with_capacity(length); - for i in 0..length { - bytes.push(*init.add(i)); - } - let pointer = bytes.as_mut_ptr(); - debug_assert!(bytes.len() == bytes.capacity()); - (*out).data = pointer; - (*out).size = length; - mem::forget(bytes); - } - - #[no_mangle] - pub unsafe extern "C" fn [](out: *mut [], length: usize) { - let mut bytes: Vec<*mut []> = Vec::with_capacity(length); - let pointer = bytes.as_mut_ptr(); - (*out).data = pointer; - (*out).size = length; - mem::forget(bytes); - } - } - wasm_declare_vec_inner!($name); - }; -} - -macro_rules! wasm_declare_ref_base { - ($name:ident) => { - wasm_declare_own!($name); - paste::item! { - #[no_mangle] - pub extern "C" fn [](_arg: *const []) -> *mut [] { - todo!("in generated declare ref base"); - //ptr::null_mut() - } - - // TODO: finish this... - - } - }; -} - #[allow(non_camel_case_types)] pub type wasm_byte_t = u8; wasm_declare_vec!(byte); @@ -434,14 +189,6 @@ pub unsafe extern "C" fn wasm_trap_trace(trap: *const wasm_trap_t, out_ptr: *mut todo!() }*/ -#[repr(C)] -pub struct wasm_extern_t { - // this is how we ensure the instance stays alive - pub(crate) instance: Option>, - pub(crate) inner: Extern, -} -wasm_declare_boxed_vec!(extern); - #[derive(Debug, Clone, Copy)] #[repr(C)] pub struct wasm_valtype_t { diff --git a/lib/c-api/src/wasm_c_api/module.rs b/lib/c-api/src/wasm_c_api/module.rs index f2c8f9741..de6273215 100644 --- a/lib/c-api/src/wasm_c_api/module.rs +++ b/lib/c-api/src/wasm_c_api/module.rs @@ -1,6 +1,7 @@ +use super::store::wasm_store_t; use super::{ wasm_byte_vec_t, wasm_exporttype_t, wasm_exporttype_vec_t, wasm_importtype_t, - wasm_importtype_vec_t, wasm_store_t, + wasm_importtype_vec_t, }; use crate::c_try; use std::mem; diff --git a/lib/c-api/src/wasm_c_api/wasi/mod.rs b/lib/c-api/src/wasm_c_api/wasi/mod.rs index ad18010b4..066c00694 100644 --- a/lib/c-api/src/wasm_c_api/wasi/mod.rs +++ b/lib/c-api/src/wasm_c_api/wasi/mod.rs @@ -5,8 +5,10 @@ mod capture_files; use super::{ - externals::memory::wasm_memory_t, instance::wasm_instance_t, wasm_extern_t, wasm_func_t, - wasm_module_t, wasm_store_t, + externals::{wasm_extern_t, wasm_func_t, wasm_memory_t}, + instance::wasm_instance_t, + module::wasm_module_t, + store::wasm_store_t, }; // required due to really weird Rust resolution rules for macros // https://github.com/rust-lang/rust/issues/57966 From 1a0527af78b92c149dffc1b53d4eff20e9626c80 Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Thu, 24 Sep 2020 11:41:04 +0200 Subject: [PATCH 047/281] feat(c-api) Move all types into their own modules. --- .../src/wasm_c_api/externals/function.rs | 3 +- lib/c-api/src/wasm_c_api/externals/global.rs | 2 +- lib/c-api/src/wasm_c_api/externals/memory.rs | 3 +- lib/c-api/src/wasm_c_api/externals/table.rs | 3 +- lib/c-api/src/wasm_c_api/instance.rs | 11 +- lib/c-api/src/wasm_c_api/macros.rs | 18 + lib/c-api/src/wasm_c_api/mod.rs | 901 +----------------- lib/c-api/src/wasm_c_api/module.rs | 3 +- lib/c-api/src/wasm_c_api/trap.rs | 48 + lib/c-api/src/wasm_c_api/types/byte.rs | 4 + lib/c-api/src/wasm_c_api/types/export.rs | 62 ++ lib/c-api/src/wasm_c_api/types/extern_.rs | 243 +++++ lib/c-api/src/wasm_c_api/types/frame.rs | 5 + lib/c-api/src/wasm_c_api/types/function.rs | 112 +++ lib/c-api/src/wasm_c_api/types/global.rs | 72 ++ lib/c-api/src/wasm_c_api/types/import.rs | 94 ++ lib/c-api/src/wasm_c_api/types/memory.rs | 61 ++ lib/c-api/src/wasm_c_api/types/mod.rs | 27 + lib/c-api/src/wasm_c_api/types/mutability.rs | 56 ++ lib/c-api/src/wasm_c_api/types/name.rs | 4 + lib/c-api/src/wasm_c_api/types/reference.rs | 3 + lib/c-api/src/wasm_c_api/types/table.rs | 79 ++ lib/c-api/src/wasm_c_api/types/value.rs | 92 ++ lib/c-api/src/wasm_c_api/utils.rs | 17 - lib/c-api/src/wasm_c_api/value.rs | 2 +- lib/c-api/src/wasm_c_api/wasi/mod.rs | 1 - 26 files changed, 993 insertions(+), 933 deletions(-) create mode 100644 lib/c-api/src/wasm_c_api/trap.rs create mode 100644 lib/c-api/src/wasm_c_api/types/byte.rs create mode 100644 lib/c-api/src/wasm_c_api/types/export.rs create mode 100644 lib/c-api/src/wasm_c_api/types/extern_.rs create mode 100644 lib/c-api/src/wasm_c_api/types/frame.rs create mode 100644 lib/c-api/src/wasm_c_api/types/function.rs create mode 100644 lib/c-api/src/wasm_c_api/types/global.rs create mode 100644 lib/c-api/src/wasm_c_api/types/import.rs create mode 100644 lib/c-api/src/wasm_c_api/types/memory.rs create mode 100644 lib/c-api/src/wasm_c_api/types/mod.rs create mode 100644 lib/c-api/src/wasm_c_api/types/mutability.rs create mode 100644 lib/c-api/src/wasm_c_api/types/name.rs create mode 100644 lib/c-api/src/wasm_c_api/types/reference.rs create mode 100644 lib/c-api/src/wasm_c_api/types/table.rs create mode 100644 lib/c-api/src/wasm_c_api/types/value.rs delete mode 100644 lib/c-api/src/wasm_c_api/utils.rs diff --git a/lib/c-api/src/wasm_c_api/externals/function.rs b/lib/c-api/src/wasm_c_api/externals/function.rs index 361009415..9f3fe269c 100644 --- a/lib/c-api/src/wasm_c_api/externals/function.rs +++ b/lib/c-api/src/wasm_c_api/externals/function.rs @@ -1,6 +1,7 @@ use super::super::store::wasm_store_t; +use super::super::trap::wasm_trap_t; +use super::super::types::{wasm_functype_t, wasm_valkind_enum}; use super::super::value::{wasm_val_inner, wasm_val_t}; -use super::super::{wasm_functype_t, wasm_trap_t, wasm_valkind_enum}; use std::convert::TryInto; use std::ffi::c_void; use std::ptr::NonNull; diff --git a/lib/c-api/src/wasm_c_api/externals/global.rs b/lib/c-api/src/wasm_c_api/externals/global.rs index 9c8f64ed0..383e00ed9 100644 --- a/lib/c-api/src/wasm_c_api/externals/global.rs +++ b/lib/c-api/src/wasm_c_api/externals/global.rs @@ -1,6 +1,6 @@ use super::super::store::wasm_store_t; +use super::super::types::wasm_globaltype_t; use super::super::value::wasm_val_t; -use super::super::wasm_globaltype_t; use std::convert::TryInto; use std::ptr::NonNull; use wasmer::{Global, Store, Val}; diff --git a/lib/c-api/src/wasm_c_api/externals/memory.rs b/lib/c-api/src/wasm_c_api/externals/memory.rs index 12bb666a5..b8336b7fa 100644 --- a/lib/c-api/src/wasm_c_api/externals/memory.rs +++ b/lib/c-api/src/wasm_c_api/externals/memory.rs @@ -1,6 +1,5 @@ use super::super::store::wasm_store_t; -use super::super::wasm_memorytype_t; -use crate::c_try; +use super::super::types::wasm_memorytype_t; use std::mem; use std::ptr::NonNull; use wasmer::{Memory, Pages, Store}; diff --git a/lib/c-api/src/wasm_c_api/externals/table.rs b/lib/c-api/src/wasm_c_api/externals/table.rs index 6cb5faf61..e0ca9b673 100644 --- a/lib/c-api/src/wasm_c_api/externals/table.rs +++ b/lib/c-api/src/wasm_c_api/externals/table.rs @@ -1,6 +1,5 @@ use super::super::store::wasm_store_t; -use super::super::{wasm_ref_t, wasm_table_size_t, wasm_tabletype_t}; -use crate::c_try; +use super::super::types::{wasm_ref_t, wasm_table_size_t, wasm_tabletype_t}; use std::ptr::NonNull; use wasmer::{Store, Table}; diff --git a/lib/c-api/src/wasm_c_api/instance.rs b/lib/c-api/src/wasm_c_api/instance.rs index 617413811..0f59866bc 100644 --- a/lib/c-api/src/wasm_c_api/instance.rs +++ b/lib/c-api/src/wasm_c_api/instance.rs @@ -1,10 +1,7 @@ -use super::{ - externals::{wasm_extern_t, wasm_extern_vec_t}, - module::wasm_module_t, - store::wasm_store_t, - wasm_trap_t, -}; -use crate::c_try; +use super::externals::{wasm_extern_t, wasm_extern_vec_t}; +use super::module::wasm_module_t; +use super::store::wasm_store_t; +use super::trap::wasm_trap_t; use crate::ordered_resolver::OrderedResolver; use std::mem; use std::ptr::NonNull; diff --git a/lib/c-api/src/wasm_c_api/macros.rs b/lib/c-api/src/wasm_c_api/macros.rs index abc64711e..f37d9b71a 100644 --- a/lib/c-api/src/wasm_c_api/macros.rs +++ b/lib/c-api/src/wasm_c_api/macros.rs @@ -155,3 +155,21 @@ macro_rules! wasm_declare_own { } }; } + +#[macro_export] +macro_rules! c_try { + ($expr:expr) => {{ + let res: Result<_, _> = $expr; + match res { + Ok(val) => val, + Err(err) => { + crate::error::update_last_error(err); + return None; + } + } + }}; + ($expr:expr, $e:expr) => {{ + let opt: Option<_> = $expr; + c_try!(opt.ok_or_else(|| $e)) + }}; +} diff --git a/lib/c-api/src/wasm_c_api/mod.rs b/lib/c-api/src/wasm_c_api/mod.rs index 1e24d7d63..830c46944 100644 --- a/lib/c-api/src/wasm_c_api/mod.rs +++ b/lib/c-api/src/wasm_c_api/mod.rs @@ -8,905 +8,8 @@ pub mod externals; pub mod instance; pub mod module; pub mod store; -pub(crate) mod utils; +pub mod trap; +pub mod types; pub mod value; #[cfg(feature = "wasi")] pub mod wasi; - -// required due to really weird Rust resolution rules -// https://github.com/rust-lang/rust/issues/57966 -use crate::c_try; -use externals::wasm_extern_t; -use std::convert::{TryFrom, TryInto}; -use std::mem; -use std::ptr::NonNull; -use thiserror::Error; -use value::wasm_valkind_t; -use wasmer::{ - ExportType, ExternType, FunctionType, GlobalType, ImportType, MemoryType, Mutability, Pages, - RuntimeError, TableType, ValType, -}; -#[cfg(feature = "jit")] -use wasmer_engine_jit::JIT; - -#[allow(non_camel_case_types)] -pub type wasm_table_size_t = u32; - -#[allow(non_camel_case_types)] -pub type wasm_mutability_t = u8; - -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -#[allow(non_camel_case_types)] -#[repr(u8)] -enum wasm_mutability_enum { - WASM_CONST = 0, - WASM_VAR, -} - -impl wasm_mutability_enum { - #[allow(dead_code)] - fn is_mutable(self) -> bool { - self == Self::WASM_VAR - } -} - -impl TryFrom for wasm_mutability_enum { - type Error = &'static str; - - fn try_from(item: wasm_mutability_t) -> Result { - Ok(match item { - 0 => wasm_mutability_enum::WASM_CONST, - 1 => wasm_mutability_enum::WASM_VAR, - _ => return Err("wasm_mutability_t value out of bounds"), - }) - } -} - -impl From for wasm_mutability_t { - fn from(other: wasm_mutability_enum) -> Self { - other as wasm_mutability_t - } -} - -impl From for Mutability { - fn from(other: wasm_mutability_enum) -> Self { - match other { - wasm_mutability_enum::WASM_CONST => Mutability::Const, - wasm_mutability_enum::WASM_VAR => Mutability::Var, - } - } -} - -impl From for wasm_mutability_enum { - fn from(other: Mutability) -> Self { - match other { - Mutability::Const => wasm_mutability_enum::WASM_CONST, - Mutability::Var => wasm_mutability_enum::WASM_VAR, - } - } -} - -impl From for ValType { - fn from(other: wasm_valkind_enum) -> Self { - use wasm_valkind_enum::*; - match other { - WASM_I32 => ValType::I32, - WASM_I64 => ValType::I64, - WASM_F32 => ValType::F32, - WASM_F64 => ValType::F64, - WASM_ANYREF => ValType::ExternRef, - WASM_FUNCREF => ValType::FuncRef, - } - } -} - -impl From for ValType { - fn from(other: wasm_valtype_t) -> Self { - other.valkind.into() - } -} - -impl From for wasm_valtype_t { - fn from(other: ValType) -> Self { - Self { - valkind: other.into(), - } - } -} - -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -#[allow(non_camel_case_types)] -#[repr(u8)] -pub enum wasm_valkind_enum { - WASM_I32 = 0, - WASM_I64 = 1, - WASM_F32 = 2, - WASM_F64 = 3, - WASM_ANYREF = 128, - WASM_FUNCREF = 129, -} - -impl From for wasm_valkind_enum { - fn from(other: ValType) -> Self { - match other { - ValType::I32 => Self::WASM_I32, - ValType::I64 => Self::WASM_I64, - ValType::F32 => Self::WASM_F32, - ValType::F64 => Self::WASM_F64, - ValType::V128 => todo!("no v128 type in Wasm C API yet!"), - ValType::ExternRef => Self::WASM_ANYREF, - ValType::FuncRef => Self::WASM_FUNCREF, - } - } -} - -#[allow(non_camel_case_types)] -pub type wasm_byte_t = u8; -wasm_declare_vec!(byte); - -// opaque type over `ExternRef`? -#[allow(non_camel_case_types)] -pub struct wasm_ref_t; - -// opaque type which is a `RuntimeError` -#[repr(C)] -pub struct wasm_trap_t {} - -#[no_mangle] -pub unsafe extern "C" fn wasm_trap_delete(trap: Option>) { - if let Some(t_inner) = trap { - let _ = Box::from_raw(t_inner.cast::().as_ptr()); - } -} - -#[no_mangle] -pub unsafe extern "C" fn wasm_trap_message( - trap: *const wasm_trap_t, - out_ptr: *mut wasm_byte_vec_t, -) { - let re = &*(trap as *const RuntimeError); - // this code assumes no nul bytes appear in the message - let mut message = format!("{}\0", re); - message.shrink_to_fit(); - - // TODO use `String::into_raw_parts` when it gets stabilized - (*out_ptr).size = message.as_bytes().len(); - (*out_ptr).data = message.as_mut_ptr(); - mem::forget(message); -} - -// in trap/RuntimeError we need to store -// 1. message -// 2. origin (frame); frame contains: -// 1. func index -// 2. func offset -// 3. module offset -// 4. which instance this was apart of - -/*#[no_mangle] -pub unsafe extern "C" fn wasm_trap_trace(trap: *const wasm_trap_t, out_ptr: *mut wasm_frame_vec_t) { - let re = &*(trap as *const RuntimeError); - todo!() -}*/ - -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct wasm_valtype_t { - valkind: wasm_valkind_enum, -} - -impl Default for wasm_valtype_t { - fn default() -> Self { - Self { - valkind: wasm_valkind_enum::WASM_I32, - } - } -} - -wasm_declare_boxed_vec!(valtype); - -#[no_mangle] -pub extern "C" fn wasm_valtype_new(kind: wasm_valkind_t) -> Option> { - let kind_enum = kind.try_into().ok()?; - let valtype = wasm_valtype_t { valkind: kind_enum }; - Some(Box::new(valtype)) -} - -#[no_mangle] -pub unsafe extern "C" fn wasm_valtype_delete(_valtype: Option>) {} - -#[no_mangle] -pub unsafe extern "C" fn wasm_valtype_kind(valtype: *const wasm_valtype_t) -> wasm_valkind_t { - if valtype.is_null() { - // TODO: handle error - panic!("wasm_valtype_kind: argument is null pointer"); - } - return (*valtype).valkind as wasm_valkind_t; -} - -//wasm_declare_ref!(trap); -//wasm_declare_ref!(foreign); - -#[derive(Clone, Debug)] -#[repr(transparent)] -#[allow(non_camel_case_types)] -pub struct wasm_globaltype_t { - extern_: wasm_externtype_t, -} - -impl wasm_globaltype_t { - fn as_globaltype(&self) -> &GlobalType { - if let ExternType::Global(ref g) = self.extern_.inner { - g - } else { - unreachable!( - "Data corruption detected: `wasm_globaltype_t` does not contain a `GlobalType`" - ); - } - } -} - -wasm_declare_vec!(globaltype); - -#[no_mangle] -pub unsafe extern "C" fn wasm_globaltype_new( - // own - valtype: Option>, - mutability: wasm_mutability_t, -) -> Option> { - wasm_globaltype_new_inner(valtype?, mutability) -} - -#[no_mangle] -pub unsafe extern "C" fn wasm_globaltype_delete(_globaltype: Option>) {} - -unsafe fn wasm_globaltype_new_inner( - // own - valtype: Box, - mutability: wasm_mutability_t, -) -> Option> { - let me: wasm_mutability_enum = mutability.try_into().ok()?; - let gd = Box::new(wasm_globaltype_t { - extern_: wasm_externtype_t { - inner: ExternType::Global(GlobalType::new((*valtype).into(), me.into())), - }, - }); - wasm_valtype_delete(Some(valtype)); - - Some(gd) -} - -#[no_mangle] -pub unsafe extern "C" fn wasm_globaltype_mutability( - globaltype: &wasm_globaltype_t, -) -> wasm_mutability_t { - let gt = globaltype.as_globaltype(); - wasm_mutability_enum::from(gt.mutability).into() -} - -// TODO: fix memory leak -// this function leaks memory because the returned limits pointer is not owned -#[no_mangle] -pub unsafe extern "C" fn wasm_globaltype_content( - globaltype: &wasm_globaltype_t, -) -> *const wasm_valtype_t { - let gt = globaltype.as_globaltype(); - Box::into_raw(Box::new(gt.ty.into())) -} - -#[derive(Clone, Debug)] -#[repr(C)] -#[allow(non_camel_case_types)] -pub struct wasm_tabletype_t { - extern_: wasm_externtype_t, -} - -wasm_declare_vec!(tabletype); - -impl wasm_tabletype_t { - fn as_tabletype(&self) -> &TableType { - if let ExternType::Table(ref t) = self.extern_.inner { - t - } else { - unreachable!( - "Data corruption detected: `wasm_tabletype_t` does not contain a `TableType`" - ); - } - } -} - -#[no_mangle] -pub unsafe extern "C" fn wasm_tabletype_new( - // own - valtype: Box, - limits: &wasm_limits_t, -) -> Box { - // TODO: investigate if `0` is in fact a sentinel value here - let max_elements = if limits.max == 0 { - None - } else { - Some(limits.max as _) - }; - let out = Box::new(wasm_tabletype_t { - extern_: wasm_externtype_t { - inner: ExternType::Table(TableType::new( - (*valtype).into(), - limits.min as _, - max_elements, - )), - }, - }); - wasm_valtype_delete(Some(valtype)); - - out -} - -// TODO: fix memory leak -// this function leaks memory because the returned limits pointer is not owned -#[no_mangle] -pub unsafe extern "C" fn wasm_tabletype_limits( - tabletype: &wasm_tabletype_t, -) -> *const wasm_limits_t { - let tt = tabletype.as_tabletype(); - Box::into_raw(Box::new(wasm_limits_t { - min: tt.minimum as _, - max: tt.maximum.unwrap_or(0), - })) -} - -// TODO: fix memory leak -// this function leaks memory because the returned limits pointer is not owned -#[no_mangle] -pub unsafe extern "C" fn wasm_tabletype_element( - tabletype: &wasm_tabletype_t, -) -> *const wasm_valtype_t { - let tt = tabletype.as_tabletype(); - - Box::into_raw(Box::new(tt.ty.into())) -} - -#[no_mangle] -pub unsafe extern "C" fn wasm_tabletype_delete(_tabletype: Option>) {} - -// opaque type wrapping `MemoryType` -#[derive(Clone, Debug)] -#[repr(transparent)] -#[allow(non_camel_case_types)] -pub struct wasm_memorytype_t { - extern_: wasm_externtype_t, -} - -impl wasm_memorytype_t { - pub(crate) fn as_memorytype(&self) -> &MemoryType { - if let ExternType::Memory(ref mt) = self.extern_.inner { - mt - } else { - unreachable!( - "Data corruption detected: `wasm_memorytype_t` does not contain a `MemoryType`" - ); - } - } -} - -wasm_declare_vec!(memorytype); - -#[derive(Copy, Clone, Debug)] -#[repr(C)] -pub struct wasm_limits_t { - min: u32, - max: u32, -} - -#[no_mangle] -pub unsafe extern "C" fn wasm_memorytype_new(limits: &wasm_limits_t) -> Box { - let min_pages = Pages(limits.min as _); - // TODO: investigate if `0` is in fact a sentinel value here - let max_pages = if limits.max == 0 { - None - } else { - Some(Pages(limits.max as _)) - }; - Box::new(wasm_memorytype_t { - extern_: wasm_externtype_t { - inner: ExternType::Memory(MemoryType::new(min_pages, max_pages, false)), - }, - }) -} - -#[no_mangle] -pub unsafe extern "C" fn wasm_memorytype_delete(_memorytype: Option>) {} - -// TODO: fix memory leak -// this function leaks memory because the returned limits pointer is not owned -#[no_mangle] -pub unsafe extern "C" fn wasm_memorytype_limits(mt: &wasm_memorytype_t) -> *const wasm_limits_t { - let md = mt.as_memorytype(); - Box::into_raw(Box::new(wasm_limits_t { - min: md.minimum.bytes().0 as _, - max: md.maximum.map(|max| max.bytes().0 as _).unwrap_or(0), - })) -} - -#[derive(Clone, Debug)] -#[allow(non_camel_case_types)] -#[repr(transparent)] -pub struct wasm_functype_t { - extern_: wasm_externtype_t, -} - -impl wasm_functype_t { - pub(crate) fn sig(&self) -> &FunctionType { - if let ExternType::Function(ref f) = self.extern_.inner { - f - } else { - unreachable!("data corruption: `wasm_functype_t` does not contain a function") - } - } -} - -wasm_declare_vec!(functype); - -#[no_mangle] -pub unsafe extern "C" fn wasm_functype_new( - // own - params: Option>, - // own - results: Option>, -) -> Option> { - wasm_functype_new_inner(params?, results?) -} - -unsafe fn wasm_functype_new_inner( - // own - params: NonNull, - // own - results: NonNull, -) -> Option> { - let params = params.as_ref(); - let results = results.as_ref(); - let params: Vec = params - .into_slice()? - .iter() - .map(|&ptr| *ptr) - .map(Into::into) - .collect::>(); - let results: Vec = results - .into_slice()? - .iter() - .map(|&ptr| *ptr) - .map(Into::into) - .collect::>(); - - let extern_ = wasm_externtype_t { - inner: ExternType::Function(FunctionType::new(params, results)), - }; - Some(Box::new(wasm_functype_t { extern_ })) -} - -#[no_mangle] -pub unsafe extern "C" fn wasm_functype_delete(_ft: Option>) {} - -#[no_mangle] -pub unsafe extern "C" fn wasm_functype_copy( - arg: Option>, -) -> Option> { - let arg = arg?; - let funcsig = arg.as_ref(); - Some(Box::new(funcsig.clone())) -} - -// TODO: fix memory leak -#[no_mangle] -pub unsafe extern "C" fn wasm_functype_params(ft: &wasm_functype_t) -> *const wasm_valtype_vec_t { - let mut valtypes = ft - .sig() - .params() - .iter() - .cloned() - .map(Into::into) - .map(Box::new) - .map(Box::into_raw) - .collect::>(); - let out = Box::into_raw(Box::new(wasm_valtype_vec_t { - size: valtypes.len(), - data: valtypes.as_mut_ptr(), - })); - mem::forget(valtypes); - out as *const _ -} - -// TODO: fix memory leak -#[no_mangle] -pub unsafe extern "C" fn wasm_functype_results(ft: &wasm_functype_t) -> *const wasm_valtype_vec_t { - let mut valtypes = ft - .sig() - .results() - .iter() - .cloned() - .map(Into::into) - .map(Box::new) - .map(Box::into_raw) - .collect::>(); - let out = Box::into_raw(Box::new(wasm_valtype_vec_t { - size: valtypes.len(), - data: valtypes.as_mut_ptr(), - })); - mem::forget(valtypes); - out as *const _ -} - -#[derive(Debug)] -#[repr(C)] -pub struct wasm_frame_t {} - -wasm_declare_vec!(frame); - -#[derive(Clone, Debug)] -#[allow(non_camel_case_types)] -#[repr(transparent)] -pub struct wasm_externtype_t { - inner: ExternType, -} - -#[no_mangle] -pub unsafe extern "C" fn wasm_extern_type(e: &wasm_extern_t) -> Box { - Box::new(wasm_externtype_t { - inner: e.inner.ty(), - }) -} - -#[no_mangle] -pub unsafe extern "C" fn wasm_externtype_delete(_et: Option>) {} - -impl From for wasm_externtype_t { - fn from(other: ExternType) -> Self { - Self { inner: other } - } -} - -impl From<&ExternType> for wasm_externtype_t { - fn from(other: &ExternType) -> Self { - other.clone().into() - } -} - -#[allow(non_camel_case_types)] -type wasm_externkind_t = u8; - -#[allow(non_camel_case_types)] -#[repr(u8)] -pub enum wasm_externkind_enum { - WASM_EXTERN_FUNC = 0, - WASM_EXTERN_GLOBAL = 1, - WASM_EXTERN_TABLE = 2, - WASM_EXTERN_MEMORY = 3, -} - -#[no_mangle] -pub unsafe extern "C" fn wasm_extern_kind(e: &wasm_extern_t) -> wasm_externkind_t { - wasm_externkind_enum::from(e.inner.ty()) as wasm_externkind_t -} - -impl From for wasm_externkind_enum { - fn from(other: ExternType) -> Self { - (&other).into() - } -} -impl From<&ExternType> for wasm_externkind_enum { - fn from(other: &ExternType) -> Self { - match other { - ExternType::Function(_) => Self::WASM_EXTERN_FUNC, - ExternType::Global(_) => Self::WASM_EXTERN_GLOBAL, - ExternType::Table(_) => Self::WASM_EXTERN_TABLE, - ExternType::Memory(_) => Self::WASM_EXTERN_MEMORY, - } - } -} - -#[no_mangle] -pub unsafe extern "C" fn wasm_externtype_kind(et: &wasm_externtype_t) -> wasm_externkind_t { - wasm_externkind_enum::from(&et.inner) as wasm_externkind_t -} - -#[derive(Debug, Clone, Error)] -#[error("failed to convert from `wasm_externtype_t`: {0}")] -pub struct ExternTypeConversionError(&'static str); -impl From<&'static str> for ExternTypeConversionError { - fn from(other: &'static str) -> Self { - Self(other) - } -} - -impl TryFrom<&'static wasm_externtype_t> for &'static wasm_functype_t { - type Error = ExternTypeConversionError; - fn try_from(other: &'static wasm_externtype_t) -> Result { - if let ExternType::Function(_) = other.inner { - Ok(unsafe { mem::transmute::<&'static wasm_externtype_t, Self>(other) }) - } else { - Err(ExternTypeConversionError("Wrong type: expected function")) - } - } -} -impl TryFrom<&'static wasm_externtype_t> for &'static wasm_globaltype_t { - type Error = ExternTypeConversionError; - fn try_from(other: &'static wasm_externtype_t) -> Result { - if let ExternType::Global(_) = other.inner { - Ok(unsafe { mem::transmute::<&'static wasm_externtype_t, Self>(other) }) - } else { - Err(ExternTypeConversionError("Wrong type: expected global")) - } - } -} -impl TryFrom<&'static wasm_externtype_t> for &'static wasm_memorytype_t { - type Error = ExternTypeConversionError; - fn try_from(other: &'static wasm_externtype_t) -> Result { - if let ExternType::Memory(_) = other.inner { - Ok(unsafe { mem::transmute::<&'static wasm_externtype_t, Self>(other) }) - } else { - Err(ExternTypeConversionError("Wrong type: expected memory")) - } - } -} -impl TryFrom<&'static wasm_externtype_t> for &'static wasm_tabletype_t { - type Error = ExternTypeConversionError; - fn try_from(other: &'static wasm_externtype_t) -> Result { - if let ExternType::Table(_) = other.inner { - Ok(unsafe { mem::transmute::<&'static wasm_externtype_t, Self>(other) }) - } else { - Err(ExternTypeConversionError("Wrong type: expected table")) - } - } -} - -#[no_mangle] -pub unsafe extern "C" fn wasm_externtype_as_functype_const( - et: &'static wasm_externtype_t, -) -> Option<&'static wasm_functype_t> { - Some(c_try!(et.try_into())) -} -#[no_mangle] -pub unsafe extern "C" fn wasm_externtype_as_functype( - et: &'static wasm_externtype_t, -) -> Option<&'static wasm_functype_t> { - Some(c_try!(et.try_into())) -} -#[no_mangle] -pub unsafe extern "C" fn wasm_functype_as_externtype_const( - ft: &'static wasm_functype_t, -) -> &'static wasm_externtype_t { - &ft.extern_ -} -#[no_mangle] -pub unsafe extern "C" fn wasm_functype_as_externtype( - ft: &'static wasm_functype_t, -) -> &'static wasm_externtype_t { - &ft.extern_ -} - -#[no_mangle] -pub unsafe extern "C" fn wasm_externtype_as_memorytype_const( - et: &'static wasm_externtype_t, -) -> Option<&'static wasm_memorytype_t> { - Some(c_try!(et.try_into())) -} -#[no_mangle] -pub unsafe extern "C" fn wasm_externtype_as_memorytype( - et: &'static wasm_externtype_t, -) -> Option<&'static wasm_memorytype_t> { - Some(c_try!(et.try_into())) -} -#[no_mangle] -pub unsafe extern "C" fn wasm_memorytype_as_externtype_const( - mt: &'static wasm_memorytype_t, -) -> &'static wasm_externtype_t { - &mt.extern_ -} -#[no_mangle] -pub unsafe extern "C" fn wasm_memorytype_as_externtype( - mt: &'static wasm_memorytype_t, -) -> &'static wasm_externtype_t { - &mt.extern_ -} - -#[no_mangle] -pub unsafe extern "C" fn wasm_externtype_as_globaltype_const( - et: &'static wasm_externtype_t, -) -> Option<&'static wasm_globaltype_t> { - Some(c_try!(et.try_into())) -} -#[no_mangle] -pub unsafe extern "C" fn wasm_externtype_as_globaltype( - et: &'static wasm_externtype_t, -) -> Option<&'static wasm_globaltype_t> { - Some(c_try!(et.try_into())) -} -#[no_mangle] -pub unsafe extern "C" fn wasm_globaltype_as_externtype_const( - gt: &'static wasm_globaltype_t, -) -> &'static wasm_externtype_t { - >.extern_ -} -#[no_mangle] -pub unsafe extern "C" fn wasm_globaltype_as_externtype( - gt: &'static wasm_globaltype_t, -) -> &'static wasm_externtype_t { - >.extern_ -} - -#[no_mangle] -pub unsafe extern "C" fn wasm_externtype_as_tabletype_const( - et: &'static wasm_externtype_t, -) -> Option<&'static wasm_tabletype_t> { - Some(c_try!(et.try_into())) -} -#[no_mangle] -pub unsafe extern "C" fn wasm_externtype_as_tabletype( - et: &'static wasm_externtype_t, -) -> Option<&'static wasm_tabletype_t> { - Some(c_try!(et.try_into())) -} -#[no_mangle] -pub unsafe extern "C" fn wasm_tabletype_as_externtype_const( - tt: &'static wasm_tabletype_t, -) -> &'static wasm_externtype_t { - &tt.extern_ -} -#[no_mangle] -pub unsafe extern "C" fn wasm_tabletype_as_externtype( - tt: &'static wasm_tabletype_t, -) -> &'static wasm_externtype_t { - &tt.extern_ -} - -#[allow(non_camel_case_types)] -type wasm_name_t = wasm_byte_vec_t; - -#[repr(C)] -#[allow(non_camel_case_types)] -pub struct wasm_exporttype_t { - name: NonNull, - extern_type: NonNull, -} - -wasm_declare_boxed_vec!(exporttype); - -#[no_mangle] -pub extern "C" fn wasm_exporttype_new( - name: NonNull, - extern_type: NonNull, -) -> Box { - Box::new(wasm_exporttype_t { name, extern_type }) -} - -#[no_mangle] -pub extern "C" fn wasm_exporttype_name(et: &'static wasm_exporttype_t) -> &'static wasm_name_t { - unsafe { et.name.as_ref() } -} - -#[no_mangle] -pub extern "C" fn wasm_exporttype_type( - et: &'static wasm_exporttype_t, -) -> &'static wasm_externtype_t { - unsafe { et.extern_type.as_ref() } -} - -impl From for wasm_exporttype_t { - fn from(other: ExportType) -> Self { - (&other).into() - } -} - -impl From<&ExportType> for wasm_exporttype_t { - fn from(other: &ExportType) -> Self { - // TODO: double check that freeing String as `Vec` is valid - let name = { - let mut heap_str: Box = other.name().to_string().into_boxed_str(); - let char_ptr = heap_str.as_mut_ptr(); - let str_len = heap_str.bytes().len(); - let name_inner = wasm_name_t { - size: str_len, - data: char_ptr, - }; - Box::leak(heap_str); - unsafe { NonNull::new_unchecked(Box::into_raw(Box::new(name_inner))) } - }; - - let extern_type = { - let extern_type: wasm_externtype_t = other.ty().into(); - unsafe { NonNull::new_unchecked(Box::into_raw(Box::new(extern_type))) } - }; - - wasm_exporttype_t { name, extern_type } - } -} - -// TODO: improve ownership in `importtype_t` (can we safely use `Box` here?) -#[repr(C)] -#[allow(non_camel_case_types)] -pub struct wasm_importtype_t { - module: NonNull, - name: NonNull, - extern_type: NonNull, -} - -wasm_declare_boxed_vec!(importtype); - -#[no_mangle] -pub extern "C" fn wasm_importtype_new( - module: NonNull, - name: NonNull, - extern_type: NonNull, -) -> Box { - Box::new(wasm_importtype_t { - name, - module, - extern_type, - }) -} - -#[no_mangle] -pub extern "C" fn wasm_importtype_module(et: &'static wasm_importtype_t) -> &'static wasm_name_t { - unsafe { et.module.as_ref() } -} - -#[no_mangle] -pub extern "C" fn wasm_importtype_name(et: &'static wasm_importtype_t) -> &'static wasm_name_t { - unsafe { et.name.as_ref() } -} - -#[no_mangle] -pub extern "C" fn wasm_importtype_type( - et: &'static wasm_importtype_t, -) -> &'static wasm_externtype_t { - unsafe { et.extern_type.as_ref() } -} - -#[no_mangle] -pub unsafe extern "C" fn wasm_importtype_delete(_importtype: Option>) {} - -impl From for wasm_importtype_t { - fn from(other: ImportType) -> Self { - (&other).into() - } -} - -impl From<&ImportType> for wasm_importtype_t { - fn from(other: &ImportType) -> Self { - // TODO: double check that freeing String as `Vec` is valid - let name = { - let mut heap_str: Box = other.name().to_string().into_boxed_str(); - let char_ptr = heap_str.as_mut_ptr(); - let str_len = heap_str.bytes().len(); - let name_inner = wasm_name_t { - size: str_len, - data: char_ptr, - }; - Box::leak(heap_str); - unsafe { NonNull::new_unchecked(Box::into_raw(Box::new(name_inner))) } - }; - - // TODO: double check that freeing String as `Vec` is valid - let module = { - let mut heap_str: Box = other.module().to_string().into_boxed_str(); - let char_ptr = heap_str.as_mut_ptr(); - let str_len = heap_str.bytes().len(); - let name_inner = wasm_name_t { - size: str_len, - data: char_ptr, - }; - Box::leak(heap_str); - unsafe { NonNull::new_unchecked(Box::into_raw(Box::new(name_inner))) } - }; - - let extern_type = { - let extern_type: wasm_externtype_t = other.ty().into(); - unsafe { NonNull::new_unchecked(Box::into_raw(Box::new(extern_type))) } - }; - - wasm_importtype_t { - name, - module, - extern_type, - } - } -} diff --git a/lib/c-api/src/wasm_c_api/module.rs b/lib/c-api/src/wasm_c_api/module.rs index de6273215..9133d53af 100644 --- a/lib/c-api/src/wasm_c_api/module.rs +++ b/lib/c-api/src/wasm_c_api/module.rs @@ -1,9 +1,8 @@ use super::store::wasm_store_t; -use super::{ +use super::types::{ wasm_byte_vec_t, wasm_exporttype_t, wasm_exporttype_vec_t, wasm_importtype_t, wasm_importtype_vec_t, }; -use crate::c_try; use std::mem; use std::ptr::NonNull; use std::slice; diff --git a/lib/c-api/src/wasm_c_api/trap.rs b/lib/c-api/src/wasm_c_api/trap.rs new file mode 100644 index 000000000..d2503a636 --- /dev/null +++ b/lib/c-api/src/wasm_c_api/trap.rs @@ -0,0 +1,48 @@ +use super::types::wasm_byte_vec_t; +use std::mem; +use std::ptr::NonNull; +use wasmer::RuntimeError; + +// opaque type which is a `RuntimeError` +#[repr(C)] +pub struct wasm_trap_t {} + +#[no_mangle] +pub unsafe extern "C" fn wasm_trap_delete(trap: Option>) { + if let Some(t_inner) = trap { + let _ = Box::from_raw(t_inner.cast::().as_ptr()); + } +} + +#[no_mangle] +pub unsafe extern "C" fn wasm_trap_message( + trap: *const wasm_trap_t, + out_ptr: *mut wasm_byte_vec_t, +) { + let re = &*(trap as *const RuntimeError); + // this code assumes no nul bytes appear in the message + let mut message = format!("{}\0", re); + message.shrink_to_fit(); + + // TODO use `String::into_raw_parts` when it gets stabilized + (*out_ptr).size = message.as_bytes().len(); + (*out_ptr).data = message.as_mut_ptr(); + mem::forget(message); +} + +// in trap/RuntimeError we need to store +// 1. message +// 2. origin (frame); frame contains: +// 1. func index +// 2. func offset +// 3. module offset +// 4. which instance this was apart of + +/*#[no_mangle] +pub unsafe extern "C" fn wasm_trap_trace(trap: *const wasm_trap_t, out_ptr: *mut wasm_frame_vec_t) { + let re = &*(trap as *const RuntimeError); + todo!() +}*/ + +//wasm_declare_ref!(trap); +//wasm_declare_ref!(foreign); diff --git a/lib/c-api/src/wasm_c_api/types/byte.rs b/lib/c-api/src/wasm_c_api/types/byte.rs new file mode 100644 index 000000000..20ee607e6 --- /dev/null +++ b/lib/c-api/src/wasm_c_api/types/byte.rs @@ -0,0 +1,4 @@ +#[allow(non_camel_case_types)] +pub type wasm_byte_t = u8; + +wasm_declare_vec!(byte); diff --git a/lib/c-api/src/wasm_c_api/types/export.rs b/lib/c-api/src/wasm_c_api/types/export.rs new file mode 100644 index 000000000..237256039 --- /dev/null +++ b/lib/c-api/src/wasm_c_api/types/export.rs @@ -0,0 +1,62 @@ +use super::{wasm_externtype_t, wasm_name_t}; +use std::ptr::NonNull; +use wasmer::ExportType; + +#[repr(C)] +#[allow(non_camel_case_types)] +pub struct wasm_exporttype_t { + name: NonNull, + extern_type: NonNull, +} + +wasm_declare_boxed_vec!(exporttype); + +#[no_mangle] +pub extern "C" fn wasm_exporttype_new( + name: NonNull, + extern_type: NonNull, +) -> Box { + Box::new(wasm_exporttype_t { name, extern_type }) +} + +#[no_mangle] +pub extern "C" fn wasm_exporttype_name(et: &'static wasm_exporttype_t) -> &'static wasm_name_t { + unsafe { et.name.as_ref() } +} + +#[no_mangle] +pub extern "C" fn wasm_exporttype_type( + et: &'static wasm_exporttype_t, +) -> &'static wasm_externtype_t { + unsafe { et.extern_type.as_ref() } +} + +impl From for wasm_exporttype_t { + fn from(other: ExportType) -> Self { + (&other).into() + } +} + +impl From<&ExportType> for wasm_exporttype_t { + fn from(other: &ExportType) -> Self { + // TODO: double check that freeing String as `Vec` is valid + let name = { + let mut heap_str: Box = other.name().to_string().into_boxed_str(); + let char_ptr = heap_str.as_mut_ptr(); + let str_len = heap_str.bytes().len(); + let name_inner = wasm_name_t { + size: str_len, + data: char_ptr, + }; + Box::leak(heap_str); + unsafe { NonNull::new_unchecked(Box::into_raw(Box::new(name_inner))) } + }; + + let extern_type = { + let extern_type: wasm_externtype_t = other.ty().into(); + unsafe { NonNull::new_unchecked(Box::into_raw(Box::new(extern_type))) } + }; + + wasm_exporttype_t { name, extern_type } + } +} diff --git a/lib/c-api/src/wasm_c_api/types/extern_.rs b/lib/c-api/src/wasm_c_api/types/extern_.rs new file mode 100644 index 000000000..0cd826085 --- /dev/null +++ b/lib/c-api/src/wasm_c_api/types/extern_.rs @@ -0,0 +1,243 @@ +use super::super::externals::wasm_extern_t; +use super::{wasm_functype_t, wasm_globaltype_t, wasm_memorytype_t, wasm_tabletype_t}; +use std::convert::{TryFrom, TryInto}; +use std::mem; +use thiserror::Error; +use wasmer::ExternType; + +#[derive(Clone, Debug)] +#[allow(non_camel_case_types)] +#[repr(transparent)] +pub struct wasm_externtype_t { + pub(crate) inner: ExternType, +} + +#[no_mangle] +pub unsafe extern "C" fn wasm_extern_type(e: &wasm_extern_t) -> Box { + Box::new(wasm_externtype_t { + inner: e.inner.ty(), + }) +} + +#[no_mangle] +pub unsafe extern "C" fn wasm_externtype_delete(_et: Option>) {} + +impl From for wasm_externtype_t { + fn from(other: ExternType) -> Self { + Self { inner: other } + } +} + +impl From<&ExternType> for wasm_externtype_t { + fn from(other: &ExternType) -> Self { + other.clone().into() + } +} + +#[allow(non_camel_case_types)] +type wasm_externkind_t = u8; + +#[allow(non_camel_case_types)] +#[repr(u8)] +pub enum wasm_externkind_enum { + WASM_EXTERN_FUNC = 0, + WASM_EXTERN_GLOBAL = 1, + WASM_EXTERN_TABLE = 2, + WASM_EXTERN_MEMORY = 3, +} + +#[no_mangle] +pub unsafe extern "C" fn wasm_extern_kind(e: &wasm_extern_t) -> wasm_externkind_t { + wasm_externkind_enum::from(e.inner.ty()) as wasm_externkind_t +} + +impl From for wasm_externkind_enum { + fn from(other: ExternType) -> Self { + (&other).into() + } +} +impl From<&ExternType> for wasm_externkind_enum { + fn from(other: &ExternType) -> Self { + match other { + ExternType::Function(_) => Self::WASM_EXTERN_FUNC, + ExternType::Global(_) => Self::WASM_EXTERN_GLOBAL, + ExternType::Table(_) => Self::WASM_EXTERN_TABLE, + ExternType::Memory(_) => Self::WASM_EXTERN_MEMORY, + } + } +} + +#[no_mangle] +pub unsafe extern "C" fn wasm_externtype_kind(et: &wasm_externtype_t) -> wasm_externkind_t { + wasm_externkind_enum::from(&et.inner) as wasm_externkind_t +} + +#[derive(Debug, Clone, Error)] +#[error("failed to convert from `wasm_externtype_t`: {0}")] +pub struct ExternTypeConversionError(&'static str); + +impl From<&'static str> for ExternTypeConversionError { + fn from(other: &'static str) -> Self { + Self(other) + } +} + +impl TryFrom<&'static wasm_externtype_t> for &'static wasm_functype_t { + type Error = ExternTypeConversionError; + + fn try_from(other: &'static wasm_externtype_t) -> Result { + if let ExternType::Function(_) = other.inner { + Ok(unsafe { mem::transmute::<&'static wasm_externtype_t, Self>(other) }) + } else { + Err(ExternTypeConversionError("Wrong type: expected function")) + } + } +} + +impl TryFrom<&'static wasm_externtype_t> for &'static wasm_globaltype_t { + type Error = ExternTypeConversionError; + + fn try_from(other: &'static wasm_externtype_t) -> Result { + if let ExternType::Global(_) = other.inner { + Ok(unsafe { mem::transmute::<&'static wasm_externtype_t, Self>(other) }) + } else { + Err(ExternTypeConversionError("Wrong type: expected global")) + } + } +} + +impl TryFrom<&'static wasm_externtype_t> for &'static wasm_memorytype_t { + type Error = ExternTypeConversionError; + + fn try_from(other: &'static wasm_externtype_t) -> Result { + if let ExternType::Memory(_) = other.inner { + Ok(unsafe { mem::transmute::<&'static wasm_externtype_t, Self>(other) }) + } else { + Err(ExternTypeConversionError("Wrong type: expected memory")) + } + } +} + +impl TryFrom<&'static wasm_externtype_t> for &'static wasm_tabletype_t { + type Error = ExternTypeConversionError; + + fn try_from(other: &'static wasm_externtype_t) -> Result { + if let ExternType::Table(_) = other.inner { + Ok(unsafe { mem::transmute::<&'static wasm_externtype_t, Self>(other) }) + } else { + Err(ExternTypeConversionError("Wrong type: expected table")) + } + } +} + +#[no_mangle] +pub unsafe extern "C" fn wasm_externtype_as_functype_const( + et: &'static wasm_externtype_t, +) -> Option<&'static wasm_functype_t> { + Some(c_try!(et.try_into())) +} + +#[no_mangle] +pub unsafe extern "C" fn wasm_externtype_as_functype( + et: &'static wasm_externtype_t, +) -> Option<&'static wasm_functype_t> { + Some(c_try!(et.try_into())) +} + +#[no_mangle] +pub unsafe extern "C" fn wasm_functype_as_externtype_const( + ft: &'static wasm_functype_t, +) -> &'static wasm_externtype_t { + &ft.extern_ +} + +#[no_mangle] +pub unsafe extern "C" fn wasm_functype_as_externtype( + ft: &'static wasm_functype_t, +) -> &'static wasm_externtype_t { + &ft.extern_ +} + +#[no_mangle] +pub unsafe extern "C" fn wasm_externtype_as_memorytype_const( + et: &'static wasm_externtype_t, +) -> Option<&'static wasm_memorytype_t> { + Some(c_try!(et.try_into())) +} + +#[no_mangle] +pub unsafe extern "C" fn wasm_externtype_as_memorytype( + et: &'static wasm_externtype_t, +) -> Option<&'static wasm_memorytype_t> { + Some(c_try!(et.try_into())) +} + +#[no_mangle] +pub unsafe extern "C" fn wasm_memorytype_as_externtype_const( + mt: &'static wasm_memorytype_t, +) -> &'static wasm_externtype_t { + &mt.extern_ +} + +#[no_mangle] +pub unsafe extern "C" fn wasm_memorytype_as_externtype( + mt: &'static wasm_memorytype_t, +) -> &'static wasm_externtype_t { + &mt.extern_ +} + +#[no_mangle] +pub unsafe extern "C" fn wasm_externtype_as_globaltype_const( + et: &'static wasm_externtype_t, +) -> Option<&'static wasm_globaltype_t> { + Some(c_try!(et.try_into())) +} + +#[no_mangle] +pub unsafe extern "C" fn wasm_externtype_as_globaltype( + et: &'static wasm_externtype_t, +) -> Option<&'static wasm_globaltype_t> { + Some(c_try!(et.try_into())) +} + +#[no_mangle] +pub unsafe extern "C" fn wasm_globaltype_as_externtype_const( + gt: &'static wasm_globaltype_t, +) -> &'static wasm_externtype_t { + >.extern_ +} + +#[no_mangle] +pub unsafe extern "C" fn wasm_globaltype_as_externtype( + gt: &'static wasm_globaltype_t, +) -> &'static wasm_externtype_t { + >.extern_ +} + +#[no_mangle] +pub unsafe extern "C" fn wasm_externtype_as_tabletype_const( + et: &'static wasm_externtype_t, +) -> Option<&'static wasm_tabletype_t> { + Some(c_try!(et.try_into())) +} + +#[no_mangle] +pub unsafe extern "C" fn wasm_externtype_as_tabletype( + et: &'static wasm_externtype_t, +) -> Option<&'static wasm_tabletype_t> { + Some(c_try!(et.try_into())) +} + +#[no_mangle] +pub unsafe extern "C" fn wasm_tabletype_as_externtype_const( + tt: &'static wasm_tabletype_t, +) -> &'static wasm_externtype_t { + &tt.extern_ +} + +#[no_mangle] +pub unsafe extern "C" fn wasm_tabletype_as_externtype( + tt: &'static wasm_tabletype_t, +) -> &'static wasm_externtype_t { + &tt.extern_ +} diff --git a/lib/c-api/src/wasm_c_api/types/frame.rs b/lib/c-api/src/wasm_c_api/types/frame.rs new file mode 100644 index 000000000..ca2539667 --- /dev/null +++ b/lib/c-api/src/wasm_c_api/types/frame.rs @@ -0,0 +1,5 @@ +#[derive(Debug)] +#[repr(C)] +pub struct wasm_frame_t {} + +wasm_declare_vec!(frame); diff --git a/lib/c-api/src/wasm_c_api/types/function.rs b/lib/c-api/src/wasm_c_api/types/function.rs new file mode 100644 index 000000000..d42d62245 --- /dev/null +++ b/lib/c-api/src/wasm_c_api/types/function.rs @@ -0,0 +1,112 @@ +use super::{wasm_externtype_t, wasm_valtype_t, wasm_valtype_vec_t}; +use std::mem; +use std::ptr::NonNull; +use wasmer::{ExternType, FunctionType, ValType}; + +#[derive(Clone, Debug)] +#[allow(non_camel_case_types)] +#[repr(transparent)] +pub struct wasm_functype_t { + pub(crate) extern_: wasm_externtype_t, +} + +impl wasm_functype_t { + pub(crate) fn sig(&self) -> &FunctionType { + if let ExternType::Function(ref f) = self.extern_.inner { + f + } else { + unreachable!("data corruption: `wasm_functype_t` does not contain a function") + } + } +} + +wasm_declare_vec!(functype); + +#[no_mangle] +pub unsafe extern "C" fn wasm_functype_new( + // own + params: Option>, + // own + results: Option>, +) -> Option> { + wasm_functype_new_inner(params?, results?) +} + +unsafe fn wasm_functype_new_inner( + // own + params: NonNull, + // own + results: NonNull, +) -> Option> { + let params = params.as_ref(); + let results = results.as_ref(); + let params: Vec = params + .into_slice()? + .iter() + .map(|&ptr| *ptr) + .map(Into::into) + .collect::>(); + let results: Vec = results + .into_slice()? + .iter() + .map(|&ptr| *ptr) + .map(Into::into) + .collect::>(); + + let extern_ = wasm_externtype_t { + inner: ExternType::Function(FunctionType::new(params, results)), + }; + Some(Box::new(wasm_functype_t { extern_ })) +} + +#[no_mangle] +pub unsafe extern "C" fn wasm_functype_delete(_ft: Option>) {} + +#[no_mangle] +pub unsafe extern "C" fn wasm_functype_copy( + arg: Option>, +) -> Option> { + let arg = arg?; + let funcsig = arg.as_ref(); + Some(Box::new(funcsig.clone())) +} + +// TODO: fix memory leak +#[no_mangle] +pub unsafe extern "C" fn wasm_functype_params(ft: &wasm_functype_t) -> *const wasm_valtype_vec_t { + let mut valtypes = ft + .sig() + .params() + .iter() + .cloned() + .map(Into::into) + .map(Box::new) + .map(Box::into_raw) + .collect::>(); + let out = Box::into_raw(Box::new(wasm_valtype_vec_t { + size: valtypes.len(), + data: valtypes.as_mut_ptr(), + })); + mem::forget(valtypes); + out as *const _ +} + +// TODO: fix memory leak +#[no_mangle] +pub unsafe extern "C" fn wasm_functype_results(ft: &wasm_functype_t) -> *const wasm_valtype_vec_t { + let mut valtypes = ft + .sig() + .results() + .iter() + .cloned() + .map(Into::into) + .map(Box::new) + .map(Box::into_raw) + .collect::>(); + let out = Box::into_raw(Box::new(wasm_valtype_vec_t { + size: valtypes.len(), + data: valtypes.as_mut_ptr(), + })); + mem::forget(valtypes); + out as *const _ +} diff --git a/lib/c-api/src/wasm_c_api/types/global.rs b/lib/c-api/src/wasm_c_api/types/global.rs new file mode 100644 index 000000000..185a4d92e --- /dev/null +++ b/lib/c-api/src/wasm_c_api/types/global.rs @@ -0,0 +1,72 @@ +use super::{ + wasm_externtype_t, wasm_mutability_enum, wasm_mutability_t, wasm_valtype_delete, wasm_valtype_t, +}; +use std::convert::TryInto; +use wasmer::{ExternType, GlobalType}; + +#[derive(Clone, Debug)] +#[repr(transparent)] +#[allow(non_camel_case_types)] +pub struct wasm_globaltype_t { + pub(crate) extern_: wasm_externtype_t, +} + +impl wasm_globaltype_t { + pub(crate) fn as_globaltype(&self) -> &GlobalType { + if let ExternType::Global(ref g) = self.extern_.inner { + g + } else { + unreachable!( + "Data corruption detected: `wasm_globaltype_t` does not contain a `GlobalType`" + ); + } + } +} + +wasm_declare_vec!(globaltype); + +#[no_mangle] +pub unsafe extern "C" fn wasm_globaltype_new( + // own + valtype: Option>, + mutability: wasm_mutability_t, +) -> Option> { + wasm_globaltype_new_inner(valtype?, mutability) +} + +#[no_mangle] +pub unsafe extern "C" fn wasm_globaltype_delete(_globaltype: Option>) {} + +unsafe fn wasm_globaltype_new_inner( + // own + valtype: Box, + mutability: wasm_mutability_t, +) -> Option> { + let me: wasm_mutability_enum = mutability.try_into().ok()?; + let gd = Box::new(wasm_globaltype_t { + extern_: wasm_externtype_t { + inner: ExternType::Global(GlobalType::new((*valtype).into(), me.into())), + }, + }); + wasm_valtype_delete(Some(valtype)); + + Some(gd) +} + +#[no_mangle] +pub unsafe extern "C" fn wasm_globaltype_mutability( + globaltype: &wasm_globaltype_t, +) -> wasm_mutability_t { + let gt = globaltype.as_globaltype(); + wasm_mutability_enum::from(gt.mutability).into() +} + +// TODO: fix memory leak +// this function leaks memory because the returned limits pointer is not owned +#[no_mangle] +pub unsafe extern "C" fn wasm_globaltype_content( + globaltype: &wasm_globaltype_t, +) -> *const wasm_valtype_t { + let gt = globaltype.as_globaltype(); + Box::into_raw(Box::new(gt.ty.into())) +} diff --git a/lib/c-api/src/wasm_c_api/types/import.rs b/lib/c-api/src/wasm_c_api/types/import.rs new file mode 100644 index 000000000..a45b1644b --- /dev/null +++ b/lib/c-api/src/wasm_c_api/types/import.rs @@ -0,0 +1,94 @@ +use super::{wasm_externtype_t, wasm_name_t}; +use std::ptr::NonNull; +use wasmer::ImportType; + +// TODO: improve ownership in `importtype_t` (can we safely use `Box` here?) +#[repr(C)] +#[allow(non_camel_case_types)] +pub struct wasm_importtype_t { + pub(crate) module: NonNull, + pub(crate) name: NonNull, + pub(crate) extern_type: NonNull, +} + +wasm_declare_boxed_vec!(importtype); + +#[no_mangle] +pub extern "C" fn wasm_importtype_new( + module: NonNull, + name: NonNull, + extern_type: NonNull, +) -> Box { + Box::new(wasm_importtype_t { + name, + module, + extern_type, + }) +} + +#[no_mangle] +pub extern "C" fn wasm_importtype_module(et: &'static wasm_importtype_t) -> &'static wasm_name_t { + unsafe { et.module.as_ref() } +} + +#[no_mangle] +pub extern "C" fn wasm_importtype_name(et: &'static wasm_importtype_t) -> &'static wasm_name_t { + unsafe { et.name.as_ref() } +} + +#[no_mangle] +pub extern "C" fn wasm_importtype_type( + et: &'static wasm_importtype_t, +) -> &'static wasm_externtype_t { + unsafe { et.extern_type.as_ref() } +} + +#[no_mangle] +pub unsafe extern "C" fn wasm_importtype_delete(_importtype: Option>) {} + +impl From for wasm_importtype_t { + fn from(other: ImportType) -> Self { + (&other).into() + } +} + +impl From<&ImportType> for wasm_importtype_t { + fn from(other: &ImportType) -> Self { + // TODO: double check that freeing String as `Vec` is valid + let name = { + let mut heap_str: Box = other.name().to_string().into_boxed_str(); + let char_ptr = heap_str.as_mut_ptr(); + let str_len = heap_str.bytes().len(); + let name_inner = wasm_name_t { + size: str_len, + data: char_ptr, + }; + Box::leak(heap_str); + unsafe { NonNull::new_unchecked(Box::into_raw(Box::new(name_inner))) } + }; + + // TODO: double check that freeing String as `Vec` is valid + let module = { + let mut heap_str: Box = other.module().to_string().into_boxed_str(); + let char_ptr = heap_str.as_mut_ptr(); + let str_len = heap_str.bytes().len(); + let name_inner = wasm_name_t { + size: str_len, + data: char_ptr, + }; + Box::leak(heap_str); + unsafe { NonNull::new_unchecked(Box::into_raw(Box::new(name_inner))) } + }; + + let extern_type = { + let extern_type: wasm_externtype_t = other.ty().into(); + unsafe { NonNull::new_unchecked(Box::into_raw(Box::new(extern_type))) } + }; + + wasm_importtype_t { + name, + module, + extern_type, + } + } +} diff --git a/lib/c-api/src/wasm_c_api/types/memory.rs b/lib/c-api/src/wasm_c_api/types/memory.rs new file mode 100644 index 000000000..2591a2db0 --- /dev/null +++ b/lib/c-api/src/wasm_c_api/types/memory.rs @@ -0,0 +1,61 @@ +use super::wasm_externtype_t; +use wasmer::{ExternType, MemoryType, Pages}; + +// opaque type wrapping `MemoryType` +#[derive(Clone, Debug)] +#[repr(transparent)] +#[allow(non_camel_case_types)] +pub struct wasm_memorytype_t { + pub(crate) extern_: wasm_externtype_t, +} + +impl wasm_memorytype_t { + pub(crate) fn as_memorytype(&self) -> &MemoryType { + if let ExternType::Memory(ref mt) = self.extern_.inner { + mt + } else { + unreachable!( + "Data corruption detected: `wasm_memorytype_t` does not contain a `MemoryType`" + ); + } + } +} + +wasm_declare_vec!(memorytype); + +#[derive(Copy, Clone, Debug)] +#[repr(C)] +pub struct wasm_limits_t { + pub(crate) min: u32, + pub(crate) max: u32, +} + +#[no_mangle] +pub unsafe extern "C" fn wasm_memorytype_new(limits: &wasm_limits_t) -> Box { + let min_pages = Pages(limits.min as _); + // TODO: investigate if `0` is in fact a sentinel value here + let max_pages = if limits.max == 0 { + None + } else { + Some(Pages(limits.max as _)) + }; + Box::new(wasm_memorytype_t { + extern_: wasm_externtype_t { + inner: ExternType::Memory(MemoryType::new(min_pages, max_pages, false)), + }, + }) +} + +#[no_mangle] +pub unsafe extern "C" fn wasm_memorytype_delete(_memorytype: Option>) {} + +// TODO: fix memory leak +// this function leaks memory because the returned limits pointer is not owned +#[no_mangle] +pub unsafe extern "C" fn wasm_memorytype_limits(mt: &wasm_memorytype_t) -> *const wasm_limits_t { + let md = mt.as_memorytype(); + Box::into_raw(Box::new(wasm_limits_t { + min: md.minimum.bytes().0 as _, + max: md.maximum.map(|max| max.bytes().0 as _).unwrap_or(0), + })) +} diff --git a/lib/c-api/src/wasm_c_api/types/mod.rs b/lib/c-api/src/wasm_c_api/types/mod.rs new file mode 100644 index 000000000..d25d872c3 --- /dev/null +++ b/lib/c-api/src/wasm_c_api/types/mod.rs @@ -0,0 +1,27 @@ +mod byte; +mod export; +mod extern_; +mod frame; +mod function; +mod global; +mod import; +mod memory; +mod mutability; +mod name; +mod reference; +mod table; +mod value; + +pub use byte::*; +pub use export::*; +pub use extern_::*; +pub use frame::*; +pub use function::*; +pub use global::*; +pub use import::*; +pub use memory::*; +pub use mutability::*; +pub use name::*; +pub use reference::*; +pub use table::*; +pub use value::*; diff --git a/lib/c-api/src/wasm_c_api/types/mutability.rs b/lib/c-api/src/wasm_c_api/types/mutability.rs new file mode 100644 index 000000000..23f52959c --- /dev/null +++ b/lib/c-api/src/wasm_c_api/types/mutability.rs @@ -0,0 +1,56 @@ +use std::convert::TryFrom; +use wasmer::Mutability; + +#[allow(non_camel_case_types)] +pub type wasm_mutability_t = u8; + +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +#[allow(non_camel_case_types)] +#[repr(u8)] +pub enum wasm_mutability_enum { + WASM_CONST = 0, + WASM_VAR, +} + +impl wasm_mutability_enum { + #[allow(dead_code)] + fn is_mutable(self) -> bool { + self == Self::WASM_VAR + } +} + +impl TryFrom for wasm_mutability_enum { + type Error = &'static str; + + fn try_from(item: wasm_mutability_t) -> Result { + Ok(match item { + 0 => wasm_mutability_enum::WASM_CONST, + 1 => wasm_mutability_enum::WASM_VAR, + _ => return Err("wasm_mutability_t value out of bounds"), + }) + } +} + +impl From for wasm_mutability_t { + fn from(other: wasm_mutability_enum) -> Self { + other as wasm_mutability_t + } +} + +impl From for Mutability { + fn from(other: wasm_mutability_enum) -> Self { + match other { + wasm_mutability_enum::WASM_CONST => Mutability::Const, + wasm_mutability_enum::WASM_VAR => Mutability::Var, + } + } +} + +impl From for wasm_mutability_enum { + fn from(other: Mutability) -> Self { + match other { + Mutability::Const => wasm_mutability_enum::WASM_CONST, + Mutability::Var => wasm_mutability_enum::WASM_VAR, + } + } +} diff --git a/lib/c-api/src/wasm_c_api/types/name.rs b/lib/c-api/src/wasm_c_api/types/name.rs new file mode 100644 index 000000000..aedee66cb --- /dev/null +++ b/lib/c-api/src/wasm_c_api/types/name.rs @@ -0,0 +1,4 @@ +use super::wasm_byte_vec_t; + +#[allow(non_camel_case_types)] +pub type wasm_name_t = wasm_byte_vec_t; diff --git a/lib/c-api/src/wasm_c_api/types/reference.rs b/lib/c-api/src/wasm_c_api/types/reference.rs new file mode 100644 index 000000000..f3e6424ca --- /dev/null +++ b/lib/c-api/src/wasm_c_api/types/reference.rs @@ -0,0 +1,3 @@ +// opaque type over `ExternRef`? +#[allow(non_camel_case_types)] +pub struct wasm_ref_t; diff --git a/lib/c-api/src/wasm_c_api/types/table.rs b/lib/c-api/src/wasm_c_api/types/table.rs new file mode 100644 index 000000000..beb37b659 --- /dev/null +++ b/lib/c-api/src/wasm_c_api/types/table.rs @@ -0,0 +1,79 @@ +use super::{wasm_externtype_t, wasm_limits_t, wasm_valtype_delete, wasm_valtype_t}; +use wasmer::{ExternType, TableType}; + +#[allow(non_camel_case_types)] +pub type wasm_table_size_t = u32; + +#[derive(Clone, Debug)] +#[repr(C)] +#[allow(non_camel_case_types)] +pub struct wasm_tabletype_t { + pub(crate) extern_: wasm_externtype_t, +} + +wasm_declare_vec!(tabletype); + +impl wasm_tabletype_t { + pub(crate) fn as_tabletype(&self) -> &TableType { + if let ExternType::Table(ref t) = self.extern_.inner { + t + } else { + unreachable!( + "Data corruption detected: `wasm_tabletype_t` does not contain a `TableType`" + ); + } + } +} + +#[no_mangle] +pub unsafe extern "C" fn wasm_tabletype_new( + // own + valtype: Box, + limits: &wasm_limits_t, +) -> Box { + // TODO: investigate if `0` is in fact a sentinel value here + let max_elements = if limits.max == 0 { + None + } else { + Some(limits.max as _) + }; + let out = Box::new(wasm_tabletype_t { + extern_: wasm_externtype_t { + inner: ExternType::Table(TableType::new( + (*valtype).into(), + limits.min as _, + max_elements, + )), + }, + }); + wasm_valtype_delete(Some(valtype)); + + out +} + +// TODO: fix memory leak +// this function leaks memory because the returned limits pointer is not owned +#[no_mangle] +pub unsafe extern "C" fn wasm_tabletype_limits( + tabletype: &wasm_tabletype_t, +) -> *const wasm_limits_t { + let tt = tabletype.as_tabletype(); + Box::into_raw(Box::new(wasm_limits_t { + min: tt.minimum as _, + max: tt.maximum.unwrap_or(0), + })) +} + +// TODO: fix memory leak +// this function leaks memory because the returned limits pointer is not owned +#[no_mangle] +pub unsafe extern "C" fn wasm_tabletype_element( + tabletype: &wasm_tabletype_t, +) -> *const wasm_valtype_t { + let tt = tabletype.as_tabletype(); + + Box::into_raw(Box::new(tt.ty.into())) +} + +#[no_mangle] +pub unsafe extern "C" fn wasm_tabletype_delete(_tabletype: Option>) {} diff --git a/lib/c-api/src/wasm_c_api/types/value.rs b/lib/c-api/src/wasm_c_api/types/value.rs new file mode 100644 index 000000000..c7f0fa549 --- /dev/null +++ b/lib/c-api/src/wasm_c_api/types/value.rs @@ -0,0 +1,92 @@ +use super::super::value::wasm_valkind_t; +use std::convert::TryInto; +use wasmer::ValType; + +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +#[allow(non_camel_case_types)] +#[repr(u8)] +pub enum wasm_valkind_enum { + WASM_I32 = 0, + WASM_I64 = 1, + WASM_F32 = 2, + WASM_F64 = 3, + WASM_ANYREF = 128, + WASM_FUNCREF = 129, +} + +impl From for wasm_valkind_enum { + fn from(other: ValType) -> Self { + match other { + ValType::I32 => Self::WASM_I32, + ValType::I64 => Self::WASM_I64, + ValType::F32 => Self::WASM_F32, + ValType::F64 => Self::WASM_F64, + ValType::V128 => todo!("no v128 type in Wasm C API yet!"), + ValType::ExternRef => Self::WASM_ANYREF, + ValType::FuncRef => Self::WASM_FUNCREF, + } + } +} + +impl From for ValType { + fn from(other: wasm_valkind_enum) -> Self { + use wasm_valkind_enum::*; + match other { + WASM_I32 => ValType::I32, + WASM_I64 => ValType::I64, + WASM_F32 => ValType::F32, + WASM_F64 => ValType::F64, + WASM_ANYREF => ValType::ExternRef, + WASM_FUNCREF => ValType::FuncRef, + } + } +} + +#[derive(Debug, Clone, Copy)] +#[repr(C)] +pub struct wasm_valtype_t { + valkind: wasm_valkind_enum, +} + +impl Default for wasm_valtype_t { + fn default() -> Self { + Self { + valkind: wasm_valkind_enum::WASM_I32, + } + } +} + +wasm_declare_boxed_vec!(valtype); + +impl From for ValType { + fn from(other: wasm_valtype_t) -> Self { + other.valkind.into() + } +} + +impl From for wasm_valtype_t { + fn from(other: ValType) -> Self { + Self { + valkind: other.into(), + } + } +} + +#[no_mangle] +pub extern "C" fn wasm_valtype_new(kind: wasm_valkind_t) -> Option> { + let kind_enum = kind.try_into().ok()?; + let valtype = wasm_valtype_t { valkind: kind_enum }; + Some(Box::new(valtype)) +} + +#[no_mangle] +pub unsafe extern "C" fn wasm_valtype_delete(_valtype: Option>) {} + +#[no_mangle] +pub unsafe extern "C" fn wasm_valtype_kind(valtype: *const wasm_valtype_t) -> wasm_valkind_t { + if valtype.is_null() { + // TODO: handle error + panic!("wasm_valtype_kind: argument is null pointer"); + } + return (*valtype).valkind as wasm_valkind_t; +} diff --git a/lib/c-api/src/wasm_c_api/utils.rs b/lib/c-api/src/wasm_c_api/utils.rs deleted file mode 100644 index fa041ee70..000000000 --- a/lib/c-api/src/wasm_c_api/utils.rs +++ /dev/null @@ -1,17 +0,0 @@ -#[macro_export] -macro_rules! c_try { - ($expr:expr) => {{ - let res: Result<_, _> = $expr; - match res { - Ok(val) => val, - Err(err) => { - crate::error::update_last_error(err); - return None; - } - } - }}; - ($expr:expr, $e:expr) => {{ - let opt: Option<_> = $expr; - c_try!(opt.ok_or_else(|| $e)) - }}; -} diff --git a/lib/c-api/src/wasm_c_api/value.rs b/lib/c-api/src/wasm_c_api/value.rs index 0fc7071ad..03cc48e52 100644 --- a/lib/c-api/src/wasm_c_api/value.rs +++ b/lib/c-api/src/wasm_c_api/value.rs @@ -1,4 +1,4 @@ -use super::{wasm_ref_t, wasm_valkind_enum}; +use super::types::{wasm_ref_t, wasm_valkind_enum}; use std::convert::{TryFrom, TryInto}; use std::ptr::NonNull; use wasmer::Val; diff --git a/lib/c-api/src/wasm_c_api/wasi/mod.rs b/lib/c-api/src/wasm_c_api/wasi/mod.rs index 066c00694..3ea267463 100644 --- a/lib/c-api/src/wasm_c_api/wasi/mod.rs +++ b/lib/c-api/src/wasm_c_api/wasi/mod.rs @@ -12,7 +12,6 @@ use super::{ }; // required due to really weird Rust resolution rules for macros // https://github.com/rust-lang/rust/issues/57966 -use crate::c_try; use crate::error::{update_last_error, CApiError}; use std::convert::TryFrom; use std::ffi::CStr; From 174b03f4e94f791efcbd6f9e055f83538720df22 Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Thu, 24 Sep 2020 16:15:04 +0200 Subject: [PATCH 048/281] feat(c-api) Use our fork of cbindgen. Our fork contains incoming PR. It helps for example to skip struct fields. --- Cargo.lock | 3 +- lib/c-api/Cargo.toml | 2 +- lib/c-api/build.rs | 7 ++- lib/c-api/src/wasm_c_api/engine.rs | 1 + .../src/wasm_c_api/externals/function.rs | 2 + lib/c-api/src/wasm_c_api/externals/global.rs | 1 + lib/c-api/src/wasm_c_api/externals/memory.rs | 1 + lib/c-api/src/wasm_c_api/externals/mod.rs | 2 + lib/c-api/src/wasm_c_api/externals/table.rs | 1 + lib/c-api/src/wasm_c_api/instance.rs | 1 + lib/c-api/src/wasm_c_api/module.rs | 1 + lib/c-api/src/wasm_c_api/types/extern_.rs | 3 +- lib/c-api/src/wasm_c_api/types/function.rs | 3 +- lib/c-api/src/wasm_c_api/types/global.rs | 3 +- lib/c-api/src/wasm_c_api/types/memory.rs | 3 +- lib/c-api/src/wasm_c_api/types/table.rs | 1 + lib/c-api/src/wasm_c_api/wasi/mod.rs | 2 + lib/c-api/wasmer_wasm.h | 51 ++++++++++--------- 18 files changed, 55 insertions(+), 33 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c6d2ad432..be2fe5a3a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -206,8 +206,7 @@ dependencies = [ [[package]] name = "cbindgen" version = "0.14.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "afa64e93023395ee316490cf013f07f753bc88d116eb1aec1bcee7d63fbcca53" +source = "git+https://github.com/Hywan/cbindgen?branch=incoming#ab5427b358f8953f1455e3a630af76e8dd37af67" dependencies = [ "clap", "heck", diff --git a/lib/c-api/Cargo.toml b/lib/c-api/Cargo.toml index 1196ae318..1b577fcde 100644 --- a/lib/c-api/Cargo.toml +++ b/lib/c-api/Cargo.toml @@ -78,4 +78,4 @@ cranelift-backend = ["cranelift"] llvm-backend = ["llvm"] [build-dependencies] -cbindgen = { version = "0.14.6" } +cbindgen = { git = "https://github.com/Hywan/cbindgen", branch = "incoming" } diff --git a/lib/c-api/build.rs b/lib/c-api/build.rs index 10309c6ac..038f3aef3 100644 --- a/lib/c-api/build.rs +++ b/lib/c-api/build.rs @@ -127,7 +127,12 @@ fn build_wasm_c_api_headers(crate_dir: &str, out_dir: &str) { "include-deprecated", INCLUDE_DEPRECATED_FEATURE_AS_C_DEFINE, ) - .with_include("wasm.h") + // Do not include `wasm.h` as it doesn't contain any + // documentation. + // We export the same functions, with documentations and + // examples, which is better for the user. + // + //.with_include("wasm.h") .with_documentation(true); #[cfg(not(feature = "include-deprecated"))] diff --git a/lib/c-api/src/wasm_c_api/engine.rs b/lib/c-api/src/wasm_c_api/engine.rs index e869f6744..1d16d50f2 100644 --- a/lib/c-api/src/wasm_c_api/engine.rs +++ b/lib/c-api/src/wasm_c_api/engine.rs @@ -14,6 +14,7 @@ pub extern "C" fn wasm_config_new() -> *mut wasm_config_t { #[repr(C)] pub struct wasm_engine_t { + /// cbindgen:ignore pub(crate) inner: Arc, } diff --git a/lib/c-api/src/wasm_c_api/externals/function.rs b/lib/c-api/src/wasm_c_api/externals/function.rs index 9f3fe269c..2512c475c 100644 --- a/lib/c-api/src/wasm_c_api/externals/function.rs +++ b/lib/c-api/src/wasm_c_api/externals/function.rs @@ -10,7 +10,9 @@ use wasmer::{Function, Instance, RuntimeError, Store, Val}; #[repr(C)] pub struct wasm_func_t { + /// cbindgen:ignore pub(crate) inner: Function, + /// cbindgen:ignore // this is how we ensure the instance stays alive pub(crate) instance: Option>, } diff --git a/lib/c-api/src/wasm_c_api/externals/global.rs b/lib/c-api/src/wasm_c_api/externals/global.rs index 383e00ed9..575670c19 100644 --- a/lib/c-api/src/wasm_c_api/externals/global.rs +++ b/lib/c-api/src/wasm_c_api/externals/global.rs @@ -7,6 +7,7 @@ use wasmer::{Global, Store, Val}; #[repr(C)] pub struct wasm_global_t { + /// cbindgen:ignore // maybe needs to hold onto instance pub(crate) inner: Global, } diff --git a/lib/c-api/src/wasm_c_api/externals/memory.rs b/lib/c-api/src/wasm_c_api/externals/memory.rs index b8336b7fa..751c37c10 100644 --- a/lib/c-api/src/wasm_c_api/externals/memory.rs +++ b/lib/c-api/src/wasm_c_api/externals/memory.rs @@ -6,6 +6,7 @@ use wasmer::{Memory, Pages, Store}; #[repr(C)] pub struct wasm_memory_t { + /// cbindgen:ignore // maybe needs to hold onto instance pub(crate) inner: Memory, } diff --git a/lib/c-api/src/wasm_c_api/externals/mod.rs b/lib/c-api/src/wasm_c_api/externals/mod.rs index 174a2a9f3..604651e1a 100644 --- a/lib/c-api/src/wasm_c_api/externals/mod.rs +++ b/lib/c-api/src/wasm_c_api/externals/mod.rs @@ -13,8 +13,10 @@ use wasmer::{Extern, Instance}; #[repr(C)] pub struct wasm_extern_t { + /// cbindgen:ignore // this is how we ensure the instance stays alive pub(crate) instance: Option>, + /// cbindgen:ignore pub(crate) inner: Extern, } diff --git a/lib/c-api/src/wasm_c_api/externals/table.rs b/lib/c-api/src/wasm_c_api/externals/table.rs index e0ca9b673..3ebef63f4 100644 --- a/lib/c-api/src/wasm_c_api/externals/table.rs +++ b/lib/c-api/src/wasm_c_api/externals/table.rs @@ -5,6 +5,7 @@ use wasmer::{Store, Table}; #[repr(C)] pub struct wasm_table_t { + /// cbindgen:ignore // maybe needs to hold onto instance pub(crate) inner: Table, } diff --git a/lib/c-api/src/wasm_c_api/instance.rs b/lib/c-api/src/wasm_c_api/instance.rs index 0f59866bc..7bcd1de03 100644 --- a/lib/c-api/src/wasm_c_api/instance.rs +++ b/lib/c-api/src/wasm_c_api/instance.rs @@ -10,6 +10,7 @@ use wasmer::{Extern, Instance}; #[repr(C)] pub struct wasm_instance_t { + /// cbindgen:ignore pub(crate) inner: Arc, } diff --git a/lib/c-api/src/wasm_c_api/module.rs b/lib/c-api/src/wasm_c_api/module.rs index 9133d53af..3f7efb116 100644 --- a/lib/c-api/src/wasm_c_api/module.rs +++ b/lib/c-api/src/wasm_c_api/module.rs @@ -11,6 +11,7 @@ use wasmer::{Module, Store}; #[repr(C)] pub struct wasm_module_t { + /// cbindgen:ignore pub(crate) inner: Arc, } diff --git a/lib/c-api/src/wasm_c_api/types/extern_.rs b/lib/c-api/src/wasm_c_api/types/extern_.rs index 0cd826085..b02e337fb 100644 --- a/lib/c-api/src/wasm_c_api/types/extern_.rs +++ b/lib/c-api/src/wasm_c_api/types/extern_.rs @@ -7,8 +7,9 @@ use wasmer::ExternType; #[derive(Clone, Debug)] #[allow(non_camel_case_types)] -#[repr(transparent)] +#[repr(C)] pub struct wasm_externtype_t { + /// cbindgen:ignore pub(crate) inner: ExternType, } diff --git a/lib/c-api/src/wasm_c_api/types/function.rs b/lib/c-api/src/wasm_c_api/types/function.rs index d42d62245..f00bdda67 100644 --- a/lib/c-api/src/wasm_c_api/types/function.rs +++ b/lib/c-api/src/wasm_c_api/types/function.rs @@ -4,9 +4,10 @@ use std::ptr::NonNull; use wasmer::{ExternType, FunctionType, ValType}; #[derive(Clone, Debug)] +#[repr(C)] #[allow(non_camel_case_types)] -#[repr(transparent)] pub struct wasm_functype_t { + /// cbindgen:ignore pub(crate) extern_: wasm_externtype_t, } diff --git a/lib/c-api/src/wasm_c_api/types/global.rs b/lib/c-api/src/wasm_c_api/types/global.rs index 185a4d92e..2f590cea8 100644 --- a/lib/c-api/src/wasm_c_api/types/global.rs +++ b/lib/c-api/src/wasm_c_api/types/global.rs @@ -5,9 +5,10 @@ use std::convert::TryInto; use wasmer::{ExternType, GlobalType}; #[derive(Clone, Debug)] -#[repr(transparent)] +#[repr(C)] #[allow(non_camel_case_types)] pub struct wasm_globaltype_t { + /// cbindgen:ignore pub(crate) extern_: wasm_externtype_t, } diff --git a/lib/c-api/src/wasm_c_api/types/memory.rs b/lib/c-api/src/wasm_c_api/types/memory.rs index 2591a2db0..5a1fa3a2f 100644 --- a/lib/c-api/src/wasm_c_api/types/memory.rs +++ b/lib/c-api/src/wasm_c_api/types/memory.rs @@ -3,9 +3,10 @@ use wasmer::{ExternType, MemoryType, Pages}; // opaque type wrapping `MemoryType` #[derive(Clone, Debug)] -#[repr(transparent)] +#[repr(C)] #[allow(non_camel_case_types)] pub struct wasm_memorytype_t { + /// cbindgen:ignore pub(crate) extern_: wasm_externtype_t, } diff --git a/lib/c-api/src/wasm_c_api/types/table.rs b/lib/c-api/src/wasm_c_api/types/table.rs index beb37b659..3718958df 100644 --- a/lib/c-api/src/wasm_c_api/types/table.rs +++ b/lib/c-api/src/wasm_c_api/types/table.rs @@ -8,6 +8,7 @@ pub type wasm_table_size_t = u32; #[repr(C)] #[allow(non_camel_case_types)] pub struct wasm_tabletype_t { + /// cbindgen:ignore pub(crate) extern_: wasm_externtype_t, } diff --git a/lib/c-api/src/wasm_c_api/wasi/mod.rs b/lib/c-api/src/wasm_c_api/wasi/mod.rs index 3ea267463..4a272b7b5 100644 --- a/lib/c-api/src/wasm_c_api/wasi/mod.rs +++ b/lib/c-api/src/wasm_c_api/wasi/mod.rs @@ -31,6 +31,7 @@ pub struct wasi_config_t { inherit_stdout: bool, inherit_stderr: bool, inherit_stdin: bool, + /// cbindgen:ignore state_builder: WasiStateBuilder, } @@ -92,6 +93,7 @@ pub extern "C" fn wasi_config_inherit_stdin(config: &mut wasi_config_t) { #[allow(non_camel_case_types)] #[repr(C)] pub struct wasi_env_t { + /// cbindgen:ignore inner: WasiEnv, } diff --git a/lib/c-api/wasmer_wasm.h b/lib/c-api/wasmer_wasm.h index b6f6f1c8c..38dbf8654 100644 --- a/lib/c-api/wasmer_wasm.h +++ b/lib/c-api/wasmer_wasm.h @@ -61,10 +61,6 @@ enum wasm_valkind_enum { }; typedef uint8_t wasm_valkind_enum; -typedef struct Arc_Instance Arc_Instance; - -typedef struct Arc_Module Arc_Module; - typedef struct Box_wasi_config_t Box_wasi_config_t; typedef struct Box_wasm_engine_t Box_wasm_engine_t; @@ -87,8 +83,6 @@ typedef struct Box_wasm_tabletype_t Box_wasm_tabletype_t; typedef struct Box_wasm_valtype_t Box_wasm_valtype_t; -typedef struct Option_Arc_Instance Option_Arc_Instance; - typedef struct Option_Box_wasi_config_t Option_Box_wasi_config_t; typedef struct Option_Box_wasi_env_t Option_Box_wasi_env_t; @@ -127,8 +121,6 @@ typedef struct Option_Box_wasm_valtype_t Option_Box_wasm_valtype_t; typedef struct wasi_version_t wasi_version_t; #endif -typedef struct wasm_engine_t wasm_engine_t; - typedef struct wasm_ref_t wasm_ref_t; #if defined(WASMER_WASI_ENABLED) @@ -136,22 +128,21 @@ typedef struct { bool inherit_stdout; bool inherit_stderr; bool inherit_stdin; - WasiStateBuilder state_builder; } wasi_config_t; #endif #if defined(WASMER_WASI_ENABLED) typedef struct { - WasiEnv inner; + } wasi_env_t; #endif typedef struct { - Arc_Instance inner; + } wasm_instance_t; typedef struct { - Memory inner; + } wasm_memory_t; /** @@ -162,12 +153,11 @@ typedef struct { } wasm_store_t; typedef struct { - Arc_Module inner; + } wasm_module_t; typedef struct { - Option_Arc_Instance instance; - Extern inner; + } wasm_extern_t; /** @@ -179,7 +169,9 @@ typedef struct { typedef wasm_byte_vec_t wasm_name_t; -typedef ExternType wasm_externtype_t; +typedef struct { + +} wasm_externtype_t; typedef struct { wasm_name_t *name; @@ -188,19 +180,24 @@ typedef struct { typedef uint8_t wasm_externkind_t; -typedef wasm_externtype_t wasm_functype_t; +typedef struct { -typedef wasm_externtype_t wasm_globaltype_t; - -typedef wasm_externtype_t wasm_memorytype_t; +} wasm_functype_t; typedef struct { - wasm_externtype_t extern_; + +} wasm_globaltype_t; + +typedef struct { + +} wasm_memorytype_t; + +typedef struct { + } wasm_tabletype_t; typedef struct { - Function inner; - Option_Arc_Instance instance; + } wasm_func_t; typedef struct { @@ -229,7 +226,7 @@ typedef wasm_trap_t *(*wasm_func_callback_with_env_t)(void*, const wasm_val_t *a typedef void (*wasm_env_finalizer_t)(void); typedef struct { - Global inner; + } wasm_global_t; typedef struct { @@ -250,7 +247,11 @@ typedef struct { } wasm_limits_t; typedef struct { - Table inner; + +} wasm_engine_t; + +typedef struct { + } wasm_table_t; typedef uint32_t wasm_table_size_t; From c29a259679873578bee735d9399a31d03185a84d Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Thu, 24 Sep 2020 12:00:58 -0700 Subject: [PATCH 049/281] Add `rlib` as a crate-type for wasmer-c-api This is how `wasmer-runtime-c-api` was before and seems to fix a use case that users relied on --- lib/c-api/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/c-api/Cargo.toml b/lib/c-api/Cargo.toml index bc525a831..935ef0e0c 100644 --- a/lib/c-api/Cargo.toml +++ b/lib/c-api/Cargo.toml @@ -12,7 +12,7 @@ readme = "README.md" edition = "2018" [lib] -crate-type = ["cdylib", "staticlib"] +crate-type = ["cdylib", "rlib", "staticlib"] [dependencies] wasmer = { version = "1.0.0-alpha3", path = "../api", default-features = false } From 6f2f495d66f7ab219dc129c4aa4abc8fd36d3d29 Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Fri, 25 Sep 2020 11:11:14 -0700 Subject: [PATCH 050/281] Finish updating version, add to publish.py --- Cargo.lock | 3 +-- lib/engine-object-file/Cargo.toml | 10 +++++----- scripts/publish.py | 7 +++++-- 3 files changed, 11 insertions(+), 9 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 337e239d2..35fc8962f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2229,7 +2229,6 @@ dependencies = [ "wasmer-engine-native", "wasmer-engine-object-file", "wasmer-types", - "wasmer-vm", "wasmer-wasi", "wasmer-wasi-experimental-io-devices", "wasmer-wast", @@ -2392,7 +2391,7 @@ dependencies = [ [[package]] name = "wasmer-engine-object-file" -version = "1.0.0-alpha01.0" +version = "1.0.0-alpha3" dependencies = [ "bincode", "cfg-if", diff --git a/lib/engine-object-file/Cargo.toml b/lib/engine-object-file/Cargo.toml index 4a02fdd03..a83bc685a 100644 --- a/lib/engine-object-file/Cargo.toml +++ b/lib/engine-object-file/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "wasmer-engine-object-file" -version = "1.0.0-alpha01.0" +version = "1.0.0-alpha3" authors = ["Wasmer Engineering Team "] description = "Wasmer Object File Engine" categories = ["wasm"] @@ -13,11 +13,11 @@ edition = "2018" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -wasmer-types = { path = "../wasmer-types", version = "1.0.0-alpha01.0" } -wasmer-compiler = { path = "../compiler", version = "1.0.0-alpha01.0" } +wasmer-types = { path = "../wasmer-types", version = "1.0.0-alpha3" } +wasmer-compiler = { path = "../compiler", version = "1.0.0-alpha3" } wasmer-vm = { path = "../vm", version = "1.0.0-alpha01.0" } -wasmer-engine = { path = "../engine", version = "1.0.0-alpha01.0" } -wasmer-object = { path = "../object", version = "1.0.0-alpha01.0" } +wasmer-engine = { path = "../engine", version = "1.0.0-alpha3" } +wasmer-object = { path = "../object", version = "1.0.0-alpha3" } serde = { version = "1.0", features = ["derive", "rc"] } cfg-if = "0.1" tracing = "0.1" diff --git a/scripts/publish.py b/scripts/publish.py index 7a1001a2d..c0f9fd134 100644 --- a/scripts/publish.py +++ b/scripts/publish.py @@ -36,16 +36,18 @@ dep_graph = { "wasmer-engine-jit": set(["wasmer-types", "wasmer-vm", "wasmer-compiler", "wasmer-engine"]), "wasmer-engine-native": set(["wasmer-types", "wasmer-vm", "wasmer-compiler", "wasmer-engine", "wasmer-object"]), + "wasmer-engine-object-file": set(["wasmer-types", "wasmer-vm", "wasmer-compiler", "wasmer-engine", + "wasmer-object"]), "wasmer": set(["wasmer-vm", "wasmer-compiler-singlepass", "wasmer-compiler-cranelift", "wasmer-compiler-llvm", "wasmer-compiler", "wasmer-engine", "wasmer-engine-jit", - "wasmer-engine-native", "wasmer-types"]), + "wasmer-engine-native", "wasmer-engine-object-file", "wasmer-types"]), "wasmer-cache": set(["wasmer"]), "wasmer-wasi": set(["wasmer"]), "wasmer-wasi-experimental-io-devices": set(["wasmer-wasi"]), "wasmer-emscripten": set(["wasmer"]), "wasmer-c-api": set(["wasmer", "wasmer-compiler", "wasmer-compiler-cranelift", "wasmer-compiler-singlepass", "wasmer-compiler-llvm", "wasmer-emscripten", "wasmer-engine", "wasmer-engine-jit", - "wasmer-engine-native", "wasmer-wasi", "wasmer-types"]), + "wasmer-engine-native", "wasmer-engine-object-file", "wasmer-wasi", "wasmer-types"]), } # where each crate is located in the `lib` directory @@ -62,6 +64,7 @@ location = { "wasmer-engine": "engine", "wasmer-engine-jit": "engine-jit", "wasmer-engine-native": "engine-native", + "wasmer-engine-object-file": "engine-object-file", "wasmer-cache": "cache", "wasmer": "api", "wasmer-wasi": "wasi", From b32371db6ff907d5b8f973d7582ece0f60af2ee6 Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Fri, 25 Sep 2020 12:53:06 -0700 Subject: [PATCH 051/281] Begin adding CLI integration tests for object-file-engine --- Cargo.lock | 8 + Cargo.toml | 1 + lib/engine-object-file/Cargo.toml | 2 - tests/integration/cli/Cargo.toml | 12 ++ tests/integration/cli/src/compile.rs | 162 ++++++++++++++++++ tests/integration/cli/src/lib.rs | 6 + .../src/object_file_engine_test_c_source.c | 143 ++++++++++++++++ 7 files changed, 332 insertions(+), 2 deletions(-) create mode 100644 tests/integration/cli/Cargo.toml create mode 100644 tests/integration/cli/src/compile.rs create mode 100644 tests/integration/cli/src/lib.rs create mode 100644 tests/integration/cli/src/object_file_engine_test_c_source.c diff --git a/Cargo.lock b/Cargo.lock index 35fc8962f..ce7c68c70 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2407,6 +2407,14 @@ dependencies = [ "wasmer-vm", ] +[[package]] +name = "wasmer-integration-tests-cli" +version = "1.0.0-alpha3" +dependencies = [ + "anyhow", + "tempfile", +] + [[package]] name = "wasmer-object" version = "1.0.0-alpha3" diff --git a/Cargo.toml b/Cargo.toml index fad668064..c65c8da9e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -46,6 +46,7 @@ members = [ "lib/wasi-experimental-io-devices", "lib/wasmer-types", "tests/lib/wast", + "tests/integration/cli", ] exclude = [ "lib/deprecated", diff --git a/lib/engine-object-file/Cargo.toml b/lib/engine-object-file/Cargo.toml index a83bc685a..47aee16c1 100644 --- a/lib/engine-object-file/Cargo.toml +++ b/lib/engine-object-file/Cargo.toml @@ -10,8 +10,6 @@ repository = "https://github.com/wasmerio/wasmer" readme = "README.md" edition = "2018" -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - [dependencies] wasmer-types = { path = "../wasmer-types", version = "1.0.0-alpha3" } wasmer-compiler = { path = "../compiler", version = "1.0.0-alpha3" } diff --git a/tests/integration/cli/Cargo.toml b/tests/integration/cli/Cargo.toml new file mode 100644 index 000000000..3b2a58a09 --- /dev/null +++ b/tests/integration/cli/Cargo.toml @@ -0,0 +1,12 @@ +[package] +name = "wasmer-integration-tests-cli" +version = "1.0.0-alpha3" +authors = ["Wasmer Engineering Team "] +description = "CLI integration tests" +repository = "https://github.com/wasmerio/wasmer" +edition = "2018" +publish = false + +[dependencies] +anyhow = "1" +tempfile = "3" \ No newline at end of file diff --git a/tests/integration/cli/src/compile.rs b/tests/integration/cli/src/compile.rs new file mode 100644 index 000000000..85481b3fe --- /dev/null +++ b/tests/integration/cli/src/compile.rs @@ -0,0 +1,162 @@ +//! CLI tests for the compile subcommand. + +use anyhow::bail; +use std::fs; +use std::io::Write; +use std::path::Path; +use std::process::Command; + +#[derive(Debug, Copy, Clone)] +pub enum Engine { + Jit, + Native, + ObjectFile, +} + +impl Engine { + pub const fn to_flag(self) -> &'static str { + match self { + Engine::Jit => "--jit", + Engine::Native => "--native", + Engine::ObjectFile => "--object-file", + } + } +} + +#[derive(Debug, Copy, Clone)] +pub enum Backend { + Cranelift, + LLVM, + Singlepass, +} + +impl Backend { + pub const fn to_flag(self) -> &'static str { + match self { + Backend::Cranelift => "--cranelift", + Backend::LLVM => "--llvm", + Backend::Singlepass => "--singlepass", + } + } +} + +fn run_wasmer_compile( + path_to_wasm: &Path, + wasm_output_path: &Path, + header_output_path: &Path, + backend: Backend, + engine: Engine, +) -> anyhow::Result<()> { + let output = Command::new("wasmer") + .arg("compile") + .arg(path_to_wasm) + .arg(backend.to_flag()) + .arg(engine.to_flag()) + .arg("-o") + .arg(wasm_output_path) + .arg("--header") + .arg(header_output_path) + .output()?; + + if !output.status.success() { + bail!( + "wasmer compile failed with: {}", + std::str::from_utf8(&output.stderr) + .expect("stderr is not utf8! need to handle arbitrary bytes") + ); + } + Ok(()) +} + +fn run_c_compile(path_to_c_src: &Path, output_name: &Path) -> anyhow::Result<()> { + let output = Command::new("clang") + .arg("-O2") + .arg("-c") + .arg(path_to_c_src) + .arg(output_name) + .output()?; + + if !output.status.success() { + bail!( + "C code compile failed with: {}", + std::str::from_utf8(&output.stderr) + .expect("stderr is not utf8! need to handle arbitrary bytes") + ); + } + Ok(()) +} + +fn link_code(c_src_object: &Path, wasm_object: &Path, lib_wasmer: &Path) -> anyhow::Result<()> { + // TODO: linker selection + let output = Command::new("g++") + .arg("-O2") + .arg(c_src_object) + .arg(wasm_object) + .arg(lib_wasmer) + .output()?; + + if !output.status.success() { + bail!( + "linking failed with: {}", + std::str::from_utf8(&output.stderr) + .expect("stderr is not utf8! need to handle arbitrary bytes") + ); + } + Ok(()) +} + +fn run_code(executable_path: &Path) -> anyhow::Result<()> { + let output = Command::new(executable_path).output()?; + + if !output.status.success() { + bail!( + "running executable failed: {}", + std::str::from_utf8(&output.stderr) + .expect("stderr is not utf8! need to handle arbitrary bytes") + ); + } + Ok(()) +} + +const OBJECT_FILE_ENGINE_TEST_C_SOURCE: &[u8] = + include_bytes!("object_file_engine_test_c_source.c"); +// TODO: +const OBJECT_FILE_ENGINE_TEST_WASM_PATH: &str = + concat!(env!("CARGO_MANIFEST_DIR"), "/assets/jq.wasm"); + +#[test] +fn object_file_engine_works() -> anyhow::Result<()> { + let operating_dir = tempfile::tempdir()?; + + std::env::set_current_dir(&operating_dir); + + let wasm_path = Path::new(OBJECT_FILE_ENGINE_TEST_WASM_PATH); + let wasm_object_path = Path::new("wasm.o"); + let header_output_path = Path::new("my_wasm.h"); + // TODO: figure out how to get access to libwasmer here + let libwasmer_path = Path::new("libwasmer.a"); + + run_wasmer_compile( + &wasm_path, + &wasm_object_path, + &header_output_path, + Backend::Cranelift, + Engine::ObjectFile, + )?; + + let c_src_file_name = Path::new("c_src.c"); + let c_object_name = Path::new("c_src.o"); + let executable_name = Path::new("a.out"); + + // TODO: adjust C source code based on locations of things + { + let mut c_src_file = fs::File::open(&c_src_file_name)?; + c_src_file.write_all(OBJECT_FILE_ENGINE_TEST_C_SOURCE)?; + } + run_c_compile(&c_src_file_name, &c_object_name)?; + link_code(&c_object_name, wasm_object_path, &libwasmer_path)?; + + run_code(&executable_name)?; + + Ok(()) +} diff --git a/tests/integration/cli/src/lib.rs b/tests/integration/cli/src/lib.rs new file mode 100644 index 000000000..69d222b5e --- /dev/null +++ b/tests/integration/cli/src/lib.rs @@ -0,0 +1,6 @@ +#![forbid(unsafe_code)] +#![cfg(test)] + +//! CLI integration tests + +mod compile; diff --git a/tests/integration/cli/src/object_file_engine_test_c_source.c b/tests/integration/cli/src/object_file_engine_test_c_source.c new file mode 100644 index 000000000..2a5d3aa43 --- /dev/null +++ b/tests/integration/cli/src/object_file_engine_test_c_source.c @@ -0,0 +1,143 @@ +#include "wasmer_wasm.h" +#include "wasm.h" +#include "my_wasm.h" + +#include +#include + +void wasmer_function__1(void); +void wasmer_trampoline_function_call__1(void*, void*, void*); + +// todo: add to wasmer_wasm.h or something +void* wasm_instance_get_vmctx_ptr(wasm_instance_t*); + +// a bit of a hack; TODO: clean this up +typedef struct my_byte_vec_t { + size_t size; + char* data; +} my_byte_vec_t; + + +void print_wasmer_error() +{ + int error_len = wasmer_last_error_length(); + printf("Error len: `%d`\n", error_len); + char *error_str = malloc(error_len); + wasmer_last_error_message(error_str, error_len); + printf("Error str: `%s`\n", error_str); +} + + +int main() { + printf("Initializing...\n"); + wasm_engine_t* engine = wasm_engine_new(); + wasm_store_t* store = wasm_store_new(engine); + + char* byte_ptr = (char*)&WASMER_METADATA[0]; + + // We need to pass all the bytes as one big buffer so we have to do all this logic to memcpy + // the various pieces together from the generated header file. + // + // We should provide a `deseralize_vectored` function to avoid requiring this extra work. + + size_t num_function_pointers + = sizeof(function_pointers) / sizeof(void*); + size_t num_function_trampolines + = sizeof(function_trampolines) / sizeof(void*); + size_t num_dynamic_function_trampoline_pointers + = sizeof(dynamic_function_trampoline_pointers) / sizeof(void*); + + + size_t buffer_size = module_bytes_len + + sizeof(size_t) + sizeof(function_pointers) + + sizeof(size_t) + sizeof(function_trampolines) + + sizeof(size_t) + sizeof(dynamic_function_trampoline_pointers); + + char* memory_buffer = (char*) malloc(buffer_size); + size_t current_offset = 0; + printf("Buffer size: %d\n", buffer_size); + + memcpy(memory_buffer + current_offset, byte_ptr, module_bytes_len); + current_offset += module_bytes_len; + + memcpy(memory_buffer + current_offset, (void*)&num_function_pointers, sizeof(size_t)); + current_offset += sizeof(size_t); + + memcpy(memory_buffer + current_offset, (void*)&function_pointers[0], sizeof(function_pointers)); + current_offset += sizeof(function_pointers); + + memcpy(memory_buffer + current_offset, (void*)&num_function_trampolines, sizeof(size_t)); + current_offset += sizeof(size_t); + + memcpy(memory_buffer + current_offset, (void*)&function_trampolines[0], sizeof(function_trampolines)); + current_offset += sizeof(function_trampolines); + + memcpy(memory_buffer + current_offset, (void*)&num_dynamic_function_trampoline_pointers, sizeof(size_t)); + current_offset += sizeof(size_t); + + memcpy(memory_buffer + current_offset, (void*)&dynamic_function_trampoline_pointers[0], sizeof(dynamic_function_trampoline_pointers)); + current_offset += sizeof(dynamic_function_trampoline_pointers); + + my_byte_vec_t module_byte_vec = { + .size = buffer_size, + .data = memory_buffer, + }; + + wasm_module_t* module = wasm_module_deserialize(store, (wasm_byte_vec_t*) &module_byte_vec); + if (! module) { + printf("Failed to create module\n"); + print_wasmer_error(); + return -1; + } + free(memory_buffer); + + // We have now finished the memory buffer book keeping and we have a valid Module. + + // In this example we're passing some JavaScript source code as a command line argumnet + // to a WASI module that can evaluate JavaScript. + wasi_config_t* config = wasi_config_new("constant_value_here"); + const char* js_string = "function greet(name) { return JSON.stringify('Hello, ' + name); }; print(greet('World'));"; + wasi_config_arg(config, "--eval"); + wasi_config_arg(config, js_string); + wasi_env_t* wasi_env = wasi_env_new(config); + if (!wasi_env) { + printf("> Error building WASI env!\n"); + print_wasmer_error(); + return 1; + } + + wasm_importtype_vec_t import_types; + wasm_module_imports(module, &import_types); + int num_imports = import_types.size; + wasm_extern_t** imports = malloc(num_imports * sizeof(wasm_extern_t*)); + wasm_importtype_vec_delete(&import_types); + + bool get_imports_result = wasi_get_imports(store, module, wasi_env, imports); + if (!get_imports_result) { + printf("> Error getting WASI imports!\n"); + print_wasmer_error(); + return 1; + } + + wasm_instance_t* instance = wasm_instance_new(store, module, (const wasm_extern_t* const*) imports, NULL); + if (! instance) { + printf("Failed to create instance\n"); + print_wasmer_error(); + return -1; + } + wasi_env_set_instance(wasi_env, instance); + + // WASI is now set up. + + void* vmctx = wasm_instance_get_vmctx_ptr(instance); + wasm_val_t* inout[2] = { NULL, NULL }; + + // We're able to call our compiled functions directly through their trampolines. + wasmer_trampoline_function_call__1(vmctx, wasmer_function__1, &inout); + + wasm_instance_delete(instance); + wasm_module_delete(module); + wasm_store_delete(store); + wasm_engine_delete(engine); + return 0; +} From e4e706bbeaac6272406864bc5da901ca4f0ef773 Mon Sep 17 00:00:00 2001 From: Syrus Date: Fri, 25 Sep 2020 14:20:36 -0700 Subject: [PATCH 052/281] Register individual FDEs for musl libc --- lib/engine-jit/src/unwind/systemv.rs | 48 +++++++++++----------------- 1 file changed, 19 insertions(+), 29 deletions(-) diff --git a/lib/engine-jit/src/unwind/systemv.rs b/lib/engine-jit/src/unwind/systemv.rs index 86d33c250..e9e452a0d 100644 --- a/lib/engine-jit/src/unwind/systemv.rs +++ b/lib/engine-jit/src/unwind/systemv.rs @@ -59,39 +59,29 @@ impl UnwindRegistry { #[allow(clippy::cast_ptr_alignment)] unsafe fn register_frames(&mut self, eh_frame: &[u8]) { - cfg_if::cfg_if! { - if #[cfg(target_os = "macos")] { - // On macOS, `__register_frame` takes a pointer to a single FDE - let start = eh_frame.as_ptr(); - let end = start.add(eh_frame.len()); - let mut current = start; + if cfg!(all(target_os = "linux", target_env = "gnu")) { + // On gnu (libgcc), `__register_frame` will walk the FDEs until an entry of length 0 + let ptr = eh_frame.as_ptr(); + __register_frame(ptr); + self.registrations.push(ptr as usize); + } else { + // For libunwind, `__register_frame` takes a pointer to a single FDE + let start = eh_frame.as_ptr(); + let end = start.add(eh_frame.len()); + let mut current = start; - // Walk all of the entries in the frame table and register them - while current < end { - let len = std::ptr::read::(current as *const u32) as usize; + // Walk all of the entries in the frame table and register them + while current < end { + let len = std::ptr::read::(current as *const u32) as usize; - // Skip over the CIE - if current != start { - __register_frame(current); - self.registrations.push(current as usize); - } - - // Move to the next table entry (+4 because the length itself is not inclusive) - current = current.add(len + 4); + // Skip over the CIE + if current != start { + __register_frame(current); + self.registrations.push(current as usize); } - } else { - // On other platforms, `__register_frame` will walk the FDEs until an entry of length 0 - // Registering an empty `eh_frame` (i.e. which - // contains empty FDEs) cause problems on Linux when - // deregistering it. We must avoid this - // scenario. Usually, this is handled upstream by the - // compilers. - debug_assert_ne!(eh_frame, &[0, 0, 0, 0], "`eh_frame` seems to contain empty FDEs"); - - let ptr = eh_frame.as_ptr(); - __register_frame(ptr); - self.registrations.push(ptr as usize); + // Move to the next table entry (+4 because the length itself is not inclusive) + current = current.add(len + 4); } } } From 1f95b866ecc8122d77f103857e5dff7d19696f26 Mon Sep 17 00:00:00 2001 From: Syrus Date: Fri, 25 Sep 2020 14:32:59 -0700 Subject: [PATCH 053/281] Add the debug assert back --- lib/engine-jit/src/unwind/systemv.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/lib/engine-jit/src/unwind/systemv.rs b/lib/engine-jit/src/unwind/systemv.rs index e9e452a0d..53b312d51 100644 --- a/lib/engine-jit/src/unwind/systemv.rs +++ b/lib/engine-jit/src/unwind/systemv.rs @@ -60,6 +60,13 @@ impl UnwindRegistry { #[allow(clippy::cast_ptr_alignment)] unsafe fn register_frames(&mut self, eh_frame: &[u8]) { if cfg!(all(target_os = "linux", target_env = "gnu")) { + // Registering an empty `eh_frame` (i.e. which + // contains empty FDEs) cause problems on Linux when + // deregistering it. We must avoid this + // scenario. Usually, this is handled upstream by the + // compilers. + debug_assert_ne!(eh_frame, &[0, 0, 0, 0], "`eh_frame` seems to contain empty FDEs"); + // On gnu (libgcc), `__register_frame` will walk the FDEs until an entry of length 0 let ptr = eh_frame.as_ptr(); __register_frame(ptr); From 7f4d873af461f0e725a481d9a0814d8da962366c Mon Sep 17 00:00:00 2001 From: Syrus Date: Fri, 25 Sep 2020 16:46:19 -0700 Subject: [PATCH 054/281] Add length check --- lib/engine-jit/src/unwind/systemv.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/engine-jit/src/unwind/systemv.rs b/lib/engine-jit/src/unwind/systemv.rs index 53b312d51..3ed3e13d8 100644 --- a/lib/engine-jit/src/unwind/systemv.rs +++ b/lib/engine-jit/src/unwind/systemv.rs @@ -82,7 +82,8 @@ impl UnwindRegistry { let len = std::ptr::read::(current as *const u32) as usize; // Skip over the CIE - if current != start { + // We also skip to register the frame if the FDE is empty (len == 0) + if current != start && len > 0 { __register_frame(current); self.registrations.push(current as usize); } From 27dcd68fee166ff2112d5f5e1bfde88bb09a175d Mon Sep 17 00:00:00 2001 From: Syrus Date: Fri, 25 Sep 2020 16:54:57 -0700 Subject: [PATCH 055/281] Added extra comment --- lib/engine-jit/src/unwind/systemv.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/engine-jit/src/unwind/systemv.rs b/lib/engine-jit/src/unwind/systemv.rs index 3ed3e13d8..a848c49f7 100644 --- a/lib/engine-jit/src/unwind/systemv.rs +++ b/lib/engine-jit/src/unwind/systemv.rs @@ -82,8 +82,10 @@ impl UnwindRegistry { let len = std::ptr::read::(current as *const u32) as usize; // Skip over the CIE - // We also skip to register the frame if the FDE is empty (len == 0) - if current != start && len > 0 { + if current != start { + // If len == 0, __register_frame will be a no-op. + // So rather than skip it here, we just let __register_frame + // deal with empty FDEs the way they want. __register_frame(current); self.registrations.push(current as usize); } From 76ad597bef89c7a0210eb5ec5885ab33bfec7f16 Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Sun, 27 Sep 2020 15:45:42 -0700 Subject: [PATCH 056/281] Clean up CLI integration tests --- Cargo.lock | 1 + Makefile | 3 + lib/cli/Cargo.toml | 1 + tests/integration/cli/assets/qjs.wasm | 1 + tests/integration/cli/assets/wasm.h | 1 + tests/integration/cli/assets/wasmer_wasm.h | 1 + tests/integration/cli/src/compile.rs | 229 ++++++++++++++------- 7 files changed, 167 insertions(+), 70 deletions(-) create mode 120000 tests/integration/cli/assets/qjs.wasm create mode 120000 tests/integration/cli/assets/wasm.h create mode 120000 tests/integration/cli/assets/wasmer_wasm.h diff --git a/Cargo.lock b/Cargo.lock index ce7c68c70..f23e7aa48 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2229,6 +2229,7 @@ dependencies = [ "wasmer-engine-native", "wasmer-engine-object-file", "wasmer-types", + "wasmer-vm", "wasmer-wasi", "wasmer-wasi-experimental-io-devices", "wasmer-wast", diff --git a/Makefile b/Makefile index 98a6ac221..3fad585b5 100644 --- a/Makefile +++ b/Makefile @@ -144,6 +144,9 @@ test-deprecated: cargo test --manifest-path lib/deprecated/runtime/Cargo.toml -p wasmer-runtime --release cargo test --manifest-path lib/deprecated/runtime/Cargo.toml -p wasmer-runtime --release --examples +test-integration: + WASMER_TEST_WASMER_PATH=`pwd`/target/release/wasmer WASMER_TEST_LIBWASMER_PATH=`pwd`/target/release/libwasmer_c_api.a cargo test -p wasmer-integration-tests-cli + ############# # Packaging # ############# diff --git a/lib/cli/Cargo.toml b/lib/cli/Cargo.toml index 5c3ff2f60..b73828bf8 100644 --- a/lib/cli/Cargo.toml +++ b/lib/cli/Cargo.toml @@ -27,6 +27,7 @@ wasmer-engine = { version = "1.0.0-alpha3", path = "../engine" } wasmer-engine-jit = { version = "1.0.0-alpha3", path = "../engine-jit", optional = true } wasmer-engine-native = { version = "1.0.0-alpha3", path = "../engine-native", optional = true } wasmer-engine-object-file = { version = "1.0.0-alpha3", path = "../engine-object-file", optional = true } +wasmer-vm = { version = "1.0.0-alpha3", path = "../vm" } wasmer-wasi = { version = "1.0.0-alpha3", path = "../wasi", optional = true } wasmer-wasi-experimental-io-devices = { version = "1.0.0-alpha3", path = "../wasi-experimental-io-devices", optional = true } wasmer-wast = { version = "1.0.0-alpha3", path = "../../tests/lib/wast", optional = true } diff --git a/tests/integration/cli/assets/qjs.wasm b/tests/integration/cli/assets/qjs.wasm new file mode 120000 index 000000000..a50e63916 --- /dev/null +++ b/tests/integration/cli/assets/qjs.wasm @@ -0,0 +1 @@ +../../../../lib/c-api/tests/assets/qjs.wasm \ No newline at end of file diff --git a/tests/integration/cli/assets/wasm.h b/tests/integration/cli/assets/wasm.h new file mode 120000 index 000000000..f6a87ecce --- /dev/null +++ b/tests/integration/cli/assets/wasm.h @@ -0,0 +1 @@ +../../../../lib/c-api/tests/wasm-c-api/include/wasm.h \ No newline at end of file diff --git a/tests/integration/cli/assets/wasmer_wasm.h b/tests/integration/cli/assets/wasmer_wasm.h new file mode 120000 index 000000000..ba89eb029 --- /dev/null +++ b/tests/integration/cli/assets/wasmer_wasm.h @@ -0,0 +1 @@ +../../../../lib/c-api/wasmer_wasm.h \ No newline at end of file diff --git a/tests/integration/cli/src/compile.rs b/tests/integration/cli/src/compile.rs index 85481b3fe..0919405b9 100644 --- a/tests/integration/cli/src/compile.rs +++ b/tests/integration/cli/src/compile.rs @@ -1,11 +1,36 @@ //! CLI tests for the compile subcommand. -use anyhow::bail; +use anyhow::{bail, Context}; +use std::env; use std::fs; use std::io::Write; -use std::path::Path; +use std::path::{Path, PathBuf}; use std::process::Command; +const CLI_INTEGRATION_TESTS_ASSETS: &str = concat!(env!("CARGO_MANIFEST_DIR"), "/assets"); + +const OBJECT_FILE_ENGINE_TEST_C_SOURCE: &[u8] = + include_bytes!("object_file_engine_test_c_source.c"); +// TODO: +const OBJECT_FILE_ENGINE_TEST_WASM_PATH: &str = + concat!(env!("CARGO_MANIFEST_DIR"), "/assets/qjs.wasm"); + +/// Get the path to the `wasmer` executable to be used in this test. +fn get_wasmer_path() -> PathBuf { + PathBuf::from( + env::var("WASMER_TEST_WASMER_PATH") + .expect("`WASMER_TEST_WASMER_PATH` env var set with the path of a wasmer executable"), + ) +} + +/// Get the path to the `libwasmer.a` static library. +fn get_libwasmer_path() -> PathBuf { + PathBuf::from( + env::var("WASMER_TEST_LIBWASMER_PATH") + .expect("`WASMER_TEST_LIBWASMER_PATH` env var set with the path of libwasmer.a"), + ) +} + #[derive(Debug, Copy, Clone)] pub enum Engine { Jit, @@ -24,55 +49,84 @@ impl Engine { } #[derive(Debug, Copy, Clone)] -pub enum Backend { +pub enum Compiler { Cranelift, LLVM, Singlepass, } -impl Backend { +impl Compiler { pub const fn to_flag(self) -> &'static str { match self { - Backend::Cranelift => "--cranelift", - Backend::LLVM => "--llvm", - Backend::Singlepass => "--singlepass", + Compiler::Cranelift => "--cranelift", + Compiler::LLVM => "--llvm", + Compiler::Singlepass => "--singlepass", } } } -fn run_wasmer_compile( - path_to_wasm: &Path, - wasm_output_path: &Path, - header_output_path: &Path, - backend: Backend, +/// Data used to run the `wasmer compile` command. +#[derive(Debug)] +struct WasmerCompile { + /// Path to wasmer executable used to run the command. + wasmer_path: PathBuf, + /// Path to the Wasm file to compile. + wasm_path: PathBuf, + /// Path to the object file produced by compiling the Wasm. + wasm_object_path: PathBuf, + /// Path to output the generated header to. + header_output_path: PathBuf, + /// Compiler with which to compile the Wasm. + compiler: Compiler, + /// Engine with which to use to generate the artifacts. engine: Engine, -) -> anyhow::Result<()> { - let output = Command::new("wasmer") - .arg("compile") - .arg(path_to_wasm) - .arg(backend.to_flag()) - .arg(engine.to_flag()) - .arg("-o") - .arg(wasm_output_path) - .arg("--header") - .arg(header_output_path) - .output()?; +} - if !output.status.success() { - bail!( - "wasmer compile failed with: {}", - std::str::from_utf8(&output.stderr) - .expect("stderr is not utf8! need to handle arbitrary bytes") - ); +impl Default for WasmerCompile { + fn default() -> Self { + Self { + wasmer_path: get_wasmer_path(), + wasm_path: PathBuf::from(OBJECT_FILE_ENGINE_TEST_WASM_PATH), + wasm_object_path: PathBuf::from("wasm.o"), + header_output_path: PathBuf::from("my_wasm.h"), + compiler: Compiler::Cranelift, + engine: Engine::ObjectFile, + } + } +} + +impl WasmerCompile { + fn run(&self) -> anyhow::Result<()> { + let output = Command::new(&self.wasmer_path) + .arg("compile") + .arg(&self.wasm_path) + .arg(&self.compiler.to_flag()) + .arg(&self.engine.to_flag()) + .arg("-o") + .arg(&self.wasm_object_path) + .arg("--header") + .arg(&self.header_output_path) + .output()?; + + if !output.status.success() { + bail!( + "wasmer compile failed with: {}", + std::str::from_utf8(&output.stderr) + .expect("stderr is not utf8! need to handle arbitrary bytes") + ); + } + Ok(()) } - Ok(()) } fn run_c_compile(path_to_c_src: &Path, output_name: &Path) -> anyhow::Result<()> { - let output = Command::new("clang") + let output = Command::new("cc") .arg("-O2") .arg("-c") .arg(path_to_c_src) + .arg("-I") + .arg(CLI_INTEGRATION_TESTS_ASSETS) + .arg("-o") .arg(output_name) .output()?; @@ -86,23 +140,52 @@ fn run_c_compile(path_to_c_src: &Path, output_name: &Path) -> anyhow::Result<()> Ok(()) } -fn link_code(c_src_object: &Path, wasm_object: &Path, lib_wasmer: &Path) -> anyhow::Result<()> { - // TODO: linker selection - let output = Command::new("g++") - .arg("-O2") - .arg(c_src_object) - .arg(wasm_object) - .arg(lib_wasmer) - .output()?; +/// Data used to run a linking command for generated artifacts. +#[derive(Debug)] +struct LinkCode { + /// Path to the linker used to run the linking command. + linker_path: PathBuf, + /// String used as an optimization flag. + optimization_flag: String, + /// Paths of objects to link. + object_paths: Vec, + /// Path to the output target. + output_path: PathBuf, + /// Path to the static libwasmer library. + libwasmer_path: PathBuf, +} - if !output.status.success() { - bail!( - "linking failed with: {}", - std::str::from_utf8(&output.stderr) - .expect("stderr is not utf8! need to handle arbitrary bytes") - ); +impl Default for LinkCode { + fn default() -> Self { + Self { + linker_path: PathBuf::from("g++"), + optimization_flag: String::from("-O2"), + object_paths: vec![], + output_path: PathBuf::from("a.out"), + libwasmer_path: get_libwasmer_path(), + } + } +} + +impl LinkCode { + fn run(&self) -> anyhow::Result<()> { + let output = Command::new(&self.linker_path) + .arg(&self.optimization_flag) + .args(&self.object_paths) + .arg(&self.libwasmer_path) + .arg("-o") + .arg(&self.output_path) + .output()?; + + if !output.status.success() { + bail!( + "linking failed with: {}", + std::str::from_utf8(&output.stderr) + .expect("stderr is not utf8! need to handle arbitrary bytes") + ); + } + Ok(()) } - Ok(()) } fn run_code(executable_path: &Path) -> anyhow::Result<()> { @@ -118,45 +201,51 @@ fn run_code(executable_path: &Path) -> anyhow::Result<()> { Ok(()) } -const OBJECT_FILE_ENGINE_TEST_C_SOURCE: &[u8] = - include_bytes!("object_file_engine_test_c_source.c"); -// TODO: -const OBJECT_FILE_ENGINE_TEST_WASM_PATH: &str = - concat!(env!("CARGO_MANIFEST_DIR"), "/assets/jq.wasm"); - #[test] fn object_file_engine_works() -> anyhow::Result<()> { let operating_dir = tempfile::tempdir()?; std::env::set_current_dir(&operating_dir); - let wasm_path = Path::new(OBJECT_FILE_ENGINE_TEST_WASM_PATH); - let wasm_object_path = Path::new("wasm.o"); - let header_output_path = Path::new("my_wasm.h"); - // TODO: figure out how to get access to libwasmer here - let libwasmer_path = Path::new("libwasmer.a"); + let wasm_path = PathBuf::from(OBJECT_FILE_ENGINE_TEST_WASM_PATH); + let wasm_object_path = PathBuf::from("wasm.o"); + let header_output_path = PathBuf::from("my_wasm.h"); + let libwasmer_path = get_libwasmer_path(); - run_wasmer_compile( - &wasm_path, - &wasm_object_path, - &header_output_path, - Backend::Cranelift, - Engine::ObjectFile, - )?; + WasmerCompile { + wasm_path: wasm_path.clone(), + wasm_object_path: wasm_object_path.clone(), + header_output_path, + compiler: Compiler::Cranelift, + engine: Engine::ObjectFile, + ..Default::default() + } + .run() + .context("Failed to compile wasm with Wasmer")?; let c_src_file_name = Path::new("c_src.c"); - let c_object_name = Path::new("c_src.o"); - let executable_name = Path::new("a.out"); + let c_object_path = PathBuf::from("c_src.o"); + let executable_path = PathBuf::from("a.out"); // TODO: adjust C source code based on locations of things { - let mut c_src_file = fs::File::open(&c_src_file_name)?; + let mut c_src_file = fs::OpenOptions::new() + .create_new(true) + .write(true) + .open(&c_src_file_name) + .context("Failed to open C source code file")?; c_src_file.write_all(OBJECT_FILE_ENGINE_TEST_C_SOURCE)?; } - run_c_compile(&c_src_file_name, &c_object_name)?; - link_code(&c_object_name, wasm_object_path, &libwasmer_path)?; + run_c_compile(&c_src_file_name, &c_object_path).context("Failed to compile C source code")?; + LinkCode { + object_paths: vec![c_object_path, wasm_object_path], + output_path: executable_path.clone(), + ..Default::default() + } + .run() + .context("Failed to link objects together")?; - run_code(&executable_name)?; + run_code(&executable_path).context("Failed to run generated executable")?; Ok(()) } From 007c77416fff29715ea2eaad96e8ab666fc9083e Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Sun, 27 Sep 2020 17:28:10 -0700 Subject: [PATCH 057/281] Make CLI integration tests use sensible defaults: no required env vars --- .github/workflows/main.yaml | 3 ++ Makefile | 2 +- tests/integration/cli/src/compile.rs | 42 ++++++++++++++++++++-------- 3 files changed, 34 insertions(+), 13 deletions(-) diff --git a/.github/workflows/main.yaml b/.github/workflows/main.yaml index eae48e621..5ad198e1b 100644 --- a/.github/workflows/main.yaml +++ b/.github/workflows/main.yaml @@ -143,6 +143,9 @@ jobs: run: | make build-wapm if: needs.setup.outputs.DOING_RELEASE == '1' + - name: Run integration tests + run: | + make test-integration - name: Package Wasmer run: | make package diff --git a/Makefile b/Makefile index 3fad585b5..d17627562 100644 --- a/Makefile +++ b/Makefile @@ -145,7 +145,7 @@ test-deprecated: cargo test --manifest-path lib/deprecated/runtime/Cargo.toml -p wasmer-runtime --release --examples test-integration: - WASMER_TEST_WASMER_PATH=`pwd`/target/release/wasmer WASMER_TEST_LIBWASMER_PATH=`pwd`/target/release/libwasmer_c_api.a cargo test -p wasmer-integration-tests-cli + cargo test -p wasmer-integration-tests-cli ############# # Packaging # diff --git a/tests/integration/cli/src/compile.rs b/tests/integration/cli/src/compile.rs index 0919405b9..e30ebd5ad 100644 --- a/tests/integration/cli/src/compile.rs +++ b/tests/integration/cli/src/compile.rs @@ -15,19 +15,25 @@ const OBJECT_FILE_ENGINE_TEST_C_SOURCE: &[u8] = const OBJECT_FILE_ENGINE_TEST_WASM_PATH: &str = concat!(env!("CARGO_MANIFEST_DIR"), "/assets/qjs.wasm"); +const WASMER_PATH: &str = concat!( + env!("CARGO_MANIFEST_DIR"), + "/../../../target/release/wasmer" +); + +const LIBWASMER_PATH: &str = concat!( + env!("CARGO_MANIFEST_DIR"), + "/../../../target/release/libwasmer_c_api.a" +); + /// Get the path to the `wasmer` executable to be used in this test. fn get_wasmer_path() -> PathBuf { - PathBuf::from( - env::var("WASMER_TEST_WASMER_PATH") - .expect("`WASMER_TEST_WASMER_PATH` env var set with the path of a wasmer executable"), - ) + PathBuf::from(env::var("WASMER_TEST_WASMER_PATH").unwrap_or_else(|_| WASMER_PATH.to_string())) } /// Get the path to the `libwasmer.a` static library. fn get_libwasmer_path() -> PathBuf { PathBuf::from( - env::var("WASMER_TEST_LIBWASMER_PATH") - .expect("`WASMER_TEST_LIBWASMER_PATH` env var set with the path of libwasmer.a"), + env::var("WASMER_TEST_LIBWASMER_PATH").unwrap_or_else(|_| LIBWASMER_PATH.to_string()), ) } @@ -39,7 +45,8 @@ pub enum Engine { } impl Engine { - pub const fn to_flag(self) -> &'static str { + // TODO: make this `const fn` when Wasmer moves to Rust 1.46.0+ + pub fn to_flag(self) -> &'static str { match self { Engine::Jit => "--jit", Engine::Native => "--native", @@ -56,7 +63,8 @@ pub enum Compiler { } impl Compiler { - pub const fn to_flag(self) -> &'static str { + // TODO: make this `const fn` when Wasmer moves to Rust 1.46.0+ + pub fn to_flag(self) -> &'static str { match self { Compiler::Cranelift => "--cranelift", Compiler::LLVM => "--llvm", @@ -188,7 +196,7 @@ impl LinkCode { } } -fn run_code(executable_path: &Path) -> anyhow::Result<()> { +fn run_code(executable_path: &Path) -> anyhow::Result { let output = Command::new(executable_path).output()?; if !output.status.success() { @@ -198,14 +206,17 @@ fn run_code(executable_path: &Path) -> anyhow::Result<()> { .expect("stderr is not utf8! need to handle arbitrary bytes") ); } - Ok(()) + let output = + std::str::from_utf8(&output.stdout).expect("output from running executable is not utf-8"); + + Ok(output.to_owned()) } #[test] fn object_file_engine_works() -> anyhow::Result<()> { let operating_dir = tempfile::tempdir()?; - std::env::set_current_dir(&operating_dir); + std::env::set_current_dir(&operating_dir)?; let wasm_path = PathBuf::from(OBJECT_FILE_ENGINE_TEST_WASM_PATH); let wasm_object_path = PathBuf::from("wasm.o"); @@ -245,7 +256,14 @@ fn object_file_engine_works() -> anyhow::Result<()> { .run() .context("Failed to link objects together")?; - run_code(&executable_path).context("Failed to run generated executable")?; + let result = run_code(&executable_path).context("Failed to run generated executable")?; + assert_eq!( + &result, + r#"Initializing... +Buffer size: 1801380 +"Hello, World" +"# + ); Ok(()) } From 40865799e6573aff31a8f944b26d9fc2318b9752 Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Mon, 28 Sep 2020 14:02:02 +0200 Subject: [PATCH 058/281] feat(c-api) Don't create a module for `byte` and `frame`. --- lib/c-api/src/wasm_c_api/types/byte.rs | 4 ---- lib/c-api/src/wasm_c_api/types/frame.rs | 5 ----- lib/c-api/src/wasm_c_api/types/mod.rs | 15 +++++++++++---- 3 files changed, 11 insertions(+), 13 deletions(-) delete mode 100644 lib/c-api/src/wasm_c_api/types/byte.rs delete mode 100644 lib/c-api/src/wasm_c_api/types/frame.rs diff --git a/lib/c-api/src/wasm_c_api/types/byte.rs b/lib/c-api/src/wasm_c_api/types/byte.rs deleted file mode 100644 index 20ee607e6..000000000 --- a/lib/c-api/src/wasm_c_api/types/byte.rs +++ /dev/null @@ -1,4 +0,0 @@ -#[allow(non_camel_case_types)] -pub type wasm_byte_t = u8; - -wasm_declare_vec!(byte); diff --git a/lib/c-api/src/wasm_c_api/types/frame.rs b/lib/c-api/src/wasm_c_api/types/frame.rs deleted file mode 100644 index ca2539667..000000000 --- a/lib/c-api/src/wasm_c_api/types/frame.rs +++ /dev/null @@ -1,5 +0,0 @@ -#[derive(Debug)] -#[repr(C)] -pub struct wasm_frame_t {} - -wasm_declare_vec!(frame); diff --git a/lib/c-api/src/wasm_c_api/types/mod.rs b/lib/c-api/src/wasm_c_api/types/mod.rs index d25d872c3..be015a110 100644 --- a/lib/c-api/src/wasm_c_api/types/mod.rs +++ b/lib/c-api/src/wasm_c_api/types/mod.rs @@ -1,7 +1,5 @@ -mod byte; mod export; mod extern_; -mod frame; mod function; mod global; mod import; @@ -12,10 +10,8 @@ mod reference; mod table; mod value; -pub use byte::*; pub use export::*; pub use extern_::*; -pub use frame::*; pub use function::*; pub use global::*; pub use import::*; @@ -25,3 +21,14 @@ pub use name::*; pub use reference::*; pub use table::*; pub use value::*; + +#[allow(non_camel_case_types)] +pub type wasm_byte_t = u8; + +wasm_declare_vec!(byte); + +#[derive(Debug)] +#[repr(C)] +pub struct wasm_frame_t {} + +wasm_declare_vec!(frame); From 8f627d98347ffeb0631f8ebed40110a12ef4a24f Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Mon, 28 Sep 2020 14:49:44 +0200 Subject: [PATCH 059/281] feat(c-api) Instruct cbindgen to ignore all functions and types defined in `wasm.h`. --- lib/c-api/src/wasm_c_api/engine.rs | 14 +++++++--- .../src/wasm_c_api/externals/function.rs | 14 +++++++--- lib/c-api/src/wasm_c_api/externals/global.rs | 10 +++++-- lib/c-api/src/wasm_c_api/externals/memory.rs | 13 +++++++-- lib/c-api/src/wasm_c_api/externals/mod.rs | 13 ++++++--- lib/c-api/src/wasm_c_api/externals/table.rs | 10 +++++-- lib/c-api/src/wasm_c_api/instance.rs | 7 +++-- lib/c-api/src/wasm_c_api/macros.rs | 11 ++++++++ lib/c-api/src/wasm_c_api/module.rs | 10 +++++-- lib/c-api/src/wasm_c_api/store.rs | 5 +++- lib/c-api/src/wasm_c_api/trap.rs | 5 +++- lib/c-api/src/wasm_c_api/types/export.rs | 5 +++- lib/c-api/src/wasm_c_api/types/extern_.rs | 27 ++++++++++++++++--- lib/c-api/src/wasm_c_api/types/function.rs | 10 ++++--- lib/c-api/src/wasm_c_api/types/global.rs | 9 ++++--- lib/c-api/src/wasm_c_api/types/import.rs | 7 ++++- lib/c-api/src/wasm_c_api/types/memory.rs | 13 ++++----- lib/c-api/src/wasm_c_api/types/mod.rs | 13 ++++++--- lib/c-api/src/wasm_c_api/types/mutability.rs | 4 ++- lib/c-api/src/wasm_c_api/types/name.rs | 4 --- lib/c-api/src/wasm_c_api/types/reference.rs | 3 --- lib/c-api/src/wasm_c_api/types/table.rs | 8 +++++- lib/c-api/src/wasm_c_api/types/value.rs | 9 +++++-- lib/c-api/src/wasm_c_api/value.rs | 9 +++++-- 24 files changed, 178 insertions(+), 55 deletions(-) delete mode 100644 lib/c-api/src/wasm_c_api/types/name.rs delete mode 100644 lib/c-api/src/wasm_c_api/types/reference.rs diff --git a/lib/c-api/src/wasm_c_api/engine.rs b/lib/c-api/src/wasm_c_api/engine.rs index 1d16d50f2..eb11c3e6e 100644 --- a/lib/c-api/src/wasm_c_api/engine.rs +++ b/lib/c-api/src/wasm_c_api/engine.rs @@ -3,18 +3,21 @@ use std::sync::Arc; use wasmer::Engine; /// this can be a wasmer-specific type with wasmer-specific functions for manipulating it -#[repr(C)] +/// +/// cbindgen:ignore +#[allow(non_camel_case_types)] pub struct wasm_config_t {} +/// cbindgen:ignore #[no_mangle] pub extern "C" fn wasm_config_new() -> *mut wasm_config_t { todo!("wasm_config_new") //ptr::null_mut() } -#[repr(C)] +/// cbindgen:ignore +#[allow(non_camel_case_types)] pub struct wasm_engine_t { - /// cbindgen:ignore pub(crate) inner: Arc, } @@ -36,6 +39,7 @@ cfg_if! { } } + /// cbindgen:ignore #[no_mangle] pub extern "C" fn wasm_engine_new() -> Box { let compiler_config: Box = get_default_compiler_config(); @@ -45,6 +49,7 @@ cfg_if! { } else if #[cfg(feature = "jit")] { // Headless JIT + /// cbindgen:ignore #[no_mangle] pub extern "C" fn wasm_engine_new() -> Box { let engine: Arc = Arc::new(JIT::headless().engine()); @@ -52,6 +57,7 @@ cfg_if! { } } else { + /// cbindgen:ignore #[no_mangle] pub extern "C" fn wasm_engine_new() -> Box { unimplemented!("The JITEngine is not attached"); @@ -59,9 +65,11 @@ cfg_if! { } } +/// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn wasm_engine_delete(_wasm_engine_address: Option>) {} +/// cbindgen:ignore #[no_mangle] pub extern "C" fn wasm_engine_new_with_config( _config_ptr: *mut wasm_config_t, diff --git a/lib/c-api/src/wasm_c_api/externals/function.rs b/lib/c-api/src/wasm_c_api/externals/function.rs index 2512c475c..22366809f 100644 --- a/lib/c-api/src/wasm_c_api/externals/function.rs +++ b/lib/c-api/src/wasm_c_api/externals/function.rs @@ -8,19 +8,20 @@ use std::ptr::NonNull; use std::sync::Arc; use wasmer::{Function, Instance, RuntimeError, Store, Val}; -#[repr(C)] +/// cbindgen:ignore +#[allow(non_camel_case_types)] pub struct wasm_func_t { - /// cbindgen:ignore pub(crate) inner: Function, - /// cbindgen:ignore // this is how we ensure the instance stays alive pub(crate) instance: Option>, } +/// cbindgen:ignore #[allow(non_camel_case_types)] pub type wasm_func_callback_t = unsafe extern "C" fn(args: *const wasm_val_t, results: *mut wasm_val_t) -> *mut wasm_trap_t; +/// cbindgen:ignore #[allow(non_camel_case_types)] pub type wasm_func_callback_with_env_t = unsafe extern "C" fn( *mut c_void, @@ -28,9 +29,11 @@ pub type wasm_func_callback_with_env_t = unsafe extern "C" fn( results: *mut wasm_val_t, ) -> *mut wasm_trap_t; +/// cbindgen:ignore #[allow(non_camel_case_types)] pub type wasm_env_finalizer_t = unsafe extern "C" fn(c_void); +/// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn wasm_func_new( store: Option>, @@ -74,6 +77,7 @@ pub unsafe extern "C" fn wasm_func_new( })) } +/// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn wasm_func_new_with_env( store: Option>, @@ -120,9 +124,11 @@ pub unsafe extern "C" fn wasm_func_new_with_env( })) } +/// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn wasm_func_delete(_func: Option>) {} +/// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn wasm_func_call( func: &wasm_func_t, @@ -147,11 +153,13 @@ pub unsafe extern "C" fn wasm_func_call( } } +/// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn wasm_func_param_arity(func: &wasm_func_t) -> usize { func.inner.ty().params().len() } +/// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn wasm_func_result_arity(func: &wasm_func_t) -> usize { func.inner.ty().results().len() diff --git a/lib/c-api/src/wasm_c_api/externals/global.rs b/lib/c-api/src/wasm_c_api/externals/global.rs index 575670c19..ba148aa21 100644 --- a/lib/c-api/src/wasm_c_api/externals/global.rs +++ b/lib/c-api/src/wasm_c_api/externals/global.rs @@ -5,13 +5,14 @@ use std::convert::TryInto; use std::ptr::NonNull; use wasmer::{Global, Store, Val}; -#[repr(C)] +/// cbindgen:ignore +#[allow(non_camel_case_types)] pub struct wasm_global_t { - /// cbindgen:ignore // maybe needs to hold onto instance pub(crate) inner: Global, } +/// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn wasm_global_new( store_ptr: Option>, @@ -31,10 +32,12 @@ pub unsafe extern "C" fn wasm_global_new( Some(Box::new(wasm_global_t { inner: global })) } +/// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn wasm_global_delete(_global: Option>) {} // TODO: figure out if these should be deep or shallow copies +/// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn wasm_global_copy(wasm_global: &wasm_global_t) -> Box { // do shallow copy @@ -43,18 +46,21 @@ pub unsafe extern "C" fn wasm_global_copy(wasm_global: &wasm_global_t) -> Box>, @@ -24,10 +25,12 @@ pub unsafe extern "C" fn wasm_memory_new( Some(Box::new(wasm_memory_t { inner: memory })) } +/// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn wasm_memory_delete(_memory: Option>) {} // TODO: figure out if these should be deep or shallow copies +/// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn wasm_memory_copy(wasm_memory: &wasm_memory_t) -> Box { // do shallow copy @@ -36,12 +39,14 @@ pub unsafe extern "C" fn wasm_memory_copy(wasm_memory: &wasm_memory_t) -> Box *mut wasm_memorytype_t { todo!("wasm_memory_type") } // get a raw pointer into bytes +/// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn wasm_memory_data(memory: &mut wasm_memory_t) -> *mut u8 { mem::transmute::<&[std::cell::Cell], &[u8]>(&memory.inner.view()[..]) as *const [u8] @@ -49,23 +54,27 @@ pub unsafe extern "C" fn wasm_memory_data(memory: &mut wasm_memory_t) -> *mut u8 } // size in bytes +/// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn wasm_memory_data_size(memory: &wasm_memory_t) -> usize { memory.inner.size().bytes().0 } // size in pages +/// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn wasm_memory_size(memory: &wasm_memory_t) -> u32 { memory.inner.size().0 as _ } // delta is in pages +/// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn wasm_memory_grow(memory: &mut wasm_memory_t, delta: u32) -> bool { memory.inner.grow(Pages(delta)).is_ok() } +/// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn wasm_memory_same( wasm_memory1: &wasm_memory_t, diff --git a/lib/c-api/src/wasm_c_api/externals/mod.rs b/lib/c-api/src/wasm_c_api/externals/mod.rs index 604651e1a..6f04a94d1 100644 --- a/lib/c-api/src/wasm_c_api/externals/mod.rs +++ b/lib/c-api/src/wasm_c_api/externals/mod.rs @@ -11,17 +11,17 @@ use std::sync::Arc; pub use table::*; use wasmer::{Extern, Instance}; -#[repr(C)] +/// cbindgen:ignore +#[allow(non_camel_case_types)] pub struct wasm_extern_t { - /// cbindgen:ignore // this is how we ensure the instance stays alive pub(crate) instance: Option>, - /// cbindgen:ignore pub(crate) inner: Extern, } wasm_declare_boxed_vec!(extern); +/// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn wasm_func_as_extern( func_ptr: Option>, @@ -35,6 +35,7 @@ pub unsafe extern "C" fn wasm_func_as_extern( })) } +/// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn wasm_global_as_extern( global_ptr: Option>, @@ -49,6 +50,7 @@ pub unsafe extern "C" fn wasm_global_as_extern( })) } +/// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn wasm_memory_as_extern( memory_ptr: Option>, @@ -63,6 +65,7 @@ pub unsafe extern "C" fn wasm_memory_as_extern( })) } +/// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn wasm_table_as_extern( table_ptr: Option>, @@ -77,6 +80,7 @@ pub unsafe extern "C" fn wasm_table_as_extern( })) } +/// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn wasm_extern_as_func( extern_ptr: Option>, @@ -93,6 +97,7 @@ pub unsafe extern "C" fn wasm_extern_as_func( } } +/// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn wasm_extern_as_global( extern_ptr: Option>, @@ -106,6 +111,7 @@ pub unsafe extern "C" fn wasm_extern_as_global( } } +/// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn wasm_extern_as_memory( extern_ptr: Option>, @@ -119,6 +125,7 @@ pub unsafe extern "C" fn wasm_extern_as_memory( } } +/// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn wasm_extern_as_table( extern_ptr: Option>, diff --git a/lib/c-api/src/wasm_c_api/externals/table.rs b/lib/c-api/src/wasm_c_api/externals/table.rs index 3ebef63f4..44600035d 100644 --- a/lib/c-api/src/wasm_c_api/externals/table.rs +++ b/lib/c-api/src/wasm_c_api/externals/table.rs @@ -3,13 +3,14 @@ use super::super::types::{wasm_ref_t, wasm_table_size_t, wasm_tabletype_t}; use std::ptr::NonNull; use wasmer::{Store, Table}; -#[repr(C)] +/// cbindgen:ignore +#[allow(non_camel_case_types)] pub struct wasm_table_t { - /// cbindgen:ignore // maybe needs to hold onto instance pub(crate) inner: Table, } +/// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn wasm_table_new( store_ptr: Option>, @@ -26,9 +27,11 @@ pub unsafe extern "C" fn wasm_table_new( Some(Box::new(wasm_table_t { inner: table })) } +/// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn wasm_table_delete(_table: Option>) {} +/// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn wasm_table_copy(wasm_table: &wasm_table_t) -> Box { // do shallow copy @@ -37,6 +40,7 @@ pub unsafe extern "C" fn wasm_table_copy(wasm_table: &wasm_table_t) -> Box usize { wasm_table.inner.size() as _ } +/// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn wasm_table_grow( _wasm_table: &mut wasm_table_t, diff --git a/lib/c-api/src/wasm_c_api/instance.rs b/lib/c-api/src/wasm_c_api/instance.rs index 7bcd1de03..139de7fd2 100644 --- a/lib/c-api/src/wasm_c_api/instance.rs +++ b/lib/c-api/src/wasm_c_api/instance.rs @@ -8,9 +8,9 @@ use std::ptr::NonNull; use std::sync::Arc; use wasmer::{Extern, Instance}; -#[repr(C)] +/// cbindgen:ignore +#[allow(non_camel_case_types)] pub struct wasm_instance_t { - /// cbindgen:ignore pub(crate) inner: Arc, } @@ -51,6 +51,7 @@ unsafe fn argument_import_iter( .unwrap_or_else(|| Box::new(std::iter::empty()) as _) } +/// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn wasm_instance_new( store: Option>, @@ -73,9 +74,11 @@ pub unsafe extern "C" fn wasm_instance_new( Some(Box::new(wasm_instance_t { inner: instance })) } +/// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn wasm_instance_delete(_instance: Option>) {} +/// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn wasm_instance_exports( instance: &wasm_instance_t, diff --git a/lib/c-api/src/wasm_c_api/macros.rs b/lib/c-api/src/wasm_c_api/macros.rs index f37d9b71a..9a022ce38 100644 --- a/lib/c-api/src/wasm_c_api/macros.rs +++ b/lib/c-api/src/wasm_c_api/macros.rs @@ -3,12 +3,14 @@ macro_rules! wasm_declare_vec_inner { ($name:ident) => { paste::item! { + /// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn [](out: *mut []) { // TODO: actually implement this [](out, 0); } + /// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn [](ptr: *mut []) { let vec = &mut *ptr; @@ -27,6 +29,7 @@ macro_rules! wasm_declare_vec_inner { macro_rules! wasm_declare_vec { ($name:ident) => { paste::item! { + /// cbindgen:ignore #[repr(C)] pub struct [] { pub size: usize, @@ -44,6 +47,7 @@ macro_rules! wasm_declare_vec { } // TODO: investigate possible memory leak on `init` (owned pointer) + /// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn [](out: *mut [], length: usize, init: *mut []) { let mut bytes: Vec<[]> = Vec::with_capacity(length); @@ -57,6 +61,7 @@ macro_rules! wasm_declare_vec { ::std::mem::forget(bytes); } + /// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn [](out: *mut [], length: usize) { let mut bytes: Vec<[]> = Vec::with_capacity(length); @@ -76,6 +81,7 @@ macro_rules! wasm_declare_vec { macro_rules! wasm_declare_boxed_vec { ($name:ident) => { paste::item! { + /// cbindgen:ignore #[repr(C)] pub struct [] { pub size: usize, @@ -94,6 +100,7 @@ macro_rules! wasm_declare_boxed_vec { } // TODO: investigate possible memory leak on `init` (owned pointer) + /// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn [](out: *mut [], length: usize, init: *const *mut []) { let mut bytes: Vec<*mut []> = Vec::with_capacity(length); @@ -107,6 +114,7 @@ macro_rules! wasm_declare_boxed_vec { ::std::mem::forget(bytes); } + /// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn [](out: *mut [], length: usize) { let mut bytes: Vec<*mut []> = Vec::with_capacity(length); @@ -128,6 +136,7 @@ macro_rules! wasm_declare_ref_base { wasm_declare_own!($name); paste::item! { + /// cbindgen:ignore #[no_mangle] pub extern "C" fn [](_arg: *const []) -> *mut [] { todo!("in generated declare ref base"); @@ -145,9 +154,11 @@ macro_rules! wasm_declare_ref_base { macro_rules! wasm_declare_own { ($name:ident) => { paste::item! { + /// cbindgen:ignore #[repr(C)] pub struct [] {} + /// cbindgen:ignore #[no_mangle] pub extern "C" fn [](_arg: *mut []) { todo!("in generated delete") diff --git a/lib/c-api/src/wasm_c_api/module.rs b/lib/c-api/src/wasm_c_api/module.rs index 3f7efb116..bca743268 100644 --- a/lib/c-api/src/wasm_c_api/module.rs +++ b/lib/c-api/src/wasm_c_api/module.rs @@ -9,12 +9,13 @@ use std::slice; use std::sync::Arc; use wasmer::{Module, Store}; -#[repr(C)] +/// cbindgen:ignore +#[allow(non_camel_case_types)] pub struct wasm_module_t { - /// cbindgen:ignore pub(crate) inner: Arc, } +/// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn wasm_module_new( store_ptr: Option>, @@ -31,9 +32,11 @@ pub unsafe extern "C" fn wasm_module_new( })) } +/// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn wasm_module_delete(_module: Option>) {} +/// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn wasm_module_exports( module: &wasm_module_t, @@ -53,6 +56,7 @@ pub unsafe extern "C" fn wasm_module_exports( mem::forget(exports); } +/// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn wasm_module_imports( module: &wasm_module_t, @@ -72,6 +76,7 @@ pub unsafe extern "C" fn wasm_module_imports( mem::forget(imports); } +/// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn wasm_module_deserialize( store_ptr: Option>, @@ -97,6 +102,7 @@ pub unsafe extern "C" fn wasm_module_deserialize( )))) } +/// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn wasm_module_serialize( module: &wasm_module_t, diff --git a/lib/c-api/src/wasm_c_api/store.rs b/lib/c-api/src/wasm_c_api/store.rs index 6eaa78bd8..32b241d84 100644 --- a/lib/c-api/src/wasm_c_api/store.rs +++ b/lib/c-api/src/wasm_c_api/store.rs @@ -3,9 +3,11 @@ use std::ptr::NonNull; use wasmer::Store; /// Opaque wrapper around `Store` -#[repr(C)] +/// cbindgen:ignore +#[allow(non_camel_case_types)] pub struct wasm_store_t {} +/// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn wasm_store_new( wasm_engine_ptr: Option>, @@ -18,6 +20,7 @@ pub unsafe extern "C" fn wasm_store_new( )) } +/// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn wasm_store_delete(wasm_store: Option>) { if let Some(s_inner) = wasm_store { diff --git a/lib/c-api/src/wasm_c_api/trap.rs b/lib/c-api/src/wasm_c_api/trap.rs index d2503a636..104cabe97 100644 --- a/lib/c-api/src/wasm_c_api/trap.rs +++ b/lib/c-api/src/wasm_c_api/trap.rs @@ -4,9 +4,11 @@ use std::ptr::NonNull; use wasmer::RuntimeError; // opaque type which is a `RuntimeError` -#[repr(C)] +/// cbindgen:ignore +#[allow(non_camel_case_types)] pub struct wasm_trap_t {} +/// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn wasm_trap_delete(trap: Option>) { if let Some(t_inner) = trap { @@ -14,6 +16,7 @@ pub unsafe extern "C" fn wasm_trap_delete(trap: Option>) { } } +/// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn wasm_trap_message( trap: *const wasm_trap_t, diff --git a/lib/c-api/src/wasm_c_api/types/export.rs b/lib/c-api/src/wasm_c_api/types/export.rs index 237256039..81b8039f7 100644 --- a/lib/c-api/src/wasm_c_api/types/export.rs +++ b/lib/c-api/src/wasm_c_api/types/export.rs @@ -2,7 +2,7 @@ use super::{wasm_externtype_t, wasm_name_t}; use std::ptr::NonNull; use wasmer::ExportType; -#[repr(C)] +/// cbindgen:ignore #[allow(non_camel_case_types)] pub struct wasm_exporttype_t { name: NonNull, @@ -11,6 +11,7 @@ pub struct wasm_exporttype_t { wasm_declare_boxed_vec!(exporttype); +/// cbindgen:ignore #[no_mangle] pub extern "C" fn wasm_exporttype_new( name: NonNull, @@ -19,11 +20,13 @@ pub extern "C" fn wasm_exporttype_new( Box::new(wasm_exporttype_t { name, extern_type }) } +/// cbindgen:ignore #[no_mangle] pub extern "C" fn wasm_exporttype_name(et: &'static wasm_exporttype_t) -> &'static wasm_name_t { unsafe { et.name.as_ref() } } +/// cbindgen:ignore #[no_mangle] pub extern "C" fn wasm_exporttype_type( et: &'static wasm_exporttype_t, diff --git a/lib/c-api/src/wasm_c_api/types/extern_.rs b/lib/c-api/src/wasm_c_api/types/extern_.rs index b02e337fb..3d537e59e 100644 --- a/lib/c-api/src/wasm_c_api/types/extern_.rs +++ b/lib/c-api/src/wasm_c_api/types/extern_.rs @@ -5,14 +5,14 @@ use std::mem; use thiserror::Error; use wasmer::ExternType; -#[derive(Clone, Debug)] +/// cbindgen:ignore #[allow(non_camel_case_types)] -#[repr(C)] +#[derive(Clone, Debug)] pub struct wasm_externtype_t { - /// cbindgen:ignore pub(crate) inner: ExternType, } +/// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn wasm_extern_type(e: &wasm_extern_t) -> Box { Box::new(wasm_externtype_t { @@ -20,6 +20,7 @@ pub unsafe extern "C" fn wasm_extern_type(e: &wasm_extern_t) -> Box>) {} @@ -35,9 +36,11 @@ impl From<&ExternType> for wasm_externtype_t { } } +/// cbindgen:ignore #[allow(non_camel_case_types)] type wasm_externkind_t = u8; +/// cbindgen:ignore #[allow(non_camel_case_types)] #[repr(u8)] pub enum wasm_externkind_enum { @@ -47,6 +50,7 @@ pub enum wasm_externkind_enum { WASM_EXTERN_MEMORY = 3, } +/// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn wasm_extern_kind(e: &wasm_extern_t) -> wasm_externkind_t { wasm_externkind_enum::from(e.inner.ty()) as wasm_externkind_t @@ -68,6 +72,7 @@ impl From<&ExternType> for wasm_externkind_enum { } } +/// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn wasm_externtype_kind(et: &wasm_externtype_t) -> wasm_externkind_t { wasm_externkind_enum::from(&et.inner) as wasm_externkind_t @@ -131,6 +136,7 @@ impl TryFrom<&'static wasm_externtype_t> for &'static wasm_tabletype_t { } } +/// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn wasm_externtype_as_functype_const( et: &'static wasm_externtype_t, @@ -138,6 +144,7 @@ pub unsafe extern "C" fn wasm_externtype_as_functype_const( Some(c_try!(et.try_into())) } +/// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn wasm_externtype_as_functype( et: &'static wasm_externtype_t, @@ -145,6 +152,7 @@ pub unsafe extern "C" fn wasm_externtype_as_functype( Some(c_try!(et.try_into())) } +/// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn wasm_functype_as_externtype_const( ft: &'static wasm_functype_t, @@ -152,6 +160,7 @@ pub unsafe extern "C" fn wasm_functype_as_externtype_const( &ft.extern_ } +/// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn wasm_functype_as_externtype( ft: &'static wasm_functype_t, @@ -159,6 +168,7 @@ pub unsafe extern "C" fn wasm_functype_as_externtype( &ft.extern_ } +/// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn wasm_externtype_as_memorytype_const( et: &'static wasm_externtype_t, @@ -166,6 +176,7 @@ pub unsafe extern "C" fn wasm_externtype_as_memorytype_const( Some(c_try!(et.try_into())) } +/// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn wasm_externtype_as_memorytype( et: &'static wasm_externtype_t, @@ -173,6 +184,7 @@ pub unsafe extern "C" fn wasm_externtype_as_memorytype( Some(c_try!(et.try_into())) } +/// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn wasm_memorytype_as_externtype_const( mt: &'static wasm_memorytype_t, @@ -180,6 +192,7 @@ pub unsafe extern "C" fn wasm_memorytype_as_externtype_const( &mt.extern_ } +/// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn wasm_memorytype_as_externtype( mt: &'static wasm_memorytype_t, @@ -187,6 +200,7 @@ pub unsafe extern "C" fn wasm_memorytype_as_externtype( &mt.extern_ } +/// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn wasm_externtype_as_globaltype_const( et: &'static wasm_externtype_t, @@ -194,6 +208,7 @@ pub unsafe extern "C" fn wasm_externtype_as_globaltype_const( Some(c_try!(et.try_into())) } +/// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn wasm_externtype_as_globaltype( et: &'static wasm_externtype_t, @@ -201,6 +216,7 @@ pub unsafe extern "C" fn wasm_externtype_as_globaltype( Some(c_try!(et.try_into())) } +/// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn wasm_globaltype_as_externtype_const( gt: &'static wasm_globaltype_t, @@ -208,6 +224,7 @@ pub unsafe extern "C" fn wasm_globaltype_as_externtype_const( >.extern_ } +/// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn wasm_globaltype_as_externtype( gt: &'static wasm_globaltype_t, @@ -215,6 +232,7 @@ pub unsafe extern "C" fn wasm_globaltype_as_externtype( >.extern_ } +/// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn wasm_externtype_as_tabletype_const( et: &'static wasm_externtype_t, @@ -222,6 +240,7 @@ pub unsafe extern "C" fn wasm_externtype_as_tabletype_const( Some(c_try!(et.try_into())) } +/// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn wasm_externtype_as_tabletype( et: &'static wasm_externtype_t, @@ -229,6 +248,7 @@ pub unsafe extern "C" fn wasm_externtype_as_tabletype( Some(c_try!(et.try_into())) } +/// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn wasm_tabletype_as_externtype_const( tt: &'static wasm_tabletype_t, @@ -236,6 +256,7 @@ pub unsafe extern "C" fn wasm_tabletype_as_externtype_const( &tt.extern_ } +/// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn wasm_tabletype_as_externtype( tt: &'static wasm_tabletype_t, diff --git a/lib/c-api/src/wasm_c_api/types/function.rs b/lib/c-api/src/wasm_c_api/types/function.rs index f00bdda67..35f4674e8 100644 --- a/lib/c-api/src/wasm_c_api/types/function.rs +++ b/lib/c-api/src/wasm_c_api/types/function.rs @@ -3,11 +3,10 @@ use std::mem; use std::ptr::NonNull; use wasmer::{ExternType, FunctionType, ValType}; -#[derive(Clone, Debug)] -#[repr(C)] +/// cbindgen:ignore #[allow(non_camel_case_types)] +#[derive(Clone, Debug)] pub struct wasm_functype_t { - /// cbindgen:ignore pub(crate) extern_: wasm_externtype_t, } @@ -23,6 +22,7 @@ impl wasm_functype_t { wasm_declare_vec!(functype); +/// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn wasm_functype_new( // own @@ -60,9 +60,11 @@ unsafe fn wasm_functype_new_inner( Some(Box::new(wasm_functype_t { extern_ })) } +/// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn wasm_functype_delete(_ft: Option>) {} +/// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn wasm_functype_copy( arg: Option>, @@ -73,6 +75,7 @@ pub unsafe extern "C" fn wasm_functype_copy( } // TODO: fix memory leak +/// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn wasm_functype_params(ft: &wasm_functype_t) -> *const wasm_valtype_vec_t { let mut valtypes = ft @@ -93,6 +96,7 @@ pub unsafe extern "C" fn wasm_functype_params(ft: &wasm_functype_t) -> *const wa } // TODO: fix memory leak +/// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn wasm_functype_results(ft: &wasm_functype_t) -> *const wasm_valtype_vec_t { let mut valtypes = ft diff --git a/lib/c-api/src/wasm_c_api/types/global.rs b/lib/c-api/src/wasm_c_api/types/global.rs index 2f590cea8..9547430cc 100644 --- a/lib/c-api/src/wasm_c_api/types/global.rs +++ b/lib/c-api/src/wasm_c_api/types/global.rs @@ -4,11 +4,10 @@ use super::{ use std::convert::TryInto; use wasmer::{ExternType, GlobalType}; -#[derive(Clone, Debug)] -#[repr(C)] +/// cbindgen:ignore #[allow(non_camel_case_types)] +#[derive(Clone, Debug)] pub struct wasm_globaltype_t { - /// cbindgen:ignore pub(crate) extern_: wasm_externtype_t, } @@ -26,6 +25,7 @@ impl wasm_globaltype_t { wasm_declare_vec!(globaltype); +/// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn wasm_globaltype_new( // own @@ -35,6 +35,7 @@ pub unsafe extern "C" fn wasm_globaltype_new( wasm_globaltype_new_inner(valtype?, mutability) } +/// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn wasm_globaltype_delete(_globaltype: Option>) {} @@ -54,6 +55,7 @@ unsafe fn wasm_globaltype_new_inner( Some(gd) } +/// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn wasm_globaltype_mutability( globaltype: &wasm_globaltype_t, @@ -64,6 +66,7 @@ pub unsafe extern "C" fn wasm_globaltype_mutability( // TODO: fix memory leak // this function leaks memory because the returned limits pointer is not owned +/// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn wasm_globaltype_content( globaltype: &wasm_globaltype_t, diff --git a/lib/c-api/src/wasm_c_api/types/import.rs b/lib/c-api/src/wasm_c_api/types/import.rs index a45b1644b..8e45570e7 100644 --- a/lib/c-api/src/wasm_c_api/types/import.rs +++ b/lib/c-api/src/wasm_c_api/types/import.rs @@ -3,7 +3,7 @@ use std::ptr::NonNull; use wasmer::ImportType; // TODO: improve ownership in `importtype_t` (can we safely use `Box` here?) -#[repr(C)] +/// cbindgen:ignore #[allow(non_camel_case_types)] pub struct wasm_importtype_t { pub(crate) module: NonNull, @@ -13,6 +13,7 @@ pub struct wasm_importtype_t { wasm_declare_boxed_vec!(importtype); +/// cbindgen:ignore #[no_mangle] pub extern "C" fn wasm_importtype_new( module: NonNull, @@ -26,16 +27,19 @@ pub extern "C" fn wasm_importtype_new( }) } +/// cbindgen:ignore #[no_mangle] pub extern "C" fn wasm_importtype_module(et: &'static wasm_importtype_t) -> &'static wasm_name_t { unsafe { et.module.as_ref() } } +/// cbindgen:ignore #[no_mangle] pub extern "C" fn wasm_importtype_name(et: &'static wasm_importtype_t) -> &'static wasm_name_t { unsafe { et.name.as_ref() } } +/// cbindgen:ignore #[no_mangle] pub extern "C" fn wasm_importtype_type( et: &'static wasm_importtype_t, @@ -43,6 +47,7 @@ pub extern "C" fn wasm_importtype_type( unsafe { et.extern_type.as_ref() } } +/// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn wasm_importtype_delete(_importtype: Option>) {} diff --git a/lib/c-api/src/wasm_c_api/types/memory.rs b/lib/c-api/src/wasm_c_api/types/memory.rs index 5a1fa3a2f..cc2cfa39b 100644 --- a/lib/c-api/src/wasm_c_api/types/memory.rs +++ b/lib/c-api/src/wasm_c_api/types/memory.rs @@ -2,9 +2,9 @@ use super::wasm_externtype_t; use wasmer::{ExternType, MemoryType, Pages}; // opaque type wrapping `MemoryType` -#[derive(Clone, Debug)] -#[repr(C)] +/// cbindgen:ignore #[allow(non_camel_case_types)] +#[derive(Clone, Debug)] pub struct wasm_memorytype_t { /// cbindgen:ignore pub(crate) extern_: wasm_externtype_t, @@ -24,14 +24,15 @@ impl wasm_memorytype_t { wasm_declare_vec!(memorytype); +/// cbindgen:ignore +#[allow(non_camel_case_types)] #[derive(Copy, Clone, Debug)] -#[repr(C)] pub struct wasm_limits_t { pub(crate) min: u32, pub(crate) max: u32, } -#[no_mangle] +/// cbindgen:ignoren#[no_mangle] pub unsafe extern "C" fn wasm_memorytype_new(limits: &wasm_limits_t) -> Box { let min_pages = Pages(limits.min as _); // TODO: investigate if `0` is in fact a sentinel value here @@ -47,12 +48,12 @@ pub unsafe extern "C" fn wasm_memorytype_new(limits: &wasm_limits_t) -> Box>) {} // TODO: fix memory leak // this function leaks memory because the returned limits pointer is not owned -#[no_mangle] +/// cbindgen:ignoren#[no_mangle] pub unsafe extern "C" fn wasm_memorytype_limits(mt: &wasm_memorytype_t) -> *const wasm_limits_t { let md = mt.as_memorytype(); Box::into_raw(Box::new(wasm_limits_t { diff --git a/lib/c-api/src/wasm_c_api/types/mod.rs b/lib/c-api/src/wasm_c_api/types/mod.rs index be015a110..65bd9e6d3 100644 --- a/lib/c-api/src/wasm_c_api/types/mod.rs +++ b/lib/c-api/src/wasm_c_api/types/mod.rs @@ -5,8 +5,6 @@ mod global; mod import; mod memory; mod mutability; -mod name; -mod reference; mod table; mod value; @@ -17,8 +15,6 @@ pub use global::*; pub use import::*; pub use memory::*; pub use mutability::*; -pub use name::*; -pub use reference::*; pub use table::*; pub use value::*; @@ -32,3 +28,12 @@ wasm_declare_vec!(byte); pub struct wasm_frame_t {} wasm_declare_vec!(frame); + +/// cbindgen:ignore +#[allow(non_camel_case_types)] +pub type wasm_name_t = wasm_byte_vec_t; + +// opaque type over `ExternRef`? +/// cbindgen:ignore +#[allow(non_camel_case_types)] +pub struct wasm_ref_t; diff --git a/lib/c-api/src/wasm_c_api/types/mutability.rs b/lib/c-api/src/wasm_c_api/types/mutability.rs index 23f52959c..6611843d7 100644 --- a/lib/c-api/src/wasm_c_api/types/mutability.rs +++ b/lib/c-api/src/wasm_c_api/types/mutability.rs @@ -1,11 +1,13 @@ use std::convert::TryFrom; use wasmer::Mutability; +/// cbindgen:ignore #[allow(non_camel_case_types)] pub type wasm_mutability_t = u8; -#[derive(Debug, Clone, Copy, PartialEq, Eq)] +/// cbindgen:ignore #[allow(non_camel_case_types)] +#[derive(Debug, Clone, Copy, PartialEq, Eq)] #[repr(u8)] pub enum wasm_mutability_enum { WASM_CONST = 0, diff --git a/lib/c-api/src/wasm_c_api/types/name.rs b/lib/c-api/src/wasm_c_api/types/name.rs deleted file mode 100644 index aedee66cb..000000000 --- a/lib/c-api/src/wasm_c_api/types/name.rs +++ /dev/null @@ -1,4 +0,0 @@ -use super::wasm_byte_vec_t; - -#[allow(non_camel_case_types)] -pub type wasm_name_t = wasm_byte_vec_t; diff --git a/lib/c-api/src/wasm_c_api/types/reference.rs b/lib/c-api/src/wasm_c_api/types/reference.rs deleted file mode 100644 index f3e6424ca..000000000 --- a/lib/c-api/src/wasm_c_api/types/reference.rs +++ /dev/null @@ -1,3 +0,0 @@ -// opaque type over `ExternRef`? -#[allow(non_camel_case_types)] -pub struct wasm_ref_t; diff --git a/lib/c-api/src/wasm_c_api/types/table.rs b/lib/c-api/src/wasm_c_api/types/table.rs index 3718958df..73455bede 100644 --- a/lib/c-api/src/wasm_c_api/types/table.rs +++ b/lib/c-api/src/wasm_c_api/types/table.rs @@ -1,12 +1,14 @@ use super::{wasm_externtype_t, wasm_limits_t, wasm_valtype_delete, wasm_valtype_t}; use wasmer::{ExternType, TableType}; +/// cbindgen:ignore #[allow(non_camel_case_types)] pub type wasm_table_size_t = u32; +/// cbindgen:ignore +#[allow(non_camel_case_types)] #[derive(Clone, Debug)] #[repr(C)] -#[allow(non_camel_case_types)] pub struct wasm_tabletype_t { /// cbindgen:ignore pub(crate) extern_: wasm_externtype_t, @@ -26,6 +28,7 @@ impl wasm_tabletype_t { } } +/// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn wasm_tabletype_new( // own @@ -54,6 +57,7 @@ pub unsafe extern "C" fn wasm_tabletype_new( // TODO: fix memory leak // this function leaks memory because the returned limits pointer is not owned +/// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn wasm_tabletype_limits( tabletype: &wasm_tabletype_t, @@ -67,6 +71,7 @@ pub unsafe extern "C" fn wasm_tabletype_limits( // TODO: fix memory leak // this function leaks memory because the returned limits pointer is not owned +/// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn wasm_tabletype_element( tabletype: &wasm_tabletype_t, @@ -76,5 +81,6 @@ pub unsafe extern "C" fn wasm_tabletype_element( Box::into_raw(Box::new(tt.ty.into())) } +/// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn wasm_tabletype_delete(_tabletype: Option>) {} diff --git a/lib/c-api/src/wasm_c_api/types/value.rs b/lib/c-api/src/wasm_c_api/types/value.rs index c7f0fa549..60dff16b0 100644 --- a/lib/c-api/src/wasm_c_api/types/value.rs +++ b/lib/c-api/src/wasm_c_api/types/value.rs @@ -2,8 +2,9 @@ use super::super::value::wasm_valkind_t; use std::convert::TryInto; use wasmer::ValType; -#[derive(Debug, Clone, Copy, PartialEq, Eq)] +/// cbindgen:ignore #[allow(non_camel_case_types)] +#[derive(Debug, Clone, Copy, PartialEq, Eq)] #[repr(u8)] pub enum wasm_valkind_enum { WASM_I32 = 0, @@ -42,8 +43,9 @@ impl From for ValType { } } +/// cbindgen:ignore +#[allow(non_camel_case_types)] #[derive(Debug, Clone, Copy)] -#[repr(C)] pub struct wasm_valtype_t { valkind: wasm_valkind_enum, } @@ -72,6 +74,7 @@ impl From for wasm_valtype_t { } } +/// cbindgen:ignore #[no_mangle] pub extern "C" fn wasm_valtype_new(kind: wasm_valkind_t) -> Option> { let kind_enum = kind.try_into().ok()?; @@ -79,9 +82,11 @@ pub extern "C" fn wasm_valtype_new(kind: wasm_valkind_t) -> Option>) {} +/// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn wasm_valtype_kind(valtype: *const wasm_valtype_t) -> wasm_valkind_t { if valtype.is_null() { diff --git a/lib/c-api/src/wasm_c_api/value.rs b/lib/c-api/src/wasm_c_api/value.rs index 03cc48e52..2102bbb1e 100644 --- a/lib/c-api/src/wasm_c_api/value.rs +++ b/lib/c-api/src/wasm_c_api/value.rs @@ -3,10 +3,12 @@ use std::convert::{TryFrom, TryInto}; use std::ptr::NonNull; use wasmer::Val; +/// cbindgen:ignore #[allow(non_camel_case_types)] pub type wasm_valkind_t = u8; -#[repr(C)] +/// cbindgen:ignore +#[allow(non_camel_case_types)] #[derive(Clone, Copy)] pub union wasm_val_inner { pub(crate) int32_t: i32, @@ -16,7 +18,8 @@ pub union wasm_val_inner { pub(crate) wref: *mut wasm_ref_t, } -#[repr(C)] +/// cbindgen:ignore +#[allow(non_camel_case_types)] pub struct wasm_val_t { pub(crate) kind: wasm_valkind_t, pub(crate) of: wasm_val_inner, @@ -31,6 +34,7 @@ impl Clone for wasm_val_t { } } +/// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn wasm_val_copy(out_ptr: *mut wasm_val_t, val: &wasm_val_t) { (*out_ptr).kind = val.kind; @@ -46,6 +50,7 @@ pub unsafe extern "C" fn wasm_val_copy(out_ptr: *mut wasm_val_t, val: &wasm_val_ }; } +/// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn wasm_val_delete(val: Option>) { if let Some(v_inner) = val { From b59db4cee2f14186944f2763c327a2c9f0f9a2d2 Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Mon, 28 Sep 2020 14:52:27 +0200 Subject: [PATCH 060/281] feat(c-api) `wasmer_wasm.h` includes `wasm.h`. --- lib/c-api/build.rs | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/lib/c-api/build.rs b/lib/c-api/build.rs index 038f3aef3..10309c6ac 100644 --- a/lib/c-api/build.rs +++ b/lib/c-api/build.rs @@ -127,12 +127,7 @@ fn build_wasm_c_api_headers(crate_dir: &str, out_dir: &str) { "include-deprecated", INCLUDE_DEPRECATED_FEATURE_AS_C_DEFINE, ) - // Do not include `wasm.h` as it doesn't contain any - // documentation. - // We export the same functions, with documentations and - // examples, which is better for the user. - // - //.with_include("wasm.h") + .with_include("wasm.h") .with_documentation(true); #[cfg(not(feature = "include-deprecated"))] From 04ef295a1da64a912d53c4a0257450c8eb5d38f3 Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Mon, 28 Sep 2020 14:52:55 +0200 Subject: [PATCH 061/281] chore(c-api) Regenerate `wasmer_wasm.h`. --- lib/c-api/wasmer_wasm.h | 398 ---------------------------------------- 1 file changed, 398 deletions(-) diff --git a/lib/c-api/wasmer_wasm.h b/lib/c-api/wasmer_wasm.h index 38dbf8654..c4b319422 100644 --- a/lib/c-api/wasmer_wasm.h +++ b/lib/c-api/wasmer_wasm.h @@ -51,78 +51,16 @@ #include #include "wasm.h" -enum wasm_valkind_enum { - WASM_I32 = 0, - WASM_I64 = 1, - WASM_F32 = 2, - WASM_F64 = 3, - WASM_ANYREF = 128, - WASM_FUNCREF = 129, -}; -typedef uint8_t wasm_valkind_enum; - typedef struct Box_wasi_config_t Box_wasi_config_t; -typedef struct Box_wasm_engine_t Box_wasm_engine_t; - -typedef struct Box_wasm_exporttype_t Box_wasm_exporttype_t; - -typedef struct Box_wasm_externtype_t Box_wasm_externtype_t; - -typedef struct Box_wasm_global_t Box_wasm_global_t; - -typedef struct Box_wasm_importtype_t Box_wasm_importtype_t; - -typedef struct Box_wasm_memory_t Box_wasm_memory_t; - -typedef struct Box_wasm_memorytype_t Box_wasm_memorytype_t; - -typedef struct Box_wasm_table_t Box_wasm_table_t; - -typedef struct Box_wasm_tabletype_t Box_wasm_tabletype_t; - -typedef struct Box_wasm_valtype_t Box_wasm_valtype_t; - typedef struct Option_Box_wasi_config_t Option_Box_wasi_config_t; typedef struct Option_Box_wasi_env_t Option_Box_wasi_env_t; -typedef struct Option_Box_wasm_engine_t Option_Box_wasm_engine_t; - -typedef struct Option_Box_wasm_extern_t Option_Box_wasm_extern_t; - -typedef struct Option_Box_wasm_externtype_t Option_Box_wasm_externtype_t; - -typedef struct Option_Box_wasm_func_t Option_Box_wasm_func_t; - -typedef struct Option_Box_wasm_functype_t Option_Box_wasm_functype_t; - -typedef struct Option_Box_wasm_global_t Option_Box_wasm_global_t; - -typedef struct Option_Box_wasm_globaltype_t Option_Box_wasm_globaltype_t; - -typedef struct Option_Box_wasm_importtype_t Option_Box_wasm_importtype_t; - -typedef struct Option_Box_wasm_instance_t Option_Box_wasm_instance_t; - -typedef struct Option_Box_wasm_memory_t Option_Box_wasm_memory_t; - -typedef struct Option_Box_wasm_memorytype_t Option_Box_wasm_memorytype_t; - -typedef struct Option_Box_wasm_module_t Option_Box_wasm_module_t; - -typedef struct Option_Box_wasm_table_t Option_Box_wasm_table_t; - -typedef struct Option_Box_wasm_tabletype_t Option_Box_wasm_tabletype_t; - -typedef struct Option_Box_wasm_valtype_t Option_Box_wasm_valtype_t; - #if defined(WASMER_WASI_ENABLED) typedef struct wasi_version_t wasi_version_t; #endif -typedef struct wasm_ref_t wasm_ref_t; - #if defined(WASMER_WASI_ENABLED) typedef struct { bool inherit_stdout; @@ -137,125 +75,6 @@ typedef struct { } wasi_env_t; #endif -typedef struct { - -} wasm_instance_t; - -typedef struct { - -} wasm_memory_t; - -/** - * Opaque wrapper around `Store` - */ -typedef struct { - -} wasm_store_t; - -typedef struct { - -} wasm_module_t; - -typedef struct { - -} wasm_extern_t; - -/** - * this can be a wasmer-specific type with wasmer-specific functions for manipulating it - */ -typedef struct { - -} wasm_config_t; - -typedef wasm_byte_vec_t wasm_name_t; - -typedef struct { - -} wasm_externtype_t; - -typedef struct { - wasm_name_t *name; - wasm_externtype_t *extern_type; -} wasm_exporttype_t; - -typedef uint8_t wasm_externkind_t; - -typedef struct { - -} wasm_functype_t; - -typedef struct { - -} wasm_globaltype_t; - -typedef struct { - -} wasm_memorytype_t; - -typedef struct { - -} wasm_tabletype_t; - -typedef struct { - -} wasm_func_t; - -typedef struct { - -} wasm_trap_t; - -typedef uint8_t wasm_valkind_t; - -typedef union { - int32_t int32_t; - int64_t int64_t; - float float32_t; - double float64_t; - wasm_ref_t *wref; -} wasm_val_inner; - -typedef struct { - wasm_valkind_t kind; - wasm_val_inner of; -} wasm_val_t; - -typedef wasm_trap_t *(*wasm_func_callback_t)(const wasm_val_t *args, wasm_val_t *results); - -typedef wasm_trap_t *(*wasm_func_callback_with_env_t)(void*, const wasm_val_t *args, wasm_val_t *results); - -typedef void (*wasm_env_finalizer_t)(void); - -typedef struct { - -} wasm_global_t; - -typedef struct { - wasm_valkind_enum valkind; -} wasm_valtype_t; - -typedef uint8_t wasm_mutability_t; - -typedef struct { - wasm_name_t *module; - wasm_name_t *name; - wasm_externtype_t *extern_type; -} wasm_importtype_t; - -typedef struct { - uint32_t min; - uint32_t max; -} wasm_limits_t; - -typedef struct { - -} wasm_engine_t; - -typedef struct { - -} wasm_table_t; - -typedef uint32_t wasm_table_size_t; - #if defined(WASMER_WASI_ENABLED) void wasi_config_arg(wasi_config_t *config, const char *arg); #endif @@ -321,223 +140,6 @@ bool wasi_get_imports(wasm_store_t *store, wasi_version_t wasi_get_wasi_version(const wasm_module_t *module); #endif -wasm_config_t *wasm_config_new(void); - -void wasm_engine_delete(Option_Box_wasm_engine_t _wasm_engine_address); - -Box_wasm_engine_t wasm_engine_new_with_config(wasm_config_t *_config_ptr); - -const wasm_name_t *wasm_exporttype_name(const wasm_exporttype_t *et); - -Box_wasm_exporttype_t wasm_exporttype_new(wasm_name_t *name, wasm_externtype_t *extern_type); - -const wasm_externtype_t *wasm_exporttype_type(const wasm_exporttype_t *et); - -Option_Box_wasm_func_t wasm_extern_as_func(wasm_extern_t *extern_ptr); - -Option_Box_wasm_global_t wasm_extern_as_global(wasm_extern_t *extern_ptr); - -Option_Box_wasm_memory_t wasm_extern_as_memory(wasm_extern_t *extern_ptr); - -Option_Box_wasm_table_t wasm_extern_as_table(wasm_extern_t *extern_ptr); - -wasm_externkind_t wasm_extern_kind(const wasm_extern_t *e); - -Box_wasm_externtype_t wasm_extern_type(const wasm_extern_t *e); - -const wasm_functype_t *wasm_externtype_as_functype(const wasm_externtype_t *et); - -const wasm_functype_t *wasm_externtype_as_functype_const(const wasm_externtype_t *et); - -const wasm_globaltype_t *wasm_externtype_as_globaltype(const wasm_externtype_t *et); - -const wasm_globaltype_t *wasm_externtype_as_globaltype_const(const wasm_externtype_t *et); - -const wasm_memorytype_t *wasm_externtype_as_memorytype(const wasm_externtype_t *et); - -const wasm_memorytype_t *wasm_externtype_as_memorytype_const(const wasm_externtype_t *et); - -const wasm_tabletype_t *wasm_externtype_as_tabletype(const wasm_externtype_t *et); - -const wasm_tabletype_t *wasm_externtype_as_tabletype_const(const wasm_externtype_t *et); - -void wasm_externtype_delete(Option_Box_wasm_externtype_t _et); - -wasm_externkind_t wasm_externtype_kind(const wasm_externtype_t *et); - -Option_Box_wasm_extern_t wasm_func_as_extern(wasm_func_t *func_ptr); - -wasm_trap_t *wasm_func_call(const wasm_func_t *func, const wasm_val_t *args, wasm_val_t *results); - -void wasm_func_delete(Option_Box_wasm_func_t _func); - -Option_Box_wasm_func_t wasm_func_new(wasm_store_t *store, - const wasm_functype_t *ft, - wasm_func_callback_t callback); - -Option_Box_wasm_func_t wasm_func_new_with_env(wasm_store_t *store, - const wasm_functype_t *ft, - wasm_func_callback_with_env_t callback, - void *env, - wasm_env_finalizer_t finalizer); - -uintptr_t wasm_func_param_arity(const wasm_func_t *func); - -uintptr_t wasm_func_result_arity(const wasm_func_t *func); - -const wasm_externtype_t *wasm_functype_as_externtype(const wasm_functype_t *ft); - -const wasm_externtype_t *wasm_functype_as_externtype_const(const wasm_functype_t *ft); - -Option_Box_wasm_functype_t wasm_functype_copy(wasm_functype_t *arg); - -void wasm_functype_delete(Option_Box_wasm_functype_t _ft); - -Option_Box_wasm_functype_t wasm_functype_new(wasm_valtype_vec_t *params, - wasm_valtype_vec_t *results); - -const wasm_valtype_vec_t *wasm_functype_params(const wasm_functype_t *ft); - -const wasm_valtype_vec_t *wasm_functype_results(const wasm_functype_t *ft); - -Option_Box_wasm_extern_t wasm_global_as_extern(wasm_global_t *global_ptr); - -Box_wasm_global_t wasm_global_copy(const wasm_global_t *wasm_global); - -void wasm_global_delete(Option_Box_wasm_global_t _global); - -void wasm_global_get(const wasm_global_t *wasm_global, wasm_val_t *out); - -Option_Box_wasm_global_t wasm_global_new(wasm_store_t *store_ptr, - const wasm_globaltype_t *gt, - const wasm_val_t *val); - -bool wasm_global_same(const wasm_global_t *wasm_global1, const wasm_global_t *wasm_global2); - -void wasm_global_set(wasm_global_t *wasm_global, const wasm_val_t *val); - -const wasm_externtype_t *wasm_globaltype_as_externtype(const wasm_globaltype_t *gt); - -const wasm_externtype_t *wasm_globaltype_as_externtype_const(const wasm_globaltype_t *gt); - -const wasm_valtype_t *wasm_globaltype_content(const wasm_globaltype_t *globaltype); - -void wasm_globaltype_delete(Option_Box_wasm_globaltype_t _globaltype); - -wasm_mutability_t wasm_globaltype_mutability(const wasm_globaltype_t *globaltype); - -Option_Box_wasm_globaltype_t wasm_globaltype_new(Option_Box_wasm_valtype_t valtype, - wasm_mutability_t mutability); - -void wasm_importtype_delete(Option_Box_wasm_importtype_t _importtype); - -const wasm_name_t *wasm_importtype_module(const wasm_importtype_t *et); - -const wasm_name_t *wasm_importtype_name(const wasm_importtype_t *et); - -Box_wasm_importtype_t wasm_importtype_new(wasm_name_t *module, - wasm_name_t *name, - wasm_externtype_t *extern_type); - -const wasm_externtype_t *wasm_importtype_type(const wasm_importtype_t *et); - -void wasm_instance_delete(Option_Box_wasm_instance_t _instance); - -void wasm_instance_exports(const wasm_instance_t *instance, wasm_extern_vec_t *out); - -Option_Box_wasm_instance_t wasm_instance_new(wasm_store_t *store, - const wasm_module_t *module, - const wasm_extern_t *const *imports, - wasm_trap_t **_traps); - -Option_Box_wasm_extern_t wasm_memory_as_extern(wasm_memory_t *memory_ptr); - -Box_wasm_memory_t wasm_memory_copy(const wasm_memory_t *wasm_memory); - -uint8_t *wasm_memory_data(wasm_memory_t *memory); - -uintptr_t wasm_memory_data_size(const wasm_memory_t *memory); - -void wasm_memory_delete(Option_Box_wasm_memory_t _memory); - -bool wasm_memory_grow(wasm_memory_t *memory, uint32_t delta); - -Option_Box_wasm_memory_t wasm_memory_new(wasm_store_t *store_ptr, const wasm_memorytype_t *mt); - -bool wasm_memory_same(const wasm_memory_t *wasm_memory1, const wasm_memory_t *wasm_memory2); - -uint32_t wasm_memory_size(const wasm_memory_t *memory); - -wasm_memorytype_t *wasm_memory_type(const wasm_memory_t *_memory_ptr); - -const wasm_externtype_t *wasm_memorytype_as_externtype(const wasm_memorytype_t *mt); - -const wasm_externtype_t *wasm_memorytype_as_externtype_const(const wasm_memorytype_t *mt); - -void wasm_memorytype_delete(Option_Box_wasm_memorytype_t _memorytype); - -const wasm_limits_t *wasm_memorytype_limits(const wasm_memorytype_t *mt); - -Box_wasm_memorytype_t wasm_memorytype_new(const wasm_limits_t *limits); - -void wasm_module_delete(Option_Box_wasm_module_t _module); - -wasm_module_t *wasm_module_deserialize(wasm_store_t *store_ptr, const wasm_byte_vec_t *bytes); - -void wasm_module_exports(const wasm_module_t *module, wasm_exporttype_vec_t *out); - -void wasm_module_imports(const wasm_module_t *module, wasm_importtype_vec_t *out); - -Option_Box_wasm_module_t wasm_module_new(wasm_store_t *store_ptr, const wasm_byte_vec_t *bytes); - -void wasm_module_serialize(const wasm_module_t *module, wasm_byte_vec_t *out_ptr); - -void wasm_store_delete(wasm_store_t *wasm_store); - -wasm_store_t *wasm_store_new(wasm_engine_t *wasm_engine_ptr); - -Option_Box_wasm_extern_t wasm_table_as_extern(wasm_table_t *table_ptr); - -Box_wasm_table_t wasm_table_copy(const wasm_table_t *wasm_table); - -void wasm_table_delete(Option_Box_wasm_table_t _table); - -bool wasm_table_grow(wasm_table_t *_wasm_table, wasm_table_size_t _delta, wasm_ref_t *_init); - -Option_Box_wasm_table_t wasm_table_new(wasm_store_t *store_ptr, - const wasm_tabletype_t *tt, - const wasm_ref_t *init); - -bool wasm_table_same(const wasm_table_t *wasm_table1, const wasm_table_t *wasm_table2); - -uintptr_t wasm_table_size(const wasm_table_t *wasm_table); - -const wasm_externtype_t *wasm_tabletype_as_externtype(const wasm_tabletype_t *tt); - -const wasm_externtype_t *wasm_tabletype_as_externtype_const(const wasm_tabletype_t *tt); - -void wasm_tabletype_delete(Option_Box_wasm_tabletype_t _tabletype); - -const wasm_valtype_t *wasm_tabletype_element(const wasm_tabletype_t *tabletype); - -const wasm_limits_t *wasm_tabletype_limits(const wasm_tabletype_t *tabletype); - -Box_wasm_tabletype_t wasm_tabletype_new(Box_wasm_valtype_t valtype, const wasm_limits_t *limits); - -void wasm_trap_delete(wasm_trap_t *trap); - -void wasm_trap_message(const wasm_trap_t *trap, wasm_byte_vec_t *out_ptr); - -void wasm_val_copy(wasm_val_t *out_ptr, const wasm_val_t *val); - -void wasm_val_delete(wasm_val_t *val); - -void wasm_valtype_delete(Option_Box_wasm_valtype_t _valtype); - -wasm_valkind_t wasm_valtype_kind(const wasm_valtype_t *valtype); - -Option_Box_wasm_valtype_t wasm_valtype_new(wasm_valkind_t kind); - /** * Gets the length in bytes of the last error if any. * From f61a11526c1ad07179f1916394fafd91c8a67b40 Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Mon, 28 Sep 2020 15:33:42 +0200 Subject: [PATCH 062/281] chore(c-api) Use original `cbindgen` instead of our fork. --- lib/c-api/Cargo.toml | 2 +- lib/c-api/wasmer_wasm.h | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/c-api/Cargo.toml b/lib/c-api/Cargo.toml index 1b577fcde..fcb317160 100644 --- a/lib/c-api/Cargo.toml +++ b/lib/c-api/Cargo.toml @@ -78,4 +78,4 @@ cranelift-backend = ["cranelift"] llvm-backend = ["llvm"] [build-dependencies] -cbindgen = { git = "https://github.com/Hywan/cbindgen", branch = "incoming" } +cbindgen = "0.14.6" \ No newline at end of file diff --git a/lib/c-api/wasmer_wasm.h b/lib/c-api/wasmer_wasm.h index c4b319422..3348f90ce 100644 --- a/lib/c-api/wasmer_wasm.h +++ b/lib/c-api/wasmer_wasm.h @@ -66,12 +66,13 @@ typedef struct { bool inherit_stdout; bool inherit_stderr; bool inherit_stdin; + WasiStateBuilder state_builder; } wasi_config_t; #endif #if defined(WASMER_WASI_ENABLED) typedef struct { - + WasiEnv inner; } wasi_env_t; #endif From 1c0708df330f9a123f6ee2d76b00d5163f22866d Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Mon, 28 Sep 2020 15:39:33 +0200 Subject: [PATCH 063/281] fix(c-api) Add missing `JIT` symbol. --- lib/c-api/src/wasm_c_api/engine.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/c-api/src/wasm_c_api/engine.rs b/lib/c-api/src/wasm_c_api/engine.rs index eb11c3e6e..184718751 100644 --- a/lib/c-api/src/wasm_c_api/engine.rs +++ b/lib/c-api/src/wasm_c_api/engine.rs @@ -25,6 +25,8 @@ cfg_if! { if #[cfg(all(feature = "jit", feature = "compiler"))] { // Compiler JIT use wasmer_compiler::CompilerConfig; + use wasmer_engine_jit::JIT; + fn get_default_compiler_config() -> Box { cfg_if! { if #[cfg(feature = "cranelift")] { From 579d00ffd71a523443adcb9e8381dd235ccf5a89 Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Mon, 28 Sep 2020 15:40:51 +0200 Subject: [PATCH 064/281] chore(c-api) Fix a bad `sed`, woops. --- lib/c-api/src/wasm_c_api/types/memory.rs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/lib/c-api/src/wasm_c_api/types/memory.rs b/lib/c-api/src/wasm_c_api/types/memory.rs index cc2cfa39b..39456f87c 100644 --- a/lib/c-api/src/wasm_c_api/types/memory.rs +++ b/lib/c-api/src/wasm_c_api/types/memory.rs @@ -32,7 +32,8 @@ pub struct wasm_limits_t { pub(crate) max: u32, } -/// cbindgen:ignoren#[no_mangle] +/// cbindgen:ignore +#[no_mangle] pub unsafe extern "C" fn wasm_memorytype_new(limits: &wasm_limits_t) -> Box { let min_pages = Pages(limits.min as _); // TODO: investigate if `0` is in fact a sentinel value here @@ -48,12 +49,14 @@ pub unsafe extern "C" fn wasm_memorytype_new(limits: &wasm_limits_t) -> Box>) {} // TODO: fix memory leak // this function leaks memory because the returned limits pointer is not owned -/// cbindgen:ignoren#[no_mangle] +/// cbindgen:ignore +#[no_mangle] pub unsafe extern "C" fn wasm_memorytype_limits(mt: &wasm_memorytype_t) -> *const wasm_limits_t { let md = mt.as_memorytype(); Box::into_raw(Box::new(wasm_limits_t { From 570b174fb513a1e74ad071bf2fd3ca444afd4b90 Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Mon, 28 Sep 2020 15:45:52 +0200 Subject: [PATCH 065/281] fix(c-api) Polish deprecated API. --- lib/c-api/build.rs | 2 +- lib/c-api/src/deprecated/mod.rs | 2 +- lib/c-api/wasmer.h | 396 -------------------------------- lib/c-api/wasmer.hh | 338 --------------------------- 4 files changed, 2 insertions(+), 736 deletions(-) diff --git a/lib/c-api/build.rs b/lib/c-api/build.rs index 10309c6ac..ceab25593 100644 --- a/lib/c-api/build.rs +++ b/lib/c-api/build.rs @@ -230,7 +230,7 @@ fn build_wasm_c_api_headers(crate_dir: &str, out_dir: &str) { // List of all structs and enums to exclude given by: // - // `rg 'pub (enum|struct)' deprecated/` + // `rg 'pub (enum|struct|union)' deprecated/` builder = builder .exclude_item("NamedExportDescriptors(Vec)") .exclude_item("NamedImportDescriptors(Vec)") diff --git a/lib/c-api/src/deprecated/mod.rs b/lib/c-api/src/deprecated/mod.rs index 1c5e33d0a..64334eba5 100644 --- a/lib/c-api/src/deprecated/mod.rs +++ b/lib/c-api/src/deprecated/mod.rs @@ -172,7 +172,7 @@ pub(crate) unsafe fn get_slice_checked<'a, T>(ptr: *const T, len: usize) -> &'a lazy_static! { pub(crate) static ref GLOBAL_STORE: wasmer::Store = - wasmer::Store::new(&*crate::wasm_c_api::wasm_engine_new().inner); + wasmer::Store::new(&*crate::wasm_c_api::engine::wasm_engine_new().inner); } pub(crate) fn get_global_store() -> &'static wasmer::Store { diff --git a/lib/c-api/wasmer.h b/lib/c-api/wasmer.h index 3fa18e7ef..c664264b5 100644 --- a/lib/c-api/wasmer.h +++ b/lib/c-api/wasmer.h @@ -77,16 +77,6 @@ enum Version { typedef uint8_t Version; #endif -enum wasm_valkind_enum { - WASM_I32 = 0, - WASM_I64 = 1, - WASM_F32 = 2, - WASM_F64 = 3, - WASM_ANYREF = 128, - WASM_FUNCREF = 129, -}; -typedef uint8_t wasm_valkind_enum; - /** * List of export/import kinds. */ @@ -150,76 +140,16 @@ enum wasmer_value_tag { }; typedef uint32_t wasmer_value_tag; -typedef struct Arc_Instance Arc_Instance; - -typedef struct Arc_Module Arc_Module; - typedef struct Box_wasi_config_t Box_wasi_config_t; -typedef struct Box_wasm_engine_t Box_wasm_engine_t; - -typedef struct Box_wasm_exporttype_t Box_wasm_exporttype_t; - -typedef struct Box_wasm_externtype_t Box_wasm_externtype_t; - -typedef struct Box_wasm_global_t Box_wasm_global_t; - -typedef struct Box_wasm_importtype_t Box_wasm_importtype_t; - -typedef struct Box_wasm_memory_t Box_wasm_memory_t; - -typedef struct Box_wasm_memorytype_t Box_wasm_memorytype_t; - -typedef struct Box_wasm_table_t Box_wasm_table_t; - -typedef struct Box_wasm_tabletype_t Box_wasm_tabletype_t; - -typedef struct Box_wasm_valtype_t Box_wasm_valtype_t; - -typedef struct Option_Arc_Instance Option_Arc_Instance; - typedef struct Option_Box_wasi_config_t Option_Box_wasi_config_t; typedef struct Option_Box_wasi_env_t Option_Box_wasi_env_t; -typedef struct Option_Box_wasm_engine_t Option_Box_wasm_engine_t; - -typedef struct Option_Box_wasm_extern_t Option_Box_wasm_extern_t; - -typedef struct Option_Box_wasm_externtype_t Option_Box_wasm_externtype_t; - -typedef struct Option_Box_wasm_func_t Option_Box_wasm_func_t; - -typedef struct Option_Box_wasm_functype_t Option_Box_wasm_functype_t; - -typedef struct Option_Box_wasm_global_t Option_Box_wasm_global_t; - -typedef struct Option_Box_wasm_globaltype_t Option_Box_wasm_globaltype_t; - -typedef struct Option_Box_wasm_importtype_t Option_Box_wasm_importtype_t; - -typedef struct Option_Box_wasm_instance_t Option_Box_wasm_instance_t; - -typedef struct Option_Box_wasm_memory_t Option_Box_wasm_memory_t; - -typedef struct Option_Box_wasm_memorytype_t Option_Box_wasm_memorytype_t; - -typedef struct Option_Box_wasm_module_t Option_Box_wasm_module_t; - -typedef struct Option_Box_wasm_table_t Option_Box_wasm_table_t; - -typedef struct Option_Box_wasm_tabletype_t Option_Box_wasm_tabletype_t; - -typedef struct Option_Box_wasm_valtype_t Option_Box_wasm_valtype_t; - #if defined(WASMER_WASI_ENABLED) typedef struct wasi_version_t wasi_version_t; #endif -typedef struct wasm_engine_t wasm_engine_t; - -typedef struct wasm_ref_t wasm_ref_t; - #if defined(WASMER_WASI_ENABLED) typedef struct { bool inherit_stdout; @@ -235,115 +165,6 @@ typedef struct { } wasi_env_t; #endif -typedef struct { - Arc_Instance inner; -} wasm_instance_t; - -typedef struct { - Memory inner; -} wasm_memory_t; - -/** - * Opaque wrapper around `Store` - */ -typedef struct { - -} wasm_store_t; - -typedef struct { - Arc_Module inner; -} wasm_module_t; - -typedef struct { - Option_Arc_Instance instance; - Extern inner; -} wasm_extern_t; - -/** - * this can be a wasmer-specific type with wasmer-specific functions for manipulating it - */ -typedef struct { - -} wasm_config_t; - -typedef wasm_byte_vec_t wasm_name_t; - -typedef ExternType wasm_externtype_t; - -typedef struct { - wasm_name_t *name; - wasm_externtype_t *extern_type; -} wasm_exporttype_t; - -typedef uint8_t wasm_externkind_t; - -typedef wasm_externtype_t wasm_functype_t; - -typedef wasm_externtype_t wasm_globaltype_t; - -typedef wasm_externtype_t wasm_memorytype_t; - -typedef struct { - wasm_externtype_t extern_; -} wasm_tabletype_t; - -typedef struct { - Function inner; - Option_Arc_Instance instance; -} wasm_func_t; - -typedef struct { - -} wasm_trap_t; - -typedef uint8_t wasm_valkind_t; - -typedef union { - int32_t int32_t; - int64_t int64_t; - float float32_t; - double float64_t; - wasm_ref_t *wref; -} wasm_val_inner; - -typedef struct { - wasm_valkind_t kind; - wasm_val_inner of; -} wasm_val_t; - -typedef wasm_trap_t *(*wasm_func_callback_t)(const wasm_val_t *args, wasm_val_t *results); - -typedef wasm_trap_t *(*wasm_func_callback_with_env_t)(void*, const wasm_val_t *args, wasm_val_t *results); - -typedef void (*wasm_env_finalizer_t)(void); - -typedef struct { - Global inner; -} wasm_global_t; - -typedef struct { - wasm_valkind_enum valkind; -} wasm_valtype_t; - -typedef uint8_t wasm_mutability_t; - -typedef struct { - wasm_name_t *module; - wasm_name_t *name; - wasm_externtype_t *extern_type; -} wasm_importtype_t; - -typedef struct { - uint32_t min; - uint32_t max; -} wasm_limits_t; - -typedef struct { - Table inner; -} wasm_table_t; - -typedef uint32_t wasm_table_size_t; - typedef struct { } wasmer_module_t; @@ -670,223 +491,6 @@ bool wasi_get_imports(wasm_store_t *store, wasi_version_t wasi_get_wasi_version(const wasm_module_t *module); #endif -wasm_config_t *wasm_config_new(void); - -void wasm_engine_delete(Option_Box_wasm_engine_t _wasm_engine_address); - -Box_wasm_engine_t wasm_engine_new_with_config(wasm_config_t *_config_ptr); - -const wasm_name_t *wasm_exporttype_name(const wasm_exporttype_t *et); - -Box_wasm_exporttype_t wasm_exporttype_new(wasm_name_t *name, wasm_externtype_t *extern_type); - -const wasm_externtype_t *wasm_exporttype_type(const wasm_exporttype_t *et); - -Option_Box_wasm_func_t wasm_extern_as_func(wasm_extern_t *extern_ptr); - -Option_Box_wasm_global_t wasm_extern_as_global(wasm_extern_t *extern_ptr); - -Option_Box_wasm_memory_t wasm_extern_as_memory(wasm_extern_t *extern_ptr); - -Option_Box_wasm_table_t wasm_extern_as_table(wasm_extern_t *extern_ptr); - -wasm_externkind_t wasm_extern_kind(const wasm_extern_t *e); - -Box_wasm_externtype_t wasm_extern_type(const wasm_extern_t *e); - -const wasm_functype_t *wasm_externtype_as_functype(const wasm_externtype_t *et); - -const wasm_functype_t *wasm_externtype_as_functype_const(const wasm_externtype_t *et); - -const wasm_globaltype_t *wasm_externtype_as_globaltype(const wasm_externtype_t *et); - -const wasm_globaltype_t *wasm_externtype_as_globaltype_const(const wasm_externtype_t *et); - -const wasm_memorytype_t *wasm_externtype_as_memorytype(const wasm_externtype_t *et); - -const wasm_memorytype_t *wasm_externtype_as_memorytype_const(const wasm_externtype_t *et); - -const wasm_tabletype_t *wasm_externtype_as_tabletype(const wasm_externtype_t *et); - -const wasm_tabletype_t *wasm_externtype_as_tabletype_const(const wasm_externtype_t *et); - -void wasm_externtype_delete(Option_Box_wasm_externtype_t _et); - -wasm_externkind_t wasm_externtype_kind(const wasm_externtype_t *et); - -Option_Box_wasm_extern_t wasm_func_as_extern(wasm_func_t *func_ptr); - -wasm_trap_t *wasm_func_call(const wasm_func_t *func, const wasm_val_t *args, wasm_val_t *results); - -void wasm_func_delete(Option_Box_wasm_func_t _func); - -Option_Box_wasm_func_t wasm_func_new(wasm_store_t *store, - const wasm_functype_t *ft, - wasm_func_callback_t callback); - -Option_Box_wasm_func_t wasm_func_new_with_env(wasm_store_t *store, - const wasm_functype_t *ft, - wasm_func_callback_with_env_t callback, - void *env, - wasm_env_finalizer_t finalizer); - -uintptr_t wasm_func_param_arity(const wasm_func_t *func); - -uintptr_t wasm_func_result_arity(const wasm_func_t *func); - -const wasm_externtype_t *wasm_functype_as_externtype(const wasm_functype_t *ft); - -const wasm_externtype_t *wasm_functype_as_externtype_const(const wasm_functype_t *ft); - -Option_Box_wasm_functype_t wasm_functype_copy(wasm_functype_t *arg); - -void wasm_functype_delete(Option_Box_wasm_functype_t _ft); - -Option_Box_wasm_functype_t wasm_functype_new(wasm_valtype_vec_t *params, - wasm_valtype_vec_t *results); - -const wasm_valtype_vec_t *wasm_functype_params(const wasm_functype_t *ft); - -const wasm_valtype_vec_t *wasm_functype_results(const wasm_functype_t *ft); - -Option_Box_wasm_extern_t wasm_global_as_extern(wasm_global_t *global_ptr); - -Box_wasm_global_t wasm_global_copy(const wasm_global_t *wasm_global); - -void wasm_global_delete(Option_Box_wasm_global_t _global); - -void wasm_global_get(const wasm_global_t *wasm_global, wasm_val_t *out); - -Option_Box_wasm_global_t wasm_global_new(wasm_store_t *store_ptr, - const wasm_globaltype_t *gt, - const wasm_val_t *val); - -bool wasm_global_same(const wasm_global_t *wasm_global1, const wasm_global_t *wasm_global2); - -void wasm_global_set(wasm_global_t *wasm_global, const wasm_val_t *val); - -const wasm_externtype_t *wasm_globaltype_as_externtype(const wasm_globaltype_t *gt); - -const wasm_externtype_t *wasm_globaltype_as_externtype_const(const wasm_globaltype_t *gt); - -const wasm_valtype_t *wasm_globaltype_content(const wasm_globaltype_t *globaltype); - -void wasm_globaltype_delete(Option_Box_wasm_globaltype_t _globaltype); - -wasm_mutability_t wasm_globaltype_mutability(const wasm_globaltype_t *globaltype); - -Option_Box_wasm_globaltype_t wasm_globaltype_new(Option_Box_wasm_valtype_t valtype, - wasm_mutability_t mutability); - -void wasm_importtype_delete(Option_Box_wasm_importtype_t _importtype); - -const wasm_name_t *wasm_importtype_module(const wasm_importtype_t *et); - -const wasm_name_t *wasm_importtype_name(const wasm_importtype_t *et); - -Box_wasm_importtype_t wasm_importtype_new(wasm_name_t *module, - wasm_name_t *name, - wasm_externtype_t *extern_type); - -const wasm_externtype_t *wasm_importtype_type(const wasm_importtype_t *et); - -void wasm_instance_delete(Option_Box_wasm_instance_t _instance); - -void wasm_instance_exports(const wasm_instance_t *instance, wasm_extern_vec_t *out); - -Option_Box_wasm_instance_t wasm_instance_new(wasm_store_t *store, - const wasm_module_t *module, - const wasm_extern_t *const *imports, - wasm_trap_t **_traps); - -Option_Box_wasm_extern_t wasm_memory_as_extern(wasm_memory_t *memory_ptr); - -Box_wasm_memory_t wasm_memory_copy(const wasm_memory_t *wasm_memory); - -uint8_t *wasm_memory_data(wasm_memory_t *memory); - -uintptr_t wasm_memory_data_size(const wasm_memory_t *memory); - -void wasm_memory_delete(Option_Box_wasm_memory_t _memory); - -bool wasm_memory_grow(wasm_memory_t *memory, uint32_t delta); - -Option_Box_wasm_memory_t wasm_memory_new(wasm_store_t *store_ptr, const wasm_memorytype_t *mt); - -bool wasm_memory_same(const wasm_memory_t *wasm_memory1, const wasm_memory_t *wasm_memory2); - -uint32_t wasm_memory_size(const wasm_memory_t *memory); - -wasm_memorytype_t *wasm_memory_type(const wasm_memory_t *_memory_ptr); - -const wasm_externtype_t *wasm_memorytype_as_externtype(const wasm_memorytype_t *mt); - -const wasm_externtype_t *wasm_memorytype_as_externtype_const(const wasm_memorytype_t *mt); - -void wasm_memorytype_delete(Option_Box_wasm_memorytype_t _memorytype); - -const wasm_limits_t *wasm_memorytype_limits(const wasm_memorytype_t *mt); - -Box_wasm_memorytype_t wasm_memorytype_new(const wasm_limits_t *limits); - -void wasm_module_delete(Option_Box_wasm_module_t _module); - -wasm_module_t *wasm_module_deserialize(wasm_store_t *store_ptr, const wasm_byte_vec_t *bytes); - -void wasm_module_exports(const wasm_module_t *module, wasm_exporttype_vec_t *out); - -void wasm_module_imports(const wasm_module_t *module, wasm_importtype_vec_t *out); - -Option_Box_wasm_module_t wasm_module_new(wasm_store_t *store_ptr, const wasm_byte_vec_t *bytes); - -void wasm_module_serialize(const wasm_module_t *module, wasm_byte_vec_t *out_ptr); - -void wasm_store_delete(wasm_store_t *wasm_store); - -wasm_store_t *wasm_store_new(wasm_engine_t *wasm_engine_ptr); - -Option_Box_wasm_extern_t wasm_table_as_extern(wasm_table_t *table_ptr); - -Box_wasm_table_t wasm_table_copy(const wasm_table_t *wasm_table); - -void wasm_table_delete(Option_Box_wasm_table_t _table); - -bool wasm_table_grow(wasm_table_t *_wasm_table, wasm_table_size_t _delta, wasm_ref_t *_init); - -Option_Box_wasm_table_t wasm_table_new(wasm_store_t *store_ptr, - const wasm_tabletype_t *tt, - const wasm_ref_t *init); - -bool wasm_table_same(const wasm_table_t *wasm_table1, const wasm_table_t *wasm_table2); - -uintptr_t wasm_table_size(const wasm_table_t *wasm_table); - -const wasm_externtype_t *wasm_tabletype_as_externtype(const wasm_tabletype_t *tt); - -const wasm_externtype_t *wasm_tabletype_as_externtype_const(const wasm_tabletype_t *tt); - -void wasm_tabletype_delete(Option_Box_wasm_tabletype_t _tabletype); - -const wasm_valtype_t *wasm_tabletype_element(const wasm_tabletype_t *tabletype); - -const wasm_limits_t *wasm_tabletype_limits(const wasm_tabletype_t *tabletype); - -Box_wasm_tabletype_t wasm_tabletype_new(Box_wasm_valtype_t valtype, const wasm_limits_t *limits); - -void wasm_trap_delete(wasm_trap_t *trap); - -void wasm_trap_message(const wasm_trap_t *trap, wasm_byte_vec_t *out_ptr); - -void wasm_val_copy(wasm_val_t *out_ptr, const wasm_val_t *val); - -void wasm_val_delete(wasm_val_t *val); - -void wasm_valtype_delete(Option_Box_wasm_valtype_t _valtype); - -wasm_valkind_t wasm_valtype_kind(const wasm_valtype_t *valtype); - -Option_Box_wasm_valtype_t wasm_valtype_new(wasm_valkind_t kind); - /** * Creates a new Module from the given wasm bytes. * diff --git a/lib/c-api/wasmer.hh b/lib/c-api/wasmer.hh index 0401d50d7..09781e1ce 100644 --- a/lib/c-api/wasmer.hh +++ b/lib/c-api/wasmer.hh @@ -68,15 +68,6 @@ enum class Version : uint8_t { }; #endif -enum class wasm_valkind_enum : uint8_t { - WASM_I32 = 0, - WASM_I64 = 1, - WASM_F32 = 2, - WASM_F64 = 3, - WASM_ANYREF = 128, - WASM_FUNCREF = 129, -}; - /// List of export/import kinds. enum class wasmer_import_export_kind : uint32_t { /// The export/import is a function. @@ -112,9 +103,6 @@ enum class wasmer_value_tag : uint32_t { WASM_F64, }; -template -struct Arc; - template struct Box; @@ -125,10 +113,6 @@ struct Option; struct wasi_version_t; #endif -struct wasm_engine_t; - -struct wasm_ref_t; - #if defined(WASMER_WASI_ENABLED) struct wasi_config_t { bool inherit_stdout; @@ -144,111 +128,6 @@ struct wasi_env_t { }; #endif -struct wasm_instance_t { - Arc inner; -}; - -struct wasm_memory_t { - Memory inner; -}; - -/// Opaque wrapper around `Store` -struct wasm_store_t { - -}; - -struct wasm_module_t { - Arc inner; -}; - -struct wasm_extern_t { - Option> instance; - Extern inner; -}; - -/// this can be a wasmer-specific type with wasmer-specific functions for manipulating it -struct wasm_config_t { - -}; - -using wasm_name_t = wasm_byte_vec_t; - -using wasm_externtype_t = ExternType; - -struct wasm_exporttype_t { - wasm_name_t *name; - wasm_externtype_t *extern_type; -}; - -struct wasm_func_t { - Function inner; - Option> instance; -}; - -struct wasm_global_t { - Global inner; -}; - -struct wasm_table_t { - Table inner; -}; - -using wasm_externkind_t = uint8_t; - -using wasm_functype_t = wasm_externtype_t; - -using wasm_globaltype_t = wasm_externtype_t; - -using wasm_memorytype_t = wasm_externtype_t; - -struct wasm_tabletype_t { - wasm_externtype_t extern_; -}; - -struct wasm_trap_t { - -}; - -using wasm_valkind_t = uint8_t; - -union wasm_val_inner { - int32_t int32_t; - int64_t int64_t; - float float32_t; - double float64_t; - wasm_ref_t *wref; -}; - -struct wasm_val_t { - wasm_valkind_t kind; - wasm_val_inner of; -}; - -using wasm_func_callback_t = wasm_trap_t*(*)(const wasm_val_t *args, wasm_val_t *results); - -using wasm_func_callback_with_env_t = wasm_trap_t*(*)(void*, const wasm_val_t *args, wasm_val_t *results); - -using wasm_env_finalizer_t = void(*)(void); - -struct wasm_valtype_t { - wasm_valkind_enum valkind; -}; - -using wasm_mutability_t = uint8_t; - -struct wasm_importtype_t { - wasm_name_t *module; - wasm_name_t *name; - wasm_externtype_t *extern_type; -}; - -struct wasm_limits_t { - uint32_t min; - uint32_t max; -}; - -using wasm_table_size_t = uint32_t; - struct wasmer_module_t { }; @@ -527,223 +406,6 @@ bool wasi_get_imports(wasm_store_t *store, wasi_version_t wasi_get_wasi_version(const wasm_module_t *module); #endif -wasm_config_t *wasm_config_new(); - -void wasm_engine_delete(Option> _wasm_engine_address); - -Box wasm_engine_new_with_config(wasm_config_t *_config_ptr); - -const wasm_name_t *wasm_exporttype_name(const wasm_exporttype_t *et); - -Box wasm_exporttype_new(wasm_name_t *name, wasm_externtype_t *extern_type); - -const wasm_externtype_t *wasm_exporttype_type(const wasm_exporttype_t *et); - -Option> wasm_extern_as_func(wasm_extern_t *extern_ptr); - -Option> wasm_extern_as_global(wasm_extern_t *extern_ptr); - -Option> wasm_extern_as_memory(wasm_extern_t *extern_ptr); - -Option> wasm_extern_as_table(wasm_extern_t *extern_ptr); - -wasm_externkind_t wasm_extern_kind(const wasm_extern_t *e); - -Box wasm_extern_type(const wasm_extern_t *e); - -const wasm_functype_t *wasm_externtype_as_functype(const wasm_externtype_t *et); - -const wasm_functype_t *wasm_externtype_as_functype_const(const wasm_externtype_t *et); - -const wasm_globaltype_t *wasm_externtype_as_globaltype(const wasm_externtype_t *et); - -const wasm_globaltype_t *wasm_externtype_as_globaltype_const(const wasm_externtype_t *et); - -const wasm_memorytype_t *wasm_externtype_as_memorytype(const wasm_externtype_t *et); - -const wasm_memorytype_t *wasm_externtype_as_memorytype_const(const wasm_externtype_t *et); - -const wasm_tabletype_t *wasm_externtype_as_tabletype(const wasm_externtype_t *et); - -const wasm_tabletype_t *wasm_externtype_as_tabletype_const(const wasm_externtype_t *et); - -void wasm_externtype_delete(Option> _et); - -wasm_externkind_t wasm_externtype_kind(const wasm_externtype_t *et); - -Option> wasm_func_as_extern(wasm_func_t *func_ptr); - -wasm_trap_t *wasm_func_call(const wasm_func_t *func, const wasm_val_t *args, wasm_val_t *results); - -void wasm_func_delete(Option> _func); - -Option> wasm_func_new(wasm_store_t *store, - const wasm_functype_t *ft, - wasm_func_callback_t callback); - -Option> wasm_func_new_with_env(wasm_store_t *store, - const wasm_functype_t *ft, - wasm_func_callback_with_env_t callback, - void *env, - wasm_env_finalizer_t finalizer); - -uintptr_t wasm_func_param_arity(const wasm_func_t *func); - -uintptr_t wasm_func_result_arity(const wasm_func_t *func); - -const wasm_externtype_t *wasm_functype_as_externtype(const wasm_functype_t *ft); - -const wasm_externtype_t *wasm_functype_as_externtype_const(const wasm_functype_t *ft); - -Option> wasm_functype_copy(wasm_functype_t *arg); - -void wasm_functype_delete(Option> _ft); - -Option> wasm_functype_new(wasm_valtype_vec_t *params, - wasm_valtype_vec_t *results); - -const wasm_valtype_vec_t *wasm_functype_params(const wasm_functype_t *ft); - -const wasm_valtype_vec_t *wasm_functype_results(const wasm_functype_t *ft); - -Option> wasm_global_as_extern(wasm_global_t *global_ptr); - -Box wasm_global_copy(const wasm_global_t *wasm_global); - -void wasm_global_delete(Option> _global); - -void wasm_global_get(const wasm_global_t *wasm_global, wasm_val_t *out); - -Option> wasm_global_new(wasm_store_t *store_ptr, - const wasm_globaltype_t *gt, - const wasm_val_t *val); - -bool wasm_global_same(const wasm_global_t *wasm_global1, const wasm_global_t *wasm_global2); - -void wasm_global_set(wasm_global_t *wasm_global, const wasm_val_t *val); - -const wasm_externtype_t *wasm_globaltype_as_externtype(const wasm_globaltype_t *gt); - -const wasm_externtype_t *wasm_globaltype_as_externtype_const(const wasm_globaltype_t *gt); - -const wasm_valtype_t *wasm_globaltype_content(const wasm_globaltype_t *globaltype); - -void wasm_globaltype_delete(Option> _globaltype); - -wasm_mutability_t wasm_globaltype_mutability(const wasm_globaltype_t *globaltype); - -Option> wasm_globaltype_new(Option> valtype, - wasm_mutability_t mutability); - -void wasm_importtype_delete(Option> _importtype); - -const wasm_name_t *wasm_importtype_module(const wasm_importtype_t *et); - -const wasm_name_t *wasm_importtype_name(const wasm_importtype_t *et); - -Box wasm_importtype_new(wasm_name_t *module, - wasm_name_t *name, - wasm_externtype_t *extern_type); - -const wasm_externtype_t *wasm_importtype_type(const wasm_importtype_t *et); - -void wasm_instance_delete(Option> _instance); - -void wasm_instance_exports(const wasm_instance_t *instance, wasm_extern_vec_t *out); - -Option> wasm_instance_new(wasm_store_t *store, - const wasm_module_t *module, - const wasm_extern_t *const *imports, - wasm_trap_t **_traps); - -Option> wasm_memory_as_extern(wasm_memory_t *memory_ptr); - -Box wasm_memory_copy(const wasm_memory_t *wasm_memory); - -uint8_t *wasm_memory_data(wasm_memory_t *memory); - -uintptr_t wasm_memory_data_size(const wasm_memory_t *memory); - -void wasm_memory_delete(Option> _memory); - -bool wasm_memory_grow(wasm_memory_t *memory, uint32_t delta); - -Option> wasm_memory_new(wasm_store_t *store_ptr, const wasm_memorytype_t *mt); - -bool wasm_memory_same(const wasm_memory_t *wasm_memory1, const wasm_memory_t *wasm_memory2); - -uint32_t wasm_memory_size(const wasm_memory_t *memory); - -wasm_memorytype_t *wasm_memory_type(const wasm_memory_t *_memory_ptr); - -const wasm_externtype_t *wasm_memorytype_as_externtype(const wasm_memorytype_t *mt); - -const wasm_externtype_t *wasm_memorytype_as_externtype_const(const wasm_memorytype_t *mt); - -void wasm_memorytype_delete(Option> _memorytype); - -const wasm_limits_t *wasm_memorytype_limits(const wasm_memorytype_t *mt); - -Box wasm_memorytype_new(const wasm_limits_t *limits); - -void wasm_module_delete(Option> _module); - -wasm_module_t *wasm_module_deserialize(wasm_store_t *store_ptr, const wasm_byte_vec_t *bytes); - -void wasm_module_exports(const wasm_module_t *module, wasm_exporttype_vec_t *out); - -void wasm_module_imports(const wasm_module_t *module, wasm_importtype_vec_t *out); - -Option> wasm_module_new(wasm_store_t *store_ptr, const wasm_byte_vec_t *bytes); - -void wasm_module_serialize(const wasm_module_t *module, wasm_byte_vec_t *out_ptr); - -void wasm_store_delete(wasm_store_t *wasm_store); - -wasm_store_t *wasm_store_new(wasm_engine_t *wasm_engine_ptr); - -Option> wasm_table_as_extern(wasm_table_t *table_ptr); - -Box wasm_table_copy(const wasm_table_t *wasm_table); - -void wasm_table_delete(Option> _table); - -bool wasm_table_grow(wasm_table_t *_wasm_table, wasm_table_size_t _delta, wasm_ref_t *_init); - -Option> wasm_table_new(wasm_store_t *store_ptr, - const wasm_tabletype_t *tt, - const wasm_ref_t *init); - -bool wasm_table_same(const wasm_table_t *wasm_table1, const wasm_table_t *wasm_table2); - -uintptr_t wasm_table_size(const wasm_table_t *wasm_table); - -const wasm_externtype_t *wasm_tabletype_as_externtype(const wasm_tabletype_t *tt); - -const wasm_externtype_t *wasm_tabletype_as_externtype_const(const wasm_tabletype_t *tt); - -void wasm_tabletype_delete(Option> _tabletype); - -const wasm_valtype_t *wasm_tabletype_element(const wasm_tabletype_t *tabletype); - -const wasm_limits_t *wasm_tabletype_limits(const wasm_tabletype_t *tabletype); - -Box wasm_tabletype_new(Box valtype, const wasm_limits_t *limits); - -void wasm_trap_delete(wasm_trap_t *trap); - -void wasm_trap_message(const wasm_trap_t *trap, wasm_byte_vec_t *out_ptr); - -void wasm_val_copy(wasm_val_t *out_ptr, const wasm_val_t *val); - -void wasm_val_delete(wasm_val_t *val); - -void wasm_valtype_delete(Option> _valtype); - -wasm_valkind_t wasm_valtype_kind(const wasm_valtype_t *valtype); - -Option> wasm_valtype_new(wasm_valkind_t kind); - /// Creates a new Module from the given wasm bytes. /// /// Returns `wasmer_result_t::WASMER_OK` upon success. From ffd1e6eddf0ac32cd631375b0a4633733b66a79d Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Mon, 28 Sep 2020 17:09:44 +0200 Subject: [PATCH 066/281] test(c-api) Split the test suites (deprecated and wasm-c-api). --- lib/c-api/tests/{ => deprecated}/.gitignore | 0 .../tests/{ => deprecated}/CMakeLists.txt | 183 +++--------------- .../tests/{ => deprecated}/assets/README.md | 0 .../assets/emscripten_hello_world.c | 0 .../assets/emscripten_hello_world.wasm | Bin .../tests/{ => deprecated}/assets/exports.rs | 0 .../{ => deprecated}/assets/exports.wasm | Bin .../{ => deprecated}/assets/extended_wasi.rs | 0 .../assets/extended_wasi.wasm | Bin .../{ => deprecated}/assets/hello_wasm.wasm | Bin .../tests/{ => deprecated}/assets/inc.wasm | Bin .../tests/{ => deprecated}/assets/inc.wast | 0 .../tests/{ => deprecated}/assets/qjs.wasm | Bin .../{ => deprecated}/assets/return_hello.rs | 0 .../{ => deprecated}/assets/return_hello.wasm | Bin .../tests/{ => deprecated}/assets/sum.wasm | Bin .../assets/wasm_sample_app.wasm | Bin .../tests/{ => deprecated}/test-context.c | 0 .../test-emscripten-import-object.c | 0 .../{ => deprecated}/test-exported-memory.c | 0 .../tests/{ => deprecated}/test-exports.c | 0 .../tests/{ => deprecated}/test-globals.c | 0 .../test-import-function-callinfo.c | 0 .../{ => deprecated}/test-import-function.c | 0 .../{ => deprecated}/test-import-object.c | 0 .../tests/{ => deprecated}/test-import-trap.c | 0 .../tests/{ => deprecated}/test-imports.c | 0 .../tests/{ => deprecated}/test-instantiate.c | 0 .../tests/{ => deprecated}/test-memory.c | 0 .../{ => deprecated}/test-module-exports.c | 0 .../test-module-import-instantiate.c | 0 .../{ => deprecated}/test-module-imports.c | 0 .../{ => deprecated}/test-module-serialize.c | 0 .../tests/{ => deprecated}/test-module.c | 0 .../tests/{ => deprecated}/test-tables.c | 0 .../tests/{ => deprecated}/test-validate.c | 0 .../test-wasi-import-object.c | 0 ...ime_c_api_tests.rs => deprecated_tests.rs} | 17 +- lib/c-api/tests/wasm_c_api/.gitignore | 15 ++ .../{ => wasm_c_api}/wasm-c-api/.gitignore | 0 .../{ => wasm_c_api}/wasm-c-api/Dockerfile | 0 .../tests/{ => wasm_c_api}/wasm-c-api/LICENSE | 0 .../{ => wasm_c_api}/wasm-c-api/README.md | 0 .../wasm-c-api/example/callback.c | 0 .../wasm-c-api/example/callback.cc | 0 .../wasm-c-api/example/callback.wasm | Bin .../wasm-c-api/example/callback.wat | 0 .../wasm-c-api/example/finalize.c | 0 .../wasm-c-api/example/finalize.cc | 0 .../wasm-c-api/example/finalize.wasm | Bin .../wasm-c-api/example/finalize.wat | 0 .../wasm-c-api/example/global.c | 0 .../wasm-c-api/example/global.cc | 0 .../wasm-c-api/example/global.wasm | Bin .../wasm-c-api/example/global.wat | 0 .../wasm-c-api/example/hello.c | 0 .../wasm-c-api/example/hello.cc | 0 .../wasm-c-api/example/hello.wasm | Bin .../wasm-c-api/example/hello.wat | 0 .../wasm-c-api/example/hostref.c | 0 .../wasm-c-api/example/hostref.cc | 0 .../wasm-c-api/example/hostref.wasm | Bin .../wasm-c-api/example/hostref.wat | 0 .../wasm-c-api/example/memory.c | 0 .../wasm-c-api/example/memory.cc | 0 .../wasm-c-api/example/memory.wasm | Bin .../wasm-c-api/example/memory.wat | 0 .../wasm-c-api/example/multi.c | 0 .../wasm-c-api/example/multi.cc | 0 .../wasm-c-api/example/multi.wasm | Bin .../wasm-c-api/example/multi.wat | 0 .../wasm-c-api/example/reflect.c | 0 .../wasm-c-api/example/reflect.cc | 0 .../wasm-c-api/example/reflect.wasm | Bin .../wasm-c-api/example/reflect.wat | 0 .../wasm-c-api/example/serialize.c | 0 .../wasm-c-api/example/serialize.cc | 0 .../wasm-c-api/example/serialize.wasm | Bin .../wasm-c-api/example/serialize.wat | 0 .../wasm-c-api/example/start.c | 0 .../wasm-c-api/example/start.cc | 0 .../wasm-c-api/example/start.wasm | Bin .../wasm-c-api/example/start.wat | 0 .../wasm-c-api/example/table.c | 0 .../wasm-c-api/example/table.cc | 0 .../wasm-c-api/example/table.wasm | Bin .../wasm-c-api/example/table.wat | 0 .../wasm-c-api/example/threads.c | 0 .../wasm-c-api/example/threads.cc | 0 .../wasm-c-api/example/threads.wasm | Bin .../wasm-c-api/example/threads.wat | 0 .../wasm-c-api/example/trap.c | 0 .../wasm-c-api/example/trap.cc | 0 .../wasm-c-api/example/trap.wasm | Bin .../wasm-c-api/example/trap.wat | 0 .../wasm-c-api/include/wasm.h | 0 .../wasm-c-api/include/wasm.hh | 0 .../0001-BUILD.gn-add-wasm-v8-lowlevel.patch | 0 .../wasm-c-api/src/wasm-bin.cc | 0 .../wasm-c-api/src/wasm-bin.hh | 0 .../{ => wasm_c_api}/wasm-c-api/src/wasm-c.cc | 0 .../wasm-c-api/src/wasm-v8-lowlevel.cc | 0 .../wasm-c-api/src/wasm-v8-lowlevel.hh | 0 .../wasm-c-api/src/wasm-v8.cc | 0 104 files changed, 54 insertions(+), 161 deletions(-) rename lib/c-api/tests/{ => deprecated}/.gitignore (100%) rename lib/c-api/tests/{ => deprecated}/CMakeLists.txt (50%) rename lib/c-api/tests/{ => deprecated}/assets/README.md (100%) rename lib/c-api/tests/{ => deprecated}/assets/emscripten_hello_world.c (100%) rename lib/c-api/tests/{ => deprecated}/assets/emscripten_hello_world.wasm (100%) rename lib/c-api/tests/{ => deprecated}/assets/exports.rs (100%) rename lib/c-api/tests/{ => deprecated}/assets/exports.wasm (100%) rename lib/c-api/tests/{ => deprecated}/assets/extended_wasi.rs (100%) rename lib/c-api/tests/{ => deprecated}/assets/extended_wasi.wasm (100%) rename lib/c-api/tests/{ => deprecated}/assets/hello_wasm.wasm (100%) rename lib/c-api/tests/{ => deprecated}/assets/inc.wasm (100%) rename lib/c-api/tests/{ => deprecated}/assets/inc.wast (100%) rename lib/c-api/tests/{ => deprecated}/assets/qjs.wasm (100%) rename lib/c-api/tests/{ => deprecated}/assets/return_hello.rs (100%) rename lib/c-api/tests/{ => deprecated}/assets/return_hello.wasm (100%) rename lib/c-api/tests/{ => deprecated}/assets/sum.wasm (100%) rename lib/c-api/tests/{ => deprecated}/assets/wasm_sample_app.wasm (100%) rename lib/c-api/tests/{ => deprecated}/test-context.c (100%) rename lib/c-api/tests/{ => deprecated}/test-emscripten-import-object.c (100%) rename lib/c-api/tests/{ => deprecated}/test-exported-memory.c (100%) rename lib/c-api/tests/{ => deprecated}/test-exports.c (100%) rename lib/c-api/tests/{ => deprecated}/test-globals.c (100%) rename lib/c-api/tests/{ => deprecated}/test-import-function-callinfo.c (100%) rename lib/c-api/tests/{ => deprecated}/test-import-function.c (100%) rename lib/c-api/tests/{ => deprecated}/test-import-object.c (100%) rename lib/c-api/tests/{ => deprecated}/test-import-trap.c (100%) rename lib/c-api/tests/{ => deprecated}/test-imports.c (100%) rename lib/c-api/tests/{ => deprecated}/test-instantiate.c (100%) rename lib/c-api/tests/{ => deprecated}/test-memory.c (100%) rename lib/c-api/tests/{ => deprecated}/test-module-exports.c (100%) rename lib/c-api/tests/{ => deprecated}/test-module-import-instantiate.c (100%) rename lib/c-api/tests/{ => deprecated}/test-module-imports.c (100%) rename lib/c-api/tests/{ => deprecated}/test-module-serialize.c (100%) rename lib/c-api/tests/{ => deprecated}/test-module.c (100%) rename lib/c-api/tests/{ => deprecated}/test-tables.c (100%) rename lib/c-api/tests/{ => deprecated}/test-validate.c (100%) rename lib/c-api/tests/{ => deprecated}/test-wasi-import-object.c (100%) rename lib/c-api/tests/{runtime_c_api_tests.rs => deprecated_tests.rs} (80%) create mode 100644 lib/c-api/tests/wasm_c_api/.gitignore rename lib/c-api/tests/{ => wasm_c_api}/wasm-c-api/.gitignore (100%) rename lib/c-api/tests/{ => wasm_c_api}/wasm-c-api/Dockerfile (100%) rename lib/c-api/tests/{ => wasm_c_api}/wasm-c-api/LICENSE (100%) rename lib/c-api/tests/{ => wasm_c_api}/wasm-c-api/README.md (100%) rename lib/c-api/tests/{ => wasm_c_api}/wasm-c-api/example/callback.c (100%) rename lib/c-api/tests/{ => wasm_c_api}/wasm-c-api/example/callback.cc (100%) rename lib/c-api/tests/{ => wasm_c_api}/wasm-c-api/example/callback.wasm (100%) rename lib/c-api/tests/{ => wasm_c_api}/wasm-c-api/example/callback.wat (100%) rename lib/c-api/tests/{ => wasm_c_api}/wasm-c-api/example/finalize.c (100%) rename lib/c-api/tests/{ => wasm_c_api}/wasm-c-api/example/finalize.cc (100%) rename lib/c-api/tests/{ => wasm_c_api}/wasm-c-api/example/finalize.wasm (100%) rename lib/c-api/tests/{ => wasm_c_api}/wasm-c-api/example/finalize.wat (100%) rename lib/c-api/tests/{ => wasm_c_api}/wasm-c-api/example/global.c (100%) rename lib/c-api/tests/{ => wasm_c_api}/wasm-c-api/example/global.cc (100%) rename lib/c-api/tests/{ => wasm_c_api}/wasm-c-api/example/global.wasm (100%) rename lib/c-api/tests/{ => wasm_c_api}/wasm-c-api/example/global.wat (100%) rename lib/c-api/tests/{ => wasm_c_api}/wasm-c-api/example/hello.c (100%) rename lib/c-api/tests/{ => wasm_c_api}/wasm-c-api/example/hello.cc (100%) rename lib/c-api/tests/{ => wasm_c_api}/wasm-c-api/example/hello.wasm (100%) rename lib/c-api/tests/{ => wasm_c_api}/wasm-c-api/example/hello.wat (100%) rename lib/c-api/tests/{ => wasm_c_api}/wasm-c-api/example/hostref.c (100%) rename lib/c-api/tests/{ => wasm_c_api}/wasm-c-api/example/hostref.cc (100%) rename lib/c-api/tests/{ => wasm_c_api}/wasm-c-api/example/hostref.wasm (100%) rename lib/c-api/tests/{ => wasm_c_api}/wasm-c-api/example/hostref.wat (100%) rename lib/c-api/tests/{ => wasm_c_api}/wasm-c-api/example/memory.c (100%) rename lib/c-api/tests/{ => wasm_c_api}/wasm-c-api/example/memory.cc (100%) rename lib/c-api/tests/{ => wasm_c_api}/wasm-c-api/example/memory.wasm (100%) rename lib/c-api/tests/{ => wasm_c_api}/wasm-c-api/example/memory.wat (100%) rename lib/c-api/tests/{ => wasm_c_api}/wasm-c-api/example/multi.c (100%) rename lib/c-api/tests/{ => wasm_c_api}/wasm-c-api/example/multi.cc (100%) rename lib/c-api/tests/{ => wasm_c_api}/wasm-c-api/example/multi.wasm (100%) rename lib/c-api/tests/{ => wasm_c_api}/wasm-c-api/example/multi.wat (100%) rename lib/c-api/tests/{ => wasm_c_api}/wasm-c-api/example/reflect.c (100%) rename lib/c-api/tests/{ => wasm_c_api}/wasm-c-api/example/reflect.cc (100%) rename lib/c-api/tests/{ => wasm_c_api}/wasm-c-api/example/reflect.wasm (100%) rename lib/c-api/tests/{ => wasm_c_api}/wasm-c-api/example/reflect.wat (100%) rename lib/c-api/tests/{ => wasm_c_api}/wasm-c-api/example/serialize.c (100%) rename lib/c-api/tests/{ => wasm_c_api}/wasm-c-api/example/serialize.cc (100%) rename lib/c-api/tests/{ => wasm_c_api}/wasm-c-api/example/serialize.wasm (100%) rename lib/c-api/tests/{ => wasm_c_api}/wasm-c-api/example/serialize.wat (100%) rename lib/c-api/tests/{ => wasm_c_api}/wasm-c-api/example/start.c (100%) rename lib/c-api/tests/{ => wasm_c_api}/wasm-c-api/example/start.cc (100%) rename lib/c-api/tests/{ => wasm_c_api}/wasm-c-api/example/start.wasm (100%) rename lib/c-api/tests/{ => wasm_c_api}/wasm-c-api/example/start.wat (100%) rename lib/c-api/tests/{ => wasm_c_api}/wasm-c-api/example/table.c (100%) rename lib/c-api/tests/{ => wasm_c_api}/wasm-c-api/example/table.cc (100%) rename lib/c-api/tests/{ => wasm_c_api}/wasm-c-api/example/table.wasm (100%) rename lib/c-api/tests/{ => wasm_c_api}/wasm-c-api/example/table.wat (100%) rename lib/c-api/tests/{ => wasm_c_api}/wasm-c-api/example/threads.c (100%) rename lib/c-api/tests/{ => wasm_c_api}/wasm-c-api/example/threads.cc (100%) rename lib/c-api/tests/{ => wasm_c_api}/wasm-c-api/example/threads.wasm (100%) rename lib/c-api/tests/{ => wasm_c_api}/wasm-c-api/example/threads.wat (100%) rename lib/c-api/tests/{ => wasm_c_api}/wasm-c-api/example/trap.c (100%) rename lib/c-api/tests/{ => wasm_c_api}/wasm-c-api/example/trap.cc (100%) rename lib/c-api/tests/{ => wasm_c_api}/wasm-c-api/example/trap.wasm (100%) rename lib/c-api/tests/{ => wasm_c_api}/wasm-c-api/example/trap.wat (100%) rename lib/c-api/tests/{ => wasm_c_api}/wasm-c-api/include/wasm.h (100%) rename lib/c-api/tests/{ => wasm_c_api}/wasm-c-api/include/wasm.hh (100%) rename lib/c-api/tests/{ => wasm_c_api}/wasm-c-api/patch/0001-BUILD.gn-add-wasm-v8-lowlevel.patch (100%) rename lib/c-api/tests/{ => wasm_c_api}/wasm-c-api/src/wasm-bin.cc (100%) rename lib/c-api/tests/{ => wasm_c_api}/wasm-c-api/src/wasm-bin.hh (100%) rename lib/c-api/tests/{ => wasm_c_api}/wasm-c-api/src/wasm-c.cc (100%) rename lib/c-api/tests/{ => wasm_c_api}/wasm-c-api/src/wasm-v8-lowlevel.cc (100%) rename lib/c-api/tests/{ => wasm_c_api}/wasm-c-api/src/wasm-v8-lowlevel.hh (100%) rename lib/c-api/tests/{ => wasm_c_api}/wasm-c-api/src/wasm-v8.cc (100%) diff --git a/lib/c-api/tests/.gitignore b/lib/c-api/tests/deprecated/.gitignore similarity index 100% rename from lib/c-api/tests/.gitignore rename to lib/c-api/tests/deprecated/.gitignore diff --git a/lib/c-api/tests/CMakeLists.txt b/lib/c-api/tests/deprecated/CMakeLists.txt similarity index 50% rename from lib/c-api/tests/CMakeLists.txt rename to lib/c-api/tests/deprecated/CMakeLists.txt index 728e11181..9cd2e5374 100644 --- a/lib/c-api/tests/CMakeLists.txt +++ b/lib/c-api/tests/deprecated/CMakeLists.txt @@ -1,40 +1,22 @@ cmake_minimum_required (VERSION 2.6) project (WasmerRuntimeCApiTests) +add_executable(test-context test-context.c) add_executable(test-exported-memory test-exported-memory.c) add_executable(test-exports test-exports.c) add_executable(test-globals test-globals.c) +add_executable(test-import-object test-import-object.c) add_executable(test-import-trap test-import-trap.c) add_executable(test-imports test-imports.c) -add_executable(test-import-object test-import-object.c) add_executable(test-instantiate test-instantiate.c) add_executable(test-memory test-memory.c) add_executable(test-module test-module.c) add_executable(test-module-exports test-module-exports.c) +add_executable(test-module-import-instantiate test-module-import-instantiate.c) add_executable(test-module-imports test-module-imports.c) add_executable(test-module-serialize test-module-serialize.c) add_executable(test-tables test-tables.c) add_executable(test-validate test-validate.c) -add_executable(test-context test-context.c) -add_executable(test-module-import-instantiate test-module-import-instantiate.c) - -# Wasm C API tests -add_executable(wasm-c-api-callback wasm-c-api/example/callback.c) -#add_executable(wasm-c-api-finalize wasm-c-api/example/finalize.c) -add_executable(wasm-c-api-global wasm-c-api/example/global.c) -add_executable(wasm-c-api-hello wasm-c-api/example/hello.c) -#add_executable(wasm-c-api-hostref wasm-c-api/example/hostref.c) -add_executable(wasm-c-api-memory wasm-c-api/example/memory.c) -#add_executable(wasm-c-api-multi wasm-c-api/example/multi.c) -add_executable(wasm-c-api-reflect wasm-c-api/example/reflect.c) -add_executable(wasm-c-api-serialize wasm-c-api/example/serialize.c) -#add_executable(wasm-c-api-start wasm-c-api/example/start.c) -#add_executable(wasm-c-api-table wasm-c-api/example/table.c) -#add_executable(wasm-c-api-threads wasm-c-api/example/threads.c) -#add_executable(wasm-c-api-trap wasm-c-api/example/trap.c) - -# Custom Wasm C API tests -add_executable(wasm-c-api-wasi wasm-c-api-wasi.c) if (DEFINED WASI_TESTS) add_executable(test-wasi-import-object test-wasi-import-object.c) @@ -44,12 +26,11 @@ if (DEFINED EMSCRIPTEN_TESTS) add_executable(test-emscripten-import-object test-emscripten-import-object.c) endif() -include_directories(wasm-c-api/include) -include_directories(..) +include_directories(../../) find_library( WASMER_LIB NAMES libwasmer_c_api.dylib libwasmer_c_api.so wasmer_c_api.dll - PATHS ${CMAKE_SOURCE_DIR}/../../../target/release/ + PATHS ${CMAKE_SOURCE_DIR}/../../../../target/release/ ) if(NOT WASMER_LIB) @@ -68,6 +49,10 @@ set( "/WX" > ) +target_link_libraries(test-context general ${WASMER_LIB}) +target_compile_options(test-context PRIVATE ${COMPILER_OPTIONS}) +add_test(test-context test-context) + target_link_libraries(test-exported-memory general ${WASMER_LIB}) target_compile_options(test-exported-memory PRIVATE ${COMPILER_OPTIONS}) add_test(test-exported-memory test-exported-memory) @@ -80,6 +65,10 @@ target_link_libraries(test-globals general ${WASMER_LIB}) target_compile_options(test-globals PRIVATE ${COMPILER_OPTIONS}) add_test(test-globals test-globals) +target_link_libraries(test-import-object general ${WASMER_LIB}) +target_compile_options(test-import-object PRIVATE ${COMPILER_OPTIONS}) +add_test(test-import-object test-import-object) + # trampoline functionality not yet implemented #target_link_libraries(test-import-function general ${WASMER_LIB}) #target_compile_options(test-import-function PRIVATE ${COMPILER_OPTIONS}) @@ -89,28 +78,6 @@ target_link_libraries(test-import-trap general ${WASMER_LIB}) target_compile_options(test-import-trap PRIVATE ${COMPILER_OPTIONS}) add_test(test-import-trap test-import-trap) -target_link_libraries(test-imports general ${WASMER_LIB}) -target_compile_options(test-imports PRIVATE ${COMPILER_OPTIONS}) -add_test(test-imports test-imports) - -target_link_libraries(test-import-object general ${WASMER_LIB}) -target_compile_options(test-import-object PRIVATE ${COMPILER_OPTIONS}) -add_test(test-import-object test-import-object) - - -if (DEFINED WASI_TESTS) - target_link_libraries(test-wasi-import-object general ${WASMER_LIB}) - target_compile_options(test-wasi-import-object PRIVATE ${COMPILER_OPTIONS}) - # TODO: reenable this test - #add_test(test-wasi-import-object test-wasi-import-object) -endif() - -if (DEFINED EMSCRIPTEN_TESTS) - target_link_libraries(test-emscripten-import-object general ${WASMER_LIB}) - target_compile_options(test-emscripten-import-object PRIVATE ${COMPILER_OPTIONS}) - add_test(test-emscripten-import-object test-emscripten-import-object) -endif() - target_link_libraries(test-instantiate general ${WASMER_LIB}) target_compile_options(test-instantiate PRIVATE ${COMPILER_OPTIONS}) add_test(test-instantiate test-instantiate) @@ -131,6 +98,14 @@ target_link_libraries(test-module-imports general ${WASMER_LIB}) target_compile_options(test-module-imports PRIVATE ${COMPILER_OPTIONS}) add_test(test-module-imports test-module-imports) +target_link_libraries(test-module-import-instantiate general ${WASMER_LIB}) +target_compile_options(test-module-import-instantiate PRIVATE ${COMPILER_OPTIONS}) +add_test(test-module-import-instantiate test-module-import-instantiate) + +target_link_libraries(test-imports general ${WASMER_LIB}) +target_compile_options(test-imports PRIVATE ${COMPILER_OPTIONS}) +add_test(test-imports test-imports) + target_link_libraries(test-module-serialize general ${WASMER_LIB}) target_compile_options(test-module-serialize PRIVATE ${COMPILER_OPTIONS}) add_test(test-module-serialize test-module-serialize) @@ -143,109 +118,15 @@ target_link_libraries(test-validate general ${WASMER_LIB}) target_compile_options(test-validate PRIVATE ${COMPILER_OPTIONS}) add_test(test-validate test-validate) -target_link_libraries(test-context general ${WASMER_LIB}) -target_compile_options(test-context PRIVATE ${COMPILER_OPTIONS}) -add_test(test-context test-context) - -target_link_libraries(test-module-import-instantiate general ${WASMER_LIB}) -target_compile_options(test-module-import-instantiate PRIVATE ${COMPILER_OPTIONS}) -add_test(test-module-import-instantiate test-module-import-instantiate) - -# Wasm C API tests - -target_link_libraries(wasm-c-api-callback general ${WASMER_LIB}) -target_compile_options(wasm-c-api-callback PRIVATE ${COMPILER_OPTIONS}) -add_test(NAME wasm-c-api-callback - COMMAND wasm-c-api-callback - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/wasm-c-api/example/ -) - -#target_link_libraries(wasm-c-api-finalize general ${WASMER_LIB}) -#target_compile_options(wasm-c-api-finalize PRIVATE ${COMPILER_OPTIONS}) -#add_test(NAME wasm-c-api-finalize -# COMMAND wasm-c-api-finalize -# WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/wasm-c-api/example/ -#) - -target_link_libraries(wasm-c-api-global general ${WASMER_LIB}) -target_compile_options(wasm-c-api-global PRIVATE ${COMPILER_OPTIONS}) -add_test(NAME wasm-c-api-global - COMMAND wasm-c-api-global - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/wasm-c-api/example/ -) - -target_link_libraries(wasm-c-api-hello general ${WASMER_LIB}) -target_compile_options(wasm-c-api-hello PRIVATE ${COMPILER_OPTIONS}) -add_test(NAME wasm-c-api-hello - COMMAND wasm-c-api-hello - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/wasm-c-api/example/ -) - -#target_link_libraries(wasm-c-api-hostref general ${WASMER_LIB}) -#target_compile_options(wasm-c-api-hostref PRIVATE ${COMPILER_OPTIONS}) -#add_test(NAME wasm-c-api-hostref -# COMMAND wasm-c-api-hostref -# WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/wasm-c-api/example/ -#) - -target_link_libraries(wasm-c-api-memory general ${WASMER_LIB}) -target_compile_options(wasm-c-api-memory PRIVATE ${COMPILER_OPTIONS}) -add_test(NAME wasm-c-api-memory - COMMAND wasm-c-api-memory - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/wasm-c-api/example/ -) - -#target_link_libraries(wasm-c-api-multi general ${WASMER_LIB}) -#target_compile_options(wasm-c-api-multi PRIVATE ${COMPILER_OPTIONS}) -#add_test(NAME wasm-c-api-multi -# COMMAND wasm-c-api-multi -# WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/wasm-c-api/example/ -#) - -target_link_libraries(wasm-c-api-reflect general ${WASMER_LIB}) -target_compile_options(wasm-c-api-reflect PRIVATE ${COMPILER_OPTIONS}) -add_test(NAME wasm-c-api-reflect - COMMAND wasm-c-api-reflect - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/wasm-c-api/example/ -) - -target_link_libraries(wasm-c-api-serialize general ${WASMER_LIB}) -target_compile_options(wasm-c-api-serialize PRIVATE ${COMPILER_OPTIONS}) -add_test(NAME wasm-c-api-serialize - COMMAND wasm-c-api-serialize - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/wasm-c-api/example/ -) - -#target_link_libraries(wasm-c-api-start general ${WASMER_LIB}) -#target_compile_options(wasm-c-api-start PRIVATE ${COMPILER_OPTIONS}) -#add_test(NAME wasm-c-api-start -# COMMAND wasm-c-api-start -# WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/wasm-c-api/example/ -#) - -#target_link_libraries(wasm-c-api-table general ${WASMER_LIB}) -#target_compile_options(wasm-c-api-table PRIVATE ${COMPILER_OPTIONS}) -#add_test(NAME wasm-c-api-table -# COMMAND wasm-c-api-table -# WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/wasm-c-api/example/ -#) - -#target_link_libraries(wasm-c-api-threads general ${WASMER_LIB}) -#target_compile_options(wasm-c-api-threads PRIVATE ${COMPILER_OPTIONS}) -#add_test(NAME wasm-c-api-threads -# COMMAND wasm-c-api-threads -# WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/wasm-c-api/example/ -#) - -#target_link_libraries(wasm-c-api-trap general ${WASMER_LIB}) -#target_compile_options(wasm-c-api-trap PRIVATE ${COMPILER_OPTIONS}) -#add_test(NAME wasm-c-api-trap -# COMMAND wasm-c-api-trap -# WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/wasm-c-api/example/ -#) - -set_property(TARGET wasm-c-api-wasi PROPERTY C_STANDARD 11) -target_link_libraries(wasm-c-api-wasi general ${WASMER_LIB}) -target_compile_options(wasm-c-api-wasi PRIVATE ${COMPILER_OPTIONS}) -add_test(wasm-c-api-wasi wasm-c-api-wasi) +if (DEFINED WASI_TESTS) + target_link_libraries(test-wasi-import-object general ${WASMER_LIB}) + target_compile_options(test-wasi-import-object PRIVATE ${COMPILER_OPTIONS}) + # TODO: reenable this test + #add_test(test-wasi-import-object test-wasi-import-object) +endif() +if (DEFINED EMSCRIPTEN_TESTS) + target_link_libraries(test-emscripten-import-object general ${WASMER_LIB}) + target_compile_options(test-emscripten-import-object PRIVATE ${COMPILER_OPTIONS}) + add_test(test-emscripten-import-object test-emscripten-import-object) +endif() diff --git a/lib/c-api/tests/assets/README.md b/lib/c-api/tests/deprecated/assets/README.md similarity index 100% rename from lib/c-api/tests/assets/README.md rename to lib/c-api/tests/deprecated/assets/README.md diff --git a/lib/c-api/tests/assets/emscripten_hello_world.c b/lib/c-api/tests/deprecated/assets/emscripten_hello_world.c similarity index 100% rename from lib/c-api/tests/assets/emscripten_hello_world.c rename to lib/c-api/tests/deprecated/assets/emscripten_hello_world.c diff --git a/lib/c-api/tests/assets/emscripten_hello_world.wasm b/lib/c-api/tests/deprecated/assets/emscripten_hello_world.wasm similarity index 100% rename from lib/c-api/tests/assets/emscripten_hello_world.wasm rename to lib/c-api/tests/deprecated/assets/emscripten_hello_world.wasm diff --git a/lib/c-api/tests/assets/exports.rs b/lib/c-api/tests/deprecated/assets/exports.rs similarity index 100% rename from lib/c-api/tests/assets/exports.rs rename to lib/c-api/tests/deprecated/assets/exports.rs diff --git a/lib/c-api/tests/assets/exports.wasm b/lib/c-api/tests/deprecated/assets/exports.wasm similarity index 100% rename from lib/c-api/tests/assets/exports.wasm rename to lib/c-api/tests/deprecated/assets/exports.wasm diff --git a/lib/c-api/tests/assets/extended_wasi.rs b/lib/c-api/tests/deprecated/assets/extended_wasi.rs similarity index 100% rename from lib/c-api/tests/assets/extended_wasi.rs rename to lib/c-api/tests/deprecated/assets/extended_wasi.rs diff --git a/lib/c-api/tests/assets/extended_wasi.wasm b/lib/c-api/tests/deprecated/assets/extended_wasi.wasm similarity index 100% rename from lib/c-api/tests/assets/extended_wasi.wasm rename to lib/c-api/tests/deprecated/assets/extended_wasi.wasm diff --git a/lib/c-api/tests/assets/hello_wasm.wasm b/lib/c-api/tests/deprecated/assets/hello_wasm.wasm similarity index 100% rename from lib/c-api/tests/assets/hello_wasm.wasm rename to lib/c-api/tests/deprecated/assets/hello_wasm.wasm diff --git a/lib/c-api/tests/assets/inc.wasm b/lib/c-api/tests/deprecated/assets/inc.wasm similarity index 100% rename from lib/c-api/tests/assets/inc.wasm rename to lib/c-api/tests/deprecated/assets/inc.wasm diff --git a/lib/c-api/tests/assets/inc.wast b/lib/c-api/tests/deprecated/assets/inc.wast similarity index 100% rename from lib/c-api/tests/assets/inc.wast rename to lib/c-api/tests/deprecated/assets/inc.wast diff --git a/lib/c-api/tests/assets/qjs.wasm b/lib/c-api/tests/deprecated/assets/qjs.wasm similarity index 100% rename from lib/c-api/tests/assets/qjs.wasm rename to lib/c-api/tests/deprecated/assets/qjs.wasm diff --git a/lib/c-api/tests/assets/return_hello.rs b/lib/c-api/tests/deprecated/assets/return_hello.rs similarity index 100% rename from lib/c-api/tests/assets/return_hello.rs rename to lib/c-api/tests/deprecated/assets/return_hello.rs diff --git a/lib/c-api/tests/assets/return_hello.wasm b/lib/c-api/tests/deprecated/assets/return_hello.wasm similarity index 100% rename from lib/c-api/tests/assets/return_hello.wasm rename to lib/c-api/tests/deprecated/assets/return_hello.wasm diff --git a/lib/c-api/tests/assets/sum.wasm b/lib/c-api/tests/deprecated/assets/sum.wasm similarity index 100% rename from lib/c-api/tests/assets/sum.wasm rename to lib/c-api/tests/deprecated/assets/sum.wasm diff --git a/lib/c-api/tests/assets/wasm_sample_app.wasm b/lib/c-api/tests/deprecated/assets/wasm_sample_app.wasm similarity index 100% rename from lib/c-api/tests/assets/wasm_sample_app.wasm rename to lib/c-api/tests/deprecated/assets/wasm_sample_app.wasm diff --git a/lib/c-api/tests/test-context.c b/lib/c-api/tests/deprecated/test-context.c similarity index 100% rename from lib/c-api/tests/test-context.c rename to lib/c-api/tests/deprecated/test-context.c diff --git a/lib/c-api/tests/test-emscripten-import-object.c b/lib/c-api/tests/deprecated/test-emscripten-import-object.c similarity index 100% rename from lib/c-api/tests/test-emscripten-import-object.c rename to lib/c-api/tests/deprecated/test-emscripten-import-object.c diff --git a/lib/c-api/tests/test-exported-memory.c b/lib/c-api/tests/deprecated/test-exported-memory.c similarity index 100% rename from lib/c-api/tests/test-exported-memory.c rename to lib/c-api/tests/deprecated/test-exported-memory.c diff --git a/lib/c-api/tests/test-exports.c b/lib/c-api/tests/deprecated/test-exports.c similarity index 100% rename from lib/c-api/tests/test-exports.c rename to lib/c-api/tests/deprecated/test-exports.c diff --git a/lib/c-api/tests/test-globals.c b/lib/c-api/tests/deprecated/test-globals.c similarity index 100% rename from lib/c-api/tests/test-globals.c rename to lib/c-api/tests/deprecated/test-globals.c diff --git a/lib/c-api/tests/test-import-function-callinfo.c b/lib/c-api/tests/deprecated/test-import-function-callinfo.c similarity index 100% rename from lib/c-api/tests/test-import-function-callinfo.c rename to lib/c-api/tests/deprecated/test-import-function-callinfo.c diff --git a/lib/c-api/tests/test-import-function.c b/lib/c-api/tests/deprecated/test-import-function.c similarity index 100% rename from lib/c-api/tests/test-import-function.c rename to lib/c-api/tests/deprecated/test-import-function.c diff --git a/lib/c-api/tests/test-import-object.c b/lib/c-api/tests/deprecated/test-import-object.c similarity index 100% rename from lib/c-api/tests/test-import-object.c rename to lib/c-api/tests/deprecated/test-import-object.c diff --git a/lib/c-api/tests/test-import-trap.c b/lib/c-api/tests/deprecated/test-import-trap.c similarity index 100% rename from lib/c-api/tests/test-import-trap.c rename to lib/c-api/tests/deprecated/test-import-trap.c diff --git a/lib/c-api/tests/test-imports.c b/lib/c-api/tests/deprecated/test-imports.c similarity index 100% rename from lib/c-api/tests/test-imports.c rename to lib/c-api/tests/deprecated/test-imports.c diff --git a/lib/c-api/tests/test-instantiate.c b/lib/c-api/tests/deprecated/test-instantiate.c similarity index 100% rename from lib/c-api/tests/test-instantiate.c rename to lib/c-api/tests/deprecated/test-instantiate.c diff --git a/lib/c-api/tests/test-memory.c b/lib/c-api/tests/deprecated/test-memory.c similarity index 100% rename from lib/c-api/tests/test-memory.c rename to lib/c-api/tests/deprecated/test-memory.c diff --git a/lib/c-api/tests/test-module-exports.c b/lib/c-api/tests/deprecated/test-module-exports.c similarity index 100% rename from lib/c-api/tests/test-module-exports.c rename to lib/c-api/tests/deprecated/test-module-exports.c diff --git a/lib/c-api/tests/test-module-import-instantiate.c b/lib/c-api/tests/deprecated/test-module-import-instantiate.c similarity index 100% rename from lib/c-api/tests/test-module-import-instantiate.c rename to lib/c-api/tests/deprecated/test-module-import-instantiate.c diff --git a/lib/c-api/tests/test-module-imports.c b/lib/c-api/tests/deprecated/test-module-imports.c similarity index 100% rename from lib/c-api/tests/test-module-imports.c rename to lib/c-api/tests/deprecated/test-module-imports.c diff --git a/lib/c-api/tests/test-module-serialize.c b/lib/c-api/tests/deprecated/test-module-serialize.c similarity index 100% rename from lib/c-api/tests/test-module-serialize.c rename to lib/c-api/tests/deprecated/test-module-serialize.c diff --git a/lib/c-api/tests/test-module.c b/lib/c-api/tests/deprecated/test-module.c similarity index 100% rename from lib/c-api/tests/test-module.c rename to lib/c-api/tests/deprecated/test-module.c diff --git a/lib/c-api/tests/test-tables.c b/lib/c-api/tests/deprecated/test-tables.c similarity index 100% rename from lib/c-api/tests/test-tables.c rename to lib/c-api/tests/deprecated/test-tables.c diff --git a/lib/c-api/tests/test-validate.c b/lib/c-api/tests/deprecated/test-validate.c similarity index 100% rename from lib/c-api/tests/test-validate.c rename to lib/c-api/tests/deprecated/test-validate.c diff --git a/lib/c-api/tests/test-wasi-import-object.c b/lib/c-api/tests/deprecated/test-wasi-import-object.c similarity index 100% rename from lib/c-api/tests/test-wasi-import-object.c rename to lib/c-api/tests/deprecated/test-wasi-import-object.c diff --git a/lib/c-api/tests/runtime_c_api_tests.rs b/lib/c-api/tests/deprecated_tests.rs similarity index 80% rename from lib/c-api/tests/runtime_c_api_tests.rs rename to lib/c-api/tests/deprecated_tests.rs index e6e29863b..68cf7111d 100644 --- a/lib/c-api/tests/runtime_c_api_tests.rs +++ b/lib/c-api/tests/deprecated_tests.rs @@ -1,8 +1,8 @@ use std::process::Command; #[test] -fn test_c_api() { - let project_tests_dir = concat!(env!("CARGO_MANIFEST_DIR"), "/tests"); +fn test_deprecated_c_api() { + let project_tests_dir = concat!(env!("CARGO_MANIFEST_DIR"), "/tests/deprecated/"); let cmake_args = vec![ ".", @@ -35,18 +35,16 @@ fn run_command(command_str: &str, dir: &str, args: Vec<&str>) { match result { Ok(r) => { - println!("output:"); + println!("> Output:"); if let Some(code) = r.status.code() { - println!("status: {}", code); + println!("> Status: {}", code); } else { - println!("status: None"); + println!("> Status: None"); } - println!("stdout:"); - println!("{}", String::from_utf8_lossy(&r.stdout[..])); - println!("stderr:"); - println!("{}", String::from_utf8_lossy(&r.stderr[..])); + println!("> Stdout: {}", String::from_utf8_lossy(&r.stdout[..])); + println!("> Stderr: {}", String::from_utf8_lossy(&r.stderr[..])); if r.status.success() { assert!(true) @@ -54,7 +52,6 @@ fn run_command(command_str: &str, dir: &str, args: Vec<&str>) { panic!("Command failed with exit status: {:?}", r.status); } } - Err(e) => panic!("Command failed: {}", e), } } diff --git a/lib/c-api/tests/wasm_c_api/.gitignore b/lib/c-api/tests/wasm_c_api/.gitignore new file mode 100644 index 000000000..a0b8069bc --- /dev/null +++ b/lib/c-api/tests/wasm_c_api/.gitignore @@ -0,0 +1,15 @@ +CMakeLists.txt.user +CMakeCache.txt +CMakeFiles +CMakeScripts +Testing +Makefile +cmake_install.cmake +install_manifest.txt +compile_commands.json +CTestTestfile.cmake +_deps +rust-build + +# Unignore files ending with `.c` (i.e. `wasm-c-api-wasi.c`) +!*.c \ No newline at end of file diff --git a/lib/c-api/tests/wasm-c-api/.gitignore b/lib/c-api/tests/wasm_c_api/wasm-c-api/.gitignore similarity index 100% rename from lib/c-api/tests/wasm-c-api/.gitignore rename to lib/c-api/tests/wasm_c_api/wasm-c-api/.gitignore diff --git a/lib/c-api/tests/wasm-c-api/Dockerfile b/lib/c-api/tests/wasm_c_api/wasm-c-api/Dockerfile similarity index 100% rename from lib/c-api/tests/wasm-c-api/Dockerfile rename to lib/c-api/tests/wasm_c_api/wasm-c-api/Dockerfile diff --git a/lib/c-api/tests/wasm-c-api/LICENSE b/lib/c-api/tests/wasm_c_api/wasm-c-api/LICENSE similarity index 100% rename from lib/c-api/tests/wasm-c-api/LICENSE rename to lib/c-api/tests/wasm_c_api/wasm-c-api/LICENSE diff --git a/lib/c-api/tests/wasm-c-api/README.md b/lib/c-api/tests/wasm_c_api/wasm-c-api/README.md similarity index 100% rename from lib/c-api/tests/wasm-c-api/README.md rename to lib/c-api/tests/wasm_c_api/wasm-c-api/README.md diff --git a/lib/c-api/tests/wasm-c-api/example/callback.c b/lib/c-api/tests/wasm_c_api/wasm-c-api/example/callback.c similarity index 100% rename from lib/c-api/tests/wasm-c-api/example/callback.c rename to lib/c-api/tests/wasm_c_api/wasm-c-api/example/callback.c diff --git a/lib/c-api/tests/wasm-c-api/example/callback.cc b/lib/c-api/tests/wasm_c_api/wasm-c-api/example/callback.cc similarity index 100% rename from lib/c-api/tests/wasm-c-api/example/callback.cc rename to lib/c-api/tests/wasm_c_api/wasm-c-api/example/callback.cc diff --git a/lib/c-api/tests/wasm-c-api/example/callback.wasm b/lib/c-api/tests/wasm_c_api/wasm-c-api/example/callback.wasm similarity index 100% rename from lib/c-api/tests/wasm-c-api/example/callback.wasm rename to lib/c-api/tests/wasm_c_api/wasm-c-api/example/callback.wasm diff --git a/lib/c-api/tests/wasm-c-api/example/callback.wat b/lib/c-api/tests/wasm_c_api/wasm-c-api/example/callback.wat similarity index 100% rename from lib/c-api/tests/wasm-c-api/example/callback.wat rename to lib/c-api/tests/wasm_c_api/wasm-c-api/example/callback.wat diff --git a/lib/c-api/tests/wasm-c-api/example/finalize.c b/lib/c-api/tests/wasm_c_api/wasm-c-api/example/finalize.c similarity index 100% rename from lib/c-api/tests/wasm-c-api/example/finalize.c rename to lib/c-api/tests/wasm_c_api/wasm-c-api/example/finalize.c diff --git a/lib/c-api/tests/wasm-c-api/example/finalize.cc b/lib/c-api/tests/wasm_c_api/wasm-c-api/example/finalize.cc similarity index 100% rename from lib/c-api/tests/wasm-c-api/example/finalize.cc rename to lib/c-api/tests/wasm_c_api/wasm-c-api/example/finalize.cc diff --git a/lib/c-api/tests/wasm-c-api/example/finalize.wasm b/lib/c-api/tests/wasm_c_api/wasm-c-api/example/finalize.wasm similarity index 100% rename from lib/c-api/tests/wasm-c-api/example/finalize.wasm rename to lib/c-api/tests/wasm_c_api/wasm-c-api/example/finalize.wasm diff --git a/lib/c-api/tests/wasm-c-api/example/finalize.wat b/lib/c-api/tests/wasm_c_api/wasm-c-api/example/finalize.wat similarity index 100% rename from lib/c-api/tests/wasm-c-api/example/finalize.wat rename to lib/c-api/tests/wasm_c_api/wasm-c-api/example/finalize.wat diff --git a/lib/c-api/tests/wasm-c-api/example/global.c b/lib/c-api/tests/wasm_c_api/wasm-c-api/example/global.c similarity index 100% rename from lib/c-api/tests/wasm-c-api/example/global.c rename to lib/c-api/tests/wasm_c_api/wasm-c-api/example/global.c diff --git a/lib/c-api/tests/wasm-c-api/example/global.cc b/lib/c-api/tests/wasm_c_api/wasm-c-api/example/global.cc similarity index 100% rename from lib/c-api/tests/wasm-c-api/example/global.cc rename to lib/c-api/tests/wasm_c_api/wasm-c-api/example/global.cc diff --git a/lib/c-api/tests/wasm-c-api/example/global.wasm b/lib/c-api/tests/wasm_c_api/wasm-c-api/example/global.wasm similarity index 100% rename from lib/c-api/tests/wasm-c-api/example/global.wasm rename to lib/c-api/tests/wasm_c_api/wasm-c-api/example/global.wasm diff --git a/lib/c-api/tests/wasm-c-api/example/global.wat b/lib/c-api/tests/wasm_c_api/wasm-c-api/example/global.wat similarity index 100% rename from lib/c-api/tests/wasm-c-api/example/global.wat rename to lib/c-api/tests/wasm_c_api/wasm-c-api/example/global.wat diff --git a/lib/c-api/tests/wasm-c-api/example/hello.c b/lib/c-api/tests/wasm_c_api/wasm-c-api/example/hello.c similarity index 100% rename from lib/c-api/tests/wasm-c-api/example/hello.c rename to lib/c-api/tests/wasm_c_api/wasm-c-api/example/hello.c diff --git a/lib/c-api/tests/wasm-c-api/example/hello.cc b/lib/c-api/tests/wasm_c_api/wasm-c-api/example/hello.cc similarity index 100% rename from lib/c-api/tests/wasm-c-api/example/hello.cc rename to lib/c-api/tests/wasm_c_api/wasm-c-api/example/hello.cc diff --git a/lib/c-api/tests/wasm-c-api/example/hello.wasm b/lib/c-api/tests/wasm_c_api/wasm-c-api/example/hello.wasm similarity index 100% rename from lib/c-api/tests/wasm-c-api/example/hello.wasm rename to lib/c-api/tests/wasm_c_api/wasm-c-api/example/hello.wasm diff --git a/lib/c-api/tests/wasm-c-api/example/hello.wat b/lib/c-api/tests/wasm_c_api/wasm-c-api/example/hello.wat similarity index 100% rename from lib/c-api/tests/wasm-c-api/example/hello.wat rename to lib/c-api/tests/wasm_c_api/wasm-c-api/example/hello.wat diff --git a/lib/c-api/tests/wasm-c-api/example/hostref.c b/lib/c-api/tests/wasm_c_api/wasm-c-api/example/hostref.c similarity index 100% rename from lib/c-api/tests/wasm-c-api/example/hostref.c rename to lib/c-api/tests/wasm_c_api/wasm-c-api/example/hostref.c diff --git a/lib/c-api/tests/wasm-c-api/example/hostref.cc b/lib/c-api/tests/wasm_c_api/wasm-c-api/example/hostref.cc similarity index 100% rename from lib/c-api/tests/wasm-c-api/example/hostref.cc rename to lib/c-api/tests/wasm_c_api/wasm-c-api/example/hostref.cc diff --git a/lib/c-api/tests/wasm-c-api/example/hostref.wasm b/lib/c-api/tests/wasm_c_api/wasm-c-api/example/hostref.wasm similarity index 100% rename from lib/c-api/tests/wasm-c-api/example/hostref.wasm rename to lib/c-api/tests/wasm_c_api/wasm-c-api/example/hostref.wasm diff --git a/lib/c-api/tests/wasm-c-api/example/hostref.wat b/lib/c-api/tests/wasm_c_api/wasm-c-api/example/hostref.wat similarity index 100% rename from lib/c-api/tests/wasm-c-api/example/hostref.wat rename to lib/c-api/tests/wasm_c_api/wasm-c-api/example/hostref.wat diff --git a/lib/c-api/tests/wasm-c-api/example/memory.c b/lib/c-api/tests/wasm_c_api/wasm-c-api/example/memory.c similarity index 100% rename from lib/c-api/tests/wasm-c-api/example/memory.c rename to lib/c-api/tests/wasm_c_api/wasm-c-api/example/memory.c diff --git a/lib/c-api/tests/wasm-c-api/example/memory.cc b/lib/c-api/tests/wasm_c_api/wasm-c-api/example/memory.cc similarity index 100% rename from lib/c-api/tests/wasm-c-api/example/memory.cc rename to lib/c-api/tests/wasm_c_api/wasm-c-api/example/memory.cc diff --git a/lib/c-api/tests/wasm-c-api/example/memory.wasm b/lib/c-api/tests/wasm_c_api/wasm-c-api/example/memory.wasm similarity index 100% rename from lib/c-api/tests/wasm-c-api/example/memory.wasm rename to lib/c-api/tests/wasm_c_api/wasm-c-api/example/memory.wasm diff --git a/lib/c-api/tests/wasm-c-api/example/memory.wat b/lib/c-api/tests/wasm_c_api/wasm-c-api/example/memory.wat similarity index 100% rename from lib/c-api/tests/wasm-c-api/example/memory.wat rename to lib/c-api/tests/wasm_c_api/wasm-c-api/example/memory.wat diff --git a/lib/c-api/tests/wasm-c-api/example/multi.c b/lib/c-api/tests/wasm_c_api/wasm-c-api/example/multi.c similarity index 100% rename from lib/c-api/tests/wasm-c-api/example/multi.c rename to lib/c-api/tests/wasm_c_api/wasm-c-api/example/multi.c diff --git a/lib/c-api/tests/wasm-c-api/example/multi.cc b/lib/c-api/tests/wasm_c_api/wasm-c-api/example/multi.cc similarity index 100% rename from lib/c-api/tests/wasm-c-api/example/multi.cc rename to lib/c-api/tests/wasm_c_api/wasm-c-api/example/multi.cc diff --git a/lib/c-api/tests/wasm-c-api/example/multi.wasm b/lib/c-api/tests/wasm_c_api/wasm-c-api/example/multi.wasm similarity index 100% rename from lib/c-api/tests/wasm-c-api/example/multi.wasm rename to lib/c-api/tests/wasm_c_api/wasm-c-api/example/multi.wasm diff --git a/lib/c-api/tests/wasm-c-api/example/multi.wat b/lib/c-api/tests/wasm_c_api/wasm-c-api/example/multi.wat similarity index 100% rename from lib/c-api/tests/wasm-c-api/example/multi.wat rename to lib/c-api/tests/wasm_c_api/wasm-c-api/example/multi.wat diff --git a/lib/c-api/tests/wasm-c-api/example/reflect.c b/lib/c-api/tests/wasm_c_api/wasm-c-api/example/reflect.c similarity index 100% rename from lib/c-api/tests/wasm-c-api/example/reflect.c rename to lib/c-api/tests/wasm_c_api/wasm-c-api/example/reflect.c diff --git a/lib/c-api/tests/wasm-c-api/example/reflect.cc b/lib/c-api/tests/wasm_c_api/wasm-c-api/example/reflect.cc similarity index 100% rename from lib/c-api/tests/wasm-c-api/example/reflect.cc rename to lib/c-api/tests/wasm_c_api/wasm-c-api/example/reflect.cc diff --git a/lib/c-api/tests/wasm-c-api/example/reflect.wasm b/lib/c-api/tests/wasm_c_api/wasm-c-api/example/reflect.wasm similarity index 100% rename from lib/c-api/tests/wasm-c-api/example/reflect.wasm rename to lib/c-api/tests/wasm_c_api/wasm-c-api/example/reflect.wasm diff --git a/lib/c-api/tests/wasm-c-api/example/reflect.wat b/lib/c-api/tests/wasm_c_api/wasm-c-api/example/reflect.wat similarity index 100% rename from lib/c-api/tests/wasm-c-api/example/reflect.wat rename to lib/c-api/tests/wasm_c_api/wasm-c-api/example/reflect.wat diff --git a/lib/c-api/tests/wasm-c-api/example/serialize.c b/lib/c-api/tests/wasm_c_api/wasm-c-api/example/serialize.c similarity index 100% rename from lib/c-api/tests/wasm-c-api/example/serialize.c rename to lib/c-api/tests/wasm_c_api/wasm-c-api/example/serialize.c diff --git a/lib/c-api/tests/wasm-c-api/example/serialize.cc b/lib/c-api/tests/wasm_c_api/wasm-c-api/example/serialize.cc similarity index 100% rename from lib/c-api/tests/wasm-c-api/example/serialize.cc rename to lib/c-api/tests/wasm_c_api/wasm-c-api/example/serialize.cc diff --git a/lib/c-api/tests/wasm-c-api/example/serialize.wasm b/lib/c-api/tests/wasm_c_api/wasm-c-api/example/serialize.wasm similarity index 100% rename from lib/c-api/tests/wasm-c-api/example/serialize.wasm rename to lib/c-api/tests/wasm_c_api/wasm-c-api/example/serialize.wasm diff --git a/lib/c-api/tests/wasm-c-api/example/serialize.wat b/lib/c-api/tests/wasm_c_api/wasm-c-api/example/serialize.wat similarity index 100% rename from lib/c-api/tests/wasm-c-api/example/serialize.wat rename to lib/c-api/tests/wasm_c_api/wasm-c-api/example/serialize.wat diff --git a/lib/c-api/tests/wasm-c-api/example/start.c b/lib/c-api/tests/wasm_c_api/wasm-c-api/example/start.c similarity index 100% rename from lib/c-api/tests/wasm-c-api/example/start.c rename to lib/c-api/tests/wasm_c_api/wasm-c-api/example/start.c diff --git a/lib/c-api/tests/wasm-c-api/example/start.cc b/lib/c-api/tests/wasm_c_api/wasm-c-api/example/start.cc similarity index 100% rename from lib/c-api/tests/wasm-c-api/example/start.cc rename to lib/c-api/tests/wasm_c_api/wasm-c-api/example/start.cc diff --git a/lib/c-api/tests/wasm-c-api/example/start.wasm b/lib/c-api/tests/wasm_c_api/wasm-c-api/example/start.wasm similarity index 100% rename from lib/c-api/tests/wasm-c-api/example/start.wasm rename to lib/c-api/tests/wasm_c_api/wasm-c-api/example/start.wasm diff --git a/lib/c-api/tests/wasm-c-api/example/start.wat b/lib/c-api/tests/wasm_c_api/wasm-c-api/example/start.wat similarity index 100% rename from lib/c-api/tests/wasm-c-api/example/start.wat rename to lib/c-api/tests/wasm_c_api/wasm-c-api/example/start.wat diff --git a/lib/c-api/tests/wasm-c-api/example/table.c b/lib/c-api/tests/wasm_c_api/wasm-c-api/example/table.c similarity index 100% rename from lib/c-api/tests/wasm-c-api/example/table.c rename to lib/c-api/tests/wasm_c_api/wasm-c-api/example/table.c diff --git a/lib/c-api/tests/wasm-c-api/example/table.cc b/lib/c-api/tests/wasm_c_api/wasm-c-api/example/table.cc similarity index 100% rename from lib/c-api/tests/wasm-c-api/example/table.cc rename to lib/c-api/tests/wasm_c_api/wasm-c-api/example/table.cc diff --git a/lib/c-api/tests/wasm-c-api/example/table.wasm b/lib/c-api/tests/wasm_c_api/wasm-c-api/example/table.wasm similarity index 100% rename from lib/c-api/tests/wasm-c-api/example/table.wasm rename to lib/c-api/tests/wasm_c_api/wasm-c-api/example/table.wasm diff --git a/lib/c-api/tests/wasm-c-api/example/table.wat b/lib/c-api/tests/wasm_c_api/wasm-c-api/example/table.wat similarity index 100% rename from lib/c-api/tests/wasm-c-api/example/table.wat rename to lib/c-api/tests/wasm_c_api/wasm-c-api/example/table.wat diff --git a/lib/c-api/tests/wasm-c-api/example/threads.c b/lib/c-api/tests/wasm_c_api/wasm-c-api/example/threads.c similarity index 100% rename from lib/c-api/tests/wasm-c-api/example/threads.c rename to lib/c-api/tests/wasm_c_api/wasm-c-api/example/threads.c diff --git a/lib/c-api/tests/wasm-c-api/example/threads.cc b/lib/c-api/tests/wasm_c_api/wasm-c-api/example/threads.cc similarity index 100% rename from lib/c-api/tests/wasm-c-api/example/threads.cc rename to lib/c-api/tests/wasm_c_api/wasm-c-api/example/threads.cc diff --git a/lib/c-api/tests/wasm-c-api/example/threads.wasm b/lib/c-api/tests/wasm_c_api/wasm-c-api/example/threads.wasm similarity index 100% rename from lib/c-api/tests/wasm-c-api/example/threads.wasm rename to lib/c-api/tests/wasm_c_api/wasm-c-api/example/threads.wasm diff --git a/lib/c-api/tests/wasm-c-api/example/threads.wat b/lib/c-api/tests/wasm_c_api/wasm-c-api/example/threads.wat similarity index 100% rename from lib/c-api/tests/wasm-c-api/example/threads.wat rename to lib/c-api/tests/wasm_c_api/wasm-c-api/example/threads.wat diff --git a/lib/c-api/tests/wasm-c-api/example/trap.c b/lib/c-api/tests/wasm_c_api/wasm-c-api/example/trap.c similarity index 100% rename from lib/c-api/tests/wasm-c-api/example/trap.c rename to lib/c-api/tests/wasm_c_api/wasm-c-api/example/trap.c diff --git a/lib/c-api/tests/wasm-c-api/example/trap.cc b/lib/c-api/tests/wasm_c_api/wasm-c-api/example/trap.cc similarity index 100% rename from lib/c-api/tests/wasm-c-api/example/trap.cc rename to lib/c-api/tests/wasm_c_api/wasm-c-api/example/trap.cc diff --git a/lib/c-api/tests/wasm-c-api/example/trap.wasm b/lib/c-api/tests/wasm_c_api/wasm-c-api/example/trap.wasm similarity index 100% rename from lib/c-api/tests/wasm-c-api/example/trap.wasm rename to lib/c-api/tests/wasm_c_api/wasm-c-api/example/trap.wasm diff --git a/lib/c-api/tests/wasm-c-api/example/trap.wat b/lib/c-api/tests/wasm_c_api/wasm-c-api/example/trap.wat similarity index 100% rename from lib/c-api/tests/wasm-c-api/example/trap.wat rename to lib/c-api/tests/wasm_c_api/wasm-c-api/example/trap.wat diff --git a/lib/c-api/tests/wasm-c-api/include/wasm.h b/lib/c-api/tests/wasm_c_api/wasm-c-api/include/wasm.h similarity index 100% rename from lib/c-api/tests/wasm-c-api/include/wasm.h rename to lib/c-api/tests/wasm_c_api/wasm-c-api/include/wasm.h diff --git a/lib/c-api/tests/wasm-c-api/include/wasm.hh b/lib/c-api/tests/wasm_c_api/wasm-c-api/include/wasm.hh similarity index 100% rename from lib/c-api/tests/wasm-c-api/include/wasm.hh rename to lib/c-api/tests/wasm_c_api/wasm-c-api/include/wasm.hh diff --git a/lib/c-api/tests/wasm-c-api/patch/0001-BUILD.gn-add-wasm-v8-lowlevel.patch b/lib/c-api/tests/wasm_c_api/wasm-c-api/patch/0001-BUILD.gn-add-wasm-v8-lowlevel.patch similarity index 100% rename from lib/c-api/tests/wasm-c-api/patch/0001-BUILD.gn-add-wasm-v8-lowlevel.patch rename to lib/c-api/tests/wasm_c_api/wasm-c-api/patch/0001-BUILD.gn-add-wasm-v8-lowlevel.patch diff --git a/lib/c-api/tests/wasm-c-api/src/wasm-bin.cc b/lib/c-api/tests/wasm_c_api/wasm-c-api/src/wasm-bin.cc similarity index 100% rename from lib/c-api/tests/wasm-c-api/src/wasm-bin.cc rename to lib/c-api/tests/wasm_c_api/wasm-c-api/src/wasm-bin.cc diff --git a/lib/c-api/tests/wasm-c-api/src/wasm-bin.hh b/lib/c-api/tests/wasm_c_api/wasm-c-api/src/wasm-bin.hh similarity index 100% rename from lib/c-api/tests/wasm-c-api/src/wasm-bin.hh rename to lib/c-api/tests/wasm_c_api/wasm-c-api/src/wasm-bin.hh diff --git a/lib/c-api/tests/wasm-c-api/src/wasm-c.cc b/lib/c-api/tests/wasm_c_api/wasm-c-api/src/wasm-c.cc similarity index 100% rename from lib/c-api/tests/wasm-c-api/src/wasm-c.cc rename to lib/c-api/tests/wasm_c_api/wasm-c-api/src/wasm-c.cc diff --git a/lib/c-api/tests/wasm-c-api/src/wasm-v8-lowlevel.cc b/lib/c-api/tests/wasm_c_api/wasm-c-api/src/wasm-v8-lowlevel.cc similarity index 100% rename from lib/c-api/tests/wasm-c-api/src/wasm-v8-lowlevel.cc rename to lib/c-api/tests/wasm_c_api/wasm-c-api/src/wasm-v8-lowlevel.cc diff --git a/lib/c-api/tests/wasm-c-api/src/wasm-v8-lowlevel.hh b/lib/c-api/tests/wasm_c_api/wasm-c-api/src/wasm-v8-lowlevel.hh similarity index 100% rename from lib/c-api/tests/wasm-c-api/src/wasm-v8-lowlevel.hh rename to lib/c-api/tests/wasm_c_api/wasm-c-api/src/wasm-v8-lowlevel.hh diff --git a/lib/c-api/tests/wasm-c-api/src/wasm-v8.cc b/lib/c-api/tests/wasm_c_api/wasm-c-api/src/wasm-v8.cc similarity index 100% rename from lib/c-api/tests/wasm-c-api/src/wasm-v8.cc rename to lib/c-api/tests/wasm_c_api/wasm-c-api/src/wasm-v8.cc From ecfa22867e95ecac9ad214f4bc3dff615c4df5f7 Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Mon, 28 Sep 2020 17:17:25 +0200 Subject: [PATCH 067/281] test(c-api) Improve test outputs. --- lib/c-api/tests/deprecated_tests.rs | 40 ++++++++++++++--------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/lib/c-api/tests/deprecated_tests.rs b/lib/c-api/tests/deprecated_tests.rs index 68cf7111d..5d8f09351 100644 --- a/lib/c-api/tests/deprecated_tests.rs +++ b/lib/c-api/tests/deprecated_tests.rs @@ -23,35 +23,35 @@ fn test_deprecated_c_api() { } fn run_command(command_str: &str, dir: &str, args: Vec<&str>) { - println!("Running command: `{}` args: {:?}", command_str, args); + println!( + "Running command: `{}` with arguments: {:?}", + command_str, args + ); let mut command = Command::new(command_str); - command.args(&args); - command.current_dir(dir); - let result = command.output(); + match command.output() { + Ok(result) => { + println!("> Status: `{:?}`", result.status.code()); + println!( + "> Stdout: `{}`", + String::from_utf8_lossy(&result.stdout[..]) + ); + println!( + "> Stderr: `{}`", + String::from_utf8_lossy(&result.stderr[..]) + ); - match result { - Ok(r) => { - println!("> Output:"); - - if let Some(code) = r.status.code() { - println!("> Status: {}", code); - } else { - println!("> Status: None"); - } - - println!("> Stdout: {}", String::from_utf8_lossy(&r.stdout[..])); - println!("> Stderr: {}", String::from_utf8_lossy(&r.stderr[..])); - - if r.status.success() { + if result.status.success() { assert!(true) } else { - panic!("Command failed with exit status: {:?}", r.status); + panic!("Command failed with exit status: `{:?}`", result.status); } } - Err(e) => panic!("Command failed: {}", e), + Err(error) => panic!("Command failed: `{}`", error), } + + println!("\n"); } From 7708dcec50cfe7e7e611b946bedafa7386ab5f1b Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Mon, 28 Sep 2020 11:07:15 -0700 Subject: [PATCH 068/281] Attempt to `chmod +x` linked executable to fix issue on macos --- tests/integration/cli/src/compile.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/tests/integration/cli/src/compile.rs b/tests/integration/cli/src/compile.rs index e30ebd5ad..2879024fa 100644 --- a/tests/integration/cli/src/compile.rs +++ b/tests/integration/cli/src/compile.rs @@ -192,6 +192,12 @@ impl LinkCode { .expect("stderr is not utf8! need to handle arbitrary bytes") ); } + #[cfg(unix)] + Command::new("chmod") + .arg("+x") + .arg(&self.output_path) + .status() + .expect("Failed to make linked executable executable"); Ok(()) } } @@ -221,7 +227,6 @@ fn object_file_engine_works() -> anyhow::Result<()> { let wasm_path = PathBuf::from(OBJECT_FILE_ENGINE_TEST_WASM_PATH); let wasm_object_path = PathBuf::from("wasm.o"); let header_output_path = PathBuf::from("my_wasm.h"); - let libwasmer_path = get_libwasmer_path(); WasmerCompile { wasm_path: wasm_path.clone(), From 2eab9a58f12193ed77c51cd90dbd99c5d02cdb26 Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Mon, 28 Sep 2020 12:16:10 -0700 Subject: [PATCH 069/281] Get test passing on macos, add fix for linux x86_64 --- tests/integration/cli/src/compile.rs | 17 ++++++++++------- .../cli/src/object_file_engine_test_c_source.c | 1 + 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/tests/integration/cli/src/compile.rs b/tests/integration/cli/src/compile.rs index 2879024fa..6e8ca491a 100644 --- a/tests/integration/cli/src/compile.rs +++ b/tests/integration/cli/src/compile.rs @@ -37,6 +37,7 @@ fn get_libwasmer_path() -> PathBuf { ) } +#[allow(dead_code)] #[derive(Debug, Copy, Clone)] pub enum Engine { Jit, @@ -55,6 +56,7 @@ impl Engine { } } +#[allow(dead_code)] #[derive(Debug, Copy, Clone)] pub enum Compiler { Cranelift, @@ -181,6 +183,7 @@ impl LinkCode { .arg(&self.optimization_flag) .args(&self.object_paths) .arg(&self.libwasmer_path) + .arg("-pthread") .arg("-o") .arg(&self.output_path) .output()?; @@ -192,18 +195,12 @@ impl LinkCode { .expect("stderr is not utf8! need to handle arbitrary bytes") ); } - #[cfg(unix)] - Command::new("chmod") - .arg("+x") - .arg(&self.output_path) - .status() - .expect("Failed to make linked executable executable"); Ok(()) } } fn run_code(executable_path: &Path) -> anyhow::Result { - let output = Command::new(executable_path).output()?; + let output = Command::new(executable_path.canonicalize().unwrap()).output()?; if !output.status.success() { bail!( @@ -261,6 +258,12 @@ fn object_file_engine_works() -> anyhow::Result<()> { .run() .context("Failed to link objects together")?; + let cd = std::env::current_dir().unwrap(); + let rd = fs::read_dir(cd).unwrap(); + for dir in rd { + dbg!(dir); + } + let result = run_code(&executable_path).context("Failed to run generated executable")?; assert_eq!( &result, diff --git a/tests/integration/cli/src/object_file_engine_test_c_source.c b/tests/integration/cli/src/object_file_engine_test_c_source.c index 2a5d3aa43..df5a5ece9 100644 --- a/tests/integration/cli/src/object_file_engine_test_c_source.c +++ b/tests/integration/cli/src/object_file_engine_test_c_source.c @@ -132,6 +132,7 @@ int main() { void* vmctx = wasm_instance_get_vmctx_ptr(instance); wasm_val_t* inout[2] = { NULL, NULL }; + fflush(stdout); // We're able to call our compiled functions directly through their trampolines. wasmer_trampoline_function_call__1(vmctx, wasmer_function__1, &inout); From dc58c0e625b001d0941da5caf42dac070b46c12f Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Mon, 28 Sep 2020 12:54:11 -0700 Subject: [PATCH 070/281] Link with `-ldl` and improve error messages on Command failure --- tests/integration/cli/src/compile.rs | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/tests/integration/cli/src/compile.rs b/tests/integration/cli/src/compile.rs index 6e8ca491a..123f74f19 100644 --- a/tests/integration/cli/src/compile.rs +++ b/tests/integration/cli/src/compile.rs @@ -120,7 +120,9 @@ impl WasmerCompile { if !output.status.success() { bail!( - "wasmer compile failed with: {}", + "wasmer compile failed with: stdout: {}\n\nstderr: {}", + std::str::from_utf8(&output.stdout) + .expect("stdout is not utf8! need to handle arbitrary bytes"), std::str::from_utf8(&output.stderr) .expect("stderr is not utf8! need to handle arbitrary bytes") ); @@ -142,7 +144,9 @@ fn run_c_compile(path_to_c_src: &Path, output_name: &Path) -> anyhow::Result<()> if !output.status.success() { bail!( - "C code compile failed with: {}", + "C code compile failed with: stdout: {}\n\nstderr: {}", + std::str::from_utf8(&output.stdout) + .expect("stdout is not utf8! need to handle arbitrary bytes"), std::str::from_utf8(&output.stderr) .expect("stderr is not utf8! need to handle arbitrary bytes") ); @@ -183,6 +187,7 @@ impl LinkCode { .arg(&self.optimization_flag) .args(&self.object_paths) .arg(&self.libwasmer_path) + .arg("-ldl") .arg("-pthread") .arg("-o") .arg(&self.output_path) @@ -190,7 +195,9 @@ impl LinkCode { if !output.status.success() { bail!( - "linking failed with: {}", + "linking failed with: stdout: {}\n\nstderr: {}", + std::str::from_utf8(&output.stdout) + .expect("stdout is not utf8! need to handle arbitrary bytes"), std::str::from_utf8(&output.stderr) .expect("stderr is not utf8! need to handle arbitrary bytes") ); @@ -204,7 +211,9 @@ fn run_code(executable_path: &Path) -> anyhow::Result { if !output.status.success() { bail!( - "running executable failed: {}", + "running executable failed: stdout: {}\n\nstderr: {}", + std::str::from_utf8(&output.stdout) + .expect("stdout is not utf8! need to handle arbitrary bytes"), std::str::from_utf8(&output.stderr) .expect("stderr is not utf8! need to handle arbitrary bytes") ); @@ -258,12 +267,6 @@ fn object_file_engine_works() -> anyhow::Result<()> { .run() .context("Failed to link objects together")?; - let cd = std::env::current_dir().unwrap(); - let rd = fs::read_dir(cd).unwrap(); - for dir in rd { - dbg!(dir); - } - let result = run_code(&executable_path).context("Failed to run generated executable")?; assert_eq!( &result, From 1753a8bae1f24b26cde893a30f2dca4999c2d045 Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Mon, 28 Sep 2020 13:04:28 -0700 Subject: [PATCH 071/281] Link with `cc` --- tests/integration/cli/src/compile.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/integration/cli/src/compile.rs b/tests/integration/cli/src/compile.rs index 123f74f19..448fe6856 100644 --- a/tests/integration/cli/src/compile.rs +++ b/tests/integration/cli/src/compile.rs @@ -172,7 +172,7 @@ struct LinkCode { impl Default for LinkCode { fn default() -> Self { Self { - linker_path: PathBuf::from("g++"), + linker_path: PathBuf::from("cc"), optimization_flag: String::from("-O2"), object_paths: vec![], output_path: PathBuf::from("a.out"), From bdbbe7ed2f9de4ef2407933aa684abf29df5f5b1 Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Mon, 28 Sep 2020 15:06:00 -0700 Subject: [PATCH 072/281] Add config support to wasm-c-api --- Makefile | 6 +- lib/c-api/Cargo.toml | 3 +- lib/c-api/src/wasm_c_api/mod.rs | 176 +++++++++++++++++- lib/c-api/wasmer_wasm.h | 15 ++ tests/integration/cli/src/compile.rs | 27 ++- .../src/object_file_engine_test_c_source.c | 13 +- 6 files changed, 217 insertions(+), 23 deletions(-) diff --git a/Makefile b/Makefile index d17627562..e719360d7 100644 --- a/Makefile +++ b/Makefile @@ -76,15 +76,15 @@ build-capi: build-capi-cranelift build-capi-singlepass: cargo build --manifest-path lib/c-api/Cargo.toml --release \ - --no-default-features --features jit,singlepass,wasi + --no-default-features --features jit,object-file,singlepass,wasi build-capi-cranelift: cargo build --manifest-path lib/c-api/Cargo.toml --release \ - --no-default-features --features jit,cranelift,wasi + --no-default-features --features jit,object-file,cranelift,wasi build-capi-llvm: cargo build --manifest-path lib/c-api/Cargo.toml --release \ - --no-default-features --features jit,llvm,wasi + --no-default-features --features jit,object-file,llvm,wasi # this is debug code; we probably shouldn't ship it like this build-capi-native: diff --git a/lib/c-api/Cargo.toml b/lib/c-api/Cargo.toml index e1b061ffa..83787804a 100644 --- a/lib/c-api/Cargo.toml +++ b/lib/c-api/Cargo.toml @@ -60,7 +60,8 @@ object-file = [ ] compiler = [ "wasmer-engine-jit/compiler", - "wasmer-engine-native/compiler" + "wasmer-engine-native/compiler", + "wasmer-engine-object-file/compiler" ] singlepass = [ "wasmer-compiler-singlepass", diff --git a/lib/c-api/src/wasm_c_api/mod.rs b/lib/c-api/src/wasm_c_api/mod.rs index 9d017bdf8..b937dbe16 100644 --- a/lib/c-api/src/wasm_c_api/mod.rs +++ b/lib/c-api/src/wasm_c_api/mod.rs @@ -28,14 +28,79 @@ use wasmer_engine_native::Native; #[cfg(feature = "object-file")] use wasmer_engine_object_file::ObjectFile; -/// this can be a wasmer-specific type with wasmer-specific functions for manipulating it +#[derive(Debug, Copy, Clone)] #[repr(C)] -pub struct wasm_config_t {} +pub enum wasmer_compiler_t { + CRANELIFT = 0, + LLVM = 1, + SINGLEPASS = 2, +} + +impl Default for wasmer_compiler_t { + fn default() -> Self { + cfg_if! { + if #[cfg(feature = "cranelift")] { + Self::CRANELIFT + } else if #[cfg(feature = "llvm")] { + Self::LLVM + } else if #[cfg(feature = "singlepass")] { + Self::SINGLEPASS + } else { + compile_error!("Please enable one of the compiler backends") + } + } + } +} + +#[derive(Debug, Copy, Clone)] +#[repr(C)] +#[allow(non_camel_case_types)] +pub enum wasmer_engine_t { + JIT = 0, + NATIVE = 1, + OBJECT_FILE = 2, +} + +impl Default for wasmer_engine_t { + fn default() -> Self { + cfg_if! { + if #[cfg(feature = "jit")] { + Self::JIT + } else if #[cfg(feature = "native")] { + Self::NATIVE + } else if #[cfg(feature = "object-file")] { + Self::OBJECT_FILE + } else { + compile_error!("Please enable one of the engines") + } + } + } +} + +/// this can be a wasmer-specific type with wasmer-specific functions for manipulating it +#[derive(Debug, Default)] +#[repr(C)] +pub struct wasm_config_t { + compiler: wasmer_compiler_t, + engine: wasmer_engine_t, +} #[no_mangle] -pub extern "C" fn wasm_config_new() -> *mut wasm_config_t { - todo!("wasm_config_new") - //ptr::null_mut() +pub extern "C" fn wasm_config_new() -> Box { + Box::new(wasm_config_t::default()) +} + +#[no_mangle] +pub extern "C" fn wasm_config_set_compiler( + config: &mut wasm_config_t, + compiler: wasmer_compiler_t, +) { + config.compiler = compiler; +} + +#[no_mangle] +pub extern "C" fn wasm_config_set_engine(config: &mut wasm_config_t, engine: wasmer_engine_t) { + config.engine = engine; } #[repr(C)] @@ -121,9 +186,104 @@ pub unsafe extern "C" fn wasm_engine_delete(_wasm_engine_address: Option Box { - wasm_engine_new() + config: Box, +) -> Option> { + // TODO: return useful error messages in failure branches + cfg_if! { + if #[cfg(feature = "compiler")] { + let mut compiler_config: Box = match config.compiler { + wasmer_compiler_t::CRANELIFT => { + cfg_if! { + if #[cfg(feature = "cranelift")] { + Box::new(wasmer_compiler_cranelift::Cranelift::default()) + } else { + return None; + } + } + }, + wasmer_compiler_t::LLVM => { + cfg_if! { + if #[cfg(feature = "llvm")] { + Box::new(wasmer_compiler_llvm::LLVM::default()) + } else { + return None; + } + } + }, + wasmer_compiler_t::SINGLEPASS => { + cfg_if! { + if #[cfg(feature = "singlepass")] { + Box::new(wasmer_compiler_singlepass::Singlepass::default()) + } else { + return None; + } + } + }, + }; + + let inner: Arc = match config.engine { + wasmer_engine_t::JIT => { + cfg_if! { + if #[cfg(feature = "jit")] { + Arc::new(JIT::new(&*compiler_config).engine()) + } else { + return None; + } + } + }, + wasmer_engine_t::NATIVE => { + cfg_if! { + if #[cfg(feature = "native")] { + Arc::new(Native::new(&mut *compiler_config).engine()) + } else { + return None; + } + } + }, + wasmer_engine_t::OBJECT_FILE => { + cfg_if! { + if #[cfg(feature = "object-file")] { + Arc::new(ObjectFile::new(&mut *compiler_config).engine()) + } else { + return None; + } + } + }, + }; + Some(Box::new(wasm_engine_t { inner })) + } else { + let inner: Arc = match config.engine { + wasmer_engine_t::JIT => { + cfg_if! { + if #[cfg(feature = "jit")] { + Arc::new(JIT::headless().engine()) + } else { + return None; + } + } + }, + wasmer_engine_t::NATIVE => { + cfg_if! { + if #[cfg(feature = "native")] { + Arc::new(Native::headless().engine()) + } else { + return None; + } + } + }, + wasmer_engine_t::OBJECT_FILE => { + cfg_if! { + if #[cfg(feature = "object-file")] { + Arc::new(ObjectFile::headless().engine()) + } else { + return None; + } + } + }, + }; + Some(Box::new(wasm_engine_t { inner })) + } + } } #[repr(C)] diff --git a/lib/c-api/wasmer_wasm.h b/lib/c-api/wasmer_wasm.h index 56260c91f..2e407076e 100644 --- a/lib/c-api/wasmer_wasm.h +++ b/lib/c-api/wasmer_wasm.h @@ -35,6 +35,21 @@ enum { WASI_VERSION_INVALID = ~0 }; +typedef enum wasmer_compiler_t { + CRANELIFT = 0, + LLVM = 1, + SINGLEPASS = 2, +} wasmer_compiler_t; + +typedef enum wasmer_engine_t { + JIT = 0, + NATIVE = 1, + OBJECT_FILE = 2, +} wasmer_engine_t; + +void wasm_config_set_compiler(wasm_config_t* config, wasmer_compiler_t compiler); +void wasm_config_set_engine(wasm_config_t* config, wasmer_engine_t engine); + // Create a `wasi_config_t`. // // Takes as an argument the name of the Wasm program to execute (will show up diff --git a/tests/integration/cli/src/compile.rs b/tests/integration/cli/src/compile.rs index 448fe6856..2313222c2 100644 --- a/tests/integration/cli/src/compile.rs +++ b/tests/integration/cli/src/compile.rs @@ -109,7 +109,7 @@ impl WasmerCompile { fn run(&self) -> anyhow::Result<()> { let output = Command::new(&self.wasmer_path) .arg("compile") - .arg(&self.wasm_path) + .arg(&self.wasm_path.canonicalize()?) .arg(&self.compiler.to_flag()) .arg(&self.engine.to_flag()) .arg("-o") @@ -131,8 +131,13 @@ impl WasmerCompile { } } +/// Compile the C code. fn run_c_compile(path_to_c_src: &Path, output_name: &Path) -> anyhow::Result<()> { - let output = Command::new("cc") + #[cfg(not(windows))] + let c_compiler = "cc"; + #[cfg(windows)] + let c_compiler = "clang"; + let output = Command::new(c_compiler) .arg("-O2") .arg("-c") .arg(path_to_c_src) @@ -171,8 +176,12 @@ struct LinkCode { impl Default for LinkCode { fn default() -> Self { + #[cfg(not(windows))] + let linker = "cc"; + #[cfg(windows)] + let linker = "clang"; Self { - linker_path: PathBuf::from("cc"), + linker_path: PathBuf::from(linker), optimization_flag: String::from("-O2"), object_paths: vec![], output_path: PathBuf::from("a.out"), @@ -185,9 +194,15 @@ impl LinkCode { fn run(&self) -> anyhow::Result<()> { let output = Command::new(&self.linker_path) .arg(&self.optimization_flag) - .args(&self.object_paths) - .arg(&self.libwasmer_path) + .args( + self.object_paths + .iter() + .map(|path| path.canonicalize().unwrap()), + ) + .arg(&self.libwasmer_path.canonicalize()?) + .arg("-lffi") .arg("-ldl") + .arg("-lm") .arg("-pthread") .arg("-o") .arg(&self.output_path) @@ -207,7 +222,7 @@ impl LinkCode { } fn run_code(executable_path: &Path) -> anyhow::Result { - let output = Command::new(executable_path.canonicalize().unwrap()).output()?; + let output = Command::new(executable_path.canonicalize()?).output()?; if !output.status.success() { bail!( diff --git a/tests/integration/cli/src/object_file_engine_test_c_source.c b/tests/integration/cli/src/object_file_engine_test_c_source.c index df5a5ece9..0a04cac01 100644 --- a/tests/integration/cli/src/object_file_engine_test_c_source.c +++ b/tests/integration/cli/src/object_file_engine_test_c_source.c @@ -30,7 +30,10 @@ void print_wasmer_error() int main() { printf("Initializing...\n"); - wasm_engine_t* engine = wasm_engine_new(); + wasm_config_t* config = wasm_config_new(); + wasm_config_set_compiler(config, CRANELIFT); + wasm_config_set_engine(config, OBJECT_FILE); + wasm_engine_t* engine = wasm_engine_new_with_config(config); wasm_store_t* store = wasm_store_new(engine); char* byte_ptr = (char*)&WASMER_METADATA[0]; @@ -95,11 +98,11 @@ int main() { // In this example we're passing some JavaScript source code as a command line argumnet // to a WASI module that can evaluate JavaScript. - wasi_config_t* config = wasi_config_new("constant_value_here"); + wasi_config_t* wasi_config = wasi_config_new("constant_value_here"); const char* js_string = "function greet(name) { return JSON.stringify('Hello, ' + name); }; print(greet('World'));"; - wasi_config_arg(config, "--eval"); - wasi_config_arg(config, js_string); - wasi_env_t* wasi_env = wasi_env_new(config); + wasi_config_arg(wasi_config, "--eval"); + wasi_config_arg(wasi_config, js_string); + wasi_env_t* wasi_env = wasi_env_new(wasi_config); if (!wasi_env) { printf("> Error building WASI env!\n"); print_wasmer_error(); From ed75704971cc402802a8bc498ead3a9ab7714d25 Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Mon, 28 Sep 2020 15:14:47 -0700 Subject: [PATCH 073/281] Add early exit example --- Cargo.toml | 5 ++ examples/early_exit.rs | 82 ++++++++++++++++++++++++++++ examples/engine_cross_compilation.rs | 5 +- examples/wasi.rs | 6 +- 4 files changed, 92 insertions(+), 6 deletions(-) create mode 100644 examples/early_exit.rs diff --git a/Cargo.toml b/Cargo.toml index fb84f986c..f034431fa 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -128,6 +128,11 @@ test-no-traps = ["wasmer-wast/test-no-traps"] name = "static_and_dynamic_functions" harness = false +[[example]] +name = "early-exit" +path = "examples/early_exit.rs" +required-features = ["cranelift"] + [[example]] name = "engine-jit" path = "examples/engine_jit.rs" diff --git a/examples/early_exit.rs b/examples/early_exit.rs new file mode 100644 index 000000000..7253fd519 --- /dev/null +++ b/examples/early_exit.rs @@ -0,0 +1,82 @@ +//! This example shows how the host can terminate execution of Wasm early from +//! inside a host function called by the Wasm. + +use anyhow::bail; +use std::fmt; +use wasmer::{imports, wat2wasm, Function, Instance, Module, NativeFunc, RuntimeError, Store}; +use wasmer_compiler_cranelift::Cranelift; +use wasmer_engine_jit::JIT; + +// First we need to create an error type that we'll use to signal the end of execution. +#[derive(Debug, Clone, Copy)] +struct ExitCode(u32); + +// This type must implement `std::error::Error` so we must also implement `std::fmt::Display` for it. +impl fmt::Display for ExitCode { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}", self.0) + } +} + +// And then we implement `std::error::Error`. +impl std::error::Error for ExitCode {} + +// The host function that we'll use to terminate execution. +fn early_exit() { + // This is where it happens. + RuntimeError::raise(Box::new(ExitCode(1))); +} + +fn main() -> anyhow::Result<()> { + // Let's declare the Wasm module with the text representation. + let wasm_bytes = wat2wasm( + br#" +(module + (type $run_t (func (param i32 i32) (result i32))) + (type $early_exit_t (func (param) (result))) + (import "env" "early_exit" (func $early_exit (type $early_exit_t))) + (func $run (type $run_t) (param $x i32) (param $y i32) (result i32) + (call $early_exit) + (i32.add + local.get $x + local.get $y)) + (export "run" (func $run))) +"#, + )?; + + let store = Store::new(&JIT::new(&Cranelift::default()).engine()); + let module = Module::new(&store, wasm_bytes)?; + + let import_object = imports! { + "env" => { + "early_exit" => Function::new_native(&store, early_exit), + } + }; + let instance = Instance::new(&module, &import_object)?; + + // get the `run` function which we'll use as our entrypoint. + let run_func: NativeFunc<(i32, i32), i32> = + instance.exports.get_native_function("run").unwrap(); + + // When we call a function it can either succeed or fail. + match run_func.call(1, 7) { + Ok(result) => { + bail!( + "Expected early termination with `ExitCode`, found: {}", + result + ); + } + // we're expecting it to fail. + // we attempt to downcast the error into the error type that we were expecting. + Err(e) => match e.downcast::() { + // we found the exit code used to terminate execution. + Ok(exit_code) => { + println!("Exited early with exit code: {}", exit_code); + Ok(()) + } + Err(e) => { + bail!("Unknown error `{}` found. expected `ErrorCode`", e); + } + }, + } +} diff --git a/examples/engine_cross_compilation.rs b/examples/engine_cross_compilation.rs index 1c9795138..272da2cfc 100644 --- a/examples/engine_cross_compilation.rs +++ b/examples/engine_cross_compilation.rs @@ -27,7 +27,7 @@ use wasmer_engine_native::Native; fn main() -> Result<(), Box> { // Let's declare the Wasm module with the text representation. let wasm_bytes = wat2wasm( - r#" + br#" (module (type $sum_t (func (param i32 i32) (result i32))) (func $sum_f (type $sum_t) (param $x i32) (param $y i32) (result i32) @@ -35,8 +35,7 @@ fn main() -> Result<(), Box> { local.get $y i32.add) (export "sum" (func $sum_f))) -"# - .as_bytes(), +"#, )?; // Define a compiler configuration. diff --git a/examples/wasi.rs b/examples/wasi.rs index 72617e835..c9c779b74 100644 --- a/examples/wasi.rs +++ b/examples/wasi.rs @@ -21,9 +21,9 @@ use wasmer_engine_jit::JIT; use wasmer_wasi::WasiState; fn main() -> Result<(), Box> { - let wasm_path = format!( - "{}/tests/wasi-wast/wasi/unstable/hello.wasm", - std::env::var("CARGO_MANIFEST_DIR").unwrap() + let wasm_path = concat!( + env!("CARGO_MANIFEST_DIR"), + "/tests/wasi-wast/wasi/unstable/hello.wasm" ); // Let's declare the Wasm module with the text representation. let wasm_bytes = std::fs::read(wasm_path)?; From d76b0382488619c89bfaf9e3aa59617d5cbdc7c7 Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Mon, 28 Sep 2020 15:30:30 -0700 Subject: [PATCH 074/281] Prevent code coverage from running on bors branches --- .github/workflows/coverage.yaml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/.github/workflows/coverage.yaml b/.github/workflows/coverage.yaml index 778e3d3f6..98c100f14 100644 --- a/.github/workflows/coverage.yaml +++ b/.github/workflows/coverage.yaml @@ -1,4 +1,9 @@ -on: [push] +on: + push: + branches: + - '!trying' + - '!trying.tmp' + - '!staging' name: build From 649a73797d83c6c02c5990feaa505d134057a6da Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Mon, 28 Sep 2020 15:36:57 -0700 Subject: [PATCH 075/281] Also ignore `staging.tmp` for coverage --- .github/workflows/coverage.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/coverage.yaml b/.github/workflows/coverage.yaml index 98c100f14..e4070468a 100644 --- a/.github/workflows/coverage.yaml +++ b/.github/workflows/coverage.yaml @@ -4,6 +4,7 @@ on: - '!trying' - '!trying.tmp' - '!staging' + - '!staging.tmp' name: build From 4165e389dc7e19dbdada46f311dd98d53bcfe697 Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Tue, 29 Sep 2020 14:16:09 +0200 Subject: [PATCH 076/281] feat(c-api) Use `cbindgen@master`. Our PR to support `ManuallyDrop`, `MaybeUninit` and `Box` has been merged, https://github.com/eqrion/cbindgen/pull/578. --- lib/c-api/Cargo.toml | 3 ++- lib/c-api/wasmer_wasm.h | 12 +++--------- 2 files changed, 5 insertions(+), 10 deletions(-) diff --git a/lib/c-api/Cargo.toml b/lib/c-api/Cargo.toml index fcb317160..8d45aea40 100644 --- a/lib/c-api/Cargo.toml +++ b/lib/c-api/Cargo.toml @@ -78,4 +78,5 @@ cranelift-backend = ["cranelift"] llvm-backend = ["llvm"] [build-dependencies] -cbindgen = "0.14.6" \ No newline at end of file +#cbindgen = "0.14.6" +cbindgen = { git = "https://github.com/eqrion/cbindgen", branch = "master" } \ No newline at end of file diff --git a/lib/c-api/wasmer_wasm.h b/lib/c-api/wasmer_wasm.h index 3348f90ce..729603086 100644 --- a/lib/c-api/wasmer_wasm.h +++ b/lib/c-api/wasmer_wasm.h @@ -51,12 +51,6 @@ #include #include "wasm.h" -typedef struct Box_wasi_config_t Box_wasi_config_t; - -typedef struct Option_Box_wasi_config_t Option_Box_wasi_config_t; - -typedef struct Option_Box_wasi_env_t Option_Box_wasi_env_t; - #if defined(WASMER_WASI_ENABLED) typedef struct wasi_version_t wasi_version_t; #endif @@ -97,18 +91,18 @@ void wasi_config_inherit_stdout(wasi_config_t *config); #endif #if defined(WASMER_WASI_ENABLED) -Option_Box_wasi_config_t wasi_config_new(const char *program_name); +wasi_config_t *wasi_config_new(const char *program_name); #endif #if defined(WASMER_WASI_ENABLED) -void wasi_env_delete(Option_Box_wasi_env_t _state); +void wasi_env_delete(wasi_env_t *_state); #endif #if defined(WASMER_WASI_ENABLED) /** * Takes ownership over the `wasi_config_t`. */ -Option_Box_wasi_env_t wasi_env_new(Box_wasi_config_t config); +wasi_env_t *wasi_env_new(wasi_config_t *config); #endif #if defined(WASMER_WASI_ENABLED) From d55b701e9d6814286a40e2f20b3be811529c57e8 Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Tue, 29 Sep 2020 16:01:52 +0200 Subject: [PATCH 077/281] feat(c-api) Make `wasi_config_t` and `wasi_env_t` opaque structures. Removing `repr(C)` make them opaque for cbindgen. Which is perfect for what we want. --- lib/c-api/src/wasm_c_api/mod.rs | 1 + lib/c-api/src/wasm_c_api/wasi/mod.rs | 2 -- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/c-api/src/wasm_c_api/mod.rs b/lib/c-api/src/wasm_c_api/mod.rs index 830c46944..5ee3adf6e 100644 --- a/lib/c-api/src/wasm_c_api/mod.rs +++ b/lib/c-api/src/wasm_c_api/mod.rs @@ -11,5 +11,6 @@ pub mod store; pub mod trap; pub mod types; pub mod value; + #[cfg(feature = "wasi")] pub mod wasi; diff --git a/lib/c-api/src/wasm_c_api/wasi/mod.rs b/lib/c-api/src/wasm_c_api/wasi/mod.rs index 4a272b7b5..0dbc33a3a 100644 --- a/lib/c-api/src/wasm_c_api/wasi/mod.rs +++ b/lib/c-api/src/wasm_c_api/wasi/mod.rs @@ -26,7 +26,6 @@ use wasmer_wasi::{ #[derive(Debug, Default)] #[allow(non_camel_case_types)] -#[repr(C)] pub struct wasi_config_t { inherit_stdout: bool, inherit_stderr: bool, @@ -91,7 +90,6 @@ pub extern "C" fn wasi_config_inherit_stdin(config: &mut wasi_config_t) { } #[allow(non_camel_case_types)] -#[repr(C)] pub struct wasi_env_t { /// cbindgen:ignore inner: WasiEnv, From cab0854d998cf1618247a23d2ab9eeb49afc0560 Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Tue, 29 Sep 2020 16:04:25 +0200 Subject: [PATCH 078/281] feat(c-api) Rename the `include-deprecated` feature to `deprecated`, and change strategy. When `deprecated` is enabled, the `deprecated` module is included in the crate. When `deprecated` is enabled, **only** the `wasmer.h*` header files will be generated. When `deprecated` is disabled, **only** the `wasmer_wasm.h` header file will be generated. --- lib/c-api/Cargo.toml | 2 +- lib/c-api/build.rs | 24 +++++++----------------- lib/c-api/src/lib.rs | 2 +- 3 files changed, 9 insertions(+), 19 deletions(-) diff --git a/lib/c-api/Cargo.toml b/lib/c-api/Cargo.toml index 8d45aea40..5b7fafce2 100644 --- a/lib/c-api/Cargo.toml +++ b/lib/c-api/Cargo.toml @@ -70,7 +70,7 @@ llvm = [ "compiler", ] #emscripten = ["wasmer-emscripten"] -include-deprecated = [] +deprecated = [] # This is for compatibility for old usage singlepass-backend = ["singlepass"] diff --git a/lib/c-api/build.rs b/lib/c-api/build.rs index ceab25593..cd7c6c06c 100644 --- a/lib/c-api/build.rs +++ b/lib/c-api/build.rs @@ -40,7 +40,7 @@ const WASI_FEATURE_AS_C_DEFINE: &'static str = "WASMER_WASI_ENABLED"; const EMSCRIPTEN_FEATURE_AS_C_DEFINE: &'static str = "WASMER_EMSCRIPTEN_ENABLED"; #[allow(unused)] -const INCLUDE_DEPRECATED_FEATURE_AS_C_DEFINE: &'static str = "WASMER_DEPRECATED_ENABLED"; +const DEPRECATED_FEATURE_AS_C_DEFINE: &'static str = "WASMER_DEPRECATED_ENABLED"; macro_rules! map_feature_as_c_define { ($feature:expr, $c_define:ident, $accumulator:ident) => { @@ -62,7 +62,10 @@ fn main() { let crate_dir = env::var("CARGO_MANIFEST_DIR").unwrap(); let out_dir = env::var("OUT_DIR").unwrap(); + #[cfg(not(feature = "deprecated"))] build_wasm_c_api_headers(&crate_dir, &out_dir); + + #[cfg(feature = "deprecated")] build_wasmer_headers(&crate_dir, &out_dir); } @@ -87,11 +90,7 @@ fn build_wasm_c_api_headers(crate_dir: &str, out_dir: &str) { map_feature_as_c_define!("compiler", COMPILER_FEATURE_AS_C_DEFINE, pre_header); map_feature_as_c_define!("wasi", WASI_FEATURE_AS_C_DEFINE, pre_header); map_feature_as_c_define!("emscripten", EMSCRIPTEN_FEATURE_AS_C_DEFINE, pre_header); - map_feature_as_c_define!( - "include-deprecated", - INCLUDE_DEPRECATED_FEATURE_AS_C_DEFINE, - pre_header - ); + map_feature_as_c_define!("deprecated", DEPRECATED_FEATURE_AS_C_DEFINE, pre_header); // Close pre header. pre_header.push_str( @@ -122,15 +121,11 @@ fn build_wasm_c_api_headers(crate_dir: &str, out_dir: &str) { .with_define("feature", "compiler", COMPILER_FEATURE_AS_C_DEFINE) .with_define("feature", "wasi", WASI_FEATURE_AS_C_DEFINE) .with_define("feature", "emscripten", EMSCRIPTEN_FEATURE_AS_C_DEFINE) - .with_define( - "feature", - "include-deprecated", - INCLUDE_DEPRECATED_FEATURE_AS_C_DEFINE, - ) + .with_define("feature", "deprecated", DEPRECATED_FEATURE_AS_C_DEFINE) .with_include("wasm.h") .with_documentation(true); - #[cfg(not(feature = "include-deprecated"))] + #[cfg(not(feature = "deprecated"))] { // List of all functions to exclude given by: // @@ -270,7 +265,6 @@ fn build_wasm_c_api_headers(crate_dir: &str, out_dir: &str) { } builder - .exclude_item("Version") .generate() .expect("Unable to generate C bindings") .write_to_file(out_header_file.as_path()); @@ -284,10 +278,6 @@ fn build_wasm_c_api_headers(crate_dir: &str, out_dir: &str) { } } -#[cfg(not(feature = "include-deprecated"))] -fn build_wasmer_headers(_crate_dir: &str, _out_dir: &str) {} - -#[cfg(feature = "include-deprecated")] fn build_wasmer_headers(crate_dir: &str, out_dir: &str) { let mut crate_header_file = PathBuf::from(crate_dir); crate_header_file.push("wasmer"); diff --git a/lib/c-api/src/lib.rs b/lib/c-api/src/lib.rs index 3f2222985..bb52ec511 100644 --- a/lib/c-api/src/lib.rs +++ b/lib/c-api/src/lib.rs @@ -11,7 +11,7 @@ unreachable_patterns )] -#[cfg(feature = "include-deprecated")] +#[cfg(feature = "deprecated")] pub mod deprecated; pub mod error; mod ordered_resolver; From 89697564168e79aeb54bc966ddcf7ca6fec8a793 Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Tue, 29 Sep 2020 16:08:54 +0200 Subject: [PATCH 079/281] chore(c-api) Regenerate header files. --- lib/c-api/wasm.h | 2 +- lib/c-api/wasmer.h | 31 +++++++++---------------------- lib/c-api/wasmer.hh | 23 ++++++++--------------- lib/c-api/wasmer_wasm.h | 23 ++++++++--------------- 4 files changed, 26 insertions(+), 53 deletions(-) diff --git a/lib/c-api/wasm.h b/lib/c-api/wasm.h index 14a531199..3202a8f6d 120000 --- a/lib/c-api/wasm.h +++ b/lib/c-api/wasm.h @@ -1 +1 @@ -tests/wasm-c-api/include/wasm.h \ No newline at end of file +tests/wasm_c_api/wasm-c-api/include/wasm.h \ No newline at end of file diff --git a/lib/c-api/wasmer.h b/lib/c-api/wasmer.h index c664264b5..3e01c5e79 100644 --- a/lib/c-api/wasmer.h +++ b/lib/c-api/wasmer.h @@ -140,31 +140,18 @@ enum wasmer_value_tag { }; typedef uint32_t wasmer_value_tag; -typedef struct Box_wasi_config_t Box_wasi_config_t; +#if defined(WASMER_WASI_ENABLED) +typedef struct wasi_config_t wasi_config_t; +#endif -typedef struct Option_Box_wasi_config_t Option_Box_wasi_config_t; - -typedef struct Option_Box_wasi_env_t Option_Box_wasi_env_t; +#if defined(WASMER_WASI_ENABLED) +typedef struct wasi_env_t wasi_env_t; +#endif #if defined(WASMER_WASI_ENABLED) typedef struct wasi_version_t wasi_version_t; #endif -#if defined(WASMER_WASI_ENABLED) -typedef struct { - bool inherit_stdout; - bool inherit_stderr; - bool inherit_stdin; - WasiStateBuilder state_builder; -} wasi_config_t; -#endif - -#if defined(WASMER_WASI_ENABLED) -typedef struct { - WasiEnv inner; -} wasi_env_t; -#endif - typedef struct { } wasmer_module_t; @@ -447,18 +434,18 @@ void wasi_config_inherit_stdout(wasi_config_t *config); #endif #if defined(WASMER_WASI_ENABLED) -Option_Box_wasi_config_t wasi_config_new(const char *program_name); +wasi_config_t *wasi_config_new(const char *program_name); #endif #if defined(WASMER_WASI_ENABLED) -void wasi_env_delete(Option_Box_wasi_env_t _state); +void wasi_env_delete(wasi_env_t *_state); #endif #if defined(WASMER_WASI_ENABLED) /** * Takes ownership over the `wasi_config_t`. */ -Option_Box_wasi_env_t wasi_env_new(Box_wasi_config_t config); +wasi_env_t *wasi_env_new(wasi_config_t *config); #endif #if defined(WASMER_WASI_ENABLED) diff --git a/lib/c-api/wasmer.hh b/lib/c-api/wasmer.hh index 09781e1ce..7b3db3acb 100644 --- a/lib/c-api/wasmer.hh +++ b/lib/c-api/wasmer.hh @@ -109,25 +109,18 @@ struct Box; template struct Option; +#if defined(WASMER_WASI_ENABLED) +struct wasi_config_t; +#endif + +#if defined(WASMER_WASI_ENABLED) +struct wasi_env_t; +#endif + #if defined(WASMER_WASI_ENABLED) struct wasi_version_t; #endif -#if defined(WASMER_WASI_ENABLED) -struct wasi_config_t { - bool inherit_stdout; - bool inherit_stderr; - bool inherit_stdin; - WasiStateBuilder state_builder; -}; -#endif - -#if defined(WASMER_WASI_ENABLED) -struct wasi_env_t { - WasiEnv inner; -}; -#endif - struct wasmer_module_t { }; diff --git a/lib/c-api/wasmer_wasm.h b/lib/c-api/wasmer_wasm.h index 729603086..112f1d83c 100644 --- a/lib/c-api/wasmer_wasm.h +++ b/lib/c-api/wasmer_wasm.h @@ -51,25 +51,18 @@ #include #include "wasm.h" +#if defined(WASMER_WASI_ENABLED) +typedef struct wasi_config_t wasi_config_t; +#endif + +#if defined(WASMER_WASI_ENABLED) +typedef struct wasi_env_t wasi_env_t; +#endif + #if defined(WASMER_WASI_ENABLED) typedef struct wasi_version_t wasi_version_t; #endif -#if defined(WASMER_WASI_ENABLED) -typedef struct { - bool inherit_stdout; - bool inherit_stderr; - bool inherit_stdin; - WasiStateBuilder state_builder; -} wasi_config_t; -#endif - -#if defined(WASMER_WASI_ENABLED) -typedef struct { - WasiEnv inner; -} wasi_env_t; -#endif - #if defined(WASMER_WASI_ENABLED) void wasi_config_arg(wasi_config_t *config, const char *arg); #endif From f5a57b84e9846333537131fa23dce8391b1837e0 Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Tue, 29 Sep 2020 16:21:16 +0200 Subject: [PATCH 080/281] fix(c-api) Exclude non-standard WASI API from `wasmer.h`. --- lib/c-api/build.rs | 322 +++++++++++++++++++++++++-------------------- 1 file changed, 178 insertions(+), 144 deletions(-) diff --git a/lib/c-api/build.rs b/lib/c-api/build.rs index cd7c6c06c..f506a1217 100644 --- a/lib/c-api/build.rs +++ b/lib/c-api/build.rs @@ -69,6 +69,7 @@ fn main() { build_wasmer_headers(&crate_dir, &out_dir); } +#[allow(unused)] fn build_wasm_c_api_headers(crate_dir: &str, out_dir: &str) { let mut crate_header_file = PathBuf::from(crate_dir); crate_header_file.push("wasmer_wasm"); @@ -124,146 +125,7 @@ fn build_wasm_c_api_headers(crate_dir: &str, out_dir: &str) { .with_define("feature", "deprecated", DEPRECATED_FEATURE_AS_C_DEFINE) .with_include("wasm.h") .with_documentation(true); - - #[cfg(not(feature = "deprecated"))] - { - // List of all functions to exclude given by: - // - // `rg 'extern "C" fn' deprecated/` builder = builder - builder = builder - .exclude_item("wasmer_compile") - .exclude_item("wasmer_emscripten_call_main") - .exclude_item("wasmer_emscripten_destroy_globals") - .exclude_item("wasmer_emscripten_generate_import_object") - .exclude_item("wasmer_emscripten_get_globals") - .exclude_item("wasmer_emscripten_set_up") - .exclude_item("wasmer_export_descriptor_kind") - .exclude_item("wasmer_export_descriptor_name") - .exclude_item("wasmer_export_descriptors") - .exclude_item("wasmer_export_descriptors_destroy") - .exclude_item("wasmer_export_descriptors_get") - .exclude_item("wasmer_export_descriptors_len") - .exclude_item("wasmer_export_func_call") - .exclude_item("wasmer_export_func_params") - .exclude_item("wasmer_export_func_params_arity") - .exclude_item("wasmer_export_func_returns") - .exclude_item("wasmer_export_func_returns_arity") - .exclude_item("wasmer_export_kind") - .exclude_item("wasmer_export_name") - .exclude_item("wasmer_export_to_func") - .exclude_item("wasmer_export_to_memory") - .exclude_item("wasmer_exports_destroy") - .exclude_item("wasmer_exports_get") - .exclude_item("wasmer_exports_len") - .exclude_item("wasmer_global_destroy") - .exclude_item("wasmer_global_get") - .exclude_item("wasmer_global_get_descriptor") - .exclude_item("wasmer_global_new") - .exclude_item("wasmer_global_set") - .exclude_item("wasmer_import_descriptor_kind") - .exclude_item("wasmer_import_descriptor_module_name") - .exclude_item("wasmer_import_descriptor_name") - .exclude_item("wasmer_import_descriptors") - .exclude_item("wasmer_import_descriptors_destroy") - .exclude_item("wasmer_import_descriptors_get") - .exclude_item("wasmer_import_descriptors_len") - .exclude_item("wasmer_import_func_destroy") - .exclude_item("wasmer_import_func_new") - .exclude_item("wasmer_import_func_params") - .exclude_item("wasmer_import_func_params_arity") - .exclude_item("wasmer_import_func_returns") - .exclude_item("wasmer_import_func_returns_arity") - .exclude_item("wasmer_import_object_destroy") - .exclude_item("wasmer_import_object_extend") - .exclude_item("wasmer_import_object_get_import") - .exclude_item("wasmer_import_object_imports_destroy") - .exclude_item("wasmer_import_object_iter_at_end") - .exclude_item("wasmer_import_object_iter_destroy") - .exclude_item("wasmer_import_object_iter_next") - .exclude_item("wasmer_import_object_iterate_functions") - .exclude_item("wasmer_import_object_new") - .exclude_item("wasmer_import_object_new") - .exclude_item("wasmer_instance_call") - .exclude_item("wasmer_instance_context_data_get") - .exclude_item("wasmer_instance_context_data_set") - .exclude_item("wasmer_instance_context_get") - .exclude_item("wasmer_instance_context_memory") - .exclude_item("wasmer_instance_destroy") - .exclude_item("wasmer_instance_exports") - .exclude_item("wasmer_instantiate") - .exclude_item("wasmer_memory_data") - .exclude_item("wasmer_memory_data_length") - .exclude_item("wasmer_memory_destroy") - .exclude_item("wasmer_memory_grow") - .exclude_item("wasmer_memory_length") - .exclude_item("wasmer_memory_new") - .exclude_item("wasmer_module_deserialize") - .exclude_item("wasmer_module_destroy") - .exclude_item("wasmer_module_import_instantiate") - .exclude_item("wasmer_module_instantiate") - .exclude_item("wasmer_module_serialize") - .exclude_item("wasmer_serialized_module_bytes") - .exclude_item("wasmer_serialized_module_destroy") - .exclude_item("wasmer_serialized_module_from_bytes") - .exclude_item("wasmer_table_destroy") - .exclude_item("wasmer_table_grow") - .exclude_item("wasmer_table_length") - .exclude_item("wasmer_table_new") - .exclude_item("wasmer_trampoline_buffer_builder_add_callinfo_trampoline") - .exclude_item("wasmer_trampoline_buffer_builder_add_context_trampoline") - .exclude_item("wasmer_trampoline_buffer_builder_build") - .exclude_item("wasmer_trampoline_buffer_builder_new") - .exclude_item("wasmer_trampoline_buffer_destroy") - .exclude_item("wasmer_trampoline_buffer_get_trampoline") - .exclude_item("wasmer_trampoline_get_context") - .exclude_item("wasmer_trap") - .exclude_item("wasmer_validate") - .exclude_item("wasmer_wasi_generate_default_import_object") - .exclude_item("wasmer_wasi_generate_import_object") - .exclude_item("wasmer_wasi_generate_import_object_for_version") - .exclude_item("wasmer_wasi_get_version"); - - // List of all structs and enums to exclude given by: - // - // `rg 'pub (enum|struct|union)' deprecated/` - builder = builder - .exclude_item("NamedExportDescriptors(Vec)") - .exclude_item("NamedImportDescriptors(Vec)") - .exclude_item("Version") - .exclude_item("WasmerImportObjectIterator") - .exclude_item("wasmer_byte_array") - .exclude_item("wasmer_emscripten_globals_t") - .exclude_item("wasmer_export_descriptor_t") - .exclude_item("wasmer_export_descriptors_t") - .exclude_item("wasmer_export_func_t") - .exclude_item("wasmer_export_t") - .exclude_item("wasmer_exports_t") - .exclude_item("wasmer_global_descriptor_t") - .exclude_item("wasmer_global_t") - .exclude_item("wasmer_import_descriptor_t") - .exclude_item("wasmer_import_descriptors_t") - .exclude_item("wasmer_import_export_kind") - .exclude_item("wasmer_import_func_t") - .exclude_item("wasmer_import_object_iter_t") - .exclude_item("wasmer_import_object_t") - .exclude_item("wasmer_import_t") - .exclude_item("wasmer_instance_context_t") - .exclude_item("wasmer_instance_t") - .exclude_item("wasmer_limit_option_t") - .exclude_item("wasmer_limits_t") - .exclude_item("wasmer_memory_t") - .exclude_item("wasmer_module_t") - .exclude_item("wasmer_result_t") - .exclude_item("wasmer_serialized_module_t") - .exclude_item("wasmer_table_t") - .exclude_item("wasmer_trampoline_buffer_builder_t") - .exclude_item("wasmer_trampoline_buffer_t") - .exclude_item("wasmer_trampoline_callable_t") - .exclude_item("wasmer_value_t") - .exclude_item("wasmer_value_tag") - .exclude_item("wasmer_wasi_map_dir_entry_t"); - } - + builder = exclude_items_from_deprecated(builder); builder .generate() .expect("Unable to generate C bindings") @@ -278,6 +140,7 @@ fn build_wasm_c_api_headers(crate_dir: &str, out_dir: &str) { } } +#[allow(unused)] fn build_wasmer_headers(crate_dir: &str, out_dir: &str) { let mut crate_header_file = PathBuf::from(crate_dir); crate_header_file.push("wasmer"); @@ -314,7 +177,7 @@ fn build_wasmer_headers(crate_dir: &str, out_dir: &str) { // Generate the bindings in the `OUT_DIR`. out_header_file.set_extension("h"); - Builder::new() + let mut builder = Builder::new() .with_language(Language::C) .with_crate(crate_dir) .with_include_guard("WASMER_H") @@ -323,7 +186,9 @@ fn build_wasmer_headers(crate_dir: &str, out_dir: &str) { .with_define("target_arch", "x86_64", "ARCH_X86_64") .with_define("feature", "wasi", WASI_FEATURE_AS_C_DEFINE) .with_define("feature", "emscripten", EMSCRIPTEN_FEATURE_AS_C_DEFINE) - .with_documentation(true) + .with_documentation(true); + builder = exclude_items_from_wasm_c_api(builder); + builder .generate() .expect("Unable to generate C bindings") .write_to_file(out_header_file.as_path()); @@ -341,7 +206,7 @@ fn build_wasmer_headers(crate_dir: &str, out_dir: &str) { // Generate the bindings in the `OUT_DIR`. out_header_file.set_extension("hh"); - Builder::new() + let mut builder = Builder::new() .with_language(Language::Cxx) .with_crate(crate_dir) .with_include_guard("WASMER_H") @@ -350,7 +215,9 @@ fn build_wasmer_headers(crate_dir: &str, out_dir: &str) { .with_define("target_arch", "x86_64", "ARCH_X86_64") .with_define("feature", "wasi", WASI_FEATURE_AS_C_DEFINE) .with_define("feature", "emscripten", EMSCRIPTEN_FEATURE_AS_C_DEFINE) - .with_documentation(true) + .with_documentation(true); + builder = exclude_items_from_wasm_c_api(builder); + builder .generate() .expect("Unable to generate C++ bindings") .write_to_file(out_header_file.as_path()); @@ -363,3 +230,170 @@ fn build_wasmer_headers(crate_dir: &str, out_dir: &str) { .expect("Unable to copy the generated C++ bindings"); } } + +fn exclude_items_from_deprecated(mut builder: Builder) -> Builder { + // List of all functions to exclude given by: + // + // `rg 'extern "C" fn' deprecated/` builder = builder + builder = builder + .exclude_item("wasmer_compile") + .exclude_item("wasmer_emscripten_call_main") + .exclude_item("wasmer_emscripten_destroy_globals") + .exclude_item("wasmer_emscripten_generate_import_object") + .exclude_item("wasmer_emscripten_get_globals") + .exclude_item("wasmer_emscripten_set_up") + .exclude_item("wasmer_export_descriptor_kind") + .exclude_item("wasmer_export_descriptor_name") + .exclude_item("wasmer_export_descriptors") + .exclude_item("wasmer_export_descriptors_destroy") + .exclude_item("wasmer_export_descriptors_get") + .exclude_item("wasmer_export_descriptors_len") + .exclude_item("wasmer_export_func_call") + .exclude_item("wasmer_export_func_params") + .exclude_item("wasmer_export_func_params_arity") + .exclude_item("wasmer_export_func_returns") + .exclude_item("wasmer_export_func_returns_arity") + .exclude_item("wasmer_export_kind") + .exclude_item("wasmer_export_name") + .exclude_item("wasmer_export_to_func") + .exclude_item("wasmer_export_to_memory") + .exclude_item("wasmer_exports_destroy") + .exclude_item("wasmer_exports_get") + .exclude_item("wasmer_exports_len") + .exclude_item("wasmer_global_destroy") + .exclude_item("wasmer_global_get") + .exclude_item("wasmer_global_get_descriptor") + .exclude_item("wasmer_global_new") + .exclude_item("wasmer_global_set") + .exclude_item("wasmer_import_descriptor_kind") + .exclude_item("wasmer_import_descriptor_module_name") + .exclude_item("wasmer_import_descriptor_name") + .exclude_item("wasmer_import_descriptors") + .exclude_item("wasmer_import_descriptors_destroy") + .exclude_item("wasmer_import_descriptors_get") + .exclude_item("wasmer_import_descriptors_len") + .exclude_item("wasmer_import_func_destroy") + .exclude_item("wasmer_import_func_new") + .exclude_item("wasmer_import_func_params") + .exclude_item("wasmer_import_func_params_arity") + .exclude_item("wasmer_import_func_returns") + .exclude_item("wasmer_import_func_returns_arity") + .exclude_item("wasmer_import_object_destroy") + .exclude_item("wasmer_import_object_extend") + .exclude_item("wasmer_import_object_get_import") + .exclude_item("wasmer_import_object_imports_destroy") + .exclude_item("wasmer_import_object_iter_at_end") + .exclude_item("wasmer_import_object_iter_destroy") + .exclude_item("wasmer_import_object_iter_next") + .exclude_item("wasmer_import_object_iterate_functions") + .exclude_item("wasmer_import_object_new") + .exclude_item("wasmer_import_object_new") + .exclude_item("wasmer_instance_call") + .exclude_item("wasmer_instance_context_data_get") + .exclude_item("wasmer_instance_context_data_set") + .exclude_item("wasmer_instance_context_get") + .exclude_item("wasmer_instance_context_memory") + .exclude_item("wasmer_instance_destroy") + .exclude_item("wasmer_instance_exports") + .exclude_item("wasmer_instantiate") + .exclude_item("wasmer_memory_data") + .exclude_item("wasmer_memory_data_length") + .exclude_item("wasmer_memory_destroy") + .exclude_item("wasmer_memory_grow") + .exclude_item("wasmer_memory_length") + .exclude_item("wasmer_memory_new") + .exclude_item("wasmer_module_deserialize") + .exclude_item("wasmer_module_destroy") + .exclude_item("wasmer_module_import_instantiate") + .exclude_item("wasmer_module_instantiate") + .exclude_item("wasmer_module_serialize") + .exclude_item("wasmer_serialized_module_bytes") + .exclude_item("wasmer_serialized_module_destroy") + .exclude_item("wasmer_serialized_module_from_bytes") + .exclude_item("wasmer_table_destroy") + .exclude_item("wasmer_table_grow") + .exclude_item("wasmer_table_length") + .exclude_item("wasmer_table_new") + .exclude_item("wasmer_trampoline_buffer_builder_add_callinfo_trampoline") + .exclude_item("wasmer_trampoline_buffer_builder_add_context_trampoline") + .exclude_item("wasmer_trampoline_buffer_builder_build") + .exclude_item("wasmer_trampoline_buffer_builder_new") + .exclude_item("wasmer_trampoline_buffer_destroy") + .exclude_item("wasmer_trampoline_buffer_get_trampoline") + .exclude_item("wasmer_trampoline_get_context") + .exclude_item("wasmer_trap") + .exclude_item("wasmer_validate") + .exclude_item("wasmer_wasi_generate_default_import_object") + .exclude_item("wasmer_wasi_generate_import_object") + .exclude_item("wasmer_wasi_generate_import_object_for_version") + .exclude_item("wasmer_wasi_get_version"); + + // List of all structs and enums to exclude given by: + // + // `rg 'pub (enum|struct|union)' deprecated/` + builder = builder + .exclude_item("NamedExportDescriptors(Vec)") + .exclude_item("NamedImportDescriptors(Vec)") + .exclude_item("Version") + .exclude_item("WasmerImportObjectIterator") + .exclude_item("wasmer_byte_array") + .exclude_item("wasmer_emscripten_globals_t") + .exclude_item("wasmer_export_descriptor_t") + .exclude_item("wasmer_export_descriptors_t") + .exclude_item("wasmer_export_func_t") + .exclude_item("wasmer_export_t") + .exclude_item("wasmer_exports_t") + .exclude_item("wasmer_global_descriptor_t") + .exclude_item("wasmer_global_t") + .exclude_item("wasmer_import_descriptor_t") + .exclude_item("wasmer_import_descriptors_t") + .exclude_item("wasmer_import_export_kind") + .exclude_item("wasmer_import_func_t") + .exclude_item("wasmer_import_object_iter_t") + .exclude_item("wasmer_import_object_t") + .exclude_item("wasmer_import_t") + .exclude_item("wasmer_instance_context_t") + .exclude_item("wasmer_instance_t") + .exclude_item("wasmer_limit_option_t") + .exclude_item("wasmer_limits_t") + .exclude_item("wasmer_memory_t") + .exclude_item("wasmer_module_t") + .exclude_item("wasmer_result_t") + .exclude_item("wasmer_serialized_module_t") + .exclude_item("wasmer_table_t") + .exclude_item("wasmer_trampoline_buffer_builder_t") + .exclude_item("wasmer_trampoline_buffer_t") + .exclude_item("wasmer_trampoline_callable_t") + .exclude_item("wasmer_value_t") + .exclude_item("wasmer_value_tag") + .exclude_item("wasmer_wasi_map_dir_entry_t"); + + builder +} + +fn exclude_items_from_wasm_c_api(mut builder: Builder) -> Builder { + // All items defined in `wasm.h` are ignored by cbindgen, because + // we don't want duplications. We must exclude extra non-standard + // items, like the ones from the WASI API. + builder = builder + .exclude_item("wasi_config_arg") + .exclude_item("wasi_config_env") + .exclude_item("wasi_config_inherit_stderr") + .exclude_item("wasi_config_inherit_stdin") + .exclude_item("wasi_config_inherit_stdout") + .exclude_item("wasi_config_new") + .exclude_item("wasi_config_t") + .exclude_item("wasi_env_delete") + .exclude_item("wasi_env_new") + .exclude_item("wasi_env_read_stderr") + .exclude_item("wasi_env_read_stdout") + .exclude_item("wasi_env_set_instance") + .exclude_item("wasi_env_set_memory") + .exclude_item("wasi_env_t") + .exclude_item("wasi_get_imports") + .exclude_item("wasi_get_imports_inner") + .exclude_item("wasi_get_wasi_version") + .exclude_item("wasi_version_t"); + + builder +} From a259ac6862c672b2de20fead96f41fe151ca0480 Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Tue, 29 Sep 2020 16:21:48 +0200 Subject: [PATCH 081/281] chore(c-api) Regenerate `wasmer.h` header files. --- lib/c-api/wasmer.h | 77 ------------------------------------------- lib/c-api/wasmer.hh | 79 --------------------------------------------- 2 files changed, 156 deletions(-) diff --git a/lib/c-api/wasmer.h b/lib/c-api/wasmer.h index 3e01c5e79..f01244dbd 100644 --- a/lib/c-api/wasmer.h +++ b/lib/c-api/wasmer.h @@ -140,18 +140,6 @@ enum wasmer_value_tag { }; typedef uint32_t wasmer_value_tag; -#if defined(WASMER_WASI_ENABLED) -typedef struct wasi_config_t wasi_config_t; -#endif - -#if defined(WASMER_WASI_ENABLED) -typedef struct wasi_env_t wasi_env_t; -#endif - -#if defined(WASMER_WASI_ENABLED) -typedef struct wasi_version_t wasi_version_t; -#endif - typedef struct { } wasmer_module_t; @@ -413,71 +401,6 @@ typedef struct { } wasmer_wasi_map_dir_entry_t; #endif -#if defined(WASMER_WASI_ENABLED) -void wasi_config_arg(wasi_config_t *config, const char *arg); -#endif - -#if defined(WASMER_WASI_ENABLED) -void wasi_config_env(wasi_config_t *config, const char *key, const char *value); -#endif - -#if defined(WASMER_WASI_ENABLED) -void wasi_config_inherit_stderr(wasi_config_t *config); -#endif - -#if defined(WASMER_WASI_ENABLED) -void wasi_config_inherit_stdin(wasi_config_t *config); -#endif - -#if defined(WASMER_WASI_ENABLED) -void wasi_config_inherit_stdout(wasi_config_t *config); -#endif - -#if defined(WASMER_WASI_ENABLED) -wasi_config_t *wasi_config_new(const char *program_name); -#endif - -#if defined(WASMER_WASI_ENABLED) -void wasi_env_delete(wasi_env_t *_state); -#endif - -#if defined(WASMER_WASI_ENABLED) -/** - * Takes ownership over the `wasi_config_t`. - */ -wasi_env_t *wasi_env_new(wasi_config_t *config); -#endif - -#if defined(WASMER_WASI_ENABLED) -intptr_t wasi_env_read_stderr(wasi_env_t *env, char *buffer, uintptr_t buffer_len); -#endif - -#if defined(WASMER_WASI_ENABLED) -intptr_t wasi_env_read_stdout(wasi_env_t *env, char *buffer, uintptr_t buffer_len); -#endif - -#if defined(WASMER_WASI_ENABLED) -bool wasi_env_set_instance(wasi_env_t *env, const wasm_instance_t *instance); -#endif - -#if defined(WASMER_WASI_ENABLED) -void wasi_env_set_memory(wasi_env_t *env, const wasm_memory_t *memory); -#endif - -#if defined(WASMER_WASI_ENABLED) -/** - * Takes ownership of `wasi_env_t`. - */ -bool wasi_get_imports(wasm_store_t *store, - const wasm_module_t *module, - const wasi_env_t *wasi_env, - wasm_extern_t **imports); -#endif - -#if defined(WASMER_WASI_ENABLED) -wasi_version_t wasi_get_wasi_version(const wasm_module_t *module); -#endif - /** * Creates a new Module from the given wasm bytes. * diff --git a/lib/c-api/wasmer.hh b/lib/c-api/wasmer.hh index 7b3db3acb..4ca7f20a6 100644 --- a/lib/c-api/wasmer.hh +++ b/lib/c-api/wasmer.hh @@ -103,24 +103,6 @@ enum class wasmer_value_tag : uint32_t { WASM_F64, }; -template -struct Box; - -template -struct Option; - -#if defined(WASMER_WASI_ENABLED) -struct wasi_config_t; -#endif - -#if defined(WASMER_WASI_ENABLED) -struct wasi_env_t; -#endif - -#if defined(WASMER_WASI_ENABLED) -struct wasi_version_t; -#endif - struct wasmer_module_t { }; @@ -338,67 +320,6 @@ struct wasmer_wasi_map_dir_entry_t { extern "C" { -#if defined(WASMER_WASI_ENABLED) -void wasi_config_arg(wasi_config_t *config, const char *arg); -#endif - -#if defined(WASMER_WASI_ENABLED) -void wasi_config_env(wasi_config_t *config, const char *key, const char *value); -#endif - -#if defined(WASMER_WASI_ENABLED) -void wasi_config_inherit_stderr(wasi_config_t *config); -#endif - -#if defined(WASMER_WASI_ENABLED) -void wasi_config_inherit_stdin(wasi_config_t *config); -#endif - -#if defined(WASMER_WASI_ENABLED) -void wasi_config_inherit_stdout(wasi_config_t *config); -#endif - -#if defined(WASMER_WASI_ENABLED) -Option> wasi_config_new(const char *program_name); -#endif - -#if defined(WASMER_WASI_ENABLED) -void wasi_env_delete(Option> _state); -#endif - -#if defined(WASMER_WASI_ENABLED) -/// Takes ownership over the `wasi_config_t`. -Option> wasi_env_new(Box config); -#endif - -#if defined(WASMER_WASI_ENABLED) -intptr_t wasi_env_read_stderr(wasi_env_t *env, char *buffer, uintptr_t buffer_len); -#endif - -#if defined(WASMER_WASI_ENABLED) -intptr_t wasi_env_read_stdout(wasi_env_t *env, char *buffer, uintptr_t buffer_len); -#endif - -#if defined(WASMER_WASI_ENABLED) -bool wasi_env_set_instance(wasi_env_t *env, const wasm_instance_t *instance); -#endif - -#if defined(WASMER_WASI_ENABLED) -void wasi_env_set_memory(wasi_env_t *env, const wasm_memory_t *memory); -#endif - -#if defined(WASMER_WASI_ENABLED) -/// Takes ownership of `wasi_env_t`. -bool wasi_get_imports(wasm_store_t *store, - const wasm_module_t *module, - const wasi_env_t *wasi_env, - wasm_extern_t **imports); -#endif - -#if defined(WASMER_WASI_ENABLED) -wasi_version_t wasi_get_wasi_version(const wasm_module_t *module); -#endif - /// Creates a new Module from the given wasm bytes. /// /// Returns `wasmer_result_t::WASMER_OK` upon success. From 374cd36ec2381a620780762b046bc996d45f4788 Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Tue, 29 Sep 2020 10:56:02 -0700 Subject: [PATCH 082/281] Add early exit Wasm C API example (wip) --- lib/c-api/src/wasm_c_api/mod.rs | 20 +++- lib/c-api/tests/CMakeLists.txt | 5 + lib/c-api/tests/assets/call_trap.wasm | Bin 0 -> 66 bytes lib/c-api/tests/assets/call_trap.wat | 10 ++ lib/c-api/tests/wasm-c-api-trap.c | 128 ++++++++++++++++++++++++++ 5 files changed, 158 insertions(+), 5 deletions(-) create mode 100644 lib/c-api/tests/assets/call_trap.wasm create mode 100644 lib/c-api/tests/assets/call_trap.wat create mode 100644 lib/c-api/tests/wasm-c-api-trap.c diff --git a/lib/c-api/src/wasm_c_api/mod.rs b/lib/c-api/src/wasm_c_api/mod.rs index 79737d3ac..5fc32e4af 100644 --- a/lib/c-api/src/wasm_c_api/mod.rs +++ b/lib/c-api/src/wasm_c_api/mod.rs @@ -1150,15 +1150,22 @@ pub struct wasm_ref_t; // opaque type which is a `RuntimeError` #[repr(C)] -pub struct wasm_trap_t {} +pub struct wasm_trap_t { + // have a vec of frames +// have a message +} #[no_mangle] -pub unsafe extern "C" fn wasm_trap_delete(trap: Option>) { - if let Some(t_inner) = trap { - let _ = Box::from_raw(t_inner.cast::().as_ptr()); - } +pub unsafe extern "C" fn wasm_trap_new( + store: &mut wasm_store_t, + message: &wasm_message_t, +) -> Box { + todo!() } +#[no_mangle] +pub unsafe extern "C" fn wasm_trap_delete(_trap: Option>) {} + #[no_mangle] pub unsafe extern "C" fn wasm_trap_message( trap: *const wasm_trap_t, @@ -1769,6 +1776,9 @@ pub unsafe extern "C" fn wasm_tabletype_as_externtype( #[allow(non_camel_case_types)] type wasm_name_t = wasm_byte_vec_t; +#[allow(non_camel_case_types)] +type wasm_message_t = wasm_byte_vec_t; + #[repr(C)] #[allow(non_camel_case_types)] pub struct wasm_exporttype_t { diff --git a/lib/c-api/tests/CMakeLists.txt b/lib/c-api/tests/CMakeLists.txt index 728e11181..339eaf53f 100644 --- a/lib/c-api/tests/CMakeLists.txt +++ b/lib/c-api/tests/CMakeLists.txt @@ -35,6 +35,7 @@ add_executable(wasm-c-api-serialize wasm-c-api/example/serialize.c) # Custom Wasm C API tests add_executable(wasm-c-api-wasi wasm-c-api-wasi.c) +add_executable(wasm-c-api-trap wasm-c-api-trap.c) if (DEFINED WASI_TESTS) add_executable(test-wasi-import-object test-wasi-import-object.c) @@ -249,3 +250,7 @@ target_link_libraries(wasm-c-api-wasi general ${WASMER_LIB}) target_compile_options(wasm-c-api-wasi PRIVATE ${COMPILER_OPTIONS}) add_test(wasm-c-api-wasi wasm-c-api-wasi) +set_property(TARGET wasm-c-api-trap PROPERTY C_STANDARD 11) +target_link_libraries(wasm-c-api-trap general ${WASMER_LIB}) +target_compile_options(wasm-c-api-trap PRIVATE ${COMPILER_OPTIONS}) +add_test(wasm-c-api-trap wasm-c-api-trap) diff --git a/lib/c-api/tests/assets/call_trap.wasm b/lib/c-api/tests/assets/call_trap.wasm new file mode 100644 index 0000000000000000000000000000000000000000..44cbb2797532a9beacc593922220267163546cae GIT binary patch literal 66 zcmZQbEY4+QU|?Y6VoG4DuV<`JU|?VpVq{LuE8|K{EXt{jPp!x-VPIrtVq{=vXJjra U%>%0CX5?fLU{GLCV9eqM0IV+yg#Z8m literal 0 HcmV?d00001 diff --git a/lib/c-api/tests/assets/call_trap.wat b/lib/c-api/tests/assets/call_trap.wat new file mode 100644 index 000000000..6f4bb0f80 --- /dev/null +++ b/lib/c-api/tests/assets/call_trap.wat @@ -0,0 +1,10 @@ +(module + (type $run_t (func (param i32 i32) (result i32))) + (type $early_exit_t (func (param) (result))) + (import "env" "early_exit" (func $early_exit (type $early_exit_t))) + (func $run (type $run_t) (param $x i32) (param $y i32) (result i32) + (call $early_exit) + (i32.add + (local.get $x) + (local.get $y))) + (export "run" (func $run))) \ No newline at end of file diff --git a/lib/c-api/tests/wasm-c-api-trap.c b/lib/c-api/tests/wasm-c-api-trap.c new file mode 100644 index 000000000..b2a777c50 --- /dev/null +++ b/lib/c-api/tests/wasm-c-api-trap.c @@ -0,0 +1,128 @@ +#include +#include +#include +#include + +#include "wasm.h" +#include "wasmer_wasm.h" + +// Use the last_error API to retrieve error messages +void print_wasmer_error() +{ + int error_len = wasmer_last_error_length(); + printf("Error len: `%d`\n", error_len); + char *error_str = malloc(error_len); + wasmer_last_error_message(error_str, error_len); + printf("Error str: `%s`\n", error_str); +} + +wasm_store_t* store = NULL; + +wasm_trap_t* early_exit(wasm_val_t args[], wasm_val_t results[]) { + wasm_message_t* trap_message = NULL; + const char* message_inner = "trapping from a host import"; + wasm_byte_vec_new_uninitialized(trap_message, strlen(message_inner)); + // TODO: should we free this data? + return wasm_trap_new(store, trap_message); +} + +int main(int argc, const char* argv[]) { + // Initialize. + printf("Initializing...\n"); + wasm_engine_t* engine = wasm_engine_new(); + store = wasm_store_new(engine); + + // Load binary. + printf("Loading binary...\n"); + FILE* file = fopen("assets/call_trap.wasm", "r"); + if (!file) { + printf("> Error loading module!\n"); + return 1; + } + fseek(file, 0L, SEEK_END); + size_t file_size = ftell(file); + fseek(file, 0L, SEEK_SET); + wasm_byte_vec_t binary; + wasm_byte_vec_new_uninitialized(&binary, file_size); + if (fread(binary.data, file_size, 1, file) != 1) { + printf("> Error loading module!\n"); + return 1; + } + fclose(file); + + // Compile. + printf("Compiling module...\n"); + own wasm_module_t* module = wasm_module_new(store, &binary); + if (!module) { + printf("> Error compiling module!\n"); + return 1; + } + + wasm_byte_vec_delete(&binary); + + // Instantiate. + printf("Instantiating module...\n"); + + // TODO: fill imports + + wasm_functype_t* host_func_type = wasm_functype_new_0_0(); + wasm_func_t* host_func = wasm_func_new(store, host_func_type, (wasm_func_callback_t)early_exit); + wasm_extern_t* host_func_as_extern = wasm_func_as_extern(host_func); + wasm_functype_delete(host_func_type); + + wasm_extern_t* imports[] = { host_func_as_extern }; + + own wasm_instance_t* instance = + wasm_instance_new(store, module, (const wasm_extern_t *const *) imports, NULL); + if (!instance) { + printf("> Error instantiating module!\n"); + print_wasmer_error(); + return 1; + } + + // Extract export. + printf("Extracting export...\n"); + own wasm_extern_vec_t exports; + wasm_instance_exports(instance, &exports); + if (exports.size == 0) { + printf("> Error accessing exports!\n"); + return 1; + } + fprintf(stderr, "found %zu exports\n", exports.size); + + // TODO: + wasm_func_t* run_func = NULL; + if (run_func == NULL) { + printf("> Error accessing export!\n"); + print_wasmer_error(); + return 1; + } + + wasm_module_delete(module); + wasm_instance_delete(instance); + + // Call. + printf("Calling export...\n"); + if (wasm_func_call(run_func, NULL, NULL)) { + printf("> Error calling function!\n"); + return 1; + } + + wasm_extern_vec_delete(&exports); + + // NEEDS REVIEW: + for(int i = 0; i < num_imports; ++i) { + wasm_extern_delete(imports[i]); + } + free(imports); + + // Shut down. + printf("Shutting down...\n"); + wasm_func_delete(run_func); + wasm_store_delete(store); + wasm_engine_delete(engine); + + // All done. + printf("Done.\n"); + return 0; +} From 58f7650a089f7094e7781ab6a48173bda6420e82 Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Tue, 29 Sep 2020 11:03:58 -0700 Subject: [PATCH 083/281] Add debug code to figure out why C compilation fails on Windows --- tests/integration/cli/src/compile.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tests/integration/cli/src/compile.rs b/tests/integration/cli/src/compile.rs index 2313222c2..62e897c09 100644 --- a/tests/integration/cli/src/compile.rs +++ b/tests/integration/cli/src/compile.rs @@ -137,6 +137,10 @@ fn run_c_compile(path_to_c_src: &Path, output_name: &Path) -> anyhow::Result<()> let c_compiler = "cc"; #[cfg(windows)] let c_compiler = "clang"; + + dbg!(path_to_c_src.exists()); + dbg!(Path::new(CLI_INTEGRATION_TESTS_ASSETS).exists()); + dbg!(Command::new(c_compiler).arg("--help").output()); let output = Command::new(c_compiler) .arg("-O2") .arg("-c") @@ -200,7 +204,6 @@ impl LinkCode { .map(|path| path.canonicalize().unwrap()), ) .arg(&self.libwasmer_path.canonicalize()?) - .arg("-lffi") .arg("-ldl") .arg("-lm") .arg("-pthread") From 00741f02cbde72acb0fe5c88f5622b545e9d8280 Mon Sep 17 00:00:00 2001 From: Nick Lewycky Date: Tue, 29 Sep 2020 11:04:54 -0700 Subject: [PATCH 084/281] Remove `extern "C"` from a non-pub function that returns non-FFI'able type. Add `extern "C"` to two `#[no_mangle] pub` functions. --- lib/c-api/src/wasm_c_api/wasi/mod.rs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/lib/c-api/src/wasm_c_api/wasi/mod.rs b/lib/c-api/src/wasm_c_api/wasi/mod.rs index 9b6d4529a..d662ba1f0 100644 --- a/lib/c-api/src/wasm_c_api/wasi/mod.rs +++ b/lib/c-api/src/wasm_c_api/wasi/mod.rs @@ -248,7 +248,7 @@ pub unsafe extern "C" fn wasi_get_imports( } /// Takes ownership of `wasi_env_t`. -unsafe extern "C" fn wasi_get_imports_inner( +unsafe fn wasi_get_imports_inner( store: Option>, module: &wasm_module_t, wasi_env: &wasi_env_t, @@ -286,7 +286,9 @@ unsafe extern "C" fn wasi_get_imports_inner( } #[no_mangle] -pub unsafe fn wasi_get_start_function(instance: &mut wasm_instance_t) -> Option> { +pub unsafe extern "C" fn wasi_get_start_function( + instance: &mut wasm_instance_t, +) -> Option> { let f = c_try!(instance.inner.exports.get_function("_start")); Some(Box::new(wasm_func_t { inner: f.clone(), @@ -296,4 +298,4 @@ pub unsafe fn wasi_get_start_function(instance: &mut wasm_instance_t) -> Option< /// Delete a `wasm_extern_t` allocated by the API. #[no_mangle] -pub unsafe fn wasm_extern_delete(_item: Option>) {} +pub unsafe extern "C" fn wasm_extern_delete(_item: Option>) {} From dbfbfe084a47cea55d176545c7033a4293418043 Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Tue, 29 Sep 2020 11:05:11 -0700 Subject: [PATCH 085/281] Misc clean ups from feedback --- lib/engine-object-file/Cargo.toml | 1 - lib/engine-object-file/README.md | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/engine-object-file/Cargo.toml b/lib/engine-object-file/Cargo.toml index 47aee16c1..62570ec5b 100644 --- a/lib/engine-object-file/Cargo.toml +++ b/lib/engine-object-file/Cargo.toml @@ -6,7 +6,6 @@ description = "Wasmer Object File Engine" categories = ["wasm"] keywords = ["webassembly", "wasm"] repository = "https://github.com/wasmerio/wasmer" -# TODO: make a readme explaining what this crate is readme = "README.md" edition = "2018" diff --git a/lib/engine-object-file/README.md b/lib/engine-object-file/README.md index 8aefd4a02..a12bdeac4 100644 --- a/lib/engine-object-file/README.md +++ b/lib/engine-object-file/README.md @@ -1,6 +1,6 @@ # Wasmer Engine Object File -This is an [engine](https://crates.io/crates/wasmer-engine) for the [wasmer](https://crates.io/crates/wasmer/1.0.0-alpha01.0) WebAssembly VM. +This is an [engine](https://crates.io/crates/wasmer-engine) for the [wasmer](https://crates.io/crates/wasmer/1.0.0-alpha3) WebAssembly VM. This engine is used to produce native code that can be linked against providing a sandboxed WebAssembly runtime environment for the compiled module with no need From 1ed1a52d2505e6a9c90966a605bc593d1469501d Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Tue, 29 Sep 2020 14:11:39 -0700 Subject: [PATCH 086/281] Get early exit example working with C API; implement wasm_trap_t API --- CHANGELOG.md | 1 + lib/api/src/lib.rs | 4 +- lib/c-api/src/wasm_c_api/mod.rs | 129 +++++++++++++----- lib/c-api/tests/CMakeLists.txt | 24 ++-- ...m-c-api-trap.c => wasm-c-api-early-exit.c} | 94 ++++++++----- lib/engine/src/trap/frame_info.rs | 2 +- 6 files changed, 177 insertions(+), 77 deletions(-) rename lib/c-api/tests/{wasm-c-api-trap.c => wasm-c-api-early-exit.c} (55%) diff --git a/CHANGELOG.md b/CHANGELOG.md index ea7288f06..267fd762c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ # Changelog ## **[Unreleased]** +- [#1657](https://github.com/wasmerio/wasmer/pull/1657) Implement `wasm_trap_t` and `wasm_frame_t` for Wasm C API; add examples in Rust and C of exiting early with a host function. - [#1645](https://github.com/wasmerio/wasmer/pull/1645) Move the install script to https://github.com/wasmerio/wasmer-install ## 1.0.0-alpha3 - 2020-09-14 diff --git a/lib/api/src/lib.rs b/lib/api/src/lib.rs index f5631870d..6725141ae 100644 --- a/lib/api/src/lib.rs +++ b/lib/api/src/lib.rs @@ -70,8 +70,8 @@ pub use wasmer_compiler::{ }; pub use wasmer_compiler::{CpuFeature, Features, Target}; pub use wasmer_engine::{ - ChainableNamedResolver, DeserializeError, Engine, InstantiationError, LinkError, NamedResolver, - NamedResolverChain, Resolver, RuntimeError, SerializeError, + ChainableNamedResolver, DeserializeError, Engine, FrameInfo, InstantiationError, LinkError, + NamedResolver, NamedResolverChain, Resolver, RuntimeError, SerializeError, }; pub use wasmer_types::{ Atomically, Bytes, GlobalInit, LocalFunctionIndex, MemoryView, Pages, ValueType, diff --git a/lib/c-api/src/wasm_c_api/mod.rs b/lib/c-api/src/wasm_c_api/mod.rs index 5fc32e4af..e336d94eb 100644 --- a/lib/c-api/src/wasm_c_api/mod.rs +++ b/lib/c-api/src/wasm_c_api/mod.rs @@ -17,9 +17,9 @@ use crate::c_try; use crate::ordered_resolver::OrderedResolver; use wasmer::{ - Engine, ExportType, Extern, ExternType, Function, FunctionType, Global, GlobalType, ImportType, - Instance, Memory, MemoryType, Module, Mutability, Pages, RuntimeError, Store, Table, TableType, - Val, ValType, + Engine, ExportType, Extern, ExternType, FrameInfo, Function, FunctionType, Global, GlobalType, + ImportType, Instance, Memory, MemoryType, Module, Mutability, Pages, RuntimeError, Store, + Table, TableType, Val, ValType, }; #[cfg(feature = "jit")] use wasmer_engine_jit::JIT; @@ -712,7 +712,13 @@ pub unsafe extern "C" fn wasm_func_new( num_rets ]; - let _traps = callback(processed_args.as_ptr(), results.as_mut_ptr()); + let trap = callback(processed_args.as_ptr(), results.as_mut_ptr()); + dbg!(&trap); + if !trap.is_null() { + let trap: Box = Box::from_raw(trap); + dbg!("raising trap!"); + RuntimeError::raise(Box::new(trap.inner)); + } // TODO: do something with `traps` let processed_results = results @@ -783,7 +789,7 @@ pub unsafe extern "C" fn wasm_func_call( func: &wasm_func_t, args: *const wasm_val_t, results: *mut wasm_val_t, -) -> Option> { +) -> Option> { let num_params = func.inner.ty().params().len(); let params: Vec = (0..num_params) .map(|i| (&(*args.add(i))).try_into()) @@ -798,7 +804,7 @@ pub unsafe extern "C" fn wasm_func_call( } None } - Err(e) => Some(NonNull::new_unchecked(Box::into_raw(Box::new(e)) as _)), + Err(e) => Some(Box::new(e.into())), } } @@ -1151,37 +1157,47 @@ pub struct wasm_ref_t; // opaque type which is a `RuntimeError` #[repr(C)] pub struct wasm_trap_t { - // have a vec of frames -// have a message + inner: RuntimeError, +} + +impl From for wasm_trap_t { + fn from(other: RuntimeError) -> Self { + Self { inner: other } + } } #[no_mangle] pub unsafe extern "C" fn wasm_trap_new( - store: &mut wasm_store_t, + _store: &mut wasm_store_t, message: &wasm_message_t, -) -> Box { - todo!() +) -> Option> { + let message_bytes: &[u8] = message.into_slice()?; + let message_str = c_try!(std::str::from_utf8(message_bytes)); + let runtime_error = RuntimeError::new(message_str); + let trap = runtime_error.into(); + + Some(Box::new(trap)) } #[no_mangle] pub unsafe extern "C" fn wasm_trap_delete(_trap: Option>) {} #[no_mangle] -pub unsafe extern "C" fn wasm_trap_message( - trap: *const wasm_trap_t, - out_ptr: *mut wasm_byte_vec_t, -) { - let re = &*(trap as *const RuntimeError); - // this code assumes no nul bytes appear in the message - let mut message = format!("{}\0", re); - message.shrink_to_fit(); - - // TODO use `String::into_raw_parts` when it gets stabilized - (*out_ptr).size = message.as_bytes().len(); - (*out_ptr).data = message.as_mut_ptr(); - mem::forget(message); +pub unsafe extern "C" fn wasm_trap_message(trap: &wasm_trap_t, out_ptr: &mut wasm_byte_vec_t) { + let message = trap.inner.message(); + out_ptr.size = message.len(); + // TODO: make helper function for converting `Vec` into owned `wasm_T_vec_t` + let mut dupe_data: Box<[u8]> = message.into_bytes().into_boxed_slice(); + out_ptr.data = dupe_data.as_mut_ptr(); + mem::forget(dupe_data); } +#[no_mangle] +pub unsafe extern "C" fn wasm_trap_origin(trap: &wasm_trap_t) -> Option> { + trap.inner.trace().first().map(Into::into).map(Box::new) +} + +// TODO: old comment, rm after finish implementation // in trap/RuntimeError we need to store // 1. message // 2. origin (frame); frame contains: @@ -1190,11 +1206,19 @@ pub unsafe extern "C" fn wasm_trap_message( // 3. module offset // 4. which instance this was apart of -/*#[no_mangle] -pub unsafe extern "C" fn wasm_trap_trace(trap: *const wasm_trap_t, out_ptr: *mut wasm_frame_vec_t) { - let re = &*(trap as *const RuntimeError); - todo!() -}*/ +#[no_mangle] +pub unsafe extern "C" fn wasm_trap_trace(trap: &wasm_trap_t, out_ptr: &mut wasm_frame_vec_t) { + let frames = trap.inner.trace(); + out_ptr.size = frames.len(); + // TODO: make helper function for converting `Vec` into owned `wasm_T_vec_t` + let mut dupe_data: Box<[wasm_frame_t]> = frames + .iter() + .map(Into::into) + .collect::>() + .into_boxed_slice(); + out_ptr.data = dupe_data.as_mut_ptr(); + mem::forget(dupe_data); +} #[repr(C)] pub struct wasm_extern_t { @@ -1550,9 +1574,52 @@ pub unsafe extern "C" fn wasm_functype_results(ft: &wasm_functype_t) -> *const w out as *const _ } -#[derive(Debug)] +#[derive(Debug, Clone)] #[repr(C)] -pub struct wasm_frame_t {} +pub struct wasm_frame_t { + info: FrameInfo, +} + +impl<'a> From<&'a FrameInfo> for wasm_frame_t { + fn from(other: &'a FrameInfo) -> Self { + other.clone().into() + } +} + +impl From for wasm_frame_t { + fn from(other: FrameInfo) -> Self { + Self { info: other } + } +} + +#[no_mangle] +pub unsafe extern "C" fn wasm_frame_copy(frame: &wasm_frame_t) -> Box { + Box::new(frame.clone()) +} + +#[no_mangle] +pub unsafe extern "C" fn wasm_frame_delete(_frame: Option>) {} + +#[no_mangle] +pub unsafe extern "C" fn wasm_frame_instance(frame: &wasm_frame_t) -> *const wasm_instance_t { + //todo!("wasm_frame_instance") + std::ptr::null() +} + +#[no_mangle] +pub unsafe extern "C" fn wasm_frame_func_index(frame: &wasm_frame_t) -> u32 { + frame.info.func_index() +} + +#[no_mangle] +pub unsafe extern "C" fn wasm_frame_func_offset(frame: &wasm_frame_t) -> usize { + frame.info.func_offset() +} + +#[no_mangle] +pub unsafe extern "C" fn wasm_frame_module_offset(frame: &wasm_frame_t) -> usize { + frame.info.module_offset() +} wasm_declare_vec!(frame); diff --git a/lib/c-api/tests/CMakeLists.txt b/lib/c-api/tests/CMakeLists.txt index 339eaf53f..24a135bad 100644 --- a/lib/c-api/tests/CMakeLists.txt +++ b/lib/c-api/tests/CMakeLists.txt @@ -31,11 +31,11 @@ add_executable(wasm-c-api-serialize wasm-c-api/example/serialize.c) #add_executable(wasm-c-api-start wasm-c-api/example/start.c) #add_executable(wasm-c-api-table wasm-c-api/example/table.c) #add_executable(wasm-c-api-threads wasm-c-api/example/threads.c) -#add_executable(wasm-c-api-trap wasm-c-api/example/trap.c) +add_executable(wasm-c-api-trap wasm-c-api/example/trap.c) # Custom Wasm C API tests add_executable(wasm-c-api-wasi wasm-c-api-wasi.c) -add_executable(wasm-c-api-trap wasm-c-api-trap.c) +add_executable(wasm-c-api-early-exit wasm-c-api-early-exit.c) if (DEFINED WASI_TESTS) add_executable(test-wasi-import-object test-wasi-import-object.c) @@ -238,19 +238,19 @@ add_test(NAME wasm-c-api-serialize # WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/wasm-c-api/example/ #) -#target_link_libraries(wasm-c-api-trap general ${WASMER_LIB}) -#target_compile_options(wasm-c-api-trap PRIVATE ${COMPILER_OPTIONS}) -#add_test(NAME wasm-c-api-trap -# COMMAND wasm-c-api-trap -# WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/wasm-c-api/example/ -#) +target_link_libraries(wasm-c-api-trap general ${WASMER_LIB}) +target_compile_options(wasm-c-api-trap PRIVATE ${COMPILER_OPTIONS}) +add_test(NAME wasm-c-api-trap + COMMAND wasm-c-api-trap + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/wasm-c-api/example/ +) set_property(TARGET wasm-c-api-wasi PROPERTY C_STANDARD 11) target_link_libraries(wasm-c-api-wasi general ${WASMER_LIB}) target_compile_options(wasm-c-api-wasi PRIVATE ${COMPILER_OPTIONS}) add_test(wasm-c-api-wasi wasm-c-api-wasi) -set_property(TARGET wasm-c-api-trap PROPERTY C_STANDARD 11) -target_link_libraries(wasm-c-api-trap general ${WASMER_LIB}) -target_compile_options(wasm-c-api-trap PRIVATE ${COMPILER_OPTIONS}) -add_test(wasm-c-api-trap wasm-c-api-trap) +set_property(TARGET wasm-c-api-early-exit PROPERTY C_STANDARD 11) +target_link_libraries(wasm-c-api-early-exit general ${WASMER_LIB}) +target_compile_options(wasm-c-api-early-exit PRIVATE ${COMPILER_OPTIONS}) +add_test(wasm-c-api-early-exit wasm-c-api-early-exit) diff --git a/lib/c-api/tests/wasm-c-api-trap.c b/lib/c-api/tests/wasm-c-api-early-exit.c similarity index 55% rename from lib/c-api/tests/wasm-c-api-trap.c rename to lib/c-api/tests/wasm-c-api-early-exit.c index b2a777c50..c20f0d299 100644 --- a/lib/c-api/tests/wasm-c-api-trap.c +++ b/lib/c-api/tests/wasm-c-api-early-exit.c @@ -9,21 +9,21 @@ // Use the last_error API to retrieve error messages void print_wasmer_error() { - int error_len = wasmer_last_error_length(); - printf("Error len: `%d`\n", error_len); - char *error_str = malloc(error_len); - wasmer_last_error_message(error_str, error_len); - printf("Error str: `%s`\n", error_str); + int error_len = wasmer_last_error_length(); + printf("Error len: `%d`\n", error_len); + char *error_str = malloc(error_len); + wasmer_last_error_message(error_str, error_len); + printf("Error str: `%s`\n", error_str); } wasm_store_t* store = NULL; -wasm_trap_t* early_exit(wasm_val_t args[], wasm_val_t results[]) { - wasm_message_t* trap_message = NULL; - const char* message_inner = "trapping from a host import"; - wasm_byte_vec_new_uninitialized(trap_message, strlen(message_inner)); - // TODO: should we free this data? - return wasm_trap_new(store, trap_message); +own wasm_trap_t* early_exit(const wasm_val_t args[], wasm_val_t results[]) { + own wasm_message_t trap_message; + wasm_name_new_from_string(&trap_message,"trapping from a host import"); + own wasm_trap_t* trap = wasm_trap_new(store, &trap_message); + wasm_name_delete(&trap_message); + return trap; } int main(int argc, const char* argv[]) { @@ -63,23 +63,22 @@ int main(int argc, const char* argv[]) { // Instantiate. printf("Instantiating module...\n"); - // TODO: fill imports - wasm_functype_t* host_func_type = wasm_functype_new_0_0(); - wasm_func_t* host_func = wasm_func_new(store, host_func_type, (wasm_func_callback_t)early_exit); - wasm_extern_t* host_func_as_extern = wasm_func_as_extern(host_func); + wasm_func_t* host_func = wasm_func_new(store, host_func_type, early_exit); + wasm_functype_delete(host_func_type); - wasm_extern_t* imports[] = { host_func_as_extern }; - + const wasm_extern_t* imports[] = { wasm_func_as_extern(host_func) }; own wasm_instance_t* instance = - wasm_instance_new(store, module, (const wasm_extern_t *const *) imports, NULL); + wasm_instance_new(store, module, imports, NULL); if (!instance) { printf("> Error instantiating module!\n"); print_wasmer_error(); return 1; } + wasm_func_delete(host_func); + // Extract export. printf("Extracting export...\n"); own wasm_extern_vec_t exports; @@ -89,36 +88,69 @@ int main(int argc, const char* argv[]) { return 1; } fprintf(stderr, "found %zu exports\n", exports.size); + + wasm_module_delete(module); + wasm_instance_delete(instance); - // TODO: - wasm_func_t* run_func = NULL; + wasm_func_t* run_func = wasm_extern_as_func(exports.data[0]); if (run_func == NULL) { printf("> Error accessing export!\n"); print_wasmer_error(); return 1; } - wasm_module_delete(module); - wasm_instance_delete(instance); - // Call. printf("Calling export...\n"); - if (wasm_func_call(run_func, NULL, NULL)) { - printf("> Error calling function!\n"); + own const wasm_val_t args[] = { + { + .kind = WASM_I32, + .of = { .i32 = 1 } + }, + { + .kind = WASM_I32, + .of = { .i32 = 7 } + }, + }; + own wasm_val_t rets[1] = { }; + own wasm_trap_t* trap = wasm_func_call(run_func, args, rets); + if (!trap) { + printf("> Error calling function: expected trap!\n"); return 1; } - wasm_extern_vec_delete(&exports); + printf("Printing message...\n"); + own wasm_name_t message; + wasm_trap_message(trap, &message); + printf("> %s\n", message.data); - // NEEDS REVIEW: - for(int i = 0; i < num_imports; ++i) { - wasm_extern_delete(imports[i]); + /* printf("Printing origin...\n"); + own wasm_frame_t* frame = wasm_trap_origin(trap); + if (frame) { + print_frame(frame); + wasm_frame_delete(frame); + } else { + printf("> Empty origin.\n"); } - free(imports); + + printf("Printing trace...\n"); + own wasm_frame_vec_t trace; + wasm_trap_trace(trap, &trace); + if (trace.size > 0) { + for (size_t i = 0; i < trace.size; ++i) { + print_frame(trace.data[i]); + } + } else { + printf("> Empty trace.\n"); + } + + wasm_frame_vec_delete(&trace);*/ + wasm_trap_delete(trap); + wasm_name_delete(&message); + + wasm_extern_vec_delete(&exports); // Shut down. printf("Shutting down...\n"); - wasm_func_delete(run_func); wasm_store_delete(store); wasm_engine_delete(engine); diff --git a/lib/engine/src/trap/frame_info.rs b/lib/engine/src/trap/frame_info.rs index 310dc5679..464131f19 100644 --- a/lib/engine/src/trap/frame_info.rs +++ b/lib/engine/src/trap/frame_info.rs @@ -282,7 +282,7 @@ pub fn register( /// each frame is described by this structure. /// /// [`Trap`]: crate::Trap -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct FrameInfo { module_name: String, func_index: u32, From d53d58ee4c1f597524a24c978545c4400d230cf2 Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Tue, 29 Sep 2020 15:43:56 -0700 Subject: [PATCH 087/281] Add examples to tarpaulin coverage --- .tarpaulin.toml | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/.tarpaulin.toml b/.tarpaulin.toml index 9f7dae3de..78b59bfb0 100644 --- a/.tarpaulin.toml +++ b/.tarpaulin.toml @@ -1,17 +1,16 @@ [cranelift_coverage] features = "cranelift,singlepass,llvm,test-no-traps,test-cranelift" +examples = ["early-exit", "engine-jit", "engine-native", "engine-headless", "cross-compilation", "compiler-cranelift", "exported-function", "wasi"] release = true [llvm_coverage] features = "cranelift,singlepass,llvm,test-no-traps,test-llvm" +examples = ["compiler-llvm"] release = true [singlepass_coverage] features = "cranelift,singlepass,llvm,test-no-traps,test-singlepass" -release = true - -[feature_a_and_b_coverage] -features = "feature_a feature_b" +examples = ["compiler-singlepass"] release = true [report] From 903e41db50c1380f4976f7a4fa23b44b7ac16e58 Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Tue, 29 Sep 2020 15:52:29 -0700 Subject: [PATCH 088/281] Add debug code for windows C compiler --- .github/workflows/main.yaml | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/.github/workflows/main.yaml b/.github/workflows/main.yaml index 5ad198e1b..3c38aefd5 100644 --- a/.github/workflows/main.yaml +++ b/.github/workflows/main.yaml @@ -45,20 +45,24 @@ jobs: rust: 1.45.2 llvm_url: 'https://github.com/llvm/llvm-project/releases/download/llvmorg-10.0.0/clang+llvm-10.0.0-x86_64-linux-gnu-ubuntu-18.04.tar.xz' artifact_name: 'wasmer-linux-amd64' + run_integration_tests: true - build: macos os: macos-latest rust: 1.45.2 llvm_url: 'https://github.com/llvm/llvm-project/releases/download/llvmorg-10.0.0/clang+llvm-10.0.0-x86_64-apple-darwin.tar.xz' artifact_name: 'wasmer-macos-amd64' + run_integration_tests: true - build: windows os: windows-latest rust: 1.45.2 artifact_name: 'wasmer-windows-amd64' + run_integration_tests: true - build: linux-aarch64 os: [self-hosted, linux, ARM64] rust: 1.45.2 llvm_url: 'https://github.com/llvm/llvm-project/releases/download/llvmorg-10.0.0/clang+llvm-10.0.0-aarch64-linux-gnu.tar.xz' artifact_name: 'wasmer-linux-aarch64' + run_integration_tests: false env: CARGO_SCCACHE_VERSION: 0.2.13 SCCACHE_AZURE_BLOB_CONTAINER: wasmerstoragesccacheblob @@ -107,7 +111,10 @@ jobs: # echo "::set-env name=RUSTC_WRAPPER::${{ runner.tool_cache }}/cargo-sccache/bin/sccache" - name: Install LLVM (Windows) if: matrix.os == 'windows-latest' - run: choco install llvm + run: | + choco install llvm + echo "%path%" + where clang # run: | # curl --proto '=https' --tlsv1.2 -sSf https://github.com/llvm/llvm-project/releases/download/llvmorg-10.0.0/LLVM-10.0.0-win64.exe -L -o llvm-installer.exe # 7z x llvm-installer.exe -oC:/llvm-10 @@ -146,6 +153,7 @@ jobs: - name: Run integration tests run: | make test-integration + if: ${{ matrix.run_integration_tests }} - name: Package Wasmer run: | make package From ffe1c5a9e46f9bad65e987cc94bd0aa93e6815eb Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Tue, 29 Sep 2020 16:41:30 -0700 Subject: [PATCH 089/281] Address feedback, clean up wasm_T_vec_t conversions --- examples/early_exit.rs | 8 +-- lib/c-api/src/wasm_c_api/mod.rs | 65 +++++++++++++++---------- lib/c-api/tests/assets/call_trap.wat | 3 +- lib/c-api/tests/wasm-c-api-early-exit.c | 62 +++++++++++------------ 4 files changed, 77 insertions(+), 61 deletions(-) diff --git a/examples/early_exit.rs b/examples/early_exit.rs index 7253fd519..814ab01ff 100644 --- a/examples/early_exit.rs +++ b/examples/early_exit.rs @@ -54,7 +54,7 @@ fn main() -> anyhow::Result<()> { }; let instance = Instance::new(&module, &import_object)?; - // get the `run` function which we'll use as our entrypoint. + // Get the `run` function which we'll use as our entrypoint. let run_func: NativeFunc<(i32, i32), i32> = instance.exports.get_native_function("run").unwrap(); @@ -66,10 +66,10 @@ fn main() -> anyhow::Result<()> { result ); } - // we're expecting it to fail. - // we attempt to downcast the error into the error type that we were expecting. + // We're expecting it to fail. + // We attempt to downcast the error into the error type that we were expecting. Err(e) => match e.downcast::() { - // we found the exit code used to terminate execution. + // We found the exit code used to terminate execution. Ok(exit_code) => { println!("Exited early with exit code: {}", exit_code); Ok(()) diff --git a/lib/c-api/src/wasm_c_api/mod.rs b/lib/c-api/src/wasm_c_api/mod.rs index e336d94eb..edef62ad8 100644 --- a/lib/c-api/src/wasm_c_api/mod.rs +++ b/lib/c-api/src/wasm_c_api/mod.rs @@ -713,13 +713,10 @@ pub unsafe extern "C" fn wasm_func_new( ]; let trap = callback(processed_args.as_ptr(), results.as_mut_ptr()); - dbg!(&trap); if !trap.is_null() { let trap: Box = Box::from_raw(trap); - dbg!("raising trap!"); RuntimeError::raise(Box::new(trap.inner)); } - // TODO: do something with `traps` let processed_results = results .into_iter() @@ -1056,6 +1053,38 @@ macro_rules! wasm_declare_vec { } } + + impl<'a> From]>> for [] { + fn from(other: Vec<[]>) -> Self { + let mut boxed_slice = other.into_boxed_slice(); + let size = boxed_slice.len(); + let data = boxed_slice.as_mut_ptr(); + mem::forget(boxed_slice); + Self { + size, + data, + } + } + } + + impl<'a, T: Into<[]> + Clone> From<&'a [T]> for [] { + fn from(other: &'a [T]) -> Self { + let size = other.len(); + let mut copied_data = other + .iter() + .cloned() + .map(Into::into) + .collect::]>>() + .into_boxed_slice(); + let data = copied_data.as_mut_ptr(); + mem::forget(copied_data); + Self { + size, + data, + } + } + } + // TODO: investigate possible memory leak on `init` (owned pointer) #[no_mangle] pub unsafe extern "C" fn [](out: *mut [], length: usize, init: *mut []) { @@ -1185,11 +1214,9 @@ pub unsafe extern "C" fn wasm_trap_delete(_trap: Option>) {} #[no_mangle] pub unsafe extern "C" fn wasm_trap_message(trap: &wasm_trap_t, out_ptr: &mut wasm_byte_vec_t) { let message = trap.inner.message(); - out_ptr.size = message.len(); - // TODO: make helper function for converting `Vec` into owned `wasm_T_vec_t` - let mut dupe_data: Box<[u8]> = message.into_bytes().into_boxed_slice(); - out_ptr.data = dupe_data.as_mut_ptr(); - mem::forget(dupe_data); + let byte_vec: wasm_byte_vec_t = message.into_bytes().into(); + out_ptr.size = byte_vec.size; + out_ptr.data = byte_vec.data; } #[no_mangle] @@ -1197,27 +1224,13 @@ pub unsafe extern "C" fn wasm_trap_origin(trap: &wasm_trap_t) -> Option` into owned `wasm_T_vec_t` - let mut dupe_data: Box<[wasm_frame_t]> = frames - .iter() - .map(Into::into) - .collect::>() - .into_boxed_slice(); - out_ptr.data = dupe_data.as_mut_ptr(); - mem::forget(dupe_data); + let frame_vec: wasm_frame_vec_t = frames.into(); + + out_ptr.size = frame_vec.size; + out_ptr.data = frame_vec.data; } #[repr(C)] diff --git a/lib/c-api/tests/assets/call_trap.wat b/lib/c-api/tests/assets/call_trap.wat index 6f4bb0f80..febd5f88d 100644 --- a/lib/c-api/tests/assets/call_trap.wat +++ b/lib/c-api/tests/assets/call_trap.wat @@ -7,4 +7,5 @@ (i32.add (local.get $x) (local.get $y))) - (export "run" (func $run))) \ No newline at end of file + (export "run" (func $run))) + diff --git a/lib/c-api/tests/wasm-c-api-early-exit.c b/lib/c-api/tests/wasm-c-api-early-exit.c index c20f0d299..903fdb7db 100644 --- a/lib/c-api/tests/wasm-c-api-early-exit.c +++ b/lib/c-api/tests/wasm-c-api-early-exit.c @@ -1,14 +1,13 @@ +#include #include #include #include -#include #include "wasm.h" #include "wasmer_wasm.h" // Use the last_error API to retrieve error messages -void print_wasmer_error() -{ +void print_wasmer_error() { int error_len = wasmer_last_error_length(); printf("Error len: `%d`\n", error_len); char *error_str = malloc(error_len); @@ -16,25 +15,34 @@ void print_wasmer_error() printf("Error str: `%s`\n", error_str); } -wasm_store_t* store = NULL; +void print_frame(wasm_frame_t* frame) { + printf("> %p @ 0x%zx = %"PRIu32".0x%zx\n", + wasm_frame_instance(frame), + wasm_frame_module_offset(frame), + wasm_frame_func_index(frame), + wasm_frame_func_offset(frame) + ); +} -own wasm_trap_t* early_exit(const wasm_val_t args[], wasm_val_t results[]) { +wasm_store_t *store = NULL; + +own wasm_trap_t *early_exit(const wasm_val_t args[], wasm_val_t results[]) { own wasm_message_t trap_message; - wasm_name_new_from_string(&trap_message,"trapping from a host import"); - own wasm_trap_t* trap = wasm_trap_new(store, &trap_message); + wasm_name_new_from_string(&trap_message, "trapping from a host import"); + own wasm_trap_t *trap = wasm_trap_new(store, &trap_message); wasm_name_delete(&trap_message); return trap; } -int main(int argc, const char* argv[]) { +int main(int argc, const char *argv[]) { // Initialize. printf("Initializing...\n"); - wasm_engine_t* engine = wasm_engine_new(); + wasm_engine_t *engine = wasm_engine_new(); store = wasm_store_new(engine); // Load binary. printf("Loading binary...\n"); - FILE* file = fopen("assets/call_trap.wasm", "r"); + FILE *file = fopen("assets/call_trap.wasm", "r"); if (!file) { printf("> Error loading module!\n"); return 1; @@ -52,7 +60,7 @@ int main(int argc, const char* argv[]) { // Compile. printf("Compiling module...\n"); - own wasm_module_t* module = wasm_module_new(store, &binary); + own wasm_module_t *module = wasm_module_new(store, &binary); if (!module) { printf("> Error compiling module!\n"); return 1; @@ -63,14 +71,14 @@ int main(int argc, const char* argv[]) { // Instantiate. printf("Instantiating module...\n"); - wasm_functype_t* host_func_type = wasm_functype_new_0_0(); - wasm_func_t* host_func = wasm_func_new(store, host_func_type, early_exit); + wasm_functype_t *host_func_type = wasm_functype_new_0_0(); + wasm_func_t *host_func = wasm_func_new(store, host_func_type, early_exit); wasm_functype_delete(host_func_type); - const wasm_extern_t* imports[] = { wasm_func_as_extern(host_func) }; - own wasm_instance_t* instance = - wasm_instance_new(store, module, imports, NULL); + const wasm_extern_t *imports[] = {wasm_func_as_extern(host_func)}; + own wasm_instance_t *instance = + wasm_instance_new(store, module, imports, NULL); if (!instance) { printf("> Error instantiating module!\n"); print_wasmer_error(); @@ -88,11 +96,11 @@ int main(int argc, const char* argv[]) { return 1; } fprintf(stderr, "found %zu exports\n", exports.size); - + wasm_module_delete(module); wasm_instance_delete(instance); - wasm_func_t* run_func = wasm_extern_as_func(exports.data[0]); + wasm_func_t *run_func = wasm_extern_as_func(exports.data[0]); if (run_func == NULL) { printf("> Error accessing export!\n"); print_wasmer_error(); @@ -102,17 +110,11 @@ int main(int argc, const char* argv[]) { // Call. printf("Calling export...\n"); own const wasm_val_t args[] = { - { - .kind = WASM_I32, - .of = { .i32 = 1 } - }, - { - .kind = WASM_I32, - .of = { .i32 = 7 } - }, + {.kind = WASM_I32, .of = {.i32 = 1}}, + {.kind = WASM_I32, .of = {.i32 = 7}}, }; - own wasm_val_t rets[1] = { }; - own wasm_trap_t* trap = wasm_func_call(run_func, args, rets); + own wasm_val_t rets[1] = {}; + own wasm_trap_t *trap = wasm_func_call(run_func, args, rets); if (!trap) { printf("> Error calling function: expected trap!\n"); return 1; @@ -123,7 +125,7 @@ int main(int argc, const char* argv[]) { wasm_trap_message(trap, &message); printf("> %s\n", message.data); - /* printf("Printing origin...\n"); + printf("Printing origin...\n"); own wasm_frame_t* frame = wasm_trap_origin(trap); if (frame) { print_frame(frame); @@ -143,7 +145,7 @@ int main(int argc, const char* argv[]) { printf("> Empty trace.\n"); } - wasm_frame_vec_delete(&trace);*/ + wasm_frame_vec_delete(&trace); wasm_trap_delete(trap); wasm_name_delete(&message); From 818f419245ace03e623dd9de380b5ab1244536c8 Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Tue, 29 Sep 2020 16:49:15 -0700 Subject: [PATCH 090/281] Call `refreshenv` after installing LLVM on Windows to access clang --- .github/workflows/main.yaml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/main.yaml b/.github/workflows/main.yaml index 3c38aefd5..d8352916d 100644 --- a/.github/workflows/main.yaml +++ b/.github/workflows/main.yaml @@ -113,8 +113,7 @@ jobs: if: matrix.os == 'windows-latest' run: | choco install llvm - echo "%path%" - where clang + refreshenv # run: | # curl --proto '=https' --tlsv1.2 -sSf https://github.com/llvm/llvm-project/releases/download/llvmorg-10.0.0/LLVM-10.0.0-win64.exe -L -o llvm-installer.exe # 7z x llvm-installer.exe -oC:/llvm-10 From eb490fc6468be69af68823b64ade23cadf61834e Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Tue, 29 Sep 2020 17:41:10 -0700 Subject: [PATCH 091/281] Allow mapdir aliases with starting `/` Stripping leading `/` is valid because we mount mapped dirs at `/` regardless. --- lib/wasi/src/state/builder.rs | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/lib/wasi/src/state/builder.rs b/lib/wasi/src/state/builder.rs index 0bd8bd218..b3636eecb 100644 --- a/lib/wasi/src/state/builder.rs +++ b/lib/wasi/src/state/builder.rs @@ -438,7 +438,17 @@ impl PreopenDirBuilder { /// Make this preopened directory appear to the WASI program as `alias` pub fn alias(&mut self, alias: &str) -> &mut Self { - self.alias = Some(alias.to_string()); + let alias = if let Some(first_byte) = alias.as_bytes().first() { + if *first_byte == b'/' { + &alias[1..] + } else { + alias + } + } else { + alias + } + .to_string(); + self.alias = Some(alias); self } From 78a378298aee681caf2ec39dcf63a33d5103f378 Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Tue, 29 Sep 2020 17:59:24 -0700 Subject: [PATCH 092/281] Attempt to manually add LLVM's bins to Windows's path --- .github/workflows/main.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/main.yaml b/.github/workflows/main.yaml index d8352916d..a50a5318c 100644 --- a/.github/workflows/main.yaml +++ b/.github/workflows/main.yaml @@ -113,7 +113,7 @@ jobs: if: matrix.os == 'windows-latest' run: | choco install llvm - refreshenv + echo ::add-path::C:\Program Files\LLVM\bin # run: | # curl --proto '=https' --tlsv1.2 -sSf https://github.com/llvm/llvm-project/releases/download/llvmorg-10.0.0/LLVM-10.0.0-win64.exe -L -o llvm-installer.exe # 7z x llvm-installer.exe -oC:/llvm-10 From 4c25ac315bac4a7700ff63b6e5f98738fa26cce4 Mon Sep 17 00:00:00 2001 From: nlewycky Date: Wed, 30 Sep 2020 12:06:47 -0700 Subject: [PATCH 093/281] SignatureRegistry is in Engine, not Compiler. --- lib/vm/src/sig_registry.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/vm/src/sig_registry.rs b/lib/vm/src/sig_registry.rs index c4a76d782..58b690fc6 100644 --- a/lib/vm/src/sig_registry.rs +++ b/lib/vm/src/sig_registry.rs @@ -17,7 +17,7 @@ use wasmer_types::FunctionType; /// index comparison. #[derive(Debug)] pub struct SignatureRegistry { - // This structure is stored in a `Compiler` and is intended to be shared + // This structure is stored in an `Engine` and is intended to be shared // across many instances. Ideally instances can themselves be sent across // threads, and ideally we can compile across many threads. As a result we // use interior mutability here with a lock to avoid having callers to From fec7644bb8c1bffcbba188320a2739a791ea4396 Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Wed, 30 Sep 2020 10:43:18 -0700 Subject: [PATCH 094/281] Port integration test to Windows Add conditional logic for Windows style object files Explicitly require c11 for wasm.h Use `clang++` on Windows for `static_assert` Improve generated C + add hack to make function pointers work better Add logic to handle Window's static library file extension Improve linking logic to work on Windows Add support for C++ compilers for object-file-engine generated C Add C++ support to wasmer_wasm.h Add C++ support to test C file too Add linking flags for Windows, make assert line-ending neutral Adjust asserted output to handle differences on Windows --- lib/c-api/wasmer_wasm.h | 8 ++ lib/cli/src/c_gen/mod.rs | 96 ++++++++++++++++--- lib/cli/src/c_gen/object_file_header.rs | 47 ++++++--- tests/integration/cli/src/compile.rs | 54 +++++++---- .../src/object_file_engine_test_c_source.c | 14 ++- 5 files changed, 171 insertions(+), 48 deletions(-) diff --git a/lib/c-api/wasmer_wasm.h b/lib/c-api/wasmer_wasm.h index 2e407076e..a43d09c6e 100644 --- a/lib/c-api/wasmer_wasm.h +++ b/lib/c-api/wasmer_wasm.h @@ -3,6 +3,10 @@ #ifndef WASMER_WASM_H #define WASMER_WASM_H +#ifdef __cplusplus +extern "C" { +#endif + #include #include "wasm.h" @@ -157,4 +161,8 @@ int wasmer_last_error_length(); */ int wasmer_last_error_message(char* buffer, int length); +#ifdef __cplusplus +} +#endif + #endif /* WASMER_WASM_H */ diff --git a/lib/cli/src/c_gen/mod.rs b/lib/cli/src/c_gen/mod.rs index c650c1438..7e59240bc 100644 --- a/lib/cli/src/c_gen/mod.rs +++ b/lib/cli/src/c_gen/mod.rs @@ -44,6 +44,13 @@ pub enum CType { /// None is equivalent to Some(Box(Ctype::Void)). return_value: Option>, }, + /// C constant array. + Array { + /// The type of the array. + inner: Box, + }, + /// A user defined type. + TypeDef(String), } impl CType { @@ -131,6 +138,13 @@ impl CType { } w.push(')'); } + Self::Array { inner } => { + inner.generate_c(w); + w.push_str("[]"); + } + Self::TypeDef(inner) => { + w.push_str(&inner); + } } } @@ -138,6 +152,7 @@ impl CType { fn generate_c_with_name(&self, name: &str, w: &mut String) { match &self { Self::PointerTo { .. } + | Self::TypeDef { .. } | Self::Void | Self::U8 | Self::U16 @@ -176,6 +191,12 @@ impl CType { } w.push(')'); } + Self::Array { inner } => { + inner.generate_c(w); + w.push(' '); + w.push_str(&name); + w.push_str("[]"); + } } } } @@ -195,9 +216,6 @@ pub enum CStatement { Declaration { /// The name of the thing being declared. name: String, - /// Whether the thing being declared is an array. - // TODO: probably make this part of CType - array: bool, /// Whether the thing being declared is `extern`. is_extern: bool, /// Whether the thing being declared is `const`. @@ -220,6 +238,21 @@ pub enum CStatement { /// The raw value acting as a constant. value: String, }, + + /// A C-style cast + Cast { + /// The type to cast to. + target_type: CType, + /// The thing being cast. + expression: Box, + }, + /// Typedef one type to another. + TypeDef { + /// The type of the thing being typedef'd. + source_type: CType, + /// The new name by which this type may be called. + new_name: String, + }, } impl CStatement { @@ -228,7 +261,6 @@ impl CStatement { match &self { Self::Declaration { name, - array, is_extern, is_const, ctype, @@ -241,10 +273,6 @@ impl CStatement { w.push_str("extern "); } ctype.generate_c_with_name(name, w); - // TODO: array should be part of the type - if *array { - w.push_str("[]"); - } if let Some(def) = definition { w.push_str(" = "); def.generate_c(w); @@ -268,6 +296,32 @@ impl CStatement { Self::LiteralConstant { value } => { w.push_str(&value); } + Self::Cast { + target_type, + expression, + } => { + w.push('('); + target_type.generate_c(w); + w.push(')'); + w.push(' '); + expression.generate_c(w); + } + Self::TypeDef { + source_type, + new_name, + } => { + w.push_str("typedef "); + // leaky abstraction / hack, doesn't fully solve the problem + if let CType::Function { .. } = source_type { + source_type.generate_c_with_name(&format!("(*{})", new_name), w); + } else { + source_type.generate_c(w); + w.push(' '); + w.push_str(&new_name); + } + w.push(';'); + w.push('\n'); + } } } } @@ -310,6 +364,7 @@ mod test { assert_c_type!(CType::I32, "int"); assert_c_type!(CType::I64, "long long"); assert_c_type!(CType::ISize, "size_t"); + assert_c_type!(CType::TypeDef("my_type".to_string()), "my_type"); assert_c_type!( CType::Function { arguments: vec![CType::U8, CType::ISize], @@ -362,6 +417,11 @@ mod test { assert_c_type!(CType::I32, "data", "int data"); assert_c_type!(CType::I64, "data", "long long data"); assert_c_type!(CType::ISize, "data", "size_t data"); + assert_c_type!( + CType::TypeDef("my_type".to_string()), + "data", + "my_type data" + ); assert_c_type!( CType::Function { arguments: vec![CType::U8, CType::ISize], @@ -410,6 +470,16 @@ mod test { }, "\"Hello, world!\"" ); + assert_c_expr!( + CStatement::TypeDef { + source_type: CType::Function { + arguments: vec![CType::I32, CType::I32], + return_value: None, + }, + new_name: "my_func_ptr".to_string(), + }, + "typedef void (*my_func_ptr)(int, int);\n" + ); assert_c_expr!( CStatement::LiteralArray { items: vec![ @@ -430,10 +500,11 @@ mod test { assert_c_expr!( CStatement::Declaration { name: "my_array".to_string(), - array: true, is_extern: false, is_const: true, - ctype: CType::I32, + ctype: CType::Array { + inner: Box::new(CType::I32), + }, definition: Some(Box::new(CStatement::LiteralArray { items: vec![ CStatement::LiteralConstant { @@ -453,10 +524,11 @@ mod test { assert_c_expr!( CStatement::Declaration { name: "my_array".to_string(), - array: true, is_extern: true, is_const: true, - ctype: CType::I32, + ctype: CType::Array { + inner: Box::new(CType::I32), + }, definition: None, }, "const extern int my_array[];\n" diff --git a/lib/cli/src/c_gen/object_file_header.rs b/lib/cli/src/c_gen/object_file_header.rs index 7d3dd4b14..d992cc330 100644 --- a/lib/cli/src/c_gen/object_file_header.rs +++ b/lib/cli/src/c_gen/object_file_header.rs @@ -13,7 +13,6 @@ pub fn generate_header_file( let mut c_statements = vec![]; c_statements.push(CStatement::Declaration { name: "module_bytes_len".to_string(), - array: false, is_extern: false, is_const: true, ctype: CType::U32, @@ -23,10 +22,11 @@ pub fn generate_header_file( }); c_statements.push(CStatement::Declaration { name: "WASMER_METADATA".to_string(), - array: true, is_extern: true, is_const: true, - ctype: CType::U8, + ctype: CType::Array { + inner: Box::new(CType::U8), + }, definition: None, }); for (function_local_index, _sig_index) in @@ -42,7 +42,6 @@ pub fn generate_header_file( // TODO: figure out the signature here too c_statements.push(CStatement::Declaration { name: function_name.clone(), - array: false, is_extern: false, is_const: false, ctype: CType::Function { @@ -68,17 +67,21 @@ pub fn generate_header_file( symbol_registry.symbol_to_name(Symbol::LocalFunction(function_local_index)); // TODO: figure out the signature here too - function_pointer_array_statements.push(CStatement::LiteralConstant { - value: function_name.clone(), + function_pointer_array_statements.push(CStatement::Cast { + target_type: CType::void_ptr(), + expression: Box::new(CStatement::LiteralConstant { + value: function_name.clone(), + }), }); } c_statements.push(CStatement::Declaration { name: "function_pointers".to_string(), - array: true, is_extern: false, is_const: true, - ctype: CType::void_ptr(), + ctype: CType::Array { + inner: Box::new(CType::void_ptr()), + }, definition: Some(Box::new(CStatement::LiteralArray { items: function_pointer_array_statements, })), @@ -91,7 +94,6 @@ pub fn generate_header_file( c_statements.push(CStatement::Declaration { name: function_name.clone(), - array: false, is_extern: false, is_const: false, ctype: CType::Function { @@ -115,10 +117,11 @@ pub fn generate_header_file( c_statements.push(CStatement::Declaration { name: "function_trampolines".to_string(), - array: true, is_extern: false, is_const: true, - ctype: CType::void_ptr(), + ctype: CType::Array { + inner: Box::new(CType::void_ptr()), + }, definition: Some(Box::new(CStatement::LiteralArray { items: function_trampoline_statements, })), @@ -135,7 +138,6 @@ pub fn generate_header_file( // TODO: figure out the signature here c_statements.push(CStatement::Declaration { name: function_name, - array: false, is_extern: false, is_const: false, ctype: CType::Function { @@ -146,6 +148,14 @@ pub fn generate_header_file( }); } + c_statements.push(CStatement::TypeDef { + source_type: CType::Function { + arguments: vec![CType::void_ptr(), CType::void_ptr(), CType::void_ptr()], + return_value: None, + }, + new_name: "dyn_func_trampoline_t".to_string(), + }); + // dynamic function trampoline pointer array { let mut dynamic_function_trampoline_statements = vec![]; @@ -162,15 +172,22 @@ pub fn generate_header_file( } c_statements.push(CStatement::Declaration { name: "dynamic_function_trampoline_pointers".to_string(), - array: true, is_extern: false, is_const: true, - ctype: CType::void_ptr(), + ctype: CType::Array { + inner: Box::new(CType::TypeDef("dyn_func_trampoline_t".to_string())), + }, definition: Some(Box::new(CStatement::LiteralArray { items: dynamic_function_trampoline_statements, })), }); } - generate_c(&c_statements) + let inner_c = generate_c(&c_statements); + + // we wrap the inner C to work with C++ too + format!( + "#ifdef __cplusplus\nextern \"C\" {{\n#endif\n\n{}\n\n#ifdef __cplusplus\n}}\n#endif\n", + inner_c + ) } diff --git a/tests/integration/cli/src/compile.rs b/tests/integration/cli/src/compile.rs index 62e897c09..9b9cb4282 100644 --- a/tests/integration/cli/src/compile.rs +++ b/tests/integration/cli/src/compile.rs @@ -20,10 +20,16 @@ const WASMER_PATH: &str = concat!( "/../../../target/release/wasmer" ); +#[cfg(not(windows))] const LIBWASMER_PATH: &str = concat!( env!("CARGO_MANIFEST_DIR"), "/../../../target/release/libwasmer_c_api.a" ); +#[cfg(windows)] +const LIBWASMER_PATH: &str = concat!( + env!("CARGO_MANIFEST_DIR"), + "/../../../target/release/wasmer_c_api.lib" +); /// Get the path to the `wasmer` executable to be used in this test. fn get_wasmer_path() -> PathBuf { @@ -94,10 +100,14 @@ struct WasmerCompile { impl Default for WasmerCompile { fn default() -> Self { + #[cfg(not(windows))] + let wasm_obj_path = "wasm.o"; + #[cfg(windows)] + let wasm_obj_path = "wasm.obj"; Self { wasmer_path: get_wasmer_path(), wasm_path: PathBuf::from(OBJECT_FILE_ENGINE_TEST_WASM_PATH), - wasm_object_path: PathBuf::from("wasm.o"), + wasm_object_path: PathBuf::from(wasm_obj_path), header_output_path: PathBuf::from("my_wasm.h"), compiler: Compiler::Cranelift, engine: Engine::ObjectFile, @@ -136,11 +146,8 @@ fn run_c_compile(path_to_c_src: &Path, output_name: &Path) -> anyhow::Result<()> #[cfg(not(windows))] let c_compiler = "cc"; #[cfg(windows)] - let c_compiler = "clang"; + let c_compiler = "clang++"; - dbg!(path_to_c_src.exists()); - dbg!(Path::new(CLI_INTEGRATION_TESTS_ASSETS).exists()); - dbg!(Command::new(c_compiler).arg("--help").output()); let output = Command::new(c_compiler) .arg("-O2") .arg("-c") @@ -196,20 +203,20 @@ impl Default for LinkCode { impl LinkCode { fn run(&self) -> anyhow::Result<()> { - let output = Command::new(&self.linker_path) + let mut command = Command::new(&self.linker_path); + let command = command .arg(&self.optimization_flag) .args( self.object_paths .iter() .map(|path| path.canonicalize().unwrap()), ) - .arg(&self.libwasmer_path.canonicalize()?) - .arg("-ldl") - .arg("-lm") - .arg("-pthread") - .arg("-o") - .arg(&self.output_path) - .output()?; + .arg(&self.libwasmer_path.canonicalize()?); + #[cfg(windows)] + let command = command.arg("-luserenv").arg("-lWs2_32").arg("-ladvapi32"); + #[cfg(not(windows))] + let command = command.arg("-ldl").arg("-lm").arg("-pthread"); + let output = command.arg("-o").arg(&self.output_path).output()?; if !output.status.success() { bail!( @@ -249,7 +256,10 @@ fn object_file_engine_works() -> anyhow::Result<()> { std::env::set_current_dir(&operating_dir)?; let wasm_path = PathBuf::from(OBJECT_FILE_ENGINE_TEST_WASM_PATH); + #[cfg(not(windows))] let wasm_object_path = PathBuf::from("wasm.o"); + #[cfg(windows)] + let wasm_object_path = PathBuf::from("wasm.obj"); let header_output_path = PathBuf::from("my_wasm.h"); WasmerCompile { @@ -264,7 +274,10 @@ fn object_file_engine_works() -> anyhow::Result<()> { .context("Failed to compile wasm with Wasmer")?; let c_src_file_name = Path::new("c_src.c"); + #[cfg(not(windows))] let c_object_path = PathBuf::from("c_src.o"); + #[cfg(windows)] + let c_object_path = PathBuf::from("c_src.obj"); let executable_path = PathBuf::from("a.out"); // TODO: adjust C source code based on locations of things @@ -286,12 +299,17 @@ fn object_file_engine_works() -> anyhow::Result<()> { .context("Failed to link objects together")?; let result = run_code(&executable_path).context("Failed to run generated executable")?; + let result_lines = result.lines().collect::>(); assert_eq!( - &result, - r#"Initializing... -Buffer size: 1801380 -"Hello, World" -"# + result_lines, + vec![ + "Initializing...", + #[cfg(windows)] + "Buffer size: 1801376", + #[cfg(not(windows))] + "Buffer size: 1801380", + "\"Hello, World\"" + ], ); Ok(()) diff --git a/tests/integration/cli/src/object_file_engine_test_c_source.c b/tests/integration/cli/src/object_file_engine_test_c_source.c index 0a04cac01..129d02fe5 100644 --- a/tests/integration/cli/src/object_file_engine_test_c_source.c +++ b/tests/integration/cli/src/object_file_engine_test_c_source.c @@ -1,3 +1,7 @@ +#ifdef __cplusplus +extern "C" { +#endif + #include "wasmer_wasm.h" #include "wasm.h" #include "my_wasm.h" @@ -11,6 +15,10 @@ void wasmer_trampoline_function_call__1(void*, void*, void*); // todo: add to wasmer_wasm.h or something void* wasm_instance_get_vmctx_ptr(wasm_instance_t*); +#ifdef __cplusplus +} +#endif + // a bit of a hack; TODO: clean this up typedef struct my_byte_vec_t { size_t size; @@ -22,7 +30,7 @@ void print_wasmer_error() { int error_len = wasmer_last_error_length(); printf("Error len: `%d`\n", error_len); - char *error_str = malloc(error_len); + char* error_str = (char*) malloc(error_len); wasmer_last_error_message(error_str, error_len); printf("Error str: `%s`\n", error_str); } @@ -58,7 +66,7 @@ int main() { char* memory_buffer = (char*) malloc(buffer_size); size_t current_offset = 0; - printf("Buffer size: %d\n", buffer_size); + printf("Buffer size: %zu\n", buffer_size); memcpy(memory_buffer + current_offset, byte_ptr, module_bytes_len); current_offset += module_bytes_len; @@ -112,7 +120,7 @@ int main() { wasm_importtype_vec_t import_types; wasm_module_imports(module, &import_types); int num_imports = import_types.size; - wasm_extern_t** imports = malloc(num_imports * sizeof(wasm_extern_t*)); + wasm_extern_t** imports = (wasm_extern_t**) malloc(num_imports * sizeof(wasm_extern_t*)); wasm_importtype_vec_delete(&import_types); bool get_imports_result = wasi_get_imports(store, module, wasi_env, imports); From 3f9826c20945bb58ac054745230eb408366ed866 Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Wed, 30 Sep 2020 15:03:55 -0700 Subject: [PATCH 095/281] Get Windows integration test working in CI --- .github/workflows/main.yaml | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/.github/workflows/main.yaml b/.github/workflows/main.yaml index a50a5318c..a5d1d32f1 100644 --- a/.github/workflows/main.yaml +++ b/.github/workflows/main.yaml @@ -111,9 +111,9 @@ jobs: # echo "::set-env name=RUSTC_WRAPPER::${{ runner.tool_cache }}/cargo-sccache/bin/sccache" - name: Install LLVM (Windows) if: matrix.os == 'windows-latest' + shell: cmd run: | choco install llvm - echo ::add-path::C:\Program Files\LLVM\bin # run: | # curl --proto '=https' --tlsv1.2 -sSf https://github.com/llvm/llvm-project/releases/download/llvmorg-10.0.0/LLVM-10.0.0-win64.exe -L -o llvm-installer.exe # 7z x llvm-installer.exe -oC:/llvm-10 @@ -149,10 +149,15 @@ jobs: run: | make build-wapm if: needs.setup.outputs.DOING_RELEASE == '1' - - name: Run integration tests + - name: Run integration tests (Windows) + shell: cmd run: | + call refreshenv make test-integration - if: ${{ matrix.run_integration_tests }} + if: ${{ matrix.run_integration_tests }} && ${{ matrix.os }} == 'windows-latest' + - name: Run integration tests (Unix) + run: make test-integration + if: ${{ matrix.run_integration_tests }} && ${{ matrix.os }} != 'windows-latest' - name: Package Wasmer run: | make package From 83482d48cb5f9d3124acdea29c3f6d0fb8d3b653 Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Wed, 30 Sep 2020 16:13:10 -0700 Subject: [PATCH 096/281] Fix typo in GitHub Actions yaml --- .github/workflows/main.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/main.yaml b/.github/workflows/main.yaml index a5d1d32f1..a9911f376 100644 --- a/.github/workflows/main.yaml +++ b/.github/workflows/main.yaml @@ -154,10 +154,10 @@ jobs: run: | call refreshenv make test-integration - if: ${{ matrix.run_integration_tests }} && ${{ matrix.os }} == 'windows-latest' + if: matrix.run_integration_tests && matrix.os == 'windows-latest' - name: Run integration tests (Unix) run: make test-integration - if: ${{ matrix.run_integration_tests }} && ${{ matrix.os }} != 'windows-latest' + if: matrix.run_integration_tests && matrix.os != 'windows-latest' - name: Package Wasmer run: | make package From 4efacc305852dda95158a87bf7e6769670a6d666 Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Wed, 30 Sep 2020 16:35:32 -0700 Subject: [PATCH 097/281] Squashed 'tests/wasi-wast/' changes from 15de05557..f3af784fb f3af784fb Add mapdir with leading slash test git-subtree-dir: tests/wasi-wast git-subtree-split: f3af784fb148ccd5037ae159c39e99b372bad1cf --- wasi/snapshot1/mapdir_with_leading_slash.wasm | Bin 0 -> 72565 bytes wasi/snapshot1/mapdir_with_leading_slash.wast | 7 ++++++ wasi/tests/mapdir_with_leading_slash.rs | 23 ++++++++++++++++++ wasi/unstable/mapdir_with_leading_slash.wasm | Bin 0 -> 71923 bytes wasi/unstable/mapdir_with_leading_slash.wast | 7 ++++++ 5 files changed, 37 insertions(+) create mode 100644 wasi/snapshot1/mapdir_with_leading_slash.wasm create mode 100644 wasi/snapshot1/mapdir_with_leading_slash.wast create mode 100644 wasi/tests/mapdir_with_leading_slash.rs create mode 100644 wasi/unstable/mapdir_with_leading_slash.wasm create mode 100644 wasi/unstable/mapdir_with_leading_slash.wast diff --git a/wasi/snapshot1/mapdir_with_leading_slash.wasm b/wasi/snapshot1/mapdir_with_leading_slash.wasm new file mode 100644 index 0000000000000000000000000000000000000000..26e68d85722b0e1cb64b5b9274c4c7a69561e8a5 GIT binary patch literal 72565 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 +} diff --git a/wasi/unstable/mapdir_with_leading_slash.wasm b/wasi/unstable/mapdir_with_leading_slash.wasm new file mode 100644 index 0000000000000000000000000000000000000000..eacc71d81e3bb27085bc2769d41a04d113eade99 GIT binary patch literal 71923 zcmd?S51eIJRp)#5Ip^NGRi~=^bZA16Zppcq7AlgM)`{s%6HM)Xq&rO~1bHZo&v{9N z@TUqws=8^=2dPTZU`wJzWgs8}Ed~ifAR}IL2p$08yhxr)8pMB#`<3 z);j0hd#fu+hhcp0^LaF>^KbuId+qgquf1<_+5XprBuT<`Ve_Tw%1T(dG^`|-W-E5f zi-c!h>P2#C&R;Hxy}ZgF`IzuuN1s&EZ@lbP))Ifa_En!J{7$!%c6-%TRxMk(%KEXV z^r3WS=Jl8Df7K=O>MPe%Y&*FS+8f z*Ib^Y<7GBoe#OC8Ex-1POZLC&M=#&MUModYVx1l~T(_NWTu;Y(_urHNKVT0PL}6Mo&pHaO=O)cWLes!BCsY& zPL=7Tm`J+aPL@)VPLnj(or*ju**KXdc~0jxmeNN`JE?! z|F4Dr7*2k3`uXsm!k>rV4Sy0&{*IIXBK%EwAe?+S{oC+&;lG9-OW%@C{nGDc4~H+M zAzyiV63fLwvMnh;8e-ND>Ae1B^Hr#lG8v??w7vNK8arTm!wd?3u^MHQ$u2s5E5)I~~5RT8Hc%5;XCxilGs^JhZ* z1XDoK^gztj$JwcUoK|;yPwcx2(|6+CB^0JdN;V&>P-f@Pq(%Ilr2KG53VUxQtZVC* z;pN`(v~_HKdM^fzk8hbG8bJrp+UE3q`jqlX42JQ>a$#Gtv9Mtdiv;WVM?+Zgp@OtQ zR)xhX-3tzBa$%5GVJ{72F&r51f`4J}mO+Tg1v6>7Qe{FmI4hqq9SQ?UMH$*N3k^Pi zKCqK>Nf~+p1S34*RiSkF{BVj3S z+&u#!_B%8;w;;fCtI@ZvX<|21W?hvh={mbmzQsP3gRTZVq0*ZN>0VIj012FQp_-`D z#q!G`H2`W*T3mOGAT>h93iOrQ0(AncBV

*(%&p<+tpr-g0P1n(L#wD4#O?o}HFe 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 X6Fm(o%DPuKeEe;2Ru{=53YPx@2sFHU literal 0 HcmV?d00001 diff --git a/wasi/unstable/mapdir_with_leading_slash.wast b/wasi/unstable/mapdir_with_leading_slash.wast new file mode 100644 index 000000000..945e660f7 --- /dev/null +++ b/wasi/unstable/mapdir_with_leading_slash.wast @@ -0,0 +1,7 @@ +;; This file was generated by https://github.com/wasmerio/wasi-tests + +(wasi_test "mapdir_with_leading_slash.wasm" + (map_dirs "/hamlet:test_fs/hamlet") + (assert_return (i64.const 0)) + (assert_stdout "File exists? true\nSCENE III. A room in the castle.\n\n Enter KING CLAUDIUS, ROSENCRANTZ, and GUILDENSTERN \n\nKING CLAUDIUS\n\n I like him not, nor stands it safe with us\n To let his madness range. Therefore prepare you;\n I your commission will forthwith dispatch,\n \n") +) From 5ac0f89d92084a043fa645a26a4e273fe9b5dab7 Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Wed, 30 Sep 2020 17:10:05 -0700 Subject: [PATCH 098/281] Add small clean up --- lib/c-api/wasmer_wasm.h | 4 ++++ lib/engine-object-file/README.md | 3 --- tests/integration/cli/src/object_file_engine_test_c_source.c | 3 --- 3 files changed, 4 insertions(+), 6 deletions(-) diff --git a/lib/c-api/wasmer_wasm.h b/lib/c-api/wasmer_wasm.h index a43d09c6e..7cc40a61a 100644 --- a/lib/c-api/wasmer_wasm.h +++ b/lib/c-api/wasmer_wasm.h @@ -118,6 +118,10 @@ own wasm_func_t* wasi_get_start_function(wasm_instance_t*); // Delete a `wasm_extern_t` allocated by the API. void wasm_extern_delete(own wasm_extern_t*); +// Get an opaque pointer to the vmctx. This pointer can be used to call functions +// through their generated trampolines when compiling with the object-file engine. +void* wasm_instance_get_vmctx_ptr(wasm_instance_t*); + // TODO: figure out if we can do less duplication. /** * Gets the length in bytes of the last error if any. diff --git a/lib/engine-object-file/README.md b/lib/engine-object-file/README.md index a12bdeac4..79d63de9e 100644 --- a/lib/engine-object-file/README.md +++ b/lib/engine-object-file/README.md @@ -35,9 +35,6 @@ Now lets create a program to link with this object file. void wasmer_function__1(void); void wasmer_trampoline_function_call__1(void*, void*, void*); -// todo: add to wasmer_wasm.h or something -void* wasm_instance_get_vmctx_ptr(wasm_instance_t*); - // a bit of a hack; TODO: clean this up typedef struct my_byte_vec_t { size_t size; diff --git a/tests/integration/cli/src/object_file_engine_test_c_source.c b/tests/integration/cli/src/object_file_engine_test_c_source.c index 129d02fe5..7e018245e 100644 --- a/tests/integration/cli/src/object_file_engine_test_c_source.c +++ b/tests/integration/cli/src/object_file_engine_test_c_source.c @@ -12,9 +12,6 @@ extern "C" { void wasmer_function__1(void); void wasmer_trampoline_function_call__1(void*, void*, void*); -// todo: add to wasmer_wasm.h or something -void* wasm_instance_get_vmctx_ptr(wasm_instance_t*); - #ifdef __cplusplus } #endif From 614e4f7033b2014fa48070eb6733611e208caa74 Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Wed, 30 Sep 2020 17:47:24 -0700 Subject: [PATCH 099/281] Clean up code and add comment --- lib/wasi/src/state/builder.rs | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/lib/wasi/src/state/builder.rs b/lib/wasi/src/state/builder.rs index b3636eecb..f6694bb02 100644 --- a/lib/wasi/src/state/builder.rs +++ b/lib/wasi/src/state/builder.rs @@ -438,17 +438,10 @@ impl PreopenDirBuilder { /// Make this preopened directory appear to the WASI program as `alias` pub fn alias(&mut self, alias: &str) -> &mut Self { - let alias = if let Some(first_byte) = alias.as_bytes().first() { - if *first_byte == b'/' { - &alias[1..] - } else { - alias - } - } else { - alias - } - .to_string(); - self.alias = Some(alias); + // We mount at preopened dirs at `/` by default and multiple `/` in a row + // are equal to a single `/`. + let alias = alias.trim_start_matches('/'); + self.alias = Some(alias.to_string()); self } From 5ea1f1eb25b0adb1ea9b5c14e49e3eaf999abbc2 Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Thu, 1 Oct 2020 09:52:23 +0200 Subject: [PATCH 100/281] feat(c-api) Always generate _all_ C headers. Include the deprecated API per default. --- Makefile | 6 +++--- lib/c-api/Cargo.toml | 2 ++ lib/c-api/build.rs | 8 -------- 3 files changed, 5 insertions(+), 11 deletions(-) diff --git a/Makefile b/Makefile index 3cb273b8a..2f1482b31 100644 --- a/Makefile +++ b/Makefile @@ -76,15 +76,15 @@ build-capi: build-capi-cranelift build-capi-singlepass: cargo build --manifest-path lib/c-api/Cargo.toml --release \ - --no-default-features --features jit,singlepass,wasi + --no-default-features --features jit,singlepass,wasi,deprecated build-capi-cranelift: cargo build --manifest-path lib/c-api/Cargo.toml --release \ - --no-default-features --features jit,cranelift,wasi + --no-default-features --features jit,cranelift,wasi,deprecated build-capi-llvm: cargo build --manifest-path lib/c-api/Cargo.toml --release \ - --no-default-features --features jit,llvm,wasi + --no-default-features --features jit,llvm,wasi,deprecated ########### diff --git a/lib/c-api/Cargo.toml b/lib/c-api/Cargo.toml index 5b7fafce2..c7b25a3a1 100644 --- a/lib/c-api/Cargo.toml +++ b/lib/c-api/Cargo.toml @@ -42,6 +42,7 @@ paste = "0.1" default = [ "cranelift", "wasi", + "deprecated", ] wasi = ["wasmer-wasi", "typetag", "serde"] engine = [] @@ -70,6 +71,7 @@ llvm = [ "compiler", ] #emscripten = ["wasmer-emscripten"] +# Include the deprecated Wasmer C API. deprecated = [] # This is for compatibility for old usage diff --git a/lib/c-api/build.rs b/lib/c-api/build.rs index f506a1217..af5f06fd2 100644 --- a/lib/c-api/build.rs +++ b/lib/c-api/build.rs @@ -39,9 +39,6 @@ const WASI_FEATURE_AS_C_DEFINE: &'static str = "WASMER_WASI_ENABLED"; #[allow(unused)] const EMSCRIPTEN_FEATURE_AS_C_DEFINE: &'static str = "WASMER_EMSCRIPTEN_ENABLED"; -#[allow(unused)] -const DEPRECATED_FEATURE_AS_C_DEFINE: &'static str = "WASMER_DEPRECATED_ENABLED"; - macro_rules! map_feature_as_c_define { ($feature:expr, $c_define:ident, $accumulator:ident) => { #[cfg(feature = $feature)] @@ -62,10 +59,7 @@ fn main() { let crate_dir = env::var("CARGO_MANIFEST_DIR").unwrap(); let out_dir = env::var("OUT_DIR").unwrap(); - #[cfg(not(feature = "deprecated"))] build_wasm_c_api_headers(&crate_dir, &out_dir); - - #[cfg(feature = "deprecated")] build_wasmer_headers(&crate_dir, &out_dir); } @@ -91,7 +85,6 @@ fn build_wasm_c_api_headers(crate_dir: &str, out_dir: &str) { map_feature_as_c_define!("compiler", COMPILER_FEATURE_AS_C_DEFINE, pre_header); map_feature_as_c_define!("wasi", WASI_FEATURE_AS_C_DEFINE, pre_header); map_feature_as_c_define!("emscripten", EMSCRIPTEN_FEATURE_AS_C_DEFINE, pre_header); - map_feature_as_c_define!("deprecated", DEPRECATED_FEATURE_AS_C_DEFINE, pre_header); // Close pre header. pre_header.push_str( @@ -122,7 +115,6 @@ fn build_wasm_c_api_headers(crate_dir: &str, out_dir: &str) { .with_define("feature", "compiler", COMPILER_FEATURE_AS_C_DEFINE) .with_define("feature", "wasi", WASI_FEATURE_AS_C_DEFINE) .with_define("feature", "emscripten", EMSCRIPTEN_FEATURE_AS_C_DEFINE) - .with_define("feature", "deprecated", DEPRECATED_FEATURE_AS_C_DEFINE) .with_include("wasm.h") .with_documentation(true); builder = exclude_items_from_deprecated(builder); From c1fb4b2c29592367b23135060e57b62dcfe848b3 Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Thu, 1 Oct 2020 10:07:35 +0200 Subject: [PATCH 101/281] test(c-api) Restore the deprecated test suite. --- Cargo.lock | 2 +- lib/c-api/Cargo.toml | 6 ++++- lib/c-api/tests/deprecated/CMakeLists.txt | 25 ++++++++++--------- lib/c-api/tests/deprecated/test-context.c | 2 +- .../test-emscripten-import-object.c | 2 +- .../tests/deprecated/test-exported-memory.c | 2 +- lib/c-api/tests/deprecated/test-exports.c | 2 +- lib/c-api/tests/deprecated/test-globals.c | 2 +- .../test-import-function-callinfo.c | 2 +- .../tests/deprecated/test-import-function.c | 2 +- .../tests/deprecated/test-import-object.c | 2 +- lib/c-api/tests/deprecated/test-import-trap.c | 2 +- lib/c-api/tests/deprecated/test-imports.c | 2 +- lib/c-api/tests/deprecated/test-instantiate.c | 2 +- lib/c-api/tests/deprecated/test-memory.c | 2 +- .../tests/deprecated/test-module-exports.c | 2 +- .../test-module-import-instantiate.c | 2 +- .../tests/deprecated/test-module-imports.c | 2 +- .../tests/deprecated/test-module-serialize.c | 2 +- lib/c-api/tests/deprecated/test-module.c | 2 +- lib/c-api/tests/deprecated/test-tables.c | 2 +- lib/c-api/tests/deprecated/test-validate.c | 2 +- .../deprecated/test-wasi-import-object.c | 3 +-- lib/c-api/tests/deprecated_tests.rs | 11 +++----- 24 files changed, 43 insertions(+), 42 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index be2fe5a3a..0ec86758b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -206,7 +206,7 @@ dependencies = [ [[package]] name = "cbindgen" version = "0.14.6" -source = "git+https://github.com/Hywan/cbindgen?branch=incoming#ab5427b358f8953f1455e3a630af76e8dd37af67" +source = "git+https://github.com/eqrion/cbindgen#1fc4cb072422e722f8bcb3af5766f84587a180c6" dependencies = [ "clap", "heck", diff --git a/lib/c-api/Cargo.toml b/lib/c-api/Cargo.toml index c7b25a3a1..64c2b4e16 100644 --- a/lib/c-api/Cargo.toml +++ b/lib/c-api/Cargo.toml @@ -70,10 +70,14 @@ llvm = [ "wasmer-compiler-llvm", "compiler", ] -#emscripten = ["wasmer-emscripten"] + # Include the deprecated Wasmer C API. deprecated = [] +# Deprecated feature. +# TODO: Port this feature. +#emscripten = ["wasmer-emscripten"] + # This is for compatibility for old usage singlepass-backend = ["singlepass"] cranelift-backend = ["cranelift"] diff --git a/lib/c-api/tests/deprecated/CMakeLists.txt b/lib/c-api/tests/deprecated/CMakeLists.txt index 9cd2e5374..96a2fc088 100644 --- a/lib/c-api/tests/deprecated/CMakeLists.txt +++ b/lib/c-api/tests/deprecated/CMakeLists.txt @@ -78,6 +78,10 @@ target_link_libraries(test-import-trap general ${WASMER_LIB}) target_compile_options(test-import-trap PRIVATE ${COMPILER_OPTIONS}) add_test(test-import-trap test-import-trap) +target_link_libraries(test-imports general ${WASMER_LIB}) +target_compile_options(test-imports PRIVATE ${COMPILER_OPTIONS}) +add_test(test-imports test-imports) + target_link_libraries(test-instantiate general ${WASMER_LIB}) target_compile_options(test-instantiate PRIVATE ${COMPILER_OPTIONS}) add_test(test-instantiate test-instantiate) @@ -94,17 +98,13 @@ target_link_libraries(test-module-exports general ${WASMER_LIB}) target_compile_options(test-module-exports PRIVATE ${COMPILER_OPTIONS}) add_test(test-module-exports test-module-exports) -target_link_libraries(test-module-imports general ${WASMER_LIB}) -target_compile_options(test-module-imports PRIVATE ${COMPILER_OPTIONS}) -add_test(test-module-imports test-module-imports) - target_link_libraries(test-module-import-instantiate general ${WASMER_LIB}) target_compile_options(test-module-import-instantiate PRIVATE ${COMPILER_OPTIONS}) add_test(test-module-import-instantiate test-module-import-instantiate) -target_link_libraries(test-imports general ${WASMER_LIB}) -target_compile_options(test-imports PRIVATE ${COMPILER_OPTIONS}) -add_test(test-imports test-imports) +target_link_libraries(test-module-imports general ${WASMER_LIB}) +target_compile_options(test-module-imports PRIVATE ${COMPILER_OPTIONS}) +add_test(test-module-imports test-module-imports) target_link_libraries(test-module-serialize general ${WASMER_LIB}) target_compile_options(test-module-serialize PRIVATE ${COMPILER_OPTIONS}) @@ -125,8 +125,9 @@ if (DEFINED WASI_TESTS) #add_test(test-wasi-import-object test-wasi-import-object) endif() -if (DEFINED EMSCRIPTEN_TESTS) - target_link_libraries(test-emscripten-import-object general ${WASMER_LIB}) - target_compile_options(test-emscripten-import-object PRIVATE ${COMPILER_OPTIONS}) - add_test(test-emscripten-import-object test-emscripten-import-object) -endif() +# TODO: reenable this test +#if (DEFINED EMSCRIPTEN_TESTS) +# target_link_libraries(test-emscripten-import-object general ${WASMER_LIB}) +# target_compile_options(test-emscripten-import-object PRIVATE ${COMPILER_OPTIONS}) +# add_test(test-emscripten-import-object test-emscripten-import-object) +#endif() diff --git a/lib/c-api/tests/deprecated/test-context.c b/lib/c-api/tests/deprecated/test-context.c index a8d0f7099..44abec1ee 100644 --- a/lib/c-api/tests/deprecated/test-context.c +++ b/lib/c-api/tests/deprecated/test-context.c @@ -1,5 +1,5 @@ #include -#include "../wasmer.h" +#include "../../wasmer.h" #include #include #include diff --git a/lib/c-api/tests/deprecated/test-emscripten-import-object.c b/lib/c-api/tests/deprecated/test-emscripten-import-object.c index bbc581db3..91e018d2b 100644 --- a/lib/c-api/tests/deprecated/test-emscripten-import-object.c +++ b/lib/c-api/tests/deprecated/test-emscripten-import-object.c @@ -1,5 +1,5 @@ #include -#include "../wasmer.h" +#include "../../wasmer.h" #include #include #include diff --git a/lib/c-api/tests/deprecated/test-exported-memory.c b/lib/c-api/tests/deprecated/test-exported-memory.c index 895b5c27c..d4537f1c1 100644 --- a/lib/c-api/tests/deprecated/test-exported-memory.c +++ b/lib/c-api/tests/deprecated/test-exported-memory.c @@ -1,5 +1,5 @@ #include -#include "../wasmer.h" +#include "../../wasmer.h" #include #include #include diff --git a/lib/c-api/tests/deprecated/test-exports.c b/lib/c-api/tests/deprecated/test-exports.c index e245414be..202156f37 100644 --- a/lib/c-api/tests/deprecated/test-exports.c +++ b/lib/c-api/tests/deprecated/test-exports.c @@ -1,6 +1,6 @@ #include #include -#include "../wasmer.h" +#include "../../wasmer.h" #include #include #include diff --git a/lib/c-api/tests/deprecated/test-globals.c b/lib/c-api/tests/deprecated/test-globals.c index a694d2e75..50e354e1c 100644 --- a/lib/c-api/tests/deprecated/test-globals.c +++ b/lib/c-api/tests/deprecated/test-globals.c @@ -1,5 +1,5 @@ #include -#include "../wasmer.h" +#include "../../wasmer.h" #include #include diff --git a/lib/c-api/tests/deprecated/test-import-function-callinfo.c b/lib/c-api/tests/deprecated/test-import-function-callinfo.c index 371f9eeba..1d30db112 100644 --- a/lib/c-api/tests/deprecated/test-import-function-callinfo.c +++ b/lib/c-api/tests/deprecated/test-import-function-callinfo.c @@ -1,5 +1,5 @@ #include -#include "../wasmer.h" +#include "../../wasmer.h" #include #include #include diff --git a/lib/c-api/tests/deprecated/test-import-function.c b/lib/c-api/tests/deprecated/test-import-function.c index a53dec75f..526d18eaa 100644 --- a/lib/c-api/tests/deprecated/test-import-function.c +++ b/lib/c-api/tests/deprecated/test-import-function.c @@ -1,5 +1,5 @@ #include -#include "../wasmer.h" +#include "../../wasmer.h" #include #include #include diff --git a/lib/c-api/tests/deprecated/test-import-object.c b/lib/c-api/tests/deprecated/test-import-object.c index 7cf2ee7be..84f04b1df 100644 --- a/lib/c-api/tests/deprecated/test-import-object.c +++ b/lib/c-api/tests/deprecated/test-import-object.c @@ -1,5 +1,5 @@ #include -#include "../wasmer.h" +#include "../../wasmer.h" #include #include #include diff --git a/lib/c-api/tests/deprecated/test-import-trap.c b/lib/c-api/tests/deprecated/test-import-trap.c index eec9072ac..11294d220 100644 --- a/lib/c-api/tests/deprecated/test-import-trap.c +++ b/lib/c-api/tests/deprecated/test-import-trap.c @@ -1,5 +1,5 @@ #include -#include "../wasmer.h" +#include "../../wasmer.h" #include #include #include diff --git a/lib/c-api/tests/deprecated/test-imports.c b/lib/c-api/tests/deprecated/test-imports.c index ec6bf28a5..203d56f67 100644 --- a/lib/c-api/tests/deprecated/test-imports.c +++ b/lib/c-api/tests/deprecated/test-imports.c @@ -1,5 +1,5 @@ #include -#include "../wasmer.h" +#include "../../wasmer.h" #include #include #include diff --git a/lib/c-api/tests/deprecated/test-instantiate.c b/lib/c-api/tests/deprecated/test-instantiate.c index 2bbca92d6..84f5e4210 100644 --- a/lib/c-api/tests/deprecated/test-instantiate.c +++ b/lib/c-api/tests/deprecated/test-instantiate.c @@ -1,5 +1,5 @@ #include -#include "../wasmer.h" +#include "../../wasmer.h" #include #include #include diff --git a/lib/c-api/tests/deprecated/test-memory.c b/lib/c-api/tests/deprecated/test-memory.c index 421b0ca94..8e1576a75 100644 --- a/lib/c-api/tests/deprecated/test-memory.c +++ b/lib/c-api/tests/deprecated/test-memory.c @@ -1,5 +1,5 @@ #include -#include "../wasmer.h" +#include "../../wasmer.h" #include #include #include diff --git a/lib/c-api/tests/deprecated/test-module-exports.c b/lib/c-api/tests/deprecated/test-module-exports.c index f290ef45b..1dc0eb3e0 100644 --- a/lib/c-api/tests/deprecated/test-module-exports.c +++ b/lib/c-api/tests/deprecated/test-module-exports.c @@ -1,5 +1,5 @@ #include -#include "../wasmer.h" +#include "../../wasmer.h" #include #include diff --git a/lib/c-api/tests/deprecated/test-module-import-instantiate.c b/lib/c-api/tests/deprecated/test-module-import-instantiate.c index 9649335e8..448634d57 100644 --- a/lib/c-api/tests/deprecated/test-module-import-instantiate.c +++ b/lib/c-api/tests/deprecated/test-module-import-instantiate.c @@ -1,5 +1,5 @@ #include -#include "../wasmer.h" +#include "../../wasmer.h" #include #include #include diff --git a/lib/c-api/tests/deprecated/test-module-imports.c b/lib/c-api/tests/deprecated/test-module-imports.c index 532005928..21a41a744 100644 --- a/lib/c-api/tests/deprecated/test-module-imports.c +++ b/lib/c-api/tests/deprecated/test-module-imports.c @@ -1,5 +1,5 @@ #include -#include "../wasmer.h" +#include "../../wasmer.h" #include #include diff --git a/lib/c-api/tests/deprecated/test-module-serialize.c b/lib/c-api/tests/deprecated/test-module-serialize.c index 56b5834af..dcab39526 100644 --- a/lib/c-api/tests/deprecated/test-module-serialize.c +++ b/lib/c-api/tests/deprecated/test-module-serialize.c @@ -1,5 +1,5 @@ #include -#include "../wasmer.h" +#include "../../wasmer.h" #include #include diff --git a/lib/c-api/tests/deprecated/test-module.c b/lib/c-api/tests/deprecated/test-module.c index a3f21f6a1..9f818ffd9 100644 --- a/lib/c-api/tests/deprecated/test-module.c +++ b/lib/c-api/tests/deprecated/test-module.c @@ -1,5 +1,5 @@ #include -#include "../wasmer.h" +#include "../../wasmer.h" #include #include diff --git a/lib/c-api/tests/deprecated/test-tables.c b/lib/c-api/tests/deprecated/test-tables.c index ac093d182..8d001de50 100644 --- a/lib/c-api/tests/deprecated/test-tables.c +++ b/lib/c-api/tests/deprecated/test-tables.c @@ -1,5 +1,5 @@ #include -#include "../wasmer.h" +#include "../../wasmer.h" #include #include diff --git a/lib/c-api/tests/deprecated/test-validate.c b/lib/c-api/tests/deprecated/test-validate.c index 8ce135d82..e4d80735a 100644 --- a/lib/c-api/tests/deprecated/test-validate.c +++ b/lib/c-api/tests/deprecated/test-validate.c @@ -1,5 +1,5 @@ #include -#include "../wasmer.h" +#include "../../wasmer.h" #include #include diff --git a/lib/c-api/tests/deprecated/test-wasi-import-object.c b/lib/c-api/tests/deprecated/test-wasi-import-object.c index da9484996..0dacda8cb 100644 --- a/lib/c-api/tests/deprecated/test-wasi-import-object.c +++ b/lib/c-api/tests/deprecated/test-wasi-import-object.c @@ -1,5 +1,5 @@ #include -#include "../wasmer.h" +#include "../../wasmer.h" #include #include #include @@ -257,4 +257,3 @@ int main() return 0; } - diff --git a/lib/c-api/tests/deprecated_tests.rs b/lib/c-api/tests/deprecated_tests.rs index 5d8f09351..f8c2a6683 100644 --- a/lib/c-api/tests/deprecated_tests.rs +++ b/lib/c-api/tests/deprecated_tests.rs @@ -34,14 +34,11 @@ fn run_command(command_str: &str, dir: &str, args: Vec<&str>) { match command.output() { Ok(result) => { - println!("> Status: `{:?}`", result.status.code()); println!( - "> Stdout: `{}`", - String::from_utf8_lossy(&result.stdout[..]) - ); - println!( - "> Stderr: `{}`", - String::from_utf8_lossy(&result.stderr[..]) + "> Status: `{:?}`\n> Stdout: `{}`\n> Stderr: `{}`", + result.status.code(), + String::from_utf8_lossy(&result.stdout[..]), + String::from_utf8_lossy(&result.stderr[..]), ); if result.status.success() { From 3f8d7f4f741ffaa48c15fe23d584fec0d20e106d Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Thu, 1 Oct 2020 10:11:02 +0200 Subject: [PATCH 102/281] test(c-api) Update the CMake project name for the deprecated test suite. --- lib/c-api/tests/deprecated/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/c-api/tests/deprecated/CMakeLists.txt b/lib/c-api/tests/deprecated/CMakeLists.txt index 96a2fc088..ddb1cb6de 100644 --- a/lib/c-api/tests/deprecated/CMakeLists.txt +++ b/lib/c-api/tests/deprecated/CMakeLists.txt @@ -1,5 +1,5 @@ cmake_minimum_required (VERSION 2.6) -project (WasmerRuntimeCApiTests) +project (WasmerDeprecatedCApiTests) add_executable(test-context test-context.c) add_executable(test-exported-memory test-exported-memory.c) From bf7b50a8eb83b7fbd9de6e93f39b5674c0ba88a5 Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Thu, 1 Oct 2020 14:13:02 +0200 Subject: [PATCH 103/281] test(c-api) Restore the `wasm-c-api` test suite. --- lib/c-api/tests/deprecated_tests.rs | 42 +----- lib/c-api/tests/test_c_helpers/mod.rs | 46 ++++++ lib/c-api/tests/wasm_c_api/CMakeLists.txt | 140 ++++++++++++++++++ .../test-wasi.c} | 4 +- .../tests/wasm_c_api/wasm-c-api-callback | Bin 0 -> 19008 bytes lib/c-api/tests/wasm_c_api/wasm-c-api-global | Bin 0 -> 23088 bytes lib/c-api/tests/wasm_c_api/wasm-c-api-hello | Bin 0 -> 18520 bytes lib/c-api/tests/wasm_c_api/wasm-c-api-memory | Bin 0 -> 19456 bytes lib/c-api/tests/wasm_c_api/wasm-c-api-reflect | Bin 0 -> 19956 bytes .../tests/wasm_c_api/wasm-c-api-serialize | Bin 0 -> 18680 bytes lib/c-api/tests/wasm_c_api_tests.rs | 18 +++ 11 files changed, 211 insertions(+), 39 deletions(-) create mode 100644 lib/c-api/tests/test_c_helpers/mod.rs create mode 100644 lib/c-api/tests/wasm_c_api/CMakeLists.txt rename lib/c-api/tests/{wasm-c-api-wasi.c => wasm_c_api/test-wasi.c} (98%) create mode 100755 lib/c-api/tests/wasm_c_api/wasm-c-api-callback create mode 100755 lib/c-api/tests/wasm_c_api/wasm-c-api-global create mode 100755 lib/c-api/tests/wasm_c_api/wasm-c-api-hello create mode 100755 lib/c-api/tests/wasm_c_api/wasm-c-api-memory create mode 100755 lib/c-api/tests/wasm_c_api/wasm-c-api-reflect create mode 100755 lib/c-api/tests/wasm_c_api/wasm-c-api-serialize create mode 100644 lib/c-api/tests/wasm_c_api_tests.rs diff --git a/lib/c-api/tests/deprecated_tests.rs b/lib/c-api/tests/deprecated_tests.rs index f8c2a6683..b15a26b1b 100644 --- a/lib/c-api/tests/deprecated_tests.rs +++ b/lib/c-api/tests/deprecated_tests.rs @@ -1,4 +1,6 @@ -use std::process::Command; +mod test_c_helpers; + +use test_c_helpers::compile_with_cmake_and_run_test; #[test] fn test_deprecated_c_api() { @@ -15,40 +17,6 @@ fn test_deprecated_c_api() { #[cfg(target_os = "windows")] r#"-G "MinGW Makefiles""#, ]; - // we use -f so it doesn't fail if the file doesn't exist - run_command("rm", project_tests_dir, vec!["-f", "CMakeCache.txt"]); - run_command("cmake", project_tests_dir, cmake_args); - run_command("make", project_tests_dir, vec!["-Wdev", "-Werror=dev"]); - run_command("make", project_tests_dir, vec!["test", "ARGS=\"-V\""]); -} - -fn run_command(command_str: &str, dir: &str, args: Vec<&str>) { - println!( - "Running command: `{}` with arguments: {:?}", - command_str, args - ); - - let mut command = Command::new(command_str); - command.args(&args); - command.current_dir(dir); - - match command.output() { - Ok(result) => { - println!( - "> Status: `{:?}`\n> Stdout: `{}`\n> Stderr: `{}`", - result.status.code(), - String::from_utf8_lossy(&result.stdout[..]), - String::from_utf8_lossy(&result.stderr[..]), - ); - - if result.status.success() { - assert!(true) - } else { - panic!("Command failed with exit status: `{:?}`", result.status); - } - } - Err(error) => panic!("Command failed: `{}`", error), - } - - println!("\n"); + + compile_with_cmake_and_run_test(project_tests_dir, cmake_args); } diff --git a/lib/c-api/tests/test_c_helpers/mod.rs b/lib/c-api/tests/test_c_helpers/mod.rs new file mode 100644 index 000000000..32c520cae --- /dev/null +++ b/lib/c-api/tests/test_c_helpers/mod.rs @@ -0,0 +1,46 @@ +use std::process::Command; + +pub fn compile_with_cmake_and_run_test(project_tests_dir: &str, cmake_args: Vec<&str>) { + run_command( + "rm", + project_tests_dir, + vec![ + "-f", // we use -f so it doesn't fail if the file doesn't exist + "CMakeCache.txt", + ], + ); + run_command("cmake", project_tests_dir, cmake_args); + run_command("make", project_tests_dir, vec!["-Wdev", "-Werror=dev"]); + run_command("make", project_tests_dir, vec!["test", "ARGS=\"-V\""]); +} + +pub fn run_command(command_str: &str, dir: &str, args: Vec<&str>) { + println!( + "Running command: `{}` with arguments: {:?}", + command_str, args + ); + + let mut command = Command::new(command_str); + command.args(&args); + command.current_dir(dir); + + match command.output() { + Ok(result) => { + println!( + "> Status: `{:?}`\n> Stdout: `{}`\n> Stderr: `{}`", + result.status.code(), + String::from_utf8_lossy(&result.stdout[..]), + String::from_utf8_lossy(&result.stderr[..]), + ); + + if result.status.success() { + assert!(true) + } else { + panic!("Command failed with exit status: `{:?}`", result.status); + } + } + Err(error) => panic!("Command failed: `{}`", error), + } + + println!("\n"); +} diff --git a/lib/c-api/tests/wasm_c_api/CMakeLists.txt b/lib/c-api/tests/wasm_c_api/CMakeLists.txt new file mode 100644 index 000000000..55eedab30 --- /dev/null +++ b/lib/c-api/tests/wasm_c_api/CMakeLists.txt @@ -0,0 +1,140 @@ +cmake_minimum_required (VERSION 2.6) +project (WasmerWasmCApiTests) + +# Examples as tests from the `wasm-c-api` repository. +add_executable(wasm-c-api-callback wasm-c-api/example/callback.c) +#add_executable(wasm-c-api-finalize wasm-c-api/example/finalize.c) +#add_executable(wasm-c-api-global wasm-c-api/example/global.c) +add_executable(wasm-c-api-hello wasm-c-api/example/hello.c) +#add_executable(wasm-c-api-hostref wasm-c-api/example/hostref.c) +#add_executable(wasm-c-api-memory wasm-c-api/example/memory.c) +#add_executable(wasm-c-api-multi wasm-c-api/example/multi.c) +add_executable(wasm-c-api-reflect wasm-c-api/example/reflect.c) +add_executable(wasm-c-api-serialize wasm-c-api/example/serialize.c) +#add_executable(wasm-c-api-start wasm-c-api/example/start.c) +#add_executable(wasm-c-api-table wasm-c-api/example/table.c) +#add_executable(wasm-c-api-threads wasm-c-api/example/threads.c) +#add_executable(wasm-c-api-trap wasm-c-api/example/trap.c) + +# Our additional tests. +#add_executable(test-wasi test-wasi.c) + +include_directories(wasm-c-api/include) +include_directories(../../) + +find_library( + WASMER_LIB NAMES libwasmer_c_api.dylib libwasmer_c_api.so wasmer_c_api.dll + PATHS ${CMAKE_SOURCE_DIR}/../../../../target/release/ +) + +if(NOT WASMER_LIB) + message(FATAL_ERROR "wasmer library not found") +endif() + +enable_testing() + +set( + COMPILER_OPTIONS + # Clang or gcc + $<$,$>: + "-Werror" > + # MSVC + $<$: + "/WX" > +) + +target_link_libraries(wasm-c-api-callback general ${WASMER_LIB}) +target_compile_options(wasm-c-api-callback PRIVATE ${COMPILER_OPTIONS}) +add_test(NAME wasm-c-api-callback + COMMAND wasm-c-api-callback + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/wasm-c-api/example/ +) + +#target_link_libraries(wasm-c-api-finalize general ${WASMER_LIB}) +#target_compile_options(wasm-c-api-finalize PRIVATE ${COMPILER_OPTIONS}) +#add_test(NAME wasm-c-api-finalize +# COMMAND wasm-c-api-finalize +# WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/wasm-c-api/example/ +#) + +#target_link_libraries(wasm-c-api-global general ${WASMER_LIB}) +#target_compile_options(wasm-c-api-global PRIVATE ${COMPILER_OPTIONS}) +#add_test(NAME wasm-c-api-global +# COMMAND wasm-c-api-global +# WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/wasm-c-api/example/ +#) + +target_link_libraries(wasm-c-api-hello general ${WASMER_LIB}) +target_compile_options(wasm-c-api-hello PRIVATE ${COMPILER_OPTIONS}) +add_test(NAME wasm-c-api-hello + COMMAND wasm-c-api-hello + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/wasm-c-api/example/ +) + +#target_link_libraries(wasm-c-api-hostref general ${WASMER_LIB}) +#target_compile_options(wasm-c-api-hostref PRIVATE ${COMPILER_OPTIONS}) +#add_test(NAME wasm-c-api-hostref +# COMMAND wasm-c-api-hostref +# WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/wasm-c-api/example/ +#) + +#target_link_libraries(wasm-c-api-memory general ${WASMER_LIB}) +#target_compile_options(wasm-c-api-memory PRIVATE ${COMPILER_OPTIONS}) +#add_test(NAME wasm-c-api-memory +# COMMAND wasm-c-api-memory +# WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/wasm-c-api/example/ +#) + +#target_link_libraries(wasm-c-api-multi general ${WASMER_LIB}) +#target_compile_options(wasm-c-api-multi PRIVATE ${COMPILER_OPTIONS}) +#add_test(NAME wasm-c-api-multi +# COMMAND wasm-c-api-multi +# WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/wasm-c-api/example/ +#) + +target_link_libraries(wasm-c-api-reflect general ${WASMER_LIB}) +target_compile_options(wasm-c-api-reflect PRIVATE ${COMPILER_OPTIONS}) +add_test(NAME wasm-c-api-reflect + COMMAND wasm-c-api-reflect + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/wasm-c-api/example/ +) + +target_link_libraries(wasm-c-api-serialize general ${WASMER_LIB}) +target_compile_options(wasm-c-api-serialize PRIVATE ${COMPILER_OPTIONS}) +add_test(NAME wasm-c-api-serialize + COMMAND wasm-c-api-serialize + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/wasm-c-api/example/ +) + +#target_link_libraries(wasm-c-api-start general ${WASMER_LIB}) +#target_compile_options(wasm-c-api-start PRIVATE ${COMPILER_OPTIONS}) +#add_test(NAME wasm-c-api-start +# COMMAND wasm-c-api-start +# WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/wasm-c-api/example/ +#) + +#target_link_libraries(wasm-c-api-table general ${WASMER_LIB}) +#target_compile_options(wasm-c-api-table PRIVATE ${COMPILER_OPTIONS}) +#add_test(NAME wasm-c-api-table +# COMMAND wasm-c-api-table +# WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/wasm-c-api/example/ +#) + +#target_link_libraries(wasm-c-api-threads general ${WASMER_LIB}) +#target_compile_options(wasm-c-api-threads PRIVATE ${COMPILER_OPTIONS}) +#add_test(NAME wasm-c-api-threads +# COMMAND wasm-c-api-threads +# WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/wasm-c-api/example/ +#) + +#target_link_libraries(wasm-c-api-trap general ${WASMER_LIB}) +#target_compile_options(wasm-c-api-trap PRIVATE ${COMPILER_OPTIONS}) +#add_test(NAME wasm-c-api-trap +# COMMAND wasm-c-api-trap +# WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/wasm-c-api/example/ +#) + +#set_property(TARGET test-wasi PROPERTY C_STANDARD 11) +#target_link_libraries(test-wasi general ${WASMER_LIB}) +#target_compile_options(test-wasi PRIVATE ${COMPILER_OPTIONS}) +#add_test(test-wasi test-wasi) diff --git a/lib/c-api/tests/wasm-c-api-wasi.c b/lib/c-api/tests/wasm_c_api/test-wasi.c similarity index 98% rename from lib/c-api/tests/wasm-c-api-wasi.c rename to lib/c-api/tests/wasm_c_api/test-wasi.c index bc020d418..9a507b02e 100644 --- a/lib/c-api/tests/wasm-c-api-wasi.c +++ b/lib/c-api/tests/wasm_c_api/test-wasi.c @@ -3,8 +3,8 @@ #include #include -#include "wasm.h" -#include "wasmer_wasm.h" +#include "../../wasm.h" +#include "../../wasmer_wasm.h" #define BUF_SIZE 128 diff --git a/lib/c-api/tests/wasm_c_api/wasm-c-api-callback b/lib/c-api/tests/wasm_c_api/wasm-c-api-callback new file mode 100755 index 0000000000000000000000000000000000000000..0d13b4ebaa1fb423817d1fcd2fd866e9a95366cd GIT binary patch literal 19008 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 literal 0 HcmV?d00001 diff --git a/lib/c-api/tests/wasm_c_api/wasm-c-api-global b/lib/c-api/tests/wasm_c_api/wasm-c-api-global new file mode 100755 index 0000000000000000000000000000000000000000..db530731c5e475ab440235f15421717f1237eb80 GIT binary patch literal 23088 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%0DF2aZ#z9S7Tmsi<{{wq(;6{Ij6KvE3Iz;!4aq^ zMXnpAJKu)fDBW(9cHA^R^((h%z__K@!hXpc2VWlpc=mi{Et-})dfHl+90CV^NvEjZ z&*j2o<%bX=u&b3(#o+GFU#;-vn!bCdmL2(!5L3&JN;)LzmnD5c(ibH?Ch6BC{ko(t zNjfa)aY?@^>9-^uk@SS5Cnf!!q@$94U(!>Oo|g2Cq-Q1lk)*FlItIGAeBV#dtlKuV zYyy|vP$GfoC$1qU2~K+AO>(c0yG-t<*RKk`y;sZQQOA5$WV7Qwx_MF zZH`zQGA!Fphn`Mn?fB9;VpA&VB%^lnIcQ0R&FN@dS|n4^Y`+xY-Kd>z<0}x6g@Z^o zo6d%8t=E^1=WPp~)~EY2NjaDj>EV=i%-2c%tQB=Q5?*`Q)%Z50a!xdbkYv{_JSA_T z0B?~4PBt2oM%IB$I_oqHAC1MVT#kdO&KxYfiTL{%n$FrSJTX}M>B*-sS~>;oZHc@i z2ac!rr{u63(kTnMmhZ3do=2AY7Hcfub3crhmG7uo$m8b5JE11L^TD;FN|o^hK^tTs z$Uu;RAOk@Lf(!&12r>|4Ajm+Ffgl4x27(N{zcWz5p|z?1Bsg83-~EWFW{ukbxirK?Z^h1Q`f25M&_8z<-y4dH0Lm{D$_fPLrRm<6MUs zOYAXw^U-WvJdqVco&4BVek5;pbV?cPw+C6*J@bnAVZrJE!%f zto``FJ?Wi7vE)#Or)H&klPRmtL6@%w<{WcpReZp)vMDo~GkHLRUAui%U3`Fs`!)-kNfa%efWkC&sNT={ucQ#k7BAn7@~Ce z@Ma(G_Tjt_mwfoR55MZe7kv14KKzyszvIITv2qYq*AGX11+Noa65@7L9LJKsb-?fS z??mPA6!6R>uaJ4D{2djXBNTU|&PV0-at|sG-z`Mt3105IJgS99mI9Ae1%7HngivRr zE=B!+jv2x)QB1#w_&X+cx^@ql@*ZmVPa*gH28sIL;r$cP+rQrU^_H(UdvBY+^#<>g z^0sf>+Lc1%rrsdqHlhWM8+n7UZVOj(-{xH>l-qV4)*E)6q&B2H(pR@d*OcT=R#WtE z%1W^+^>$;QxMttD|0*>tt0^_?xJpNfYAUzhW2gQ5SH{)Z!QN~)+j03wP5k5D7sY?) F{{S^Fb+rHh literal 0 HcmV?d00001 diff --git a/lib/c-api/tests/wasm_c_api/wasm-c-api-memory b/lib/c-api/tests/wasm_c_api/wasm-c-api-memory new file mode 100755 index 0000000000000000000000000000000000000000..094ff5d0ebe30e7b37bfce5e84f6a5f86b982dc7 GIT binary patch literal 19456 zcmeHPdvH|Oc|QxtB{*h<>j%LYuXz}ZK@x;`z_vWXu=bK5TQ(?l+_;xz_ky;pcDMTg ziK#lGVhMNF>(Qhy;&>9q$t0O1Gto?Kk4lUxj0&pjIErJ(jGIXnPn=$Put$@`L?N!# z-|w7rckf<_PWoTRy?1oZ`CjLH-S1qT-95WMy!`Hmei)bcr+ia61@H`-cWl#iM#bx zXDX<=-goYJ@H64(RV{}pjRBQ$wfg`=! zgct_S{47R$bh{9nFb<+%$mcR{L*wPxSO^%)x+V|gyRQ=usOOfOMwoL$Xmq==kjpkE z6MGxu-N`s`URaLOk6*uY{nif$?_59BwW$C7V}CZX5%dt6j4`-C%tIqAb9vReIcove zqdC_agvNN9u5&1Aq}>b}c}`7`)7YLfv$@8O?nBX3<973)nM`Lo%~ZbePolX_GuwDb z4f$wxznO2$nn^R7GaKV(CdUXA*N7R>OrinNB=%A#FWTFT=GY6w19+SUsP!dS$5(f+2K&-8ICTMFBEhhGjJ z)dpV&4Qbp}H8^T7=Y&$-3aJ?oG;bLV7Wsk>ezZJ(*1r5PyneX4CZF{ihOINar&i%N zus&64|4qbt#eQ&ldfIXRC=^uk-=zINjn@+{|EXr9<4EMW?3aREx`!AhuMscv+8?K0%5r9<-cc{L#ln!csF3&0ZiJPx zMH+F}hm+s+HTwU6{JyLz<9#mk*&})xD<^n$O@5DDoWxQ%AO3(V!g&yuo4<kjJCa%d9<+b%gslX?3c(cH(M;M@~57}U=`ai)9z67F5u=|z|FzC zaFk1{SurqSoe$25n*gI&&+)dN;wx%<3#S6JiaV*Pi30y>y|Up|m_`luT(EDH5_rCp zdxouIgi=e@q*3|UDYafWMdh}Q*UBjPK=7z`;5`%oqIwH-$APCPL#^K3ILsdD7{BP@DyvR_YmmyC`wsgeGzEw1`!3h8pLW?~iqWVicz1C0cyP0KxL)5IQe2qh*rc>}**w9eRR8{S@xIe3d(#FZ@=E3@Q;7ah+Qvu0(oWwjNeV=pB+_p^SxnFG=O* zKZh@He5rPPh_z}JSJL|qT6lg;-K(HuHx6pw)Ldy$-{xOm(mt)F7To5!HTUr~uvN~7 zWRxRNMcftm&mI3b*Z#35Ga!X7D-+T``xSV(X}aQDjs`Bt#61g6h5o1X3v15q02S;3 z`v8G*^KoPVL9dqN=4ZLAtf0yjG+P#4nMYj;|B?DWQKO^eUmZ z35^nB@+Yvkr#o)MJ(_ry&?Z9PCiDoQlY|n4{+`e=LQfF-I-$QN#JfDvMd%GeDMFKk z;)E7rX-qsu=ypPFgzh7BKcUA6-9soxXd|H~2=Ot}@f||T2%RT%9ig`fEg*E6kRZgz z&BP__Vmj_1bdeB36BBO{;=At?7YMB*^a>%q9X>Ha=zc<{2<;*?Kxhx4ZxHGv^faNv zguV#q-cUH3O=m;VSj^1j@Tpv=)9g%VyF+GICY{ZPRvj+fxJvgbdoKs##6RAJ+Qxkkx(HL8g&qf;aW-gzTAEu}eOC-2n@yxDh zXC`Sj>iA=V888%P46B5Oc;)mq5w_^PxAvT1xm>XeEU z+m7h$Xqe4Z1)KYq@ZR|Rkg{^)1G&w!r+KLdUS{0#UR@H60Nz|Vl60Y3wN2K)?s z^fK@o-aO!&06){Ct;b*K@dG_xg>&VUtJmWaJ+9Q_7(PBF|4lvqLXYq1aY~PKw7!q) z@diDH^te`!oAh|E9wT~uM30}><32rR^mtg0NA>um9#81;89jbikI(CISdTC1@uPRA z{fPVw_!;ms;AgQP6`OzlskOqYT^9uB6{W=DnGl{d2~ zBbqaK!iTKPOqMz|LS~nTS?g_Yz+qFFfv?-jaF18W>VQnl?O^{*ramM?dnaacbp$6X z9DTlpM_M@LTV96zdN~*avoVZZ;;_v0;0$i%CJcL7`*9wIrbfLC?c11_&a*e1aA5{R zTOao@^4%GClI+>o+Sp{3Cr>fCZvK>)rKj}Haqd$tpU%1s9rtkbg#HSdhp?&^|aF&Ytp4PbY`y$_SaGWqC|2Z^_^2PuZXFd4q z9^Cfe?|JY`9{j&N_&gYM+q>F>U+ck_C>*`InmqW!9^CZc2R(SngFoZJd9qynDSIz@ z@Np0RTMxbfnRL(RS#3Ao;K9Ql{Bs`sfCv9e5B{VFKk31F^4x9z2Oj+A9{g7xybkNZ zJ^y+SzFOg!r7o16;A%m+3Y4TknF${F<+`~MjlZ?P-|FD;KD@Oq&jNA{Ekols971Tf zqAf>TfwmHD720iRtI@cAxyII_-GRpAvFp(q&>GR2&^DlLM8gsjpG5n=6vxOZ>kp*ouy54q}-dmE#KG)3-TW>D0|rIxIAEHyN_ zRjHxOuqZbtH6n6PZBWX#yS;$km&*=||&(vZ8OJ-6z$5$z$X1Y_k2@}+6w1_Zh4kPNNBRDi}%j?n8-AIjBy zKJUHRogLc}{}#>2?|pxN-}imryz!fvxAUVv{qC)I2+^=u2(bv|-6$6?6QUr(z=U`| zih*L9?K|#>+#UJUC&{fp8tTb;Df*d&qG|4n+_kS>McRk!dAfOlP^yI*rfFM8?3%9M z-_$B}2I8ldDIL;FYU(8Vy`*X8?EHaTmF4$0^a17XlGbo(*I=3Uw^TEfKeO9PWUMTB zet&}>RQ^uNP76Vrd9NOG;)~_%Y&>;PEBO6w{jl=aqn(iU9(BGUFwK1Ga6Hv%##3Es zN!O3Z$<@jq$D9XgzYir*HOKWhifOj(*tf&H{gZd@RihhLe#AdK^L%4r8mMBL z2h*NmUC^H%RzZKXcMstg%Olw2iwm?obewKnZl6sv5jAr?$ph(xnX$7A z`fJzYDd5i=7v`3@Q8z(gnw?QQT4VU*Yu~KmbNfl!>#t_1u-g3Gwe!wTMA~+`bF0xN9u8X@{+Dq4kL+sgp226T^bs}L1Tq>(luhQMTgC~uDlu?6s#J28%s zzmq%^9&Q`-cR7kT50rb4iXp^)FGJ%i0K+KnLTS$DvdxM3f#%MhL?>t-m_9O&7k@kY z)ZRBYpZxdU$zSZf*zwR!;D=FUA4AK<5)|SxmrFM+;<=)S9GDR6(0}%4>MBWAE4G_K zq0BueC~V%Jv$DD7?w-TZRCAkk$V#L$Nh@VHey<15QJz!21HpFv=}q+{BFtr;Pi7 zY2JTKUti0#>(CR^&3)jC}C9WV@+D%L)-u2rlzFPEv< zL6*+tZxyQvES1ZyCO4a16`jv8^LaM%W`l7q;=mI#=P;MXZ4IG;onZVC!q6aG38+*6gfwa~W@hjbg-^esUJ9fivMb{f5^)l8XeCTb@@of51&K8gz=0Gfo=P z(CCb_>i?zJqe|mPRgG~+#!x)x{0lUu3$E99D6doSnpZaetZb%=k>{Mx>PSAQylz(- zJyne{=Vq<3lU|!$uTN8>7@36E>y=GJ*-REAC!Lq2^qlj;C7JkkCSIIHXFr6LWKkwi z<~bi$y7S8@G3yxEJNdO4TBh=Bb*vcuJZ}i7iNfOKEyo~ms`HTbGLj;fz1~(uyhP%H)#y?O^Q$f zPfe-UrL1m;5UumHn_dch^LX(r8kjuACo0bSX$q=XNYE3XB5i)L_`}UFA&v_aIB(*q zjZw;9Fv@-7#X>i=E=gA3gk+a?PoAQ4XM)^;8B7cvz^^by2>UenZU6;kIq7_rNV(-@ zs1ysGs{8+_gi}U2kCr;v(ya`y7#Ty)#%et~r5wjSjyFhuedEsE%JH*G<>R2xpY!O+ z6rvq7iVxofzecG{P%P|YBj2S-F*1TiMrw@|m4_t|y3wCQ$`JH}O7a_0rM@wQJ6tTZ z)06Jr2v`-TgKkT^E5>cRheJnC_rE^d|7t^M^t2J1Fb4h)S3*49rMvxbhwt=YQll+z-ji%TeftMloQ!PoSIR{h|2qE{4?2 zC^7vWR~l`l0@*u0b|G|he9P=w1ca-|`MQA4@XRaUa$15bwlSb01Nt#qRROVya?21T z7~fZAFl=}~8~)E?!C=GFWTWBlaJH3O;!643%td=!9Zq z-Tw?j)9;c0Ec(WrW?Gc`Mw}JWw6EfPhhEEl!_F~@wCqvc;J;=lP8ACq*wW?7&T(Yq z<(3wu#b=xPLR5-eGVVV!1;#zkS7sZtSRl+c+Oj?*>m#!6mG$RkeV?rRW&K5256b#W zvL2H4S7iNwtRIwhMb;0=`lzgr$@;jg|4G(gm-VBv9+vgvvVKC=Ps;j)tiK`aXJq|N zS&zv2Sy`Wy^{A}JWPM83&&m3GvL2W9X<45^y{r7;7XWtboo!6wVpHkvL{6rEjVyNe z6MKc&Q^Z~(_8-Lff1-Pm*!PINLF^>4mB{<_H;COtY?#J5zBx9!g;y%7 z|1qJO%QfZVy;iuTC9G)E?#Wn+DVQS@uZ^v2%KRK&ey(#(_%80V@q5 zdl<{b-tN3Dli8U*oRX<*OQ$TH3OFz~1>X0_!wWIT1mAb_ZiI#Js(BE{e8Ib+2E6m3 zwLGeb%LrhQfgl4x27(L(83-~EWFW{ukbxirK?Z^h1Q`f2@Yk7v*YN;>4+1V}xK!^a zU#Z~-G+e7;lZHpJ@s@UvYIs7!XEl6I!?PM*(D0`k{!+vL)^J9{MLLdmY4~0Z!y4Y8 z;T8?IYiMZrDGmQl!!8Xo8un^9sNsVe9@p@34WH3)RKsx%&ujQ!8vaZ}N5j9)vn1$M zkbxirK?Z^h1Q`f25M&_8K#+kT13?CY47}Ylu?pFS&R{j{?#4eLg{CIs& zR#Zd|64NxJIsDw!HnVn$yk+2Z#S-b9MQSCfbjFgRt4U<7XeT9M5;@EI9Eo)#Y%7r< zu?a*5KWn$UNNru!YRa7!2YPJFJY>bpPW)ijmfluqoXI^vG(O@JaWe|} z{S7{W+uD#{P~TL=Czid??MYm1Q9=vH7tmB2k?M7a7tmF^l`IajFcrF5z)txuGV zjXbn==94G$=sosa**#RbSXEIwr()idb7rnk?@gj<|04IasG91tcc?1y3`!!NjN3Bo zN=+>HfqACGalgpZ-mqV$TRTzZ=j?RW8~=z;q7BBX?Am#N8O}kpcV&iFK%kZ$ve9qYPu}x{mh#Mg0wx#jTR& zKGc=?xCsANVBf#{9S4RHYEWMq;PcY=N?LtqfHWQ(LJr$2)$`OQO}FAhER=84wEJC? zJ2lNcs+9BhDYUO>{kTiNN6C9YLoBlaRD9V-f7M5GPp?=15g+}8kAB)me@oE}O&%|z z22rJd&?pPQq-^ld)+Gd?=uqq)sh{mF1d#Ydm;(ckyc7k%_q$fRN^e;@PF zdwldkAAO&XKIWsJ@zLB&>uv89A3fuvS74)`SHICmZ}rjbKDyIK_xR|q_~=J`^uPJ& z7ku<9KKl2HMlaNHIRG~~z7vJt!rW$HUMI-8h1V708WjG}A&hb@${LjGP}ZU}qFj&i5tMZ(>ruEK;w;~QvJr)IlG}ne zq2O~Yg5MUo8RhK~YZzahnR~r7<#kf6!t~}?c`4K!eYMn-=Q^r6@`9;x_ljCi=FqHn z;pi?I^v;VCq#3?t-yE(=hJORFXZ__` z)GhMrnDYNt9jDHzG+e+T6_Gr-a+J7Q$$6c*D)lQ9>`0$a$+JvY*i-GF^#VG2wKk^# zPeY@ShxO5+ JC~m66p8*uMvd91c literal 0 HcmV?d00001 diff --git a/lib/c-api/tests/wasm_c_api/wasm-c-api-serialize b/lib/c-api/tests/wasm_c_api/wasm-c-api-serialize new file mode 100755 index 0000000000000000000000000000000000000000..f9c5bb1e7939ac5f34c65766f04b304872ed26aa GIT binary patch literal 18680 zcmeHPZH!da89pnB2+Hy$rGAe1MJ?{^QfyZ1(m{6gk|JV(f}7II-I)tBb#`W)xdXc< z+pI3ra66s2wx;2SKd5P1QcZ)2T4RbKf$HK9OHI?z)|!o}_HIKBp-oHrA$^{6&YijU zE;i|}Cgz@S&iirR_j%8G&;3~LJ#&BYk3WBOnGhYbgbjrB!KRnvOl}v~8n!yFP`< zpu0I+*-+N3Qp^@(iczg;R-M{lwWW&UeRz$+`-!&jW#3`0#+#!R3eU{hg|c0NE{gZe zwF+;woU{;>nfF$iF}_UIspN}$v_TZ_t?Lxt?=>FfUh$?QlW3z-F{r{FkVf8m=QO9sAJ+5htWoqOvK zkFAC-fhybMr9x8;+N#Ms$Hojb0hn# zVzS@fYZpr8A-m`#w_DXAyOP|eh+|du*iN!y7i_C)C$o0B${DC$Gh3YuAM|k< zuNT#i*OBc&>N?tUhwYY;s$&mz-5d18Wn>I<2;`}hu?opj*+~`(dxscQhPV|i=bgg3 zah*S-Wv*jf;ta$Yh%*ppAkILXfj9$k2I36F8Hh6wXCTf%oPjt4aR&bP3~V#p_l@y0 z3Bw&dZ@9IyMze1_o>d+Z-qUz24QT+9n?3`@I21i6-8bE|XSk<~@e_%i$0wx!<7cK2 z*=St436E@yhA`ap`8U#MI2v~p#9yc{ zj=8TRz~rlZKIXkZS4eJsE0GS<;H3Lj&)dK|#t!dEX;C|7G)IrP_06<;S~Orr)DrG2OOJI!9J13dGlrni hhgKoW_kbNr3VQ&SQX5Ssk@LNR!Ivrf{jm3g{}J;?@Pl4W1z)U8EJ$ws9zxA#hnqftxt~JT4j9d=p87ZR zk172a^as4E^8OQ+8S8cvrN-!(Tkj>pT8KR-jpnwqz&WdNCcNzupgs%}WBe#dd!%nD zpxKf^gq_E|yFfbU@9w-|KNule z*O%t#S?}ji;INtUex?{)ZE8~mB z=C+VqP3}>0T-aQL-1X$1CAX9u1}diKk>jKPX+iE*a)0{>+~>%hA(tZe9=Qj|ohCOx z?k#ZZtwI6s3KN4?=8>+hu6bf@!mta4Qeu0lQpnyoPi!dWoxD}ZKL#slu(4!irANMK zRYs%=FE*r!-Nn}wq5_a~rBbRS3fgw4l&uwPpsgQ%W25=Ty)-L)d3m5NMKuI8wrm-ZE9*#1({##+kv zS9s4OOOWCi5`53S29%ZWs9DJ4yumx64!rZh@v2IT@f9(RGZ1GW&On@jI0JD8;ta$Y zh%*ppAkILXfj9$k20qytIH32Be@D}2H2tBbM>Ks^(-WFLj|UKZknpmm$25IY(_d-& zuBM)*=QRD7rgJpjLQSvM^kz-FH0{;&UQIV@`V~!gY5H|d9ZkQX=_h*?qzv}jJ~414?l3v`@39h z8Ord@?Bbq$(GCD?j`YBtF?Y1o!;W1knpV~11`T%Yigbksl=FLOPB(n30049>hq}1$ zgWBPcwmq}4j!=gl*MX4M87T+nGBLALyB%!xsNF7^pxdFDoqAIX$9H&UuLeER>QS3! z0$F`!W|zOgM=sm3XupP>jOs&Pr&_&Lr&I|};dG=&!%el+d#!>@78eVhrae@4Mld~= z4impkpJfi^uvT`ahGQ&;BNT^u55D10D4G7=B5~)Cl`o3Bx!GoxnCe1vC@H|C4)J%? z1JEzP1F>WJdlB61wE!Ld@A>K0*}-34tLJ9Rq^$Ps@HrZ{dUb-~@6Rc(LItIpENjsQ z<%c5j!x4E`MCSJ+g8s#bT#Lw~O6E{x`7T-rE&0WWJQgCP*x)Pp ztq2}Vm!o34m;9CjzXxz7D!+rk?Vvn@7NPPxElW_BqF#l{<;zt_S7!7ZRv9qOL&2es6IT>i;8l0$;wEdCu{>DZz8jl;>RN&Lr Date: Thu, 1 Oct 2020 14:22:30 +0200 Subject: [PATCH 104/281] doc(c-api) Restore the `README.md`. --- lib/c-api/README.md | 120 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 120 insertions(+) diff --git a/lib/c-api/README.md b/lib/c-api/README.md index ceb9ef9eb..b35970987 100644 --- a/lib/c-api/README.md +++ b/lib/c-api/README.md @@ -1,2 +1,122 @@ # `wasmer-c-api` [![Build Status](https://github.com/wasmerio/wasmer/workflows/build/badge.svg?style=flat-square)](https://github.com/wasmerio/wasmer/actions?query=workflow%3Abuild) [![Join Wasmer Slack](https://img.shields.io/static/v1?label=Slack&message=join%20chat&color=brighgreen&style=flat-square)](https://slack.wasmer.io) [![MIT License](https://img.shields.io/github/license/wasmerio/wasmer.svg?style=flat-square)](https://github.com/wasmerio/wasmer/blob/master/LICENSE) +This crate exposes a C and a C++ API for the Wasmer runtime. It also fully supports the [wasm-c-api common API](https://github.com/WebAssembly/wasm-c-api). + +## Usage + +Once you [install Wasmer in your system](https://github.com/wasmerio/wasmer-install), the *shared object files* and the *headers* will be automatically available **inside the Wasmer installed path**. + +The C ([`wasmer.h`][wasmer_h]) and C++ ([`wasmer.hh`][wasmer_hh]) header +files can be found in the Wasmer `include` directory: + +```bash +wasmer config --includedir +``` + +The runtime shared libraries (`.so`, `.dylib`, `.dll`) can be found in the Wasmer +`lib` directory: + +```bash +wasmer config --libdir +``` + +> Note: You can also download the libraries or header files directly +from [Wasmer release page]. + +The full C API documentation can be found here: +https://wasmerio.github.io/wasmer/c-api/ + +Here is a simple example to use the C API: + +```c +#include +#include "../wasmer.h" +#include +#include +int main() +{ + // Read the Wasm file bytes. + FILE *file = fopen("sum.wasm", "r"); + fseek(file, 0, SEEK_END); + long len = ftell(file); + uint8_t *bytes = malloc(len); + fseek(file, 0, SEEK_SET); + fread(bytes, 1, len, file); + fclose(file); + // Prepare the imports. + wasmer_import_t imports[] = {}; + // Instantiate! + wasmer_instance_t *instance = NULL; + wasmer_result_t instantiation_result = wasmer_instantiate(&instance, bytes, len, imports, 0); + assert(instantiation_result == WASMER_OK); + // Let's call a function. + // Start by preparing the arguments. + // Value of argument #1 is `7i32`. + wasmer_value_t argument_one; + argument_one.tag = WASM_I32; + argument_one.value.I32 = 7; + // Value of argument #2 is `8i32`. + wasmer_value_t argument_two; + argument_two.tag = WASM_I32; + argument_two.value.I32 = 8; + // Prepare the arguments. + wasmer_value_t arguments[] = {argument_one, argument_two}; + // Prepare the return value. + wasmer_value_t result_one; + wasmer_value_t results[] = {result_one}; + // Call the `sum` function with the prepared arguments and the return value. + wasmer_result_t call_result = wasmer_instance_call(instance, "sum", arguments, 2, results, 1); + // Let's display the result. + printf("Call result: %d\n", call_result); + printf("Result: %d\n", results[0].value.I32); + // `sum(7, 8) == 15`. + assert(results[0].value.I32 == 15); + assert(call_result == WASMER_OK); + wasmer_instance_destroy(instance); + return 0; +} +``` + +# Testing + +Tests are run using the release build of the library. If you make +changes or compile with non-default features, please ensure you +rebuild in release mode for the tests to see the changes. + +The tests can be run via `cargo test`, such as: + +```sh +$ cargo test --release -- --nocapture +``` + +To run tests manually, enter the `lib/c-api/tests` directory +and run the following commands: + +```sh +$ cmake . +$ make +$ make test +``` + +## pkg-config + +The Wasmer binary ships with an utility tool that outputs config +in the `pkg-config` format. + +You can use it like: + +```bash +wasmer config --pkg-config > $PKG_CONFIG_PATH/wasmer.pc +``` + +# License + +Wasmer is primarily distributed under the terms of the [MIT +license][mit-license] ([LICENSE][license]). + + +[wasmer_h]: ./wasmer.h +[wasmer_hh]: ./wasmer.hh +[mit-license]: http://opensource.org/licenses/MIT +[license]: https://github.com/wasmerio/wasmer/blob/master/LICENSE +[Wasmer release page]: https://github.com/wasmerio/wasmer/releases From 9c208a1529f855db26aab02d536117162c6f12a7 Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Thu, 1 Oct 2020 11:47:22 -0700 Subject: [PATCH 105/281] Ignore mapdir_with_leading_slash on Windows for now These tests are failing because we call `take(N)` on chars of a string read from a file. It seems that on Windows, the programs get line endings with `\r\n`, this is a problem for the way our tests assert correct output. We'll need to find a general solution to this problem later. --- tests/ignores.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/ignores.txt b/tests/ignores.txt index 85b22ac4c..38be894e1 100644 --- a/tests/ignores.txt +++ b/tests/ignores.txt @@ -61,12 +61,14 @@ wasitests::snapshot1::file_metadata on windows wasitests::snapshot1::fseek on windows wasitests::snapshot1::path_link on windows wasitests::snapshot1::path_symlink on windows +wasitests::snapshot1::mapdir_with_leading_slash on windows wasitests::unstable::fd_pread on windows wasitests::unstable::fd_read on windows wasitests::unstable::file_metadata on windows wasitests::unstable::fseek on windows wasitests::unstable::path_link on windows wasitests::unstable::path_symlink on windows +wasitests::unstable::mapdir_with_leading_slash on windows # This test is meant to only run on Unix wasitests::unstable::unix_open_special_files on windows From 9a3c5cf389d0a29355795fcd2eca17250aebfbad Mon Sep 17 00:00:00 2001 From: Nick Lewycky Date: Tue, 29 Sep 2020 11:04:54 -0700 Subject: [PATCH 106/281] Remove `extern "C"` from a non-pub function that returns non-FFI'able type. Add `extern "C"` to two `#[no_mangle] pub` functions. --- lib/c-api/src/wasm_c_api/wasi/mod.rs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/lib/c-api/src/wasm_c_api/wasi/mod.rs b/lib/c-api/src/wasm_c_api/wasi/mod.rs index 0dbc33a3a..550d2ff04 100644 --- a/lib/c-api/src/wasm_c_api/wasi/mod.rs +++ b/lib/c-api/src/wasm_c_api/wasi/mod.rs @@ -250,7 +250,7 @@ pub unsafe extern "C" fn wasi_get_imports( } /// Takes ownership of `wasi_env_t`. -unsafe extern "C" fn wasi_get_imports_inner( +unsafe fn wasi_get_imports_inner( store: Option>, module: &wasm_module_t, wasi_env: &wasi_env_t, @@ -288,7 +288,9 @@ unsafe extern "C" fn wasi_get_imports_inner( } #[no_mangle] -pub unsafe fn wasi_get_start_function(instance: &mut wasm_instance_t) -> Option> { +pub unsafe extern "C" fn wasi_get_start_function( + instance: &mut wasm_instance_t, +) -> Option> { let f = c_try!(instance.inner.exports.get_function("_start")); Some(Box::new(wasm_func_t { inner: f.clone(), @@ -298,4 +300,4 @@ pub unsafe fn wasi_get_start_function(instance: &mut wasm_instance_t) -> Option< /// Delete a `wasm_extern_t` allocated by the API. #[no_mangle] -pub unsafe fn wasm_extern_delete(_item: Option>) {} +pub unsafe extern "C" fn wasm_extern_delete(_item: Option>) {} From 762a6acc85e8cd4dbb1483578446a8fab1ae1027 Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Thu, 24 Sep 2020 12:00:58 -0700 Subject: [PATCH 107/281] Add `rlib` as a crate-type for wasmer-c-api This is how `wasmer-runtime-c-api` was before and seems to fix a use case that users relied on --- lib/c-api/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/c-api/Cargo.toml b/lib/c-api/Cargo.toml index 64c2b4e16..58cd9dd81 100644 --- a/lib/c-api/Cargo.toml +++ b/lib/c-api/Cargo.toml @@ -12,7 +12,7 @@ readme = "README.md" edition = "2018" [lib] -crate-type = ["cdylib", "staticlib"] +crate-type = ["cdylib", "rlib", "staticlib"] [dependencies] wasmer = { version = "1.0.0-alpha3", path = "../api", default-features = false } From b309c5f4d7e8ec001b611e08e0e17fb7eb254347 Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Mon, 28 Sep 2020 15:14:47 -0700 Subject: [PATCH 108/281] Add early exit example --- Cargo.toml | 5 ++ examples/early_exit.rs | 82 ++++++++++++++++++++++++++++ examples/engine_cross_compilation.rs | 5 +- examples/wasi.rs | 6 +- 4 files changed, 92 insertions(+), 6 deletions(-) create mode 100644 examples/early_exit.rs diff --git a/Cargo.toml b/Cargo.toml index fb84f986c..f034431fa 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -128,6 +128,11 @@ test-no-traps = ["wasmer-wast/test-no-traps"] name = "static_and_dynamic_functions" harness = false +[[example]] +name = "early-exit" +path = "examples/early_exit.rs" +required-features = ["cranelift"] + [[example]] name = "engine-jit" path = "examples/engine_jit.rs" diff --git a/examples/early_exit.rs b/examples/early_exit.rs new file mode 100644 index 000000000..7253fd519 --- /dev/null +++ b/examples/early_exit.rs @@ -0,0 +1,82 @@ +//! This example shows how the host can terminate execution of Wasm early from +//! inside a host function called by the Wasm. + +use anyhow::bail; +use std::fmt; +use wasmer::{imports, wat2wasm, Function, Instance, Module, NativeFunc, RuntimeError, Store}; +use wasmer_compiler_cranelift::Cranelift; +use wasmer_engine_jit::JIT; + +// First we need to create an error type that we'll use to signal the end of execution. +#[derive(Debug, Clone, Copy)] +struct ExitCode(u32); + +// This type must implement `std::error::Error` so we must also implement `std::fmt::Display` for it. +impl fmt::Display for ExitCode { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}", self.0) + } +} + +// And then we implement `std::error::Error`. +impl std::error::Error for ExitCode {} + +// The host function that we'll use to terminate execution. +fn early_exit() { + // This is where it happens. + RuntimeError::raise(Box::new(ExitCode(1))); +} + +fn main() -> anyhow::Result<()> { + // Let's declare the Wasm module with the text representation. + let wasm_bytes = wat2wasm( + br#" +(module + (type $run_t (func (param i32 i32) (result i32))) + (type $early_exit_t (func (param) (result))) + (import "env" "early_exit" (func $early_exit (type $early_exit_t))) + (func $run (type $run_t) (param $x i32) (param $y i32) (result i32) + (call $early_exit) + (i32.add + local.get $x + local.get $y)) + (export "run" (func $run))) +"#, + )?; + + let store = Store::new(&JIT::new(&Cranelift::default()).engine()); + let module = Module::new(&store, wasm_bytes)?; + + let import_object = imports! { + "env" => { + "early_exit" => Function::new_native(&store, early_exit), + } + }; + let instance = Instance::new(&module, &import_object)?; + + // get the `run` function which we'll use as our entrypoint. + let run_func: NativeFunc<(i32, i32), i32> = + instance.exports.get_native_function("run").unwrap(); + + // When we call a function it can either succeed or fail. + match run_func.call(1, 7) { + Ok(result) => { + bail!( + "Expected early termination with `ExitCode`, found: {}", + result + ); + } + // we're expecting it to fail. + // we attempt to downcast the error into the error type that we were expecting. + Err(e) => match e.downcast::() { + // we found the exit code used to terminate execution. + Ok(exit_code) => { + println!("Exited early with exit code: {}", exit_code); + Ok(()) + } + Err(e) => { + bail!("Unknown error `{}` found. expected `ErrorCode`", e); + } + }, + } +} diff --git a/examples/engine_cross_compilation.rs b/examples/engine_cross_compilation.rs index 1c9795138..272da2cfc 100644 --- a/examples/engine_cross_compilation.rs +++ b/examples/engine_cross_compilation.rs @@ -27,7 +27,7 @@ use wasmer_engine_native::Native; fn main() -> Result<(), Box> { // Let's declare the Wasm module with the text representation. let wasm_bytes = wat2wasm( - r#" + br#" (module (type $sum_t (func (param i32 i32) (result i32))) (func $sum_f (type $sum_t) (param $x i32) (param $y i32) (result i32) @@ -35,8 +35,7 @@ fn main() -> Result<(), Box> { local.get $y i32.add) (export "sum" (func $sum_f))) -"# - .as_bytes(), +"#, )?; // Define a compiler configuration. diff --git a/examples/wasi.rs b/examples/wasi.rs index 72617e835..c9c779b74 100644 --- a/examples/wasi.rs +++ b/examples/wasi.rs @@ -21,9 +21,9 @@ use wasmer_engine_jit::JIT; use wasmer_wasi::WasiState; fn main() -> Result<(), Box> { - let wasm_path = format!( - "{}/tests/wasi-wast/wasi/unstable/hello.wasm", - std::env::var("CARGO_MANIFEST_DIR").unwrap() + let wasm_path = concat!( + env!("CARGO_MANIFEST_DIR"), + "/tests/wasi-wast/wasi/unstable/hello.wasm" ); // Let's declare the Wasm module with the text representation. let wasm_bytes = std::fs::read(wasm_path)?; From bcb88120f7d5563999289ee5ae4d1b8d0c394022 Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Tue, 29 Sep 2020 15:43:56 -0700 Subject: [PATCH 109/281] Add examples to tarpaulin coverage --- .tarpaulin.toml | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/.tarpaulin.toml b/.tarpaulin.toml index 9f7dae3de..78b59bfb0 100644 --- a/.tarpaulin.toml +++ b/.tarpaulin.toml @@ -1,17 +1,16 @@ [cranelift_coverage] features = "cranelift,singlepass,llvm,test-no-traps,test-cranelift" +examples = ["early-exit", "engine-jit", "engine-native", "engine-headless", "cross-compilation", "compiler-cranelift", "exported-function", "wasi"] release = true [llvm_coverage] features = "cranelift,singlepass,llvm,test-no-traps,test-llvm" +examples = ["compiler-llvm"] release = true [singlepass_coverage] features = "cranelift,singlepass,llvm,test-no-traps,test-singlepass" -release = true - -[feature_a_and_b_coverage] -features = "feature_a feature_b" +examples = ["compiler-singlepass"] release = true [report] From ecb79e2af0ae6cfbfbec6134d99fe9f54d5dfde2 Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Thu, 1 Oct 2020 21:16:29 +0200 Subject: [PATCH 110/281] fix(c-api) Cherry-pick manually from https://github.com/wasmerio/wasmer/pull/1657. --- .../src/wasm_c_api/externals/function.rs | 11 ++- lib/c-api/src/wasm_c_api/macros.rs | 31 ++++++++ lib/c-api/src/wasm_c_api/trap.rs | 78 ++++++++++--------- lib/c-api/src/wasm_c_api/types/frame.rs | 51 ++++++++++++ lib/c-api/src/wasm_c_api/types/mod.rs | 12 +-- 5 files changed, 138 insertions(+), 45 deletions(-) create mode 100644 lib/c-api/src/wasm_c_api/types/frame.rs diff --git a/lib/c-api/src/wasm_c_api/externals/function.rs b/lib/c-api/src/wasm_c_api/externals/function.rs index 22366809f..86e7a84b2 100644 --- a/lib/c-api/src/wasm_c_api/externals/function.rs +++ b/lib/c-api/src/wasm_c_api/externals/function.rs @@ -60,8 +60,11 @@ pub unsafe extern "C" fn wasm_func_new( num_rets ]; - let _traps = callback(processed_args.as_ptr(), results.as_mut_ptr()); - // TODO: do something with `traps` + let trap = callback(processed_args.as_ptr(), results.as_mut_ptr()); + if !trap.is_null() { + let trap: Box = Box::from_raw(trap); + RuntimeError::raise(Box::new(trap.inner)); + } let processed_results = results .into_iter() @@ -134,7 +137,7 @@ pub unsafe extern "C" fn wasm_func_call( func: &wasm_func_t, args: *const wasm_val_t, results: *mut wasm_val_t, -) -> Option> { +) -> Option> { let num_params = func.inner.ty().params().len(); let params: Vec = (0..num_params) .map(|i| (&(*args.add(i))).try_into()) @@ -149,7 +152,7 @@ pub unsafe extern "C" fn wasm_func_call( } None } - Err(e) => Some(NonNull::new_unchecked(Box::into_raw(Box::new(e)) as _)), + Err(e) => Some(Box::new(e.into())), } } diff --git a/lib/c-api/src/wasm_c_api/macros.rs b/lib/c-api/src/wasm_c_api/macros.rs index 9a022ce38..36dbf47f6 100644 --- a/lib/c-api/src/wasm_c_api/macros.rs +++ b/lib/c-api/src/wasm_c_api/macros.rs @@ -36,6 +36,37 @@ macro_rules! wasm_declare_vec { pub data: *mut [], } + impl<'a> From]>> for [] { + fn from(other: Vec<[]>) -> Self { + let mut boxed_slice = other.into_boxed_slice(); + let size = boxed_slice.len(); + let data = boxed_slice.as_mut_ptr(); + ::std::mem::forget(boxed_slice); + Self { + size, + data, + } + } + } + + impl<'a, T: Into<[]> + Clone> From<&'a [T]> for [] { + fn from(other: &'a [T]) -> Self { + let size = other.len(); + let mut copied_data = other + .iter() + .cloned() + .map(Into::into) + .collect::]>>() + .into_boxed_slice(); + let data = copied_data.as_mut_ptr(); + ::std::mem::forget(copied_data); + Self { + size, + data, + } + } + } + impl [] { pub unsafe fn into_slice(&self) -> Option<&[[]]>{ if self.data.is_null() { diff --git a/lib/c-api/src/wasm_c_api/trap.rs b/lib/c-api/src/wasm_c_api/trap.rs index 104cabe97..6bb4758be 100644 --- a/lib/c-api/src/wasm_c_api/trap.rs +++ b/lib/c-api/src/wasm_c_api/trap.rs @@ -1,51 +1,59 @@ -use super::types::wasm_byte_vec_t; -use std::mem; -use std::ptr::NonNull; +use super::store::wasm_store_t; +use super::types::{wasm_byte_vec_t, wasm_frame_t, wasm_frame_vec_t, wasm_message_t}; use wasmer::RuntimeError; // opaque type which is a `RuntimeError` /// cbindgen:ignore #[allow(non_camel_case_types)] -pub struct wasm_trap_t {} +pub struct wasm_trap_t { + pub(crate) inner: RuntimeError, +} -/// cbindgen:ignore -#[no_mangle] -pub unsafe extern "C" fn wasm_trap_delete(trap: Option>) { - if let Some(t_inner) = trap { - let _ = Box::from_raw(t_inner.cast::().as_ptr()); +impl From for wasm_trap_t { + fn from(other: RuntimeError) -> Self { + Self { inner: other } } } /// cbindgen:ignore #[no_mangle] -pub unsafe extern "C" fn wasm_trap_message( - trap: *const wasm_trap_t, - out_ptr: *mut wasm_byte_vec_t, -) { - let re = &*(trap as *const RuntimeError); - // this code assumes no nul bytes appear in the message - let mut message = format!("{}\0", re); - message.shrink_to_fit(); +pub unsafe extern "C" fn wasm_trap_new( + _store: &mut wasm_store_t, + message: &wasm_message_t, +) -> Option> { + let message_bytes: &[u8] = message.into_slice()?; + let message_str = c_try!(std::str::from_utf8(message_bytes)); + let runtime_error = RuntimeError::new(message_str); + let trap = runtime_error.into(); - // TODO use `String::into_raw_parts` when it gets stabilized - (*out_ptr).size = message.as_bytes().len(); - (*out_ptr).data = message.as_mut_ptr(); - mem::forget(message); + Some(Box::new(trap)) } -// in trap/RuntimeError we need to store -// 1. message -// 2. origin (frame); frame contains: -// 1. func index -// 2. func offset -// 3. module offset -// 4. which instance this was apart of +/// cbindgen:ignore +#[no_mangle] +pub unsafe extern "C" fn wasm_trap_delete(_trap: Option>) {} -/*#[no_mangle] -pub unsafe extern "C" fn wasm_trap_trace(trap: *const wasm_trap_t, out_ptr: *mut wasm_frame_vec_t) { - let re = &*(trap as *const RuntimeError); - todo!() -}*/ +/// cbindgen:ignore +#[no_mangle] +pub unsafe extern "C" fn wasm_trap_message(trap: &wasm_trap_t, out_ptr: &mut wasm_byte_vec_t) { + let message = trap.inner.message(); + let byte_vec: wasm_byte_vec_t = message.into_bytes().into(); + out_ptr.size = byte_vec.size; + out_ptr.data = byte_vec.data; +} -//wasm_declare_ref!(trap); -//wasm_declare_ref!(foreign); +/// cbindgen:ignore +#[no_mangle] +pub unsafe extern "C" fn wasm_trap_origin(trap: &wasm_trap_t) -> Option> { + trap.inner.trace().first().map(Into::into).map(Box::new) +} + +/// cbindgen:ignore +#[no_mangle] +pub unsafe extern "C" fn wasm_trap_trace(trap: &wasm_trap_t, out_ptr: &mut wasm_frame_vec_t) { + let frames = trap.inner.trace(); + let frame_vec: wasm_frame_vec_t = frames.into(); + + out_ptr.size = frame_vec.size; + out_ptr.data = frame_vec.data; +} diff --git a/lib/c-api/src/wasm_c_api/types/frame.rs b/lib/c-api/src/wasm_c_api/types/frame.rs new file mode 100644 index 000000000..9fc841671 --- /dev/null +++ b/lib/c-api/src/wasm_c_api/types/frame.rs @@ -0,0 +1,51 @@ +use super::super::instance::wasm_instance_t; +use wasmer::FrameInfo; + +#[derive(Debug, Clone)] +#[repr(C)] +pub struct wasm_frame_t { + info: FrameInfo, +} + +impl<'a> From<&'a FrameInfo> for wasm_frame_t { + fn from(other: &'a FrameInfo) -> Self { + other.clone().into() + } +} + +impl From for wasm_frame_t { + fn from(other: FrameInfo) -> Self { + Self { info: other } + } +} + +#[no_mangle] +pub unsafe extern "C" fn wasm_frame_copy(frame: &wasm_frame_t) -> Box { + Box::new(frame.clone()) +} + +#[no_mangle] +pub unsafe extern "C" fn wasm_frame_delete(_frame: Option>) {} + +#[no_mangle] +pub unsafe extern "C" fn wasm_frame_instance(frame: &wasm_frame_t) -> *const wasm_instance_t { + //todo!("wasm_frame_instance") + std::ptr::null() +} + +#[no_mangle] +pub unsafe extern "C" fn wasm_frame_func_index(frame: &wasm_frame_t) -> u32 { + frame.info.func_index() +} + +#[no_mangle] +pub unsafe extern "C" fn wasm_frame_func_offset(frame: &wasm_frame_t) -> usize { + frame.info.func_offset() +} + +#[no_mangle] +pub unsafe extern "C" fn wasm_frame_module_offset(frame: &wasm_frame_t) -> usize { + frame.info.module_offset() +} + +wasm_declare_vec!(frame); diff --git a/lib/c-api/src/wasm_c_api/types/mod.rs b/lib/c-api/src/wasm_c_api/types/mod.rs index 65bd9e6d3..c2212a760 100644 --- a/lib/c-api/src/wasm_c_api/types/mod.rs +++ b/lib/c-api/src/wasm_c_api/types/mod.rs @@ -1,5 +1,6 @@ mod export; mod extern_; +mod frame; mod function; mod global; mod import; @@ -10,6 +11,7 @@ mod value; pub use export::*; pub use extern_::*; +pub use frame::*; pub use function::*; pub use global::*; pub use import::*; @@ -23,12 +25,6 @@ pub type wasm_byte_t = u8; wasm_declare_vec!(byte); -#[derive(Debug)] -#[repr(C)] -pub struct wasm_frame_t {} - -wasm_declare_vec!(frame); - /// cbindgen:ignore #[allow(non_camel_case_types)] pub type wasm_name_t = wasm_byte_vec_t; @@ -37,3 +33,7 @@ pub type wasm_name_t = wasm_byte_vec_t; /// cbindgen:ignore #[allow(non_camel_case_types)] pub struct wasm_ref_t; + +/// cbindgen:ignore +#[allow(non_camel_case_types)] +pub type wasm_message_t = wasm_byte_vec_t; From 90621088fbcd5ced845dbb866d994f1bda4ee976 Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Thu, 1 Oct 2020 21:16:58 +0200 Subject: [PATCH 111/281] fix(c-api) Cherry-pick manually from https://github.com/wasmerio/wasmer/pull/1657. --- CHANGELOG.md | 1 + examples/early_exit.rs | 8 ++++---- lib/api/src/lib.rs | 4 ++-- lib/engine/src/trap/frame_info.rs | 2 +- 4 files changed, 8 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ea7288f06..267fd762c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ # Changelog ## **[Unreleased]** +- [#1657](https://github.com/wasmerio/wasmer/pull/1657) Implement `wasm_trap_t` and `wasm_frame_t` for Wasm C API; add examples in Rust and C of exiting early with a host function. - [#1645](https://github.com/wasmerio/wasmer/pull/1645) Move the install script to https://github.com/wasmerio/wasmer-install ## 1.0.0-alpha3 - 2020-09-14 diff --git a/examples/early_exit.rs b/examples/early_exit.rs index 7253fd519..814ab01ff 100644 --- a/examples/early_exit.rs +++ b/examples/early_exit.rs @@ -54,7 +54,7 @@ fn main() -> anyhow::Result<()> { }; let instance = Instance::new(&module, &import_object)?; - // get the `run` function which we'll use as our entrypoint. + // Get the `run` function which we'll use as our entrypoint. let run_func: NativeFunc<(i32, i32), i32> = instance.exports.get_native_function("run").unwrap(); @@ -66,10 +66,10 @@ fn main() -> anyhow::Result<()> { result ); } - // we're expecting it to fail. - // we attempt to downcast the error into the error type that we were expecting. + // We're expecting it to fail. + // We attempt to downcast the error into the error type that we were expecting. Err(e) => match e.downcast::() { - // we found the exit code used to terminate execution. + // We found the exit code used to terminate execution. Ok(exit_code) => { println!("Exited early with exit code: {}", exit_code); Ok(()) diff --git a/lib/api/src/lib.rs b/lib/api/src/lib.rs index f5631870d..6725141ae 100644 --- a/lib/api/src/lib.rs +++ b/lib/api/src/lib.rs @@ -70,8 +70,8 @@ pub use wasmer_compiler::{ }; pub use wasmer_compiler::{CpuFeature, Features, Target}; pub use wasmer_engine::{ - ChainableNamedResolver, DeserializeError, Engine, InstantiationError, LinkError, NamedResolver, - NamedResolverChain, Resolver, RuntimeError, SerializeError, + ChainableNamedResolver, DeserializeError, Engine, FrameInfo, InstantiationError, LinkError, + NamedResolver, NamedResolverChain, Resolver, RuntimeError, SerializeError, }; pub use wasmer_types::{ Atomically, Bytes, GlobalInit, LocalFunctionIndex, MemoryView, Pages, ValueType, diff --git a/lib/engine/src/trap/frame_info.rs b/lib/engine/src/trap/frame_info.rs index 310dc5679..464131f19 100644 --- a/lib/engine/src/trap/frame_info.rs +++ b/lib/engine/src/trap/frame_info.rs @@ -282,7 +282,7 @@ pub fn register( /// each frame is described by this structure. /// /// [`Trap`]: crate::Trap -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct FrameInfo { module_name: String, func_index: u32, From a2854ebfea9ea00524f92d4081ab8fe7e172a278 Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Thu, 1 Oct 2020 21:20:13 +0200 Subject: [PATCH 112/281] fix(c-api) Adjust cbindgen metadata for header files. --- lib/c-api/build.rs | 1 + lib/c-api/src/wasm_c_api/types/frame.rs | 7 ++++++- lib/c-api/src/wasm_c_api/wasi/mod.rs | 2 ++ lib/c-api/wasmer_wasm.h | 4 ++++ 4 files changed, 13 insertions(+), 1 deletion(-) diff --git a/lib/c-api/build.rs b/lib/c-api/build.rs index af5f06fd2..6f6208f54 100644 --- a/lib/c-api/build.rs +++ b/lib/c-api/build.rs @@ -384,6 +384,7 @@ fn exclude_items_from_wasm_c_api(mut builder: Builder) -> Builder { .exclude_item("wasi_env_t") .exclude_item("wasi_get_imports") .exclude_item("wasi_get_imports_inner") + .exclude_item("wasi_get_start_function") .exclude_item("wasi_get_wasi_version") .exclude_item("wasi_version_t"); diff --git a/lib/c-api/src/wasm_c_api/types/frame.rs b/lib/c-api/src/wasm_c_api/types/frame.rs index 9fc841671..f85f57616 100644 --- a/lib/c-api/src/wasm_c_api/types/frame.rs +++ b/lib/c-api/src/wasm_c_api/types/frame.rs @@ -2,7 +2,6 @@ use super::super::instance::wasm_instance_t; use wasmer::FrameInfo; #[derive(Debug, Clone)] -#[repr(C)] pub struct wasm_frame_t { info: FrameInfo, } @@ -19,30 +18,36 @@ impl From for wasm_frame_t { } } +/// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn wasm_frame_copy(frame: &wasm_frame_t) -> Box { Box::new(frame.clone()) } +/// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn wasm_frame_delete(_frame: Option>) {} +/// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn wasm_frame_instance(frame: &wasm_frame_t) -> *const wasm_instance_t { //todo!("wasm_frame_instance") std::ptr::null() } +/// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn wasm_frame_func_index(frame: &wasm_frame_t) -> u32 { frame.info.func_index() } +/// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn wasm_frame_func_offset(frame: &wasm_frame_t) -> usize { frame.info.func_offset() } +/// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn wasm_frame_module_offset(frame: &wasm_frame_t) -> usize { frame.info.module_offset() diff --git a/lib/c-api/src/wasm_c_api/wasi/mod.rs b/lib/c-api/src/wasm_c_api/wasi/mod.rs index 550d2ff04..86f8717d9 100644 --- a/lib/c-api/src/wasm_c_api/wasi/mod.rs +++ b/lib/c-api/src/wasm_c_api/wasi/mod.rs @@ -299,5 +299,7 @@ pub unsafe extern "C" fn wasi_get_start_function( } /// Delete a `wasm_extern_t` allocated by the API. +/// +/// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn wasm_extern_delete(_item: Option>) {} diff --git a/lib/c-api/wasmer_wasm.h b/lib/c-api/wasmer_wasm.h index 112f1d83c..f63ac73f7 100644 --- a/lib/c-api/wasmer_wasm.h +++ b/lib/c-api/wasmer_wasm.h @@ -124,6 +124,10 @@ bool wasi_get_imports(wasm_store_t *store, wasm_extern_t **imports); #endif +#if defined(WASMER_WASI_ENABLED) +wasm_func_t *wasi_get_start_function(wasm_instance_t *instance); +#endif + #if defined(WASMER_WASI_ENABLED) wasi_version_t wasi_get_wasi_version(const wasm_module_t *module); #endif From 3a81643ff0a0a09336eef98578c8628d7a7a7432 Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Thu, 1 Oct 2020 21:23:06 +0200 Subject: [PATCH 113/281] chore(c-api) Update header files. --- lib/c-api/wasmer_wasm.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/c-api/wasmer_wasm.h b/lib/c-api/wasmer_wasm.h index f63ac73f7..f7c4be4ae 100644 --- a/lib/c-api/wasmer_wasm.h +++ b/lib/c-api/wasmer_wasm.h @@ -28,6 +28,9 @@ # define DEPRECATED(message) __declspec(deprecated(message)) #endif +// The `jit` feature has been enabled for this build. +#define WASMER_JIT_ENABLED + // The `compiler` feature has been enabled for this build. #define WASMER_COMPILER_ENABLED From a117df1740e3e740a4f7d63e9a9ece6cd852f05f Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Thu, 1 Oct 2020 21:26:45 +0200 Subject: [PATCH 114/281] chore(c-api) Remove a warning about `wasm_frame_t` case. --- lib/c-api/src/wasm_c_api/types/frame.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/c-api/src/wasm_c_api/types/frame.rs b/lib/c-api/src/wasm_c_api/types/frame.rs index f85f57616..48e9a9597 100644 --- a/lib/c-api/src/wasm_c_api/types/frame.rs +++ b/lib/c-api/src/wasm_c_api/types/frame.rs @@ -1,6 +1,7 @@ use super::super::instance::wasm_instance_t; use wasmer::FrameInfo; +#[allow(non_camel_case_types)] #[derive(Debug, Clone)] pub struct wasm_frame_t { info: FrameInfo, From 5d9fc86bb88f04ad48f7e38e8f8ffedc8932a19d Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Thu, 1 Oct 2020 21:27:18 +0200 Subject: [PATCH 115/281] test(c-api) Enable the `wasi-c-api-trap` test case. --- lib/c-api/tests/wasm_c_api/CMakeLists.txt | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/lib/c-api/tests/wasm_c_api/CMakeLists.txt b/lib/c-api/tests/wasm_c_api/CMakeLists.txt index 55eedab30..89614ea96 100644 --- a/lib/c-api/tests/wasm_c_api/CMakeLists.txt +++ b/lib/c-api/tests/wasm_c_api/CMakeLists.txt @@ -14,7 +14,7 @@ add_executable(wasm-c-api-serialize wasm-c-api/example/serialize.c) #add_executable(wasm-c-api-start wasm-c-api/example/start.c) #add_executable(wasm-c-api-table wasm-c-api/example/table.c) #add_executable(wasm-c-api-threads wasm-c-api/example/threads.c) -#add_executable(wasm-c-api-trap wasm-c-api/example/trap.c) +add_executable(wasm-c-api-trap wasm-c-api/example/trap.c) # Our additional tests. #add_executable(test-wasi test-wasi.c) @@ -127,12 +127,12 @@ add_test(NAME wasm-c-api-serialize # WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/wasm-c-api/example/ #) -#target_link_libraries(wasm-c-api-trap general ${WASMER_LIB}) -#target_compile_options(wasm-c-api-trap PRIVATE ${COMPILER_OPTIONS}) -#add_test(NAME wasm-c-api-trap -# COMMAND wasm-c-api-trap -# WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/wasm-c-api/example/ -#) +target_link_libraries(wasm-c-api-trap general ${WASMER_LIB}) +target_compile_options(wasm-c-api-trap PRIVATE ${COMPILER_OPTIONS}) +add_test(NAME wasm-c-api-trap + COMMAND wasm-c-api-trap + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/wasm-c-api/example/ +) #set_property(TARGET test-wasi PROPERTY C_STANDARD 11) #target_link_libraries(test-wasi general ${WASMER_LIB}) From 68d6292c35137a3063d8bc43b040105abe100077 Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Thu, 1 Oct 2020 21:40:02 +0200 Subject: [PATCH 116/281] test(c-api) Restore the `test-wasi` and disable the `test-early-exit`. --- lib/c-api/tests/wasm_c_api/CMakeLists.txt | 16 +- .../tests/wasm_c_api/assets/call_trap.wasm | Bin 0 -> 66 bytes .../tests/wasm_c_api/assets/call_trap.wat | 11 ++ .../assets/qjs.wasm | Bin lib/c-api/tests/wasm_c_api/test-early-exit.c | 163 ++++++++++++++++++ lib/c-api/tests/wasm_c_api/test-wasi.c | 2 +- 6 files changed, 186 insertions(+), 6 deletions(-) create mode 100644 lib/c-api/tests/wasm_c_api/assets/call_trap.wasm create mode 100644 lib/c-api/tests/wasm_c_api/assets/call_trap.wat rename lib/c-api/tests/{deprecated => wasm_c_api}/assets/qjs.wasm (100%) create mode 100644 lib/c-api/tests/wasm_c_api/test-early-exit.c diff --git a/lib/c-api/tests/wasm_c_api/CMakeLists.txt b/lib/c-api/tests/wasm_c_api/CMakeLists.txt index 89614ea96..fb70268af 100644 --- a/lib/c-api/tests/wasm_c_api/CMakeLists.txt +++ b/lib/c-api/tests/wasm_c_api/CMakeLists.txt @@ -17,7 +17,8 @@ add_executable(wasm-c-api-serialize wasm-c-api/example/serialize.c) add_executable(wasm-c-api-trap wasm-c-api/example/trap.c) # Our additional tests. -#add_executable(test-wasi test-wasi.c) +add_executable(test-wasi test-wasi.c) +#add_executable(test-early-exit test-early-exit.c) include_directories(wasm-c-api/include) include_directories(../../) @@ -134,7 +135,12 @@ add_test(NAME wasm-c-api-trap WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/wasm-c-api/example/ ) -#set_property(TARGET test-wasi PROPERTY C_STANDARD 11) -#target_link_libraries(test-wasi general ${WASMER_LIB}) -#target_compile_options(test-wasi PRIVATE ${COMPILER_OPTIONS}) -#add_test(test-wasi test-wasi) +set_property(TARGET test-wasi PROPERTY C_STANDARD 11) +target_link_libraries(test-wasi general ${WASMER_LIB}) +target_compile_options(test-wasi PRIVATE ${COMPILER_OPTIONS}) +add_test(test-wasi test-wasi) + +#set_property(TARGET test-early-exit PROPERTY C_STANDARD 11) +#target_link_libraries(test-early-exit general ${WASMER_LIB}) +#target_compile_options(test-early-exit PRIVATE ${COMPILER_OPTIONS}) +#add_test(test-early-exit test-early-exit) diff --git a/lib/c-api/tests/wasm_c_api/assets/call_trap.wasm b/lib/c-api/tests/wasm_c_api/assets/call_trap.wasm new file mode 100644 index 0000000000000000000000000000000000000000..44cbb2797532a9beacc593922220267163546cae GIT binary patch literal 66 zcmZQbEY4+QU|?Y6VoG4DuV<`JU|?VpVq{LuE8|K{EXt{jPp!x-VPIrtVq{=vXJjra U%>%0CX5?fLU{GLCV9eqM0IV+yg#Z8m literal 0 HcmV?d00001 diff --git a/lib/c-api/tests/wasm_c_api/assets/call_trap.wat b/lib/c-api/tests/wasm_c_api/assets/call_trap.wat new file mode 100644 index 000000000..febd5f88d --- /dev/null +++ b/lib/c-api/tests/wasm_c_api/assets/call_trap.wat @@ -0,0 +1,11 @@ +(module + (type $run_t (func (param i32 i32) (result i32))) + (type $early_exit_t (func (param) (result))) + (import "env" "early_exit" (func $early_exit (type $early_exit_t))) + (func $run (type $run_t) (param $x i32) (param $y i32) (result i32) + (call $early_exit) + (i32.add + (local.get $x) + (local.get $y))) + (export "run" (func $run))) + diff --git a/lib/c-api/tests/deprecated/assets/qjs.wasm b/lib/c-api/tests/wasm_c_api/assets/qjs.wasm similarity index 100% rename from lib/c-api/tests/deprecated/assets/qjs.wasm rename to lib/c-api/tests/wasm_c_api/assets/qjs.wasm diff --git a/lib/c-api/tests/wasm_c_api/test-early-exit.c b/lib/c-api/tests/wasm_c_api/test-early-exit.c new file mode 100644 index 000000000..60730bd74 --- /dev/null +++ b/lib/c-api/tests/wasm_c_api/test-early-exit.c @@ -0,0 +1,163 @@ +#include +#include +#include +#include + +#include "../../wasmer_wasm.h" + +#define own + +// Use the last_error API to retrieve error messages +void print_wasmer_error() { + int error_len = wasmer_last_error_length(); + printf("Error len: `%d`\n", error_len); + char *error_str = malloc(error_len); + wasmer_last_error_message(error_str, error_len); + printf("Error str: `%s`\n", error_str); +} + +void print_frame(wasm_frame_t* frame) { + printf("> %p @ 0x%zx = %"PRIu32".0x%zx\n", + wasm_frame_instance(frame), + wasm_frame_module_offset(frame), + wasm_frame_func_index(frame), + wasm_frame_func_offset(frame) + ); +} + +wasm_store_t *store = NULL; + +own wasm_trap_t *early_exit(const wasm_val_t args[], wasm_val_t results[]) { + own wasm_message_t trap_message; + wasm_name_new_from_string(&trap_message, "trapping from a host import"); + own wasm_trap_t *trap = wasm_trap_new(store, &trap_message); + wasm_name_delete(&trap_message); + return trap; +} + +int main(int argc, const char *argv[]) { + // Initialize. + printf("Initializing...\n"); + wasm_engine_t *engine = wasm_engine_new(); + store = wasm_store_new(engine); + + // Load binary. + printf("Loading binary...\n"); + FILE *file = fopen("assets/call_trap.wasm", "r"); + if (!file) { + printf("> Error loading module!\n"); + return 1; + } + fseek(file, 0L, SEEK_END); + size_t file_size = ftell(file); + fseek(file, 0L, SEEK_SET); + wasm_byte_vec_t binary; + wasm_byte_vec_new_uninitialized(&binary, file_size); + if (fread(binary.data, file_size, 1, file) != 1) { + printf("> Error loading module!\n"); + return 1; + } + fclose(file); + + // Compile. + printf("Compiling module...\n"); + own wasm_module_t *module = wasm_module_new(store, &binary); + if (!module) { + printf("> Error compiling module!\n"); + return 1; + } + + wasm_byte_vec_delete(&binary); + + // Instantiate. + printf("Instantiating module...\n"); + + wasm_functype_t *host_func_type = wasm_functype_new_0_0(); + wasm_func_t *host_func = wasm_func_new(store, host_func_type, early_exit); + + wasm_functype_delete(host_func_type); + + const wasm_extern_t *imports[] = {wasm_func_as_extern(host_func)}; + own wasm_instance_t *instance = + wasm_instance_new(store, module, imports, NULL); + if (!instance) { + printf("> Error instantiating module!\n"); + print_wasmer_error(); + return 1; + } + + wasm_func_delete(host_func); + + // Extract export. + printf("Extracting export...\n"); + own wasm_extern_vec_t exports; + wasm_instance_exports(instance, &exports); + if (exports.size == 0) { + printf("> Error accessing exports!\n"); + return 1; + } + fprintf(stderr, "found %zu exports\n", exports.size); + + wasm_module_delete(module); + wasm_instance_delete(instance); + + wasm_func_t *run_func = wasm_extern_as_func(exports.data[0]); + if (run_func == NULL) { + printf("> Error accessing export!\n"); + print_wasmer_error(); + return 1; + } + + // Call. + printf("Calling export...\n"); + own const wasm_val_t args[] = { + {.kind = WASM_I32, .of = {.i32 = 1}}, + {.kind = WASM_I32, .of = {.i32 = 7}}, + }; + own wasm_val_t rets[1] = {}; + own wasm_trap_t *trap = wasm_func_call(run_func, args, rets); + if (!trap) { + printf("> Error calling function: expected trap!\n"); + return 1; + } + + printf("Printing message...\n"); + own wasm_name_t message; + wasm_trap_message(trap, &message); + printf("> %s\n", message.data); + + printf("Printing origin...\n"); + own wasm_frame_t* frame = wasm_trap_origin(trap); + if (frame) { + print_frame(frame); + wasm_frame_delete(frame); + } else { + printf("> Empty origin.\n"); + } + + printf("Printing trace...\n"); + own wasm_frame_vec_t trace; + wasm_trap_trace(trap, &trace); + if (trace.size > 0) { + for (size_t i = 0; i < trace.size; ++i) { + print_frame(trace.data[i]); + } + } else { + printf("> Empty trace.\n"); + } + + wasm_frame_vec_delete(&trace); + wasm_trap_delete(trap); + wasm_name_delete(&message); + + wasm_extern_vec_delete(&exports); + + // Shut down. + printf("Shutting down...\n"); + wasm_store_delete(store); + wasm_engine_delete(engine); + + // All done. + printf("Done.\n"); + return 0; +} diff --git a/lib/c-api/tests/wasm_c_api/test-wasi.c b/lib/c-api/tests/wasm_c_api/test-wasi.c index 9a507b02e..ddc5748e4 100644 --- a/lib/c-api/tests/wasm_c_api/test-wasi.c +++ b/lib/c-api/tests/wasm_c_api/test-wasi.c @@ -3,10 +3,10 @@ #include #include -#include "../../wasm.h" #include "../../wasmer_wasm.h" #define BUF_SIZE 128 +#define own // Use the last_error API to retrieve error messages void print_wasmer_error() From 0095ec9538746ab225d9c9dca0d6493c0dfa22e1 Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Thu, 1 Oct 2020 23:07:43 +0200 Subject: [PATCH 117/281] fix(c-api) `wasm_val_t` is not an opaque type, let's use a C representation. --- lib/c-api/src/wasm_c_api/value.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/c-api/src/wasm_c_api/value.rs b/lib/c-api/src/wasm_c_api/value.rs index 2102bbb1e..dd2254b10 100644 --- a/lib/c-api/src/wasm_c_api/value.rs +++ b/lib/c-api/src/wasm_c_api/value.rs @@ -20,9 +20,10 @@ pub union wasm_val_inner { /// cbindgen:ignore #[allow(non_camel_case_types)] +#[repr(C)] pub struct wasm_val_t { - pub(crate) kind: wasm_valkind_t, - pub(crate) of: wasm_val_inner, + pub kind: wasm_valkind_t, + pub of: wasm_val_inner, } impl Clone for wasm_val_t { From ddbbd96f1c1828a15e170791c049c956e5389c28 Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Thu, 1 Oct 2020 23:23:23 +0200 Subject: [PATCH 118/281] test(c-api) Run `make clean` before, in case of. --- lib/c-api/tests/test_c_helpers/mod.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/c-api/tests/test_c_helpers/mod.rs b/lib/c-api/tests/test_c_helpers/mod.rs index 32c520cae..22c3c937a 100644 --- a/lib/c-api/tests/test_c_helpers/mod.rs +++ b/lib/c-api/tests/test_c_helpers/mod.rs @@ -10,6 +10,7 @@ pub fn compile_with_cmake_and_run_test(project_tests_dir: &str, cmake_args: Vec< ], ); run_command("cmake", project_tests_dir, cmake_args); + run_command("make", project_tests_dir, vec!["clean"]); run_command("make", project_tests_dir, vec!["-Wdev", "-Werror=dev"]); run_command("make", project_tests_dir, vec!["test", "ARGS=\"-V\""]); } From d5fa5256124e4609774593b42640d8ab2ded5330 Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Thu, 1 Oct 2020 23:23:41 +0200 Subject: [PATCH 119/281] test(c-api) Enable the `test-early-exit` test case. --- lib/c-api/tests/wasm_c_api/CMakeLists.txt | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/c-api/tests/wasm_c_api/CMakeLists.txt b/lib/c-api/tests/wasm_c_api/CMakeLists.txt index fb70268af..061006e8e 100644 --- a/lib/c-api/tests/wasm_c_api/CMakeLists.txt +++ b/lib/c-api/tests/wasm_c_api/CMakeLists.txt @@ -18,7 +18,7 @@ add_executable(wasm-c-api-trap wasm-c-api/example/trap.c) # Our additional tests. add_executable(test-wasi test-wasi.c) -#add_executable(test-early-exit test-early-exit.c) +add_executable(test-early-exit test-early-exit.c) include_directories(wasm-c-api/include) include_directories(../../) @@ -140,7 +140,7 @@ target_link_libraries(test-wasi general ${WASMER_LIB}) target_compile_options(test-wasi PRIVATE ${COMPILER_OPTIONS}) add_test(test-wasi test-wasi) -#set_property(TARGET test-early-exit PROPERTY C_STANDARD 11) -#target_link_libraries(test-early-exit general ${WASMER_LIB}) -#target_compile_options(test-early-exit PRIVATE ${COMPILER_OPTIONS}) -#add_test(test-early-exit test-early-exit) +set_property(TARGET test-early-exit PROPERTY C_STANDARD 11) +target_link_libraries(test-early-exit general ${WASMER_LIB}) +target_compile_options(test-early-exit PRIVATE ${COMPILER_OPTIONS}) +add_test(test-early-exit test-early-exit) From 1a45756cad905f2c9905eb0b208d9278732211b5 Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Fri, 2 Oct 2020 09:45:34 +0200 Subject: [PATCH 120/281] test(c-api) Use the `REQUIRED` option of `find_library`. --- lib/c-api/tests/deprecated/CMakeLists.txt | 5 +---- lib/c-api/tests/wasm_c_api/CMakeLists.txt | 5 +---- 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/lib/c-api/tests/deprecated/CMakeLists.txt b/lib/c-api/tests/deprecated/CMakeLists.txt index ddb1cb6de..813c5927f 100644 --- a/lib/c-api/tests/deprecated/CMakeLists.txt +++ b/lib/c-api/tests/deprecated/CMakeLists.txt @@ -31,12 +31,9 @@ include_directories(../../) find_library( WASMER_LIB NAMES libwasmer_c_api.dylib libwasmer_c_api.so wasmer_c_api.dll PATHS ${CMAKE_SOURCE_DIR}/../../../../target/release/ + REQUIRED ) -if(NOT WASMER_LIB) - message(FATAL_ERROR "wasmer library not found") -endif() - enable_testing() set( diff --git a/lib/c-api/tests/wasm_c_api/CMakeLists.txt b/lib/c-api/tests/wasm_c_api/CMakeLists.txt index 061006e8e..463cdb70b 100644 --- a/lib/c-api/tests/wasm_c_api/CMakeLists.txt +++ b/lib/c-api/tests/wasm_c_api/CMakeLists.txt @@ -26,12 +26,9 @@ include_directories(../../) find_library( WASMER_LIB NAMES libwasmer_c_api.dylib libwasmer_c_api.so wasmer_c_api.dll PATHS ${CMAKE_SOURCE_DIR}/../../../../target/release/ + REQUIRED ) -if(NOT WASMER_LIB) - message(FATAL_ERROR "wasmer library not found") -endif() - enable_testing() set( From ae1a50b5d797b398fddab26976bdb544e0b54d27 Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Fri, 2 Oct 2020 09:51:48 +0200 Subject: [PATCH 121/281] chore(c-api) Move `cbindgen:ignore` from functions/types to modules. This patch removes the amount of `cbindgen:ignore` instructions by moving this instruction onto the parent module. --- lib/c-api/src/wasm_c_api/engine.rs | 14 +++-------- .../src/wasm_c_api/externals/function.rs | 10 -------- lib/c-api/src/wasm_c_api/externals/global.rs | 7 ------ lib/c-api/src/wasm_c_api/externals/memory.rs | 10 -------- lib/c-api/src/wasm_c_api/externals/mod.rs | 9 -------- lib/c-api/src/wasm_c_api/externals/table.rs | 7 ------ lib/c-api/src/wasm_c_api/instance.rs | 4 ---- lib/c-api/src/wasm_c_api/macros.rs | 11 --------- lib/c-api/src/wasm_c_api/mod.rs | 15 ++++++++++++ lib/c-api/src/wasm_c_api/module.rs | 7 ------ lib/c-api/src/wasm_c_api/store.rs | 3 --- lib/c-api/src/wasm_c_api/trap.rs | 6 ----- lib/c-api/src/wasm_c_api/types/export.rs | 4 ---- lib/c-api/src/wasm_c_api/types/extern_.rs | 23 ------------------- lib/c-api/src/wasm_c_api/types/frame.rs | 6 ----- lib/c-api/src/wasm_c_api/types/function.rs | 6 ----- lib/c-api/src/wasm_c_api/types/global.rs | 5 ---- lib/c-api/src/wasm_c_api/types/import.rs | 6 ----- lib/c-api/src/wasm_c_api/types/memory.rs | 6 ----- lib/c-api/src/wasm_c_api/types/mod.rs | 3 --- lib/c-api/src/wasm_c_api/types/mutability.rs | 2 -- lib/c-api/src/wasm_c_api/types/table.rs | 7 ------ lib/c-api/src/wasm_c_api/types/value.rs | 5 ---- lib/c-api/src/wasm_c_api/value.rs | 5 ---- 24 files changed, 18 insertions(+), 163 deletions(-) diff --git a/lib/c-api/src/wasm_c_api/engine.rs b/lib/c-api/src/wasm_c_api/engine.rs index 184718751..82152a152 100644 --- a/lib/c-api/src/wasm_c_api/engine.rs +++ b/lib/c-api/src/wasm_c_api/engine.rs @@ -4,18 +4,15 @@ use wasmer::Engine; /// this can be a wasmer-specific type with wasmer-specific functions for manipulating it /// -/// cbindgen:ignore #[allow(non_camel_case_types)] pub struct wasm_config_t {} -/// cbindgen:ignore #[no_mangle] pub extern "C" fn wasm_config_new() -> *mut wasm_config_t { todo!("wasm_config_new") //ptr::null_mut() } -/// cbindgen:ignore #[allow(non_camel_case_types)] pub struct wasm_engine_t { pub(crate) inner: Arc, @@ -41,8 +38,7 @@ cfg_if! { } } - /// cbindgen:ignore - #[no_mangle] + #[no_mangle] pub extern "C" fn wasm_engine_new() -> Box { let compiler_config: Box = get_default_compiler_config(); let engine: Arc = Arc::new(JIT::new(&*compiler_config).engine()); @@ -51,27 +47,23 @@ cfg_if! { } else if #[cfg(feature = "jit")] { // Headless JIT - /// cbindgen:ignore - #[no_mangle] + #[no_mangle] pub extern "C" fn wasm_engine_new() -> Box { let engine: Arc = Arc::new(JIT::headless().engine()); Box::new(wasm_engine_t { inner: engine }) } } else { - /// cbindgen:ignore - #[no_mangle] + #[no_mangle] pub extern "C" fn wasm_engine_new() -> Box { unimplemented!("The JITEngine is not attached"); } } } -/// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn wasm_engine_delete(_wasm_engine_address: Option>) {} -/// cbindgen:ignore #[no_mangle] pub extern "C" fn wasm_engine_new_with_config( _config_ptr: *mut wasm_config_t, diff --git a/lib/c-api/src/wasm_c_api/externals/function.rs b/lib/c-api/src/wasm_c_api/externals/function.rs index 86e7a84b2..ee351d955 100644 --- a/lib/c-api/src/wasm_c_api/externals/function.rs +++ b/lib/c-api/src/wasm_c_api/externals/function.rs @@ -8,7 +8,6 @@ use std::ptr::NonNull; use std::sync::Arc; use wasmer::{Function, Instance, RuntimeError, Store, Val}; -/// cbindgen:ignore #[allow(non_camel_case_types)] pub struct wasm_func_t { pub(crate) inner: Function, @@ -16,12 +15,10 @@ pub struct wasm_func_t { pub(crate) instance: Option>, } -/// cbindgen:ignore #[allow(non_camel_case_types)] pub type wasm_func_callback_t = unsafe extern "C" fn(args: *const wasm_val_t, results: *mut wasm_val_t) -> *mut wasm_trap_t; -/// cbindgen:ignore #[allow(non_camel_case_types)] pub type wasm_func_callback_with_env_t = unsafe extern "C" fn( *mut c_void, @@ -29,11 +26,9 @@ pub type wasm_func_callback_with_env_t = unsafe extern "C" fn( results: *mut wasm_val_t, ) -> *mut wasm_trap_t; -/// cbindgen:ignore #[allow(non_camel_case_types)] pub type wasm_env_finalizer_t = unsafe extern "C" fn(c_void); -/// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn wasm_func_new( store: Option>, @@ -80,7 +75,6 @@ pub unsafe extern "C" fn wasm_func_new( })) } -/// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn wasm_func_new_with_env( store: Option>, @@ -127,11 +121,9 @@ pub unsafe extern "C" fn wasm_func_new_with_env( })) } -/// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn wasm_func_delete(_func: Option>) {} -/// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn wasm_func_call( func: &wasm_func_t, @@ -156,13 +148,11 @@ pub unsafe extern "C" fn wasm_func_call( } } -/// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn wasm_func_param_arity(func: &wasm_func_t) -> usize { func.inner.ty().params().len() } -/// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn wasm_func_result_arity(func: &wasm_func_t) -> usize { func.inner.ty().results().len() diff --git a/lib/c-api/src/wasm_c_api/externals/global.rs b/lib/c-api/src/wasm_c_api/externals/global.rs index ba148aa21..92c1ed1e4 100644 --- a/lib/c-api/src/wasm_c_api/externals/global.rs +++ b/lib/c-api/src/wasm_c_api/externals/global.rs @@ -5,14 +5,12 @@ use std::convert::TryInto; use std::ptr::NonNull; use wasmer::{Global, Store, Val}; -/// cbindgen:ignore #[allow(non_camel_case_types)] pub struct wasm_global_t { // maybe needs to hold onto instance pub(crate) inner: Global, } -/// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn wasm_global_new( store_ptr: Option>, @@ -32,12 +30,10 @@ pub unsafe extern "C" fn wasm_global_new( Some(Box::new(wasm_global_t { inner: global })) } -/// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn wasm_global_delete(_global: Option>) {} // TODO: figure out if these should be deep or shallow copies -/// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn wasm_global_copy(wasm_global: &wasm_global_t) -> Box { // do shallow copy @@ -46,21 +42,18 @@ pub unsafe extern "C" fn wasm_global_copy(wasm_global: &wasm_global_t) -> Box>, @@ -25,12 +23,10 @@ pub unsafe extern "C" fn wasm_memory_new( Some(Box::new(wasm_memory_t { inner: memory })) } -/// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn wasm_memory_delete(_memory: Option>) {} // TODO: figure out if these should be deep or shallow copies -/// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn wasm_memory_copy(wasm_memory: &wasm_memory_t) -> Box { // do shallow copy @@ -39,14 +35,12 @@ pub unsafe extern "C" fn wasm_memory_copy(wasm_memory: &wasm_memory_t) -> Box *mut wasm_memorytype_t { todo!("wasm_memory_type") } // get a raw pointer into bytes -/// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn wasm_memory_data(memory: &mut wasm_memory_t) -> *mut u8 { mem::transmute::<&[std::cell::Cell], &[u8]>(&memory.inner.view()[..]) as *const [u8] @@ -54,27 +48,23 @@ pub unsafe extern "C" fn wasm_memory_data(memory: &mut wasm_memory_t) -> *mut u8 } // size in bytes -/// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn wasm_memory_data_size(memory: &wasm_memory_t) -> usize { memory.inner.size().bytes().0 } // size in pages -/// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn wasm_memory_size(memory: &wasm_memory_t) -> u32 { memory.inner.size().0 as _ } // delta is in pages -/// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn wasm_memory_grow(memory: &mut wasm_memory_t, delta: u32) -> bool { memory.inner.grow(Pages(delta)).is_ok() } -/// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn wasm_memory_same( wasm_memory1: &wasm_memory_t, diff --git a/lib/c-api/src/wasm_c_api/externals/mod.rs b/lib/c-api/src/wasm_c_api/externals/mod.rs index 6f04a94d1..1fd931c5b 100644 --- a/lib/c-api/src/wasm_c_api/externals/mod.rs +++ b/lib/c-api/src/wasm_c_api/externals/mod.rs @@ -11,7 +11,6 @@ use std::sync::Arc; pub use table::*; use wasmer::{Extern, Instance}; -/// cbindgen:ignore #[allow(non_camel_case_types)] pub struct wasm_extern_t { // this is how we ensure the instance stays alive @@ -21,7 +20,6 @@ pub struct wasm_extern_t { wasm_declare_boxed_vec!(extern); -/// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn wasm_func_as_extern( func_ptr: Option>, @@ -35,7 +33,6 @@ pub unsafe extern "C" fn wasm_func_as_extern( })) } -/// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn wasm_global_as_extern( global_ptr: Option>, @@ -50,7 +47,6 @@ pub unsafe extern "C" fn wasm_global_as_extern( })) } -/// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn wasm_memory_as_extern( memory_ptr: Option>, @@ -65,7 +61,6 @@ pub unsafe extern "C" fn wasm_memory_as_extern( })) } -/// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn wasm_table_as_extern( table_ptr: Option>, @@ -80,7 +75,6 @@ pub unsafe extern "C" fn wasm_table_as_extern( })) } -/// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn wasm_extern_as_func( extern_ptr: Option>, @@ -97,7 +91,6 @@ pub unsafe extern "C" fn wasm_extern_as_func( } } -/// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn wasm_extern_as_global( extern_ptr: Option>, @@ -111,7 +104,6 @@ pub unsafe extern "C" fn wasm_extern_as_global( } } -/// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn wasm_extern_as_memory( extern_ptr: Option>, @@ -125,7 +117,6 @@ pub unsafe extern "C" fn wasm_extern_as_memory( } } -/// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn wasm_extern_as_table( extern_ptr: Option>, diff --git a/lib/c-api/src/wasm_c_api/externals/table.rs b/lib/c-api/src/wasm_c_api/externals/table.rs index 44600035d..f6ade8a5a 100644 --- a/lib/c-api/src/wasm_c_api/externals/table.rs +++ b/lib/c-api/src/wasm_c_api/externals/table.rs @@ -3,14 +3,12 @@ use super::super::types::{wasm_ref_t, wasm_table_size_t, wasm_tabletype_t}; use std::ptr::NonNull; use wasmer::{Store, Table}; -/// cbindgen:ignore #[allow(non_camel_case_types)] pub struct wasm_table_t { // maybe needs to hold onto instance pub(crate) inner: Table, } -/// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn wasm_table_new( store_ptr: Option>, @@ -27,11 +25,9 @@ pub unsafe extern "C" fn wasm_table_new( Some(Box::new(wasm_table_t { inner: table })) } -/// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn wasm_table_delete(_table: Option>) {} -/// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn wasm_table_copy(wasm_table: &wasm_table_t) -> Box { // do shallow copy @@ -40,7 +36,6 @@ pub unsafe extern "C" fn wasm_table_copy(wasm_table: &wasm_table_t) -> Box usize { wasm_table.inner.size() as _ } -/// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn wasm_table_grow( _wasm_table: &mut wasm_table_t, diff --git a/lib/c-api/src/wasm_c_api/instance.rs b/lib/c-api/src/wasm_c_api/instance.rs index 139de7fd2..39a82fd28 100644 --- a/lib/c-api/src/wasm_c_api/instance.rs +++ b/lib/c-api/src/wasm_c_api/instance.rs @@ -8,7 +8,6 @@ use std::ptr::NonNull; use std::sync::Arc; use wasmer::{Extern, Instance}; -/// cbindgen:ignore #[allow(non_camel_case_types)] pub struct wasm_instance_t { pub(crate) inner: Arc, @@ -51,7 +50,6 @@ unsafe fn argument_import_iter( .unwrap_or_else(|| Box::new(std::iter::empty()) as _) } -/// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn wasm_instance_new( store: Option>, @@ -74,11 +72,9 @@ pub unsafe extern "C" fn wasm_instance_new( Some(Box::new(wasm_instance_t { inner: instance })) } -/// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn wasm_instance_delete(_instance: Option>) {} -/// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn wasm_instance_exports( instance: &wasm_instance_t, diff --git a/lib/c-api/src/wasm_c_api/macros.rs b/lib/c-api/src/wasm_c_api/macros.rs index 36dbf47f6..2f723206c 100644 --- a/lib/c-api/src/wasm_c_api/macros.rs +++ b/lib/c-api/src/wasm_c_api/macros.rs @@ -3,14 +3,12 @@ macro_rules! wasm_declare_vec_inner { ($name:ident) => { paste::item! { - /// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn [](out: *mut []) { // TODO: actually implement this [](out, 0); } - /// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn [](ptr: *mut []) { let vec = &mut *ptr; @@ -29,7 +27,6 @@ macro_rules! wasm_declare_vec_inner { macro_rules! wasm_declare_vec { ($name:ident) => { paste::item! { - /// cbindgen:ignore #[repr(C)] pub struct [] { pub size: usize, @@ -78,7 +75,6 @@ macro_rules! wasm_declare_vec { } // TODO: investigate possible memory leak on `init` (owned pointer) - /// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn [](out: *mut [], length: usize, init: *mut []) { let mut bytes: Vec<[]> = Vec::with_capacity(length); @@ -92,7 +88,6 @@ macro_rules! wasm_declare_vec { ::std::mem::forget(bytes); } - /// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn [](out: *mut [], length: usize) { let mut bytes: Vec<[]> = Vec::with_capacity(length); @@ -112,7 +107,6 @@ macro_rules! wasm_declare_vec { macro_rules! wasm_declare_boxed_vec { ($name:ident) => { paste::item! { - /// cbindgen:ignore #[repr(C)] pub struct [] { pub size: usize, @@ -131,7 +125,6 @@ macro_rules! wasm_declare_boxed_vec { } // TODO: investigate possible memory leak on `init` (owned pointer) - /// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn [](out: *mut [], length: usize, init: *const *mut []) { let mut bytes: Vec<*mut []> = Vec::with_capacity(length); @@ -145,7 +138,6 @@ macro_rules! wasm_declare_boxed_vec { ::std::mem::forget(bytes); } - /// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn [](out: *mut [], length: usize) { let mut bytes: Vec<*mut []> = Vec::with_capacity(length); @@ -167,7 +159,6 @@ macro_rules! wasm_declare_ref_base { wasm_declare_own!($name); paste::item! { - /// cbindgen:ignore #[no_mangle] pub extern "C" fn [](_arg: *const []) -> *mut [] { todo!("in generated declare ref base"); @@ -185,11 +176,9 @@ macro_rules! wasm_declare_ref_base { macro_rules! wasm_declare_own { ($name:ident) => { paste::item! { - /// cbindgen:ignore #[repr(C)] pub struct [] {} - /// cbindgen:ignore #[no_mangle] pub extern "C" fn [](_arg: *mut []) { todo!("in generated delete") diff --git a/lib/c-api/src/wasm_c_api/mod.rs b/lib/c-api/src/wasm_c_api/mod.rs index 5ee3adf6e..537e32349 100644 --- a/lib/c-api/src/wasm_c_api/mod.rs +++ b/lib/c-api/src/wasm_c_api/mod.rs @@ -3,13 +3,28 @@ #[macro_use] pub mod macros; +/// cbindgen:ignore pub mod engine; + +/// cbindgen:ignore pub mod externals; + +/// cbindgen:ignore pub mod instance; + +/// cbindgen:ignore pub mod module; + +/// cbindgen:ignore pub mod store; + +/// cbindgen:ignore pub mod trap; + +/// cbindgen:ignore pub mod types; + +/// cbindgen:ignore pub mod value; #[cfg(feature = "wasi")] diff --git a/lib/c-api/src/wasm_c_api/module.rs b/lib/c-api/src/wasm_c_api/module.rs index bca743268..b2dbc002f 100644 --- a/lib/c-api/src/wasm_c_api/module.rs +++ b/lib/c-api/src/wasm_c_api/module.rs @@ -9,13 +9,11 @@ use std::slice; use std::sync::Arc; use wasmer::{Module, Store}; -/// cbindgen:ignore #[allow(non_camel_case_types)] pub struct wasm_module_t { pub(crate) inner: Arc, } -/// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn wasm_module_new( store_ptr: Option>, @@ -32,11 +30,9 @@ pub unsafe extern "C" fn wasm_module_new( })) } -/// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn wasm_module_delete(_module: Option>) {} -/// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn wasm_module_exports( module: &wasm_module_t, @@ -56,7 +52,6 @@ pub unsafe extern "C" fn wasm_module_exports( mem::forget(exports); } -/// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn wasm_module_imports( module: &wasm_module_t, @@ -76,7 +71,6 @@ pub unsafe extern "C" fn wasm_module_imports( mem::forget(imports); } -/// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn wasm_module_deserialize( store_ptr: Option>, @@ -102,7 +96,6 @@ pub unsafe extern "C" fn wasm_module_deserialize( )))) } -/// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn wasm_module_serialize( module: &wasm_module_t, diff --git a/lib/c-api/src/wasm_c_api/store.rs b/lib/c-api/src/wasm_c_api/store.rs index 32b241d84..6336f0033 100644 --- a/lib/c-api/src/wasm_c_api/store.rs +++ b/lib/c-api/src/wasm_c_api/store.rs @@ -3,11 +3,9 @@ use std::ptr::NonNull; use wasmer::Store; /// Opaque wrapper around `Store` -/// cbindgen:ignore #[allow(non_camel_case_types)] pub struct wasm_store_t {} -/// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn wasm_store_new( wasm_engine_ptr: Option>, @@ -20,7 +18,6 @@ pub unsafe extern "C" fn wasm_store_new( )) } -/// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn wasm_store_delete(wasm_store: Option>) { if let Some(s_inner) = wasm_store { diff --git a/lib/c-api/src/wasm_c_api/trap.rs b/lib/c-api/src/wasm_c_api/trap.rs index 6bb4758be..4bea90090 100644 --- a/lib/c-api/src/wasm_c_api/trap.rs +++ b/lib/c-api/src/wasm_c_api/trap.rs @@ -3,7 +3,6 @@ use super::types::{wasm_byte_vec_t, wasm_frame_t, wasm_frame_vec_t, wasm_message use wasmer::RuntimeError; // opaque type which is a `RuntimeError` -/// cbindgen:ignore #[allow(non_camel_case_types)] pub struct wasm_trap_t { pub(crate) inner: RuntimeError, @@ -15,7 +14,6 @@ impl From for wasm_trap_t { } } -/// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn wasm_trap_new( _store: &mut wasm_store_t, @@ -29,11 +27,9 @@ pub unsafe extern "C" fn wasm_trap_new( Some(Box::new(trap)) } -/// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn wasm_trap_delete(_trap: Option>) {} -/// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn wasm_trap_message(trap: &wasm_trap_t, out_ptr: &mut wasm_byte_vec_t) { let message = trap.inner.message(); @@ -42,13 +38,11 @@ pub unsafe extern "C" fn wasm_trap_message(trap: &wasm_trap_t, out_ptr: &mut was out_ptr.data = byte_vec.data; } -/// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn wasm_trap_origin(trap: &wasm_trap_t) -> Option> { trap.inner.trace().first().map(Into::into).map(Box::new) } -/// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn wasm_trap_trace(trap: &wasm_trap_t, out_ptr: &mut wasm_frame_vec_t) { let frames = trap.inner.trace(); diff --git a/lib/c-api/src/wasm_c_api/types/export.rs b/lib/c-api/src/wasm_c_api/types/export.rs index 81b8039f7..1a9c03011 100644 --- a/lib/c-api/src/wasm_c_api/types/export.rs +++ b/lib/c-api/src/wasm_c_api/types/export.rs @@ -2,7 +2,6 @@ use super::{wasm_externtype_t, wasm_name_t}; use std::ptr::NonNull; use wasmer::ExportType; -/// cbindgen:ignore #[allow(non_camel_case_types)] pub struct wasm_exporttype_t { name: NonNull, @@ -11,7 +10,6 @@ pub struct wasm_exporttype_t { wasm_declare_boxed_vec!(exporttype); -/// cbindgen:ignore #[no_mangle] pub extern "C" fn wasm_exporttype_new( name: NonNull, @@ -20,13 +18,11 @@ pub extern "C" fn wasm_exporttype_new( Box::new(wasm_exporttype_t { name, extern_type }) } -/// cbindgen:ignore #[no_mangle] pub extern "C" fn wasm_exporttype_name(et: &'static wasm_exporttype_t) -> &'static wasm_name_t { unsafe { et.name.as_ref() } } -/// cbindgen:ignore #[no_mangle] pub extern "C" fn wasm_exporttype_type( et: &'static wasm_exporttype_t, diff --git a/lib/c-api/src/wasm_c_api/types/extern_.rs b/lib/c-api/src/wasm_c_api/types/extern_.rs index 3d537e59e..97692de73 100644 --- a/lib/c-api/src/wasm_c_api/types/extern_.rs +++ b/lib/c-api/src/wasm_c_api/types/extern_.rs @@ -5,14 +5,12 @@ use std::mem; use thiserror::Error; use wasmer::ExternType; -/// cbindgen:ignore #[allow(non_camel_case_types)] #[derive(Clone, Debug)] pub struct wasm_externtype_t { pub(crate) inner: ExternType, } -/// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn wasm_extern_type(e: &wasm_extern_t) -> Box { Box::new(wasm_externtype_t { @@ -20,7 +18,6 @@ pub unsafe extern "C" fn wasm_extern_type(e: &wasm_extern_t) -> Box>) {} @@ -36,11 +33,9 @@ impl From<&ExternType> for wasm_externtype_t { } } -/// cbindgen:ignore #[allow(non_camel_case_types)] type wasm_externkind_t = u8; -/// cbindgen:ignore #[allow(non_camel_case_types)] #[repr(u8)] pub enum wasm_externkind_enum { @@ -50,7 +45,6 @@ pub enum wasm_externkind_enum { WASM_EXTERN_MEMORY = 3, } -/// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn wasm_extern_kind(e: &wasm_extern_t) -> wasm_externkind_t { wasm_externkind_enum::from(e.inner.ty()) as wasm_externkind_t @@ -72,7 +66,6 @@ impl From<&ExternType> for wasm_externkind_enum { } } -/// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn wasm_externtype_kind(et: &wasm_externtype_t) -> wasm_externkind_t { wasm_externkind_enum::from(&et.inner) as wasm_externkind_t @@ -136,7 +129,6 @@ impl TryFrom<&'static wasm_externtype_t> for &'static wasm_tabletype_t { } } -/// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn wasm_externtype_as_functype_const( et: &'static wasm_externtype_t, @@ -144,7 +136,6 @@ pub unsafe extern "C" fn wasm_externtype_as_functype_const( Some(c_try!(et.try_into())) } -/// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn wasm_externtype_as_functype( et: &'static wasm_externtype_t, @@ -152,7 +143,6 @@ pub unsafe extern "C" fn wasm_externtype_as_functype( Some(c_try!(et.try_into())) } -/// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn wasm_functype_as_externtype_const( ft: &'static wasm_functype_t, @@ -160,7 +150,6 @@ pub unsafe extern "C" fn wasm_functype_as_externtype_const( &ft.extern_ } -/// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn wasm_functype_as_externtype( ft: &'static wasm_functype_t, @@ -168,7 +157,6 @@ pub unsafe extern "C" fn wasm_functype_as_externtype( &ft.extern_ } -/// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn wasm_externtype_as_memorytype_const( et: &'static wasm_externtype_t, @@ -176,7 +164,6 @@ pub unsafe extern "C" fn wasm_externtype_as_memorytype_const( Some(c_try!(et.try_into())) } -/// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn wasm_externtype_as_memorytype( et: &'static wasm_externtype_t, @@ -184,7 +171,6 @@ pub unsafe extern "C" fn wasm_externtype_as_memorytype( Some(c_try!(et.try_into())) } -/// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn wasm_memorytype_as_externtype_const( mt: &'static wasm_memorytype_t, @@ -192,7 +178,6 @@ pub unsafe extern "C" fn wasm_memorytype_as_externtype_const( &mt.extern_ } -/// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn wasm_memorytype_as_externtype( mt: &'static wasm_memorytype_t, @@ -200,7 +185,6 @@ pub unsafe extern "C" fn wasm_memorytype_as_externtype( &mt.extern_ } -/// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn wasm_externtype_as_globaltype_const( et: &'static wasm_externtype_t, @@ -208,7 +192,6 @@ pub unsafe extern "C" fn wasm_externtype_as_globaltype_const( Some(c_try!(et.try_into())) } -/// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn wasm_externtype_as_globaltype( et: &'static wasm_externtype_t, @@ -216,7 +199,6 @@ pub unsafe extern "C" fn wasm_externtype_as_globaltype( Some(c_try!(et.try_into())) } -/// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn wasm_globaltype_as_externtype_const( gt: &'static wasm_globaltype_t, @@ -224,7 +206,6 @@ pub unsafe extern "C" fn wasm_globaltype_as_externtype_const( >.extern_ } -/// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn wasm_globaltype_as_externtype( gt: &'static wasm_globaltype_t, @@ -232,7 +213,6 @@ pub unsafe extern "C" fn wasm_globaltype_as_externtype( >.extern_ } -/// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn wasm_externtype_as_tabletype_const( et: &'static wasm_externtype_t, @@ -240,7 +220,6 @@ pub unsafe extern "C" fn wasm_externtype_as_tabletype_const( Some(c_try!(et.try_into())) } -/// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn wasm_externtype_as_tabletype( et: &'static wasm_externtype_t, @@ -248,7 +227,6 @@ pub unsafe extern "C" fn wasm_externtype_as_tabletype( Some(c_try!(et.try_into())) } -/// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn wasm_tabletype_as_externtype_const( tt: &'static wasm_tabletype_t, @@ -256,7 +234,6 @@ pub unsafe extern "C" fn wasm_tabletype_as_externtype_const( &tt.extern_ } -/// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn wasm_tabletype_as_externtype( tt: &'static wasm_tabletype_t, diff --git a/lib/c-api/src/wasm_c_api/types/frame.rs b/lib/c-api/src/wasm_c_api/types/frame.rs index 48e9a9597..d926ce977 100644 --- a/lib/c-api/src/wasm_c_api/types/frame.rs +++ b/lib/c-api/src/wasm_c_api/types/frame.rs @@ -19,36 +19,30 @@ impl From for wasm_frame_t { } } -/// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn wasm_frame_copy(frame: &wasm_frame_t) -> Box { Box::new(frame.clone()) } -/// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn wasm_frame_delete(_frame: Option>) {} -/// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn wasm_frame_instance(frame: &wasm_frame_t) -> *const wasm_instance_t { //todo!("wasm_frame_instance") std::ptr::null() } -/// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn wasm_frame_func_index(frame: &wasm_frame_t) -> u32 { frame.info.func_index() } -/// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn wasm_frame_func_offset(frame: &wasm_frame_t) -> usize { frame.info.func_offset() } -/// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn wasm_frame_module_offset(frame: &wasm_frame_t) -> usize { frame.info.module_offset() diff --git a/lib/c-api/src/wasm_c_api/types/function.rs b/lib/c-api/src/wasm_c_api/types/function.rs index 35f4674e8..699e86a66 100644 --- a/lib/c-api/src/wasm_c_api/types/function.rs +++ b/lib/c-api/src/wasm_c_api/types/function.rs @@ -3,7 +3,6 @@ use std::mem; use std::ptr::NonNull; use wasmer::{ExternType, FunctionType, ValType}; -/// cbindgen:ignore #[allow(non_camel_case_types)] #[derive(Clone, Debug)] pub struct wasm_functype_t { @@ -22,7 +21,6 @@ impl wasm_functype_t { wasm_declare_vec!(functype); -/// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn wasm_functype_new( // own @@ -60,11 +58,9 @@ unsafe fn wasm_functype_new_inner( Some(Box::new(wasm_functype_t { extern_ })) } -/// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn wasm_functype_delete(_ft: Option>) {} -/// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn wasm_functype_copy( arg: Option>, @@ -75,7 +71,6 @@ pub unsafe extern "C" fn wasm_functype_copy( } // TODO: fix memory leak -/// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn wasm_functype_params(ft: &wasm_functype_t) -> *const wasm_valtype_vec_t { let mut valtypes = ft @@ -96,7 +91,6 @@ pub unsafe extern "C" fn wasm_functype_params(ft: &wasm_functype_t) -> *const wa } // TODO: fix memory leak -/// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn wasm_functype_results(ft: &wasm_functype_t) -> *const wasm_valtype_vec_t { let mut valtypes = ft diff --git a/lib/c-api/src/wasm_c_api/types/global.rs b/lib/c-api/src/wasm_c_api/types/global.rs index 9547430cc..78ed193f4 100644 --- a/lib/c-api/src/wasm_c_api/types/global.rs +++ b/lib/c-api/src/wasm_c_api/types/global.rs @@ -4,7 +4,6 @@ use super::{ use std::convert::TryInto; use wasmer::{ExternType, GlobalType}; -/// cbindgen:ignore #[allow(non_camel_case_types)] #[derive(Clone, Debug)] pub struct wasm_globaltype_t { @@ -25,7 +24,6 @@ impl wasm_globaltype_t { wasm_declare_vec!(globaltype); -/// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn wasm_globaltype_new( // own @@ -35,7 +33,6 @@ pub unsafe extern "C" fn wasm_globaltype_new( wasm_globaltype_new_inner(valtype?, mutability) } -/// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn wasm_globaltype_delete(_globaltype: Option>) {} @@ -55,7 +52,6 @@ unsafe fn wasm_globaltype_new_inner( Some(gd) } -/// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn wasm_globaltype_mutability( globaltype: &wasm_globaltype_t, @@ -66,7 +62,6 @@ pub unsafe extern "C" fn wasm_globaltype_mutability( // TODO: fix memory leak // this function leaks memory because the returned limits pointer is not owned -/// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn wasm_globaltype_content( globaltype: &wasm_globaltype_t, diff --git a/lib/c-api/src/wasm_c_api/types/import.rs b/lib/c-api/src/wasm_c_api/types/import.rs index 8e45570e7..23efd73c2 100644 --- a/lib/c-api/src/wasm_c_api/types/import.rs +++ b/lib/c-api/src/wasm_c_api/types/import.rs @@ -3,7 +3,6 @@ use std::ptr::NonNull; use wasmer::ImportType; // TODO: improve ownership in `importtype_t` (can we safely use `Box` here?) -/// cbindgen:ignore #[allow(non_camel_case_types)] pub struct wasm_importtype_t { pub(crate) module: NonNull, @@ -13,7 +12,6 @@ pub struct wasm_importtype_t { wasm_declare_boxed_vec!(importtype); -/// cbindgen:ignore #[no_mangle] pub extern "C" fn wasm_importtype_new( module: NonNull, @@ -27,19 +25,16 @@ pub extern "C" fn wasm_importtype_new( }) } -/// cbindgen:ignore #[no_mangle] pub extern "C" fn wasm_importtype_module(et: &'static wasm_importtype_t) -> &'static wasm_name_t { unsafe { et.module.as_ref() } } -/// cbindgen:ignore #[no_mangle] pub extern "C" fn wasm_importtype_name(et: &'static wasm_importtype_t) -> &'static wasm_name_t { unsafe { et.name.as_ref() } } -/// cbindgen:ignore #[no_mangle] pub extern "C" fn wasm_importtype_type( et: &'static wasm_importtype_t, @@ -47,7 +42,6 @@ pub extern "C" fn wasm_importtype_type( unsafe { et.extern_type.as_ref() } } -/// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn wasm_importtype_delete(_importtype: Option>) {} diff --git a/lib/c-api/src/wasm_c_api/types/memory.rs b/lib/c-api/src/wasm_c_api/types/memory.rs index 39456f87c..1daf70438 100644 --- a/lib/c-api/src/wasm_c_api/types/memory.rs +++ b/lib/c-api/src/wasm_c_api/types/memory.rs @@ -2,11 +2,9 @@ use super::wasm_externtype_t; use wasmer::{ExternType, MemoryType, Pages}; // opaque type wrapping `MemoryType` -/// cbindgen:ignore #[allow(non_camel_case_types)] #[derive(Clone, Debug)] pub struct wasm_memorytype_t { - /// cbindgen:ignore pub(crate) extern_: wasm_externtype_t, } @@ -24,7 +22,6 @@ impl wasm_memorytype_t { wasm_declare_vec!(memorytype); -/// cbindgen:ignore #[allow(non_camel_case_types)] #[derive(Copy, Clone, Debug)] pub struct wasm_limits_t { @@ -32,7 +29,6 @@ pub struct wasm_limits_t { pub(crate) max: u32, } -/// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn wasm_memorytype_new(limits: &wasm_limits_t) -> Box { let min_pages = Pages(limits.min as _); @@ -49,13 +45,11 @@ pub unsafe extern "C" fn wasm_memorytype_new(limits: &wasm_limits_t) -> Box>) {} // TODO: fix memory leak // this function leaks memory because the returned limits pointer is not owned -/// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn wasm_memorytype_limits(mt: &wasm_memorytype_t) -> *const wasm_limits_t { let md = mt.as_memorytype(); diff --git a/lib/c-api/src/wasm_c_api/types/mod.rs b/lib/c-api/src/wasm_c_api/types/mod.rs index c2212a760..c518bce80 100644 --- a/lib/c-api/src/wasm_c_api/types/mod.rs +++ b/lib/c-api/src/wasm_c_api/types/mod.rs @@ -25,15 +25,12 @@ pub type wasm_byte_t = u8; wasm_declare_vec!(byte); -/// cbindgen:ignore #[allow(non_camel_case_types)] pub type wasm_name_t = wasm_byte_vec_t; // opaque type over `ExternRef`? -/// cbindgen:ignore #[allow(non_camel_case_types)] pub struct wasm_ref_t; -/// cbindgen:ignore #[allow(non_camel_case_types)] pub type wasm_message_t = wasm_byte_vec_t; diff --git a/lib/c-api/src/wasm_c_api/types/mutability.rs b/lib/c-api/src/wasm_c_api/types/mutability.rs index 6611843d7..5bac0bc48 100644 --- a/lib/c-api/src/wasm_c_api/types/mutability.rs +++ b/lib/c-api/src/wasm_c_api/types/mutability.rs @@ -1,11 +1,9 @@ use std::convert::TryFrom; use wasmer::Mutability; -/// cbindgen:ignore #[allow(non_camel_case_types)] pub type wasm_mutability_t = u8; -/// cbindgen:ignore #[allow(non_camel_case_types)] #[derive(Debug, Clone, Copy, PartialEq, Eq)] #[repr(u8)] diff --git a/lib/c-api/src/wasm_c_api/types/table.rs b/lib/c-api/src/wasm_c_api/types/table.rs index 73455bede..e8973772e 100644 --- a/lib/c-api/src/wasm_c_api/types/table.rs +++ b/lib/c-api/src/wasm_c_api/types/table.rs @@ -1,16 +1,13 @@ use super::{wasm_externtype_t, wasm_limits_t, wasm_valtype_delete, wasm_valtype_t}; use wasmer::{ExternType, TableType}; -/// cbindgen:ignore #[allow(non_camel_case_types)] pub type wasm_table_size_t = u32; -/// cbindgen:ignore #[allow(non_camel_case_types)] #[derive(Clone, Debug)] #[repr(C)] pub struct wasm_tabletype_t { - /// cbindgen:ignore pub(crate) extern_: wasm_externtype_t, } @@ -28,7 +25,6 @@ impl wasm_tabletype_t { } } -/// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn wasm_tabletype_new( // own @@ -57,7 +53,6 @@ pub unsafe extern "C" fn wasm_tabletype_new( // TODO: fix memory leak // this function leaks memory because the returned limits pointer is not owned -/// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn wasm_tabletype_limits( tabletype: &wasm_tabletype_t, @@ -71,7 +66,6 @@ pub unsafe extern "C" fn wasm_tabletype_limits( // TODO: fix memory leak // this function leaks memory because the returned limits pointer is not owned -/// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn wasm_tabletype_element( tabletype: &wasm_tabletype_t, @@ -81,6 +75,5 @@ pub unsafe extern "C" fn wasm_tabletype_element( Box::into_raw(Box::new(tt.ty.into())) } -/// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn wasm_tabletype_delete(_tabletype: Option>) {} diff --git a/lib/c-api/src/wasm_c_api/types/value.rs b/lib/c-api/src/wasm_c_api/types/value.rs index 60dff16b0..542833638 100644 --- a/lib/c-api/src/wasm_c_api/types/value.rs +++ b/lib/c-api/src/wasm_c_api/types/value.rs @@ -2,7 +2,6 @@ use super::super::value::wasm_valkind_t; use std::convert::TryInto; use wasmer::ValType; -/// cbindgen:ignore #[allow(non_camel_case_types)] #[derive(Debug, Clone, Copy, PartialEq, Eq)] #[repr(u8)] @@ -43,7 +42,6 @@ impl From for ValType { } } -/// cbindgen:ignore #[allow(non_camel_case_types)] #[derive(Debug, Clone, Copy)] pub struct wasm_valtype_t { @@ -74,7 +72,6 @@ impl From for wasm_valtype_t { } } -/// cbindgen:ignore #[no_mangle] pub extern "C" fn wasm_valtype_new(kind: wasm_valkind_t) -> Option> { let kind_enum = kind.try_into().ok()?; @@ -82,11 +79,9 @@ pub extern "C" fn wasm_valtype_new(kind: wasm_valkind_t) -> Option>) {} -/// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn wasm_valtype_kind(valtype: *const wasm_valtype_t) -> wasm_valkind_t { if valtype.is_null() { diff --git a/lib/c-api/src/wasm_c_api/value.rs b/lib/c-api/src/wasm_c_api/value.rs index dd2254b10..cb427e78d 100644 --- a/lib/c-api/src/wasm_c_api/value.rs +++ b/lib/c-api/src/wasm_c_api/value.rs @@ -3,11 +3,9 @@ use std::convert::{TryFrom, TryInto}; use std::ptr::NonNull; use wasmer::Val; -/// cbindgen:ignore #[allow(non_camel_case_types)] pub type wasm_valkind_t = u8; -/// cbindgen:ignore #[allow(non_camel_case_types)] #[derive(Clone, Copy)] pub union wasm_val_inner { @@ -18,7 +16,6 @@ pub union wasm_val_inner { pub(crate) wref: *mut wasm_ref_t, } -/// cbindgen:ignore #[allow(non_camel_case_types)] #[repr(C)] pub struct wasm_val_t { @@ -35,7 +32,6 @@ impl Clone for wasm_val_t { } } -/// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn wasm_val_copy(out_ptr: *mut wasm_val_t, val: &wasm_val_t) { (*out_ptr).kind = val.kind; @@ -51,7 +47,6 @@ pub unsafe extern "C" fn wasm_val_copy(out_ptr: *mut wasm_val_t, val: &wasm_val_ }; } -/// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn wasm_val_delete(val: Option>) { if let Some(v_inner) = val { From 2fdd9ea692a2e1f66e3a8218857d712d277de1d9 Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Fri, 2 Oct 2020 10:10:24 +0200 Subject: [PATCH 122/281] feat(c-api) Simplify the `build.rs` script. --- lib/c-api/build.rs | 111 ++++++++++++++++++++------------------------- 1 file changed, 48 insertions(+), 63 deletions(-) diff --git a/lib/c-api/build.rs b/lib/c-api/build.rs index 6f6208f54..683c62f85 100644 --- a/lib/c-api/build.rs +++ b/lib/c-api/build.rs @@ -63,7 +63,7 @@ fn main() { build_wasmer_headers(&crate_dir, &out_dir); } -#[allow(unused)] +/// Build the header files for the `wasm_c_api` API. fn build_wasm_c_api_headers(crate_dir: &str, out_dir: &str) { let mut crate_header_file = PathBuf::from(crate_dir); crate_header_file.push("wasmer_wasm"); @@ -98,27 +98,16 @@ fn build_wasm_c_api_headers(crate_dir: &str, out_dir: &str) { "#, ); + let guard = "WASMER_WASM_H"; + // C bindings. { // Generate the bindings in the `OUT_DIR`. out_header_file.set_extension("h"); - #[allow(unused_mut)] - let mut builder = Builder::new() - .with_language(Language::C) - .with_crate(crate_dir) - .with_include_guard("WASMER_WASM_H") - .with_header(&pre_header) - .with_define("target_family", "windows", "_WIN32") - .with_define("target_arch", "x86_64", "ARCH_X86_64") - .with_define("feature", "jit", JIT_FEATURE_AS_C_DEFINE) - .with_define("feature", "compiler", COMPILER_FEATURE_AS_C_DEFINE) - .with_define("feature", "wasi", WASI_FEATURE_AS_C_DEFINE) - .with_define("feature", "emscripten", EMSCRIPTEN_FEATURE_AS_C_DEFINE) + // Build and generate the header file. + exclude_items_from_deprecated(new_builder(Language::C, crate_dir, guard, &pre_header)) .with_include("wasm.h") - .with_documentation(true); - builder = exclude_items_from_deprecated(builder); - builder .generate() .expect("Unable to generate C bindings") .write_to_file(out_header_file.as_path()); @@ -132,7 +121,7 @@ fn build_wasm_c_api_headers(crate_dir: &str, out_dir: &str) { } } -#[allow(unused)] +/// Build the header files for the `deprecated` API. fn build_wasmer_headers(crate_dir: &str, out_dir: &str) { let mut crate_header_file = PathBuf::from(crate_dir); crate_header_file.push("wasmer"); @@ -164,23 +153,15 @@ fn build_wasmer_headers(crate_dir: &str, out_dir: &str) { "#, ); + let guard = "WASMER_H"; + // C bindings. { // Generate the bindings in the `OUT_DIR`. out_header_file.set_extension("h"); - let mut builder = Builder::new() - .with_language(Language::C) - .with_crate(crate_dir) - .with_include_guard("WASMER_H") - .with_header(&pre_header) - .with_define("target_family", "windows", "_WIN32") - .with_define("target_arch", "x86_64", "ARCH_X86_64") - .with_define("feature", "wasi", WASI_FEATURE_AS_C_DEFINE) - .with_define("feature", "emscripten", EMSCRIPTEN_FEATURE_AS_C_DEFINE) - .with_documentation(true); - builder = exclude_items_from_wasm_c_api(builder); - builder + // Build and generate the header file. + exclude_items_from_wasm_c_api(new_builder(Language::C, crate_dir, guard, &pre_header)) .generate() .expect("Unable to generate C bindings") .write_to_file(out_header_file.as_path()); @@ -198,18 +179,8 @@ fn build_wasmer_headers(crate_dir: &str, out_dir: &str) { // Generate the bindings in the `OUT_DIR`. out_header_file.set_extension("hh"); - let mut builder = Builder::new() - .with_language(Language::Cxx) - .with_crate(crate_dir) - .with_include_guard("WASMER_H") - .with_header(&pre_header) - .with_define("target_family", "windows", "_WIN32") - .with_define("target_arch", "x86_64", "ARCH_X86_64") - .with_define("feature", "wasi", WASI_FEATURE_AS_C_DEFINE) - .with_define("feature", "emscripten", EMSCRIPTEN_FEATURE_AS_C_DEFINE) - .with_documentation(true); - builder = exclude_items_from_wasm_c_api(builder); - builder + // Build and generate the header file. + exclude_items_from_wasm_c_api(new_builder(Language::Cxx, crate_dir, guard, &pre_header)) .generate() .expect("Unable to generate C++ bindings") .write_to_file(out_header_file.as_path()); @@ -223,11 +194,28 @@ fn build_wasmer_headers(crate_dir: &str, out_dir: &str) { } } -fn exclude_items_from_deprecated(mut builder: Builder) -> Builder { - // List of all functions to exclude given by: - // - // `rg 'extern "C" fn' deprecated/` builder = builder - builder = builder +/// Create a fresh new `Builder`, already pre-configured. +fn new_builder(language: Language, crate_dir: &str, include_guard: &str, header: &str) -> Builder { + Builder::new() + .with_language(language) + .with_crate(crate_dir) + .with_include_guard(include_guard) + .with_header(header) + .with_documentation(true) + .with_define("target_family", "windows", "_WIN32") + .with_define("target_arch", "x86_64", "ARCH_X86_64") + .with_define("feature", "jit", JIT_FEATURE_AS_C_DEFINE) + .with_define("feature", "compiler", COMPILER_FEATURE_AS_C_DEFINE) + .with_define("feature", "wasi", WASI_FEATURE_AS_C_DEFINE) + .with_define("feature", "emscripten", EMSCRIPTEN_FEATURE_AS_C_DEFINE) +} + +/// Exclude types and functions from the `deprecated` API. +fn exclude_items_from_deprecated(builder: Builder) -> Builder { + builder + // List of all functions to exclude given by: + // + // `rg 'extern "C" fn' deprecated/` builder = builder .exclude_item("wasmer_compile") .exclude_item("wasmer_emscripten_call_main") .exclude_item("wasmer_emscripten_destroy_globals") @@ -318,12 +306,10 @@ fn exclude_items_from_deprecated(mut builder: Builder) -> Builder { .exclude_item("wasmer_wasi_generate_default_import_object") .exclude_item("wasmer_wasi_generate_import_object") .exclude_item("wasmer_wasi_generate_import_object_for_version") - .exclude_item("wasmer_wasi_get_version"); - - // List of all structs and enums to exclude given by: - // - // `rg 'pub (enum|struct|union)' deprecated/` - builder = builder + .exclude_item("wasmer_wasi_get_version") + // List of all structs and enums to exclude given by: + // + // `rg 'pub (enum|struct|union)' deprecated/` .exclude_item("NamedExportDescriptors(Vec)") .exclude_item("NamedImportDescriptors(Vec)") .exclude_item("Version") @@ -358,16 +344,17 @@ fn exclude_items_from_deprecated(mut builder: Builder) -> Builder { .exclude_item("wasmer_trampoline_callable_t") .exclude_item("wasmer_value_t") .exclude_item("wasmer_value_tag") - .exclude_item("wasmer_wasi_map_dir_entry_t"); - - builder + .exclude_item("wasmer_wasi_map_dir_entry_t") } -fn exclude_items_from_wasm_c_api(mut builder: Builder) -> Builder { - // All items defined in `wasm.h` are ignored by cbindgen, because - // we don't want duplications. We must exclude extra non-standard - // items, like the ones from the WASI API. - builder = builder +/// Excludes non-standard types and functions of the `wasm_c_api` API. +/// +/// All items defined in `wasm.h` are ignored by cbindgen already +/// based on `cbindgen:ignore` instructions, because we don't want +/// duplications. We must exclude extra non-standard items, like the +/// ones from the WASI API. +fn exclude_items_from_wasm_c_api(builder: Builder) -> Builder { + builder .exclude_item("wasi_config_arg") .exclude_item("wasi_config_env") .exclude_item("wasi_config_inherit_stderr") @@ -386,7 +373,5 @@ fn exclude_items_from_wasm_c_api(mut builder: Builder) -> Builder { .exclude_item("wasi_get_imports_inner") .exclude_item("wasi_get_start_function") .exclude_item("wasi_get_wasi_version") - .exclude_item("wasi_version_t"); - - builder + .exclude_item("wasi_version_t") } From 7f4862117f32391c0fd613caf217b0b3f86f0b06 Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Fri, 2 Oct 2020 10:40:26 +0200 Subject: [PATCH 123/281] doc(c-api) Write a quick introduction to the crate. --- lib/c-api/src/lib.rs | 19 +++++++++++++++++++ lib/c-api/src/wasm_c_api/mod.rs | 2 +- 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/lib/c-api/src/lib.rs b/lib/c-api/src/lib.rs index bb52ec511..23e8a5a6d 100644 --- a/lib/c-api/src/lib.rs +++ b/lib/c-api/src/lib.rs @@ -1,3 +1,22 @@ +//! Wasmer C API. +//! +//! [Wasmer](https://github.com/wasmerio/wasmer) is the leading +//! WebAssembly runtime. This crate exposes the C and C++ bindings. +//! +//! This crate provides 2 API: +//! +//! * `deprecated`, which is the old one, and is represented by the +//! `wasmer.h` and the `wasmer.hh` C header files, +//! * `wasm_c_api`, which is the new, standard C API, and is +//! represented by the `wasmer_wasm.h` C header file. +//! +//! The `wasm_c_api` follows the [official WebAssembly C and C++ +//! API](https://github.com/WebAssembly/wasm-c-api). It provides +//! however some extensions, like the `wasi_*` types and functions, +//! which aren't yet defined by the standard. The `wasmer_wasm.h` +//! header file already depends on the `wasm.h` file. A copy lands in +//! this repository for the sake of simplicity. + #![doc(html_favicon_url = "https://wasmer.io/static/icons/favicon.ico")] #![doc(html_logo_url = "https://avatars3.githubusercontent.com/u/44205449?s=200&v=4")] // temporary while in transition diff --git a/lib/c-api/src/wasm_c_api/mod.rs b/lib/c-api/src/wasm_c_api/mod.rs index 537e32349..9d9d26485 100644 --- a/lib/c-api/src/wasm_c_api/mod.rs +++ b/lib/c-api/src/wasm_c_api/mod.rs @@ -1,4 +1,4 @@ -//! entrypoints for the standard C API +//! Entrypoints for the standard C API #[macro_use] pub mod macros; From e7d6af01e6a4d892a5ade4ddd0d7d511f6b0604c Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Fri, 2 Oct 2020 11:09:20 +0200 Subject: [PATCH 124/281] feat(c-api) Remove the `deprecated` feature. This feature is no longer necessary. The `build.rs` no longer uses it. The overhead of including the deprecated symbol inside the dylib is acceptable. It simplifies the overall build system. --- Makefile | 6 +++--- lib/c-api/Cargo.toml | 4 ---- lib/c-api/src/lib.rs | 1 - 3 files changed, 3 insertions(+), 8 deletions(-) diff --git a/Makefile b/Makefile index 2f1482b31..3cb273b8a 100644 --- a/Makefile +++ b/Makefile @@ -76,15 +76,15 @@ build-capi: build-capi-cranelift build-capi-singlepass: cargo build --manifest-path lib/c-api/Cargo.toml --release \ - --no-default-features --features jit,singlepass,wasi,deprecated + --no-default-features --features jit,singlepass,wasi build-capi-cranelift: cargo build --manifest-path lib/c-api/Cargo.toml --release \ - --no-default-features --features jit,cranelift,wasi,deprecated + --no-default-features --features jit,cranelift,wasi build-capi-llvm: cargo build --manifest-path lib/c-api/Cargo.toml --release \ - --no-default-features --features jit,llvm,wasi,deprecated + --no-default-features --features jit,llvm,wasi ########### diff --git a/lib/c-api/Cargo.toml b/lib/c-api/Cargo.toml index 58cd9dd81..4bc32e47f 100644 --- a/lib/c-api/Cargo.toml +++ b/lib/c-api/Cargo.toml @@ -42,7 +42,6 @@ paste = "0.1" default = [ "cranelift", "wasi", - "deprecated", ] wasi = ["wasmer-wasi", "typetag", "serde"] engine = [] @@ -71,9 +70,6 @@ llvm = [ "compiler", ] -# Include the deprecated Wasmer C API. -deprecated = [] - # Deprecated feature. # TODO: Port this feature. #emscripten = ["wasmer-emscripten"] diff --git a/lib/c-api/src/lib.rs b/lib/c-api/src/lib.rs index 23e8a5a6d..b4e5ff502 100644 --- a/lib/c-api/src/lib.rs +++ b/lib/c-api/src/lib.rs @@ -30,7 +30,6 @@ unreachable_patterns )] -#[cfg(feature = "deprecated")] pub mod deprecated; pub mod error; mod ordered_resolver; From 92ca7899f532de348c99de7253d87e0cb8adb848 Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Fri, 2 Oct 2020 11:15:37 +0200 Subject: [PATCH 125/281] chore(c-api) Use canonical path to `wasm*.h` headers. --- lib/c-api/tests/deprecated/test-context.c | 2 +- lib/c-api/tests/deprecated/test-emscripten-import-object.c | 2 +- lib/c-api/tests/deprecated/test-exported-memory.c | 2 +- lib/c-api/tests/deprecated/test-exports.c | 2 +- lib/c-api/tests/deprecated/test-globals.c | 2 +- lib/c-api/tests/deprecated/test-import-function-callinfo.c | 2 +- lib/c-api/tests/deprecated/test-import-function.c | 2 +- lib/c-api/tests/deprecated/test-import-object.c | 2 +- lib/c-api/tests/deprecated/test-import-trap.c | 2 +- lib/c-api/tests/deprecated/test-imports.c | 2 +- lib/c-api/tests/deprecated/test-instantiate.c | 2 +- lib/c-api/tests/deprecated/test-memory.c | 2 +- lib/c-api/tests/deprecated/test-module-exports.c | 2 +- lib/c-api/tests/deprecated/test-module-import-instantiate.c | 2 +- lib/c-api/tests/deprecated/test-module-imports.c | 2 +- lib/c-api/tests/deprecated/test-module-serialize.c | 2 +- lib/c-api/tests/deprecated/test-module.c | 2 +- lib/c-api/tests/deprecated/test-tables.c | 2 +- lib/c-api/tests/deprecated/test-validate.c | 2 +- lib/c-api/tests/deprecated/test-wasi-import-object.c | 2 +- lib/c-api/tests/wasm_c_api/test-early-exit.c | 2 +- lib/c-api/tests/wasm_c_api/test-wasi.c | 2 +- 22 files changed, 22 insertions(+), 22 deletions(-) diff --git a/lib/c-api/tests/deprecated/test-context.c b/lib/c-api/tests/deprecated/test-context.c index 44abec1ee..11512ea4b 100644 --- a/lib/c-api/tests/deprecated/test-context.c +++ b/lib/c-api/tests/deprecated/test-context.c @@ -1,5 +1,5 @@ #include -#include "../../wasmer.h" +#include "wasmer.h" #include #include #include diff --git a/lib/c-api/tests/deprecated/test-emscripten-import-object.c b/lib/c-api/tests/deprecated/test-emscripten-import-object.c index 91e018d2b..b1524ae92 100644 --- a/lib/c-api/tests/deprecated/test-emscripten-import-object.c +++ b/lib/c-api/tests/deprecated/test-emscripten-import-object.c @@ -1,5 +1,5 @@ #include -#include "../../wasmer.h" +#include "wasmer.h" #include #include #include diff --git a/lib/c-api/tests/deprecated/test-exported-memory.c b/lib/c-api/tests/deprecated/test-exported-memory.c index d4537f1c1..103870b89 100644 --- a/lib/c-api/tests/deprecated/test-exported-memory.c +++ b/lib/c-api/tests/deprecated/test-exported-memory.c @@ -1,5 +1,5 @@ #include -#include "../../wasmer.h" +#include "wasmer.h" #include #include #include diff --git a/lib/c-api/tests/deprecated/test-exports.c b/lib/c-api/tests/deprecated/test-exports.c index 202156f37..cc0d08eff 100644 --- a/lib/c-api/tests/deprecated/test-exports.c +++ b/lib/c-api/tests/deprecated/test-exports.c @@ -1,6 +1,6 @@ #include #include -#include "../../wasmer.h" +#include "wasmer.h" #include #include #include diff --git a/lib/c-api/tests/deprecated/test-globals.c b/lib/c-api/tests/deprecated/test-globals.c index 50e354e1c..9853d5112 100644 --- a/lib/c-api/tests/deprecated/test-globals.c +++ b/lib/c-api/tests/deprecated/test-globals.c @@ -1,5 +1,5 @@ #include -#include "../../wasmer.h" +#include "wasmer.h" #include #include diff --git a/lib/c-api/tests/deprecated/test-import-function-callinfo.c b/lib/c-api/tests/deprecated/test-import-function-callinfo.c index 1d30db112..beeff2d15 100644 --- a/lib/c-api/tests/deprecated/test-import-function-callinfo.c +++ b/lib/c-api/tests/deprecated/test-import-function-callinfo.c @@ -1,5 +1,5 @@ #include -#include "../../wasmer.h" +#include "wasmer.h" #include #include #include diff --git a/lib/c-api/tests/deprecated/test-import-function.c b/lib/c-api/tests/deprecated/test-import-function.c index 526d18eaa..a8640d4ef 100644 --- a/lib/c-api/tests/deprecated/test-import-function.c +++ b/lib/c-api/tests/deprecated/test-import-function.c @@ -1,5 +1,5 @@ #include -#include "../../wasmer.h" +#include "wasmer.h" #include #include #include diff --git a/lib/c-api/tests/deprecated/test-import-object.c b/lib/c-api/tests/deprecated/test-import-object.c index 84f04b1df..61a81a648 100644 --- a/lib/c-api/tests/deprecated/test-import-object.c +++ b/lib/c-api/tests/deprecated/test-import-object.c @@ -1,5 +1,5 @@ #include -#include "../../wasmer.h" +#include "wasmer.h" #include #include #include diff --git a/lib/c-api/tests/deprecated/test-import-trap.c b/lib/c-api/tests/deprecated/test-import-trap.c index 11294d220..8854b59e6 100644 --- a/lib/c-api/tests/deprecated/test-import-trap.c +++ b/lib/c-api/tests/deprecated/test-import-trap.c @@ -1,5 +1,5 @@ #include -#include "../../wasmer.h" +#include "wasmer.h" #include #include #include diff --git a/lib/c-api/tests/deprecated/test-imports.c b/lib/c-api/tests/deprecated/test-imports.c index 203d56f67..757c471cc 100644 --- a/lib/c-api/tests/deprecated/test-imports.c +++ b/lib/c-api/tests/deprecated/test-imports.c @@ -1,5 +1,5 @@ #include -#include "../../wasmer.h" +#include "wasmer.h" #include #include #include diff --git a/lib/c-api/tests/deprecated/test-instantiate.c b/lib/c-api/tests/deprecated/test-instantiate.c index 84f5e4210..a54b6aff0 100644 --- a/lib/c-api/tests/deprecated/test-instantiate.c +++ b/lib/c-api/tests/deprecated/test-instantiate.c @@ -1,5 +1,5 @@ #include -#include "../../wasmer.h" +#include "wasmer.h" #include #include #include diff --git a/lib/c-api/tests/deprecated/test-memory.c b/lib/c-api/tests/deprecated/test-memory.c index 8e1576a75..46186567f 100644 --- a/lib/c-api/tests/deprecated/test-memory.c +++ b/lib/c-api/tests/deprecated/test-memory.c @@ -1,5 +1,5 @@ #include -#include "../../wasmer.h" +#include "wasmer.h" #include #include #include diff --git a/lib/c-api/tests/deprecated/test-module-exports.c b/lib/c-api/tests/deprecated/test-module-exports.c index 1dc0eb3e0..6920dedaf 100644 --- a/lib/c-api/tests/deprecated/test-module-exports.c +++ b/lib/c-api/tests/deprecated/test-module-exports.c @@ -1,5 +1,5 @@ #include -#include "../../wasmer.h" +#include "wasmer.h" #include #include diff --git a/lib/c-api/tests/deprecated/test-module-import-instantiate.c b/lib/c-api/tests/deprecated/test-module-import-instantiate.c index 448634d57..f86158a5c 100644 --- a/lib/c-api/tests/deprecated/test-module-import-instantiate.c +++ b/lib/c-api/tests/deprecated/test-module-import-instantiate.c @@ -1,5 +1,5 @@ #include -#include "../../wasmer.h" +#include "wasmer.h" #include #include #include diff --git a/lib/c-api/tests/deprecated/test-module-imports.c b/lib/c-api/tests/deprecated/test-module-imports.c index 21a41a744..f9c398776 100644 --- a/lib/c-api/tests/deprecated/test-module-imports.c +++ b/lib/c-api/tests/deprecated/test-module-imports.c @@ -1,5 +1,5 @@ #include -#include "../../wasmer.h" +#include "wasmer.h" #include #include diff --git a/lib/c-api/tests/deprecated/test-module-serialize.c b/lib/c-api/tests/deprecated/test-module-serialize.c index dcab39526..85eeed61b 100644 --- a/lib/c-api/tests/deprecated/test-module-serialize.c +++ b/lib/c-api/tests/deprecated/test-module-serialize.c @@ -1,5 +1,5 @@ #include -#include "../../wasmer.h" +#include "wasmer.h" #include #include diff --git a/lib/c-api/tests/deprecated/test-module.c b/lib/c-api/tests/deprecated/test-module.c index 9f818ffd9..c099d1721 100644 --- a/lib/c-api/tests/deprecated/test-module.c +++ b/lib/c-api/tests/deprecated/test-module.c @@ -1,5 +1,5 @@ #include -#include "../../wasmer.h" +#include "wasmer.h" #include #include diff --git a/lib/c-api/tests/deprecated/test-tables.c b/lib/c-api/tests/deprecated/test-tables.c index 8d001de50..3bf93648d 100644 --- a/lib/c-api/tests/deprecated/test-tables.c +++ b/lib/c-api/tests/deprecated/test-tables.c @@ -1,5 +1,5 @@ #include -#include "../../wasmer.h" +#include "wasmer.h" #include #include diff --git a/lib/c-api/tests/deprecated/test-validate.c b/lib/c-api/tests/deprecated/test-validate.c index e4d80735a..91ecbc1e8 100644 --- a/lib/c-api/tests/deprecated/test-validate.c +++ b/lib/c-api/tests/deprecated/test-validate.c @@ -1,5 +1,5 @@ #include -#include "../../wasmer.h" +#include "wasmer.h" #include #include diff --git a/lib/c-api/tests/deprecated/test-wasi-import-object.c b/lib/c-api/tests/deprecated/test-wasi-import-object.c index 0dacda8cb..fc3c0f7fe 100644 --- a/lib/c-api/tests/deprecated/test-wasi-import-object.c +++ b/lib/c-api/tests/deprecated/test-wasi-import-object.c @@ -1,5 +1,5 @@ #include -#include "../../wasmer.h" +#include "wasmer.h" #include #include #include diff --git a/lib/c-api/tests/wasm_c_api/test-early-exit.c b/lib/c-api/tests/wasm_c_api/test-early-exit.c index 60730bd74..bbc70af7d 100644 --- a/lib/c-api/tests/wasm_c_api/test-early-exit.c +++ b/lib/c-api/tests/wasm_c_api/test-early-exit.c @@ -3,7 +3,7 @@ #include #include -#include "../../wasmer_wasm.h" +#include "wasmer_wasm.h" #define own diff --git a/lib/c-api/tests/wasm_c_api/test-wasi.c b/lib/c-api/tests/wasm_c_api/test-wasi.c index ddc5748e4..81c22fd92 100644 --- a/lib/c-api/tests/wasm_c_api/test-wasi.c +++ b/lib/c-api/tests/wasm_c_api/test-wasi.c @@ -3,7 +3,7 @@ #include #include -#include "../../wasmer_wasm.h" +#include "wasmer_wasm.h" #define BUF_SIZE 128 #define own From a593c889da411680b1030de65cd0edfb61a35e92 Mon Sep 17 00:00:00 2001 From: Nick Lewycky Date: Fri, 2 Oct 2020 15:26:11 -0700 Subject: [PATCH 126/281] Stack probes are not ordinary functions. --- lib/vm/src/libcalls.rs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/lib/vm/src/libcalls.rs b/lib/vm/src/libcalls.rs index da8604b3d..1750e7a85 100644 --- a/lib/vm/src/libcalls.rs +++ b/lib/vm/src/libcalls.rs @@ -396,11 +396,10 @@ pub unsafe extern "C" fn wasmer_raise_trap(trap_code: TrapCode) -> ! { /// /// # Safety /// -/// To be defined (TODO) +/// This function does not follow the standard function ABI, and is called as +/// part of the function prologue. #[no_mangle] -pub unsafe extern "C" fn wasmer_probestack() { - PROBESTACK(); -} +pub static wasmer_probestack: unsafe extern "C" fn() = PROBESTACK; /// The name of a runtime library routine. /// From 3845e5fd67b2b4e7b9a0d102c154d6dd07c777da Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Fri, 2 Oct 2020 15:30:13 -0700 Subject: [PATCH 127/281] Clean up binary files from C API refactor --- lib/c-api/tests/deprecated/.gitignore | 3 ++- lib/c-api/tests/wasm_c_api/.gitignore | 4 +++- lib/c-api/tests/wasm_c_api/wasm-c-api-callback | Bin 19008 -> 0 bytes lib/c-api/tests/wasm_c_api/wasm-c-api-global | Bin 23088 -> 0 bytes lib/c-api/tests/wasm_c_api/wasm-c-api-hello | Bin 18520 -> 0 bytes lib/c-api/tests/wasm_c_api/wasm-c-api-memory | Bin 19456 -> 0 bytes lib/c-api/tests/wasm_c_api/wasm-c-api-reflect | Bin 19956 -> 0 bytes lib/c-api/tests/wasm_c_api/wasm-c-api-serialize | Bin 18680 -> 0 bytes 8 files changed, 5 insertions(+), 2 deletions(-) delete mode 100755 lib/c-api/tests/wasm_c_api/wasm-c-api-callback delete mode 100755 lib/c-api/tests/wasm_c_api/wasm-c-api-global delete mode 100755 lib/c-api/tests/wasm_c_api/wasm-c-api-hello delete mode 100755 lib/c-api/tests/wasm_c_api/wasm-c-api-memory delete mode 100755 lib/c-api/tests/wasm_c_api/wasm-c-api-reflect delete mode 100755 lib/c-api/tests/wasm_c_api/wasm-c-api-serialize diff --git a/lib/c-api/tests/deprecated/.gitignore b/lib/c-api/tests/deprecated/.gitignore index 3d28fe7a6..e1956243e 100644 --- a/lib/c-api/tests/deprecated/.gitignore +++ b/lib/c-api/tests/deprecated/.gitignore @@ -32,6 +32,7 @@ test-emscripten-import-object # ignore wasm-c-api binaries wasm-c-api-* +test-* # Unignore files ending with `.c` (i.e. `wasm-c-api-wasi.c`) -!*.c \ No newline at end of file +!*.c diff --git a/lib/c-api/tests/wasm_c_api/.gitignore b/lib/c-api/tests/wasm_c_api/.gitignore index a0b8069bc..4340312fa 100644 --- a/lib/c-api/tests/wasm_c_api/.gitignore +++ b/lib/c-api/tests/wasm_c_api/.gitignore @@ -11,5 +11,7 @@ CTestTestfile.cmake _deps rust-build +wasm-c-api-* +test-* # Unignore files ending with `.c` (i.e. `wasm-c-api-wasi.c`) -!*.c \ No newline at end of file +!*.c diff --git a/lib/c-api/tests/wasm_c_api/wasm-c-api-callback b/lib/c-api/tests/wasm_c_api/wasm-c-api-callback deleted file mode 100755 index 0d13b4ebaa1fb423817d1fcd2fd866e9a95366cd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 19008 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 diff --git a/lib/c-api/tests/wasm_c_api/wasm-c-api-global b/lib/c-api/tests/wasm_c_api/wasm-c-api-global deleted file mode 100755 index db530731c5e475ab440235f15421717f1237eb80..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 23088 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%0DF2aZ#z9S7Tmsi<{{wq(;6{Ij6KvE3Iz;!4aq^ zMXnpAJKu)fDBW(9cHA^R^((h%z__K@!hXpc2VWlpc=mi{Et-})dfHl+90CV^NvEjZ z&*j2o<%bX=u&b3(#o+GFU#;-vn!bCdmL2(!5L3&JN;)LzmnD5c(ibH?Ch6BC{ko(t zNjfa)aY?@^>9-^uk@SS5Cnf!!q@$94U(!>Oo|g2Cq-Q1lk)*FlItIGAeBV#dtlKuV zYyy|vP$GfoC$1qU2~K+AO>(c0yG-t<*RKk`y;sZQQOA5$WV7Qwx_MF zZH`zQGA!Fphn`Mn?fB9;VpA&VB%^lnIcQ0R&FN@dS|n4^Y`+xY-Kd>z<0}x6g@Z^o zo6d%8t=E^1=WPp~)~EY2NjaDj>EV=i%-2c%tQB=Q5?*`Q)%Z50a!xdbkYv{_JSA_T z0B?~4PBt2oM%IB$I_oqHAC1MVT#kdO&KxYfiTL{%n$FrSJTX}M>B*-sS~>;oZHc@i z2ac!rr{u63(kTnMmhZ3do=2AY7Hcfub3crhmG7uo$m8b5JE11L^TD;FN|o^hK^tTs z$Uu;RAOk@Lf(!&12r>|4Ajm+Ffgl4x27(N{zcWz5p|z?1Bsg83-~EWFW{ukbxirK?Z^h1Q`f25M&_8z<-y4dH0Lm{D$_fPLrRm<6MUs zOYAXw^U-WvJdqVco&4BVek5;pbV?cPw+C6*J@bnAVZrJE!%f zto``FJ?Wi7vE)#Or)H&klPRmtL6@%w<{WcpReZp)vMDo~GkHLRUAui%U3`Fs`!)-kNfa%efWkC&sNT={ucQ#k7BAn7@~Ce z@Ma(G_Tjt_mwfoR55MZe7kv14KKzyszvIITv2qYq*AGX11+Noa65@7L9LJKsb-?fS z??mPA6!6R>uaJ4D{2djXBNTU|&PV0-at|sG-z`Mt3105IJgS99mI9Ae1%7HngivRr zE=B!+jv2x)QB1#w_&X+cx^@ql@*ZmVPa*gH28sIL;r$cP+rQrU^_H(UdvBY+^#<>g z^0sf>+Lc1%rrsdqHlhWM8+n7UZVOj(-{xH>l-qV4)*E)6q&B2H(pR@d*OcT=R#WtE z%1W^+^>$;QxMttD|0*>tt0^_?xJpNfYAUzhW2gQ5SH{)Z!QN~)+j03wP5k5D7sY?) F{{S^Fb+rHh diff --git a/lib/c-api/tests/wasm_c_api/wasm-c-api-memory b/lib/c-api/tests/wasm_c_api/wasm-c-api-memory deleted file mode 100755 index 094ff5d0ebe30e7b37bfce5e84f6a5f86b982dc7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 19456 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 JC~m66p8*uMvd91c diff --git a/lib/c-api/tests/wasm_c_api/wasm-c-api-serialize b/lib/c-api/tests/wasm_c_api/wasm-c-api-serialize deleted file mode 100755 index f9c5bb1e7939ac5f34c65766f04b304872ed26aa..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 18680 zcmeHPZH!da89pnB2+Hy$rGAe1MJ?{^QfyZ1(m{6gk|JV(f}7II-I)tBb#`W)xdXc< z+pI3ra66s2wx;2SKd5P1QcZ)2T4RbKf$HK9OHI?z)|!o}_HIKBp-oHrA$^{6&YijU zE;i|}Cgz@S&iirR_j%8G&;3~LJ#&BYk3WBOnGhYbgbjrB!KRnvOl}v~8n!yFP`< zpu0I+*-+N3Qp^@(iczg;R-M{lwWW&UeRz$+`-!&jW#3`0#+#!R3eU{hg|c0NE{gZe zwF+;woU{;>nfF$iF}_UIspN}$v_TZ_t?Lxt?=>FfUh$?QlW3z-F{r{FkVf8m=QO9sAJ+5htWoqOvK zkFAC-fhybMr9x8;+N#Ms$Hojb0hn# zVzS@fYZpr8A-m`#w_DXAyOP|eh+|du*iN!y7i_C)C$o0B${DC$Gh3YuAM|k< zuNT#i*OBc&>N?tUhwYY;s$&mz-5d18Wn>I<2;`}hu?opj*+~`(dxscQhPV|i=bgg3 zah*S-Wv*jf;ta$Yh%*ppAkILXfj9$k2I36F8Hh6wXCTf%oPjt4aR&bP3~V#p_l@y0 z3Bw&dZ@9IyMze1_o>d+Z-qUz24QT+9n?3`@I21i6-8bE|XSk<~@e_%i$0wx!<7cK2 z*=St436E@yhA`ap`8U#MI2v~p#9yc{ zj=8TRz~rlZKIXkZS4eJsE0GS<;H3Lj&)dK|#t!dEX;C|7G)IrP_06<;S~Orr)DrG2OOJI!9J13dGlrni hhgKoW_kbNr3VQ&SQX5Ssk@LNR!Ivrf{jm3g{}J;?@Pl4W1z)U8EJ$ws9zxA#hnqftxt~JT4j9d=p87ZR zk172a^as4E^8OQ+8S8cvrN-!(Tkj>pT8KR-jpnwqz&WdNCcNzupgs%}WBe#dd!%nD zpxKf^gq_E|yFfbU@9w-|KNule z*O%t#S?}ji;INtUex?{)ZE8~mB z=C+VqP3}>0T-aQL-1X$1CAX9u1}diKk>jKPX+iE*a)0{>+~>%hA(tZe9=Qj|ohCOx z?k#ZZtwI6s3KN4?=8>+hu6bf@!mta4Qeu0lQpnyoPi!dWoxD}ZKL#slu(4!irANMK zRYs%=FE*r!-Nn}wq5_a~rBbRS3fgw4l&uwPpsgQ%W25=Ty)-L)d3m5NMKuI8wrm-ZE9*#1({##+kv zS9s4OOOWCi5`53S29%ZWs9DJ4yumx64!rZh@v2IT@f9(RGZ1GW&On@jI0JD8;ta$Y zh%*ppAkILXfj9$k20qytIH32Be@D}2H2tBbM>Ks^(-WFLj|UKZknpmm$25IY(_d-& zuBM)*=QRD7rgJpjLQSvM^kz-FH0{;&UQIV@`V~!gY5H|d9ZkQX=_h*?qzv}jJ~414?l3v`@39h z8Ord@?Bbq$(GCD?j`YBtF?Y1o!;W1knpV~11`T%Yigbksl=FLOPB(n30049>hq}1$ zgWBPcwmq}4j!=gl*MX4M87T+nGBLALyB%!xsNF7^pxdFDoqAIX$9H&UuLeER>QS3! z0$F`!W|zOgM=sm3XupP>jOs&Pr&_&Lr&I|};dG=&!%el+d#!>@78eVhrae@4Mld~= z4impkpJfi^uvT`ahGQ&;BNT^u55D10D4G7=B5~)Cl`o3Bx!GoxnCe1vC@H|C4)J%? z1JEzP1F>WJdlB61wE!Ld@A>K0*}-34tLJ9Rq^$Ps@HrZ{dUb-~@6Rc(LItIpENjsQ z<%c5j!x4E`MCSJ+g8s#bT#Lw~O6E{x`7T-rE&0WWJQgCP*x)Pp ztq2}Vm!o34m;9CjzXxz7D!+rk?Vvn@7NPPxElW_BqF#l{<;zt_S7!7ZRv9qOL&2es6IT>i;8l0$;wEdCu{>DZz8jl;>RN&Lr Date: Fri, 2 Oct 2020 15:33:36 -0700 Subject: [PATCH 128/281] Add a changelog entry. --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 267fd762c..d195b62b7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ # Changelog ## **[Unreleased]** +- [#1671](https://github.com/wasmerio/wasmer/pull/1671) Fix probestack firing inappropriately, and sometimes over/under allocating stack. - [#1657](https://github.com/wasmerio/wasmer/pull/1657) Implement `wasm_trap_t` and `wasm_frame_t` for Wasm C API; add examples in Rust and C of exiting early with a host function. - [#1645](https://github.com/wasmerio/wasmer/pull/1645) Move the install script to https://github.com/wasmerio/wasmer-install From 34e613957030f6d2b5aa0b6c55f6f0ddf2842f22 Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Fri, 2 Oct 2020 16:24:46 -0700 Subject: [PATCH 129/281] Add conversion logic for boxed_vec, simplify vec creation code --- lib/c-api/src/wasm_c_api/macros.rs | 47 +++++++++++++++++++++++------- lib/c-api/src/wasm_c_api/module.rs | 32 +++++--------------- 2 files changed, 45 insertions(+), 34 deletions(-) diff --git a/lib/c-api/src/wasm_c_api/macros.rs b/lib/c-api/src/wasm_c_api/macros.rs index 2f723206c..0231205e3 100644 --- a/lib/c-api/src/wasm_c_api/macros.rs +++ b/lib/c-api/src/wasm_c_api/macros.rs @@ -8,16 +8,6 @@ macro_rules! wasm_declare_vec_inner { // TODO: actually implement this [](out, 0); } - - #[no_mangle] - pub unsafe extern "C" fn [](ptr: *mut []) { - let vec = &mut *ptr; - if !vec.data.is_null() { - Vec::from_raw_parts(vec.data, vec.size, vec.size); - vec.data = ::std::ptr::null_mut(); - vec.size = 0; - } - } } } } @@ -96,6 +86,17 @@ macro_rules! wasm_declare_vec { (*out).size = length; ::std::mem::forget(bytes); } + + + #[no_mangle] + pub unsafe extern "C" fn [](ptr: *mut []) { + let vec = &mut *ptr; + if !vec.data.is_null() { + Vec::from_raw_parts(vec.data, vec.size, vec.size); + vec.data = ::std::ptr::null_mut(); + vec.size = 0; + } + } } wasm_declare_vec_inner!($name); @@ -113,6 +114,21 @@ macro_rules! wasm_declare_boxed_vec { pub data: *mut *mut [], } + impl<'a> From]>>> for [] { + fn from(other: Vec]>>) -> Self { + let boxed_slice: Box<[Box<[]>]> = other.into_boxed_slice(); + let mut boxed_slice: Box<[*mut []]> = unsafe { ::std::mem::transmute(boxed_slice) }; + let size = boxed_slice.len(); + let data = boxed_slice.as_mut_ptr(); + + ::std::mem::forget(boxed_slice); + Self { + size, + data, + } + } + } + // TODO: do this properly impl [] { pub unsafe fn into_slice(&self) -> Option<&[*mut []]>{ @@ -146,6 +162,17 @@ macro_rules! wasm_declare_boxed_vec { (*out).size = length; ::std::mem::forget(bytes); } + + #[no_mangle] + pub unsafe extern "C" fn [](ptr: *mut []) { + let vec = &mut *ptr; + if !vec.data.is_null() { + let data: Vec<*mut []> = Vec::from_raw_parts(vec.data, vec.size, vec.size); + let data: Vec]>> = ::std::mem::transmute(data); + vec.data = ::std::ptr::null_mut(); + vec.size = 0; + } + } } wasm_declare_vec_inner!($name); diff --git a/lib/c-api/src/wasm_c_api/module.rs b/lib/c-api/src/wasm_c_api/module.rs index b2dbc002f..206d97382 100644 --- a/lib/c-api/src/wasm_c_api/module.rs +++ b/lib/c-api/src/wasm_c_api/module.rs @@ -38,18 +38,14 @@ pub unsafe extern "C" fn wasm_module_exports( module: &wasm_module_t, out: &mut wasm_exporttype_vec_t, ) { - let mut exports = module + let exports = module .inner .exports() .map(Into::into) .map(Box::new) - .map(Box::into_raw) - .collect::>(); + .collect::>>(); - debug_assert_eq!(exports.len(), exports.capacity()); - out.size = exports.len(); - out.data = exports.as_mut_ptr(); - mem::forget(exports); + *out = exports.into(); } #[no_mangle] @@ -57,18 +53,14 @@ pub unsafe extern "C" fn wasm_module_imports( module: &wasm_module_t, out: &mut wasm_importtype_vec_t, ) { - let mut imports = module + let imports = module .inner .imports() .map(Into::into) .map(Box::new) - .map(Box::into_raw) - .collect::>(); + .collect::>>(); - debug_assert_eq!(imports.len(), imports.capacity()); - out.size = imports.len(); - out.data = imports.as_mut_ptr(); - mem::forget(imports); + *out = imports.into(); } #[no_mangle] @@ -102,16 +94,8 @@ pub unsafe extern "C" fn wasm_module_serialize( out_ptr: &mut wasm_byte_vec_t, ) { let mut byte_vec = match module.inner.serialize() { - Ok(mut byte_vec) => { - byte_vec.shrink_to_fit(); - byte_vec - } + Ok(byte_vec) => byte_vec, Err(_) => return, }; - // ensure we won't leak memory - // TODO: use `Vec::into_raw_parts` when it becomes stable - debug_assert_eq!(byte_vec.capacity(), byte_vec.len()); - out_ptr.size = byte_vec.len(); - out_ptr.data = byte_vec.as_mut_ptr(); - mem::forget(byte_vec); + *out_ptr = byte_vec.into(); } From e6c61c74ff8d5256a017631cdee08a0edab95237 Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Fri, 2 Oct 2020 16:33:03 -0700 Subject: [PATCH 130/281] Update boxed_vec to deal with boxed values --- lib/c-api/src/wasm_c_api/macros.rs | 6 ++++-- lib/c-api/src/wasm_c_api/module.rs | 1 - lib/c-api/src/wasm_c_api/types/function.rs | 4 ++-- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/lib/c-api/src/wasm_c_api/macros.rs b/lib/c-api/src/wasm_c_api/macros.rs index 0231205e3..afa81957d 100644 --- a/lib/c-api/src/wasm_c_api/macros.rs +++ b/lib/c-api/src/wasm_c_api/macros.rs @@ -131,12 +131,14 @@ macro_rules! wasm_declare_boxed_vec { // TODO: do this properly impl [] { - pub unsafe fn into_slice(&self) -> Option<&[*mut []]>{ + pub unsafe fn into_slice(&self) -> Option<&[Box<[]>]>{ if self.data.is_null() { return None; } - Some(::std::slice::from_raw_parts(self.data, self.size)) + let slice: &[*mut []] = ::std::slice::from_raw_parts(self.data, self.size); + let slice: &[Box<[]>] = ::std::mem::transmute(slice); + Some(slice) } } diff --git a/lib/c-api/src/wasm_c_api/module.rs b/lib/c-api/src/wasm_c_api/module.rs index 206d97382..627f932e4 100644 --- a/lib/c-api/src/wasm_c_api/module.rs +++ b/lib/c-api/src/wasm_c_api/module.rs @@ -3,7 +3,6 @@ use super::types::{ wasm_byte_vec_t, wasm_exporttype_t, wasm_exporttype_vec_t, wasm_importtype_t, wasm_importtype_vec_t, }; -use std::mem; use std::ptr::NonNull; use std::slice; use std::sync::Arc; diff --git a/lib/c-api/src/wasm_c_api/types/function.rs b/lib/c-api/src/wasm_c_api/types/function.rs index 699e86a66..7e95a39a2 100644 --- a/lib/c-api/src/wasm_c_api/types/function.rs +++ b/lib/c-api/src/wasm_c_api/types/function.rs @@ -42,13 +42,13 @@ unsafe fn wasm_functype_new_inner( let params: Vec = params .into_slice()? .iter() - .map(|&ptr| *ptr) + .map(|ptr| **ptr) .map(Into::into) .collect::>(); let results: Vec = results .into_slice()? .iter() - .map(|&ptr| *ptr) + .map(|ptr| **ptr) .map(Into::into) .collect::>(); From f0487763bf20bd11868c2b629bbb3031c2b94c62 Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Fri, 2 Oct 2020 17:31:18 -0700 Subject: [PATCH 131/281] Readd functionality from object file engine --- lib/c-api/src/wasm_c_api/engine.rs | 264 +++++++++++++++++++++++++---- lib/c-api/src/wasm_c_api/mod.rs | 6 + 2 files changed, 238 insertions(+), 32 deletions(-) diff --git a/lib/c-api/src/wasm_c_api/engine.rs b/lib/c-api/src/wasm_c_api/engine.rs index 82152a152..b9107f29c 100644 --- a/lib/c-api/src/wasm_c_api/engine.rs +++ b/lib/c-api/src/wasm_c_api/engine.rs @@ -1,44 +1,119 @@ use cfg_if::cfg_if; use std::sync::Arc; use wasmer::Engine; +#[cfg(feature = "jit")] +use wasmer_engine_jit::JIT; +#[cfg(feature = "native")] +use wasmer_engine_native::Native; +#[cfg(feature = "object-file")] +use wasmer_engine_object_file::ObjectFile; +// cbindegn should see this /// this can be a wasmer-specific type with wasmer-specific functions for manipulating it -/// -#[allow(non_camel_case_types)] -pub struct wasm_config_t {} - -#[no_mangle] -pub extern "C" fn wasm_config_new() -> *mut wasm_config_t { - todo!("wasm_config_new") - //ptr::null_mut() +#[derive(Debug, Copy, Clone)] +#[repr(C)] +pub enum wasmer_compiler_t { + CRANELIFT = 0, + LLVM = 1, + SINGLEPASS = 2, } +impl Default for wasmer_compiler_t { + fn default() -> Self { + cfg_if! { + if #[cfg(feature = "cranelift")] { + Self::CRANELIFT + } else if #[cfg(feature = "llvm")] { + Self::LLVM + } else if #[cfg(feature = "singlepass")] { + Self::SINGLEPASS + } else { + compile_error!("Please enable one of the compiler backends") + } + } + } +} + +// cbindegn should see this +#[derive(Debug, Copy, Clone)] +#[repr(C)] #[allow(non_camel_case_types)] +pub enum wasmer_engine_t { + JIT = 0, + NATIVE = 1, + OBJECT_FILE = 2, +} + +impl Default for wasmer_engine_t { + fn default() -> Self { + cfg_if! { + if #[cfg(feature = "jit")] { + Self::JIT + } else if #[cfg(feature = "native")] { + Self::NATIVE + } else if #[cfg(feature = "object-file")] { + Self::OBJECT_FILE + } else { + compile_error!("Please enable one of the engines") + } + } + } +} + +/// this can be a wasmer-specific type with wasmer-specific functions for manipulating it +#[derive(Debug, Default)] +#[repr(C)] +pub struct wasm_config_t { + compiler: wasmer_compiler_t, + engine: wasmer_engine_t, +} + +#[no_mangle] +pub extern "C" fn wasm_config_new() -> Box { + Box::new(wasm_config_t::default()) +} + +// cbindegn should see this +#[no_mangle] +pub extern "C" fn wasm_config_set_compiler( + config: &mut wasm_config_t, + compiler: wasmer_compiler_t, +) { + config.compiler = compiler; +} + +// cbindegn should see this +#[no_mangle] +pub extern "C" fn wasm_config_set_engine(config: &mut wasm_config_t, engine: wasmer_engine_t) { + config.engine = engine; +} + +#[repr(C)] pub struct wasm_engine_t { pub(crate) inner: Arc, } +// Compiler JIT +#[cfg(feature = "compiler")] +use wasmer_compiler::CompilerConfig; +#[cfg(feature = "compiler")] +fn get_default_compiler_config() -> Box { + cfg_if! { + if #[cfg(feature = "cranelift")] { + Box::new(wasmer_compiler_cranelift::Cranelift::default()) + } else if #[cfg(feature = "llvm")] { + Box::new(wasmer_compiler_llvm::LLVM::default()) + } else if #[cfg(feature = "singlepass")] { + Box::new(wasmer_compiler_singlepass::Singlepass::default()) + } else { + compile_error!("Please enable one of the compiler backends") + } + } +} + cfg_if! { if #[cfg(all(feature = "jit", feature = "compiler"))] { - // Compiler JIT - use wasmer_compiler::CompilerConfig; - use wasmer_engine_jit::JIT; - - fn get_default_compiler_config() -> Box { - cfg_if! { - if #[cfg(feature = "cranelift")] { - Box::new(wasmer_compiler_cranelift::Cranelift::default()) - } else if #[cfg(feature = "llvm")] { - Box::new(wasmer_compiler_llvm::LLVM::default()) - } else if #[cfg(feature = "singlepass")] { - Box::new(wasmer_compiler_singlepass::Singlepass::default()) - } else { - compile_error!("Please enable one of the compiler backends") - } - } - } - - #[no_mangle] + #[no_mangle] pub extern "C" fn wasm_engine_new() -> Box { let compiler_config: Box = get_default_compiler_config(); let engine: Arc = Arc::new(JIT::new(&*compiler_config).engine()); @@ -47,14 +122,44 @@ cfg_if! { } else if #[cfg(feature = "jit")] { // Headless JIT - #[no_mangle] + #[no_mangle] pub extern "C" fn wasm_engine_new() -> Box { let engine: Arc = Arc::new(JIT::headless().engine()); Box::new(wasm_engine_t { inner: engine }) } } + else if #[cfg(all(feature = "native", feature = "compiler"))] { + #[no_mangle] + pub extern "C" fn wasm_engine_new() -> Box { + let mut compiler_config: Box = get_default_compiler_config(); + let engine: Arc = Arc::new(Native::new(&mut *compiler_config).engine()); + Box::new(wasm_engine_t { inner: engine }) + } + } + else if #[cfg(feature = "native")] { + #[no_mangle] + pub extern "C" fn wasm_engine_new() -> Box { + let engine: Arc = Arc::new(Native::headless().engine()); + Box::new(wasm_engine_t { inner: engine }) + } + } + else if #[cfg(all(feature = "object-file", feature = "compiler"))] { + #[no_mangle] + pub extern "C" fn wasm_engine_new() -> Box { + let mut compiler_config: Box = get_default_compiler_config(); + let engine: Arc = Arc::new(ObjectFile::new(&mut *compiler_config).engine()); + Box::new(wasm_engine_t { inner: engine }) + } + } + else if #[cfg(feature = "object-file")] { + #[no_mangle] + pub extern "C" fn wasm_engine_new() -> Box { + let engine: Arc = Arc::new(ObjectFile::headless().engine()); + Box::new(wasm_engine_t { inner: engine }) + } + } else { - #[no_mangle] + #[no_mangle] pub extern "C" fn wasm_engine_new() -> Box { unimplemented!("The JITEngine is not attached"); } @@ -66,7 +171,102 @@ pub unsafe extern "C" fn wasm_engine_delete(_wasm_engine_address: Option Box { - wasm_engine_new() + config: Box, +) -> Option> { + // TODO: return useful error messages in failure branches + cfg_if! { + if #[cfg(feature = "compiler")] { + let mut compiler_config: Box = match config.compiler { + wasmer_compiler_t::CRANELIFT => { + cfg_if! { + if #[cfg(feature = "cranelift")] { + Box::new(wasmer_compiler_cranelift::Cranelift::default()) + } else { + return None; + } + } + }, + wasmer_compiler_t::LLVM => { + cfg_if! { + if #[cfg(feature = "llvm")] { + Box::new(wasmer_compiler_llvm::LLVM::default()) + } else { + return None; + } + } + }, + wasmer_compiler_t::SINGLEPASS => { + cfg_if! { + if #[cfg(feature = "singlepass")] { + Box::new(wasmer_compiler_singlepass::Singlepass::default()) + } else { + return None; + } + } + }, + }; + + let inner: Arc = match config.engine { + wasmer_engine_t::JIT => { + cfg_if! { + if #[cfg(feature = "jit")] { + Arc::new(JIT::new(&*compiler_config).engine()) + } else { + return None; + } + } + }, + wasmer_engine_t::NATIVE => { + cfg_if! { + if #[cfg(feature = "native")] { + Arc::new(Native::new(&mut *compiler_config).engine()) + } else { + return None; + } + } + }, + wasmer_engine_t::OBJECT_FILE => { + cfg_if! { + if #[cfg(feature = "object-file")] { + Arc::new(ObjectFile::new(&mut *compiler_config).engine()) + } else { + return None; + } + } + }, + }; + Some(Box::new(wasm_engine_t { inner })) + } else { + let inner: Arc = match config.engine { + wasmer_engine_t::JIT => { + cfg_if! { + if #[cfg(feature = "jit")] { + Arc::new(JIT::headless().engine()) + } else { + return None; + } + } + }, + wasmer_engine_t::NATIVE => { + cfg_if! { + if #[cfg(feature = "native")] { + Arc::new(Native::headless().engine()) + } else { + return None; + } + } + }, + wasmer_engine_t::OBJECT_FILE => { + cfg_if! { + if #[cfg(feature = "object-file")] { + Arc::new(ObjectFile::headless().engine()) + } else { + return None; + } + } + }, + }; + Some(Box::new(wasm_engine_t { inner })) + } + } } diff --git a/lib/c-api/src/wasm_c_api/mod.rs b/lib/c-api/src/wasm_c_api/mod.rs index 9d9d26485..efb5270d2 100644 --- a/lib/c-api/src/wasm_c_api/mod.rs +++ b/lib/c-api/src/wasm_c_api/mod.rs @@ -29,3 +29,9 @@ pub mod value; #[cfg(feature = "wasi")] pub mod wasi; + +// TODO: find a home for this function +#[no_mangle] +pub unsafe extern "C" fn wasm_instance_get_vmctx_ptr(instance: &wasm_instance_t) -> *mut c_void { + instance.inner.vmctx_ptr() as _ +} From ff4cb6d412ae5dc2b729be414f199346d0e6db64 Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Mon, 5 Oct 2020 14:49:23 +0200 Subject: [PATCH 132/281] feat(c-api) Implement `wasm_module_validate`. --- lib/c-api/src/wasm_c_api/module.rs | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/lib/c-api/src/wasm_c_api/module.rs b/lib/c-api/src/wasm_c_api/module.rs index 627f932e4..a1e49ebc6 100644 --- a/lib/c-api/src/wasm_c_api/module.rs +++ b/lib/c-api/src/wasm_c_api/module.rs @@ -3,6 +3,7 @@ use super::types::{ wasm_byte_vec_t, wasm_exporttype_t, wasm_exporttype_vec_t, wasm_importtype_t, wasm_importtype_vec_t, }; +use crate::error::update_last_error; use std::ptr::NonNull; use std::slice; use std::sync::Arc; @@ -32,6 +33,30 @@ pub unsafe extern "C" fn wasm_module_new( #[no_mangle] pub unsafe extern "C" fn wasm_module_delete(_module: Option>) {} +#[no_mangle] +pub unsafe extern "C" fn wasm_module_validate( + store_ptr: Option>, + bytes: &wasm_byte_vec_t, +) -> bool { + // TODO: review lifetime of byte slice. + let wasm_byte_slice: &[u8] = slice::from_raw_parts(bytes.data, bytes.size); + + if store_ptr.is_none() { + return false; + } + + let store_ptr = store_ptr.unwrap().cast::(); + let store = store_ptr.as_ref(); + + if let Err(error) = Module::validate(store, wasm_byte_slice) { + update_last_error(error); + + false + } else { + true + } +} + #[no_mangle] pub unsafe extern "C" fn wasm_module_exports( module: &wasm_module_t, From 3edcc896989180a2f6f7543fe588adb48e9420e3 Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Mon, 5 Oct 2020 21:16:43 +0200 Subject: [PATCH 133/281] feat(c-api) Redefine `wasm_store_t`. `wasm_store_t` is now a proper struct (rather than an opaque type) of kind: ```rs struct wasm_store_t { inner: Store } ``` The rest of the patch updates the code accordingly. --- .../src/wasm_c_api/externals/function.rs | 21 +++++++-------- lib/c-api/src/wasm_c_api/externals/global.rs | 8 +++--- lib/c-api/src/wasm_c_api/externals/memory.rs | 9 +++---- lib/c-api/src/wasm_c_api/externals/table.rs | 10 +++---- lib/c-api/src/wasm_c_api/instance.rs | 3 +-- lib/c-api/src/wasm_c_api/module.rs | 27 ++++++------------- lib/c-api/src/wasm_c_api/store.rs | 19 +++++-------- lib/c-api/src/wasm_c_api/wasi/mod.rs | 10 +++---- 8 files changed, 38 insertions(+), 69 deletions(-) diff --git a/lib/c-api/src/wasm_c_api/externals/function.rs b/lib/c-api/src/wasm_c_api/externals/function.rs index ee351d955..b64f52d87 100644 --- a/lib/c-api/src/wasm_c_api/externals/function.rs +++ b/lib/c-api/src/wasm_c_api/externals/function.rs @@ -4,9 +4,8 @@ use super::super::types::{wasm_functype_t, wasm_valkind_enum}; use super::super::value::{wasm_val_inner, wasm_val_t}; use std::convert::TryInto; use std::ffi::c_void; -use std::ptr::NonNull; use std::sync::Arc; -use wasmer::{Function, Instance, RuntimeError, Store, Val}; +use wasmer::{Function, Instance, RuntimeError, Val}; #[allow(non_camel_case_types)] pub struct wasm_func_t { @@ -31,13 +30,11 @@ pub type wasm_env_finalizer_t = unsafe extern "C" fn(c_void); #[no_mangle] pub unsafe extern "C" fn wasm_func_new( - store: Option>, + store: &wasm_store_t, ft: &wasm_functype_t, callback: wasm_func_callback_t, ) -> Option> { // TODO: handle null pointers? - let store_ptr = store?.cast::(); - let store = store_ptr.as_ref(); let func_sig = ft.sig(); let num_rets = func_sig.results().len(); let inner_callback = move |args: &[Val]| -> Result, RuntimeError> { @@ -68,24 +65,23 @@ pub unsafe extern "C" fn wasm_func_new( .expect("Result conversion failed"); Ok(processed_results) }; - let f = Function::new(store, &func_sig, inner_callback); + let function = Function::new(&store.inner, &func_sig, inner_callback); + Some(Box::new(wasm_func_t { instance: None, - inner: f, + inner: function, })) } #[no_mangle] pub unsafe extern "C" fn wasm_func_new_with_env( - store: Option>, + store: &wasm_store_t, ft: &wasm_functype_t, callback: wasm_func_callback_with_env_t, env: *mut c_void, finalizer: wasm_env_finalizer_t, ) -> Option> { // TODO: handle null pointers? - let store_ptr = store?.cast::(); - let store = store_ptr.as_ref(); let func_sig = ft.sig(); let num_rets = func_sig.results().len(); let inner_callback = @@ -114,10 +110,11 @@ pub unsafe extern "C" fn wasm_func_new_with_env( .expect("Result conversion failed"); Ok(processed_results) }; - let f = Function::new_with_env(store, &func_sig, env, inner_callback); + let function = Function::new_with_env(&store.inner, &func_sig, env, inner_callback); + Some(Box::new(wasm_func_t { instance: None, - inner: f, + inner: function, })) } diff --git a/lib/c-api/src/wasm_c_api/externals/global.rs b/lib/c-api/src/wasm_c_api/externals/global.rs index 92c1ed1e4..aa04bf6f6 100644 --- a/lib/c-api/src/wasm_c_api/externals/global.rs +++ b/lib/c-api/src/wasm_c_api/externals/global.rs @@ -2,8 +2,7 @@ use super::super::store::wasm_store_t; use super::super::types::wasm_globaltype_t; use super::super::value::wasm_val_t; use std::convert::TryInto; -use std::ptr::NonNull; -use wasmer::{Global, Store, Val}; +use wasmer::{Global, Val}; #[allow(non_camel_case_types)] pub struct wasm_global_t { @@ -13,14 +12,13 @@ pub struct wasm_global_t { #[no_mangle] pub unsafe extern "C" fn wasm_global_new( - store_ptr: Option>, + store: &wasm_store_t, gt: &wasm_globaltype_t, val: &wasm_val_t, ) -> Option> { let gt = gt.as_globaltype(); let wasm_val = val.try_into().ok()?; - let store_ptr: NonNull = store_ptr?.cast::(); - let store = store_ptr.as_ref(); + let store = &store.inner; let global = if gt.mutability.is_mutable() { Global::new_mut(store, wasm_val) } else { diff --git a/lib/c-api/src/wasm_c_api/externals/memory.rs b/lib/c-api/src/wasm_c_api/externals/memory.rs index e44a636b0..2976f2e52 100644 --- a/lib/c-api/src/wasm_c_api/externals/memory.rs +++ b/lib/c-api/src/wasm_c_api/externals/memory.rs @@ -1,8 +1,7 @@ use super::super::store::wasm_store_t; use super::super::types::wasm_memorytype_t; use std::mem; -use std::ptr::NonNull; -use wasmer::{Memory, Pages, Store}; +use wasmer::{Memory, Pages}; #[allow(non_camel_case_types)] pub struct wasm_memory_t { @@ -12,14 +11,12 @@ pub struct wasm_memory_t { #[no_mangle] pub unsafe extern "C" fn wasm_memory_new( - store_ptr: Option>, + store: &wasm_store_t, mt: &wasm_memorytype_t, ) -> Option> { let md = mt.as_memorytype().clone(); - let store_ptr: NonNull = store_ptr?.cast::(); - let store = store_ptr.as_ref(); + let memory = c_try!(Memory::new(&store.inner, md)); - let memory = c_try!(Memory::new(store, md)); Some(Box::new(wasm_memory_t { inner: memory })) } diff --git a/lib/c-api/src/wasm_c_api/externals/table.rs b/lib/c-api/src/wasm_c_api/externals/table.rs index f6ade8a5a..526c36b2c 100644 --- a/lib/c-api/src/wasm_c_api/externals/table.rs +++ b/lib/c-api/src/wasm_c_api/externals/table.rs @@ -1,7 +1,6 @@ use super::super::store::wasm_store_t; use super::super::types::{wasm_ref_t, wasm_table_size_t, wasm_tabletype_t}; -use std::ptr::NonNull; -use wasmer::{Store, Table}; +use wasmer::Table; #[allow(non_camel_case_types)] pub struct wasm_table_t { @@ -11,17 +10,14 @@ pub struct wasm_table_t { #[no_mangle] pub unsafe extern "C" fn wasm_table_new( - store_ptr: Option>, + store: &wasm_store_t, tt: &wasm_tabletype_t, init: *const wasm_ref_t, ) -> Option> { let tt = tt.as_tabletype().clone(); - let store_ptr: NonNull = store_ptr?.cast::(); - let store = store_ptr.as_ref(); - let init_val = todo!("get val from init somehow"); + let table = c_try!(Table::new(&store.inner, tt, init_val)); - let table = c_try!(Table::new(store, tt, init_val)); Some(Box::new(wasm_table_t { inner: table })) } diff --git a/lib/c-api/src/wasm_c_api/instance.rs b/lib/c-api/src/wasm_c_api/instance.rs index 39a82fd28..a79044a4e 100644 --- a/lib/c-api/src/wasm_c_api/instance.rs +++ b/lib/c-api/src/wasm_c_api/instance.rs @@ -4,7 +4,6 @@ use super::store::wasm_store_t; use super::trap::wasm_trap_t; use crate::ordered_resolver::OrderedResolver; use std::mem; -use std::ptr::NonNull; use std::sync::Arc; use wasmer::{Extern, Instance}; @@ -52,7 +51,7 @@ unsafe fn argument_import_iter( #[no_mangle] pub unsafe extern "C" fn wasm_instance_new( - store: Option>, + _store: &wasm_store_t, module: &wasm_module_t, imports: *const *const wasm_extern_t, // own diff --git a/lib/c-api/src/wasm_c_api/module.rs b/lib/c-api/src/wasm_c_api/module.rs index a1e49ebc6..6e334097b 100644 --- a/lib/c-api/src/wasm_c_api/module.rs +++ b/lib/c-api/src/wasm_c_api/module.rs @@ -7,7 +7,7 @@ use crate::error::update_last_error; use std::ptr::NonNull; use std::slice; use std::sync::Arc; -use wasmer::{Module, Store}; +use wasmer::Module; #[allow(non_camel_case_types)] pub struct wasm_module_t { @@ -16,14 +16,12 @@ pub struct wasm_module_t { #[no_mangle] pub unsafe extern "C" fn wasm_module_new( - store_ptr: Option>, + store: &wasm_store_t, bytes: &wasm_byte_vec_t, ) -> Option> { // TODO: review lifetime of byte slice let wasm_byte_slice: &[u8] = slice::from_raw_parts_mut(bytes.data, bytes.size); - let store_ptr: NonNull = store_ptr?.cast::(); - let store = store_ptr.as_ref(); - let module = c_try!(Module::from_binary(store, wasm_byte_slice)); + let module = c_try!(Module::from_binary(&store.inner, wasm_byte_slice)); Some(Box::new(wasm_module_t { inner: Arc::new(module), @@ -35,20 +33,13 @@ pub unsafe extern "C" fn wasm_module_delete(_module: Option>) #[no_mangle] pub unsafe extern "C" fn wasm_module_validate( - store_ptr: Option>, + store: &wasm_store_t, bytes: &wasm_byte_vec_t, ) -> bool { // TODO: review lifetime of byte slice. let wasm_byte_slice: &[u8] = slice::from_raw_parts(bytes.data, bytes.size); - if store_ptr.is_none() { - return false; - } - - let store_ptr = store_ptr.unwrap().cast::(); - let store = store_ptr.as_ref(); - - if let Err(error) = Module::validate(store, wasm_byte_slice) { + if let Err(error) = Module::validate(&store.inner, wasm_byte_slice) { update_last_error(error); false @@ -89,7 +80,7 @@ pub unsafe extern "C" fn wasm_module_imports( #[no_mangle] pub unsafe extern "C" fn wasm_module_deserialize( - store_ptr: Option>, + store: &wasm_store_t, bytes: *const wasm_byte_vec_t, ) -> Option> { // TODO: read config from store and use that to decide which compiler to use @@ -101,9 +92,7 @@ pub unsafe extern "C" fn wasm_module_deserialize( (&*bytes).into_slice().unwrap() }; - let store_ptr: NonNull = store_ptr?.cast::(); - let store = store_ptr.as_ref(); - let module = c_try!(Module::deserialize(store, byte_slice)); + let module = c_try!(Module::deserialize(&store.inner, byte_slice)); Some(NonNull::new_unchecked(Box::into_raw(Box::new( wasm_module_t { @@ -117,7 +106,7 @@ pub unsafe extern "C" fn wasm_module_serialize( module: &wasm_module_t, out_ptr: &mut wasm_byte_vec_t, ) { - let mut byte_vec = match module.inner.serialize() { + let byte_vec = match module.inner.serialize() { Ok(byte_vec) => byte_vec, Err(_) => return, }; diff --git a/lib/c-api/src/wasm_c_api/store.rs b/lib/c-api/src/wasm_c_api/store.rs index 6336f0033..3a379ce9a 100644 --- a/lib/c-api/src/wasm_c_api/store.rs +++ b/lib/c-api/src/wasm_c_api/store.rs @@ -4,25 +4,20 @@ use wasmer::Store; /// Opaque wrapper around `Store` #[allow(non_camel_case_types)] -pub struct wasm_store_t {} +pub struct wasm_store_t { + pub(crate) inner: Store, +} #[no_mangle] pub unsafe extern "C" fn wasm_store_new( wasm_engine_ptr: Option>, -) -> Option> { +) -> Option> { let wasm_engine_ptr = wasm_engine_ptr?; let wasm_engine = wasm_engine_ptr.as_ref(); let store = Store::new(&*wasm_engine.inner); - Some(NonNull::new_unchecked( - Box::into_raw(Box::new(store)) as *mut wasm_store_t - )) + + Some(Box::new(wasm_store_t { inner: store })) } #[no_mangle] -pub unsafe extern "C" fn wasm_store_delete(wasm_store: Option>) { - if let Some(s_inner) = wasm_store { - // this should not leak memory: - // we should double check it to make sure though - let _: Box = Box::from_raw(s_inner.cast::().as_ptr()); - } -} +pub unsafe extern "C" fn wasm_store_delete(_store: Option>) {} diff --git a/lib/c-api/src/wasm_c_api/wasi/mod.rs b/lib/c-api/src/wasm_c_api/wasi/mod.rs index 86f8717d9..cf0a08b73 100644 --- a/lib/c-api/src/wasm_c_api/wasi/mod.rs +++ b/lib/c-api/src/wasm_c_api/wasi/mod.rs @@ -16,9 +16,8 @@ use crate::error::{update_last_error, CApiError}; use std::convert::TryFrom; use std::ffi::CStr; use std::os::raw::c_char; -use std::ptr::NonNull; use std::slice; -use wasmer::{Extern, NamedResolver, Store}; +use wasmer::{Extern, NamedResolver}; use wasmer_wasi::{ generate_import_object_from_env, get_wasi_version, WasiEnv, WasiFile, WasiState, WasiStateBuilder, WasiVersion, @@ -241,7 +240,7 @@ pub unsafe extern "C" fn wasi_get_wasi_version(module: &wasm_module_t) -> wasi_v /// Takes ownership of `wasi_env_t`. #[no_mangle] pub unsafe extern "C" fn wasi_get_imports( - store: Option>, + store: &wasm_store_t, module: &wasm_module_t, wasi_env: &wasi_env_t, imports: *mut *mut wasm_extern_t, @@ -251,13 +250,12 @@ pub unsafe extern "C" fn wasi_get_imports( /// Takes ownership of `wasi_env_t`. unsafe fn wasi_get_imports_inner( - store: Option>, + store: &wasm_store_t, module: &wasm_module_t, wasi_env: &wasi_env_t, imports: *mut *mut wasm_extern_t, ) -> Option<()> { - let store_ptr = store?.cast::(); - let store = store_ptr.as_ref(); + let store = &store.inner; let version = c_try!( get_wasi_version(&module.inner, false).ok_or_else(|| CApiError { From 0f8d68652f34e622c989774a8084ce0bfd771f1f Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Mon, 5 Oct 2020 12:30:58 -0700 Subject: [PATCH 134/281] Finish merge with C API refactor --- Makefile | 9 --------- lib/c-api/build.rs | 5 +++++ lib/c-api/src/wasm_c_api/engine.rs | 9 +++++---- lib/c-api/src/wasm_c_api/mod.rs | 7 +------ lib/c-api/src/wasm_c_api/wasmer.rs | 9 +++++++++ lib/c-api/wasmer_wasm.h | 24 ++++++++++++++++++++++++ tests/integration/cli/assets/qjs.wasm | 2 +- tests/integration/cli/assets/wasm.h | 2 +- 8 files changed, 46 insertions(+), 21 deletions(-) create mode 100644 lib/c-api/src/wasm_c_api/wasmer.rs diff --git a/Makefile b/Makefile index e719360d7..66899854f 100644 --- a/Makefile +++ b/Makefile @@ -86,15 +86,6 @@ build-capi-llvm: cargo build --manifest-path lib/c-api/Cargo.toml --release \ --no-default-features --features jit,object-file,llvm,wasi -# this is debug code; we probably shouldn't ship it like this -build-capi-native: - cargo build --manifest-path lib/c-api/Cargo.toml --release \ - --no-default-features --features object-file,wasi -build-capi-native-debug: - cargo build --manifest-path lib/c-api/Cargo.toml \ - --no-default-features --features object-file,wasi - - ########### # Testing # ########### diff --git a/lib/c-api/build.rs b/lib/c-api/build.rs index 683c62f85..0bced17d8 100644 --- a/lib/c-api/build.rs +++ b/lib/c-api/build.rs @@ -374,4 +374,9 @@ fn exclude_items_from_wasm_c_api(builder: Builder) -> Builder { .exclude_item("wasi_get_start_function") .exclude_item("wasi_get_wasi_version") .exclude_item("wasi_version_t") + .exclude_item("wasm_instance_get_vmctx_ptr") + .exclude_item("wasmer_compiler_t") + .exclude_item("wasmer_engine_t") + .exclude_item("wasm_config_set_compiler") + .exclude_item("wasm_config_set_engine") } diff --git a/lib/c-api/src/wasm_c_api/engine.rs b/lib/c-api/src/wasm_c_api/engine.rs index b9107f29c..73f9e7533 100644 --- a/lib/c-api/src/wasm_c_api/engine.rs +++ b/lib/c-api/src/wasm_c_api/engine.rs @@ -8,7 +8,6 @@ use wasmer_engine_native::Native; #[cfg(feature = "object-file")] use wasmer_engine_object_file::ObjectFile; -// cbindegn should see this /// this can be a wasmer-specific type with wasmer-specific functions for manipulating it #[derive(Debug, Copy, Clone)] #[repr(C)] @@ -34,7 +33,6 @@ impl Default for wasmer_compiler_t { } } -// cbindegn should see this #[derive(Debug, Copy, Clone)] #[repr(C)] #[allow(non_camel_case_types)] @@ -60,6 +58,7 @@ impl Default for wasmer_engine_t { } } +/// cbindgen:ignore /// this can be a wasmer-specific type with wasmer-specific functions for manipulating it #[derive(Debug, Default)] #[repr(C)] @@ -68,12 +67,12 @@ pub struct wasm_config_t { engine: wasmer_engine_t, } +/// cbindgen:ignore #[no_mangle] pub extern "C" fn wasm_config_new() -> Box { Box::new(wasm_config_t::default()) } -// cbindegn should see this #[no_mangle] pub extern "C" fn wasm_config_set_compiler( config: &mut wasm_config_t, @@ -82,12 +81,12 @@ pub extern "C" fn wasm_config_set_compiler( config.compiler = compiler; } -// cbindegn should see this #[no_mangle] pub extern "C" fn wasm_config_set_engine(config: &mut wasm_config_t, engine: wasmer_engine_t) { config.engine = engine; } +/// cbindgen:ignore #[repr(C)] pub struct wasm_engine_t { pub(crate) inner: Arc, @@ -166,9 +165,11 @@ cfg_if! { } } +/// cbindgen:ignore #[no_mangle] pub unsafe extern "C" fn wasm_engine_delete(_wasm_engine_address: Option>) {} +/// cbindgen:ignore #[no_mangle] pub extern "C" fn wasm_engine_new_with_config( config: Box, diff --git a/lib/c-api/src/wasm_c_api/mod.rs b/lib/c-api/src/wasm_c_api/mod.rs index efb5270d2..bfdd68a9d 100644 --- a/lib/c-api/src/wasm_c_api/mod.rs +++ b/lib/c-api/src/wasm_c_api/mod.rs @@ -3,7 +3,6 @@ #[macro_use] pub mod macros; -/// cbindgen:ignore pub mod engine; /// cbindgen:ignore @@ -30,8 +29,4 @@ pub mod value; #[cfg(feature = "wasi")] pub mod wasi; -// TODO: find a home for this function -#[no_mangle] -pub unsafe extern "C" fn wasm_instance_get_vmctx_ptr(instance: &wasm_instance_t) -> *mut c_void { - instance.inner.vmctx_ptr() as _ -} +pub mod wasmer; diff --git a/lib/c-api/src/wasm_c_api/wasmer.rs b/lib/c-api/src/wasm_c_api/wasmer.rs new file mode 100644 index 000000000..5d6122c05 --- /dev/null +++ b/lib/c-api/src/wasm_c_api/wasmer.rs @@ -0,0 +1,9 @@ +//! Wasmer-specific extensions to the Wasm C API. + +use crate::wasm_c_api::instance::wasm_instance_t; +use std::ffi::c_void; + +#[no_mangle] +pub unsafe extern "C" fn wasm_instance_get_vmctx_ptr(instance: &wasm_instance_t) -> *mut c_void { + instance.inner.vmctx_ptr() as _ +} diff --git a/lib/c-api/wasmer_wasm.h b/lib/c-api/wasmer_wasm.h index f63ac73f7..963ca7ff5 100644 --- a/lib/c-api/wasmer_wasm.h +++ b/lib/c-api/wasmer_wasm.h @@ -28,6 +28,9 @@ # define DEPRECATED(message) __declspec(deprecated(message)) #endif +// The `jit` feature has been enabled for this build. +#define WASMER_JIT_ENABLED + // The `compiler` feature has been enabled for this build. #define WASMER_COMPILER_ENABLED @@ -51,6 +54,21 @@ #include #include "wasm.h" +/** + * this can be a wasmer-specific type with wasmer-specific functions for manipulating it + */ +typedef enum { + CRANELIFT = 0, + LLVM = 1, + SINGLEPASS = 2, +} wasmer_compiler_t; + +typedef enum { + JIT = 0, + NATIVE = 1, + OBJECT_FILE = 2, +} wasmer_engine_t; + #if defined(WASMER_WASI_ENABLED) typedef struct wasi_config_t wasi_config_t; #endif @@ -132,6 +150,12 @@ wasm_func_t *wasi_get_start_function(wasm_instance_t *instance); wasi_version_t wasi_get_wasi_version(const wasm_module_t *module); #endif +void wasm_config_set_compiler(wasm_config_t *config, wasmer_compiler_t compiler); + +void wasm_config_set_engine(wasm_config_t *config, wasmer_engine_t engine); + +void *wasm_instance_get_vmctx_ptr(const wasm_instance_t *instance); + /** * Gets the length in bytes of the last error if any. * diff --git a/tests/integration/cli/assets/qjs.wasm b/tests/integration/cli/assets/qjs.wasm index a50e63916..acf393b8b 120000 --- a/tests/integration/cli/assets/qjs.wasm +++ b/tests/integration/cli/assets/qjs.wasm @@ -1 +1 @@ -../../../../lib/c-api/tests/assets/qjs.wasm \ No newline at end of file +../../../../lib/c-api/tests/wasm_c_api/assets/qjs.wasm \ No newline at end of file diff --git a/tests/integration/cli/assets/wasm.h b/tests/integration/cli/assets/wasm.h index f6a87ecce..2e4ac6e93 120000 --- a/tests/integration/cli/assets/wasm.h +++ b/tests/integration/cli/assets/wasm.h @@ -1 +1 @@ -../../../../lib/c-api/tests/wasm-c-api/include/wasm.h \ No newline at end of file +../../../../lib/c-api/wasm.h \ No newline at end of file From bbffd46efbacfc0d311c0f81e37bcb743c69cdff Mon Sep 17 00:00:00 2001 From: Syrus Akbary Date: Mon, 5 Oct 2020 12:42:21 -0700 Subject: [PATCH 135/281] Fix typo --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 2ebda57e9..bb884f125 100644 --- a/README.md +++ b/README.md @@ -171,7 +171,7 @@ Test you want? The [Wasmer docs will show you how](https://docs.wasmer.io/ecosys ## Community -Wasmer has an amazing community developers and contributors. Welcome, please join us! 👋 +Wasmer has an amazing community of developers and contributors. Welcome, please join us! 👋 ### Channels From d07d727e698ce22a0b4fcddc6e6e6afaee76c37a Mon Sep 17 00:00:00 2001 From: Nick Lewycky Date: Mon, 5 Oct 2020 13:36:31 -0700 Subject: [PATCH 136/281] Fix warning about zero-sized FDEs. --- lib/engine-jit/src/unwind/systemv.rs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/lib/engine-jit/src/unwind/systemv.rs b/lib/engine-jit/src/unwind/systemv.rs index a848c49f7..25691091a 100644 --- a/lib/engine-jit/src/unwind/systemv.rs +++ b/lib/engine-jit/src/unwind/systemv.rs @@ -82,10 +82,8 @@ impl UnwindRegistry { let len = std::ptr::read::(current as *const u32) as usize; // Skip over the CIE - if current != start { - // If len == 0, __register_frame will be a no-op. - // So rather than skip it here, we just let __register_frame - // deal with empty FDEs the way they want. + // LLVM's libunwind emits a warning on zero-sized FDEs. + if current != start && len != 0 { __register_frame(current); self.registrations.push(current as usize); } From 61e5f2c2a13d970cd7f0c3a08ec2db054ed41c5f Mon Sep 17 00:00:00 2001 From: Nick Lewycky Date: Mon, 5 Oct 2020 13:41:21 -0700 Subject: [PATCH 137/281] Adjust comment. --- lib/engine-jit/src/unwind/systemv.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/engine-jit/src/unwind/systemv.rs b/lib/engine-jit/src/unwind/systemv.rs index 25691091a..d08ea7780 100644 --- a/lib/engine-jit/src/unwind/systemv.rs +++ b/lib/engine-jit/src/unwind/systemv.rs @@ -81,8 +81,8 @@ impl UnwindRegistry { while current < end { let len = std::ptr::read::(current as *const u32) as usize; - // Skip over the CIE - // LLVM's libunwind emits a warning on zero-sized FDEs. + // Skip over the CIE and zero-length FDEs. + // LLVM's libunwind emits a warning on zero-length FDEs. if current != start && len != 0 { __register_frame(current); self.registrations.push(current as usize); From 439e73fcc5460b40cd72d9eec3cc2112afcb43a7 Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Mon, 5 Oct 2020 14:23:54 -0700 Subject: [PATCH 138/281] Address feedback, add downcasting to Artifact trait --- lib/cli/src/commands/compile.rs | 6 ++-- lib/engine-jit/src/artifact.rs | 11 +----- lib/engine-native/src/artifact.rs | 10 ------ lib/engine-object-file/src/artifact.rs | 18 +++++----- lib/engine/src/artifact.rs | 47 +++++++++++++++++++++----- tests/lib/engine-dummy/src/artifact.rs | 8 ----- 6 files changed, 54 insertions(+), 46 deletions(-) diff --git a/lib/cli/src/commands/compile.rs b/lib/cli/src/commands/compile.rs index 43bc44524..102db034f 100644 --- a/lib/cli/src/commands/compile.rs +++ b/lib/cli/src/commands/compile.rs @@ -106,8 +106,10 @@ impl Compile { #[cfg(feature = "object-file")] if engine_type == EngineType::ObjectFile { - let symbol_registry = module.artifact().symbol_registry(); - let metadata_length = module.artifact().metadata_length(); + let artifact: &wasmer_engine_object_file::ObjectFileArtifact = + module.artifact().as_ref().downcast_ref().context("Engine type is ObjectFile but could not downcast artifact into ObjectFileArtifact")?; + let symbol_registry = artifact.symbol_registry(); + let metadata_length = artifact.metadata_length(); let module_info = module.info(); let header_file_src = crate::c_gen::object_file_header::generate_header_file( module_info, diff --git a/lib/engine-jit/src/artifact.rs b/lib/engine-jit/src/artifact.rs index a85edf6a8..b4c9af239 100644 --- a/lib/engine-jit/src/artifact.rs +++ b/lib/engine-jit/src/artifact.rs @@ -7,7 +7,7 @@ use crate::link::link_module; use crate::serialize::SerializableCompilation; use crate::serialize::SerializableModule; use std::sync::{Arc, Mutex}; -use wasmer_compiler::{CompileError, Features, SymbolRegistry, Triple}; +use wasmer_compiler::{CompileError, Features, Triple}; #[cfg(feature = "compiler")] use wasmer_compiler::{CompileModuleInfo, ModuleEnvironment}; use wasmer_engine::{ @@ -291,13 +291,4 @@ impl Artifact for JITArtifact { serialized.extend(bytes); Ok(serialized) } - - fn symbol_registry(&self) -> &dyn SymbolRegistry { - unimplemented!("TODO: figure out why engine JIT doesn't have a SymbolRegistry") - } - - fn metadata_length(&self) -> usize { - // TODO: figure out what to do here - 0 - } } diff --git a/lib/engine-native/src/artifact.rs b/lib/engine-native/src/artifact.rs index 201699550..cefde4d8d 100644 --- a/lib/engine-native/src/artifact.rs +++ b/lib/engine-native/src/artifact.rs @@ -592,14 +592,4 @@ impl Artifact for NativeArtifact { fn serialize(&self) -> Result, SerializeError> { Ok(std::fs::read(&self.sharedobject_path)?) } - - fn symbol_registry(&self) -> &dyn SymbolRegistry { - &self.metadata - } - - fn metadata_length(&self) -> usize { - // TODO: figure out what to do here; - // we could easily store this data and return it... so we probably should - 0 - } } diff --git a/lib/engine-object-file/src/artifact.rs b/lib/engine-object-file/src/artifact.rs index 4550081bd..8d42d3192 100644 --- a/lib/engine-object-file/src/artifact.rs +++ b/lib/engine-object-file/src/artifact.rs @@ -416,6 +416,16 @@ impl ObjectFileArtifact { metadata_length: 0, }) } + + /// Get the `SymbolRegistry` used to generate the names used in the Artifact. + pub fn symbol_registry(&self) -> &dyn SymbolRegistry { + &self.metadata + } + + /// The length in bytes of the metadata in the serialized output. + pub fn metadata_length(&self) -> usize { + self.metadata_length + } } impl Artifact for ObjectFileArtifact { @@ -472,12 +482,4 @@ impl Artifact for ObjectFileArtifact { fn serialize(&self) -> Result, SerializeError> { Ok(self.module_bytes.clone()) } - - fn symbol_registry(&self) -> &dyn SymbolRegistry { - &self.metadata - } - - fn metadata_length(&self) -> usize { - self.metadata_length - } } diff --git a/lib/engine/src/artifact.rs b/lib/engine/src/artifact.rs index 81088f922..67211b057 100644 --- a/lib/engine/src/artifact.rs +++ b/lib/engine/src/artifact.rs @@ -5,7 +5,7 @@ use std::any::Any; use std::fs; use std::path::Path; use std::sync::Arc; -use wasmer_compiler::{Features, SymbolRegistry}; +use wasmer_compiler::Features; use wasmer_types::entity::{BoxedSlice, PrimaryMap}; use wasmer_types::{ DataInitializer, FunctionIndex, LocalFunctionIndex, MemoryIndex, OwnedDataInitializer, @@ -21,7 +21,7 @@ use wasmer_vm::{ /// The `Artifact` contains the compiled data for a given /// module as well as extra information needed to run the /// module at runtime, such as [`ModuleInfo`] and [`Features`]. -pub trait Artifact: Send + Sync { +pub trait Artifact: Send + Sync + Upcastable { /// Return a reference-counted pointer to the module fn module(&self) -> Arc; @@ -147,10 +147,41 @@ pub trait Artifact: Send + Sync { .finish_instantiation(&data_initializers) .map_err(|trap| InstantiationError::Start(RuntimeError::from_trap(trap))) } - - /// Get the `SymbolRegistry` used to generate the names used in the Artifact. - fn symbol_registry(&self) -> &dyn SymbolRegistry; - - /// The length in bytes of the metadata in the serialized output. - fn metadata_length(&self) -> usize; +} + +// Implementation of `Upcastable` taken from https://users.rust-lang.org/t/why-does-downcasting-not-work-for-subtraits/33286/7 . +/// Trait needed to get downcasting from `WasiFile` to work. +pub trait Upcastable { + fn upcast_any_ref(self: &'_ Self) -> &'_ dyn Any; + fn upcast_any_mut(self: &'_ mut Self) -> &'_ mut dyn Any; + fn upcast_any_box(self: Box) -> Box; +} + +impl Upcastable for T { + #[inline] + fn upcast_any_ref(self: &'_ Self) -> &'_ dyn Any { + self + } + #[inline] + fn upcast_any_mut(self: &'_ mut Self) -> &'_ mut dyn Any { + self + } + #[inline] + fn upcast_any_box(self: Box) -> Box { + self + } +} + +impl dyn Artifact + 'static { + /// Try to downcast the artifact into a given type. + #[inline] + pub fn downcast_ref(self: &'_ Self) -> Option<&'_ T> { + self.upcast_any_ref().downcast_ref::() + } + + /// Try to downcast the artifact into a given type mutably. + #[inline] + pub fn downcast_mut(self: &'_ mut Self) -> Option<&'_ mut T> { + self.upcast_any_mut().downcast_mut::() + } } diff --git a/tests/lib/engine-dummy/src/artifact.rs b/tests/lib/engine-dummy/src/artifact.rs index e624979c4..42cda621a 100644 --- a/tests/lib/engine-dummy/src/artifact.rs +++ b/tests/lib/engine-dummy/src/artifact.rs @@ -240,12 +240,4 @@ impl Artifact for DummyArtifact { "The serializer feature is not enabled in the DummyEngine", )) } - - fn symbol_registry(&self) -> &dyn wasmer_compiler::SymbolRegistry { - unimplemented!("dummy engine does not hav ea symbol registry") - } - - fn metadata_length(&self) -> usize { - 0 - } } From ab153fc642a091ad7f4bd181e91f38c77a684ec9 Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Mon, 5 Oct 2020 15:45:52 -0700 Subject: [PATCH 139/281] Improve error messages around memory creation --- lib/c-api/src/wasm_c_api/types/memory.rs | 1 + lib/c-api/tests/wasm_c_api/CMakeLists.txt | 6 +++ lib/c-api/tests/wasm_c_api/test-memory.c | 55 +++++++++++++++++++++++ lib/c-api/wasmer_wasm.h | 2 +- lib/vm/src/memory.rs | 50 ++++++++++++++++----- 5 files changed, 101 insertions(+), 13 deletions(-) create mode 100644 lib/c-api/tests/wasm_c_api/test-memory.c diff --git a/lib/c-api/src/wasm_c_api/types/memory.rs b/lib/c-api/src/wasm_c_api/types/memory.rs index 1daf70438..e810092ba 100644 --- a/lib/c-api/src/wasm_c_api/types/memory.rs +++ b/lib/c-api/src/wasm_c_api/types/memory.rs @@ -24,6 +24,7 @@ wasm_declare_vec!(memorytype); #[allow(non_camel_case_types)] #[derive(Copy, Clone, Debug)] +#[repr(C)] pub struct wasm_limits_t { pub(crate) min: u32, pub(crate) max: u32, diff --git a/lib/c-api/tests/wasm_c_api/CMakeLists.txt b/lib/c-api/tests/wasm_c_api/CMakeLists.txt index 463cdb70b..4ee4291b5 100644 --- a/lib/c-api/tests/wasm_c_api/CMakeLists.txt +++ b/lib/c-api/tests/wasm_c_api/CMakeLists.txt @@ -19,6 +19,7 @@ add_executable(wasm-c-api-trap wasm-c-api/example/trap.c) # Our additional tests. add_executable(test-wasi test-wasi.c) add_executable(test-early-exit test-early-exit.c) +add_executable(test-memory test-memory.c) include_directories(wasm-c-api/include) include_directories(../../) @@ -141,3 +142,8 @@ set_property(TARGET test-early-exit PROPERTY C_STANDARD 11) target_link_libraries(test-early-exit general ${WASMER_LIB}) target_compile_options(test-early-exit PRIVATE ${COMPILER_OPTIONS}) add_test(test-early-exit test-early-exit) + +set_property(TARGET test-memory PROPERTY C_STANDARD 11) +target_link_libraries(test-memory general ${WASMER_LIB}) +target_compile_options(test-memory PRIVATE ${COMPILER_OPTIONS}) +add_test(test-memory test-memory) diff --git a/lib/c-api/tests/wasm_c_api/test-memory.c b/lib/c-api/tests/wasm_c_api/test-memory.c new file mode 100644 index 000000000..aa69aedce --- /dev/null +++ b/lib/c-api/tests/wasm_c_api/test-memory.c @@ -0,0 +1,55 @@ +#include +#include +#include +#include + +#include "wasmer_wasm.h" + +#define own + +// Use the last_error API to retrieve error messages +own char* get_wasmer_error() { + int error_len = wasmer_last_error_length(); + printf("Error len: `%d`\n", error_len); + char *error_str = malloc(error_len); + wasmer_last_error_message(error_str, error_len); + return error_str; +} + +int main(int argc, const char *argv[]) { + printf("Initializing...\n"); + own wasm_engine_t* engine = wasm_engine_new(); + own wasm_store_t* store = wasm_store_new(engine); + + wasm_limits_t limits1 = { + .min = 0, + .max = wasm_limits_max_default, + }; + own wasm_memorytype_t* memtype1 = wasm_memorytype_new(&limits1); + own wasm_memory_t* memory1 = wasm_memory_new(store, memtype1); + assert(memory1 == NULL); + char* error = get_wasmer_error(); + printf("Found error string: %s\n", error); + assert(0 == strcmp("The maximum requested memory (4294967295 pages) is greater than the maximum allowed memory (65536 pages)", error)); + free(error); + + wasm_memorytype_delete(memtype1); + + wasm_limits_t limits2 = { + .min = 15, + .max = 25, + }; + own wasm_memorytype_t* memtype2 = wasm_memorytype_new(&limits2); + own wasm_memory_t* memory2 = wasm_memory_new(store, memtype2); + assert(memory2 != NULL); + + wasm_memorytype_delete(memtype2); + wasm_memory_delete(memory2); + + printf("Shutting down...\n"); + wasm_store_delete(store); + wasm_engine_delete(engine); + + printf("Done.\n"); + return 0; +} diff --git a/lib/c-api/wasmer_wasm.h b/lib/c-api/wasmer_wasm.h index f7c4be4ae..4201bdd54 100644 --- a/lib/c-api/wasmer_wasm.h +++ b/lib/c-api/wasmer_wasm.h @@ -121,7 +121,7 @@ void wasi_env_set_memory(wasi_env_t *env, const wasm_memory_t *memory); /** * Takes ownership of `wasi_env_t`. */ -bool wasi_get_imports(wasm_store_t *store, +bool wasi_get_imports(const wasm_store_t *store, const wasm_module_t *module, const wasi_env_t *wasi_env, wasm_extern_t **imports); diff --git a/lib/vm/src/memory.rs b/lib/vm/src/memory.rs index dbf722914..f632b9fc8 100644 --- a/lib/vm/src/memory.rs +++ b/lib/vm/src/memory.rs @@ -7,7 +7,7 @@ use crate::mmap::Mmap; use crate::vmcontext::VMMemoryDefinition; -use more_asserts::{assert_ge, assert_le}; +use more_asserts::assert_ge; use serde::{Deserialize, Serialize}; use std::borrow::BorrowMut; use std::cell::UnsafeCell; @@ -39,6 +39,22 @@ pub enum MemoryError { /// The reason why the provided memory is invalid. reason: String, }, + /// Caller asked for more minimum memory than we can give them. + #[error("The minimum requested ({} pages) memory is greater than the maximum allowed memory ({} pages)", min_requested.0, max_allowed.0)] + MinimumMemoryTooLarge { + /// The number of pages requested as the minimum amount of memory. + min_requested: Pages, + /// The maximum amount of memory we can allocate. + max_allowed: Pages, + }, + /// Caller asked for a maximum memory greater than we can give them. + #[error("The maximum requested memory ({} pages) is greater than the maximum allowed memory ({} pages)", max_requested.0, max_allowed.0)] + MaximumMemoryTooLarge { + /// The number of pages requested as the maximum amount of memory. + max_requested: Pages, + /// The number of pages requested as the maximum amount of memory. + max_allowed: Pages, + }, /// A user defined error value, used for error cases not listed above. #[error("A user-defined error occurred: {0}")] Generic(String), @@ -140,19 +156,29 @@ struct WasmMmap { impl LinearMemory { /// Create a new linear memory instance with specified minimum and maximum number of wasm pages. pub fn new(memory: &MemoryType, style: &MemoryStyle) -> Result { - // `maximum` cannot be set to more than `65536` pages. - assert_le!(memory.minimum, Pages::max_value()); - assert!(memory.maximum.is_none() || memory.maximum.unwrap() <= Pages::max_value()); - - if memory.maximum.is_some() && memory.maximum.unwrap() < memory.minimum { - return Err(MemoryError::InvalidMemory { - reason: format!( - "the maximum ({} pages) is less than the minimum ({} pages)", - memory.maximum.unwrap().0, - memory.minimum.0 - ), + if memory.minimum > Pages::max_value() { + return Err(MemoryError::MinimumMemoryTooLarge { + min_requested: memory.minimum, + max_allowed: Pages::max_value(), }); } + // `maximum` cannot be set to more than `65536` pages. + if let Some(max) = memory.maximum { + if max > Pages::max_value() { + return Err(MemoryError::MaximumMemoryTooLarge { + max_requested: max, + max_allowed: Pages::max_value(), + }); + } + if max < memory.minimum { + return Err(MemoryError::InvalidMemory { + reason: format!( + "the maximum ({} pages) is less than the minimum ({} pages)", + max.0, memory.minimum.0 + ), + }); + } + } let offset_guard_bytes = style.offset_guard_size() as usize; From c596ff67e3001ffa9873905673f7da10a52b0ae6 Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Tue, 6 Oct 2020 10:54:30 +0200 Subject: [PATCH 140/281] doc(changelog) Add #1636. --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index d195b62b7..911d8caf1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ # Changelog ## **[Unreleased]** +- [#1636](https://github.com/wasmerio/wasmer/pull/1636) Implement `wasm_module_validate` in the Wasm C API. - [#1671](https://github.com/wasmerio/wasmer/pull/1671) Fix probestack firing inappropriately, and sometimes over/under allocating stack. - [#1657](https://github.com/wasmerio/wasmer/pull/1657) Implement `wasm_trap_t` and `wasm_frame_t` for Wasm C API; add examples in Rust and C of exiting early with a host function. - [#1645](https://github.com/wasmerio/wasmer/pull/1645) Move the install script to https://github.com/wasmerio/wasmer-install From 80a243ff17e82b071d9b3de986877af82009a17a Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Tue, 6 Oct 2020 10:55:24 +0200 Subject: [PATCH 141/281] doc(changelog) Add #1635. --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 911d8caf1..0b0573bd9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ # Changelog ## **[Unreleased]** +- [#1635](https://github.com/wasmerio/wasmer/pull/1635) Implement `wat2wasm` in the Wasm C API. - [#1636](https://github.com/wasmerio/wasmer/pull/1636) Implement `wasm_module_validate` in the Wasm C API. - [#1671](https://github.com/wasmerio/wasmer/pull/1671) Fix probestack firing inappropriately, and sometimes over/under allocating stack. - [#1657](https://github.com/wasmerio/wasmer/pull/1657) Implement `wasm_trap_t` and `wasm_frame_t` for Wasm C API; add examples in Rust and C of exiting early with a host function. From ded3132b445475d37f9c43daa0b149c557eedbf5 Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Tue, 6 Oct 2020 11:09:35 +0200 Subject: [PATCH 142/281] feat(c-api) Implement `wat2wasm`. --- Makefile | 12 ++++++------ lib/c-api/Cargo.toml | 2 ++ lib/c-api/build.rs | 1 + lib/c-api/src/wasm_c_api/mod.rs | 2 ++ lib/c-api/src/wasm_c_api/wat.rs | 30 ++++++++++++++++++++++++++++++ lib/c-api/wasmer_wasm.h | 8 ++++++++ 6 files changed, 49 insertions(+), 6 deletions(-) create mode 100644 lib/c-api/src/wasm_c_api/wat.rs diff --git a/Makefile b/Makefile index 3cb273b8a..b4217370a 100644 --- a/Makefile +++ b/Makefile @@ -76,15 +76,15 @@ build-capi: build-capi-cranelift build-capi-singlepass: cargo build --manifest-path lib/c-api/Cargo.toml --release \ - --no-default-features --features jit,singlepass,wasi + --no-default-features --features wat,jit,singlepass,wasi build-capi-cranelift: cargo build --manifest-path lib/c-api/Cargo.toml --release \ - --no-default-features --features jit,cranelift,wasi + --no-default-features --features wat,jit,cranelift,wasi build-capi-llvm: cargo build --manifest-path lib/c-api/Cargo.toml --release \ - --no-default-features --features jit,llvm,wasi + --no-default-features --features wat,jit,llvm,wasi ########### @@ -112,15 +112,15 @@ test-packages: test-capi-singlepass: build-capi-singlepass cargo test --manifest-path lib/c-api/Cargo.toml --release \ - --no-default-features --features jit,singlepass,wasi -- --nocapture + --no-default-features --features wat,jit,singlepass,wasi -- --nocapture test-capi-cranelift: build-capi-cranelift cargo test --manifest-path lib/c-api/Cargo.toml --release \ - --no-default-features --features jit,cranelift,wasi -- --nocapture + --no-default-features --features wat,jit,cranelift,wasi -- --nocapture test-capi-llvm: build-capi-llvm cargo test --manifest-path lib/c-api/Cargo.toml --release \ - --no-default-features --features jit,llvm,wasi -- --nocapture + --no-default-features --features wat,jit,llvm,wasi -- --nocapture test-capi: test-capi-singlepass test-capi-cranelift test-capi-llvm diff --git a/lib/c-api/Cargo.toml b/lib/c-api/Cargo.toml index 4bc32e47f..d33425c46 100644 --- a/lib/c-api/Cargo.toml +++ b/lib/c-api/Cargo.toml @@ -40,9 +40,11 @@ paste = "0.1" [features] default = [ + "wat", "cranelift", "wasi", ] +wat = ["wasmer/wat"] wasi = ["wasmer-wasi", "typetag", "serde"] engine = [] jit = [ diff --git a/lib/c-api/build.rs b/lib/c-api/build.rs index 683c62f85..3f7c96ef8 100644 --- a/lib/c-api/build.rs +++ b/lib/c-api/build.rs @@ -374,4 +374,5 @@ fn exclude_items_from_wasm_c_api(builder: Builder) -> Builder { .exclude_item("wasi_get_start_function") .exclude_item("wasi_get_wasi_version") .exclude_item("wasi_version_t") + .exclude_item("wat2wasm") } diff --git a/lib/c-api/src/wasm_c_api/mod.rs b/lib/c-api/src/wasm_c_api/mod.rs index 9d9d26485..de528d8bc 100644 --- a/lib/c-api/src/wasm_c_api/mod.rs +++ b/lib/c-api/src/wasm_c_api/mod.rs @@ -29,3 +29,5 @@ pub mod value; #[cfg(feature = "wasi")] pub mod wasi; + +pub mod wat; diff --git a/lib/c-api/src/wasm_c_api/wat.rs b/lib/c-api/src/wasm_c_api/wat.rs new file mode 100644 index 000000000..d093cd650 --- /dev/null +++ b/lib/c-api/src/wasm_c_api/wat.rs @@ -0,0 +1,30 @@ +use super::types::wasm_byte_vec_t; + +/// Parses in-memory bytes as either the WAT format, or a binary Wasm +/// module. This is wasmer-specific. +/// +/// In case of failure, `wat2wasm` returns `NULL`. +#[cfg(feature = "wat")] +#[no_mangle] +pub unsafe extern "C" fn wat2wasm(wat: &wasm_byte_vec_t) -> Option> { + let wat: &[u8] = wat.into_slice()?; + + let result = match wasmer::wat2wasm(wat) { + Ok(result) => result, + Err(error) => { + crate::error::update_last_error(error); + + return None; + } + }; + + let mut result: Vec = result.into_owned(); + result.shrink_to_fit(); + + let wasm = wasm_byte_vec_t { + size: result.len(), + data: result.as_mut_ptr(), + }; + + Some(Box::new(wasm)) +} diff --git a/lib/c-api/wasmer_wasm.h b/lib/c-api/wasmer_wasm.h index 4201bdd54..8e44602c9 100644 --- a/lib/c-api/wasmer_wasm.h +++ b/lib/c-api/wasmer_wasm.h @@ -177,4 +177,12 @@ int wasmer_last_error_length(void); */ int wasmer_last_error_message(char *buffer, int length); +/** + * Parses in-memory bytes as either the WAT format, or a binary Wasm + * module. This is wasmer-specific. + * + * In case of failure, `wat2wasm` returns `NULL`. + */ +wasm_byte_vec_t *wat2wasm(const wasm_byte_vec_t *wat); + #endif /* WASMER_WASM_H */ From 78887c378e88a4da76d706588a86555d588abf8e Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Tue, 6 Oct 2020 11:14:46 +0200 Subject: [PATCH 143/281] chore(c-api) Simplify code. --- lib/c-api/src/wasm_c_api/wat.rs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/lib/c-api/src/wasm_c_api/wat.rs b/lib/c-api/src/wasm_c_api/wat.rs index d093cd650..b254ceeef 100644 --- a/lib/c-api/src/wasm_c_api/wat.rs +++ b/lib/c-api/src/wasm_c_api/wat.rs @@ -21,10 +21,8 @@ pub unsafe extern "C" fn wat2wasm(wat: &wasm_byte_vec_t) -> Option = result.into_owned(); result.shrink_to_fit(); - let wasm = wasm_byte_vec_t { + Some(Box::new(wasm_byte_vec_t { size: result.len(), data: result.as_mut_ptr(), - }; - - Some(Box::new(wasm)) + })) } From 264ed836aca682845007dc8dc602cf5ebcf89578 Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Tue, 6 Oct 2020 20:54:36 +0200 Subject: [PATCH 144/281] feat(c-api) Use `c_try!` and `From` implementations to simplify `wat2wasm`. --- lib/c-api/src/wasm_c_api/wat.rs | 18 ++---------------- 1 file changed, 2 insertions(+), 16 deletions(-) diff --git a/lib/c-api/src/wasm_c_api/wat.rs b/lib/c-api/src/wasm_c_api/wat.rs index b254ceeef..0ff73d69c 100644 --- a/lib/c-api/src/wasm_c_api/wat.rs +++ b/lib/c-api/src/wasm_c_api/wat.rs @@ -8,21 +8,7 @@ use super::types::wasm_byte_vec_t; #[no_mangle] pub unsafe extern "C" fn wat2wasm(wat: &wasm_byte_vec_t) -> Option> { let wat: &[u8] = wat.into_slice()?; + let result: wasm_byte_vec_t = c_try!(wasmer::wat2wasm(wat)).into_owned().into(); - let result = match wasmer::wat2wasm(wat) { - Ok(result) => result, - Err(error) => { - crate::error::update_last_error(error); - - return None; - } - }; - - let mut result: Vec = result.into_owned(); - result.shrink_to_fit(); - - Some(Box::new(wasm_byte_vec_t { - size: result.len(), - data: result.as_mut_ptr(), - })) + Some(Box::new(result)) } From c3efc06e876bbf98d8ed490fe2b2774883100f1b Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Tue, 6 Oct 2020 20:56:36 +0200 Subject: [PATCH 145/281] test(c-api) Add test case for `wat2wasm`. --- lib/c-api/tests/wasm_c_api/CMakeLists.txt | 18 +++++--- lib/c-api/tests/wasm_c_api/test-wat2wasm.c | 52 ++++++++++++++++++++++ 2 files changed, 64 insertions(+), 6 deletions(-) create mode 100644 lib/c-api/tests/wasm_c_api/test-wat2wasm.c diff --git a/lib/c-api/tests/wasm_c_api/CMakeLists.txt b/lib/c-api/tests/wasm_c_api/CMakeLists.txt index 4ee4291b5..1ac9b3eaf 100644 --- a/lib/c-api/tests/wasm_c_api/CMakeLists.txt +++ b/lib/c-api/tests/wasm_c_api/CMakeLists.txt @@ -17,9 +17,10 @@ add_executable(wasm-c-api-serialize wasm-c-api/example/serialize.c) add_executable(wasm-c-api-trap wasm-c-api/example/trap.c) # Our additional tests. -add_executable(test-wasi test-wasi.c) add_executable(test-early-exit test-early-exit.c) add_executable(test-memory test-memory.c) +add_executable(test-wasi test-wasi.c) +add_executable(test-wat2wasm test-wat2wasm.c) include_directories(wasm-c-api/include) include_directories(../../) @@ -133,11 +134,6 @@ add_test(NAME wasm-c-api-trap WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/wasm-c-api/example/ ) -set_property(TARGET test-wasi PROPERTY C_STANDARD 11) -target_link_libraries(test-wasi general ${WASMER_LIB}) -target_compile_options(test-wasi PRIVATE ${COMPILER_OPTIONS}) -add_test(test-wasi test-wasi) - set_property(TARGET test-early-exit PROPERTY C_STANDARD 11) target_link_libraries(test-early-exit general ${WASMER_LIB}) target_compile_options(test-early-exit PRIVATE ${COMPILER_OPTIONS}) @@ -147,3 +143,13 @@ set_property(TARGET test-memory PROPERTY C_STANDARD 11) target_link_libraries(test-memory general ${WASMER_LIB}) target_compile_options(test-memory PRIVATE ${COMPILER_OPTIONS}) add_test(test-memory test-memory) + +set_property(TARGET test-wasi PROPERTY C_STANDARD 11) +target_link_libraries(test-wasi general ${WASMER_LIB}) +target_compile_options(test-wasi PRIVATE ${COMPILER_OPTIONS}) +add_test(test-wasi test-wasi) + +set_property(TARGET test-wat2wasm PROPERTY C_STANDARD 11) +target_link_libraries(test-wat2wasm general ${WASMER_LIB}) +target_compile_options(test-wat2wasm PRIVATE ${COMPILER_OPTIONS}) +add_test(test-wat2wasm test-wat2wasm) diff --git a/lib/c-api/tests/wasm_c_api/test-wat2wasm.c b/lib/c-api/tests/wasm_c_api/test-wat2wasm.c new file mode 100644 index 000000000..5897cadad --- /dev/null +++ b/lib/c-api/tests/wasm_c_api/test-wat2wasm.c @@ -0,0 +1,52 @@ +#include +#include +#include +#include + +#include "wasmer_wasm.h" + +#define own + +int main(int argc, const char* argv[]) { + // Initialize. + printf("Initializing...\n"); + wasm_engine_t* engine = wasm_engine_new(); + wasm_store_t* store = wasm_store_new(engine); + + // Getting Wasm. + printf("Compiling WAT to Wasm...\n"); + + wasm_byte_vec_t wat = { + .data = "(module)", + .size = 8, + }; + wasm_byte_vec_t *wasm = wat2wasm(&wat); + + if (!wasm) { + printf("> Error compiler WAT to Wasm!\n"); + return 1; + } + + if (wasm->size != 8) { + printf("The Wasm size is incorrect!\n"); + return 1; + } + + if (!(wasm->data[0] == 0 && + wasm->data[1] == 'a' && + wasm->data[2] == 's' && + wasm->data[3] == 'm' && + wasm->data[4] == 1 && + wasm->data[5] == 0 && + wasm->data[6] == 0 && + wasm->data[7] == 0)) { + printf("The Wasm data is incorrect!\n"); + return 1; + } + + wasm_byte_vec_delete(wasm); + + // All done. + printf("Done.\n"); + return 0; +} From aa2e8f7b4dcd471c2dd4b78c8aec4811f8fdd907 Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Tue, 6 Oct 2020 12:13:59 -0700 Subject: [PATCH 146/281] Address more feedback, clean up code --- Cargo.toml | 1 - lib/api/src/module.rs | 7 +- lib/c-api/src/wasm_c_api/engine.rs | 3 +- lib/c-api/wasmer_wasm.h | 3 - lib/cli/src/c_gen/mod.rs | 4 +- lib/cli/src/c_gen/object_file_header.rs | 180 +++++++++--------- lib/cli/src/commands/compile.rs | 2 +- lib/engine-object-file/README.md | 52 ++--- lib/engine-object-file/src/artifact.rs | 18 +- .../src/object_file_engine_test_c_source.c | 11 +- 10 files changed, 135 insertions(+), 146 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index b3aa4338f..97975d4cc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -103,7 +103,6 @@ compiler = [ "wasmer-compiler/translator", "wasmer-engine-jit/compiler", "wasmer-engine-native/compiler", - # TODO: does this make sense? "wasmer-engine-object-file/compiler", ] singlepass = [ diff --git a/lib/api/src/module.rs b/lib/api/src/module.rs index 7ec3955a8..bca259d6b 100644 --- a/lib/api/src/module.rs +++ b/lib/api/src/module.rs @@ -411,8 +411,11 @@ impl Module { &self.artifact.module_ref() } - /// Temporary function to implement this; we probably want to implement the functionality - /// dependent on the `Artifact` as individual hidden methods on the `Module`. + /// Gets the [`Artifact`] used internally by the Module. + /// + /// This API is hidden because it's not necessarily stable; + /// this functionality is required for some core functionality though, like + /// the object file engine. #[doc(hidden)] pub fn artifact(&self) -> &Arc { &self.artifact diff --git a/lib/c-api/src/wasm_c_api/engine.rs b/lib/c-api/src/wasm_c_api/engine.rs index 73f9e7533..613b6a60d 100644 --- a/lib/c-api/src/wasm_c_api/engine.rs +++ b/lib/c-api/src/wasm_c_api/engine.rs @@ -87,7 +87,6 @@ pub extern "C" fn wasm_config_set_engine(config: &mut wasm_config_t, engine: was } /// cbindgen:ignore -#[repr(C)] pub struct wasm_engine_t { pub(crate) inner: Arc, } @@ -160,7 +159,7 @@ cfg_if! { else { #[no_mangle] pub extern "C" fn wasm_engine_new() -> Box { - unimplemented!("The JITEngine is not attached"); + unimplemented!("The JITEngine is not attached; You might want to recompile `wasmer_c_api` with `--feature jit`"); } } } diff --git a/lib/c-api/wasmer_wasm.h b/lib/c-api/wasmer_wasm.h index 963ca7ff5..5ef6fa954 100644 --- a/lib/c-api/wasmer_wasm.h +++ b/lib/c-api/wasmer_wasm.h @@ -28,9 +28,6 @@ # define DEPRECATED(message) __declspec(deprecated(message)) #endif -// The `jit` feature has been enabled for this build. -#define WASMER_JIT_ENABLED - // The `compiler` feature has been enabled for this build. #define WASMER_COMPILER_ENABLED diff --git a/lib/cli/src/c_gen/mod.rs b/lib/cli/src/c_gen/mod.rs index 7e59240bc..cad34e340 100644 --- a/lib/cli/src/c_gen/mod.rs +++ b/lib/cli/src/c_gen/mod.rs @@ -227,6 +227,7 @@ pub enum CStatement { /// This is useful for initializing constant arrays, for example. definition: Option>, }, + /// A literal array of CStatements. LiteralArray { /// The contents of the array. @@ -246,6 +247,7 @@ pub enum CStatement { /// The thing being cast. expression: Box, }, + /// Typedef one type to another. TypeDef { /// The type of the thing being typedef'd. @@ -379,7 +381,6 @@ mod test { }, "size_t (*)()" ); - assert_c_type!( CType::PointerTo { is_const: true, @@ -438,7 +439,6 @@ mod test { "my_func", "size_t my_func()" ); - assert_c_type!( CType::PointerTo { is_const: true, diff --git a/lib/cli/src/c_gen/object_file_header.rs b/lib/cli/src/c_gen/object_file_header.rs index d992cc330..f517cdd61 100644 --- a/lib/cli/src/c_gen/object_file_header.rs +++ b/lib/cli/src/c_gen/object_file_header.rs @@ -17,7 +17,7 @@ pub fn generate_header_file( is_const: true, ctype: CType::U32, definition: Some(Box::new(CStatement::LiteralConstant { - value: format!("{}", metadata_length), + value: metadata_length.to_string(), })), }); c_statements.push(CStatement::Declaration { @@ -29,51 +29,50 @@ pub fn generate_header_file( }, definition: None, }); - for (function_local_index, _sig_index) in - module_info + let function_declarations = module_info + .functions + .iter() + .filter_map(|(f_index, sig_index)| { + Some((module_info.local_func_index(f_index)?, sig_index)) + }) + .map(|(function_local_index, _sig_index)| { + let function_name = + symbol_registry.symbol_to_name(Symbol::LocalFunction(function_local_index)); + // TODO: figure out the signature here too + CStatement::Declaration { + name: function_name.clone(), + is_extern: false, + is_const: false, + ctype: CType::Function { + arguments: vec![CType::Void], + return_value: None, + }, + definition: None, + } + }); + c_statements.extend(function_declarations); + + // function pointer array + { + let function_pointer_array_statements = module_info .functions .iter() .filter_map(|(f_index, sig_index)| { Some((module_info.local_func_index(f_index)?, sig_index)) }) - { - let function_name = - symbol_registry.symbol_to_name(Symbol::LocalFunction(function_local_index)); - // TODO: figure out the signature here too - c_statements.push(CStatement::Declaration { - name: function_name.clone(), - is_extern: false, - is_const: false, - ctype: CType::Function { - arguments: vec![CType::Void], - return_value: None, - }, - definition: None, - }); - } + .map(|(function_local_index, _sig_index)| { + let function_name = + symbol_registry.symbol_to_name(Symbol::LocalFunction(function_local_index)); + // TODO: figure out the signature here too - // function pointer array - { - let mut function_pointer_array_statements = vec![]; - for (function_local_index, _sig_index) in - module_info - .functions - .iter() - .filter_map(|(f_index, sig_index)| { - Some((module_info.local_func_index(f_index)?, sig_index)) - }) - { - let function_name = - symbol_registry.symbol_to_name(Symbol::LocalFunction(function_local_index)); - // TODO: figure out the signature here too - - function_pointer_array_statements.push(CStatement::Cast { - target_type: CType::void_ptr(), - expression: Box::new(CStatement::LiteralConstant { - value: function_name.clone(), - }), - }); - } + CStatement::Cast { + target_type: CType::void_ptr(), + expression: Box::new(CStatement::LiteralConstant { + value: function_name.clone(), + }), + } + }) + .collect::>(); c_statements.push(CStatement::Declaration { name: "function_pointers".to_string(), @@ -88,32 +87,40 @@ pub fn generate_header_file( }); } - for (sig_index, _func_type) in module_info.signatures.iter() { - let function_name = - symbol_registry.symbol_to_name(Symbol::FunctionCallTrampoline(sig_index)); + let func_trampoline_declarations = + module_info + .signatures + .iter() + .map(|(sig_index, _func_type)| { + let function_name = + symbol_registry.symbol_to_name(Symbol::FunctionCallTrampoline(sig_index)); - c_statements.push(CStatement::Declaration { - name: function_name.clone(), - is_extern: false, - is_const: false, - ctype: CType::Function { - arguments: vec![CType::void_ptr(), CType::void_ptr(), CType::void_ptr()], - return_value: None, - }, - definition: None, - }); - } + CStatement::Declaration { + name: function_name.clone(), + is_extern: false, + is_const: false, + ctype: CType::Function { + arguments: vec![CType::void_ptr(), CType::void_ptr(), CType::void_ptr()], + return_value: None, + }, + definition: None, + } + }); + c_statements.extend(func_trampoline_declarations); // function trampolines { - let mut function_trampoline_statements = vec![]; - for (sig_index, _vm_shared_index) in module_info.signatures.iter() { - let function_name = - symbol_registry.symbol_to_name(Symbol::FunctionCallTrampoline(sig_index)); - function_trampoline_statements.push(CStatement::LiteralConstant { - value: function_name, - }); - } + let function_trampoline_statements = module_info + .signatures + .iter() + .map(|(sig_index, _vm_shared_index)| { + let function_name = + symbol_registry.symbol_to_name(Symbol::FunctionCallTrampoline(sig_index)); + CStatement::LiteralConstant { + value: function_name, + } + }) + .collect::>(); c_statements.push(CStatement::Declaration { name: "function_trampolines".to_string(), @@ -128,25 +135,26 @@ pub fn generate_header_file( }); } - for func_index in module_info + let dyn_func_declarations = module_info .functions .keys() .take(module_info.num_imported_functions) - { - let function_name = - symbol_registry.symbol_to_name(Symbol::DynamicFunctionTrampoline(func_index)); - // TODO: figure out the signature here - c_statements.push(CStatement::Declaration { - name: function_name, - is_extern: false, - is_const: false, - ctype: CType::Function { - arguments: vec![CType::void_ptr(), CType::void_ptr(), CType::void_ptr()], - return_value: None, - }, - definition: None, + .map(|func_index| { + let function_name = + symbol_registry.symbol_to_name(Symbol::DynamicFunctionTrampoline(func_index)); + // TODO: figure out the signature here + CStatement::Declaration { + name: function_name, + is_extern: false, + is_const: false, + ctype: CType::Function { + arguments: vec![CType::void_ptr(), CType::void_ptr(), CType::void_ptr()], + return_value: None, + }, + definition: None, + } }); - } + c_statements.extend(dyn_func_declarations); c_statements.push(CStatement::TypeDef { source_type: CType::Function { @@ -158,18 +166,18 @@ pub fn generate_header_file( // dynamic function trampoline pointer array { - let mut dynamic_function_trampoline_statements = vec![]; - for func_index in module_info + let dynamic_function_trampoline_statements = module_info .functions .keys() .take(module_info.num_imported_functions) - { - let function_name = - symbol_registry.symbol_to_name(Symbol::DynamicFunctionTrampoline(func_index)); - dynamic_function_trampoline_statements.push(CStatement::LiteralConstant { - value: function_name, - }); - } + .map(|func_index| { + let function_name = + symbol_registry.symbol_to_name(Symbol::DynamicFunctionTrampoline(func_index)); + CStatement::LiteralConstant { + value: function_name, + } + }) + .collect::>(); c_statements.push(CStatement::Declaration { name: "dynamic_function_trampoline_pointers".to_string(), is_extern: false, diff --git a/lib/cli/src/commands/compile.rs b/lib/cli/src/commands/compile.rs index 102db034f..1e77a08f2 100644 --- a/lib/cli/src/commands/compile.rs +++ b/lib/cli/src/commands/compile.rs @@ -16,7 +16,7 @@ pub struct Compile { #[structopt(name = "OUTPUT PATH", short = "o", parse(from_os_str))] output: PathBuf, - /// Output path for generated header filefile + /// Output path for generated header file #[structopt(name = "HEADER PATH", long = "header", parse(from_os_str))] header_path: Option, diff --git a/lib/engine-object-file/README.md b/lib/engine-object-file/README.md index 79d63de9e..9c8cde389 100644 --- a/lib/engine-object-file/README.md +++ b/lib/engine-object-file/README.md @@ -2,9 +2,9 @@ This is an [engine](https://crates.io/crates/wasmer-engine) for the [wasmer](https://crates.io/crates/wasmer/1.0.0-alpha3) WebAssembly VM. -This engine is used to produce native code that can be linked against providing -a sandboxed WebAssembly runtime environment for the compiled module with no need -for runtime compilation. +This engine is used to produce a native object file that can be linked +against providing a sandboxed WebAssembly runtime environment for the +compiled module with no need for runtime compilation. ## Example of use @@ -25,6 +25,10 @@ Target: x86_64-apple-darwin Now lets create a program to link with this object file. ```C +#ifdef __cplusplus +extern "C" { +#endif + #include "wasmer_wasm.h" #include "wasm.h" #include "my_wasm.h" @@ -35,18 +39,15 @@ Now lets create a program to link with this object file. void wasmer_function__1(void); void wasmer_trampoline_function_call__1(void*, void*, void*); -// a bit of a hack; TODO: clean this up -typedef struct my_byte_vec_t { - size_t size; - char* data; -} my_byte_vec_t; - +#ifdef __cplusplus +} +#endif void print_wasmer_error() { int error_len = wasmer_last_error_length(); printf("Error len: `%d`\n", error_len); - char *error_str = malloc(error_len); + char* error_str = (char*) malloc(error_len); wasmer_last_error_message(error_str, error_len); printf("Error str: `%s`\n", error_str); } @@ -54,7 +55,10 @@ void print_wasmer_error() int main() { printf("Initializing...\n"); - wasm_engine_t* engine = wasm_engine_new(); + wasm_config_t* config = wasm_config_new(); + wasm_config_set_compiler(config, CRANELIFT); + wasm_config_set_engine(config, OBJECT_FILE); + wasm_engine_t* engine = wasm_engine_new_with_config(config); wasm_store_t* store = wasm_store_new(engine); char* byte_ptr = (char*)&WASMER_METADATA[0]; @@ -79,7 +83,7 @@ int main() { char* memory_buffer = (char*) malloc(buffer_size); size_t current_offset = 0; - printf("Buffer size: %d\n", buffer_size); + printf("Buffer size: %zu\n", buffer_size); memcpy(memory_buffer + current_offset, byte_ptr, module_bytes_len); current_offset += module_bytes_len; @@ -102,12 +106,12 @@ int main() { memcpy(memory_buffer + current_offset, (void*)&dynamic_function_trampoline_pointers[0], sizeof(dynamic_function_trampoline_pointers)); current_offset += sizeof(dynamic_function_trampoline_pointers); - my_byte_vec_t module_byte_vec = { + wasm_byte_vec_t module_byte_vec = { .size = buffer_size, .data = memory_buffer, }; - wasm_module_t* module = wasm_module_deserialize(store, (wasm_byte_vec_t*) &module_byte_vec); + wasm_module_t* module = wasm_module_deserialize(store, &module_byte_vec); if (! module) { printf("Failed to create module\n"); print_wasmer_error(); @@ -119,11 +123,11 @@ int main() { // In this example we're passing some JavaScript source code as a command line argumnet // to a WASI module that can evaluate JavaScript. - wasi_config_t* config = wasi_config_new("constant_value_here"); + wasi_config_t* wasi_config = wasi_config_new("constant_value_here"); const char* js_string = "function greet(name) { return JSON.stringify('Hello, ' + name); }; print(greet('World'));"; - wasi_config_arg(config, "--eval"); - wasi_config_arg(config, js_string); - wasi_env_t* wasi_env = wasi_env_new(config); + wasi_config_arg(wasi_config, "--eval"); + wasi_config_arg(wasi_config, js_string); + wasi_env_t* wasi_env = wasi_env_new(wasi_config); if (!wasi_env) { printf("> Error building WASI env!\n"); print_wasmer_error(); @@ -133,7 +137,7 @@ int main() { wasm_importtype_vec_t import_types; wasm_module_imports(module, &import_types); int num_imports = import_types.size; - wasm_extern_t** imports = malloc(num_imports * sizeof(wasm_extern_t*)); + wasm_extern_t** imports = (wasm_extern_t**) malloc(num_imports * sizeof(wasm_extern_t*)); wasm_importtype_vec_delete(&import_types); bool get_imports_result = wasi_get_imports(store, module, wasi_env, imports); @@ -156,6 +160,7 @@ int main() { void* vmctx = wasm_instance_get_vmctx_ptr(instance); wasm_val_t* inout[2] = { NULL, NULL }; + fflush(stdout); // We're able to call our compiled functions directly through their trampolines. wasmer_trampoline_function_call__1(vmctx, wasmer_function__1, &inout); @@ -170,14 +175,15 @@ int main() { We save that source code into `test.c` and run: ```sh -gcc -O2 -c test.c -o test.o +clang -O2 -c test.c -o test.o ``` Now we just need to link everything together: ```sh -g++ -O2 test.o my_wasm.o libwasmer.a +clang -O2 test.o my_wasm.o libwasmer_c_api.a ``` -We link the object file we created with our C code, the object file we generated with Wasmer, -and libwasmer together and produce an executable that can call into our compiled WebAssembly! +We link the object file we created with our C code, the object file we +generated with Wasmer, and `libwasmer_c_api` together and produce an +executable that can call into our compiled WebAssembly! diff --git a/lib/engine-object-file/src/artifact.rs b/lib/engine-object-file/src/artifact.rs index 8d42d3192..80d2ce33a 100644 --- a/lib/engine-object-file/src/artifact.rs +++ b/lib/engine-object-file/src/artifact.rs @@ -116,13 +116,13 @@ impl ObjectFileArtifact { .values() .map(|table_type| tunables.table_style(table_type)) .collect(); - let compile_info = CompileModuleInfo { module: Arc::new(translation.module), features: features.clone(), memory_styles, table_styles, }; + Ok(( compile_info, translation.function_body_inputs, @@ -153,16 +153,6 @@ impl ObjectFileArtifact { let target_triple = target.triple(); - /* - // We construct the function body lengths - let function_body_lengths = compilation - .get_function_bodies() - .values() - .map(|function_body| function_body.body.len() as u64) - .map(|_function_body| 0u64) - .collect::>(); - */ - // TODO: we currently supply all-zero function body lengths. // We don't know the lengths until they're compiled, yet we have to // supply the metadata as an input to the compile. @@ -178,8 +168,6 @@ impl ObjectFileArtifact { function_body_lengths, }; - // let wasm_info = generate_data_structures_for_c(&metadata); - // generate_c(wasm_info); /* In the C file we need: - imports @@ -231,9 +219,6 @@ impl ObjectFileArtifact { obj.write().map_err(to_compile_error)? }; - //let host_target = Triple::host(); - //let is_cross_compiling = target_triple != &host_target; - Self::from_parts_crosscompiled(&mut *engine_inner, metadata, obj_bytes, metadata_length) } @@ -255,7 +240,6 @@ impl ObjectFileArtifact { let finished_functions: PrimaryMap = PrimaryMap::new(); let finished_dynamic_function_trampolines: PrimaryMap = PrimaryMap::new(); - //let signatures: PrimaryMap = PrimaryMap::new(); let signature_registry = engine_inner.signatures(); let signatures = metadata .compile_info diff --git a/tests/integration/cli/src/object_file_engine_test_c_source.c b/tests/integration/cli/src/object_file_engine_test_c_source.c index 7e018245e..74b4a3696 100644 --- a/tests/integration/cli/src/object_file_engine_test_c_source.c +++ b/tests/integration/cli/src/object_file_engine_test_c_source.c @@ -16,13 +16,6 @@ void wasmer_trampoline_function_call__1(void*, void*, void*); } #endif -// a bit of a hack; TODO: clean this up -typedef struct my_byte_vec_t { - size_t size; - char* data; -} my_byte_vec_t; - - void print_wasmer_error() { int error_len = wasmer_last_error_length(); @@ -86,12 +79,12 @@ int main() { memcpy(memory_buffer + current_offset, (void*)&dynamic_function_trampoline_pointers[0], sizeof(dynamic_function_trampoline_pointers)); current_offset += sizeof(dynamic_function_trampoline_pointers); - my_byte_vec_t module_byte_vec = { + wasm_byte_vec_t module_byte_vec = { .size = buffer_size, .data = memory_buffer, }; - wasm_module_t* module = wasm_module_deserialize(store, (wasm_byte_vec_t*) &module_byte_vec); + wasm_module_t* module = wasm_module_deserialize(store, &module_byte_vec); if (! module) { printf("Failed to create module\n"); print_wasmer_error(); From fdb077236a6847a360b6e4cefe845682548f04e0 Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Tue, 6 Oct 2020 22:19:50 +0200 Subject: [PATCH 147/281] feat(c-api) Implement `wasm_exporttype_delete`. --- lib/c-api/src/wasm_c_api/types/export.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/c-api/src/wasm_c_api/types/export.rs b/lib/c-api/src/wasm_c_api/types/export.rs index 1a9c03011..919e09271 100644 --- a/lib/c-api/src/wasm_c_api/types/export.rs +++ b/lib/c-api/src/wasm_c_api/types/export.rs @@ -30,6 +30,9 @@ pub extern "C" fn wasm_exporttype_type( unsafe { et.extern_type.as_ref() } } +#[no_mangle] +pub extern "C" fn wasm_exporttype_delete(_exporttype: Option>) {} + impl From for wasm_exporttype_t { fn from(other: ExportType) -> Self { (&other).into() From 7fdcdaa61c281f465f4c2b49126ba6e276195154 Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Tue, 6 Oct 2020 17:02:54 -0700 Subject: [PATCH 148/281] Add more changes from feedback; simplify C code with helper functions --- lib/cli/src/c_gen/mod.rs | 7 +- lib/cli/src/c_gen/object_file_header.rs | 93 +++++++++++++++++++ lib/engine-object-file/README.md | 60 +----------- lib/engine-object-file/src/artifact.rs | 12 ++- tests/integration/cli/src/compile.rs | 12 +-- .../src/object_file_engine_test_c_source.c | 60 +----------- 6 files changed, 113 insertions(+), 131 deletions(-) diff --git a/lib/cli/src/c_gen/mod.rs b/lib/cli/src/c_gen/mod.rs index cad34e340..d2248e3a2 100644 --- a/lib/cli/src/c_gen/mod.rs +++ b/lib/cli/src/c_gen/mod.rs @@ -3,6 +3,9 @@ pub mod object_file_header; +/// An identifier in C. +pub type CIdent = String; + /// A Type in the C language. #[derive(Debug, Clone)] pub enum CType { @@ -215,7 +218,7 @@ pub enum CStatement { /// A declaration of some kind. Declaration { /// The name of the thing being declared. - name: String, + name: CIdent, /// Whether the thing being declared is `extern`. is_extern: bool, /// Whether the thing being declared is `const`. @@ -253,7 +256,7 @@ pub enum CStatement { /// The type of the thing being typedef'd. source_type: CType, /// The new name by which this type may be called. - new_name: String, + new_name: CIdent, }, } diff --git a/lib/cli/src/c_gen/object_file_header.rs b/lib/cli/src/c_gen/object_file_header.rs index f517cdd61..6ffb96df2 100644 --- a/lib/cli/src/c_gen/object_file_header.rs +++ b/lib/cli/src/c_gen/object_file_header.rs @@ -4,6 +4,69 @@ use super::{generate_c, CStatement, CType}; use wasmer_compiler::{Symbol, SymbolRegistry}; use wasmer_vm::ModuleInfo; +/// Helper functions to simplify the usage of the object file engine. +const HELPER_FUNCTIONS: &str = r#" +wasm_byte_vec_t generate_serialized_data() { + // We need to pass all the bytes as one big buffer so we have to do all this logic to memcpy + // the various pieces together from the generated header file. + // + // We should provide a `deseralize_vectored` function to avoid requiring this extra work. + + char* byte_ptr = (char*)&WASMER_METADATA[0]; + + size_t num_function_pointers + = sizeof(function_pointers) / sizeof(void*); + size_t num_function_trampolines + = sizeof(function_trampolines) / sizeof(void*); + size_t num_dynamic_function_trampoline_pointers + = sizeof(dynamic_function_trampoline_pointers) / sizeof(void*); + + + size_t buffer_size = module_bytes_len + + sizeof(size_t) + sizeof(function_pointers) + + sizeof(size_t) + sizeof(function_trampolines) + + sizeof(size_t) + sizeof(dynamic_function_trampoline_pointers); + + char* memory_buffer = (char*) malloc(buffer_size); + size_t current_offset = 0; + + memcpy(memory_buffer + current_offset, byte_ptr, module_bytes_len); + current_offset += module_bytes_len; + + memcpy(memory_buffer + current_offset, (void*)&num_function_pointers, sizeof(size_t)); + current_offset += sizeof(size_t); + + memcpy(memory_buffer + current_offset, (void*)&function_pointers[0], sizeof(function_pointers)); + current_offset += sizeof(function_pointers); + + memcpy(memory_buffer + current_offset, (void*)&num_function_trampolines, sizeof(size_t)); + current_offset += sizeof(size_t); + + memcpy(memory_buffer + current_offset, (void*)&function_trampolines[0], sizeof(function_trampolines)); + current_offset += sizeof(function_trampolines); + + memcpy(memory_buffer + current_offset, (void*)&num_dynamic_function_trampoline_pointers, sizeof(size_t)); + current_offset += sizeof(size_t); + + memcpy(memory_buffer + current_offset, (void*)&dynamic_function_trampoline_pointers[0], sizeof(dynamic_function_trampoline_pointers)); + current_offset += sizeof(dynamic_function_trampoline_pointers); + + wasm_byte_vec_t module_byte_vec = { + .size = buffer_size, + .data = memory_buffer, + }; + return module_byte_vec; +} + +wasm_module_t* wasmer_object_file_engine_new(wasm_store_t* store) { + wasm_byte_vec_t module_byte_vec = generate_serialized_data(); + wasm_module_t* module = wasm_module_deserialize(store, &module_byte_vec); + free(module_byte_vec.data); + + return module; +} +"#; + /// Generate the header file that goes with the generated object file. pub fn generate_header_file( module_info: &ModuleInfo, @@ -11,6 +74,9 @@ pub fn generate_header_file( metadata_length: usize, ) -> String { let mut c_statements = vec![]; + c_statements.push(CStatement::LiteralConstant { + value: "#include \n\n".to_string(), + }); c_statements.push(CStatement::Declaration { name: "module_bytes_len".to_string(), is_extern: false, @@ -50,6 +116,13 @@ pub fn generate_header_file( definition: None, } }); + c_statements.push(CStatement::LiteralConstant { + value: r#" +// Compiled Wasm function pointers ordered by function index: the order they +// appeared in in the Wasm module. +"# + .to_string(), + }); c_statements.extend(function_declarations); // function pointer array @@ -106,6 +179,14 @@ pub fn generate_header_file( definition: None, } }); + c_statements.push(CStatement::LiteralConstant { + value: r#" +// Trampolines (functions by which we can call into Wasm) ordered by signature. +// There is 1 trampoline per function signature in the order they appear in +// the Wasm module. +"# + .to_string(), + }); c_statements.extend(func_trampoline_declarations); // function trampolines @@ -154,6 +235,14 @@ pub fn generate_header_file( definition: None, } }); + c_statements.push(CStatement::LiteralConstant { + value: r#" +// Dynamic trampolines are per-function and are used for each function where +// the type signature is not known statically. In this case, this corresponds to +// the imported functions. +"# + .to_string(), + }); c_statements.extend(dyn_func_declarations); c_statements.push(CStatement::TypeDef { @@ -191,6 +280,10 @@ pub fn generate_header_file( }); } + c_statements.push(CStatement::LiteralConstant { + value: HELPER_FUNCTIONS.to_string(), + }); + let inner_c = generate_c(&c_statements); // we wrap the inner C to work with C++ too diff --git a/lib/engine-object-file/README.md b/lib/engine-object-file/README.md index 9c8cde389..9379d92b1 100644 --- a/lib/engine-object-file/README.md +++ b/lib/engine-object-file/README.md @@ -36,9 +36,6 @@ extern "C" { #include #include -void wasmer_function__1(void); -void wasmer_trampoline_function_call__1(void*, void*, void*); - #ifdef __cplusplus } #endif @@ -52,72 +49,19 @@ void print_wasmer_error() printf("Error str: `%s`\n", error_str); } - int main() { printf("Initializing...\n"); wasm_config_t* config = wasm_config_new(); - wasm_config_set_compiler(config, CRANELIFT); wasm_config_set_engine(config, OBJECT_FILE); wasm_engine_t* engine = wasm_engine_new_with_config(config); wasm_store_t* store = wasm_store_new(engine); - char* byte_ptr = (char*)&WASMER_METADATA[0]; - - // We need to pass all the bytes as one big buffer so we have to do all this logic to memcpy - // the various pieces together from the generated header file. - // - // We should provide a `deseralize_vectored` function to avoid requiring this extra work. - - size_t num_function_pointers - = sizeof(function_pointers) / sizeof(void*); - size_t num_function_trampolines - = sizeof(function_trampolines) / sizeof(void*); - size_t num_dynamic_function_trampoline_pointers - = sizeof(dynamic_function_trampoline_pointers) / sizeof(void*); - - - size_t buffer_size = module_bytes_len - + sizeof(size_t) + sizeof(function_pointers) - + sizeof(size_t) + sizeof(function_trampolines) - + sizeof(size_t) + sizeof(dynamic_function_trampoline_pointers); - - char* memory_buffer = (char*) malloc(buffer_size); - size_t current_offset = 0; - printf("Buffer size: %zu\n", buffer_size); - - memcpy(memory_buffer + current_offset, byte_ptr, module_bytes_len); - current_offset += module_bytes_len; - - memcpy(memory_buffer + current_offset, (void*)&num_function_pointers, sizeof(size_t)); - current_offset += sizeof(size_t); - - memcpy(memory_buffer + current_offset, (void*)&function_pointers[0], sizeof(function_pointers)); - current_offset += sizeof(function_pointers); - - memcpy(memory_buffer + current_offset, (void*)&num_function_trampolines, sizeof(size_t)); - current_offset += sizeof(size_t); - - memcpy(memory_buffer + current_offset, (void*)&function_trampolines[0], sizeof(function_trampolines)); - current_offset += sizeof(function_trampolines); - - memcpy(memory_buffer + current_offset, (void*)&num_dynamic_function_trampoline_pointers, sizeof(size_t)); - current_offset += sizeof(size_t); - - memcpy(memory_buffer + current_offset, (void*)&dynamic_function_trampoline_pointers[0], sizeof(dynamic_function_trampoline_pointers)); - current_offset += sizeof(dynamic_function_trampoline_pointers); - - wasm_byte_vec_t module_byte_vec = { - .size = buffer_size, - .data = memory_buffer, - }; - - wasm_module_t* module = wasm_module_deserialize(store, &module_byte_vec); + wasm_module_t* module = wasmer_object_file_engine_new(store); if (! module) { printf("Failed to create module\n"); print_wasmer_error(); return -1; } - free(memory_buffer); // We have now finished the memory buffer book keeping and we have a valid Module. @@ -161,7 +105,7 @@ int main() { wasm_val_t* inout[2] = { NULL, NULL }; fflush(stdout); - // We're able to call our compiled functions directly through their trampolines. + // We're able to call our compiled function directly through a trampoline. wasmer_trampoline_function_call__1(vmctx, wasmer_function__1, &inout); wasm_instance_delete(instance); diff --git a/lib/engine-object-file/src/artifact.rs b/lib/engine-object-file/src/artifact.rs index 80d2ce33a..afc70684d 100644 --- a/lib/engine-object-file/src/artifact.rs +++ b/lib/engine-object-file/src/artifact.rs @@ -211,6 +211,15 @@ impl ObjectFileArtifact { module_translation.as_ref().unwrap(), function_body_inputs, )?; + // there's an ordering issue, but we can update function_body_lengths here. + /* + // We construct the function body lengths + let function_body_lengths = compilation + .get_function_bodies() + .values() + .map(|function_body| function_body.body.len() as u64) + .collect::>(); + */ let mut obj = get_object_for_target(&target_triple).map_err(to_compile_error)?; emit_data(&mut obj, WASMER_METADATA_SYMBOL, &metadata_binary) .map_err(to_compile_error)?; @@ -391,8 +400,7 @@ impl ObjectFileArtifact { Ok(Self { metadata, - // TODO: review - module_bytes: vec![], + module_bytes: bytes.to_owned(), finished_functions: finished_functions.into_boxed_slice(), finished_dynamic_function_trampolines: finished_dynamic_function_trampolines .into_boxed_slice(), diff --git a/tests/integration/cli/src/compile.rs b/tests/integration/cli/src/compile.rs index 9b9cb4282..b14635b37 100644 --- a/tests/integration/cli/src/compile.rs +++ b/tests/integration/cli/src/compile.rs @@ -300,17 +300,7 @@ fn object_file_engine_works() -> anyhow::Result<()> { let result = run_code(&executable_path).context("Failed to run generated executable")?; let result_lines = result.lines().collect::>(); - assert_eq!( - result_lines, - vec![ - "Initializing...", - #[cfg(windows)] - "Buffer size: 1801376", - #[cfg(not(windows))] - "Buffer size: 1801380", - "\"Hello, World\"" - ], - ); + assert_eq!(result_lines, vec!["Initializing...", "\"Hello, World\""],); Ok(()) } diff --git a/tests/integration/cli/src/object_file_engine_test_c_source.c b/tests/integration/cli/src/object_file_engine_test_c_source.c index 74b4a3696..35ea689f6 100644 --- a/tests/integration/cli/src/object_file_engine_test_c_source.c +++ b/tests/integration/cli/src/object_file_engine_test_c_source.c @@ -9,9 +9,6 @@ extern "C" { #include #include -void wasmer_function__1(void); -void wasmer_trampoline_function_call__1(void*, void*, void*); - #ifdef __cplusplus } #endif @@ -25,72 +22,19 @@ void print_wasmer_error() printf("Error str: `%s`\n", error_str); } - int main() { printf("Initializing...\n"); wasm_config_t* config = wasm_config_new(); - wasm_config_set_compiler(config, CRANELIFT); wasm_config_set_engine(config, OBJECT_FILE); wasm_engine_t* engine = wasm_engine_new_with_config(config); wasm_store_t* store = wasm_store_new(engine); - char* byte_ptr = (char*)&WASMER_METADATA[0]; - - // We need to pass all the bytes as one big buffer so we have to do all this logic to memcpy - // the various pieces together from the generated header file. - // - // We should provide a `deseralize_vectored` function to avoid requiring this extra work. - - size_t num_function_pointers - = sizeof(function_pointers) / sizeof(void*); - size_t num_function_trampolines - = sizeof(function_trampolines) / sizeof(void*); - size_t num_dynamic_function_trampoline_pointers - = sizeof(dynamic_function_trampoline_pointers) / sizeof(void*); - - - size_t buffer_size = module_bytes_len - + sizeof(size_t) + sizeof(function_pointers) - + sizeof(size_t) + sizeof(function_trampolines) - + sizeof(size_t) + sizeof(dynamic_function_trampoline_pointers); - - char* memory_buffer = (char*) malloc(buffer_size); - size_t current_offset = 0; - printf("Buffer size: %zu\n", buffer_size); - - memcpy(memory_buffer + current_offset, byte_ptr, module_bytes_len); - current_offset += module_bytes_len; - - memcpy(memory_buffer + current_offset, (void*)&num_function_pointers, sizeof(size_t)); - current_offset += sizeof(size_t); - - memcpy(memory_buffer + current_offset, (void*)&function_pointers[0], sizeof(function_pointers)); - current_offset += sizeof(function_pointers); - - memcpy(memory_buffer + current_offset, (void*)&num_function_trampolines, sizeof(size_t)); - current_offset += sizeof(size_t); - - memcpy(memory_buffer + current_offset, (void*)&function_trampolines[0], sizeof(function_trampolines)); - current_offset += sizeof(function_trampolines); - - memcpy(memory_buffer + current_offset, (void*)&num_dynamic_function_trampoline_pointers, sizeof(size_t)); - current_offset += sizeof(size_t); - - memcpy(memory_buffer + current_offset, (void*)&dynamic_function_trampoline_pointers[0], sizeof(dynamic_function_trampoline_pointers)); - current_offset += sizeof(dynamic_function_trampoline_pointers); - - wasm_byte_vec_t module_byte_vec = { - .size = buffer_size, - .data = memory_buffer, - }; - - wasm_module_t* module = wasm_module_deserialize(store, &module_byte_vec); + wasm_module_t* module = wasmer_object_file_engine_new(store); if (! module) { printf("Failed to create module\n"); print_wasmer_error(); return -1; } - free(memory_buffer); // We have now finished the memory buffer book keeping and we have a valid Module. @@ -134,7 +78,7 @@ int main() { wasm_val_t* inout[2] = { NULL, NULL }; fflush(stdout); - // We're able to call our compiled functions directly through their trampolines. + // We're able to call our compiled function directly through a trampoline. wasmer_trampoline_function_call__1(vmctx, wasmer_function__1, &inout); wasm_instance_delete(instance); From 52d1f86f4709a1d65f74fdf156c8086d6a269c61 Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Tue, 6 Oct 2020 17:31:26 -0700 Subject: [PATCH 149/281] Add no-op keyed helper function for object file engine generated C --- lib/cli/src/c_gen/object_file_header.rs | 3 ++- lib/engine-object-file/README.md | 4 ++-- tests/integration/cli/src/object_file_engine_test_c_source.c | 4 ++-- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/lib/cli/src/c_gen/object_file_header.rs b/lib/cli/src/c_gen/object_file_header.rs index 6ffb96df2..5ccb747c7 100644 --- a/lib/cli/src/c_gen/object_file_header.rs +++ b/lib/cli/src/c_gen/object_file_header.rs @@ -58,7 +58,8 @@ wasm_byte_vec_t generate_serialized_data() { return module_byte_vec; } -wasm_module_t* wasmer_object_file_engine_new(wasm_store_t* store) { +wasm_module_t* wasmer_object_file_engine_new(wasm_store_t* store, const char* wasm_name) { + // wasm_name intentionally unsused for now: will be used in the future. wasm_byte_vec_t module_byte_vec = generate_serialized_data(); wasm_module_t* module = wasm_module_deserialize(store, &module_byte_vec); free(module_byte_vec.data); diff --git a/lib/engine-object-file/README.md b/lib/engine-object-file/README.md index 9379d92b1..59b86b630 100644 --- a/lib/engine-object-file/README.md +++ b/lib/engine-object-file/README.md @@ -56,7 +56,7 @@ int main() { wasm_engine_t* engine = wasm_engine_new_with_config(config); wasm_store_t* store = wasm_store_new(engine); - wasm_module_t* module = wasmer_object_file_engine_new(store); + wasm_module_t* module = wasmer_object_file_engine_new(store, "qjs.wasm"); if (! module) { printf("Failed to create module\n"); print_wasmer_error(); @@ -65,7 +65,7 @@ int main() { // We have now finished the memory buffer book keeping and we have a valid Module. - // In this example we're passing some JavaScript source code as a command line argumnet + // In this example we're passing some JavaScript source code as a command line argument // to a WASI module that can evaluate JavaScript. wasi_config_t* wasi_config = wasi_config_new("constant_value_here"); const char* js_string = "function greet(name) { return JSON.stringify('Hello, ' + name); }; print(greet('World'));"; diff --git a/tests/integration/cli/src/object_file_engine_test_c_source.c b/tests/integration/cli/src/object_file_engine_test_c_source.c index 35ea689f6..ec00f9179 100644 --- a/tests/integration/cli/src/object_file_engine_test_c_source.c +++ b/tests/integration/cli/src/object_file_engine_test_c_source.c @@ -29,7 +29,7 @@ int main() { wasm_engine_t* engine = wasm_engine_new_with_config(config); wasm_store_t* store = wasm_store_new(engine); - wasm_module_t* module = wasmer_object_file_engine_new(store); + wasm_module_t* module = wasmer_object_file_engine_new(store, "qjs.wasm"); if (! module) { printf("Failed to create module\n"); print_wasmer_error(); @@ -38,7 +38,7 @@ int main() { // We have now finished the memory buffer book keeping and we have a valid Module. - // In this example we're passing some JavaScript source code as a command line argumnet + // In this example we're passing some JavaScript source code as a command line argument // to a WASI module that can evaluate JavaScript. wasi_config_t* wasi_config = wasi_config_new("constant_value_here"); const char* js_string = "function greet(name) { return JSON.stringify('Hello, ' + name); }; print(greet('World'));"; From e6bc138b1040956f307b87a9eb1cf563c5001ac0 Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Tue, 6 Oct 2020 17:39:51 -0700 Subject: [PATCH 150/281] Remove ability to use object file engine with compiler from C API Due to the way object file engine works, it only makes sense to use in headless mode from the C API. --- lib/c-api/src/wasm_c_api/engine.rs | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/lib/c-api/src/wasm_c_api/engine.rs b/lib/c-api/src/wasm_c_api/engine.rs index 613b6a60d..72aacf2c5 100644 --- a/lib/c-api/src/wasm_c_api/engine.rs +++ b/lib/c-api/src/wasm_c_api/engine.rs @@ -141,14 +141,8 @@ cfg_if! { Box::new(wasm_engine_t { inner: engine }) } } - else if #[cfg(all(feature = "object-file", feature = "compiler"))] { - #[no_mangle] - pub extern "C" fn wasm_engine_new() -> Box { - let mut compiler_config: Box = get_default_compiler_config(); - let engine: Arc = Arc::new(ObjectFile::new(&mut *compiler_config).engine()); - Box::new(wasm_engine_t { inner: engine }) - } - } + // There are currently no uses of the object-file engine + compiler from the C API. + // So if we get here, we default to headless mode regardless of if `compiler` is enabled. else if #[cfg(feature = "object-file")] { #[no_mangle] pub extern "C" fn wasm_engine_new() -> Box { @@ -227,8 +221,10 @@ pub extern "C" fn wasm_engine_new_with_config( }, wasmer_engine_t::OBJECT_FILE => { cfg_if! { + // There are currently no uses of the object-file engine + compiler from the C API. + // So we run in headless mode. if #[cfg(feature = "object-file")] { - Arc::new(ObjectFile::new(&mut *compiler_config).engine()) + Arc::new(ObjectFile::headless().engine()) } else { return None; } From cb14c7a8ae7c6dd954df103e2b1fcafab004a25d Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Tue, 6 Oct 2020 17:46:55 -0700 Subject: [PATCH 151/281] Clean up engine object file artifact --- lib/engine-object-file/src/artifact.rs | 23 +++-------------------- 1 file changed, 3 insertions(+), 20 deletions(-) diff --git a/lib/engine-object-file/src/artifact.rs b/lib/engine-object-file/src/artifact.rs index afc70684d..72f158870 100644 --- a/lib/engine-object-file/src/artifact.rs +++ b/lib/engine-object-file/src/artifact.rs @@ -326,12 +326,7 @@ impl ObjectFileArtifact { } sp.ptr = usize::from_ne_bytes(byte_buffer); cur_offset += WORD_SIZE; - // REVIEW: we can also serialize and read back lengths, do we want to do this? - /*for j in 0..WORD_SIZE { - byte_buffer[j] = bytes[cur_offset + j]; - } - sp.len = usize::from_ne_bytes(byte_buffer); - cur_offset += WORD_SIZE;*/ + // TODO: we can read back the length here if we serialize it. This will improve debug output. let fp = FunctionBodyPtr(mem::transmute(sp)); finished_functions.push(fp); @@ -363,12 +358,7 @@ impl ObjectFileArtifact { let func_type = &metadata.compile_info.module.signatures[SignatureIndex::new(i)]; engine_inner.add_trampoline(func_type, trampoline); - // REVIEW: we can also serialize and read back lengths, do we want to do this? - /*for j in 0..WORD_SIZE { - byte_buffer[j] = bytes[cur_offset + j]; - } - sp.len = usize::from_ne_bytes(byte_buffer); - cur_offset += WORD_SIZE;*/ + // TODO: we can read back the length here if we serialize it. This will improve debug output. } // read dynamic function trampolines in order now... @@ -386,13 +376,7 @@ impl ObjectFileArtifact { sp.ptr = usize::from_ne_bytes(byte_buffer); cur_offset += WORD_SIZE; - // REVIEW: we can also serialize and read back lengths, do we want to do this? - /*for j in 0..WORD_SIZE { - byte_buffer[j] = bytes[cur_offset + j]; - } - sp.len = usize::from_ne_bytes(byte_buffer); - cur_offset += WORD_SIZE;*/ - + // TODO: we can read back the length here if we serialize it. This will improve debug output. let fp = FunctionBodyPtr(mem::transmute(sp)); finished_dynamic_function_trampolines.push(fp); @@ -466,7 +450,6 @@ impl Artifact for ObjectFileArtifact { } fn preinstantiate(&self) -> Result<(), InstantiationError> { - //todo!("figure out what preinstantiate means here"); Ok(()) } From f7d5a11b39b29789590c13b22c67da2f499a8043 Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Wed, 7 Oct 2020 16:38:23 -0700 Subject: [PATCH 152/281] Fix sentinel value in wasm_limits_t for memory in wasm_c_api --- lib/c-api/src/wasm_c_api/types/memory.rs | 4 ++-- lib/c-api/tests/wasm_c_api/test-memory.c | 20 ++++++++++++++++++-- 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/lib/c-api/src/wasm_c_api/types/memory.rs b/lib/c-api/src/wasm_c_api/types/memory.rs index e810092ba..077eb772b 100644 --- a/lib/c-api/src/wasm_c_api/types/memory.rs +++ b/lib/c-api/src/wasm_c_api/types/memory.rs @@ -33,8 +33,8 @@ pub struct wasm_limits_t { #[no_mangle] pub unsafe extern "C" fn wasm_memorytype_new(limits: &wasm_limits_t) -> Box { let min_pages = Pages(limits.min as _); - // TODO: investigate if `0` is in fact a sentinel value here - let max_pages = if limits.max == 0 { + // u32::max_value() is a sentinel value for no max specified + let max_pages = if limits.max == u32::max_value() { None } else { Some(Pages(limits.max as _)) diff --git a/lib/c-api/tests/wasm_c_api/test-memory.c b/lib/c-api/tests/wasm_c_api/test-memory.c index aa69aedce..3d4c8abe7 100644 --- a/lib/c-api/tests/wasm_c_api/test-memory.c +++ b/lib/c-api/tests/wasm_c_api/test-memory.c @@ -21,20 +21,22 @@ int main(int argc, const char *argv[]) { own wasm_engine_t* engine = wasm_engine_new(); own wasm_store_t* store = wasm_store_new(engine); + // ===================== wasm_limits_t limits1 = { .min = 0, - .max = wasm_limits_max_default, + .max = 0x7FFFFFFF, }; own wasm_memorytype_t* memtype1 = wasm_memorytype_new(&limits1); own wasm_memory_t* memory1 = wasm_memory_new(store, memtype1); assert(memory1 == NULL); char* error = get_wasmer_error(); printf("Found error string: %s\n", error); - assert(0 == strcmp("The maximum requested memory (4294967295 pages) is greater than the maximum allowed memory (65536 pages)", error)); + assert(0 == strcmp("The maximum requested memory (2147483647 pages) is greater than the maximum allowed memory (65536 pages)", error)); free(error); wasm_memorytype_delete(memtype1); + // ===================== wasm_limits_t limits2 = { .min = 15, .max = 25, @@ -46,6 +48,20 @@ int main(int argc, const char *argv[]) { wasm_memorytype_delete(memtype2); wasm_memory_delete(memory2); + // ===================== + wasm_limits_t limits3 = { + .min = 15, + .max = wasm_limits_max_default, + }; + own wasm_memorytype_t* memtype3 = wasm_memorytype_new(&limits3); + own wasm_memory_t* memory3 = wasm_memory_new(store, memtype3); + assert(memory3 != NULL); + int size = wasm_memory_size(memory3); + printf("memory size: %d\n", size); + + wasm_memorytype_delete(memtype3); + wasm_memory_delete(memory3); + printf("Shutting down...\n"); wasm_store_delete(store); wasm_engine_delete(engine); From f24a34b6cf62d5ede45445065b432b4dff8d33df Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Thu, 8 Oct 2020 13:38:01 +0200 Subject: [PATCH 153/281] feat(c-api) Implement `Drop` for `wasm_exporttype_t`. `wasm_exporttype_t` has 2 fields: `name` and `extern_type`. Both are of kind `NonNull`. When `wasm_exporttype_t` is dropped, nor `name` nor `extern_type` are going to be dropped. To avoid leaking data, this patch adds a new field: `owns_fields`: * When `wasm_exporttype_t` is built from `wasm_exportype_new`, this field is set to `false` because `name` and `extern_type` are received by pointer, and its the responsibility of the caller to free them, * When `wasm_exporttype_t` is built from the `From<&ExportType>` implementation, _we_ create `name` and `extern_type` to then leak them. In this case, it is safe to reconstruct proper `Box`es to finally drop them. --- lib/c-api/src/wasm_c_api/types/export.rs | 27 ++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/lib/c-api/src/wasm_c_api/types/export.rs b/lib/c-api/src/wasm_c_api/types/export.rs index 919e09271..cd05ff6c6 100644 --- a/lib/c-api/src/wasm_c_api/types/export.rs +++ b/lib/c-api/src/wasm_c_api/types/export.rs @@ -6,6 +6,7 @@ use wasmer::ExportType; pub struct wasm_exporttype_t { name: NonNull, extern_type: NonNull, + owns_fields: bool, } wasm_declare_boxed_vec!(exporttype); @@ -15,7 +16,11 @@ pub extern "C" fn wasm_exporttype_new( name: NonNull, extern_type: NonNull, ) -> Box { - Box::new(wasm_exporttype_t { name, extern_type }) + Box::new(wasm_exporttype_t { + name, + extern_type, + owns_fields: false, + }) } #[no_mangle] @@ -33,6 +38,20 @@ pub extern "C" fn wasm_exporttype_type( #[no_mangle] pub extern "C" fn wasm_exporttype_delete(_exporttype: Option>) {} +impl Drop for wasm_exporttype_t { + fn drop(&mut self) { + if self.owns_fields { + // SAFETY: `owns_fields` is set to `true` only in + // `wasm_exporttype_t.from(&ExportType)`, where the data + // are leaked properly and won't be freed somewhere else. + unsafe { + let _ = Box::from_raw(self.name.as_ptr()); + let _ = Box::from_raw(self.extern_type.as_ptr()); + } + } + } +} + impl From for wasm_exporttype_t { fn from(other: ExportType) -> Self { (&other).into() @@ -59,6 +78,10 @@ impl From<&ExportType> for wasm_exporttype_t { unsafe { NonNull::new_unchecked(Box::into_raw(Box::new(extern_type))) } }; - wasm_exporttype_t { name, extern_type } + wasm_exporttype_t { + name, + extern_type, + owns_fields: true, + } } } From 3ebff7426338fae1c96a1fe834ce8672417d6644 Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Thu, 8 Oct 2020 13:43:59 +0200 Subject: [PATCH 154/281] doc(c-api) Update inline API documentation. --- lib/c-api/src/wasm_c_api/types/export.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/c-api/src/wasm_c_api/types/export.rs b/lib/c-api/src/wasm_c_api/types/export.rs index cd05ff6c6..1476ecb5b 100644 --- a/lib/c-api/src/wasm_c_api/types/export.rs +++ b/lib/c-api/src/wasm_c_api/types/export.rs @@ -6,6 +6,9 @@ use wasmer::ExportType; pub struct wasm_exporttype_t { name: NonNull, extern_type: NonNull, + + /// If `true`, `name` and `extern_type` will be dropped by + /// `wasm_exporttype_t::drop`. owns_fields: bool, } @@ -42,7 +45,7 @@ impl Drop for wasm_exporttype_t { fn drop(&mut self) { if self.owns_fields { // SAFETY: `owns_fields` is set to `true` only in - // `wasm_exporttype_t.from(&ExportType)`, where the data + // `wasm_exporttype_t::from(&ExportType)`, where the data // are leaked properly and won't be freed somewhere else. unsafe { let _ = Box::from_raw(self.name.as_ptr()); From 5dbab5655ec0302396abe6453e9fbb998121ace4 Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Thu, 8 Oct 2020 15:05:13 +0200 Subject: [PATCH 155/281] feat(c-api) Use `Option>` in `wasm_valtype_kind`. A more Rust-FFI idiomatic way to handle null pointer. Note: In `wasm_valtype_kind`, it's tricky to handle the error because we _must_ return a `wasm_valtype_kind` value. For the moment, it continues to panic, which is probably the best tradeoff. --- lib/c-api/src/wasm_c_api/types/value.rs | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/lib/c-api/src/wasm_c_api/types/value.rs b/lib/c-api/src/wasm_c_api/types/value.rs index 542833638..023539c36 100644 --- a/lib/c-api/src/wasm_c_api/types/value.rs +++ b/lib/c-api/src/wasm_c_api/types/value.rs @@ -1,5 +1,6 @@ use super::super::value::wasm_valkind_t; use std::convert::TryInto; +use std::ptr::NonNull; use wasmer::ValType; #[allow(non_camel_case_types)] @@ -83,10 +84,11 @@ pub extern "C" fn wasm_valtype_new(kind: wasm_valkind_t) -> Option>) {} #[no_mangle] -pub unsafe extern "C" fn wasm_valtype_kind(valtype: *const wasm_valtype_t) -> wasm_valkind_t { - if valtype.is_null() { - // TODO: handle error - panic!("wasm_valtype_kind: argument is null pointer"); - } - return (*valtype).valkind as wasm_valkind_t; +pub unsafe extern "C" fn wasm_valtype_kind( + valtype: Option>, +) -> wasm_valkind_t { + valtype + .expect("`wasm_valtype_kind: argument is a null pointer") + .as_ref() + .valkind as wasm_valkind_t } From 5d19813e63ab892c70a135575f724283540830eb Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Thu, 8 Oct 2020 17:14:45 +0200 Subject: [PATCH 156/281] fix(c-api) `wasm_limits_t` contains `Pages`, not `Bytes`. When building a `wasm_memorytype_t` with `wasm_memorytype_new`, we pass a `wasm_limits_t`, where `min` and `max` represent `Pages`. This semantics is set by `wasm_memorytype_new` itself where `min` and `max` from `wasm_limits_t` are used to compute `Pages`, which are then passed to `MemoryType`. Then, in `wasm_memorytype_limits`, we expect to get the same `wasm_limits_t` given to `wasm_memorytype_new`. But it's not! The same `MemoryType` is read, good. The `minimum` and `maximum` fields are `Pages`, good. Then, we compute the `min` and `max` values for the resulting `wasm_limits_t`, which receive `Page.bytes().0`, not good! We don't want the number of bytes, but the number of pages. This patch fixes that. --- lib/c-api/src/wasm_c_api/types/memory.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/c-api/src/wasm_c_api/types/memory.rs b/lib/c-api/src/wasm_c_api/types/memory.rs index 077eb772b..ed772c0bc 100644 --- a/lib/c-api/src/wasm_c_api/types/memory.rs +++ b/lib/c-api/src/wasm_c_api/types/memory.rs @@ -39,6 +39,7 @@ pub unsafe extern "C" fn wasm_memorytype_new(limits: &wasm_limits_t) -> Box *const wasm_limits_t { let md = mt.as_memorytype(); + Box::into_raw(Box::new(wasm_limits_t { - min: md.minimum.bytes().0 as _, - max: md.maximum.map(|max| max.bytes().0 as _).unwrap_or(0), + min: md.minimum.0 as _, + max: md.maximum.map(|max| max.0 as _).unwrap_or(0), })) } From f6595cdd33ca866998822a0846dcbecc571bc5e5 Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Thu, 8 Oct 2020 17:23:59 +0200 Subject: [PATCH 157/281] fix(c-api) Fix the sentinel value returned by `wasm_memorytype_limits`. --- lib/c-api/src/wasm_c_api/types/memory.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/c-api/src/wasm_c_api/types/memory.rs b/lib/c-api/src/wasm_c_api/types/memory.rs index ed772c0bc..a9e46e841 100644 --- a/lib/c-api/src/wasm_c_api/types/memory.rs +++ b/lib/c-api/src/wasm_c_api/types/memory.rs @@ -58,6 +58,6 @@ pub unsafe extern "C" fn wasm_memorytype_limits(mt: &wasm_memorytype_t) -> *cons Box::into_raw(Box::new(wasm_limits_t { min: md.minimum.0 as _, - max: md.maximum.map(|max| max.0 as _).unwrap_or(0), + max: md.maximum.map(|max| max.0 as _).unwrap_or(u32::max_value()), })) } From 80459f3ae05b7c66776400fd4facd968f1556355 Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Thu, 8 Oct 2020 17:24:12 +0200 Subject: [PATCH 158/281] feat(c-api) Replace the max limit sentinel value by a constant. In the `wasm.h` header file, it is defined by `wasm_limits_max_default`. --- lib/c-api/src/wasm_c_api/types/memory.rs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/lib/c-api/src/wasm_c_api/types/memory.rs b/lib/c-api/src/wasm_c_api/types/memory.rs index a9e46e841..9edd5bf37 100644 --- a/lib/c-api/src/wasm_c_api/types/memory.rs +++ b/lib/c-api/src/wasm_c_api/types/memory.rs @@ -30,11 +30,13 @@ pub struct wasm_limits_t { pub(crate) max: u32, } +const LIMITS_MAX_SENTINEL: u32 = u32::max_value(); + #[no_mangle] pub unsafe extern "C" fn wasm_memorytype_new(limits: &wasm_limits_t) -> Box { let min_pages = Pages(limits.min as _); // u32::max_value() is a sentinel value for no max specified - let max_pages = if limits.max == u32::max_value() { + let max_pages = if limits.max == LIMITS_MAX_SENTINEL { None } else { Some(Pages(limits.max as _)) @@ -58,6 +60,9 @@ pub unsafe extern "C" fn wasm_memorytype_limits(mt: &wasm_memorytype_t) -> *cons Box::into_raw(Box::new(wasm_limits_t { min: md.minimum.0 as _, - max: md.maximum.map(|max| max.0 as _).unwrap_or(u32::max_value()), + max: md + .maximum + .map(|max| max.0 as _) + .unwrap_or(LIMITS_MAX_SENTINEL), })) } From 3e77b8f2f5c295a72fcd74fa559a3736e355fec5 Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Thu, 8 Oct 2020 17:27:45 +0200 Subject: [PATCH 159/281] doc(changelog) Add #1690. --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0b0573bd9..bd944d264 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ # Changelog ## **[Unreleased]** +- [#1690](https://github.com/wasmerio/wasmer/pull/1690) Fix `wasm_memorytype_limits` where `min` and `max` represents pages, not bytes. Additionally, fixes the max limit sentinel value. - [#1635](https://github.com/wasmerio/wasmer/pull/1635) Implement `wat2wasm` in the Wasm C API. - [#1636](https://github.com/wasmerio/wasmer/pull/1636) Implement `wasm_module_validate` in the Wasm C API. - [#1671](https://github.com/wasmerio/wasmer/pull/1671) Fix probestack firing inappropriately, and sometimes over/under allocating stack. From 4a1f440d474a0065e806b63198953a18f534430d Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Thu, 8 Oct 2020 11:11:46 -0700 Subject: [PATCH 160/281] Bump Rust CI version to 1.46.0 --- .github/workflows/benchmark.yaml | 2 +- .github/workflows/coverage.yaml | 2 +- .github/workflows/lint.yaml | 2 +- .github/workflows/main.yaml | 8 ++++---- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/benchmark.yaml b/.github/workflows/benchmark.yaml index 6e88bb9a9..f15dbcab2 100644 --- a/.github/workflows/benchmark.yaml +++ b/.github/workflows/benchmark.yaml @@ -16,7 +16,7 @@ jobs: include: - build: linux os: ubuntu-latest - rust: 1.45.0 + rust: 1.46.0 env: CARGO_SCCACHE_VERSION: 0.2.13 SCCACHE_AZURE_BLOB_CONTAINER: wasmerstoragesccacheblob diff --git a/.github/workflows/coverage.yaml b/.github/workflows/coverage.yaml index e4070468a..cd86d13f2 100644 --- a/.github/workflows/coverage.yaml +++ b/.github/workflows/coverage.yaml @@ -22,7 +22,7 @@ jobs: uses: actions-rs/toolchain@v1 with: profile: minimal - toolchain: 1.45.0 + toolchain: 1.46.0 override: true - name: Install LLVM (Linux) run: | diff --git a/.github/workflows/lint.yaml b/.github/workflows/lint.yaml index 27485ac74..0395d30c3 100644 --- a/.github/workflows/lint.yaml +++ b/.github/workflows/lint.yaml @@ -19,7 +19,7 @@ jobs: uses: actions-rs/toolchain@v1 with: profile: minimal - toolchain: 1.45.0 + toolchain: 1.46.0 override: true components: rustfmt, clippy - run: make lint diff --git a/.github/workflows/main.yaml b/.github/workflows/main.yaml index a9911f376..a2e1d1bd0 100644 --- a/.github/workflows/main.yaml +++ b/.github/workflows/main.yaml @@ -42,24 +42,24 @@ jobs: include: - build: linux os: ubuntu-latest - rust: 1.45.2 + rust: 1.46.0 llvm_url: 'https://github.com/llvm/llvm-project/releases/download/llvmorg-10.0.0/clang+llvm-10.0.0-x86_64-linux-gnu-ubuntu-18.04.tar.xz' artifact_name: 'wasmer-linux-amd64' run_integration_tests: true - build: macos os: macos-latest - rust: 1.45.2 + rust: 1.46.0 llvm_url: 'https://github.com/llvm/llvm-project/releases/download/llvmorg-10.0.0/clang+llvm-10.0.0-x86_64-apple-darwin.tar.xz' artifact_name: 'wasmer-macos-amd64' run_integration_tests: true - build: windows os: windows-latest - rust: 1.45.2 + rust: 1.46.0 artifact_name: 'wasmer-windows-amd64' run_integration_tests: true - build: linux-aarch64 os: [self-hosted, linux, ARM64] - rust: 1.45.2 + rust: 1.46.0 llvm_url: 'https://github.com/llvm/llvm-project/releases/download/llvmorg-10.0.0/clang+llvm-10.0.0-aarch64-linux-gnu.tar.xz' artifact_name: 'wasmer-linux-aarch64' run_integration_tests: false From 65265dbd73c01c8660ed79b570ebef9de8e07a2c Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Thu, 8 Oct 2020 14:13:54 -0700 Subject: [PATCH 161/281] Add first draft of `wasmer create-exe` --- Cargo.lock | 1 + lib/c-api/wasmer_wasm.h | 3 + lib/cli/Cargo.toml | 1 + lib/cli/src/bin/wasmer.rs | 9 + lib/cli/src/commands.rs | 4 + lib/cli/src/commands/compile.rs | 5 +- lib/cli/src/commands/create_exe.rs | 273 +++++++++++++++++ lib/cli/src/commands/wasmer_create_exe_main.c | 89 ++++++ lib/cli/src/store.rs | 286 ++++++++++-------- 9 files changed, 543 insertions(+), 128 deletions(-) create mode 100644 lib/cli/src/commands/create_exe.rs create mode 100644 lib/cli/src/commands/wasmer_create_exe_main.c diff --git a/Cargo.lock b/Cargo.lock index e27fa5c4a..3ce702103 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2213,6 +2213,7 @@ dependencies = [ "fern", "log", "structopt", + "tempfile", "wasmer", "wasmer-cache", "wasmer-compiler", diff --git a/lib/c-api/wasmer_wasm.h b/lib/c-api/wasmer_wasm.h index 885102827..b9eea99ae 100644 --- a/lib/c-api/wasmer_wasm.h +++ b/lib/c-api/wasmer_wasm.h @@ -28,6 +28,9 @@ # define DEPRECATED(message) __declspec(deprecated(message)) #endif +// The `jit` feature has been enabled for this build. +#define WASMER_JIT_ENABLED + // The `compiler` feature has been enabled for this build. #define WASMER_COMPILER_ENABLED diff --git a/lib/cli/Cargo.toml b/lib/cli/Cargo.toml index b73828bf8..19f353b9c 100644 --- a/lib/cli/Cargo.toml +++ b/lib/cli/Cargo.toml @@ -45,6 +45,7 @@ cfg-if = "0.1" # For debug feature fern = { version = "0.6", features = ["colored"], optional = true } log = { version = "0.4", optional = true } +tempfile = "3" [features] # Don't add the compiler features in default, please add them on the Makefile diff --git a/lib/cli/src/bin/wasmer.rs b/lib/cli/src/bin/wasmer.rs index 2b1d5792e..6d72964bf 100644 --- a/lib/cli/src/bin/wasmer.rs +++ b/lib/cli/src/bin/wasmer.rs @@ -1,4 +1,6 @@ use anyhow::Result; +#[cfg(feature = "object-file")] +use wasmer_cli::commands::CreateExe; #[cfg(feature = "wast")] use wasmer_cli::commands::Wast; use wasmer_cli::commands::{Cache, Compile, Config, Inspect, Run, SelfUpdate, Validate}; @@ -26,6 +28,11 @@ enum WasmerCLIOptions { #[structopt(name = "compile")] Compile(Compile), + /// Compile a WebAssembly binary into a native executable + #[cfg(feature = "object-file")] + #[structopt(name = "create-exe")] + CreateExe(CreateExe), + /// Get various configuration information needed /// to compile programs which use Wasmer #[structopt(name = "config")] @@ -53,6 +60,8 @@ impl WasmerCLIOptions { Self::Cache(cache) => cache.execute(), Self::Validate(validate) => validate.execute(), Self::Compile(compile) => compile.execute(), + #[cfg(feature = "object-file")] + Self::CreateExe(create_exe) => create_exe.execute(), Self::Config(config) => config.execute(), Self::Inspect(inspect) => inspect.execute(), #[cfg(feature = "wast")] diff --git a/lib/cli/src/commands.rs b/lib/cli/src/commands.rs index fe7036e36..4d07c37e8 100644 --- a/lib/cli/src/commands.rs +++ b/lib/cli/src/commands.rs @@ -2,6 +2,8 @@ mod cache; mod compile; mod config; +#[cfg(feature = "object-file")] +mod create_exe; mod inspect; mod run; mod self_update; @@ -9,6 +11,8 @@ mod validate; #[cfg(feature = "wast")] mod wast; +#[cfg(feature = "object-file")] +pub use create_exe::*; #[cfg(feature = "wast")] pub use wast::*; pub use {cache::*, compile::*, config::*, inspect::*, run::*, self_update::*, validate::*}; diff --git a/lib/cli/src/commands/compile.rs b/lib/cli/src/commands/compile.rs index 1e77a08f2..bd70d6ffc 100644 --- a/lib/cli/src/commands/compile.rs +++ b/lib/cli/src/commands/compile.rs @@ -38,8 +38,7 @@ impl Compile { .context(format!("failed to compile `{}`", self.path.display())) } - fn get_recommend_extension( - &self, + pub(crate) fn get_recommend_extension( engine_type: &EngineType, target_triple: &Triple, ) -> &'static str { @@ -82,7 +81,7 @@ impl Compile { .file_stem() .map(|osstr| osstr.to_string_lossy().to_string()) .unwrap_or_default(); - let recommended_extension = self.get_recommend_extension(&engine_type, target.triple()); + let recommended_extension = Self::get_recommend_extension(&engine_type, target.triple()); match self.output.extension() { Some(ext) => { if ext != recommended_extension { diff --git a/lib/cli/src/commands/create_exe.rs b/lib/cli/src/commands/create_exe.rs new file mode 100644 index 000000000..0238da708 --- /dev/null +++ b/lib/cli/src/commands/create_exe.rs @@ -0,0 +1,273 @@ +//! Create a standalone native executable for a given Wasm file. + +use crate::store::{CompilerOptions, EngineType}; +use anyhow::{Context, Result}; +use std::env; +use std::fs; +use std::path::{Path, PathBuf}; +use std::process::Command; +use structopt::StructOpt; +use wasmer::*; + +const WASMER_MAIN_C_SOURCE: &[u8] = include_bytes!("wasmer_create_exe_main.c"); + +// TODO: to get this working locally I had to add wasmer_wasm.h and wasm.h to `.wasmer/include` manually. +// this needs to be fixed before we can ship this. + +#[derive(Debug, StructOpt)] +/// The options for the `wasmer create-exe` subcommand +pub struct CreateExe { + /// Input file + #[structopt(name = "FILE", parse(from_os_str))] + path: PathBuf, + + /// Output file + #[structopt(name = "OUTPUT PATH", short = "o", parse(from_os_str))] + output: PathBuf, + + /// Compilation Target triple + #[structopt(long = "target")] + target_triple: Option, + + #[structopt(flatten)] + compiler: CompilerOptions, + + #[structopt(short = "m", multiple = true)] + cpu_features: Vec, + + /// Additional libraries to link against. + /// This is useful for fixing linker errors that may occur on some systems. + #[structopt(short = "l", multiple = true)] + libraries: Vec, +} + +impl CreateExe { + /// Runs logic for the `compile` subcommand + pub fn execute(&self) -> Result<()> { + let target = self + .target_triple + .as_ref() + .map(|target_triple| { + let mut features = self + .cpu_features + .clone() + .into_iter() + .fold(CpuFeature::set(), |a, b| a | b); + // Cranelift requires SSE2, so we have this "hack" for now to facilitate + // usage + features |= CpuFeature::SSE2; + Target::new(target_triple.clone(), features) + }) + .unwrap_or_default(); + let engine_type = EngineType::ObjectFile; + let (store, compiler_type) = self + .compiler + .get_store_for_target_and_engine(target.clone(), engine_type)?; + + println!("Engine: {}", engine_type.to_string()); + println!("Compiler: {}", compiler_type.to_string()); + println!("Target: {}", target.triple()); + + let working_dir = tempfile::tempdir()?; + let starting_cd = env::current_dir()?; + let output_path = starting_cd.join(&self.output); + env::set_current_dir(&working_dir)?; + + // TODO: encapsulate compile code + + #[cfg(not(windows))] + let wasm_object_path = PathBuf::from("wasm.o"); + #[cfg(windows)] + let wasm_object_path = PathBuf::from("wasm.obj"); + + let wasm_module_path = starting_cd.join(&self.path); + + let header_file_path = Path::new("my_wasm.h"); + let module = + Module::from_file(&store, &wasm_module_path).context("failed to compile Wasm")?; + let _ = module.serialize_to_file(&wasm_object_path)?; + + let artifact: &wasmer_engine_object_file::ObjectFileArtifact = + module.artifact().as_ref().downcast_ref().context( + "Engine type is ObjectFile but could not downcast artifact into ObjectFileArtifact", + )?; + let symbol_registry = artifact.symbol_registry(); + let metadata_length = artifact.metadata_length(); + let module_info = module.info(); + let header_file_src = crate::c_gen::object_file_header::generate_header_file( + module_info, + symbol_registry, + metadata_length, + ); + + let header_path = header_file_path.clone(); + // for C code + let mut header = std::fs::OpenOptions::new() + .create(true) + .truncate(true) + .write(true) + .open(&header_path)?; + + use std::io::Write; + header.write(header_file_src.as_bytes())?; + + // auto compilation + // + + // write C src to disk + let c_src_path = Path::new("wasmer_main.c"); + #[cfg(not(windows))] + let c_src_obj = PathBuf::from("wasmer_main.o"); + #[cfg(windows)] + let c_src_obj = PathBuf::from("wasmer_main.obj"); + + { + let mut c_src_file = fs::OpenOptions::new() + .create_new(true) + .write(true) + .open(&c_src_path) + .context("Failed to open C source code file")?; + // TODO: + c_src_file.write_all(WASMER_MAIN_C_SOURCE)?; + } + run_c_compile(&c_src_path, &c_src_obj).context("Failed to compile C source code")?; + LinkCode { + object_paths: vec![c_src_obj, wasm_object_path], + output_path, + additional_libraries: self.libraries.clone(), + ..Default::default() + } + .run() + .context("Failed to link objects together")?; + + eprintln!( + "✔ Native executable compiled successfully to `{}`.", + self.output.display(), + ); + + Ok(()) + } +} + +fn get_wasmer_include_directory() -> anyhow::Result { + let mut path = PathBuf::from(env::var("WASMER_DIR")?); + path.push("include"); + Ok(path) +} + +fn get_libwasmer_path() -> anyhow::Result { + let mut path = PathBuf::from(env::var("WASMER_DIR")?); + path.push("lib"); + + #[cfg(not(windows))] + path.push("libwasmer.a"); + #[cfg(windows)] + path.push("libwasmer.lib"); + + Ok(path) +} + +/// Compile the C code. +fn run_c_compile(path_to_c_src: &Path, output_name: &Path) -> anyhow::Result<()> { + #[cfg(not(windows))] + let c_compiler = "cc"; + #[cfg(windows)] + let c_compiler = "clang++"; + + let output = Command::new(c_compiler) + .arg("-O2") + .arg("-c") + .arg(path_to_c_src) + .arg("-I") + .arg(get_wasmer_include_directory()?) + .arg("-o") + .arg(output_name) + .output()?; + + if !output.status.success() { + bail!( + "C code compile failed with: stdout: {}\n\nstderr: {}", + std::str::from_utf8(&output.stdout) + .expect("stdout is not utf8! need to handle arbitrary bytes"), + std::str::from_utf8(&output.stderr) + .expect("stderr is not utf8! need to handle arbitrary bytes") + ); + } + Ok(()) +} + +/// Data used to run a linking command for generated artifacts. +#[derive(Debug)] +struct LinkCode { + /// Path to the linker used to run the linking command. + linker_path: PathBuf, + /// String used as an optimization flag. + optimization_flag: String, + /// Paths of objects to link. + object_paths: Vec, + /// Additional libraries to link against. + additional_libraries: Vec, + /// Path to the output target. + output_path: PathBuf, + /// Path to the static libwasmer library. + libwasmer_path: PathBuf, +} + +impl Default for LinkCode { + fn default() -> Self { + #[cfg(not(windows))] + let linker = "cc"; + #[cfg(windows)] + let linker = "clang"; + Self { + linker_path: PathBuf::from(linker), + optimization_flag: String::from("-O2"), + object_paths: vec![], + additional_libraries: vec![], + output_path: PathBuf::from("a.out"), + libwasmer_path: get_libwasmer_path().unwrap(), + } + } +} + +impl LinkCode { + // TODO: `wasmer create-exe` needs a command line flag for extra libraries to link aganist + // or perhaps we just want to add a flag for passing things to the linker + fn run(&self) -> anyhow::Result<()> { + let mut command = Command::new(&self.linker_path); + let command = command + .arg(&self.optimization_flag) + .args( + self.object_paths + .iter() + .map(|path| path.canonicalize().unwrap()), + ) + .arg( + &self + .libwasmer_path + .canonicalize() + .context("Failed to find libwasmer")?, + ); + #[cfg(windows)] + let command = command.arg("-luserenv").arg("-lWs2_32").arg("-ladvapi32"); + #[cfg(not(windows))] + let command = command.arg("-ldl").arg("-lm").arg("-pthread"); + let link_aganist_extra_libs = self + .additional_libraries + .iter() + .map(|lib| format!("-l{}", lib)); + let command = command.args(link_aganist_extra_libs); + let output = command.arg("-o").arg(&self.output_path).output()?; + + if !output.status.success() { + bail!( + "linking failed with: stdout: {}\n\nstderr: {}", + std::str::from_utf8(&output.stdout) + .expect("stdout is not utf8! need to handle arbitrary bytes"), + std::str::from_utf8(&output.stderr) + .expect("stderr is not utf8! need to handle arbitrary bytes") + ); + } + Ok(()) + } +} diff --git a/lib/cli/src/commands/wasmer_create_exe_main.c b/lib/cli/src/commands/wasmer_create_exe_main.c new file mode 100644 index 000000000..ec00f9179 --- /dev/null +++ b/lib/cli/src/commands/wasmer_create_exe_main.c @@ -0,0 +1,89 @@ +#ifdef __cplusplus +extern "C" { +#endif + +#include "wasmer_wasm.h" +#include "wasm.h" +#include "my_wasm.h" + +#include +#include + +#ifdef __cplusplus +} +#endif + +void print_wasmer_error() +{ + int error_len = wasmer_last_error_length(); + printf("Error len: `%d`\n", error_len); + char* error_str = (char*) malloc(error_len); + wasmer_last_error_message(error_str, error_len); + printf("Error str: `%s`\n", error_str); +} + +int main() { + printf("Initializing...\n"); + wasm_config_t* config = wasm_config_new(); + wasm_config_set_engine(config, OBJECT_FILE); + wasm_engine_t* engine = wasm_engine_new_with_config(config); + wasm_store_t* store = wasm_store_new(engine); + + wasm_module_t* module = wasmer_object_file_engine_new(store, "qjs.wasm"); + if (! module) { + printf("Failed to create module\n"); + print_wasmer_error(); + return -1; + } + + // We have now finished the memory buffer book keeping and we have a valid Module. + + // In this example we're passing some JavaScript source code as a command line argument + // to a WASI module that can evaluate JavaScript. + wasi_config_t* wasi_config = wasi_config_new("constant_value_here"); + const char* js_string = "function greet(name) { return JSON.stringify('Hello, ' + name); }; print(greet('World'));"; + wasi_config_arg(wasi_config, "--eval"); + wasi_config_arg(wasi_config, js_string); + wasi_env_t* wasi_env = wasi_env_new(wasi_config); + if (!wasi_env) { + printf("> Error building WASI env!\n"); + print_wasmer_error(); + return 1; + } + + wasm_importtype_vec_t import_types; + wasm_module_imports(module, &import_types); + int num_imports = import_types.size; + wasm_extern_t** imports = (wasm_extern_t**) malloc(num_imports * sizeof(wasm_extern_t*)); + wasm_importtype_vec_delete(&import_types); + + bool get_imports_result = wasi_get_imports(store, module, wasi_env, imports); + if (!get_imports_result) { + printf("> Error getting WASI imports!\n"); + print_wasmer_error(); + return 1; + } + + wasm_instance_t* instance = wasm_instance_new(store, module, (const wasm_extern_t* const*) imports, NULL); + if (! instance) { + printf("Failed to create instance\n"); + print_wasmer_error(); + return -1; + } + wasi_env_set_instance(wasi_env, instance); + + // WASI is now set up. + + void* vmctx = wasm_instance_get_vmctx_ptr(instance); + wasm_val_t* inout[2] = { NULL, NULL }; + + fflush(stdout); + // We're able to call our compiled function directly through a trampoline. + wasmer_trampoline_function_call__1(vmctx, wasmer_function__1, &inout); + + wasm_instance_delete(instance); + wasm_module_delete(module); + wasm_store_delete(store); + wasm_engine_delete(engine); + return 0; +} diff --git a/lib/cli/src/store.rs b/lib/cli/src/store.rs index 795fcf792..9404ac2bc 100644 --- a/lib/cli/src/store.rs +++ b/lib/cli/src/store.rs @@ -14,8 +14,27 @@ use wasmer::*; use wasmer_compiler::CompilerConfig; #[derive(Debug, Clone, StructOpt)] -/// The compiler options +/// The compiler and engine options pub struct StoreOptions { + #[structopt(flatten)] + compiler: CompilerOptions, + + /// Use JIT Engine. + #[structopt(long, conflicts_with_all = &["native", "object_file"])] + jit: bool, + + /// Use Native Engine. + #[structopt(long, conflicts_with_all = &["jit", "object_file"])] + native: bool, + + /// Use ObjectFile Engine. + #[structopt(long, conflicts_with_all = &["jit", "native"])] + object_file: bool, +} + +#[derive(Debug, Clone, StructOpt)] +/// The compiler options +pub struct CompilerOptions { /// Use Singlepass compiler. #[structopt(long, conflicts_with_all = &["cranelift", "llvm", "backend"])] singlepass: bool, @@ -36,19 +55,7 @@ pub struct StoreOptions { #[structopt(long, parse(from_os_str))] llvm_debug_dir: Option, - /// Use JIT Engine. - #[structopt(long, conflicts_with_all = &["native", "object_file"])] - jit: bool, - - /// Use Native Engine. - #[structopt(long, conflicts_with_all = &["jit", "object_file"])] - native: bool, - - /// Use ObjectFile Engine. - #[structopt(long, conflicts_with_all = &["jit", "native"])] - object_file: bool, - - /// The deprecated backend flag - Please not use + /// The deprecated backend flag - Please do not use #[structopt(long = "backend", hidden = true, conflicts_with_all = &["singlepass", "cranelift", "llvm"])] backend: Option, @@ -56,80 +63,8 @@ pub struct StoreOptions { features: WasmFeatures, } -/// The compiler used for the store -#[derive(Debug, PartialEq, Eq)] -pub enum CompilerType { - /// Singlepass compiler - Singlepass, - /// Cranelift compiler - Cranelift, - /// LLVM compiler - LLVM, - /// Headless compiler - Headless, -} - -impl CompilerType { - /// Return all enabled compilers - pub fn enabled() -> Vec { - vec![ - #[cfg(feature = "singlepass")] - Self::Singlepass, - #[cfg(feature = "cranelift")] - Self::Cranelift, - #[cfg(feature = "llvm")] - Self::LLVM, - ] - } -} - -impl ToString for CompilerType { - fn to_string(&self) -> String { - match self { - Self::Singlepass => "singlepass".to_string(), - Self::Cranelift => "cranelift".to_string(), - Self::LLVM => "llvm".to_string(), - Self::Headless => "headless".to_string(), - } - } -} - -impl FromStr for CompilerType { - type Err = Error; - fn from_str(s: &str) -> Result { - match s { - "singlepass" => Ok(Self::Singlepass), - "cranelift" => Ok(Self::Cranelift), - "llvm" => Ok(Self::LLVM), - "headless" => Ok(Self::Headless), - backend => bail!("The `{}` compiler does not exist.", backend), - } - } -} - -/// The engine used for the store -#[derive(Debug, PartialEq, Eq)] -pub enum EngineType { - /// JIT Engine - JIT, - /// Native Engine - Native, - /// Object File Engine - ObjectFile, -} - -impl ToString for EngineType { - fn to_string(&self) -> String { - match self { - Self::JIT => "jit".to_string(), - Self::Native => "native".to_string(), - Self::ObjectFile => "objectfile".to_string(), - } - } -} - -#[cfg(all(feature = "compiler", feature = "engine"))] -impl StoreOptions { +#[cfg(feature = "compiler")] +impl CompilerOptions { fn get_compiler(&self) -> Result { if self.cranelift { Ok(CompilerType::Cranelift) @@ -161,7 +96,7 @@ impl StoreOptions { } } - /// Get the Target architecture + /// Get the enaled Wasm features. pub fn get_features(&self, mut features: Features) -> Result { if self.features.threads || self.features.all { features.threads(true); @@ -181,6 +116,63 @@ impl StoreOptions { Ok(features) } + /// Gets the Store for a given target and engine. + pub fn get_store_for_target_and_engine( + &self, + target: Target, + engine_type: EngineType, + ) -> Result<(Store, CompilerType)> { + let (compiler_config, compiler_type) = self.get_compiler_config()?; + let engine = self.get_engine_by_type(target, compiler_config, engine_type)?; + let store = Store::new(&*engine); + Ok((store, compiler_type)) + } + + fn get_engine_by_type( + &self, + target: Target, + compiler_config: Box, + engine_type: EngineType, + ) -> Result> { + let features = self.get_features(compiler_config.default_features_for_target(&target))?; + let engine: Box = match engine_type { + #[cfg(feature = "jit")] + EngineType::JIT => Box::new( + wasmer_engine_jit::JIT::new(&*compiler_config) + .features(features) + .target(target) + .engine(), + ), + #[cfg(feature = "native")] + EngineType::Native => { + let mut compiler_config = compiler_config; + Box::new( + wasmer_engine_native::Native::new(&mut *compiler_config) + .target(target) + .features(features) + .engine(), + ) + } + #[cfg(feature = "object-file")] + EngineType::ObjectFile => { + let mut compiler_config = compiler_config; + Box::new( + wasmer_engine_object_file::ObjectFile::new(&mut *compiler_config) + .target(target) + .features(features) + .engine(), + ) + } + #[cfg(not(all(feature = "jit", feature = "native", feature = "object-file")))] + engine => bail!( + "The `{}` engine is not included in this binary.", + engine.to_string() + ), + }; + + Ok(engine) + } + /// Get the Compiler Config for the current options #[allow(unused_variables)] pub(crate) fn get_compiler_config(&self) -> Result<(Box, CompilerType)> { @@ -315,7 +307,82 @@ impl StoreOptions { #[allow(unreachable_code)] Ok((compiler_config, compiler)) } +} +/// The compiler used for the store +#[derive(Debug, PartialEq, Eq)] +pub enum CompilerType { + /// Singlepass compiler + Singlepass, + /// Cranelift compiler + Cranelift, + /// LLVM compiler + LLVM, + /// Headless compiler + Headless, +} + +impl CompilerType { + /// Return all enabled compilers + pub fn enabled() -> Vec { + vec![ + #[cfg(feature = "singlepass")] + Self::Singlepass, + #[cfg(feature = "cranelift")] + Self::Cranelift, + #[cfg(feature = "llvm")] + Self::LLVM, + ] + } +} + +impl ToString for CompilerType { + fn to_string(&self) -> String { + match self { + Self::Singlepass => "singlepass".to_string(), + Self::Cranelift => "cranelift".to_string(), + Self::LLVM => "llvm".to_string(), + Self::Headless => "headless".to_string(), + } + } +} + +impl FromStr for CompilerType { + type Err = Error; + fn from_str(s: &str) -> Result { + match s { + "singlepass" => Ok(Self::Singlepass), + "cranelift" => Ok(Self::Cranelift), + "llvm" => Ok(Self::LLVM), + "headless" => Ok(Self::Headless), + backend => bail!("The `{}` compiler does not exist.", backend), + } + } +} + +/// The engine used for the store +#[derive(Debug, PartialEq, Eq, Clone, Copy)] +pub enum EngineType { + /// JIT Engine + JIT, + /// Native Engine + Native, + /// Object File Engine + ObjectFile, +} + +impl ToString for EngineType { + fn to_string(&self) -> String { + match self { + Self::JIT => "jit".to_string(), + Self::Native => "native".to_string(), + Self::ObjectFile => "objectfile".to_string(), + } + } +} + +#[cfg(all(feature = "compiler", feature = "engine"))] +impl StoreOptions { /// Gets the store for the host target, with the engine name and compiler name selected pub fn get_store(&self) -> Result<(Store, EngineType, CompilerType)> { let target = Target::default(); @@ -327,7 +394,7 @@ impl StoreOptions { &self, target: Target, ) -> Result<(Store, EngineType, CompilerType)> { - let (compiler_config, compiler_type) = self.get_compiler_config()?; + let (compiler_config, compiler_type) = self.compiler.get_compiler_config()?; let (engine, engine_type) = self.get_engine_with_compiler(target, compiler_config)?; let store = Store::new(&*engine); Ok((store, engine_type, compiler_type)) @@ -339,41 +406,10 @@ impl StoreOptions { compiler_config: Box, ) -> Result<(Box, EngineType)> { let engine_type = self.get_engine()?; - let features = self.get_features(compiler_config.default_features_for_target(&target))?; - let engine: Box = match engine_type { - #[cfg(feature = "jit")] - EngineType::JIT => Box::new( - wasmer_engine_jit::JIT::new(&*compiler_config) - .features(features) - .target(target) - .engine(), - ), - #[cfg(feature = "native")] - EngineType::Native => { - let mut compiler_config = compiler_config; - Box::new( - wasmer_engine_native::Native::new(&mut *compiler_config) - .target(target) - .features(features) - .engine(), - ) - } - #[cfg(feature = "object-file")] - EngineType::ObjectFile => { - let mut compiler_config = compiler_config; - Box::new( - wasmer_engine_object_file::ObjectFile::new(&mut *compiler_config) - .target(target) - .features(features) - .engine(), - ) - } - #[cfg(not(all(feature = "jit", feature = "native", feature = "object-file")))] - engine => bail!( - "The `{}` engine is not included in this binary.", - engine.to_string() - ), - }; + let engine = self + .compiler + .get_engine_by_type(target, compiler_config, engine_type)?; + Ok((engine, engine_type)) } } From 02c0df510157a48f6d891a87d32810fb292f6b48 Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Thu, 8 Oct 2020 14:28:34 -0700 Subject: [PATCH 162/281] Update to cbindgen 0.15.0 Manually specify that items should be sorted by name in the header file. We do this because cbindgen 0.15.0 removed sorting by default. --- Cargo.lock | 6 ++++-- lib/c-api/Cargo.toml | 3 +-- lib/c-api/build.rs | 4 ++++ lib/c-api/wasmer.hh | 1 + lib/c-api/wasmer_wasm.h | 3 +++ 5 files changed, 13 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e27fa5c4a..f0921418e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -205,11 +205,13 @@ dependencies = [ [[package]] name = "cbindgen" -version = "0.14.6" -source = "git+https://github.com/eqrion/cbindgen#1fc4cb072422e722f8bcb3af5766f84587a180c6" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1df6a11bba1d7cab86c166cecf4cf8acd7d02b7b65924d81b33d27197f22ee35" dependencies = [ "clap", "heck", + "indexmap", "log", "proc-macro2", "quote", diff --git a/lib/c-api/Cargo.toml b/lib/c-api/Cargo.toml index 4e96c15ad..5df7f6efb 100644 --- a/lib/c-api/Cargo.toml +++ b/lib/c-api/Cargo.toml @@ -88,5 +88,4 @@ cranelift-backend = ["cranelift"] llvm-backend = ["llvm"] [build-dependencies] -#cbindgen = "0.14.6" -cbindgen = { git = "https://github.com/eqrion/cbindgen", branch = "master" } \ No newline at end of file +cbindgen = "0.15" \ No newline at end of file diff --git a/lib/c-api/build.rs b/lib/c-api/build.rs index e78874382..627ad9039 100644 --- a/lib/c-api/build.rs +++ b/lib/c-api/build.rs @@ -197,6 +197,10 @@ fn build_wasmer_headers(crate_dir: &str, out_dir: &str) { /// Create a fresh new `Builder`, already pre-configured. fn new_builder(language: Language, crate_dir: &str, include_guard: &str, header: &str) -> Builder { Builder::new() + .with_config(cbindgen::Config { + sort_by: cbindgen::SortKey::Name, + ..cbindgen::Config::default() + }) .with_language(language) .with_crate(crate_dir) .with_include_guard(include_guard) diff --git a/lib/c-api/wasmer.hh b/lib/c-api/wasmer.hh index 4ca7f20a6..2c72b84b2 100644 --- a/lib/c-api/wasmer.hh +++ b/lib/c-api/wasmer.hh @@ -44,6 +44,7 @@ #include #include #include +#include #include #if defined(WASMER_WASI_ENABLED) diff --git a/lib/c-api/wasmer_wasm.h b/lib/c-api/wasmer_wasm.h index 885102827..b9eea99ae 100644 --- a/lib/c-api/wasmer_wasm.h +++ b/lib/c-api/wasmer_wasm.h @@ -28,6 +28,9 @@ # define DEPRECATED(message) __declspec(deprecated(message)) #endif +// The `jit` feature has been enabled for this build. +#define WASMER_JIT_ENABLED + // The `compiler` feature has been enabled for this build. #define WASMER_COMPILER_ENABLED From d687dd5bd6dd48d1b6ad79f15045cbe9fda75bd3 Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Thu, 8 Oct 2020 14:51:57 -0700 Subject: [PATCH 163/281] Add `system-libffi` feature to wasmer C API crate --- Makefile | 8 ++++++++ lib/c-api/Cargo.toml | 3 ++- lib/c-api/src/wasm_c_api/mod.rs | 1 + 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 8d07bf70c..ab9c17c05 100644 --- a/Makefile +++ b/Makefile @@ -82,6 +82,10 @@ build-capi-cranelift: cargo build --manifest-path lib/c-api/Cargo.toml --release \ --no-default-features --features wat,jit,object-file,cranelift,wasi +build-capi-cranelift-system-libffi: + cargo build --manifest-path lib/c-api/Cargo.toml --release \ + --no-default-features --features wat,jit,object-file,cranelift,wasi,system-libffi + build-capi-llvm: cargo build --manifest-path lib/c-api/Cargo.toml --release \ --no-default-features --features wat,jit,object-file,llvm,wasi @@ -118,6 +122,10 @@ test-capi-cranelift: build-capi-cranelift cargo test --manifest-path lib/c-api/Cargo.toml --release \ --no-default-features --features wat,jit,cranelift,wasi -- --nocapture +test-capi-cranelift-system-libffi: build-capi-cranelift-system-libffi + cargo test --manifest-path lib/c-api/Cargo.toml --release \ + --no-default-features --features wat,jit,cranelift,wasi,system-libffi -- --nocapture + test-capi-llvm: build-capi-llvm cargo test --manifest-path lib/c-api/Cargo.toml --release \ --no-default-features --features wat,jit,llvm,wasi -- --nocapture diff --git a/lib/c-api/Cargo.toml b/lib/c-api/Cargo.toml index 5df7f6efb..aeb0635db 100644 --- a/lib/c-api/Cargo.toml +++ b/lib/c-api/Cargo.toml @@ -77,6 +77,7 @@ llvm = [ "wasmer-compiler-llvm", "compiler", ] +system-libffi = ["libffi/system"] # Deprecated feature. # TODO: Port this feature. @@ -88,4 +89,4 @@ cranelift-backend = ["cranelift"] llvm-backend = ["llvm"] [build-dependencies] -cbindgen = "0.15" \ No newline at end of file +cbindgen = "0.15" diff --git a/lib/c-api/src/wasm_c_api/mod.rs b/lib/c-api/src/wasm_c_api/mod.rs index 47eef0cff..58eefb2a0 100644 --- a/lib/c-api/src/wasm_c_api/mod.rs +++ b/lib/c-api/src/wasm_c_api/mod.rs @@ -31,4 +31,5 @@ pub mod wasi; pub mod wasmer; +#[cfg(feature = "wat")] pub mod wat; From 4b665adc7229a810f4cb83a27e78fe75d8924ac4 Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Thu, 8 Oct 2020 16:33:41 -0700 Subject: [PATCH 164/281] Add test for `wasmer create-exe` --- tests/integration/cli/src/assets.rs | 32 ++++ tests/integration/cli/src/lib.rs | 8 +- tests/integration/cli/src/link_code.rs | 66 ++++++++ tests/integration/cli/src/util.rs | 55 ++++++ .../integration/cli/{src => tests}/compile.rs | 159 +----------------- tests/integration/cli/tests/create_exe.rs | 91 ++++++++++ .../object_file_engine_test_c_source.c | 0 7 files changed, 257 insertions(+), 154 deletions(-) create mode 100644 tests/integration/cli/src/assets.rs create mode 100644 tests/integration/cli/src/link_code.rs create mode 100644 tests/integration/cli/src/util.rs rename tests/integration/cli/{src => tests}/compile.rs (50%) create mode 100644 tests/integration/cli/tests/create_exe.rs rename tests/integration/cli/{src => tests}/object_file_engine_test_c_source.c (100%) diff --git a/tests/integration/cli/src/assets.rs b/tests/integration/cli/src/assets.rs new file mode 100644 index 000000000..4113e0b5c --- /dev/null +++ b/tests/integration/cli/src/assets.rs @@ -0,0 +1,32 @@ +use std::env; +use std::path::PathBuf; + +pub const ASSET_PATH: &str = concat!(env!("CARGO_MANIFEST_DIR"), "/assets"); + +pub const WASMER_PATH: &str = concat!( + env!("CARGO_MANIFEST_DIR"), + "/../../../target/release/wasmer" +); + +#[cfg(not(windows))] +pub const LIBWASMER_PATH: &str = concat!( + env!("CARGO_MANIFEST_DIR"), + "/../../../target/release/libwasmer_c_api.a" +); +#[cfg(windows)] +pub const LIBWASMER_PATH: &str = concat!( + env!("CARGO_MANIFEST_DIR"), + "/../../../target/release/wasmer_c_api.lib" +); + +/// Get the path to the `libwasmer.a` static library. +pub fn get_libwasmer_path() -> PathBuf { + PathBuf::from( + env::var("WASMER_TEST_LIBWASMER_PATH").unwrap_or_else(|_| LIBWASMER_PATH.to_string()), + ) +} + +/// Get the path to the `wasmer` executable to be used in this test. +pub fn get_wasmer_path() -> PathBuf { + PathBuf::from(env::var("WASMER_TEST_WASMER_PATH").unwrap_or_else(|_| WASMER_PATH.to_string())) +} diff --git a/tests/integration/cli/src/lib.rs b/tests/integration/cli/src/lib.rs index 69d222b5e..43d6ada6a 100644 --- a/tests/integration/cli/src/lib.rs +++ b/tests/integration/cli/src/lib.rs @@ -1,6 +1,10 @@ #![forbid(unsafe_code)] -#![cfg(test)] //! CLI integration tests -mod compile; +pub mod assets; +pub mod link_code; +pub mod util; + +pub use assets::*; +pub use util::*; diff --git a/tests/integration/cli/src/link_code.rs b/tests/integration/cli/src/link_code.rs new file mode 100644 index 000000000..72fb18e1b --- /dev/null +++ b/tests/integration/cli/src/link_code.rs @@ -0,0 +1,66 @@ +use crate::assets::*; +use anyhow::bail; +use std::path::PathBuf; +use std::process::Command; + +/// Data used to run a linking command for generated artifacts. +#[derive(Debug)] +pub struct LinkCode { + /// Path to the linker used to run the linking command. + pub linker_path: PathBuf, + /// String used as an optimization flag. + pub optimization_flag: String, + /// Paths of objects to link. + pub object_paths: Vec, + /// Path to the output target. + pub output_path: PathBuf, + /// Path to the static libwasmer library. + pub libwasmer_path: PathBuf, +} + +impl Default for LinkCode { + fn default() -> Self { + #[cfg(not(windows))] + let linker = "cc"; + #[cfg(windows)] + let linker = "clang"; + Self { + linker_path: PathBuf::from(linker), + optimization_flag: String::from("-O2"), + object_paths: vec![], + output_path: PathBuf::from("a.out"), + libwasmer_path: get_libwasmer_path(), + } + } +} + +impl LinkCode { + pub fn run(&self) -> anyhow::Result<()> { + let mut command = Command::new(&self.linker_path); + let command = command + .arg(&self.optimization_flag) + .args( + self.object_paths + .iter() + .map(|path| path.canonicalize().unwrap()), + ) + .arg(&self.libwasmer_path.canonicalize()?); + #[cfg(windows)] + let command = command.arg("-luserenv").arg("-lWs2_32").arg("-ladvapi32"); + #[cfg(not(windows))] + // TODO: remove `-lffi` before shipping + let command = command.arg("-ldl").arg("-lm").arg("-pthread").arg("-lffi"); + let output = command.arg("-o").arg(&self.output_path).output()?; + + if !output.status.success() { + bail!( + "linking failed with: stdout: {}\n\nstderr: {}", + std::str::from_utf8(&output.stdout) + .expect("stdout is not utf8! need to handle arbitrary bytes"), + std::str::from_utf8(&output.stderr) + .expect("stderr is not utf8! need to handle arbitrary bytes") + ); + } + Ok(()) + } +} diff --git a/tests/integration/cli/src/util.rs b/tests/integration/cli/src/util.rs new file mode 100644 index 000000000..0e4864a67 --- /dev/null +++ b/tests/integration/cli/src/util.rs @@ -0,0 +1,55 @@ +use anyhow::bail; +use std::path::Path; +use std::process::Command; + +#[derive(Debug, Copy, Clone)] +pub enum Compiler { + Cranelift, + LLVM, + Singlepass, +} + +impl Compiler { + pub const fn to_flag(self) -> &'static str { + match self { + Compiler::Cranelift => "--cranelift", + Compiler::LLVM => "--llvm", + Compiler::Singlepass => "--singlepass", + } + } +} + +#[derive(Debug, Copy, Clone)] +pub enum Engine { + Jit, + Native, + ObjectFile, +} + +impl Engine { + pub const fn to_flag(self) -> &'static str { + match self { + Engine::Jit => "--jit", + Engine::Native => "--native", + Engine::ObjectFile => "--object-file", + } + } +} + +pub fn run_code(executable_path: &Path) -> anyhow::Result { + let output = Command::new(executable_path.canonicalize()?).output()?; + + if !output.status.success() { + bail!( + "running executable failed: stdout: {}\n\nstderr: {}", + std::str::from_utf8(&output.stdout) + .expect("stdout is not utf8! need to handle arbitrary bytes"), + std::str::from_utf8(&output.stderr) + .expect("stderr is not utf8! need to handle arbitrary bytes") + ); + } + let output = + std::str::from_utf8(&output.stdout).expect("output from running executable is not utf-8"); + + Ok(output.to_owned()) +} diff --git a/tests/integration/cli/src/compile.rs b/tests/integration/cli/tests/compile.rs similarity index 50% rename from tests/integration/cli/src/compile.rs rename to tests/integration/cli/tests/compile.rs index b14635b37..ff9a7ec68 100644 --- a/tests/integration/cli/src/compile.rs +++ b/tests/integration/cli/tests/compile.rs @@ -1,84 +1,18 @@ //! CLI tests for the compile subcommand. use anyhow::{bail, Context}; -use std::env; use std::fs; use std::io::Write; use std::path::{Path, PathBuf}; use std::process::Command; - -const CLI_INTEGRATION_TESTS_ASSETS: &str = concat!(env!("CARGO_MANIFEST_DIR"), "/assets"); +use wasmer_integration_tests_cli::link_code::*; +use wasmer_integration_tests_cli::*; const OBJECT_FILE_ENGINE_TEST_C_SOURCE: &[u8] = include_bytes!("object_file_engine_test_c_source.c"); -// TODO: -const OBJECT_FILE_ENGINE_TEST_WASM_PATH: &str = - concat!(env!("CARGO_MANIFEST_DIR"), "/assets/qjs.wasm"); -const WASMER_PATH: &str = concat!( - env!("CARGO_MANIFEST_DIR"), - "/../../../target/release/wasmer" -); - -#[cfg(not(windows))] -const LIBWASMER_PATH: &str = concat!( - env!("CARGO_MANIFEST_DIR"), - "/../../../target/release/libwasmer_c_api.a" -); -#[cfg(windows)] -const LIBWASMER_PATH: &str = concat!( - env!("CARGO_MANIFEST_DIR"), - "/../../../target/release/wasmer_c_api.lib" -); - -/// Get the path to the `wasmer` executable to be used in this test. -fn get_wasmer_path() -> PathBuf { - PathBuf::from(env::var("WASMER_TEST_WASMER_PATH").unwrap_or_else(|_| WASMER_PATH.to_string())) -} - -/// Get the path to the `libwasmer.a` static library. -fn get_libwasmer_path() -> PathBuf { - PathBuf::from( - env::var("WASMER_TEST_LIBWASMER_PATH").unwrap_or_else(|_| LIBWASMER_PATH.to_string()), - ) -} - -#[allow(dead_code)] -#[derive(Debug, Copy, Clone)] -pub enum Engine { - Jit, - Native, - ObjectFile, -} - -impl Engine { - // TODO: make this `const fn` when Wasmer moves to Rust 1.46.0+ - pub fn to_flag(self) -> &'static str { - match self { - Engine::Jit => "--jit", - Engine::Native => "--native", - Engine::ObjectFile => "--object-file", - } - } -} - -#[allow(dead_code)] -#[derive(Debug, Copy, Clone)] -pub enum Compiler { - Cranelift, - LLVM, - Singlepass, -} - -impl Compiler { - // TODO: make this `const fn` when Wasmer moves to Rust 1.46.0+ - pub fn to_flag(self) -> &'static str { - match self { - Compiler::Cranelift => "--cranelift", - Compiler::LLVM => "--llvm", - Compiler::Singlepass => "--singlepass", - } - } +fn object_file_engine_test_wasm_path() -> String { + format!("{}/{}", ASSET_PATH, "qjs.wasm") } /// Data used to run the `wasmer compile` command. @@ -106,7 +40,7 @@ impl Default for WasmerCompile { let wasm_obj_path = "wasm.obj"; Self { wasmer_path: get_wasmer_path(), - wasm_path: PathBuf::from(OBJECT_FILE_ENGINE_TEST_WASM_PATH), + wasm_path: PathBuf::from(object_file_engine_test_wasm_path()), wasm_object_path: PathBuf::from(wasm_obj_path), header_output_path: PathBuf::from("my_wasm.h"), compiler: Compiler::Cranelift, @@ -153,7 +87,7 @@ fn run_c_compile(path_to_c_src: &Path, output_name: &Path) -> anyhow::Result<()> .arg("-c") .arg(path_to_c_src) .arg("-I") - .arg(CLI_INTEGRATION_TESTS_ASSETS) + .arg(ASSET_PATH) .arg("-o") .arg(output_name) .output()?; @@ -170,92 +104,13 @@ fn run_c_compile(path_to_c_src: &Path, output_name: &Path) -> anyhow::Result<()> Ok(()) } -/// Data used to run a linking command for generated artifacts. -#[derive(Debug)] -struct LinkCode { - /// Path to the linker used to run the linking command. - linker_path: PathBuf, - /// String used as an optimization flag. - optimization_flag: String, - /// Paths of objects to link. - object_paths: Vec, - /// Path to the output target. - output_path: PathBuf, - /// Path to the static libwasmer library. - libwasmer_path: PathBuf, -} - -impl Default for LinkCode { - fn default() -> Self { - #[cfg(not(windows))] - let linker = "cc"; - #[cfg(windows)] - let linker = "clang"; - Self { - linker_path: PathBuf::from(linker), - optimization_flag: String::from("-O2"), - object_paths: vec![], - output_path: PathBuf::from("a.out"), - libwasmer_path: get_libwasmer_path(), - } - } -} - -impl LinkCode { - fn run(&self) -> anyhow::Result<()> { - let mut command = Command::new(&self.linker_path); - let command = command - .arg(&self.optimization_flag) - .args( - self.object_paths - .iter() - .map(|path| path.canonicalize().unwrap()), - ) - .arg(&self.libwasmer_path.canonicalize()?); - #[cfg(windows)] - let command = command.arg("-luserenv").arg("-lWs2_32").arg("-ladvapi32"); - #[cfg(not(windows))] - let command = command.arg("-ldl").arg("-lm").arg("-pthread"); - let output = command.arg("-o").arg(&self.output_path).output()?; - - if !output.status.success() { - bail!( - "linking failed with: stdout: {}\n\nstderr: {}", - std::str::from_utf8(&output.stdout) - .expect("stdout is not utf8! need to handle arbitrary bytes"), - std::str::from_utf8(&output.stderr) - .expect("stderr is not utf8! need to handle arbitrary bytes") - ); - } - Ok(()) - } -} - -fn run_code(executable_path: &Path) -> anyhow::Result { - let output = Command::new(executable_path.canonicalize()?).output()?; - - if !output.status.success() { - bail!( - "running executable failed: stdout: {}\n\nstderr: {}", - std::str::from_utf8(&output.stdout) - .expect("stdout is not utf8! need to handle arbitrary bytes"), - std::str::from_utf8(&output.stderr) - .expect("stderr is not utf8! need to handle arbitrary bytes") - ); - } - let output = - std::str::from_utf8(&output.stdout).expect("output from running executable is not utf-8"); - - Ok(output.to_owned()) -} - #[test] fn object_file_engine_works() -> anyhow::Result<()> { let operating_dir = tempfile::tempdir()?; std::env::set_current_dir(&operating_dir)?; - let wasm_path = PathBuf::from(OBJECT_FILE_ENGINE_TEST_WASM_PATH); + let wasm_path = PathBuf::from(object_file_engine_test_wasm_path()); #[cfg(not(windows))] let wasm_object_path = PathBuf::from("wasm.o"); #[cfg(windows)] diff --git a/tests/integration/cli/tests/create_exe.rs b/tests/integration/cli/tests/create_exe.rs new file mode 100644 index 000000000..d2f50a6a9 --- /dev/null +++ b/tests/integration/cli/tests/create_exe.rs @@ -0,0 +1,91 @@ +//! Tests of the `wasmer create-exe` command. + +use anyhow::{bail, Context}; +use std::path::PathBuf; +use std::process::Command; +use wasmer_integration_tests_cli::*; + +fn create_exe_test_wasm_path() -> String { + format!("{}/{}", ASSET_PATH, "qjs.wasm") +} + +/// Data used to run the `wasmer compile` command. +#[derive(Debug)] +struct WasmerCreateExe { + /// Path to wasmer executable used to run the command. + wasmer_path: PathBuf, + /// Path to the Wasm file to compile. + wasm_path: PathBuf, + /// Path to the native executable produced by compiling the Wasm. + native_executable_path: PathBuf, + /// Compiler with which to compile the Wasm. + compiler: Compiler, +} + +impl Default for WasmerCreateExe { + fn default() -> Self { + #[cfg(not(windows))] + let native_executable_path = PathBuf::from("wasm.out"); + #[cfg(windows)] + let native_executable_path = PathBuf::from("wasm.exe"); + Self { + wasmer_path: get_wasmer_path(), + wasm_path: PathBuf::from(create_exe_test_wasm_path()), + native_executable_path, + compiler: Compiler::Cranelift, + } + } +} + +impl WasmerCreateExe { + fn run(&self) -> anyhow::Result<()> { + let output = Command::new(&self.wasmer_path) + .arg("create-exe") + .arg(&self.wasm_path.canonicalize()?) + .arg(&self.compiler.to_flag()) + // TODO: remove before shipping + .arg("-lffi") + .arg("-o") + .arg(&self.native_executable_path) + .output()?; + + if !output.status.success() { + bail!( + "wasmer create-exe failed with: stdout: {}\n\nstderr: {}", + std::str::from_utf8(&output.stdout) + .expect("stdout is not utf8! need to handle arbitrary bytes"), + std::str::from_utf8(&output.stderr) + .expect("stderr is not utf8! need to handle arbitrary bytes") + ); + } + Ok(()) + } +} + +#[test] +fn create_exe_works() -> anyhow::Result<()> { + let operating_dir = tempfile::tempdir()?; + + std::env::set_current_dir(&operating_dir)?; + + let wasm_path = PathBuf::from(create_exe_test_wasm_path()); + #[cfg(not(windows))] + let executable_path = PathBuf::from("wasm.out"); + #[cfg(windows)] + let executable_path = PathBuf::from("wasm.exe"); + + WasmerCreateExe { + wasm_path: wasm_path.clone(), + native_executable_path: executable_path.clone(), + compiler: Compiler::Cranelift, + ..Default::default() + } + .run() + .context("Failed to create-exe wasm with Wasmer")?; + + let result = run_code(&executable_path).context("Failed to run generated executable")?; + let result_lines = result.lines().collect::>(); + assert_eq!(result_lines, vec!["Initializing...", "\"Hello, World\""],); + + Ok(()) +} diff --git a/tests/integration/cli/src/object_file_engine_test_c_source.c b/tests/integration/cli/tests/object_file_engine_test_c_source.c similarity index 100% rename from tests/integration/cli/src/object_file_engine_test_c_source.c rename to tests/integration/cli/tests/object_file_engine_test_c_source.c From 61c88be86358111c27882bc266677270de04a929 Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Thu, 8 Oct 2020 16:47:14 -0700 Subject: [PATCH 165/281] Prepare for 1.0.0-alpha4 release --- CHANGELOG.md | 5 +++ Cargo.lock | 44 ++++++++++----------- Cargo.toml | 28 ++++++------- lib/api/Cargo.toml | 20 +++++----- lib/c-api/Cargo.toml | 28 ++++++------- lib/cache/Cargo.toml | 4 +- lib/cli/Cargo.toml | 34 ++++++++-------- lib/compiler-cranelift/Cargo.toml | 8 ++-- lib/compiler-llvm/Cargo.toml | 8 ++-- lib/compiler-singlepass/Cargo.toml | 8 ++-- lib/compiler/Cargo.toml | 6 +-- lib/deprecated/runtime-core/Cargo.toml | 20 +++++----- lib/emscripten/Cargo.toml | 4 +- lib/engine-jit/Cargo.toml | 10 ++--- lib/engine-native/Cargo.toml | 12 +++--- lib/engine-object-file/Cargo.toml | 10 ++--- lib/engine/Cargo.toml | 8 ++-- lib/object/Cargo.toml | 6 +-- lib/vm/Cargo.toml | 4 +- lib/wasi-experimental-io-devices/Cargo.toml | 4 +- lib/wasi/Cargo.toml | 4 +- lib/wasmer-types/Cargo.toml | 2 +- scripts/publish.py | 2 +- scripts/update-version.sh | 4 +- scripts/windows-installer/wasmer.iss | 2 +- tests/integration/cli/Cargo.toml | 4 +- tests/lib/engine-dummy/Cargo.toml | 10 ++--- tests/lib/wast/Cargo.toml | 6 +-- 28 files changed, 155 insertions(+), 150 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bd944d264..8047c8f4c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,10 +1,15 @@ # Changelog ## **[Unreleased]** + +## 1.0.0-alpha4 - 2020-10-08 +- [#1691](https://github.com/wasmerio/wasmer/pull/1691) Bump minimum supported Rust version to 1.46.0 - [#1690](https://github.com/wasmerio/wasmer/pull/1690) Fix `wasm_memorytype_limits` where `min` and `max` represents pages, not bytes. Additionally, fixes the max limit sentinel value. +- [#1682](https://github.com/wasmerio/wasmer/pull/1682) Improve error reporting when making a memory with invalid settings. - [#1635](https://github.com/wasmerio/wasmer/pull/1635) Implement `wat2wasm` in the Wasm C API. - [#1636](https://github.com/wasmerio/wasmer/pull/1636) Implement `wasm_module_validate` in the Wasm C API. - [#1671](https://github.com/wasmerio/wasmer/pull/1671) Fix probestack firing inappropriately, and sometimes over/under allocating stack. +- [#1660](https://github.com/wasmerio/wasmer/pull/1660) Fix issue preventing map-dir aliases starting with `/` from working properly. - [#1657](https://github.com/wasmerio/wasmer/pull/1657) Implement `wasm_trap_t` and `wasm_frame_t` for Wasm C API; add examples in Rust and C of exiting early with a host function. - [#1645](https://github.com/wasmerio/wasmer/pull/1645) Move the install script to https://github.com/wasmerio/wasmer-install diff --git a/Cargo.lock b/Cargo.lock index f0921418e..2aef3c278 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2141,7 +2141,7 @@ checksum = "1d649a3145108d7d3fbcde896a468d1bd636791823c9921135218ad89be08307" [[package]] name = "wasmer" -version = "1.0.0-alpha3" +version = "1.0.0-alpha4" dependencies = [ "anyhow", "cfg-if", @@ -2166,7 +2166,7 @@ dependencies = [ [[package]] name = "wasmer-c-api" -version = "1.0.0-alpha3" +version = "1.0.0-alpha4" dependencies = [ "cbindgen", "cfg-if", @@ -2193,7 +2193,7 @@ dependencies = [ [[package]] name = "wasmer-cache" -version = "1.0.0-alpha3" +version = "1.0.0-alpha4" dependencies = [ "blake3", "hex", @@ -2204,7 +2204,7 @@ dependencies = [ [[package]] name = "wasmer-cli" -version = "1.0.0-alpha3" +version = "1.0.0-alpha4" dependencies = [ "anyhow", "atty", @@ -2235,7 +2235,7 @@ dependencies = [ [[package]] name = "wasmer-compiler" -version = "1.0.0-alpha3" +version = "1.0.0-alpha4" dependencies = [ "enumset", "hashbrown 0.8.2", @@ -2252,7 +2252,7 @@ dependencies = [ [[package]] name = "wasmer-compiler-cranelift" -version = "1.0.0-alpha3" +version = "1.0.0-alpha4" dependencies = [ "cranelift-codegen", "cranelift-frontend", @@ -2271,7 +2271,7 @@ dependencies = [ [[package]] name = "wasmer-compiler-llvm" -version = "1.0.0-alpha3" +version = "1.0.0-alpha4" dependencies = [ "byteorder", "cc", @@ -2293,7 +2293,7 @@ dependencies = [ [[package]] name = "wasmer-compiler-singlepass" -version = "1.0.0-alpha3" +version = "1.0.0-alpha4" dependencies = [ "byteorder", "dynasm", @@ -2311,7 +2311,7 @@ dependencies = [ [[package]] name = "wasmer-emscripten" -version = "1.0.0-alpha3" +version = "1.0.0-alpha4" dependencies = [ "byteorder", "getrandom", @@ -2324,7 +2324,7 @@ dependencies = [ [[package]] name = "wasmer-engine" -version = "1.0.0-alpha3" +version = "1.0.0-alpha4" dependencies = [ "backtrace", "bincode", @@ -2342,7 +2342,7 @@ dependencies = [ [[package]] name = "wasmer-engine-dummy" -version = "1.0.0-alpha3" +version = "1.0.0-alpha4" dependencies = [ "bincode", "serde", @@ -2355,7 +2355,7 @@ dependencies = [ [[package]] name = "wasmer-engine-jit" -version = "1.0.0-alpha3" +version = "1.0.0-alpha4" dependencies = [ "bincode", "cfg-if", @@ -2371,7 +2371,7 @@ dependencies = [ [[package]] name = "wasmer-engine-native" -version = "1.0.0-alpha3" +version = "1.0.0-alpha4" dependencies = [ "bincode", "cfg-if", @@ -2390,7 +2390,7 @@ dependencies = [ [[package]] name = "wasmer-engine-object-file" -version = "1.0.0-alpha3" +version = "1.0.0-alpha4" dependencies = [ "bincode", "cfg-if", @@ -2408,7 +2408,7 @@ dependencies = [ [[package]] name = "wasmer-integration-tests-cli" -version = "1.0.0-alpha3" +version = "1.0.0-alpha4" dependencies = [ "anyhow", "tempfile", @@ -2416,7 +2416,7 @@ dependencies = [ [[package]] name = "wasmer-object" -version = "1.0.0-alpha3" +version = "1.0.0-alpha4" dependencies = [ "object 0.19.0", "thiserror", @@ -2426,7 +2426,7 @@ dependencies = [ [[package]] name = "wasmer-types" -version = "1.0.0-alpha3" +version = "1.0.0-alpha4" dependencies = [ "cranelift-entity", "serde", @@ -2434,7 +2434,7 @@ dependencies = [ [[package]] name = "wasmer-vm" -version = "1.0.0-alpha3" +version = "1.0.0-alpha4" dependencies = [ "backtrace", "cc", @@ -2452,7 +2452,7 @@ dependencies = [ [[package]] name = "wasmer-wasi" -version = "1.0.0-alpha3" +version = "1.0.0-alpha4" dependencies = [ "bincode", "byteorder", @@ -2470,7 +2470,7 @@ dependencies = [ [[package]] name = "wasmer-wasi-experimental-io-devices" -version = "1.0.0-alpha3" +version = "1.0.0-alpha4" dependencies = [ "minifb", "ref_thread_local", @@ -2482,7 +2482,7 @@ dependencies = [ [[package]] name = "wasmer-wast" -version = "1.0.0-alpha3" +version = "1.0.0-alpha4" dependencies = [ "anyhow", "serde", @@ -2496,7 +2496,7 @@ dependencies = [ [[package]] name = "wasmer-workspace" -version = "1.0.0-alpha3" +version = "1.0.0-alpha4" dependencies = [ "anyhow", "blake3", diff --git a/Cargo.toml b/Cargo.toml index 97975d4cc..dafadf68b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "wasmer-workspace" -version = "1.0.0-alpha3" +version = "1.0.0-alpha4" description = "Wasmer workspace" authors = ["Wasmer Engineering Team "] repository = "https://github.com/wasmerio/wasmer" @@ -10,19 +10,19 @@ publish = false autoexamples = false [dependencies] -wasmer = { version = "1.0.0-alpha3", path = "lib/api", default-features = false } -wasmer-compiler = { version = "1.0.0-alpha3", path = "lib/compiler" } -wasmer-compiler-cranelift = { version = "1.0.0-alpha3", path = "lib/compiler-cranelift", optional = true } -wasmer-compiler-singlepass = { version = "1.0.0-alpha3", path = "lib/compiler-singlepass", optional = true } -wasmer-compiler-llvm = { version = "1.0.0-alpha3", path = "lib/compiler-llvm", optional = true } -wasmer-engine = { version = "1.0.0-alpha3", path = "lib/engine" } -wasmer-engine-jit = { version = "1.0.0-alpha3", path = "lib/engine-jit", optional = true } -wasmer-engine-native = { version = "1.0.0-alpha3", path = "lib/engine-native", optional = true } -wasmer-engine-object-file = { version = "1.0.0-alpha3", path = "lib/engine-object-file", optional = true } -wasmer-wasi = { version = "1.0.0-alpha3", path = "lib/wasi", optional = true } -wasmer-wast = { version = "1.0.0-alpha3", path = "tests/lib/wast", optional = true } -wasmer-cache = { version = "1.0.0-alpha3", path = "lib/cache", optional = true } -wasmer-types = { version = "1.0.0-alpha3", path = "lib/wasmer-types" } +wasmer = { version = "1.0.0-alpha4", path = "lib/api", default-features = false } +wasmer-compiler = { version = "1.0.0-alpha4", path = "lib/compiler" } +wasmer-compiler-cranelift = { version = "1.0.0-alpha4", path = "lib/compiler-cranelift", optional = true } +wasmer-compiler-singlepass = { version = "1.0.0-alpha4", path = "lib/compiler-singlepass", optional = true } +wasmer-compiler-llvm = { version = "1.0.0-alpha4", path = "lib/compiler-llvm", optional = true } +wasmer-engine = { version = "1.0.0-alpha4", path = "lib/engine" } +wasmer-engine-jit = { version = "1.0.0-alpha4", path = "lib/engine-jit", optional = true } +wasmer-engine-native = { version = "1.0.0-alpha4", path = "lib/engine-native", optional = true } +wasmer-engine-object-file = { version = "1.0.0-alpha4", path = "lib/engine-object-file", optional = true } +wasmer-wasi = { version = "1.0.0-alpha4", path = "lib/wasi", optional = true } +wasmer-wast = { version = "1.0.0-alpha4", path = "tests/lib/wast", optional = true } +wasmer-cache = { version = "1.0.0-alpha4", path = "lib/cache", optional = true } +wasmer-types = { version = "1.0.0-alpha4", path = "lib/wasmer-types" } cfg-if = "0.1" [workspace] diff --git a/lib/api/Cargo.toml b/lib/api/Cargo.toml index dbaac537f..a66269bee 100644 --- a/lib/api/Cargo.toml +++ b/lib/api/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "wasmer" -version = "1.0.0-alpha3" +version = "1.0.0-alpha4" description = "High-performant WebAssembly runtime" categories = ["wasm"] keywords = ["wasm", "webassembly", "runtime", "vm"] @@ -11,15 +11,15 @@ readme = "README.md" edition = "2018" [dependencies] -wasmer-vm = { path = "../vm", version = "1.0.0-alpha3" } -wasmer-compiler-singlepass = { path = "../compiler-singlepass", version = "1.0.0-alpha3", optional = true } -wasmer-compiler-cranelift = { path = "../compiler-cranelift", version = "1.0.0-alpha3", optional = true } -wasmer-compiler-llvm = { path = "../compiler-llvm", version = "1.0.0-alpha3", optional = true } -wasmer-compiler = { path = "../compiler", version = "1.0.0-alpha3" } -wasmer-engine = { path = "../engine", version = "1.0.0-alpha3" } -wasmer-engine-jit = { path = "../engine-jit", version = "1.0.0-alpha3", optional = true } -wasmer-engine-native = { path = "../engine-native", version = "1.0.0-alpha3", optional = true } -wasmer-types = { path = "../wasmer-types", version = "1.0.0-alpha3" } +wasmer-vm = { path = "../vm", version = "1.0.0-alpha4" } +wasmer-compiler-singlepass = { path = "../compiler-singlepass", version = "1.0.0-alpha4", optional = true } +wasmer-compiler-cranelift = { path = "../compiler-cranelift", version = "1.0.0-alpha4", optional = true } +wasmer-compiler-llvm = { path = "../compiler-llvm", version = "1.0.0-alpha4", optional = true } +wasmer-compiler = { path = "../compiler", version = "1.0.0-alpha4" } +wasmer-engine = { path = "../engine", version = "1.0.0-alpha4" } +wasmer-engine-jit = { path = "../engine-jit", version = "1.0.0-alpha4", optional = true } +wasmer-engine-native = { path = "../engine-native", version = "1.0.0-alpha4", optional = true } +wasmer-types = { path = "../wasmer-types", version = "1.0.0-alpha4" } indexmap = { version = "1.4", features = ["serde-1"] } cfg-if = "0.1" wat = { version = "1.0", optional = true } diff --git a/lib/c-api/Cargo.toml b/lib/c-api/Cargo.toml index aeb0635db..312900c9f 100644 --- a/lib/c-api/Cargo.toml +++ b/lib/c-api/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "wasmer-c-api" -version = "1.0.0-alpha3" +version = "1.0.0-alpha4" description = "Wasmer C API library" categories = ["wasm", "api-bindings"] keywords = ["wasm", "webassembly", "runtime"] @@ -15,18 +15,18 @@ edition = "2018" crate-type = ["cdylib", "rlib", "staticlib"] [dependencies] -wasmer = { version = "1.0.0-alpha3", path = "../api", default-features = false } -wasmer-compiler = { version = "1.0.0-alpha3", path = "../compiler" } -wasmer-compiler-cranelift = { version = "1.0.0-alpha3", path = "../compiler-cranelift", optional = true } -wasmer-compiler-singlepass = { version = "1.0.0-alpha3", path = "../compiler-singlepass", optional = true } -wasmer-compiler-llvm = { version = "1.0.0-alpha3", path = "../compiler-llvm", optional = true } -wasmer-emscripten = { version = "1.0.0-alpha3", path = "../emscripten", optional = true } -wasmer-engine = { version = "1.0.0-alpha3", path = "../engine" } -wasmer-engine-jit = { version = "1.0.0-alpha3", path = "../engine-jit", optional = true } -wasmer-engine-native = { version = "1.0.0-alpha3", path = "../engine-native", optional = true } -wasmer-engine-object-file = { version = "1.0.0-alpha3", path = "../engine-object-file", optional = true } -wasmer-wasi = { version = "1.0.0-alpha3", path = "../wasi", optional = true } -wasmer-types = { version = "1.0.0-alpha3", path = "../wasmer-types" } +wasmer = { version = "1.0.0-alpha4", path = "../api", default-features = false } +wasmer-compiler = { version = "1.0.0-alpha4", path = "../compiler" } +wasmer-compiler-cranelift = { version = "1.0.0-alpha4", path = "../compiler-cranelift", optional = true } +wasmer-compiler-singlepass = { version = "1.0.0-alpha4", path = "../compiler-singlepass", optional = true } +wasmer-compiler-llvm = { version = "1.0.0-alpha4", path = "../compiler-llvm", optional = true } +wasmer-emscripten = { version = "1.0.0-alpha4", path = "../emscripten", optional = true } +wasmer-engine = { version = "1.0.0-alpha4", path = "../engine" } +wasmer-engine-jit = { version = "1.0.0-alpha4", path = "../engine-jit", optional = true } +wasmer-engine-native = { version = "1.0.0-alpha4", path = "../engine-native", optional = true } +wasmer-engine-object-file = { version = "1.0.0-alpha4", path = "../engine-object-file", optional = true } +wasmer-wasi = { version = "1.0.0-alpha4", path = "../wasi", optional = true } +wasmer-types = { version = "1.0.0-alpha4", path = "../wasmer-types" } cfg-if = "0.1" lazy_static = "1" libc = { version = "^0.2.69", default-features = false } @@ -37,7 +37,7 @@ typetag = { version = "0.1", optional = true } paste = "0.1" # for generating code in the same way thot the wasm-c-api does # Commented out for now until we can find a solution to the exported function problem -# wasmer-wasm-c-api = { version = "1.0.0-alpha3", path = "crates/wasm-c-api" } +# wasmer-wasm-c-api = { version = "1.0.0-alpha4", path = "crates/wasm-c-api" } [features] default = [ diff --git a/lib/cache/Cargo.toml b/lib/cache/Cargo.toml index 4f9b50871..584460397 100644 --- a/lib/cache/Cargo.toml +++ b/lib/cache/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "wasmer-cache" -version = "1.0.0-alpha3" +version = "1.0.0-alpha4" description = "Cache system for Wasmer WebAssembly runtime" categories = ["wasm", "caching"] keywords = ["wasm", "webassembly", "cache"] @@ -11,7 +11,7 @@ readme = "README.md" edition = "2018" [dependencies] -wasmer = { path = "../api", version = "1.0.0-alpha3", default-features = false } +wasmer = { path = "../api", version = "1.0.0-alpha4", default-features = false } memmap = "0.7" hex = "0.4" thiserror = "1" diff --git a/lib/cli/Cargo.toml b/lib/cli/Cargo.toml index b73828bf8..d77057719 100644 --- a/lib/cli/Cargo.toml +++ b/lib/cli/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "wasmer-cli" -version = "1.0.0-alpha3" +version = "1.0.0-alpha4" description = "Wasmer CLI" categories = ["wasm", "command-line-interface"] keywords = ["wasm", "webassembly", "cli"] @@ -17,22 +17,22 @@ path = "src/bin/wasmer.rs" doc = false [dependencies] -wasmer = { version = "1.0.0-alpha3", path = "../api", default-features = false } -wasmer-compiler = { version = "1.0.0-alpha3", path = "../compiler" } -wasmer-compiler-cranelift = { version = "1.0.0-alpha3", path = "../compiler-cranelift", optional = true } -wasmer-compiler-singlepass = { version = "1.0.0-alpha3", path = "../compiler-singlepass", optional = true } -wasmer-compiler-llvm = { version = "1.0.0-alpha3", path = "../compiler-llvm", optional = true } -wasmer-emscripten = { version = "1.0.0-alpha3", path = "../emscripten", optional = true } -wasmer-engine = { version = "1.0.0-alpha3", path = "../engine" } -wasmer-engine-jit = { version = "1.0.0-alpha3", path = "../engine-jit", optional = true } -wasmer-engine-native = { version = "1.0.0-alpha3", path = "../engine-native", optional = true } -wasmer-engine-object-file = { version = "1.0.0-alpha3", path = "../engine-object-file", optional = true } -wasmer-vm = { version = "1.0.0-alpha3", path = "../vm" } -wasmer-wasi = { version = "1.0.0-alpha3", path = "../wasi", optional = true } -wasmer-wasi-experimental-io-devices = { version = "1.0.0-alpha3", path = "../wasi-experimental-io-devices", optional = true } -wasmer-wast = { version = "1.0.0-alpha3", path = "../../tests/lib/wast", optional = true } -wasmer-cache = { version = "1.0.0-alpha3", path = "../cache", optional = true } -wasmer-types = { version = "1.0.0-alpha3", path = "../wasmer-types" } +wasmer = { version = "1.0.0-alpha4", path = "../api", default-features = false } +wasmer-compiler = { version = "1.0.0-alpha4", path = "../compiler" } +wasmer-compiler-cranelift = { version = "1.0.0-alpha4", path = "../compiler-cranelift", optional = true } +wasmer-compiler-singlepass = { version = "1.0.0-alpha4", path = "../compiler-singlepass", optional = true } +wasmer-compiler-llvm = { version = "1.0.0-alpha4", path = "../compiler-llvm", optional = true } +wasmer-emscripten = { version = "1.0.0-alpha4", path = "../emscripten", optional = true } +wasmer-engine = { version = "1.0.0-alpha4", path = "../engine" } +wasmer-engine-jit = { version = "1.0.0-alpha4", path = "../engine-jit", optional = true } +wasmer-engine-native = { version = "1.0.0-alpha4", path = "../engine-native", optional = true } +wasmer-engine-object-file = { version = "1.0.0-alpha4", path = "../engine-object-file", optional = true } +wasmer-vm = { version = "1.0.0-alpha4", path = "../vm" } +wasmer-wasi = { version = "1.0.0-alpha4", path = "../wasi", optional = true } +wasmer-wasi-experimental-io-devices = { version = "1.0.0-alpha4", path = "../wasi-experimental-io-devices", optional = true } +wasmer-wast = { version = "1.0.0-alpha4", path = "../../tests/lib/wast", optional = true } +wasmer-cache = { version = "1.0.0-alpha4", path = "../cache", optional = true } +wasmer-types = { version = "1.0.0-alpha4", path = "../wasmer-types" } atty = "0.2" colored = "2.0" anyhow = "1.0" diff --git a/lib/compiler-cranelift/Cargo.toml b/lib/compiler-cranelift/Cargo.toml index 286d45d2b..40ed587d8 100644 --- a/lib/compiler-cranelift/Cargo.toml +++ b/lib/compiler-cranelift/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "wasmer-compiler-cranelift" -version = "1.0.0-alpha3" +version = "1.0.0-alpha4" description = "Cranelift compiler for Wasmer WebAssembly runtime" categories = ["wasm"] keywords = ["wasm", "webassembly", "compiler", "cranelift"] @@ -12,9 +12,9 @@ readme = "README.md" edition = "2018" [dependencies] -wasmer-compiler = { path = "../compiler", version = "1.0.0-alpha3", features = ["translator"], default-features = false } -wasmer-vm = { path = "../vm", version = "1.0.0-alpha3" } -wasmer-types = { path = "../wasmer-types", version = "1.0.0-alpha3", default-features = false, features = ["std"] } +wasmer-compiler = { path = "../compiler", version = "1.0.0-alpha4", features = ["translator"], default-features = false } +wasmer-vm = { path = "../vm", version = "1.0.0-alpha4" } +wasmer-types = { path = "../wasmer-types", version = "1.0.0-alpha4", default-features = false, features = ["std"] } cranelift-codegen = { version = "0.65", default-features = false } cranelift-frontend = { version = "0.65", default-features = false } tracing = "0.1" diff --git a/lib/compiler-llvm/Cargo.toml b/lib/compiler-llvm/Cargo.toml index 07c244b09..87a7c0295 100644 --- a/lib/compiler-llvm/Cargo.toml +++ b/lib/compiler-llvm/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "wasmer-compiler-llvm" -version = "1.0.0-alpha3" +version = "1.0.0-alpha4" description = "LLVM compiler for Wasmer WebAssembly runtime" categories = ["wasm"] keywords = ["wasm", "webassembly", "compiler", "llvm"] @@ -12,9 +12,9 @@ readme = "README.md" edition = "2018" [dependencies] -wasmer-compiler = { path = "../compiler", version = "1.0.0-alpha3", features = ["translator"] } -wasmer-vm = { path = "../vm", version = "1.0.0-alpha3" } -wasmer-types = { path = "../wasmer-types", version = "1.0.0-alpha3" } +wasmer-compiler = { path = "../compiler", version = "1.0.0-alpha4", features = ["translator"] } +wasmer-vm = { path = "../vm", version = "1.0.0-alpha4" } +wasmer-types = { path = "../wasmer-types", version = "1.0.0-alpha4" } target-lexicon = { version = "0.10", default-features = false } smallvec = "1" goblin = "0.2" diff --git a/lib/compiler-singlepass/Cargo.toml b/lib/compiler-singlepass/Cargo.toml index b6f441ddb..9966a9dbc 100644 --- a/lib/compiler-singlepass/Cargo.toml +++ b/lib/compiler-singlepass/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "wasmer-compiler-singlepass" -version = "1.0.0-alpha3" +version = "1.0.0-alpha4" description = "Singlepass compiler for Wasmer WebAssembly runtime" categories = ["wasm"] keywords = ["wasm", "webassembly", "compiler", "singlepass"] @@ -12,9 +12,9 @@ readme = "README.md" edition = "2018" [dependencies] -wasmer-compiler = { path = "../compiler", version = "1.0.0-alpha3", features = ["translator"], default-features = false } -wasmer-vm = { path = "../vm", version = "1.0.0-alpha3" } -wasmer-types = { path = "../wasmer-types", version = "1.0.0-alpha3", default-features = false, features = ["std"] } +wasmer-compiler = { path = "../compiler", version = "1.0.0-alpha4", features = ["translator"], default-features = false } +wasmer-vm = { path = "../vm", version = "1.0.0-alpha4" } +wasmer-types = { path = "../wasmer-types", version = "1.0.0-alpha4", default-features = false, features = ["std"] } rayon = "1.3" hashbrown = { version = "0.8", optional = true } serde = { version = "1.0", features = ["derive"] } diff --git a/lib/compiler/Cargo.toml b/lib/compiler/Cargo.toml index a31b4fc84..fc830edcd 100644 --- a/lib/compiler/Cargo.toml +++ b/lib/compiler/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "wasmer-compiler" -version = "1.0.0-alpha3" +version = "1.0.0-alpha4" description = "Base compiler abstraction for Wasmer WebAssembly runtime" categories = ["wasm", "no-std"] keywords = ["wasm", "webassembly", "compiler"] @@ -11,8 +11,8 @@ readme = "README.md" edition = "2018" [dependencies] -wasmer-vm = { path = "../vm", version = "1.0.0-alpha3" } -wasmer-types = { path = "../wasmer-types", version = "1.0.0-alpha3", default-features = false } +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 } target-lexicon = { version = "0.10", default-features = false } enumset = "1.0" diff --git a/lib/deprecated/runtime-core/Cargo.toml b/lib/deprecated/runtime-core/Cargo.toml index f241f8419..603e56a5b 100644 --- a/lib/deprecated/runtime-core/Cargo.toml +++ b/lib/deprecated/runtime-core/Cargo.toml @@ -14,16 +14,16 @@ edition = "2018" maintenance = { status = "deprecated" } [dependencies] -wasmer-types = { path = "../../wasmer-types", version = "1.0.0-alpha3" } -wasmer = { path = "../../api", version = "1.0.0-alpha3" } -wasmer-cache = { path = "../../cache", version = "1.0.0-alpha3" } -wasmer-compiler = { path = "../../compiler", version = "1.0.0-alpha3", features = ["translator"] } -wasmer-compiler-llvm = { path = "../../compiler-llvm", version = "1.0.0-alpha3", optional = true } -wasmer-compiler-cranelift = { path = "../../compiler-cranelift", version = "1.0.0-alpha3", optional = true } -wasmer-compiler-singlepass = { path = "../../compiler-singlepass", version = "1.0.0-alpha3", optional = true } -wasmer-engine = { path = "../../engine", version = "1.0.0-alpha3" } -wasmer-engine-jit = { path = "../../engine-jit", version = "1.0.0-alpha3" } -wasmer-vm = { path = "../../vm", version = "1.0.0-alpha3" } +wasmer-types = { path = "../../wasmer-types", version = "1.0.0-alpha4" } +wasmer = { path = "../../api", version = "1.0.0-alpha4" } +wasmer-cache = { path = "../../cache", version = "1.0.0-alpha4" } +wasmer-compiler = { path = "../../compiler", version = "1.0.0-alpha4", features = ["translator"] } +wasmer-compiler-llvm = { path = "../../compiler-llvm", version = "1.0.0-alpha4", optional = true } +wasmer-compiler-cranelift = { path = "../../compiler-cranelift", version = "1.0.0-alpha4", optional = true } +wasmer-compiler-singlepass = { path = "../../compiler-singlepass", version = "1.0.0-alpha4", optional = true } +wasmer-engine = { path = "../../engine", version = "1.0.0-alpha4" } +wasmer-engine-jit = { path = "../../engine-jit", version = "1.0.0-alpha4" } +wasmer-vm = { path = "../../vm", version = "1.0.0-alpha4" } lazy_static = "1.4" [build-dependencies] diff --git a/lib/emscripten/Cargo.toml b/lib/emscripten/Cargo.toml index 39a905ea6..1cb602d33 100644 --- a/lib/emscripten/Cargo.toml +++ b/lib/emscripten/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "wasmer-emscripten" -version = "1.0.0-alpha3" +version = "1.0.0-alpha4" description = "Emscripten implementation library for Wasmer WebAssembly runtime" categories = ["wasm", "os"] keywords = ["wasm", "webassembly", "abi", "emscripten", "posix"] @@ -16,7 +16,7 @@ lazy_static = "1.4" libc = "^0.2.69" log = "0.4" time = "0.1" -wasmer = { path = "../api", version = "1.0.0-alpha3", default-features = false } +wasmer = { path = "../api", version = "1.0.0-alpha4", default-features = false } [target.'cfg(windows)'.dependencies] getrandom = "0.1" diff --git a/lib/engine-jit/Cargo.toml b/lib/engine-jit/Cargo.toml index 823e0dc30..7c0726b6b 100644 --- a/lib/engine-jit/Cargo.toml +++ b/lib/engine-jit/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "wasmer-engine-jit" -version = "1.0.0-alpha3" +version = "1.0.0-alpha4" description = "Wasmer JIT Engine" categories = ["wasm"] keywords = ["wasm", "webassembly", "engine", "jit"] @@ -11,10 +11,10 @@ readme = "README.md" edition = "2018" [dependencies] -wasmer-types = { path = "../wasmer-types", version = "1.0.0-alpha3" } -wasmer-compiler = { path = "../compiler", version = "1.0.0-alpha3", features = ["translator"] } -wasmer-vm = { path = "../vm", version = "1.0.0-alpha3" } -wasmer-engine = { path = "../engine", version = "1.0.0-alpha3" } +wasmer-types = { path = "../wasmer-types", version = "1.0.0-alpha4" } +wasmer-compiler = { path = "../compiler", version = "1.0.0-alpha4", features = ["translator"] } +wasmer-vm = { path = "../vm", version = "1.0.0-alpha4" } +wasmer-engine = { path = "../engine", version = "1.0.0-alpha4" } # flexbuffers = { path = "../../../flatbuffers/rust/flexbuffers", version = "0.1.0" } region = "2.2" serde = { version = "1.0", features = ["derive", "rc"] } diff --git a/lib/engine-native/Cargo.toml b/lib/engine-native/Cargo.toml index 7dc877b52..1ee178f85 100644 --- a/lib/engine-native/Cargo.toml +++ b/lib/engine-native/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "wasmer-engine-native" -version = "1.0.0-alpha3" +version = "1.0.0-alpha4" description = "Wasmer Native Engine" categories = ["wasm"] keywords = ["wasm", "webassembly", "engine", "native"] @@ -11,11 +11,11 @@ readme = "README.md" edition = "2018" [dependencies] -wasmer-types = { path = "../wasmer-types", version = "1.0.0-alpha3" } -wasmer-compiler = { path = "../compiler", version = "1.0.0-alpha3" } -wasmer-vm = { path = "../vm", version = "1.0.0-alpha3" } -wasmer-engine = { path = "../engine", version = "1.0.0-alpha3" } -wasmer-object = { path = "../object", version = "1.0.0-alpha3" } +wasmer-types = { path = "../wasmer-types", version = "1.0.0-alpha4" } +wasmer-compiler = { path = "../compiler", version = "1.0.0-alpha4" } +wasmer-vm = { path = "../vm", version = "1.0.0-alpha4" } +wasmer-engine = { path = "../engine", version = "1.0.0-alpha4" } +wasmer-object = { path = "../object", version = "1.0.0-alpha4" } serde = { version = "1.0", features = ["derive", "rc"] } cfg-if = "0.1" tracing = "0.1" diff --git a/lib/engine-object-file/Cargo.toml b/lib/engine-object-file/Cargo.toml index 62570ec5b..0c9005a5f 100644 --- a/lib/engine-object-file/Cargo.toml +++ b/lib/engine-object-file/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "wasmer-engine-object-file" -version = "1.0.0-alpha3" +version = "1.0.0-alpha4" authors = ["Wasmer Engineering Team "] description = "Wasmer Object File Engine" categories = ["wasm"] @@ -10,11 +10,11 @@ readme = "README.md" edition = "2018" [dependencies] -wasmer-types = { path = "../wasmer-types", version = "1.0.0-alpha3" } -wasmer-compiler = { path = "../compiler", version = "1.0.0-alpha3" } +wasmer-types = { path = "../wasmer-types", version = "1.0.0-alpha4" } +wasmer-compiler = { path = "../compiler", version = "1.0.0-alpha4" } wasmer-vm = { path = "../vm", version = "1.0.0-alpha01.0" } -wasmer-engine = { path = "../engine", version = "1.0.0-alpha3" } -wasmer-object = { path = "../object", version = "1.0.0-alpha3" } +wasmer-engine = { path = "../engine", version = "1.0.0-alpha4" } +wasmer-object = { path = "../object", version = "1.0.0-alpha4" } serde = { version = "1.0", features = ["derive", "rc"] } cfg-if = "0.1" tracing = "0.1" diff --git a/lib/engine/Cargo.toml b/lib/engine/Cargo.toml index 7696068af..87c611ad5 100644 --- a/lib/engine/Cargo.toml +++ b/lib/engine/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "wasmer-engine" -version = "1.0.0-alpha3" +version = "1.0.0-alpha4" description = "Wasmer Engine abstraction" categories = ["wasm"] keywords = ["wasm", "webassembly", "engine"] @@ -11,9 +11,9 @@ readme = "README.md" edition = "2018" [dependencies] -wasmer-types = { path = "../wasmer-types", version = "1.0.0-alpha3" } -wasmer-compiler = { path = "../compiler", version = "1.0.0-alpha3" } -wasmer-vm = { path = "../vm", version = "1.0.0-alpha3" } +wasmer-types = { path = "../wasmer-types", version = "1.0.0-alpha4" } +wasmer-compiler = { path = "../compiler", version = "1.0.0-alpha4" } +wasmer-vm = { path = "../vm", version = "1.0.0-alpha4" } target-lexicon = { version = "0.10", default-features = false } # flexbuffers = { path = "../../../flatbuffers/rust/flexbuffers", version = "0.1.0" } backtrace = "0.3" diff --git a/lib/object/Cargo.toml b/lib/object/Cargo.toml index b25b384cd..0e41bd522 100644 --- a/lib/object/Cargo.toml +++ b/lib/object/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "wasmer-object" -version = "1.0.0-alpha3" +version = "1.0.0-alpha4" description = "Wasmer Native Object generator" categories = ["wasm"] keywords = ["wasm", "webassembly"] @@ -11,8 +11,8 @@ readme = "README.md" edition = "2018" [dependencies] -wasmer-types = { path = "../wasmer-types", version = "1.0.0-alpha3" } -wasmer-compiler = { path = "../compiler", version = "1.0.0-alpha3", default-features = false, features = [ +wasmer-types = { path = "../wasmer-types", version = "1.0.0-alpha4" } +wasmer-compiler = { path = "../compiler", version = "1.0.0-alpha4", default-features = false, features = [ "std", "translator" ] } diff --git a/lib/vm/Cargo.toml b/lib/vm/Cargo.toml index ccbadb71c..30dc929c4 100644 --- a/lib/vm/Cargo.toml +++ b/lib/vm/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "wasmer-vm" -version = "1.0.0-alpha3" +version = "1.0.0-alpha4" description = "Runtime library support for Wasmer" categories = ["wasm"] keywords = ["wasm", "webassembly"] @@ -11,7 +11,7 @@ readme = "README.md" edition = "2018" [dependencies] -wasmer-types = { path = "../wasmer-types", version = "1.0.0-alpha3" } +wasmer-types = { path = "../wasmer-types", version = "1.0.0-alpha4" } region = "2.2" libc = { version = "^0.2.69", default-features = false } memoffset = "0.5" diff --git a/lib/wasi-experimental-io-devices/Cargo.toml b/lib/wasi-experimental-io-devices/Cargo.toml index dbc82f232..73985d363 100644 --- a/lib/wasi-experimental-io-devices/Cargo.toml +++ b/lib/wasi-experimental-io-devices/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "wasmer-wasi-experimental-io-devices" -version = "1.0.0-alpha3" +version = "1.0.0-alpha4" description = "An experimental non-standard WASI extension for graphics" categories = ["wasm"] keywords = ["wasm", "webassembly", "types"] @@ -14,7 +14,7 @@ edition = "2018" maintenance = { status = "experimental" } [dependencies] -wasmer-wasi = { version = "1.0.0-alpha3", path = "../wasi" } +wasmer-wasi = { version = "1.0.0-alpha4", path = "../wasi" } tracing = "0.1" minifb = "0.16" ref_thread_local = "0.0" diff --git a/lib/wasi/Cargo.toml b/lib/wasi/Cargo.toml index 1eb273748..eea131462 100644 --- a/lib/wasi/Cargo.toml +++ b/lib/wasi/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "wasmer-wasi" -version = "1.0.0-alpha3" +version = "1.0.0-alpha4" description = "WASI implementation library for Wasmer WebAssembly runtime" categories = ["wasm", "os"] keywords = ["wasm", "webassembly", "wasi", "sandbox", "ABI"] @@ -21,7 +21,7 @@ getrandom = "0.1" time = "0.1" typetag = "0.1" serde = { version = "1.0", features = ["derive"] } -wasmer = { path = "../api", version = "1.0.0-alpha3", default-features = false } +wasmer = { path = "../api", version = "1.0.0-alpha4", default-features = false } [target.'cfg(windows)'.dependencies] winapi = "0.3" diff --git a/lib/wasmer-types/Cargo.toml b/lib/wasmer-types/Cargo.toml index 9232f45f6..b47c8a9e6 100644 --- a/lib/wasmer-types/Cargo.toml +++ b/lib/wasmer-types/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "wasmer-types" -version = "1.0.0-alpha3" +version = "1.0.0-alpha4" description = "Wasmer Common Types" categories = ["wasm", "no-std", "data-structures"] keywords = ["wasm", "webassembly", "types"] diff --git a/scripts/publish.py b/scripts/publish.py index c0f9fd134..8fce6df0b 100644 --- a/scripts/publish.py +++ b/scripts/publish.py @@ -21,7 +21,7 @@ except ImportError: # TODO: find this automatically -target_version = "1.0.0-alpha3" +target_version = "1.0.0-alpha4" # TODO: generate this by parsing toml files dep_graph = { diff --git a/scripts/update-version.sh b/scripts/update-version.sh index 8bc0826af..aa1fb9dea 100755 --- a/scripts/update-version.sh +++ b/scripts/update-version.sh @@ -1,6 +1,6 @@ # A script to update the version of all the crates at the same time -PREVIOUS_VERSION='1.0.0-alpha02.0' -NEXT_VERSION='1.0.0-alpha3' +PREVIOUS_VERSION='1.0.0-alpha3' +NEXT_VERSION='1.0.0-alpha4' # quick hack fd Cargo.toml --exec sed -i '' "s/version = \"$PREVIOUS_VERSION\"/version = \"$NEXT_VERSION\"/" diff --git a/scripts/windows-installer/wasmer.iss b/scripts/windows-installer/wasmer.iss index aba12d73b..ba8eb6044 100644 --- a/scripts/windows-installer/wasmer.iss +++ b/scripts/windows-installer/wasmer.iss @@ -1,6 +1,6 @@ [Setup] AppName=Wasmer -AppVersion=1.0.0-alpha3 +AppVersion=1.0.0-alpha4 DefaultDirName={pf}\Wasmer DefaultGroupName=Wasmer Compression=lzma2 diff --git a/tests/integration/cli/Cargo.toml b/tests/integration/cli/Cargo.toml index 3b2a58a09..a6803db3b 100644 --- a/tests/integration/cli/Cargo.toml +++ b/tests/integration/cli/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "wasmer-integration-tests-cli" -version = "1.0.0-alpha3" +version = "1.0.0-alpha4" authors = ["Wasmer Engineering Team "] description = "CLI integration tests" repository = "https://github.com/wasmerio/wasmer" @@ -9,4 +9,4 @@ publish = false [dependencies] anyhow = "1" -tempfile = "3" \ No newline at end of file +tempfile = "3" diff --git a/tests/lib/engine-dummy/Cargo.toml b/tests/lib/engine-dummy/Cargo.toml index 9ed8ca71d..e7044a276 100644 --- a/tests/lib/engine-dummy/Cargo.toml +++ b/tests/lib/engine-dummy/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "wasmer-engine-dummy" -version = "1.0.0-alpha3" +version = "1.0.0-alpha4" authors = ["Wasmer Engineering Team "] description = "Wasmer placeholder engine" license = "MIT" @@ -8,10 +8,10 @@ edition = "2018" publish = false [dependencies] -wasmer-types = { path = "../../../lib/wasmer-types", version = "1.0.0-alpha3" } -wasmer-compiler = { path = "../../../lib/compiler", version = "1.0.0-alpha3" } -wasmer-vm = { path = "../../../lib/vm", version = "1.0.0-alpha3" } -wasmer-engine = { path = "../../../lib/engine", version = "1.0.0-alpha3" } +wasmer-types = { path = "../../../lib/wasmer-types", version = "1.0.0-alpha4" } +wasmer-compiler = { path = "../../../lib/compiler", version = "1.0.0-alpha4" } +wasmer-vm = { path = "../../../lib/vm", version = "1.0.0-alpha4" } +wasmer-engine = { path = "../../../lib/engine", version = "1.0.0-alpha4" } serde = { version = "1.0", features = ["derive", "rc"], optional = true } serde_bytes = { version = "0.11", optional = true } bincode = { version = "1.2", optional = true } diff --git a/tests/lib/wast/Cargo.toml b/tests/lib/wast/Cargo.toml index d22ce7751..de453bb9e 100644 --- a/tests/lib/wast/Cargo.toml +++ b/tests/lib/wast/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "wasmer-wast" -version = "1.0.0-alpha3" +version = "1.0.0-alpha4" authors = ["Wasmer Engineering Team "] description = "wast testing support for wasmer" license = "MIT OR (Apache-2.0 WITH LLVM-exception)" @@ -12,8 +12,8 @@ edition = "2018" [dependencies] anyhow = "1.0" -wasmer = { path = "../../../lib/api", version = "1.0.0-alpha3", default-features = false } -wasmer-wasi = { path = "../../../lib/wasi", version = "1.0.0-alpha3" } +wasmer = { path = "../../../lib/api", version = "1.0.0-alpha4", default-features = false } +wasmer-wasi = { path = "../../../lib/wasi", version = "1.0.0-alpha4" } wast = "17.0" serde = "1" tempfile = "3" From e57a6810c5a065356b5a43a8b93420919617b32e Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Thu, 8 Oct 2020 16:56:11 -0700 Subject: [PATCH 166/281] Include wasmer_wasm.h and update doc path --- Makefile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index ab9c17c05..99a38fd98 100644 --- a/Makefile +++ b/Makefile @@ -174,7 +174,8 @@ package-capi: mkdir -p "package/include" mkdir -p "package/lib" cp lib/c-api/wasmer.h* package/include - cp lib/c-api/doc/index.md package/include/README.md + cp lib/c-api/wasmer_wasm.h* package/include + cp lib/c-api/doc/deprecated/index.md package/include/README.md ifeq ($(OS), Windows_NT) cp target/release/wasmer_c_api.dll package/lib cp target/release/wasmer_c_api.lib package/lib From bfd10da1adc5766834a9031566b3e70774904392 Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Thu, 8 Oct 2020 17:03:02 -0700 Subject: [PATCH 167/281] Use custom build of llvm for mac and linux releases --- .github/workflows/main.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/main.yaml b/.github/workflows/main.yaml index a2e1d1bd0..5d81f4243 100644 --- a/.github/workflows/main.yaml +++ b/.github/workflows/main.yaml @@ -43,13 +43,13 @@ jobs: - build: linux os: ubuntu-latest rust: 1.46.0 - llvm_url: 'https://github.com/llvm/llvm-project/releases/download/llvmorg-10.0.0/clang+llvm-10.0.0-x86_64-linux-gnu-ubuntu-18.04.tar.xz' + llvm_url: 'https://github.com/wasmerio/llvm-build/releases/download/10.x/Ubuntu1910_Release.tar.xz' artifact_name: 'wasmer-linux-amd64' run_integration_tests: true - build: macos os: macos-latest rust: 1.46.0 - llvm_url: 'https://github.com/llvm/llvm-project/releases/download/llvmorg-10.0.0/clang+llvm-10.0.0-x86_64-apple-darwin.tar.xz' + llvm_url: 'https://github.com/wasmerio/llvm-build/releases/download/10.x/MacOS_Release.tar.xz' artifact_name: 'wasmer-macos-amd64' run_integration_tests: true - build: windows From 2bb3243fbb9d3597f9ebb1e6d6fd1ad0f0644dda Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Thu, 8 Oct 2020 17:30:48 -0700 Subject: [PATCH 168/281] Revert llvm url change --- .github/workflows/main.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/main.yaml b/.github/workflows/main.yaml index 5d81f4243..a2e1d1bd0 100644 --- a/.github/workflows/main.yaml +++ b/.github/workflows/main.yaml @@ -43,13 +43,13 @@ jobs: - build: linux os: ubuntu-latest rust: 1.46.0 - llvm_url: 'https://github.com/wasmerio/llvm-build/releases/download/10.x/Ubuntu1910_Release.tar.xz' + llvm_url: 'https://github.com/llvm/llvm-project/releases/download/llvmorg-10.0.0/clang+llvm-10.0.0-x86_64-linux-gnu-ubuntu-18.04.tar.xz' artifact_name: 'wasmer-linux-amd64' run_integration_tests: true - build: macos os: macos-latest rust: 1.46.0 - llvm_url: 'https://github.com/wasmerio/llvm-build/releases/download/10.x/MacOS_Release.tar.xz' + llvm_url: 'https://github.com/llvm/llvm-project/releases/download/llvmorg-10.0.0/clang+llvm-10.0.0-x86_64-apple-darwin.tar.xz' artifact_name: 'wasmer-macos-amd64' run_integration_tests: true - build: windows From f8a7ee20c35ae356924d0b3cdc2ed157628276bc Mon Sep 17 00:00:00 2001 From: Nick Lewycky Date: Thu, 8 Oct 2020 19:38:52 -0700 Subject: [PATCH 169/281] Always write out the whole header file. write() may return after completing part of a write and returns the amount written. Use write_all(). https://rust-lang.github.io/rust-clippy/master/index.html#unused_io_amount --- lib/cli/src/commands/compile.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/cli/src/commands/compile.rs b/lib/cli/src/commands/compile.rs index 1e77a08f2..f2e158a32 100644 --- a/lib/cli/src/commands/compile.rs +++ b/lib/cli/src/commands/compile.rs @@ -135,7 +135,7 @@ impl Compile { .open(&header_path)?; use std::io::Write; - header.write(header_file_src.as_bytes())?; + header.write_all(header_file_src.as_bytes())?; eprintln!( "✔ Header file generated successfully at `{}`.", header_path.display(), From 3031abec9147193c5b36dc6e860111231aa9c103 Mon Sep 17 00:00:00 2001 From: Nick Lewycky Date: Thu, 8 Oct 2020 19:40:41 -0700 Subject: [PATCH 170/281] NFC. Rewrite these using the matches! macro. https://doc.rust-lang.org/beta/std/macro.matches.html --- lib/wasmer-types/src/types.rs | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/lib/wasmer-types/src/types.rs b/lib/wasmer-types/src/types.rs index 70c9467b6..4caf91df9 100644 --- a/lib/wasmer-types/src/types.rs +++ b/lib/wasmer-types/src/types.rs @@ -38,18 +38,15 @@ impl Type { /// Returns true if `Type` matches any of the numeric types. (e.g. `I32`, /// `I64`, `F32`, `F64`, `V128`). pub fn is_num(self) -> bool { - match self { - Self::I32 | Self::I64 | Self::F32 | Self::F64 | Self::V128 => true, - _ => false, - } + matches!( + self, + Self::I32 | Self::I64 | Self::F32 | Self::F64 | Self::V128 + ) } /// Returns true if `Type` matches either of the reference types. pub fn is_ref(self) -> bool { - match self { - Self::ExternRef | Self::FuncRef => true, - _ => false, - } + matches!(self, Self::ExternRef | Self::FuncRef) } } From 6ffbbb750058e7aa2b6042bc75f518bb195b7548 Mon Sep 17 00:00:00 2001 From: Nick Lewycky Date: Thu, 8 Oct 2020 19:51:39 -0700 Subject: [PATCH 171/281] Use copy instead of clone. https://rust-lang.github.io/rust-clippy/master/index.html#clone_on_copy --- lib/vm/src/instance.rs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/lib/vm/src/instance.rs b/lib/vm/src/instance.rs index b38e9594a..d5a674cee 100644 --- a/lib/vm/src/instance.rs +++ b/lib/vm/src/instance.rs @@ -182,13 +182,13 @@ impl Instance { /// Return the indexed `VMTableDefinition`. #[allow(dead_code)] fn table(&self, index: LocalTableIndex) -> VMTableDefinition { - unsafe { self.table_ptr(index).as_ref().clone() } + unsafe { *self.table_ptr(index).as_ref() } } /// Updates the value for a defined table to `VMTableDefinition`. fn set_table(&self, index: LocalTableIndex, table: &VMTableDefinition) { unsafe { - *self.table_ptr(index).as_ptr() = table.clone(); + *self.table_ptr(index).as_ptr() = *table; } } @@ -209,19 +209,19 @@ impl Instance { self.memory(local_index) } else { let import = self.imported_memory(index); - unsafe { import.definition.as_ref().clone() } + unsafe { *import.definition.as_ref() } } } /// Return the indexed `VMMemoryDefinition`. fn memory(&self, index: LocalMemoryIndex) -> VMMemoryDefinition { - unsafe { self.memory_ptr(index).as_ref().clone() } + unsafe { *self.memory_ptr(index).as_ref() } } /// Set the indexed memory to `VMMemoryDefinition`. fn set_memory(&self, index: LocalMemoryIndex, mem: &VMMemoryDefinition) { unsafe { - *self.memory_ptr(index).as_ptr() = mem.clone(); + *self.memory_ptr(index).as_ptr() = *mem; } } @@ -805,7 +805,7 @@ impl InstanceHandle { .values() .map(|t| { let vmtable_ptr = t.vmtable(); - vmtable_ptr.as_ref().clone() + *vmtable_ptr.as_ref() }) .collect::>() .into_boxed_slice(); @@ -814,7 +814,7 @@ impl InstanceHandle { .values() .map(|m| { let vmmemory_ptr = m.as_ref().vmmemory(); - vmmemory_ptr.as_ref().clone() + *vmmemory_ptr.as_ref() }) .collect::>() .into_boxed_slice(); @@ -1136,7 +1136,7 @@ unsafe fn get_memory_slice<'instance>( instance.memory(local_memory_index) } else { let import = instance.imported_memory(init.location.memory_index); - import.definition.as_ref().clone() + *import.definition.as_ref() }; slice::from_raw_parts_mut(memory.base, memory.current_length.try_into().unwrap()) } From 804204dfdb2fbecf0bfb01600a705c107c839d5b Mon Sep 17 00:00:00 2001 From: Nick Lewycky Date: Thu, 8 Oct 2020 19:52:41 -0700 Subject: [PATCH 172/281] Use copy instead of clone. https://rust-lang.github.io/rust-clippy/master/index.html#clone_on_copy --- lib/vm/src/memory.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/vm/src/memory.rs b/lib/vm/src/memory.rs index f632b9fc8..11a0b2448 100644 --- a/lib/vm/src/memory.rs +++ b/lib/vm/src/memory.rs @@ -219,7 +219,7 @@ impl LinearMemory { base: base_ptr, current_length: memory.minimum.bytes().0.try_into().unwrap(), })), - memory: memory.clone(), + memory: *memory, style: style.clone(), }) } From 2a52e1f1b831a984577dff8c08851629806b4617 Mon Sep 17 00:00:00 2001 From: Nick Lewycky Date: Thu, 8 Oct 2020 19:55:00 -0700 Subject: [PATCH 173/281] Simplify this code using ok_or instead of ok_or_else. https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_lazy_evaluations --- lib/vm/src/memory.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/vm/src/memory.rs b/lib/vm/src/memory.rs index 11a0b2448..f603eb0a5 100644 --- a/lib/vm/src/memory.rs +++ b/lib/vm/src/memory.rs @@ -259,7 +259,7 @@ impl Memory for LinearMemory { let new_pages = mmap .size .checked_add(delta) - .ok_or_else(|| MemoryError::CouldNotGrow { + .ok_or(MemoryError::CouldNotGrow { current: mmap.size, attempted_delta: delta, })?; From 628b5ea1baf6b1205290633920e49af3c4e7a3ca Mon Sep 17 00:00:00 2001 From: Nick Lewycky Date: Thu, 8 Oct 2020 19:58:05 -0700 Subject: [PATCH 174/281] Use copy instead of clone. https://rust-lang.github.io/rust-clippy/master/index.html#clone_on_copy --- lib/vm/src/module.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/vm/src/module.rs b/lib/vm/src/module.rs index c81fdf831..e483d5839 100644 --- a/lib/vm/src/module.rs +++ b/lib/vm/src/module.rs @@ -155,7 +155,7 @@ impl ModuleInfo { .filter_map(|(_name, export_index)| match export_index { ExportIndex::Function(i) => { let signature = self.functions.get(*i).unwrap(); - let func_type = self.signatures.get(signature.clone()).unwrap(); + let func_type = self.signatures.get(*signature).unwrap(); Some(func_type.clone()) } _ => None, From 63815020d061e96e949789a8f6ae7ddceff35f05 Mon Sep 17 00:00:00 2001 From: Nick Lewycky Date: Thu, 8 Oct 2020 19:59:05 -0700 Subject: [PATCH 175/281] Use copy instead of clone. https://rust-lang.github.io/rust-clippy/master/index.html#clone_on_copy --- lib/vm/src/table.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/vm/src/table.rs b/lib/vm/src/table.rs index caf6864f9..23dde1098 100644 --- a/lib/vm/src/table.rs +++ b/lib/vm/src/table.rs @@ -143,7 +143,7 @@ impl LinearTable { TableStyle::CallerChecksSignature => Ok(Self { vec: Mutex::new(vec), maximum: table.maximum, - table: table.clone(), + table: *table, style: style.clone(), vm_table_definition: Box::new(UnsafeCell::new(VMTableDefinition { base: base as _, From cccdc210bead77e034c41612bc0c5305d8460d02 Mon Sep 17 00:00:00 2001 From: Nick Lewycky Date: Thu, 8 Oct 2020 20:02:34 -0700 Subject: [PATCH 176/281] Use implicit `self` type when possible. https://rust-lang.github.io/rust-clippy/master/index.html#needless_arbitrary_self_type --- lib/engine/src/artifact.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/engine/src/artifact.rs b/lib/engine/src/artifact.rs index 67211b057..f74fc4717 100644 --- a/lib/engine/src/artifact.rs +++ b/lib/engine/src/artifact.rs @@ -152,18 +152,18 @@ pub trait Artifact: Send + Sync + Upcastable { // Implementation of `Upcastable` taken from https://users.rust-lang.org/t/why-does-downcasting-not-work-for-subtraits/33286/7 . /// Trait needed to get downcasting from `WasiFile` to work. pub trait Upcastable { - fn upcast_any_ref(self: &'_ Self) -> &'_ dyn Any; - fn upcast_any_mut(self: &'_ mut Self) -> &'_ mut dyn Any; + fn upcast_any_ref(&'_ self) -> &'_ dyn Any; + fn upcast_any_mut(&'_ mut self) -> &'_ mut dyn Any; fn upcast_any_box(self: Box) -> Box; } impl Upcastable for T { #[inline] - fn upcast_any_ref(self: &'_ Self) -> &'_ dyn Any { + fn upcast_any_ref(&'_ self) -> &'_ dyn Any { self } #[inline] - fn upcast_any_mut(self: &'_ mut Self) -> &'_ mut dyn Any { + fn upcast_any_mut(&'_ mut self) -> &'_ mut dyn Any { self } #[inline] @@ -175,13 +175,13 @@ impl Upcastable for T { impl dyn Artifact + 'static { /// Try to downcast the artifact into a given type. #[inline] - pub fn downcast_ref(self: &'_ Self) -> Option<&'_ T> { + pub fn downcast_ref(&'_ self) -> Option<&'_ T> { self.upcast_any_ref().downcast_ref::() } /// Try to downcast the artifact into a given type mutably. #[inline] - pub fn downcast_mut(self: &'_ mut Self) -> Option<&'_ mut T> { + pub fn downcast_mut(&'_ mut self) -> Option<&'_ mut T> { self.upcast_any_mut().downcast_mut::() } } From a303a8e9e92352870db66d364ee8bbad2d4dc816 Mon Sep 17 00:00:00 2001 From: Nick Lewycky Date: Thu, 8 Oct 2020 20:04:04 -0700 Subject: [PATCH 177/281] Use copy instead of clone. https://rust-lang.github.io/rust-clippy/master/index.html#clone_on_copy --- lib/engine/src/resolver.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/engine/src/resolver.rs b/lib/engine/src/resolver.rs index b29d01661..82b5df625 100644 --- a/lib/engine/src/resolver.rs +++ b/lib/engine/src/resolver.rs @@ -104,8 +104,8 @@ fn get_extern_from_import(module: &ModuleInfo, import_index: &ImportIndex) -> Ex fn get_extern_from_export(_module: &ModuleInfo, export: &Export) -> ExternType { match export { Export::Function(ref f) => ExternType::Function(f.signature.clone()), - Export::Table(ref t) => ExternType::Table(t.ty().clone()), - Export::Memory(ref m) => ExternType::Memory(m.ty().clone()), + Export::Table(ref t) => ExternType::Table(*t.ty()), + Export::Memory(ref m) => ExternType::Memory(*m.ty()), Export::Global(ref g) => { let global = g.from.ty(); ExternType::Global(*global) From 388aeb3b1767d1180f787da737e7f70afe9571cc Mon Sep 17 00:00:00 2001 From: Nick Lewycky Date: Thu, 8 Oct 2020 20:08:08 -0700 Subject: [PATCH 178/281] NFC. Rewrite this using the matches! macro. https://rust-lang.github.io/rust-clippy/master/index.html#match_like_matches_macro --- lib/engine/src/serialize.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/lib/engine/src/serialize.rs b/lib/engine/src/serialize.rs index c5f1749a8..d501332c9 100644 --- a/lib/engine/src/serialize.rs +++ b/lib/engine/src/serialize.rs @@ -56,10 +56,7 @@ impl SerializableFunctionFrameInfo { /// Returns true if the extra function info is not yet /// processed pub fn is_unprocessed(&self) -> bool { - match self { - Self::Unprocessed(_) => true, - _ => false, - } + matches!(self, Self::Unprocessed(_)) } } From eed952e3227d909d919ec75b6f8173cc91604a26 Mon Sep 17 00:00:00 2001 From: Nick Lewycky Date: Thu, 8 Oct 2020 20:09:28 -0700 Subject: [PATCH 179/281] Use Self instead of the full name of the structure. https://rust-lang.github.io/rust-clippy/master/index.html#use_self --- lib/engine/src/trap/error.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/engine/src/trap/error.rs b/lib/engine/src/trap/error.rs index d4d68786c..c7811aa08 100644 --- a/lib/engine/src/trap/error.rs +++ b/lib/engine/src/trap/error.rs @@ -68,7 +68,7 @@ impl RuntimeError { let info = FRAME_INFO.read().unwrap(); match trap { Trap::User(error) => { - match error.downcast::() { + match error.downcast::() { // The error is already a RuntimeError, we return it directly Ok(runtime_error) => *runtime_error, Err(e) => Self::new_with_trace( From 6e9db4c475f852179c43737e9c28a0d31783bff9 Mon Sep 17 00:00:00 2001 From: Nick Lewycky Date: Thu, 8 Oct 2020 20:11:02 -0700 Subject: [PATCH 180/281] Use Self instead of the full name of the structure. https://rust-lang.github.io/rust-clippy/master/index.html#use_self --- lib/api/src/exports.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/api/src/exports.rs b/lib/api/src/exports.rs index f66eee3ff..c754ab819 100644 --- a/lib/api/src/exports.rs +++ b/lib/api/src/exports.rs @@ -51,7 +51,7 @@ impl Exports { /// Creates a new `Exports` with capacity `n`. pub fn with_capacity(n: usize) -> Self { - Exports { + Self { map: Arc::new(IndexMap::with_capacity(n)), } } @@ -224,7 +224,7 @@ where impl FromIterator<(String, Extern)> for Exports { fn from_iter>(iter: I) -> Self { // TODO: Move into IndexMap collect - let mut exports = Exports::new(); + let mut exports = Self::new(); for (name, extern_) in iter { exports.insert(name, extern_); } From f06dced6d11571582c6c0e4fca149dc2370a1951 Mon Sep 17 00:00:00 2001 From: Nick Lewycky Date: Thu, 8 Oct 2020 20:13:54 -0700 Subject: [PATCH 181/281] Fix unused import warning when "compiler" feature is not set. --- lib/engine-native/src/engine.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/engine-native/src/engine.rs b/lib/engine-native/src/engine.rs index 5e19af64e..5e3d5cf02 100644 --- a/lib/engine-native/src/engine.rs +++ b/lib/engine-native/src/engine.rs @@ -6,8 +6,8 @@ use std::path::Path; use std::sync::Arc; use std::sync::Mutex; #[cfg(feature = "compiler")] -use wasmer_compiler::Compiler; -use wasmer_compiler::{CompileError, Target, Triple}; +use wasmer_compiler::{Compiler, Triple}; +use wasmer_compiler::{CompileError, Target}; use wasmer_engine::{Artifact, DeserializeError, Engine, EngineId, Tunables}; #[cfg(feature = "compiler")] use wasmer_types::Features; From fdf70880db5c0178fd90fac55b2a1fff1e80419d Mon Sep 17 00:00:00 2001 From: Nick Lewycky Date: Thu, 8 Oct 2020 20:15:47 -0700 Subject: [PATCH 182/281] Use Self instead of the full name of the structure. https://rust-lang.github.io/rust-clippy/master/index.html#use_self --- lib/api/src/externals/global.rs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/lib/api/src/externals/global.rs b/lib/api/src/externals/global.rs index b922a854c..0733e60e0 100644 --- a/lib/api/src/externals/global.rs +++ b/lib/api/src/externals/global.rs @@ -23,17 +23,17 @@ pub struct Global { impl Global { /// Create a new `Global` with the initial value [`Val`]. - pub fn new(store: &Store, val: Val) -> Global { + pub fn new(store: &Store, val: Val) -> Self { Self::from_value(store, val, Mutability::Const).unwrap() } /// Create a mutable `Global` with the initial value [`Val`]. - pub fn new_mut(store: &Store, val: Val) -> Global { + pub fn new_mut(store: &Store, val: Val) -> Self { Self::from_value(store, val, Mutability::Var).unwrap() } /// Create a `Global` with the initial value [`Val`] and the provided [`Mutability`]. - fn from_value(store: &Store, val: Val, mutability: Mutability) -> Result { + fn from_value(store: &Store, val: Val, mutability: Mutability) -> Result { if !val.comes_from_same_store(store) { return Err(RuntimeError::new("cross-`Store` globals are not supported")); } @@ -47,7 +47,7 @@ impl Global { .map_err(|e| RuntimeError::new(format!("create global for {:?}: {}", val, e)))?; }; - Ok(Global { + Ok(Self { store: store.clone(), global: Arc::new(global), }) @@ -87,15 +87,15 @@ impl Global { Ok(()) } - pub(crate) fn from_export(store: &Store, wasmer_export: ExportGlobal) -> Global { - Global { + pub(crate) fn from_export(store: &Store, wasmer_export: ExportGlobal) -> Self { + Self { store: store.clone(), global: wasmer_export.from.clone(), } } /// Returns whether or not these two globals refer to the same data. - pub fn same(&self, other: &Global) -> bool { + pub fn same(&self, other: &Self) -> bool { Arc::ptr_eq(&self.global, &other.global) } } From b7b88ea680da68a036455b4e1470b09105d2f329 Mon Sep 17 00:00:00 2001 From: Nick Lewycky Date: Thu, 8 Oct 2020 20:25:17 -0700 Subject: [PATCH 183/281] Use slice operations instead of for loops to copy. https://rust-lang.github.io/rust-clippy/master/index.html#manual_memcpy --- lib/engine-object-file/src/artifact.rs | 24 +++++++++--------------- 1 file changed, 9 insertions(+), 15 deletions(-) diff --git a/lib/engine-object-file/src/artifact.rs b/lib/engine-object-file/src/artifact.rs index 72f158870..d48205ef2 100644 --- a/lib/engine-object-file/src/artifact.rs +++ b/lib/engine-object-file/src/artifact.rs @@ -298,6 +298,7 @@ impl ObjectFileArtifact { for i in 0..WORD_SIZE { byte_buffer[i] = bytes[cur_offset + i]; } + byte_buffer[0..WORD_SIZE].clone_from_slice(&bytes[cur_offset..(cur_offset + WORD_SIZE)]); cur_offset += WORD_SIZE; let num_finished_functions = usize::from_ne_bytes(byte_buffer); @@ -321,9 +322,8 @@ impl ObjectFileArtifact { sig_map.insert(sig_idx, vm_shared_idx); let mut sp = SlicePtr { ptr: 0, len: 0 }; - for j in 0..WORD_SIZE { - byte_buffer[j] = bytes[cur_offset + j]; - } + byte_buffer[0..WORD_SIZE] + .clone_from_slice(&bytes[cur_offset..(cur_offset + WORD_SIZE)]); sp.ptr = usize::from_ne_bytes(byte_buffer); cur_offset += WORD_SIZE; // TODO: we can read back the length here if we serialize it. This will improve debug output. @@ -342,15 +342,12 @@ impl ObjectFileArtifact { } // read trampolines in order - for i in 0..WORD_SIZE { - byte_buffer[i] = bytes[cur_offset + i]; - } + byte_buffer[0..WORD_SIZE].clone_from_slice(&bytes[cur_offset..(cur_offset + WORD_SIZE)]); cur_offset += WORD_SIZE; let num_function_trampolines = usize::from_ne_bytes(byte_buffer); for i in 0..num_function_trampolines { - for j in 0..WORD_SIZE { - byte_buffer[j] = bytes[cur_offset + j]; - } + byte_buffer[0..WORD_SIZE] + .clone_from_slice(&bytes[cur_offset..(cur_offset + WORD_SIZE)]); cur_offset += WORD_SIZE; let trampoline_ptr_bytes = usize::from_ne_bytes(byte_buffer); let trampoline = mem::transmute::(trampoline_ptr_bytes); @@ -363,16 +360,13 @@ impl ObjectFileArtifact { // read dynamic function trampolines in order now... let mut finished_dynamic_function_trampolines = PrimaryMap::new(); - for i in 0..WORD_SIZE { - byte_buffer[i] = bytes[cur_offset + i]; - } + byte_buffer[0..WORD_SIZE].clone_from_slice(&bytes[cur_offset..(cur_offset + WORD_SIZE)]); cur_offset += WORD_SIZE; let num_dynamic_trampoline_functions = usize::from_ne_bytes(byte_buffer); for _i in 0..num_dynamic_trampoline_functions { let mut sp = SlicePtr { ptr: 0, len: 0 }; - for j in 0..WORD_SIZE { - byte_buffer[j] = bytes[cur_offset + j]; - } + byte_buffer[0..WORD_SIZE] + .clone_from_slice(&bytes[cur_offset..(cur_offset + WORD_SIZE)]); sp.ptr = usize::from_ne_bytes(byte_buffer); cur_offset += WORD_SIZE; From 3aec7f74f2d66849f2a251eacba2c9de75022820 Mon Sep 17 00:00:00 2001 From: Nick Lewycky Date: Thu, 8 Oct 2020 20:26:47 -0700 Subject: [PATCH 184/281] Remove redundant clone, this is an Arc. https://rust-lang.github.io/rust-clippy/master/index.html#redundant_clone --- lib/api/src/externals/global.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/api/src/externals/global.rs b/lib/api/src/externals/global.rs index 0733e60e0..9cdfef3c1 100644 --- a/lib/api/src/externals/global.rs +++ b/lib/api/src/externals/global.rs @@ -90,7 +90,7 @@ impl Global { pub(crate) fn from_export(store: &Store, wasmer_export: ExportGlobal) -> Self { Self { store: store.clone(), - global: wasmer_export.from.clone(), + global: wasmer_export.from, } } From 437bbe139f24f385a913c2e98f22c80b4f42b288 Mon Sep 17 00:00:00 2001 From: Nick Lewycky Date: Thu, 8 Oct 2020 20:30:12 -0700 Subject: [PATCH 185/281] Use Self instead of the full name of the structure. https://rust-lang.github.io/rust-clippy/master/index.html#use_self --- lib/api/src/externals/memory.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/api/src/externals/memory.rs b/lib/api/src/externals/memory.rs index 765dd6bfd..6d8cd596f 100644 --- a/lib/api/src/externals/memory.rs +++ b/lib/api/src/externals/memory.rs @@ -34,12 +34,12 @@ impl Memory { /// This function will construct the `Memory` using the store [`Tunables`]. /// /// [`Tunables`]: crate::tunables::Tunables - pub fn new(store: &Store, ty: MemoryType) -> Result { + pub fn new(store: &Store, ty: MemoryType) -> Result { let tunables = store.tunables(); let style = tunables.memory_style(&ty); let memory = tunables.create_memory(&ty, &style)?; - Ok(Memory { + Ok(Self { store: store.clone(), memory, }) @@ -148,15 +148,15 @@ impl Memory { unsafe { MemoryView::new(base as _, length as u32) } } - pub(crate) fn from_export(store: &Store, wasmer_export: ExportMemory) -> Memory { - Memory { + pub(crate) fn from_export(store: &Store, wasmer_export: ExportMemory) -> Self { + Self { store: store.clone(), memory: wasmer_export.from, } } /// Returns whether or not these two globals refer to the same data. - pub fn same(&self, other: &Memory) -> bool { + pub fn same(&self, other: &Self) -> bool { Arc::ptr_eq(&self.memory, &other.memory) } } From 400006cc25419870d7a8a5ccdbab12063e8ee41f Mon Sep 17 00:00:00 2001 From: Nick Lewycky Date: Thu, 8 Oct 2020 20:31:15 -0700 Subject: [PATCH 186/281] Use Self instead of the full name of the structure. https://rust-lang.github.io/rust-clippy/master/index.html#use_self --- lib/api/src/externals/table.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/api/src/externals/table.rs b/lib/api/src/externals/table.rs index 3e5dd028d..7a56f326b 100644 --- a/lib/api/src/externals/table.rs +++ b/lib/api/src/externals/table.rs @@ -38,7 +38,7 @@ impl Table { /// This function will construct the `Table` using the store [`Tunables`]. /// /// [`Tunables`]: crate::tunables::Tunables - pub fn new(store: &Store, ty: TableType, init: Val) -> Result { + pub fn new(store: &Store, ty: TableType, init: Val) -> Result { let item = init.into_checked_anyfunc(store)?; let tunables = store.tunables(); let style = tunables.table_style(&ty); @@ -51,7 +51,7 @@ impl Table { set_table_item(table.as_ref(), i, item.clone())?; } - Ok(Table { + Ok(Self { store: store.clone(), table, }) @@ -117,9 +117,9 @@ impl Table { /// Returns an error if the range is out of bounds of either the source or /// destination tables. pub fn copy( - dst_table: &Table, + dst_table: &Self, dst_index: u32, - src_table: &Table, + src_table: &Self, src_index: u32, len: u32, ) -> Result<(), RuntimeError> { @@ -139,8 +139,8 @@ impl Table { Ok(()) } - pub(crate) fn from_export(store: &Store, wasmer_export: ExportTable) -> Table { - Table { + pub(crate) fn from_export(store: &Store, wasmer_export: ExportTable) -> Self { + Self { store: store.clone(), table: wasmer_export.from, } From 294496099e96203dbcae6548deac6232e0516439 Mon Sep 17 00:00:00 2001 From: Nick Lewycky Date: Thu, 8 Oct 2020 20:33:48 -0700 Subject: [PATCH 187/281] Use Self instead of the full name of the structure. https://rust-lang.github.io/rust-clippy/master/index.html#use_self --- lib/api/src/externals/mod.rs | 44 ++++++++++++++++++------------------ 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/lib/api/src/externals/mod.rs b/lib/api/src/externals/mod.rs index 8fdadf0a3..370a3173d 100644 --- a/lib/api/src/externals/mod.rs +++ b/lib/api/src/externals/mod.rs @@ -36,20 +36,20 @@ impl Extern { /// Return the undelying type of the inner `Extern`. pub fn ty(&self) -> ExternType { match self { - Extern::Function(ft) => ExternType::Function(ft.ty().clone()), - Extern::Memory(ft) => ExternType::Memory(*ft.ty()), - Extern::Table(tt) => ExternType::Table(*tt.ty()), - Extern::Global(gt) => ExternType::Global(*gt.ty()), + Self::Function(ft) => ExternType::Function(ft.ty().clone()), + Self::Memory(ft) => ExternType::Memory(*ft.ty()), + Self::Table(tt) => ExternType::Table(*tt.ty()), + Self::Global(gt) => ExternType::Global(*gt.ty()), } } /// Create an `Extern` from an `Export`. - pub fn from_export(store: &Store, export: Export) -> Extern { + pub fn from_export(store: &Store, export: Export) -> Self { match export { - Export::Function(f) => Extern::Function(Function::from_export(store, f)), - Export::Memory(m) => Extern::Memory(Memory::from_export(store, m)), - Export::Global(g) => Extern::Global(Global::from_export(store, g)), - Export::Table(t) => Extern::Table(Table::from_export(store, t)), + Export::Function(f) => Self::Function(Function::from_export(store, f)), + Export::Memory(m) => Self::Memory(Memory::from_export(store, m)), + Export::Global(g) => Self::Global(Global::from_export(store, g)), + Export::Table(t) => Self::Table(Table::from_export(store, t)), } } } @@ -57,14 +57,14 @@ impl Extern { impl<'a> Exportable<'a> for Extern { fn to_export(&self) -> Export { match self { - Extern::Function(f) => f.to_export(), - Extern::Global(g) => g.to_export(), - Extern::Memory(m) => m.to_export(), - Extern::Table(t) => t.to_export(), + Self::Function(f) => f.to_export(), + Self::Global(g) => g.to_export(), + Self::Memory(m) => m.to_export(), + Self::Table(t) => t.to_export(), } } - fn get_self_from_extern(_extern: &'a Extern) -> Result<&'a Self, ExportError> { + fn get_self_from_extern(_extern: &'a Self) -> Result<&'a Self, ExportError> { // Since this is already an extern, we can just return it. Ok(_extern) } @@ -73,10 +73,10 @@ impl<'a> Exportable<'a> for Extern { impl StoreObject for Extern { fn comes_from_same_store(&self, store: &Store) -> bool { let my_store = match self { - Extern::Function(f) => f.store(), - Extern::Global(g) => g.store(), - Extern::Memory(m) => m.store(), - Extern::Table(t) => t.store(), + Self::Function(f) => f.store(), + Self::Global(g) => g.store(), + Self::Memory(m) => m.store(), + Self::Table(t) => t.store(), }; Store::same(my_store, store) } @@ -99,24 +99,24 @@ impl fmt::Debug for Extern { impl From for Extern { fn from(r: Function) -> Self { - Extern::Function(r) + Self::Function(r) } } impl From for Extern { fn from(r: Global) -> Self { - Extern::Global(r) + Self::Global(r) } } impl From for Extern { fn from(r: Memory) -> Self { - Extern::Memory(r) + Self::Memory(r) } } impl From for Extern { fn from(r: Table) -> Self { - Extern::Table(r) + Self::Table(r) } } From ab53093fc624f35c6377923a1024fae01f47fd27 Mon Sep 17 00:00:00 2001 From: Nick Lewycky Date: Thu, 8 Oct 2020 20:35:00 -0700 Subject: [PATCH 188/281] Use Self instead of the full name of the structure. https://rust-lang.github.io/rust-clippy/master/index.html#use_self --- lib/api/src/instance.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/api/src/instance.rs b/lib/api/src/instance.rs index efb3bbdef..cac647fce 100644 --- a/lib/api/src/instance.rs +++ b/lib/api/src/instance.rs @@ -70,7 +70,7 @@ impl Instance { /// Those are, as defined by the spec: /// * Link errors that happen when plugging the imports into the instance /// * Runtime errors that happen when running the module `start` function. - pub fn new(module: &Module, resolver: &dyn Resolver) -> Result { + pub fn new(module: &Module, resolver: &dyn Resolver) -> Result { let store = module.store(); let handle = module.instantiate(resolver)?; @@ -85,7 +85,7 @@ impl Instance { }) .collect::(); - Ok(Instance { + Ok(Self { handle, module: module.clone(), exports, From 9acf25d246ac252001d453810be7ce4a39b333dd Mon Sep 17 00:00:00 2001 From: Nick Lewycky Date: Thu, 8 Oct 2020 20:36:17 -0700 Subject: [PATCH 189/281] Use Self instead of the full name of the structure. https://rust-lang.github.io/rust-clippy/master/index.html#use_self --- lib/api/src/module.rs | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/lib/api/src/module.rs b/lib/api/src/module.rs index bca259d6b..e18d8ac82 100644 --- a/lib/api/src/module.rs +++ b/lib/api/src/module.rs @@ -97,7 +97,7 @@ impl Module { /// # } /// ``` #[allow(unreachable_code)] - pub fn new(store: &Store, bytes: impl AsRef<[u8]>) -> Result { + pub fn new(store: &Store, bytes: impl AsRef<[u8]>) -> Result { #[cfg(feature = "wat")] let bytes = wat::parse_bytes(bytes.as_ref()).map_err(|e| { CompileError::Wasm(WasmError::Generic(format!( @@ -106,15 +106,15 @@ impl Module { ))) })?; - Module::from_binary(store, bytes.as_ref()) + Self::from_binary(store, bytes.as_ref()) } /// Creates a new WebAssembly module from a file path. - pub fn from_file(store: &Store, file: impl AsRef) -> Result { + pub fn from_file(store: &Store, file: impl AsRef) -> Result { let file_ref = file.as_ref(); let canonical = file_ref.canonicalize()?; let wasm_bytes = std::fs::read(file_ref)?; - let mut module = Module::new(store, &wasm_bytes)?; + let mut module = Self::new(store, &wasm_bytes)?; // Set the module name to the absolute path of the filename. // This is useful for debugging the stack traces. let filename = canonical.as_path().to_str().unwrap(); @@ -127,9 +127,9 @@ impl Module { /// Opposed to [`Module::new`], this function is not compatible with /// the WebAssembly text format (if the "wat" feature is enabled for /// this crate). - pub fn from_binary(store: &Store, binary: &[u8]) -> Result { - Module::validate(store, binary)?; - unsafe { Module::from_binary_unchecked(store, binary) } + pub fn from_binary(store: &Store, binary: &[u8]) -> Result { + Self::validate(store, binary)?; + unsafe { Self::from_binary_unchecked(store, binary) } } /// Creates a new WebAssembly module skipping any kind of validation. @@ -142,8 +142,8 @@ impl Module { pub unsafe fn from_binary_unchecked( store: &Store, binary: &[u8], - ) -> Result { - let module = Module::compile(store, binary)?; + ) -> Result { + let module = Self::compile(store, binary)?; Ok(module) } @@ -252,7 +252,7 @@ impl Module { } fn from_artifact(store: &Store, artifact: Arc) -> Self { - Module { + Self { store: store.clone(), artifact, } From cd494cb5cfe026d91c17830b467ab0656986abd4 Mon Sep 17 00:00:00 2001 From: Nick Lewycky Date: Thu, 8 Oct 2020 20:37:53 -0700 Subject: [PATCH 190/281] Use Self instead of the full name of the structure. https://rust-lang.github.io/rust-clippy/master/index.html#use_self --- lib/api/src/types.rs | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/lib/api/src/types.rs b/lib/api/src/types.rs index de27ede3e..b085f6a24 100644 --- a/lib/api/src/types.rs +++ b/lib/api/src/types.rs @@ -19,17 +19,17 @@ pub type Val = Value; impl StoreObject for Val { fn comes_from_same_store(&self, store: &Store) -> bool { match self { - Val::FuncRef(f) => Store::same(store, f.store()), - Val::ExternRef(ExternRef::Ref(_)) | Val::ExternRef(ExternRef::Other(_)) => false, - Val::ExternRef(ExternRef::Null) => true, - Val::I32(_) | Val::I64(_) | Val::F32(_) | Val::F64(_) | Val::V128(_) => true, + Self::FuncRef(f) => Store::same(store, f.store()), + Self::ExternRef(ExternRef::Ref(_)) | Self::ExternRef(ExternRef::Other(_)) => false, + Self::ExternRef(ExternRef::Null) => true, + Self::I32(_) | Self::I64(_) | Self::F32(_) | Self::F64(_) | Self::V128(_) => true, } } } impl From for Val { - fn from(val: Function) -> Val { - Val::FuncRef(val) + fn from(val: Function) -> Self { + Self::FuncRef(val) } } @@ -53,19 +53,19 @@ impl ValFuncRef for Val { return Err(RuntimeError::new("cross-`Store` values are not supported")); } Ok(match self { - Val::ExternRef(ExternRef::Null) => wasmer_vm::VMCallerCheckedAnyfunc { + Self::ExternRef(ExternRef::Null) => wasmer_vm::VMCallerCheckedAnyfunc { func_ptr: ptr::null(), type_index: wasmer_vm::VMSharedSignatureIndex::default(), vmctx: ptr::null_mut(), }, - Val::FuncRef(f) => f.checked_anyfunc(), + Self::FuncRef(f) => f.checked_anyfunc(), _ => return Err(RuntimeError::new("val is not funcref")), }) } - fn from_checked_anyfunc(item: wasmer_vm::VMCallerCheckedAnyfunc, store: &Store) -> Val { + fn from_checked_anyfunc(item: wasmer_vm::VMCallerCheckedAnyfunc, store: &Store) -> Self { if item.type_index == wasmer_vm::VMSharedSignatureIndex::default() { - return Val::ExternRef(ExternRef::Null); + return Self::ExternRef(ExternRef::Null); } let signature = store .engine() @@ -80,6 +80,6 @@ impl ValFuncRef for Val { vmctx: item.vmctx, }; let f = Function::from_export(store, export); - Val::FuncRef(f) + Self::FuncRef(f) } } From 882cf0e4d2a1b122db40e1c6c65326083bce04dd Mon Sep 17 00:00:00 2001 From: Nick Lewycky Date: Thu, 8 Oct 2020 20:40:58 -0700 Subject: [PATCH 191/281] Use implicit `self` type when possible. https://rust-lang.github.io/rust-clippy/master/index.html#needless_arbitrary_self_type --- lib/wasi/src/state/types.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/wasi/src/state/types.rs b/lib/wasi/src/state/types.rs index a524cf5b6..99b9cf093 100644 --- a/lib/wasi/src/state/types.rs +++ b/lib/wasi/src/state/types.rs @@ -215,18 +215,18 @@ pub trait WasiFile: fmt::Debug + Send + Write + Read + Seek + 'static + Upcastab // Implementation of `Upcastable` taken from https://users.rust-lang.org/t/why-does-downcasting-not-work-for-subtraits/33286/7 . /// Trait needed to get downcasting from `WasiFile` to work. pub trait Upcastable { - fn upcast_any_ref(self: &'_ Self) -> &'_ dyn Any; - fn upcast_any_mut(self: &'_ mut Self) -> &'_ mut dyn Any; + fn upcast_any_ref(&'_ self) -> &'_ dyn Any; + fn upcast_any_mut(&'_ mut self) -> &'_ mut dyn Any; fn upcast_any_box(self: Box) -> Box; } impl Upcastable for T { #[inline] - fn upcast_any_ref(self: &'_ Self) -> &'_ dyn Any { + fn upcast_any_ref(&'_ self) -> &'_ dyn Any { self } #[inline] - fn upcast_any_mut(self: &'_ mut Self) -> &'_ mut dyn Any { + fn upcast_any_mut(&'_ mut self) -> &'_ mut dyn Any { self } #[inline] @@ -237,11 +237,11 @@ impl Upcastable for T { impl dyn WasiFile + 'static { #[inline] - pub fn downcast_ref(self: &'_ Self) -> Option<&'_ T> { + pub fn downcast_ref(&'_ self) -> Option<&'_ T> { self.upcast_any_ref().downcast_ref::() } #[inline] - pub fn downcast_mut(self: &'_ mut Self) -> Option<&'_ mut T> { + pub fn downcast_mut(&'_ mut self) -> Option<&'_ mut T> { self.upcast_any_mut().downcast_mut::() } } From 379d8efc444ffce13a8ff6748c4c9ee397e2e698 Mon Sep 17 00:00:00 2001 From: Nick Lewycky Date: Thu, 8 Oct 2020 20:42:52 -0700 Subject: [PATCH 192/281] Remove redundant clone, this is a Cell. https://rust-lang.github.io/rust-clippy/master/index.html#redundant_clone --- lib/wasi/src/syscalls/legacy/snapshot0.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/wasi/src/syscalls/legacy/snapshot0.rs b/lib/wasi/src/syscalls/legacy/snapshot0.rs index f955b68b2..74bb0c36e 100644 --- a/lib/wasi/src/syscalls/legacy/snapshot0.rs +++ b/lib/wasi/src/syscalls/legacy/snapshot0.rs @@ -132,7 +132,7 @@ pub fn poll_oneoff( let memory = env.memory(); let mut in_origs: Vec = vec![]; for in_sub in wasi_try!(in_.deref(memory, 0, nsubscriptions)) { - in_origs.push(in_sub.get().clone()); + in_origs.push(in_sub.get()); } // get a pointer to the smaller new type From 39d87f4e516e00aaea20fd715fec69fd41f3c957 Mon Sep 17 00:00:00 2001 From: Nick Lewycky Date: Thu, 8 Oct 2020 20:56:36 -0700 Subject: [PATCH 193/281] Test whether a list is empty by looking at one value, no need for map + collect. https://rust-lang.github.io/rust-clippy/master/index.html#needless_collect --- lib/cli/src/commands/run.rs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/lib/cli/src/commands/run.rs b/lib/cli/src/commands/run.rs index 942977821..33180ceec 100644 --- a/lib/cli/src/commands/run.rs +++ b/lib/cli/src/commands/run.rs @@ -77,14 +77,10 @@ impl Run { logging::set_up_logging().unwrap(); } self.inner_execute().with_context(|| { - let compilers = CompilerType::enabled() - .iter() - .map(|c| c.to_string()) - .collect::>(); format!( "failed to run `{}`{}", self.path.display(), - if compilers.is_empty() { + if CompilerType::enabled().iter().next().is_none() { " (no compilers enabled)" } else { "" From 633310899f9270a6254d47ec2a2f8a8ca43b2ae2 Mon Sep 17 00:00:00 2001 From: Nick Lewycky Date: Thu, 8 Oct 2020 20:58:53 -0700 Subject: [PATCH 194/281] Remove redundant clones of string. https://rust-lang.github.io/rust-clippy/master/index.html#redundant_clone --- lib/cli/src/c_gen/object_file_header.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/cli/src/c_gen/object_file_header.rs b/lib/cli/src/c_gen/object_file_header.rs index 5ccb747c7..1c28e4c85 100644 --- a/lib/cli/src/c_gen/object_file_header.rs +++ b/lib/cli/src/c_gen/object_file_header.rs @@ -107,7 +107,7 @@ pub fn generate_header_file( symbol_registry.symbol_to_name(Symbol::LocalFunction(function_local_index)); // TODO: figure out the signature here too CStatement::Declaration { - name: function_name.clone(), + name: function_name, is_extern: false, is_const: false, ctype: CType::Function { @@ -142,7 +142,7 @@ pub fn generate_header_file( CStatement::Cast { target_type: CType::void_ptr(), expression: Box::new(CStatement::LiteralConstant { - value: function_name.clone(), + value: function_name, }), } }) @@ -170,7 +170,7 @@ pub fn generate_header_file( symbol_registry.symbol_to_name(Symbol::FunctionCallTrampoline(sig_index)); CStatement::Declaration { - name: function_name.clone(), + name: function_name, is_extern: false, is_const: false, ctype: CType::Function { From 03297ab9935b3ad771e2d254b47414c692c51866 Mon Sep 17 00:00:00 2001 From: Nick Lewycky Date: Thu, 8 Oct 2020 20:59:48 -0700 Subject: [PATCH 195/281] Use a non-looping push to push a single element. https://rust-lang.github.io/rust-clippy/master/index.html#single_char_push_str --- lib/cli/src/c_gen/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/cli/src/c_gen/mod.rs b/lib/cli/src/c_gen/mod.rs index d2248e3a2..d16340305 100644 --- a/lib/cli/src/c_gen/mod.rs +++ b/lib/cli/src/c_gen/mod.rs @@ -85,7 +85,7 @@ impl CType { w.push_str("const "); } inner.generate_c(w); - w.push_str("*"); + w.push('*'); } Self::U8 => { w.push_str("unsigned char"); From 3b3882f9f5f092c1f5c854678626338a7c12de9d Mon Sep 17 00:00:00 2001 From: Nick Lewycky Date: Thu, 8 Oct 2020 21:03:23 -0700 Subject: [PATCH 196/281] NFC. Remove redundant return. --- lib/cli/src/utils.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/cli/src/utils.rs b/lib/cli/src/utils.rs index 9dde684b2..dfc693e91 100644 --- a/lib/cli/src/utils.rs +++ b/lib/cli/src/utils.rs @@ -20,7 +20,7 @@ fn retrieve_alias_pathbuf(alias: &str, real_dir: &str) -> Result<(String, PathBu } else { bail!("Directory \"{}\" does not exist", &real_dir); } - return Ok((alias.to_string(), pb)); + Ok((alias.to_string(), pb)) } /// Parses a mapdir from a string From a01d3d3d702b6b96a8c47c7181a990e81629801b Mon Sep 17 00:00:00 2001 From: Nick Lewycky Date: Thu, 8 Oct 2020 21:03:51 -0700 Subject: [PATCH 197/281] cargo fmt --- lib/compiler-llvm/src/translator/abi.rs | 5 +---- lib/engine-native/src/engine.rs | 2 +- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/lib/compiler-llvm/src/translator/abi.rs b/lib/compiler-llvm/src/translator/abi.rs index 66343c758..6e26a026b 100644 --- a/lib/compiler-llvm/src/translator/abi.rs +++ b/lib/compiler-llvm/src/translator/abi.rs @@ -5,10 +5,7 @@ // // So far, this is an implementation of the SysV AMD64 ABI. -#![deny( - dead_code, - missing_docs, -)] +#![deny(dead_code, missing_docs)] use crate::translator::intrinsics::{type_to_llvm, Intrinsics}; use inkwell::{ diff --git a/lib/engine-native/src/engine.rs b/lib/engine-native/src/engine.rs index 5e3d5cf02..4950a19a8 100644 --- a/lib/engine-native/src/engine.rs +++ b/lib/engine-native/src/engine.rs @@ -5,9 +5,9 @@ use std::collections::HashMap; use std::path::Path; use std::sync::Arc; use std::sync::Mutex; +use wasmer_compiler::{CompileError, Target}; #[cfg(feature = "compiler")] use wasmer_compiler::{Compiler, Triple}; -use wasmer_compiler::{CompileError, Target}; use wasmer_engine::{Artifact, DeserializeError, Engine, EngineId, Tunables}; #[cfg(feature = "compiler")] use wasmer_types::Features; From fbad7ad25c7ff330a080666a9701199180607d5c Mon Sep 17 00:00:00 2001 From: Nick Lewycky Date: Thu, 8 Oct 2020 21:08:12 -0700 Subject: [PATCH 198/281] Running clippy again found two more improvements. Missed a manual memcpy loop in engine-object-file. CompilerType::enabled() is a Vec<>, so just use is_empty() instead of trying to generically determine whether an Iter is empty. --- lib/cli/src/commands/run.rs | 2 +- lib/engine-object-file/src/artifact.rs | 3 --- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/lib/cli/src/commands/run.rs b/lib/cli/src/commands/run.rs index 33180ceec..b3422d3ce 100644 --- a/lib/cli/src/commands/run.rs +++ b/lib/cli/src/commands/run.rs @@ -80,7 +80,7 @@ impl Run { format!( "failed to run `{}`{}", self.path.display(), - if CompilerType::enabled().iter().next().is_none() { + if CompilerType::enabled().is_empty() { " (no compilers enabled)" } else { "" diff --git a/lib/engine-object-file/src/artifact.rs b/lib/engine-object-file/src/artifact.rs index d48205ef2..2ba207659 100644 --- a/lib/engine-object-file/src/artifact.rs +++ b/lib/engine-object-file/src/artifact.rs @@ -295,9 +295,6 @@ impl ObjectFileArtifact { let mut byte_buffer = [0u8; WORD_SIZE]; let mut cur_offset = data_len + 10; - for i in 0..WORD_SIZE { - byte_buffer[i] = bytes[cur_offset + i]; - } byte_buffer[0..WORD_SIZE].clone_from_slice(&bytes[cur_offset..(cur_offset + WORD_SIZE)]); cur_offset += WORD_SIZE; From 18729709bf31eb3bce0a520730198dea826af62d Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Fri, 9 Oct 2020 14:37:07 +0200 Subject: [PATCH 199/281] feat(c-api) Update `wasm-c-api` repository. This change is important because `wasm.h` contains new functions, like `wasm_name_new_from_string_nt`, which are useful for the Go implementation. --- .../tests/wasm_c_api/wasm-c-api/README.md | 1 + .../wasm_c_api/wasm-c-api/example/callback.c | 33 +++++----- .../wasm_c_api/wasm-c-api/example/callback.cc | 11 ++-- .../wasm_c_api/wasm-c-api/example/finalize.c | 5 +- .../wasm_c_api/wasm-c-api/example/finalize.cc | 3 +- .../wasm_c_api/wasm-c-api/example/global.c | 52 ++++++++------- .../wasm_c_api/wasm-c-api/example/global.cc | 14 +++-- .../wasm_c_api/wasm-c-api/example/hello.c | 13 ++-- .../wasm_c_api/wasm-c-api/example/hello.cc | 8 ++- .../wasm_c_api/wasm-c-api/example/hostref.c | 63 ++++++++++--------- .../wasm_c_api/wasm-c-api/example/hostref.cc | 28 +++++---- .../wasm_c_api/wasm-c-api/example/memory.c | 59 +++++++++-------- .../wasm_c_api/wasm-c-api/example/memory.cc | 17 ++--- .../wasm_c_api/wasm-c-api/example/multi.c | 57 +++++++++-------- .../wasm_c_api/wasm-c-api/example/multi.cc | 10 +-- .../wasm_c_api/wasm-c-api/example/reflect.c | 6 +- .../wasm_c_api/wasm-c-api/example/reflect.cc | 3 +- .../wasm_c_api/wasm-c-api/example/serialize.c | 14 +++-- .../wasm-c-api/example/serialize.cc | 8 ++- .../wasm_c_api/wasm-c-api/example/start.c | 5 +- .../wasm_c_api/wasm-c-api/example/start.cc | 3 +- .../wasm_c_api/wasm-c-api/example/table.c | 33 +++++----- .../wasm_c_api/wasm-c-api/example/table.cc | 13 ++-- .../wasm_c_api/wasm-c-api/example/threads.c | 18 +++--- .../wasm_c_api/wasm-c-api/example/threads.cc | 7 ++- .../wasm_c_api/wasm-c-api/example/trap.c | 15 +++-- .../wasm_c_api/wasm-c-api/example/trap.cc | 10 +-- .../wasm_c_api/wasm-c-api/include/wasm.h | 29 +++++++-- .../wasm_c_api/wasm-c-api/include/wasm.hh | 24 ++++--- .../tests/wasm_c_api/wasm-c-api/src/wasm-c.cc | 35 +++++++---- .../wasm_c_api/wasm-c-api/src/wasm-v8.cc | 15 ++--- 31 files changed, 348 insertions(+), 264 deletions(-) diff --git a/lib/c-api/tests/wasm_c_api/wasm-c-api/README.md b/lib/c-api/tests/wasm_c_api/wasm-c-api/README.md index 6ba4799e8..1dbcbda97 100644 --- a/lib/c-api/tests/wasm_c_api/wasm-c-api/README.md +++ b/lib/c-api/tests/wasm_c_api/wasm-c-api/README.md @@ -94,6 +94,7 @@ Currently, known implementations of this API are included in * V8 natively (both C and C++) * Wabt (only C?) * Wasmtime (only C?) +* [Wasmer](https://github.com/wasmerio/wasmer/tree/master/lib/c-api) (only C, C++ coming soon) ### TODO diff --git a/lib/c-api/tests/wasm_c_api/wasm-c-api/example/callback.c b/lib/c-api/tests/wasm_c_api/wasm-c-api/example/callback.c index e17429bdd..2fddb1634 100644 --- a/lib/c-api/tests/wasm_c_api/wasm-c-api/example/callback.c +++ b/lib/c-api/tests/wasm_c_api/wasm-c-api/example/callback.c @@ -35,27 +35,27 @@ void wasm_val_print(wasm_val_t val) { // A function to be called from Wasm code. own wasm_trap_t* print_callback( - const wasm_val_t args[], wasm_val_t results[] + const wasm_val_vec_t* args, wasm_val_vec_t* results ) { printf("Calling back...\n> "); - wasm_val_print(args[0]); + wasm_val_print(args->data[0]); printf("\n"); - wasm_val_copy(&results[0], &args[0]); + wasm_val_copy(&results->data[0], &args->data[0]); return NULL; } // A function closure. own wasm_trap_t* closure_callback( - void* env, const wasm_val_t args[], wasm_val_t results[] + void* env, const wasm_val_vec_t* args, wasm_val_vec_t* results ) { int i = *(int*)env; printf("Calling back closure...\n"); printf("> %d\n", i); - results[0].kind = WASM_I32; - results[0].of.i32 = (int32_t)i; + results->data[0].kind = WASM_I32; + results->data[0].of.i32 = (int32_t)i; return NULL; } @@ -68,7 +68,7 @@ int main(int argc, const char* argv[]) { // Load binary. printf("Loading binary...\n"); - FILE* file = fopen("callback.wasm", "r"); + FILE* file = fopen("callback.wasm", "rb"); if (!file) { printf("> Error loading module!\n"); return 1; @@ -108,11 +108,12 @@ int main(int argc, const char* argv[]) { // Instantiate. printf("Instantiating module...\n"); - const wasm_extern_t* imports[] = { + wasm_extern_t* externs[] = { wasm_func_as_extern(print_func), wasm_func_as_extern(closure_func) }; + wasm_extern_vec_t imports = WASM_ARRAY_VEC(externs); own wasm_instance_t* instance = - wasm_instance_new(store, module, imports, NULL); + wasm_instance_new(store, module, &imports, NULL); if (!instance) { printf("> Error instantiating module!\n"); return 1; @@ -140,13 +141,11 @@ int main(int argc, const char* argv[]) { // Call. printf("Calling export...\n"); - wasm_val_t args[2]; - args[0].kind = WASM_I32; - args[0].of.i32 = 3; - args[1].kind = WASM_I32; - args[1].of.i32 = 4; - wasm_val_t results[1]; - if (wasm_func_call(run_func, args, results)) { + wasm_val_t as[2] = { WASM_I32_VAL(3), WASM_I32_VAL(4) }; + wasm_val_t rs[1] = { WASM_INIT_VAL }; + wasm_val_vec_t args = WASM_ARRAY_VEC(as); + wasm_val_vec_t results = WASM_ARRAY_VEC(rs); + if (wasm_func_call(run_func, &args, &results)) { printf("> Error calling function!\n"); return 1; } @@ -155,7 +154,7 @@ int main(int argc, const char* argv[]) { // Print result. printf("Printing result...\n"); - printf("> %u\n", results[0].of.i32); + printf("> %u\n", rs[0].of.i32); // Shut down. printf("Shutting down...\n"); diff --git a/lib/c-api/tests/wasm_c_api/wasm-c-api/example/callback.cc b/lib/c-api/tests/wasm_c_api/wasm-c-api/example/callback.cc index 41a388ca9..957629cab 100644 --- a/lib/c-api/tests/wasm_c_api/wasm-c-api/example/callback.cc +++ b/lib/c-api/tests/wasm_c_api/wasm-c-api/example/callback.cc @@ -35,7 +35,7 @@ auto operator<<(std::ostream& out, const wasm::Val& val) -> std::ostream& { // A function to be called from Wasm code. auto print_callback( - const wasm::Val args[], wasm::Val results[] + const wasm::vec& args, wasm::vec& results ) -> wasm::own { std::cout << "Calling back..." << std::endl << "> " << args[0] << std::endl; results[0] = args[0].copy(); @@ -45,7 +45,7 @@ auto print_callback( // A function closure. auto closure_callback( - void* env, const wasm::Val args[], wasm::Val results[] + void* env, const wasm::vec& args, wasm::vec& results ) -> wasm::own { auto i = *reinterpret_cast(env); std::cout << "Calling back closure..." << std::endl; @@ -103,7 +103,8 @@ void run() { // Instantiate. std::cout << "Instantiating module..." << std::endl; - wasm::Extern* imports[] = {print_func.get(), closure_func.get()}; + auto imports = wasm::vec::make( + print_func.get(), closure_func.get()); auto instance = wasm::Instance::make(store, module.get(), imports); if (!instance) { std::cout << "> Error instantiating module!" << std::endl; @@ -121,8 +122,8 @@ void run() { // Call. std::cout << "Calling export..." << std::endl; - wasm::Val args[] = {wasm::Val::i32(3), wasm::Val::i32(4)}; - wasm::Val results[1]; + auto args = wasm::vec::make(wasm::Val::i32(3), wasm::Val::i32(4)); + auto results = wasm::vec::make_uninitialized(1); if (run_func->call(args, results)) { std::cout << "> Error calling function!" << std::endl; exit(1); diff --git a/lib/c-api/tests/wasm_c_api/wasm-c-api/example/finalize.c b/lib/c-api/tests/wasm_c_api/wasm-c-api/example/finalize.c index 247368f28..502fc60b2 100644 --- a/lib/c-api/tests/wasm_c_api/wasm-c-api/example/finalize.c +++ b/lib/c-api/tests/wasm_c_api/wasm-c-api/example/finalize.c @@ -20,7 +20,7 @@ void finalize(void* data) { void run_in_store(wasm_store_t* store) { // Load binary. printf("Loading binary...\n"); - FILE* file = fopen("finalize.wasm", "r"); + FILE* file = fopen("finalize.wasm", "rb"); if (!file) { printf("> Error loading module!\n"); exit(1); @@ -50,8 +50,9 @@ void run_in_store(wasm_store_t* store) { printf("Instantiating modules...\n"); for (int i = 0; i <= iterations; ++i) { if (i % (iterations / 10) == 0) printf("%d\n", i); + wasm_extern_vec_t imports = WASM_EMPTY_VEC; own wasm_instance_t* instance = - wasm_instance_new(store, module, NULL, NULL); + wasm_instance_new(store, module, &imports, NULL); if (!instance) { printf("> Error instantiating module %d!\n", i); exit(1); diff --git a/lib/c-api/tests/wasm_c_api/wasm-c-api/example/finalize.cc b/lib/c-api/tests/wasm_c_api/wasm-c-api/example/finalize.cc index 64e134b8d..ce7e972bc 100644 --- a/lib/c-api/tests/wasm_c_api/wasm-c-api/example/finalize.cc +++ b/lib/c-api/tests/wasm_c_api/wasm-c-api/example/finalize.cc @@ -46,7 +46,8 @@ void run_in_store(wasm::Store* store) { std::cout << "Instantiating modules..." << std::endl; for (int i = 0; i <= iterations; ++i) { if (i % (iterations / 10) == 0) std::cout << i << std::endl; - auto instance = wasm::Instance::make(store, module.get(), nullptr); + auto imports = wasm::vec::make(); + auto instance = wasm::Instance::make(store, module.get(), imports); if (!instance) { std::cout << "> Error instantiating module " << i << "!" << std::endl; exit(1); diff --git a/lib/c-api/tests/wasm_c_api/wasm-c-api/example/global.c b/lib/c-api/tests/wasm_c_api/wasm-c-api/example/global.c index 5fe357cd4..5bd403369 100644 --- a/lib/c-api/tests/wasm_c_api/wasm-c-api/example/global.c +++ b/lib/c-api/tests/wasm_c_api/wasm-c-api/example/global.c @@ -39,9 +39,11 @@ wasm_func_t* get_export_func(const wasm_extern_vec_t* exports, size_t i) { #define check_call(func, type, expected) \ { \ - wasm_val_t results[1]; \ - wasm_func_call(func, NULL, results); \ - check(results[0], type, expected); \ + wasm_val_t vs[1]; \ + wasm_val_vec_t args = WASM_EMPTY_VEC; \ + wasm_val_vec_t results = WASM_ARRAY_VEC(vs); \ + wasm_func_call(func, &args, &results); \ + check(vs[0], type, expected); \ } @@ -53,7 +55,7 @@ int main(int argc, const char* argv[]) { // Load binary. printf("Loading binary...\n"); - FILE* file = fopen("global.wasm", "r"); + FILE* file = fopen("global.wasm", "rb"); if (!file) { printf("> Error loading module!\n"); return 1; @@ -90,16 +92,16 @@ int main(int argc, const char* argv[]) { own wasm_globaltype_t* var_i64_type = wasm_globaltype_new( wasm_valtype_new(WASM_I64), WASM_VAR); - wasm_val_t val_f32_1 = {.kind = WASM_F32, .of = {.f32 = 1}}; + wasm_val_t val_f32_1 = WASM_F32_VAL(1); own wasm_global_t* const_f32_import = wasm_global_new(store, const_f32_type, &val_f32_1); - wasm_val_t val_i64_2 = {.kind = WASM_I64, .of = {.i64 = 2}}; + wasm_val_t val_i64_2 = WASM_I64_VAL(2); own wasm_global_t* const_i64_import = wasm_global_new(store, const_i64_type, &val_i64_2); - wasm_val_t val_f32_3 = {.kind = WASM_F32, .of = {.f32 = 3}}; + wasm_val_t val_f32_3 = WASM_F32_VAL(3); own wasm_global_t* var_f32_import = wasm_global_new(store, var_f32_type, &val_f32_3); - wasm_val_t val_i64_4 = {.kind = WASM_I64, .of = {.i64 = 4}}; + wasm_val_t val_i64_4 = WASM_I64_VAL(4); own wasm_global_t* var_i64_import = wasm_global_new(store, var_i64_type, &val_i64_4); @@ -110,14 +112,15 @@ int main(int argc, const char* argv[]) { // Instantiate. printf("Instantiating module...\n"); - const wasm_extern_t* imports[] = { + wasm_extern_t* externs[] = { wasm_global_as_extern(const_f32_import), wasm_global_as_extern(const_i64_import), wasm_global_as_extern(var_f32_import), wasm_global_as_extern(var_i64_import) }; + wasm_extern_vec_t imports = WASM_ARRAY_VEC(externs); own wasm_instance_t* instance = - wasm_instance_new(store, module, imports, NULL); + wasm_instance_new(store, module, &imports, NULL); if (!instance) { printf("> Error instantiating module!\n"); return 1; @@ -175,13 +178,13 @@ int main(int argc, const char* argv[]) { check_call(get_var_i64_export, i64, 8); // Modify variables through API and check again. - wasm_val_t val33 = {.kind = WASM_F32, .of = {.f32 = 33}}; + wasm_val_t val33 = WASM_F32_VAL(33); wasm_global_set(var_f32_import, &val33); - wasm_val_t val34 = {.kind = WASM_I64, .of = {.i64 = 34}}; + wasm_val_t val34 = WASM_I64_VAL(34); wasm_global_set(var_i64_import, &val34); - wasm_val_t val37 = {.kind = WASM_F32, .of = {.f32 = 37}}; + wasm_val_t val37 = WASM_F32_VAL(37); wasm_global_set(var_f32_export, &val37); - wasm_val_t val38 = {.kind = WASM_I64, .of = {.i64 = 38}}; + wasm_val_t val38 = WASM_I64_VAL(38); wasm_global_set(var_i64_export, &val38); check_global(var_f32_import, f32, 33); @@ -195,14 +198,19 @@ int main(int argc, const char* argv[]) { check_call(get_var_i64_export, i64, 38); // Modify variables through calls and check again. - wasm_val_t args73[] = { {.kind = WASM_F32, .of = {.f32 = 73}} }; - wasm_func_call(set_var_f32_import, args73, NULL); - wasm_val_t args74[] = { {.kind = WASM_I64, .of = {.i64 = 74}} }; - wasm_func_call(set_var_i64_import, args74, NULL); - wasm_val_t args77[] = { {.kind = WASM_F32, .of = {.f32 = 77}} }; - wasm_func_call(set_var_f32_export, args77, NULL); - wasm_val_t args78[] = { {.kind = WASM_I64, .of = {.i64 = 78}} }; - wasm_func_call(set_var_i64_export, args78, NULL); + wasm_val_vec_t res = WASM_EMPTY_VEC; + wasm_val_t vs73[] = { WASM_F32_VAL(73) }; + wasm_val_vec_t args73 = WASM_ARRAY_VEC(vs73); + wasm_func_call(set_var_f32_import, &args73, &res); + wasm_val_t vs74[] = { WASM_I64_VAL(74) }; + wasm_val_vec_t args74 = WASM_ARRAY_VEC(vs74); + wasm_func_call(set_var_i64_import, &args74, &res); + wasm_val_t vs77[] = { WASM_F32_VAL(77) }; + wasm_val_vec_t args77 = WASM_ARRAY_VEC(vs77); + wasm_func_call(set_var_f32_export, &args77, &res); + wasm_val_t vs78[] = { WASM_I64_VAL(78) }; + wasm_val_vec_t args78 = WASM_ARRAY_VEC(vs78); + wasm_func_call(set_var_i64_export, &args78, &res); check_global(var_f32_import, f32, 73); check_global(var_i64_import, i64, 74); diff --git a/lib/c-api/tests/wasm_c_api/wasm-c-api/example/global.cc b/lib/c-api/tests/wasm_c_api/wasm-c-api/example/global.cc index efe90f05c..178eb61f8 100644 --- a/lib/c-api/tests/wasm_c_api/wasm-c-api/example/global.cc +++ b/lib/c-api/tests/wasm_c_api/wasm-c-api/example/global.cc @@ -32,8 +32,9 @@ void check(T actual, U expected) { } auto call(const wasm::Func* func) -> wasm::Val { - wasm::Val results[1]; - if (func->call(nullptr, results)) { + auto args = wasm::vec::make(); + auto results = wasm::vec::make_uninitialized(1); + if (func->call(args, results)) { std::cout << "> Error calling function!" << std::endl; exit(1); } @@ -41,8 +42,9 @@ auto call(const wasm::Func* func) -> wasm::Val { } void call(const wasm::Func* func, wasm::Val&& arg) { - wasm::Val args[1] = {std::move(arg)}; - if (func->call(args)) { + auto args = wasm::vec::make(std::move(arg)); + auto results = wasm::vec::make(); + if (func->call(args, results)) { std::cout << "> Error calling function!" << std::endl; exit(1); } @@ -95,10 +97,10 @@ void run() { // Instantiate. std::cout << "Instantiating module..." << std::endl; - wasm::Extern* imports[] = { + auto imports = wasm::vec::make( const_f32_import.get(), const_i64_import.get(), var_f32_import.get(), var_i64_import.get() - }; + ); auto instance = wasm::Instance::make(store, module.get(), imports); if (!instance) { std::cout << "> Error instantiating module!" << std::endl; diff --git a/lib/c-api/tests/wasm_c_api/wasm-c-api/example/hello.c b/lib/c-api/tests/wasm_c_api/wasm-c-api/example/hello.c index e4ef9837f..740f09969 100644 --- a/lib/c-api/tests/wasm_c_api/wasm-c-api/example/hello.c +++ b/lib/c-api/tests/wasm_c_api/wasm-c-api/example/hello.c @@ -9,7 +9,7 @@ // A function to be called from Wasm code. own wasm_trap_t* hello_callback( - const wasm_val_t args[], wasm_val_t results[] + const wasm_val_vec_t* args, wasm_val_vec_t* results ) { printf("Calling back...\n"); printf("> Hello World!\n"); @@ -25,7 +25,7 @@ int main(int argc, const char* argv[]) { // Load binary. printf("Loading binary...\n"); - FILE* file = fopen("hello.wasm", "r"); + FILE* file = fopen("hello.wasm", "rb"); if (!file) { printf("> Error loading module!\n"); return 1; @@ -61,9 +61,10 @@ int main(int argc, const char* argv[]) { // Instantiate. printf("Instantiating module...\n"); - const wasm_extern_t* imports[] = { wasm_func_as_extern(hello_func) }; + wasm_extern_t* externs[] = { wasm_func_as_extern(hello_func) }; + wasm_extern_vec_t imports = WASM_ARRAY_VEC(externs); own wasm_instance_t* instance = - wasm_instance_new(store, module, imports, NULL); + wasm_instance_new(store, module, &imports, NULL); if (!instance) { printf("> Error instantiating module!\n"); return 1; @@ -90,7 +91,9 @@ int main(int argc, const char* argv[]) { // Call. printf("Calling export...\n"); - if (wasm_func_call(run_func, NULL, NULL)) { + wasm_val_vec_t args = WASM_EMPTY_VEC; + wasm_val_vec_t results = WASM_EMPTY_VEC; + if (wasm_func_call(run_func, &args, &results)) { printf("> Error calling function!\n"); return 1; } diff --git a/lib/c-api/tests/wasm_c_api/wasm-c-api/example/hello.cc b/lib/c-api/tests/wasm_c_api/wasm-c-api/example/hello.cc index a6bbe28ac..94eb567b8 100644 --- a/lib/c-api/tests/wasm_c_api/wasm-c-api/example/hello.cc +++ b/lib/c-api/tests/wasm_c_api/wasm-c-api/example/hello.cc @@ -9,7 +9,7 @@ // A function to be called from Wasm code. auto hello_callback( - const wasm::Val args[], wasm::Val results[] + const wasm::vec& args, wasm::vec& results ) -> wasm::own { std::cout << "Calling back..." << std::endl; std::cout << "> Hello world!" << std::endl; @@ -55,7 +55,7 @@ void run() { // Instantiate. std::cout << "Instantiating module..." << std::endl; - wasm::Extern* imports[] = {hello_func.get()}; + auto imports = wasm::vec::make(hello_func.get()); auto instance = wasm::Instance::make(store, module.get(), imports); if (!instance) { std::cout << "> Error instantiating module!" << std::endl; @@ -73,7 +73,9 @@ void run() { // Call. std::cout << "Calling export..." << std::endl; - if (run_func->call()) { + auto args = wasm::vec::make(); + auto results = wasm::vec::make(); + if (run_func->call(args, results)) { std::cout << "> Error calling function!" << std::endl; exit(1); } diff --git a/lib/c-api/tests/wasm_c_api/wasm-c-api/example/hostref.c b/lib/c-api/tests/wasm_c_api/wasm-c-api/example/hostref.c index b70218e61..1e787ab19 100644 --- a/lib/c-api/tests/wasm_c_api/wasm-c-api/example/hostref.c +++ b/lib/c-api/tests/wasm_c_api/wasm-c-api/example/hostref.c @@ -10,12 +10,12 @@ // A function to be called from Wasm code. own wasm_trap_t* callback( - const wasm_val_t args[], wasm_val_t results[] + const wasm_val_vec_t* args, wasm_val_vec_t* results ) { printf("Calling back...\n> "); printf("> %p\n", - args[0].of.ref ? wasm_ref_get_host_info(args[0].of.ref) : NULL); - wasm_val_copy(&results[0], &args[0]); + args->data[0].of.ref ? wasm_ref_get_host_info(args->data[0].of.ref) : NULL); + wasm_val_copy(&results->data[0], &args->data[0]); return NULL; } @@ -47,21 +47,23 @@ wasm_table_t* get_export_table(const wasm_extern_vec_t* exports, size_t i) { own wasm_ref_t* call_v_r(const wasm_func_t* func) { printf("call_v_r... "); fflush(stdout); - wasm_val_t results[1]; - if (wasm_func_call(func, NULL, results)) { + wasm_val_t rs[] = { WASM_INIT_VAL }; + wasm_val_vec_t args = WASM_EMPTY_VEC; + wasm_val_vec_t results = WASM_ARRAY_VEC(rs); + if (wasm_func_call(func, &args, &results)) { printf("> Error calling function!\n"); exit(1); } printf("okay\n"); - return results[0].of.ref; + return rs[0].of.ref; } void call_r_v(const wasm_func_t* func, wasm_ref_t* ref) { printf("call_r_v... "); fflush(stdout); - wasm_val_t args[1]; - args[0].kind = WASM_ANYREF; - args[0].of.ref = ref; - if (wasm_func_call(func, args, NULL)) { + wasm_val_t vs[1] = { WASM_REF_VAL(ref) }; + wasm_val_vec_t args = WASM_ARRAY_VEC(vs); + wasm_val_vec_t results = WASM_EMPTY_VEC; + if (wasm_func_call(func, &args, &results)) { printf("> Error calling function!\n"); exit(1); } @@ -70,26 +72,24 @@ void call_r_v(const wasm_func_t* func, wasm_ref_t* ref) { own wasm_ref_t* call_r_r(const wasm_func_t* func, wasm_ref_t* ref) { printf("call_r_r... "); fflush(stdout); - wasm_val_t args[1]; - args[0].kind = WASM_ANYREF; - args[0].of.ref = ref; - wasm_val_t results[1]; - if (wasm_func_call(func, args, results)) { + wasm_val_t vs[1] = { WASM_REF_VAL(ref) }; + wasm_val_t rs[1] = { WASM_INIT_VAL }; + wasm_val_vec_t args = WASM_ARRAY_VEC(vs); + wasm_val_vec_t results = WASM_ARRAY_VEC(rs); + if (wasm_func_call(func, &args, &results)) { printf("> Error calling function!\n"); exit(1); } printf("okay\n"); - return results[0].of.ref; + return rs[0].of.ref; } void call_ir_v(const wasm_func_t* func, int32_t i, wasm_ref_t* ref) { printf("call_ir_v... "); fflush(stdout); - wasm_val_t args[2]; - args[0].kind = WASM_I32; - args[0].of.i32 = i; - args[1].kind = WASM_ANYREF; - args[1].of.ref = ref; - if (wasm_func_call(func, args, NULL)) { + wasm_val_t vs[2] = { WASM_I32_VAL(i), WASM_REF_VAL(ref) }; + wasm_val_vec_t args = WASM_ARRAY_VEC(vs); + wasm_val_vec_t results = WASM_EMPTY_VEC; + if (wasm_func_call(func, &args, &results)) { printf("> Error calling function!\n"); exit(1); } @@ -98,16 +98,16 @@ void call_ir_v(const wasm_func_t* func, int32_t i, wasm_ref_t* ref) { own wasm_ref_t* call_i_r(const wasm_func_t* func, int32_t i) { printf("call_i_r... "); fflush(stdout); - wasm_val_t args[1]; - args[0].kind = WASM_I32; - args[0].of.i32 = i; - wasm_val_t results[1]; - if (wasm_func_call(func, args, results)) { + wasm_val_t vs[1] = { WASM_I32_VAL(i) }; + wasm_val_t rs[1] = { WASM_INIT_VAL }; + wasm_val_vec_t args = WASM_ARRAY_VEC(vs); + wasm_val_vec_t results = WASM_ARRAY_VEC(rs); + if (wasm_func_call(func, &args, &results)) { printf("> Error calling function!\n"); exit(1); } printf("okay\n"); - return results[0].of.ref; + return rs[0].of.ref; } void check(own wasm_ref_t* actual, const wasm_ref_t* expected) { @@ -130,7 +130,7 @@ int main(int argc, const char* argv[]) { // Load binary. printf("Loading binary...\n"); - FILE* file = fopen("hostref.wasm", "r"); + FILE* file = fopen("hostref.wasm", "rb"); if (!file) { printf("> Error loading module!\n"); return 1; @@ -167,9 +167,10 @@ int main(int argc, const char* argv[]) { // Instantiate. printf("Instantiating module...\n"); - const wasm_extern_t* imports[] = { wasm_func_as_extern(callback_func) }; + wasm_extern_t* externs[] = { wasm_func_as_extern(callback_func) }; + wasm_extern_vec_t imports = WASM_ARRAY_VEC(externs); own wasm_instance_t* instance = - wasm_instance_new(store, module, imports, NULL); + wasm_instance_new(store, module, &imports, NULL); if (!instance) { printf("> Error instantiating module!\n"); return 1; diff --git a/lib/c-api/tests/wasm_c_api/wasm-c-api/example/hostref.cc b/lib/c-api/tests/wasm_c_api/wasm-c-api/example/hostref.cc index c94c8f596..09c239e0c 100644 --- a/lib/c-api/tests/wasm_c_api/wasm-c-api/example/hostref.cc +++ b/lib/c-api/tests/wasm_c_api/wasm-c-api/example/hostref.cc @@ -9,7 +9,7 @@ // A function to be called from Wasm code. auto callback( - const wasm::Val args[], wasm::Val results[] + const wasm::vec& args, wasm::vec& results ) -> wasm::own { std::cout << "Calling back..." << std::endl; std::cout << "> " << (args[0].ref() ? args[0].ref()->get_host_info() : nullptr) << std::endl; @@ -45,8 +45,9 @@ auto get_export_table(wasm::ownvec& exports, size_t i) -> wasm::Ta void call_r_v(const wasm::Func* func, const wasm::Ref* ref) { std::cout << "call_r_v... " << std::flush; - wasm::Val args[1] = {wasm::Val::ref(ref ? ref->copy() : wasm::own())}; - if (func->call(args, nullptr)) { + auto args = wasm::vec::make(wasm::Val::ref(ref ? ref->copy() : wasm::own())); + auto results = wasm::vec::make(); + if (func->call(args, results)) { std::cout << "> Error calling function!" << std::endl; exit(1); } @@ -55,8 +56,9 @@ void call_r_v(const wasm::Func* func, const wasm::Ref* ref) { auto call_v_r(const wasm::Func* func) -> wasm::own { std::cout << "call_v_r... " << std::flush; - wasm::Val results[1]; - if (func->call(nullptr, results)) { + auto args = wasm::vec::make(); + auto results = wasm::vec::make_uninitialized(1); + if (func->call(args, results)) { std::cout << "> Error calling function!" << std::endl; exit(1); } @@ -66,8 +68,8 @@ auto call_v_r(const wasm::Func* func) -> wasm::own { auto call_r_r(const wasm::Func* func, const wasm::Ref* ref) -> wasm::own { std::cout << "call_r_r... " << std::flush; - wasm::Val args[1] = {wasm::Val::ref(ref ? ref->copy() : wasm::own())}; - wasm::Val results[1]; + auto args = wasm::vec::make(wasm::Val::ref(ref ? ref->copy() : wasm::own())); + auto results = wasm::vec::make_uninitialized(1); if (func->call(args, results)) { std::cout << "> Error calling function!" << std::endl; exit(1); @@ -78,8 +80,10 @@ auto call_r_r(const wasm::Func* func, const wasm::Ref* ref) -> wasm::owncopy() : wasm::own())}; - if (func->call(args, nullptr)) { + auto args = wasm::vec::make( + wasm::Val::i32(i), wasm::Val::ref(ref ? ref->copy() : wasm::own())); + auto results = wasm::vec::make(); + if (func->call(args, results)) { std::cout << "> Error calling function!" << std::endl; exit(1); } @@ -88,8 +92,8 @@ void call_ir_v(const wasm::Func* func, int32_t i, const wasm::Ref* ref) { auto call_i_r(const wasm::Func* func, int32_t i) -> wasm::own { std::cout << "call_i_r... " << std::flush; - wasm::Val args[1] = {wasm::Val::i32(i)}; - wasm::Val results[1]; + auto args = wasm::vec::make(wasm::Val::i32(i)); + auto results = wasm::vec::make_uninitialized(1); if (func->call(args, results)) { std::cout << "> Error calling function!" << std::endl; exit(1); @@ -147,7 +151,7 @@ void run() { // Instantiate. std::cout << "Instantiating module..." << std::endl; - wasm::Extern* imports[] = {callback_func.get()}; + auto imports = wasm::vec::make(callback_func.get()); auto instance = wasm::Instance::make(store, module.get(), imports); if (!instance) { std::cout << "> Error instantiating module!" << std::endl; diff --git a/lib/c-api/tests/wasm_c_api/wasm-c-api/example/memory.c b/lib/c-api/tests/wasm_c_api/wasm-c-api/example/memory.c index af2b9414d..edd4ebadd 100644 --- a/lib/c-api/tests/wasm_c_api/wasm-c-api/example/memory.c +++ b/lib/c-api/tests/wasm_c_api/wasm-c-api/example/memory.c @@ -32,49 +32,49 @@ void check(bool success) { } } -void check_call(wasm_func_t* func, wasm_val_t args[], int32_t expected) { - wasm_val_t results[1]; - if (wasm_func_call(func, args, results) || results[0].of.i32 != expected) { +void check_call(wasm_func_t* func, int i, wasm_val_t args[], int32_t expected) { + wasm_val_t r = WASM_INIT_VAL; + wasm_val_vec_t args_ = {i, args}; + wasm_val_vec_t results = {1, &r}; + if (wasm_func_call(func, &args_, &results) || r.of.i32 != expected) { printf("> Error on result\n"); exit(1); } } void check_call0(wasm_func_t* func, int32_t expected) { - check_call(func, NULL, expected); + check_call(func, 0, NULL, expected); } void check_call1(wasm_func_t* func, int32_t arg, int32_t expected) { - wasm_val_t args[] = { {.kind = WASM_I32, .of = {.i32 = arg}} }; - check_call(func, args, expected); + wasm_val_t args[] = { WASM_I32_VAL(arg) }; + check_call(func, 1, args, expected); } void check_call2(wasm_func_t* func, int32_t arg1, int32_t arg2, int32_t expected) { - wasm_val_t args[2] = { - {.kind = WASM_I32, .of = {.i32 = arg1}}, - {.kind = WASM_I32, .of = {.i32 = arg2}} - }; - check_call(func, args, expected); + wasm_val_t args[] = { WASM_I32_VAL(arg1), WASM_I32_VAL(arg2) }; + check_call(func, 2, args, expected); } -void check_ok(wasm_func_t* func, wasm_val_t args[]) { - if (wasm_func_call(func, args, NULL)) { +void check_ok(wasm_func_t* func, int i, wasm_val_t args[]) { + wasm_val_vec_t args_ = {i, args}; + wasm_val_vec_t results = {0, NULL}; + if (wasm_func_call(func, &args_, &results)) { printf("> Error on result, expected empty\n"); exit(1); } } void check_ok2(wasm_func_t* func, int32_t arg1, int32_t arg2) { - wasm_val_t args[2] = { - {.kind = WASM_I32, .of = {.i32 = arg1}}, - {.kind = WASM_I32, .of = {.i32 = arg2}} - }; - check_ok(func, args); + wasm_val_t args[] = { WASM_I32_VAL(arg1), WASM_I32_VAL(arg2) }; + check_ok(func, 2, args); } -void check_trap(wasm_func_t* func, wasm_val_t args[]) { - wasm_val_t results[1]; - own wasm_trap_t* trap = wasm_func_call(func, args, results); +void check_trap(wasm_func_t* func, int i, wasm_val_t args[]) { + wasm_val_t r = WASM_INIT_VAL; + wasm_val_vec_t args_ = {i, args}; + wasm_val_vec_t results = {1, &r}; + own wasm_trap_t* trap = wasm_func_call(func, &args_, &results); if (! trap) { printf("> Error on result, expected trap\n"); exit(1); @@ -83,16 +83,13 @@ void check_trap(wasm_func_t* func, wasm_val_t args[]) { } void check_trap1(wasm_func_t* func, int32_t arg) { - wasm_val_t args[1] = { {.kind = WASM_I32, .of = {.i32 = arg}} }; - check_trap(func, args); + wasm_val_t args[] = { WASM_I32_VAL(arg) }; + check_trap(func, 1, args); } void check_trap2(wasm_func_t* func, int32_t arg1, int32_t arg2) { - wasm_val_t args[2] = { - {.kind = WASM_I32, .of = {.i32 = arg1}}, - {.kind = WASM_I32, .of = {.i32 = arg2}} - }; - check_trap(func, args); + wasm_val_t args[] = { WASM_I32_VAL(arg1), WASM_I32_VAL(arg2) }; + check_trap(func, 2, args); } @@ -104,7 +101,7 @@ int main(int argc, const char* argv[]) { // Load binary. printf("Loading binary...\n"); - FILE* file = fopen("memory.wasm", "r"); + FILE* file = fopen("memory.wasm", "rb"); if (!file) { printf("> Error loading module!\n"); return 1; @@ -132,7 +129,9 @@ int main(int argc, const char* argv[]) { // Instantiate. printf("Instantiating module...\n"); - own wasm_instance_t* instance = wasm_instance_new(store, module, NULL, NULL); + wasm_extern_vec_t imports = WASM_EMPTY_VEC; + own wasm_instance_t* instance = + wasm_instance_new(store, module, &imports, NULL); if (!instance) { printf("> Error instantiating module!\n"); return 1; diff --git a/lib/c-api/tests/wasm_c_api/wasm-c-api/example/memory.cc b/lib/c-api/tests/wasm_c_api/wasm-c-api/example/memory.cc index 4094accd8..6cc36192a 100644 --- a/lib/c-api/tests/wasm_c_api/wasm-c-api/example/memory.cc +++ b/lib/c-api/tests/wasm_c_api/wasm-c-api/example/memory.cc @@ -33,8 +33,9 @@ void check(T actual, U expected) { template void check_ok(const wasm::Func* func, Args... xs) { - wasm::Val args[] = {wasm::Val::i32(xs)...}; - if (func->call(args)) { + auto args = wasm::vec::make(wasm::Val::i32(xs)...); + auto results = wasm::vec::make(); + if (func->call(args, results)) { std::cout << "> Error on result, expected return" << std::endl; exit(1); } @@ -42,8 +43,9 @@ void check_ok(const wasm::Func* func, Args... xs) { template void check_trap(const wasm::Func* func, Args... xs) { - wasm::Val args[] = {wasm::Val::i32(xs)...}; - if (! func->call(args)) { + auto args = wasm::vec::make(wasm::Val::i32(xs)...); + auto results = wasm::vec::make(); + if (! func->call(args, results)) { std::cout << "> Error on result, expected trap" << std::endl; exit(1); } @@ -51,8 +53,8 @@ void check_trap(const wasm::Func* func, Args... xs) { template auto call(const wasm::Func* func, Args... xs) -> int32_t { - wasm::Val args[] = {wasm::Val::i32(xs)...}; - wasm::Val results[1]; + auto args = wasm::vec::make(wasm::Val::i32(xs)...); + auto results = wasm::vec::make_uninitialized(1); if (func->call(args, results)) { std::cout << "> Error on result, expected return" << std::endl; exit(1); @@ -92,7 +94,8 @@ void run() { // Instantiate. std::cout << "Instantiating module..." << std::endl; - auto instance = wasm::Instance::make(store, module.get(), nullptr); + auto imports = wasm::vec::make(); + auto instance = wasm::Instance::make(store, module.get(), imports); if (!instance) { std::cout << "> Error instantiating module!" << std::endl; exit(1); diff --git a/lib/c-api/tests/wasm_c_api/wasm-c-api/example/multi.c b/lib/c-api/tests/wasm_c_api/wasm-c-api/example/multi.c index 3859401c0..846c6ec92 100644 --- a/lib/c-api/tests/wasm_c_api/wasm-c-api/example/multi.c +++ b/lib/c-api/tests/wasm_c_api/wasm-c-api/example/multi.c @@ -9,31 +9,32 @@ // A function to be called from Wasm code. own wasm_trap_t* callback( - const wasm_val_t args[], wasm_val_t results[] + const wasm_val_vec_t* args, wasm_val_vec_t* results ) { printf("Calling back...\n> "); printf("> %"PRIu32" %"PRIu64" %"PRIu64" %"PRIu32"\n", - args[0].of.i32, args[1].of.i64, args[2].of.i64, args[3].of.i32); + args->data[0].of.i32, args->data[1].of.i64, + args->data[2].of.i64, args->data[3].of.i32); printf("\n"); - wasm_val_copy(&results[0], &args[3]); - wasm_val_copy(&results[1], &args[1]); - wasm_val_copy(&results[2], &args[2]); - wasm_val_copy(&results[3], &args[0]); + wasm_val_copy(&results->data[0], &args->data[3]); + wasm_val_copy(&results->data[1], &args->data[1]); + wasm_val_copy(&results->data[2], &args->data[2]); + wasm_val_copy(&results->data[3], &args->data[0]); return NULL; } // A function closure. own wasm_trap_t* closure_callback( - void* env, const wasm_val_t args[], wasm_val_t results[] + void* env, const wasm_val_vec_t* args, wasm_val_vec_t* results ) { int i = *(int*)env; printf("Calling back closure...\n"); printf("> %d\n", i); - results[0].kind = WASM_I32; - results[0].of.i32 = (int32_t)i; + results->data[0].kind = WASM_I32; + results->data[0].of.i32 = (int32_t)i; return NULL; } @@ -46,7 +47,7 @@ int main(int argc, const char* argv[]) { // Load binary. printf("Loading binary...\n"); - FILE* file = fopen("multi.wasm", "r"); + FILE* file = fopen("multi.wasm", "rb"); if (!file) { printf("> Error loading module!\n"); return 1; @@ -89,9 +90,10 @@ int main(int argc, const char* argv[]) { // Instantiate. printf("Instantiating module...\n"); - const wasm_extern_t* imports[] = {wasm_func_as_extern(callback_func)}; + wasm_extern_t* externs[] = { wasm_func_as_extern(callback_func) }; + wasm_extern_vec_t imports = WASM_ARRAY_VEC(externs); own wasm_instance_t* instance = - wasm_instance_new(store, module, imports, NULL); + wasm_instance_new(store, module, &imports, NULL); if (!instance) { printf("> Error instantiating module!\n"); return 1; @@ -118,17 +120,15 @@ int main(int argc, const char* argv[]) { // Call. printf("Calling export...\n"); - wasm_val_t args[4]; - args[0].kind = WASM_I32; - args[0].of.i32 = 1; - args[1].kind = WASM_I64; - args[1].of.i64 = 2; - args[2].kind = WASM_I64; - args[2].of.i64 = 3; - args[3].kind = WASM_I32; - args[3].of.i32 = 4; - wasm_val_t results[4]; - if (wasm_func_call(run_func, args, results)) { + wasm_val_t vals[4] = { + WASM_I32_VAL(1), WASM_I32_VAL(2), WASM_I32_VAL(3), WASM_I32_VAL(4) + }; + wasm_val_t res[4] = { + WASM_INIT_VAL, WASM_INIT_VAL, WASM_INIT_VAL, WASM_INIT_VAL + }; + wasm_val_vec_t args = WASM_ARRAY_VEC(vals); + wasm_val_vec_t results = WASM_ARRAY_VEC(res); + if (wasm_func_call(run_func, &args, &results)) { printf("> Error calling function!\n"); return 1; } @@ -138,13 +138,12 @@ int main(int argc, const char* argv[]) { // Print result. printf("Printing result...\n"); printf("> %"PRIu32" %"PRIu64" %"PRIu64" %"PRIu32"\n", - results[0].of.i32, results[1].of.i64, - results[2].of.i64, results[3].of.i32); + res[0].of.i32, res[1].of.i64, res[2].of.i64, res[3].of.i32); - assert(results[0].of.i32 == 4); - assert(results[1].of.i64 == 3); - assert(results[2].of.i64 == 2); - assert(results[3].of.i32 == 1); + assert(res[0].of.i32 == 4); + assert(res[1].of.i64 == 3); + assert(res[2].of.i64 == 2); + assert(res[3].of.i32 == 1); // Shut down. printf("Shutting down...\n"); diff --git a/lib/c-api/tests/wasm_c_api/wasm-c-api/example/multi.cc b/lib/c-api/tests/wasm_c_api/wasm-c-api/example/multi.cc index 8f7a555cd..6d0835571 100644 --- a/lib/c-api/tests/wasm_c_api/wasm-c-api/example/multi.cc +++ b/lib/c-api/tests/wasm_c_api/wasm-c-api/example/multi.cc @@ -8,7 +8,7 @@ // A function to be called from Wasm code. auto callback( - const wasm::Val args[], wasm::Val results[] + const wasm::vec& args, wasm::vec& results ) -> wasm::own { std::cout << "Calling back..." << std::endl; std::cout << "> " << args[0].i32(); @@ -66,7 +66,7 @@ void run() { // Instantiate. std::cout << "Instantiating module..." << std::endl; - wasm::Extern* imports[] = {callback_func.get()}; + auto imports = wasm::vec::make(callback_func.get()); auto instance = wasm::Instance::make(store, module.get(), imports); if (!instance) { std::cout << "> Error instantiating module!" << std::endl; @@ -84,10 +84,10 @@ void run() { // Call. std::cout << "Calling export..." << std::endl; - wasm::Val args[] = { + auto args = wasm::vec::make( wasm::Val::i32(1), wasm::Val::i64(2), wasm::Val::i64(3), wasm::Val::i32(4) - }; - wasm::Val results[4]; + ); + auto results = wasm::vec::make_uninitialized(4); if (wasm::own trap = run_func->call(args, results)) { std::cout << "> Error calling function! " << trap->message().get() << std::endl; exit(1); diff --git a/lib/c-api/tests/wasm_c_api/wasm-c-api/example/reflect.c b/lib/c-api/tests/wasm_c_api/wasm-c-api/example/reflect.c index 15e0165d1..d4383185f 100644 --- a/lib/c-api/tests/wasm_c_api/wasm-c-api/example/reflect.c +++ b/lib/c-api/tests/wasm_c_api/wasm-c-api/example/reflect.c @@ -90,7 +90,7 @@ int main(int argc, const char* argv[]) { // Load binary. printf("Loading binary...\n"); - FILE* file = fopen("reflect.wasm", "r"); + FILE* file = fopen("reflect.wasm", "rb"); if (!file) { printf("> Error loading module!\n"); return 1; @@ -118,7 +118,9 @@ int main(int argc, const char* argv[]) { // Instantiate. printf("Instantiating module...\n"); - own wasm_instance_t* instance = wasm_instance_new(store, module, NULL, NULL); + wasm_extern_vec_t imports = WASM_EMPTY_VEC; + own wasm_instance_t* instance = + wasm_instance_new(store, module, &imports, NULL); if (!instance) { printf("> Error instantiating module!\n"); return 1; diff --git a/lib/c-api/tests/wasm_c_api/wasm-c-api/example/reflect.cc b/lib/c-api/tests/wasm_c_api/wasm-c-api/example/reflect.cc index 704ae478f..9820d8143 100644 --- a/lib/c-api/tests/wasm_c_api/wasm-c-api/example/reflect.cc +++ b/lib/c-api/tests/wasm_c_api/wasm-c-api/example/reflect.cc @@ -101,7 +101,8 @@ void run() { // Instantiate. std::cout << "Instantiating module..." << std::endl; - auto instance = wasm::Instance::make(store, module.get(), nullptr); + auto imports = wasm::vec::make(); + auto instance = wasm::Instance::make(store, module.get(), imports); if (!instance) { std::cout << "> Error instantiating module!" << std::endl; exit(1); diff --git a/lib/c-api/tests/wasm_c_api/wasm-c-api/example/serialize.c b/lib/c-api/tests/wasm_c_api/wasm-c-api/example/serialize.c index 4522c00df..8ea1a379a 100644 --- a/lib/c-api/tests/wasm_c_api/wasm-c-api/example/serialize.c +++ b/lib/c-api/tests/wasm_c_api/wasm-c-api/example/serialize.c @@ -8,7 +8,9 @@ #define own // A function to be called from Wasm code. -own wasm_trap_t* hello_callback(const wasm_val_t args[], wasm_val_t results[]) { +own wasm_trap_t* hello_callback( + const wasm_val_vec_t* args, wasm_val_vec_t* results +) { printf("Calling back...\n"); printf("> Hello World!\n"); return NULL; @@ -23,7 +25,7 @@ int main(int argc, const char* argv[]) { // Load binary. printf("Loading binary...\n"); - FILE* file = fopen("serialize.wasm", "r"); + FILE* file = fopen("serialize.wasm", "rb"); if (!file) { printf("> Error loading module!\n"); return 1; @@ -76,9 +78,10 @@ int main(int argc, const char* argv[]) { // Instantiate. printf("Instantiating deserialized module...\n"); - const wasm_extern_t* imports[] = { wasm_func_as_extern(hello_func) }; + wasm_extern_t* externs[] = { wasm_func_as_extern(hello_func) }; + wasm_extern_vec_t imports = WASM_ARRAY_VEC(externs); own wasm_instance_t* instance = - wasm_instance_new(store, deserialized, imports, NULL); + wasm_instance_new(store, deserialized, &imports, NULL); if (!instance) { printf("> Error instantiating module!\n"); return 1; @@ -105,7 +108,8 @@ int main(int argc, const char* argv[]) { // Call. printf("Calling export...\n"); - if (wasm_func_call(run_func, NULL, NULL)) { + wasm_val_vec_t empty = WASM_EMPTY_VEC; + if (wasm_func_call(run_func, &empty, &empty)) { printf("> Error calling function!\n"); return 1; } diff --git a/lib/c-api/tests/wasm_c_api/wasm-c-api/example/serialize.cc b/lib/c-api/tests/wasm_c_api/wasm-c-api/example/serialize.cc index 3a059b5a1..f63baebf8 100644 --- a/lib/c-api/tests/wasm_c_api/wasm-c-api/example/serialize.cc +++ b/lib/c-api/tests/wasm_c_api/wasm-c-api/example/serialize.cc @@ -9,7 +9,7 @@ // A function to be called from Wasm code. auto hello_callback( - const wasm::Val args[], wasm::Val results[] + const wasm::vec& args, wasm::vec& results ) -> wasm::own { std::cout << "Calling back..." << std::endl; std::cout << "> Hello world!" << std::endl; @@ -67,7 +67,7 @@ void run() { // Instantiate. std::cout << "Instantiating deserialized module..." << std::endl; - wasm::Extern* imports[] = {hello_func.get()}; + auto imports = wasm::vec::make(hello_func.get()); auto instance = wasm::Instance::make(store, deserialized.get(), imports); if (!instance) { std::cout << "> Error instantiating module!" << std::endl; @@ -85,7 +85,9 @@ void run() { // Call. std::cout << "Calling export..." << std::endl; - if (run_func->call()) { + auto args = wasm::vec::make(); + auto results = wasm::vec::make(); + if (run_func->call(args, results)) { std::cout << "> Error calling function!" << std::endl; exit(1); } diff --git a/lib/c-api/tests/wasm_c_api/wasm-c-api/example/start.c b/lib/c-api/tests/wasm_c_api/wasm-c-api/example/start.c index 42fa31749..f60c03c64 100644 --- a/lib/c-api/tests/wasm_c_api/wasm-c-api/example/start.c +++ b/lib/c-api/tests/wasm_c_api/wasm-c-api/example/start.c @@ -26,7 +26,7 @@ int main(int argc, const char* argv[]) { // Load binary. printf("Loading binary...\n"); - FILE* file = fopen("start.wasm", "r"); + FILE* file = fopen("start.wasm", "rb"); if (!file) { printf("> Error loading module!\n"); return 1; @@ -54,9 +54,10 @@ int main(int argc, const char* argv[]) { // Instantiate. printf("Instantiating module...\n"); + wasm_extern_vec_t imports = WASM_EMPTY_VEC; own wasm_trap_t* trap = NULL; own wasm_instance_t* instance = - wasm_instance_new(store, module, NULL, &trap); + wasm_instance_new(store, module, &imports, &trap); if (instance || !trap) { printf("> Error instantiating module, expected trap!\n"); return 1; diff --git a/lib/c-api/tests/wasm_c_api/wasm-c-api/example/start.cc b/lib/c-api/tests/wasm_c_api/wasm-c-api/example/start.cc index 71d6fd25a..1643b9f77 100644 --- a/lib/c-api/tests/wasm_c_api/wasm-c-api/example/start.cc +++ b/lib/c-api/tests/wasm_c_api/wasm-c-api/example/start.cc @@ -47,7 +47,8 @@ void run() { // Instantiate. std::cout << "Instantiating module..." << std::endl; wasm::own trap; - auto instance = wasm::Instance::make(store, module.get(), nullptr, &trap); + auto imports = wasm::vec::make(); + auto instance = wasm::Instance::make(store, module.get(), imports, &trap); if (instance || !trap) { std::cout << "> Error instantiating module, expected trap!" << std::endl; exit(1); diff --git a/lib/c-api/tests/wasm_c_api/wasm-c-api/example/table.c b/lib/c-api/tests/wasm_c_api/wasm-c-api/example/table.c index 9b3beeb63..5e91a34a4 100644 --- a/lib/c-api/tests/wasm_c_api/wasm-c-api/example/table.c +++ b/lib/c-api/tests/wasm_c_api/wasm-c-api/example/table.c @@ -9,11 +9,11 @@ // A function to be called from Wasm code. own wasm_trap_t* neg_callback( - const wasm_val_t args[], wasm_val_t results[] + const wasm_val_vec_t* args, wasm_val_vec_t* results ) { printf("Calling back...\n"); - results[0].kind = WASM_I32; - results[0].of.i32 = -args[0].of.i32; + results->data[0].kind = WASM_I32; + results->data[0].of.i32 = -args->data[0].of.i32; return NULL; } @@ -49,23 +49,22 @@ void check_table(wasm_table_t* table, int32_t i, bool expect_set) { } void check_call(wasm_func_t* func, int32_t arg1, int32_t arg2, int32_t expected) { - wasm_val_t args[2] = { - {.kind = WASM_I32, .of = {.i32 = arg1}}, - {.kind = WASM_I32, .of = {.i32 = arg2}} - }; - wasm_val_t results[1]; - if (wasm_func_call(func, args, results) || results[0].of.i32 != expected) { + wasm_val_t vs[2] = { WASM_I32_VAL(arg1), WASM_I32_VAL(arg2) }; + wasm_val_t r[1] = { WASM_INIT_VAL }; + wasm_val_vec_t args = WASM_ARRAY_VEC(vs); + wasm_val_vec_t results = WASM_ARRAY_VEC(r); + if (wasm_func_call(func, &args, &results) || r[0].of.i32 != expected) { printf("> Error on result\n"); exit(1); } } void check_trap(wasm_func_t* func, int32_t arg1, int32_t arg2) { - wasm_val_t args[2] = { - {.kind = WASM_I32, .of = {.i32 = arg1}}, - {.kind = WASM_I32, .of = {.i32 = arg2}} - }; - own wasm_trap_t* trap = wasm_func_call(func, args, NULL); + wasm_val_t vs[2] = { WASM_I32_VAL(arg1), WASM_I32_VAL(arg2) }; + wasm_val_t r[1] = { WASM_INIT_VAL }; + wasm_val_vec_t args = WASM_ARRAY_VEC(vs); + wasm_val_vec_t results = WASM_ARRAY_VEC(r); + own wasm_trap_t* trap = wasm_func_call(func, &args, &results); if (! trap) { printf("> Error on result, expected trap\n"); exit(1); @@ -82,7 +81,7 @@ int main(int argc, const char* argv[]) { // Load binary. printf("Loading binary...\n"); - FILE* file = fopen("table.wasm", "r"); + FILE* file = fopen("table.wasm", "rb"); if (!file) { printf("> Error loading module!\n"); return 1; @@ -110,7 +109,9 @@ int main(int argc, const char* argv[]) { // Instantiate. printf("Instantiating module...\n"); - own wasm_instance_t* instance = wasm_instance_new(store, module, NULL, NULL); + wasm_extern_vec_t imports = WASM_EMPTY_VEC; + own wasm_instance_t* instance = + wasm_instance_new(store, module, &imports, NULL); if (!instance) { printf("> Error instantiating module!\n"); return 1; diff --git a/lib/c-api/tests/wasm_c_api/wasm-c-api/example/table.cc b/lib/c-api/tests/wasm_c_api/wasm-c-api/example/table.cc index 6890ae7e2..9ddf1d902 100644 --- a/lib/c-api/tests/wasm_c_api/wasm-c-api/example/table.cc +++ b/lib/c-api/tests/wasm_c_api/wasm-c-api/example/table.cc @@ -9,7 +9,7 @@ // A function to be called from Wasm code. auto neg_callback( - const wasm::Val args[], wasm::Val results[] + const wasm::vec& args, wasm::vec& results ) -> wasm::own { std::cout << "Calling back..." << std::endl; results[0] = wasm::Val(-args[0].i32()); @@ -51,8 +51,8 @@ void check(bool success) { auto call( const wasm::Func* func, wasm::Val&& arg1, wasm::Val&& arg2 ) -> wasm::Val { - wasm::Val args[2] = {std::move(arg1), std::move(arg2)}; - wasm::Val results[1]; + auto args = wasm::vec::make(std::move(arg1), std::move(arg2)); + auto results = wasm::vec::make_uninitialized(1); if (func->call(args, results)) { std::cout << "> Error on result, expected return" << std::endl; exit(1); @@ -61,8 +61,8 @@ auto call( } void check_trap(const wasm::Func* func, wasm::Val&& arg1, wasm::Val&& arg2) { - wasm::Val args[2] = {std::move(arg1), std::move(arg2)}; - wasm::Val results[1]; + auto args = wasm::vec::make(std::move(arg1), std::move(arg2)); + auto results = wasm::vec::make_uninitialized(1); if (! func->call(args, results)) { std::cout << "> Error on result, expected trap" << std::endl; exit(1); @@ -100,7 +100,8 @@ void run() { // Instantiate. std::cout << "Instantiating module..." << std::endl; - auto instance = wasm::Instance::make(store, module.get(), nullptr); + auto imports = wasm::vec::make(); + auto instance = wasm::Instance::make(store, module.get(), imports); if (!instance) { std::cout << "> Error instantiating module!" << std::endl; exit(1); diff --git a/lib/c-api/tests/wasm_c_api/wasm-c-api/example/threads.c b/lib/c-api/tests/wasm_c_api/wasm-c-api/example/threads.c index 9f9d5894a..d70bd1ae5 100644 --- a/lib/c-api/tests/wasm_c_api/wasm-c-api/example/threads.c +++ b/lib/c-api/tests/wasm_c_api/wasm-c-api/example/threads.c @@ -13,9 +13,9 @@ const int N_THREADS = 10; const int N_REPS = 3; // A function to be called from Wasm code. -own wasm_trap_t* callback(const wasm_val_t args[], wasm_val_t results[]) { - assert(args[0].kind == WASM_I32); - printf("> Thread %d running\n", args[0].of.i32); +own wasm_trap_t* callback(const wasm_val_vec_t* args, wasm_val_vec_t* results) { + assert(args->data[0].kind == WASM_I32); + printf("> Thread %d running\n", args->data[0].of.i32); return NULL; } @@ -42,18 +42,19 @@ void* run(void* args_abs) { own wasm_func_t* func = wasm_func_new(store, func_type, callback); wasm_functype_delete(func_type); - wasm_val_t val = {.kind = WASM_I32, .of = {.i32 = (int32_t)args->id}}; + wasm_val_t val = WASM_I32_VAL((int32_t)args->id); own wasm_globaltype_t* global_type = wasm_globaltype_new(wasm_valtype_new_i32(), WASM_CONST); own wasm_global_t* global = wasm_global_new(store, global_type, &val); wasm_globaltype_delete(global_type); // Instantiate. - const wasm_extern_t* imports[] = { + wasm_extern_t* externs[] = { wasm_func_as_extern(func), wasm_global_as_extern(global), }; + wasm_extern_vec_t imports = WASM_ARRAY_VEC(externs); own wasm_instance_t* instance = - wasm_instance_new(store, module, imports, NULL); + wasm_instance_new(store, module, &imports, NULL); if (!instance) { printf("> Error instantiating module!\n"); return NULL; @@ -78,7 +79,8 @@ void* run(void* args_abs) { wasm_instance_delete(instance); // Call. - if (wasm_func_call(run_func, NULL, NULL)) { + wasm_val_vec_t empty = WASM_EMPTY_VEC; + if (wasm_func_call(run_func, &empty, &empty)) { printf("> Error calling function!\n"); return NULL; } @@ -99,7 +101,7 @@ int main(int argc, const char *argv[]) { wasm_engine_t* engine = wasm_engine_new(); // Load binary. - FILE* file = fopen("threads.wasm", "r"); + FILE* file = fopen("threads.wasm", "rb"); if (!file) { printf("> Error loading module!\n"); return 1; diff --git a/lib/c-api/tests/wasm_c_api/wasm-c-api/example/threads.cc b/lib/c-api/tests/wasm_c_api/wasm-c-api/example/threads.cc index 6148be655..e130717a0 100644 --- a/lib/c-api/tests/wasm_c_api/wasm-c-api/example/threads.cc +++ b/lib/c-api/tests/wasm_c_api/wasm-c-api/example/threads.cc @@ -10,7 +10,7 @@ const int N_REPS = 3; // A function to be called from Wasm code. auto callback( - void* env, const wasm::Val args[], wasm::Val results[] + void* env, const wasm::vec& args, wasm::vec& results ) -> wasm::own { assert(args[0].kind() == wasm::ValKind::I32); std::lock_guard lock(*reinterpret_cast(env)); @@ -53,7 +53,7 @@ void run( store, global_type.get(), wasm::Val::i32(i)); // Instantiate. - wasm::Extern* imports[] = {func.get(), global.get()}; + auto imports = wasm::vec::make(func.get(), global.get()); auto instance = wasm::Instance::make(store, module.get(), imports); if (!instance) { std::lock_guard lock(*mutex); @@ -71,7 +71,8 @@ void run( auto run_func = exports[0]->func(); // Call. - run_func->call(); + auto empty = wasm::vec::make(); + run_func->call(empty, empty); } } diff --git a/lib/c-api/tests/wasm_c_api/wasm-c-api/example/trap.c b/lib/c-api/tests/wasm_c_api/wasm-c-api/example/trap.c index 975d6f859..1146f69e6 100644 --- a/lib/c-api/tests/wasm_c_api/wasm-c-api/example/trap.c +++ b/lib/c-api/tests/wasm_c_api/wasm-c-api/example/trap.c @@ -9,11 +9,11 @@ // A function to be called from Wasm code. own wasm_trap_t* fail_callback( - void* env, const wasm_val_t args[], wasm_val_t results[] + void* env, const wasm_val_vec_t* args, wasm_val_vec_t* results ) { printf("Calling back...\n"); own wasm_name_t message; - wasm_name_new_from_string(&message, "callback abort"); + wasm_name_new_from_string_nt(&message, "callback abort"); own wasm_trap_t* trap = wasm_trap_new((wasm_store_t*)env, &message); wasm_name_delete(&message); return trap; @@ -38,7 +38,7 @@ int main(int argc, const char* argv[]) { // Load binary. printf("Loading binary...\n"); - FILE* file = fopen("trap.wasm", "r"); + FILE* file = fopen("trap.wasm", "rb"); if (!file) { printf("> Error loading module!\n"); return 1; @@ -75,9 +75,10 @@ int main(int argc, const char* argv[]) { // Instantiate. printf("Instantiating module...\n"); - const wasm_extern_t* imports[] = { wasm_func_as_extern(fail_func) }; + wasm_extern_t* externs[] = { wasm_func_as_extern(fail_func) }; + wasm_extern_vec_t imports = WASM_ARRAY_VEC(externs); own wasm_instance_t* instance = - wasm_instance_new(store, module, imports, NULL); + wasm_instance_new(store, module, &imports, NULL); if (!instance) { printf("> Error instantiating module!\n"); return 1; @@ -106,7 +107,9 @@ int main(int argc, const char* argv[]) { } printf("Calling export %d...\n", i); - own wasm_trap_t* trap = wasm_func_call(func, NULL, NULL); + wasm_val_vec_t args = WASM_EMPTY_VEC; + wasm_val_vec_t results = WASM_EMPTY_VEC; + own wasm_trap_t* trap = wasm_func_call(func, &args, &results); if (!trap) { printf("> Error calling function, expected trap!\n"); return 1; diff --git a/lib/c-api/tests/wasm_c_api/wasm-c-api/example/trap.cc b/lib/c-api/tests/wasm_c_api/wasm-c-api/example/trap.cc index 9cfcf5016..2e70c76de 100644 --- a/lib/c-api/tests/wasm_c_api/wasm-c-api/example/trap.cc +++ b/lib/c-api/tests/wasm_c_api/wasm-c-api/example/trap.cc @@ -8,11 +8,11 @@ // A function to be called from Wasm code. auto fail_callback( - void* env, const wasm::Val args[], wasm::Val results[] + void* env, const wasm::vec& args, wasm::vec& results ) -> wasm::own { std::cout << "Calling back..." << std::endl; auto store = reinterpret_cast(env); - auto message = wasm::Name::make(std::string("callback abort")); + auto message = wasm::Name::make_nt(std::string("callback abort")); return wasm::Trap::make(store, message); } @@ -65,7 +65,7 @@ void run() { // Instantiate. std::cout << "Instantiating module..." << std::endl; - wasm::Extern* imports[] = {fail_func.get()}; + auto imports = wasm::vec::make(fail_func.get()); auto instance = wasm::Instance::make(store, module.get(), imports); if (!instance) { std::cout << "> Error instantiating module!" << std::endl; @@ -85,7 +85,9 @@ void run() { // Call. for (size_t i = 0; i < 2; ++i) { std::cout << "Calling export " << i << "..." << std::endl; - auto trap = exports[i]->func()->call(); + auto args = wasm::vec::make(); + auto results = wasm::vec::make(); + auto trap = exports[i]->func()->call(args, results); if (!trap) { std::cout << "> Error calling function, expected trap!" << std::endl; exit(1); diff --git a/lib/c-api/tests/wasm_c_api/wasm-c-api/include/wasm.h b/lib/c-api/tests/wasm_c_api/wasm-c-api/include/wasm.h index 46e75cacb..25e0453a3 100644 --- a/lib/c-api/tests/wasm_c_api/wasm-c-api/include/wasm.h +++ b/lib/c-api/tests/wasm_c_api/wasm-c-api/include/wasm.h @@ -105,7 +105,13 @@ typedef wasm_byte_vec_t wasm_name_t; #define wasm_name_delete wasm_byte_vec_delete static inline void wasm_name_new_from_string( - own wasm_name_t* out, const char* s + own wasm_name_t* out, own const char* s +) { + wasm_name_new(out, strlen(s), s); +} + +static inline void wasm_name_new_from_string_nt( + own wasm_name_t* out, own const char* s ) { wasm_name_new(out, strlen(s) + 1, s); } @@ -408,9 +414,9 @@ WASM_API_EXTERN own wasm_module_t* wasm_module_deserialize(wasm_store_t*, const WASM_DECLARE_REF(func) typedef own wasm_trap_t* (*wasm_func_callback_t)( - const wasm_val_t args[], wasm_val_t results[]); + const wasm_val_vec_t* args, own wasm_val_vec_t* results); typedef own wasm_trap_t* (*wasm_func_callback_with_env_t)( - void* env, const wasm_val_t args[], wasm_val_t results[]); + void* env, const wasm_val_vec_t* args, wasm_val_vec_t* results); WASM_API_EXTERN own wasm_func_t* wasm_func_new( wasm_store_t*, const wasm_functype_t*, wasm_func_callback_t); @@ -423,7 +429,7 @@ WASM_API_EXTERN size_t wasm_func_param_arity(const wasm_func_t*); WASM_API_EXTERN size_t wasm_func_result_arity(const wasm_func_t*); WASM_API_EXTERN own wasm_trap_t* wasm_func_call( - const wasm_func_t*, const wasm_val_t args[], wasm_val_t results[]); + const wasm_func_t*, const wasm_val_vec_t* args, wasm_val_vec_t* results); // Global Instances @@ -510,7 +516,7 @@ WASM_API_EXTERN const wasm_memory_t* wasm_extern_as_memory_const(const wasm_exte WASM_DECLARE_REF(instance) WASM_API_EXTERN own wasm_instance_t* wasm_instance_new( - wasm_store_t*, const wasm_module_t*, const wasm_extern_t* const imports[], + wasm_store_t*, const wasm_module_t*, const wasm_extern_vec_t* imports, own wasm_trap_t** ); @@ -520,6 +526,12 @@ WASM_API_EXTERN void wasm_instance_exports(const wasm_instance_t*, own wasm_exte /////////////////////////////////////////////////////////////////////////////// // Convenience +// Vectors + +#define WASM_EMPTY_VEC {0, NULL} +#define WASM_ARRAY_VEC(array) {sizeof(array)/sizeof(*(array)), array} + + // Value Type construction short-hands static inline own wasm_valtype_t* wasm_valtype_new_i32() { @@ -692,6 +704,13 @@ static inline void* wasm_val_ptr(const wasm_val_t* val) { #endif } +#define WASM_I32_VAL(i) {.kind = WASM_I32, .of = {.i32 = i}} +#define WASM_I64_VAL(i) {.kind = WASM_I64, .of = {.i64 = i}} +#define WASM_F32_VAL(z) {.kind = WASM_F32, .of = {.f32 = z}} +#define WASM_F64_VAL(z) {.kind = WASM_F64, .of = {.f64 = z}} +#define WASM_REF_VAL(r) {.kind = WASM_ANYREF, .of = {.ref = r}} +#define WASM_INIT_VAL {.kind = WASM_ANYREF, .of = {.ref = NULL}} + /////////////////////////////////////////////////////////////////////////////// diff --git a/lib/c-api/tests/wasm_c_api/wasm-c-api/include/wasm.hh b/lib/c-api/tests/wasm_c_api/wasm-c-api/include/wasm.hh index 29b3798e3..597c10f4d 100644 --- a/lib/c-api/tests/wasm_c_api/wasm-c-api/include/wasm.hh +++ b/lib/c-api/tests/wasm_c_api/wasm-c-api/include/wasm.hh @@ -146,6 +146,12 @@ public: } static auto make(std::string s) -> vec { + auto v = vec(s.length()); + if (v) std::strncpy(v.get(), s.data(), s.length()); + return v; + } + + static auto make_nt(std::string s) -> vec { auto v = vec(s.length() + 1); if (v) std::strcpy(v.get(), s.data()); return v; @@ -431,11 +437,11 @@ class Val { public: Val() : kind_(ValKind::ANYREF) { impl_.ref = nullptr; } - Val(int32_t i) : kind_(ValKind::I32) { impl_.i32 = i; } - Val(int64_t i) : kind_(ValKind::I64) { impl_.i64 = i; } - Val(float32_t z) : kind_(ValKind::F32) { impl_.f32 = z; } - Val(float64_t z) : kind_(ValKind::F64) { impl_.f64 = z; } - Val(own&& r) : kind_(ValKind::ANYREF) { impl_.ref = r.release(); } + explicit Val(int32_t i) : kind_(ValKind::I32) { impl_.i32 = i; } + explicit Val(int64_t i) : kind_(ValKind::I64) { impl_.i64 = i; } + explicit Val(float32_t z) : kind_(ValKind::F32) { impl_.f32 = z; } + explicit Val(float64_t z) : kind_(ValKind::F64) { impl_.f64 = z; } + explicit Val(own&& r) : kind_(ValKind::ANYREF) { impl_.ref = r.release(); } Val(Val&& that) : kind_(that.kind_), impl_(that.impl_) { if (is_ref()) that.impl_.ref = nullptr; @@ -648,8 +654,8 @@ public: Func() = delete; ~Func(); - using callback = auto (*)(const Val[], Val[]) -> own; - using callback_with_env = auto (*)(void*, const Val[], Val[]) -> own; + using callback = auto (*)(const vec&, vec&) -> own; + using callback_with_env = auto (*)(void*, const vec&, vec&) -> own; static auto make(Store*, const FuncType*, callback) -> own; static auto make(Store*, const FuncType*, callback_with_env, @@ -660,7 +666,7 @@ public: auto param_arity() const -> size_t; auto result_arity() const -> size_t; - auto call(const Val[] = nullptr, Val[] = nullptr) const -> own; + auto call(const vec&, vec&) const -> own; }; @@ -731,7 +737,7 @@ public: ~Instance(); static auto make( - Store*, const Module*, const Extern* const[], own* = nullptr + Store*, const Module*, const vec&, own* = nullptr ) -> own; auto copy() const -> own; diff --git a/lib/c-api/tests/wasm_c_api/wasm-c-api/src/wasm-c.cc b/lib/c-api/tests/wasm_c_api/wasm-c-api/src/wasm-c.cc index 982cc8071..b43161161 100644 --- a/lib/c-api/tests/wasm_c_api/wasm-c-api/src/wasm-c.cc +++ b/lib/c-api/tests/wasm_c_api/wasm-c-api/src/wasm-c.cc @@ -60,7 +60,7 @@ struct borrowed_vec { // Vectors -#define WASM_DEFINE_VEC_BASE(name, Name, vec, ptr_or_none) \ +#define WASM_DEFINE_VEC_BASE(name, Name, vec, plainvec, ptr_or_none) \ static_assert( \ sizeof(wasm_##name##_vec_t) == sizeof(vec), \ "C/C++ incompatibility" \ @@ -86,6 +86,14 @@ struct borrowed_vec { -> wasm_##name##_t ptr_or_none const* { \ return reinterpret_cast(v); \ } \ + extern "C++" inline auto reveal_##name##_vec(wasm_##name##_vec_t* v) \ + -> plainvec* { \ + return reinterpret_cast*>(v); \ + } \ + extern "C++" inline auto reveal_##name##_vec(const wasm_##name##_vec_t* v) \ + -> const plainvec* { \ + return reinterpret_cast*>(v); \ + } \ extern "C++" inline auto reveal_##name##_vec(wasm_##name##_t ptr_or_none* v) \ -> vec::elem_type* { \ return reinterpret_cast::elem_type*>(v); \ @@ -134,7 +142,7 @@ struct borrowed_vec { // Vectors with no ownership management of elements #define WASM_DEFINE_VEC_PLAIN(name, Name) \ - WASM_DEFINE_VEC_BASE(name, Name, vec, ) \ + WASM_DEFINE_VEC_BASE(name, Name, vec, vec, ) \ \ void wasm_##name##_vec_new( \ wasm_##name##_vec_t* out, \ @@ -156,7 +164,7 @@ struct borrowed_vec { // Vectors that own their elements #define WASM_DEFINE_VEC_OWN(name, Name) \ - WASM_DEFINE_VEC_BASE(name, Name, ownvec, *) \ + WASM_DEFINE_VEC_BASE(name, Name, ownvec, vec, *) \ \ void wasm_##name##_vec_new( \ wasm_##name##_vec_t* out, \ @@ -620,7 +628,7 @@ inline auto borrow_val(const wasm_val_t* v) -> borrowed_val { } // extern "C++" -WASM_DEFINE_VEC_BASE(val, Val, vec, ) +WASM_DEFINE_VEC_BASE(val, Val, vec, vec, ) void wasm_val_vec_new( wasm_val_vec_t* out, size_t size, wasm_val_t const data[] @@ -771,7 +779,9 @@ WASM_DEFINE_REF(func, Func) extern "C++" { -auto wasm_callback(void* env, const Val args[], Val results[]) -> own { +auto wasm_callback( + void* env, const vec& args, vec& results +) -> own { auto f = reinterpret_cast(env); return adopt_trap(f(hide_val_vec(args), hide_val_vec(results))); } @@ -783,7 +793,7 @@ struct wasm_callback_env_t { }; auto wasm_callback_with_env( - void* env, const Val args[], Val results[] + void* env, const vec& args, vec& results ) -> own { auto t = static_cast(env); return adopt_trap(t->callback(t->env, hide_val_vec(args), hide_val_vec(results))); @@ -826,9 +836,11 @@ size_t wasm_func_result_arity(const wasm_func_t* func) { } wasm_trap_t* wasm_func_call( - const wasm_func_t* func, const wasm_val_t args[], wasm_val_t results[] + const wasm_func_t* func, const wasm_val_vec_t* args, wasm_val_vec_t* results ) { - return release_trap(func->call(reveal_val_vec(args), reveal_val_vec(results))); + auto args_ = borrow_val_vec(args); + auto results_ = borrow_val_vec(results); + return release_trap(func->call(args_.it, results_.it)); } @@ -995,12 +1007,13 @@ WASM_DEFINE_REF(instance, Instance) wasm_instance_t* wasm_instance_new( wasm_store_t* store, const wasm_module_t* module, - const wasm_extern_t* const imports[], + const wasm_extern_vec_t* imports, wasm_trap_t** trap ) { own error; - auto instance = release_instance(Instance::make(store, module, - reinterpret_cast(imports), &error)); + auto imports_ = reveal_extern_vec(imports); + auto instance = + release_instance(Instance::make(store, module, *imports_, &error)); if (trap) *trap = hide_trap(error.release()); return instance; } diff --git a/lib/c-api/tests/wasm_c_api/wasm-c-api/src/wasm-v8.cc b/lib/c-api/tests/wasm_c_api/wasm-c-api/src/wasm-v8.cc index 75b9e6644..b58aaf40e 100644 --- a/lib/c-api/tests/wasm_c_api/wasm-c-api/src/wasm-v8.cc +++ b/lib/c-api/tests/wasm_c_api/wasm-c-api/src/wasm-v8.cc @@ -229,6 +229,7 @@ DEFINE_VEC(Global, ownvec, GLOBAL) DEFINE_VEC(Table, ownvec, TABLE) DEFINE_VEC(Memory, ownvec, MEMORY) DEFINE_VEC(Extern, ownvec, EXTERN) +DEFINE_VEC(Extern*, vec, EXTERN) DEFINE_VEC(Val, vec, VAL) #endif // #ifdef WASM_API_DEBUG @@ -1257,7 +1258,7 @@ auto Trap::message() const -> Message { auto message = v8::Exception::CreateMessage(isolate, impl(this)->v8_object()); v8::String::Utf8Value string(isolate, message->Get()); - return vec::make(std::string(*string)); + return vec::make_nt(std::string(*string)); } auto Trap::origin() const -> own { @@ -1687,7 +1688,7 @@ auto Func::result_arity() const -> size_t { return wasm_v8::func_type_result_arity(impl(this)->v8_object()); } -auto Func::call(const Val args[], Val results[]) const -> own { +auto Func::call(const vec& args, vec& results) const -> own { auto func = impl(this); auto store = func->store(); auto isolate = store->isolate(); @@ -1754,17 +1755,17 @@ void FuncData::v8_callback(const v8::FunctionCallbackInfo& info) { assert(param_types.size() == info.Length()); // TODO: cache params and result arrays per thread. - auto args = std::unique_ptr(new Val[param_types.size()]); - auto results = std::unique_ptr(new Val[result_types.size()]); + auto args = vec::make_uninitialized(param_types.size()); + auto results = vec::make_uninitialized(result_types.size()); for (size_t i = 0; i < param_types.size(); ++i) { args[i] = v8_to_val(store, info[i], param_types[i].get()); } own trap; if (self->kind == CALLBACK_WITH_ENV) { - trap = self->callback_with_env(self->env, args.get(), results.get()); + trap = self->callback_with_env(self->env, args, results); } else { - trap = self->callback(args.get(), results.get()); + trap = self->callback(args, results); } if (trap) { @@ -2019,7 +2020,7 @@ auto Instance::copy() const -> own { } auto Instance::make( - Store* store_abs, const Module* module_abs, const Extern* const imports[], + Store* store_abs, const Module* module_abs, const vec& imports, own* trap ) -> own { auto store = impl(store_abs); From 340419b7238588141ac434f561e9b979cc562b3c Mon Sep 17 00:00:00 2001 From: Syrus Akbary Date: Fri, 9 Oct 2020 09:24:11 -0700 Subject: [PATCH 200/281] Use Wasmer LLVM build (without tzinfo) for Linux --- .github/workflows/main.yaml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/main.yaml b/.github/workflows/main.yaml index a2e1d1bd0..9318e1094 100644 --- a/.github/workflows/main.yaml +++ b/.github/workflows/main.yaml @@ -43,7 +43,8 @@ jobs: - build: linux os: ubuntu-latest rust: 1.46.0 - llvm_url: 'https://github.com/llvm/llvm-project/releases/download/llvmorg-10.0.0/clang+llvm-10.0.0-x86_64-linux-gnu-ubuntu-18.04.tar.xz' + llvm_url: 'https://github.com/wasmerio/llvm-build/releases/download/10.x/Ubuntu1910_Release.tar.xz' + # llvm_url: 'https://github.com/llvm/llvm-project/releases/download/llvmorg-10.0.0/clang+llvm-10.0.0-x86_64-linux-gnu-ubuntu-18.04.tar.xz' artifact_name: 'wasmer-linux-amd64' run_integration_tests: true - build: macos From 8eb1816d798deb0623ade56f7b402bded5d708ce Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Fri, 9 Oct 2020 12:45:50 -0700 Subject: [PATCH 201/281] Add license field to engine-object-file crate --- lib/engine-object-file/Cargo.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/engine-object-file/Cargo.toml b/lib/engine-object-file/Cargo.toml index 0c9005a5f..e1e414903 100644 --- a/lib/engine-object-file/Cargo.toml +++ b/lib/engine-object-file/Cargo.toml @@ -6,6 +6,7 @@ description = "Wasmer Object File Engine" categories = ["wasm"] keywords = ["webassembly", "wasm"] repository = "https://github.com/wasmerio/wasmer" +license = "MIT" readme = "README.md" edition = "2018" From ba7b24f696228555603c1ac78da85b2d5bedc945 Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Fri, 9 Oct 2020 17:38:14 -0700 Subject: [PATCH 202/281] Add --dir and --mapdir support to native executable --- lib/c-api/build.rs | 2 + lib/c-api/src/wasm_c_api/wasi/mod.rs | 57 +++++ lib/c-api/wasmer_wasm.h | 8 + lib/cli/src/commands/wasmer_create_exe_main.c | 223 ++++++++++++------ tests/integration/cli/src/util.rs | 6 +- tests/integration/cli/tests/compile.rs | 2 +- tests/integration/cli/tests/create_exe.rs | 6 +- 7 files changed, 231 insertions(+), 73 deletions(-) diff --git a/lib/c-api/build.rs b/lib/c-api/build.rs index e78874382..f9f78ec10 100644 --- a/lib/c-api/build.rs +++ b/lib/c-api/build.rs @@ -357,6 +357,8 @@ fn exclude_items_from_wasm_c_api(builder: Builder) -> Builder { builder .exclude_item("wasi_config_arg") .exclude_item("wasi_config_env") + .exclude_item("wasi_config_mapdir") + .exclude_item("wasi_config_preopen_dir") .exclude_item("wasi_config_inherit_stderr") .exclude_item("wasi_config_inherit_stdin") .exclude_item("wasi_config_inherit_stdout") diff --git a/lib/c-api/src/wasm_c_api/wasi/mod.rs b/lib/c-api/src/wasm_c_api/wasi/mod.rs index cf0a08b73..fb0047c73 100644 --- a/lib/c-api/src/wasm_c_api/wasi/mod.rs +++ b/lib/c-api/src/wasm_c_api/wasi/mod.rs @@ -75,6 +75,63 @@ pub unsafe extern "C" fn wasi_config_arg(config: &mut wasi_config_t, arg: *const config.state_builder.arg(arg_bytes); } +#[no_mangle] +pub unsafe extern "C" fn wasi_config_preopen_dir( + config: &mut wasi_config_t, + dir: *const c_char, +) -> bool { + let dir_cstr = CStr::from_ptr(dir); + let dir_bytes = dir_cstr.to_bytes(); + let dir_str = match std::str::from_utf8(dir_bytes) { + Ok(dir_str) => dir_str, + Err(e) => { + update_last_error(e); + return false; + } + }; + + if let Err(e) = config.state_builder.preopen_dir(dir_str) { + update_last_error(e); + return false; + } + + true +} + +#[no_mangle] +pub unsafe extern "C" fn wasi_config_mapdir( + config: &mut wasi_config_t, + alias: *const c_char, + dir: *const c_char, +) -> bool { + let alias_cstr = CStr::from_ptr(alias); + let alias_bytes = alias_cstr.to_bytes(); + let alias_str = match std::str::from_utf8(alias_bytes) { + Ok(alias_str) => alias_str, + Err(e) => { + update_last_error(e); + return false; + } + }; + + let dir_cstr = CStr::from_ptr(dir); + let dir_bytes = dir_cstr.to_bytes(); + let dir_str = match std::str::from_utf8(dir_bytes) { + Ok(dir_str) => dir_str, + Err(e) => { + update_last_error(e); + return false; + } + }; + + if let Err(e) = config.state_builder.map_dir(alias_str, dir_str) { + update_last_error(e); + return false; + } + + true +} + #[no_mangle] pub extern "C" fn wasi_config_inherit_stdout(config: &mut wasi_config_t) { config.inherit_stdout = true; diff --git a/lib/c-api/wasmer_wasm.h b/lib/c-api/wasmer_wasm.h index b9eea99ae..e8f139ee8 100644 --- a/lib/c-api/wasmer_wasm.h +++ b/lib/c-api/wasmer_wasm.h @@ -101,10 +101,18 @@ void wasi_config_inherit_stdin(wasi_config_t *config); void wasi_config_inherit_stdout(wasi_config_t *config); #endif +#if defined(WASMER_WASI_ENABLED) +bool wasi_config_mapdir(wasi_config_t *config, const char *alias, const char *dir); +#endif + #if defined(WASMER_WASI_ENABLED) wasi_config_t *wasi_config_new(const char *program_name); #endif +#if defined(WASMER_WASI_ENABLED) +bool wasi_config_preopen_dir(wasi_config_t *config, const char *dir); +#endif + #if defined(WASMER_WASI_ENABLED) void wasi_env_delete(wasi_env_t *_state); #endif diff --git a/lib/cli/src/commands/wasmer_create_exe_main.c b/lib/cli/src/commands/wasmer_create_exe_main.c index ec00f9179..6b56c02fc 100644 --- a/lib/cli/src/commands/wasmer_create_exe_main.c +++ b/lib/cli/src/commands/wasmer_create_exe_main.c @@ -9,81 +9,166 @@ extern "C" { #include #include +// TODO: make this define templated so that the Rust code can toggle it on/off +#define WASI + #ifdef __cplusplus } #endif void print_wasmer_error() { - int error_len = wasmer_last_error_length(); - printf("Error len: `%d`\n", error_len); - char* error_str = (char*) malloc(error_len); - wasmer_last_error_message(error_str, error_len); - printf("Error str: `%s`\n", error_str); + int error_len = wasmer_last_error_length(); + printf("Error len: `%d`\n", error_len); + char* error_str = (char*) malloc(error_len); + wasmer_last_error_message(error_str, error_len); + printf("%s\n", error_str); } -int main() { - printf("Initializing...\n"); - wasm_config_t* config = wasm_config_new(); - wasm_config_set_engine(config, OBJECT_FILE); - wasm_engine_t* engine = wasm_engine_new_with_config(config); - wasm_store_t* store = wasm_store_new(engine); - - wasm_module_t* module = wasmer_object_file_engine_new(store, "qjs.wasm"); - if (! module) { - printf("Failed to create module\n"); - print_wasmer_error(); - return -1; - } - - // We have now finished the memory buffer book keeping and we have a valid Module. - - // In this example we're passing some JavaScript source code as a command line argument - // to a WASI module that can evaluate JavaScript. - wasi_config_t* wasi_config = wasi_config_new("constant_value_here"); - const char* js_string = "function greet(name) { return JSON.stringify('Hello, ' + name); }; print(greet('World'));"; - wasi_config_arg(wasi_config, "--eval"); - wasi_config_arg(wasi_config, js_string); - wasi_env_t* wasi_env = wasi_env_new(wasi_config); - if (!wasi_env) { - printf("> Error building WASI env!\n"); - print_wasmer_error(); - return 1; - } - - wasm_importtype_vec_t import_types; - wasm_module_imports(module, &import_types); - int num_imports = import_types.size; - wasm_extern_t** imports = (wasm_extern_t**) malloc(num_imports * sizeof(wasm_extern_t*)); - wasm_importtype_vec_delete(&import_types); - - bool get_imports_result = wasi_get_imports(store, module, wasi_env, imports); - if (!get_imports_result) { - printf("> Error getting WASI imports!\n"); - print_wasmer_error(); - return 1; - } - - wasm_instance_t* instance = wasm_instance_new(store, module, (const wasm_extern_t* const*) imports, NULL); - if (! instance) { - printf("Failed to create instance\n"); - print_wasmer_error(); - return -1; - } - wasi_env_set_instance(wasi_env, instance); - - // WASI is now set up. - - void* vmctx = wasm_instance_get_vmctx_ptr(instance); - wasm_val_t* inout[2] = { NULL, NULL }; - - fflush(stdout); - // We're able to call our compiled function directly through a trampoline. - wasmer_trampoline_function_call__1(vmctx, wasmer_function__1, &inout); - - wasm_instance_delete(instance); - wasm_module_delete(module); - wasm_store_delete(store); - wasm_engine_delete(engine); - return 0; +#ifdef WASI +int find_colon(char* string) { + int colon_location = 0; + for (int j = 0; j < strlen(string); ++j) { + if (string[j] == ':') { + colon_location = j; + break; + } + } + return colon_location; +} + +void pass_mapdir_arg(wasi_config_t* wasi_config, char* mapdir) { + int colon_location = find_colon(mapdir); + if (colon_location == 0) { + // error malformed argument + fprintf(stderr, "Expected mapdir argument of the form alias:directory\n"); + exit(-1); + } + // TODO: triple check for off by one errors + int dir_len = strlen(mapdir) - colon_location; + char* alias = (char*)malloc(colon_location); + char* dir = (char*)malloc(dir_len); + int j = 0; + for (j = 0; j < colon_location; ++j) { + alias[j] = mapdir[j]; + } + alias[j] = 0; + for (j = 0; j < dir_len; ++j) { + dir[j] = mapdir[j + colon_location]; + } + dir[j] = 0; + + wasi_config_mapdir(wasi_config, alias, dir); + free(alias); + free(dir); +} + +// We try to parse out `--dir` and `--mapdir` ahead of time and process those +// specially. All other arguments are passed to the guest program. +void handle_arguments(wasi_config_t* wasi_config, int argc, char* argv[]) { + for (int i = 1; i < argc; ++i) { + // We probably want special args like `--dir` and `--mapdir` to not be passed directly + if (strcmp(argv[i], "--dir") == 0) { + // next arg is a preopen directory + if ((i + 1) < argc ) { + i++; + wasi_config_preopen_dir(wasi_config, argv[i]); + } else { + fprintf(stderr, "--dir expects a following argument specifying which directory to preopen\n"); + exit(-1); + } + } + else if (strcmp(argv[i], "--mapdir") == 0) { + // next arg is a mapdir + if ((i + 1) < argc ) { + i++; + pass_mapdir_arg(wasi_config, argv[i]); + } else { + fprintf(stderr, "--mapdir expects a following argument specifying which directory to preopen in the form alias:directory\n"); + exit(-1); + } + } + else if (strncmp(argv[i], "--dir=", strlen("--dir=")) == 0 ) { + // this arg is a preopen dir + char* dir = argv[i] + strlen("--dir="); + wasi_config_preopen_dir(wasi_config, dir); + } + else if (strncmp(argv[i], "--mapdir=", strlen("--mapdir=")) == 0 ) { + // this arg is a mapdir + char* mapdir = argv[i] + strlen("--mapdir="); + pass_mapdir_arg(wasi_config, mapdir); + } + else { + // guest argument + wasi_config_arg(wasi_config, argv[i]); + } + } +} +#endif + +int main(int argc, char* argv[]) { + printf("Initializing...\n"); + wasm_config_t* config = wasm_config_new(); + wasm_config_set_engine(config, OBJECT_FILE); + wasm_engine_t* engine = wasm_engine_new_with_config(config); + wasm_store_t* store = wasm_store_new(engine); + + wasm_module_t* module = wasmer_object_file_engine_new(store, "qjs.wasm"); + if (! module) { + fprintf(stderr, "Failed to create module\n"); + print_wasmer_error(); + return -1; + } + + // We have now finished the memory buffer book keeping and we have a valid Module. + + #ifdef WASI + wasi_config_t* wasi_config = wasi_config_new(argv[0]); + handle_arguments(wasi_config, argc, argv); + + wasi_env_t* wasi_env = wasi_env_new(wasi_config); + if (!wasi_env) { + fprintf(stderr, "Error building WASI env!\n"); + print_wasmer_error(); + return 1; + } + #endif + + wasm_importtype_vec_t import_types; + wasm_module_imports(module, &import_types); + int num_imports = import_types.size; + wasm_extern_t** imports = (wasm_extern_t**) malloc(num_imports * sizeof(wasm_extern_t*)); + wasm_importtype_vec_delete(&import_types); + + #ifdef WASI + bool get_imports_result = wasi_get_imports(store, module, wasi_env, imports); + if (!get_imports_result) { + fprintf(stderr, "Error getting WASI imports!\n"); + print_wasmer_error(); + return 1; + } + #endif + + wasm_instance_t* instance = wasm_instance_new(store, module, (const wasm_extern_t* const*) imports, NULL); + if (! instance) { + fprintf(stderr, "Failed to create instance\n"); + print_wasmer_error(); + return -1; + } + + #ifdef WASI + wasi_env_set_instance(wasi_env, instance); + #endif + + void* vmctx = wasm_instance_get_vmctx_ptr(instance); + wasm_val_t* inout[2] = { NULL, NULL }; + + // We're able to call our compiled function directly through a trampoline. + wasmer_trampoline_function_call__1(vmctx, wasmer_function__1, &inout); + + wasm_instance_delete(instance); + wasm_module_delete(module); + wasm_store_delete(store); + wasm_engine_delete(engine); + return 0; } diff --git a/tests/integration/cli/src/util.rs b/tests/integration/cli/src/util.rs index 0e4864a67..8cfcaae20 100644 --- a/tests/integration/cli/src/util.rs +++ b/tests/integration/cli/src/util.rs @@ -36,8 +36,10 @@ impl Engine { } } -pub fn run_code(executable_path: &Path) -> anyhow::Result { - let output = Command::new(executable_path.canonicalize()?).output()?; +pub fn run_code(executable_path: &Path, args: &[String]) -> anyhow::Result { + let output = Command::new(executable_path.canonicalize()?) + .args(args) + .output()?; if !output.status.success() { bail!( diff --git a/tests/integration/cli/tests/compile.rs b/tests/integration/cli/tests/compile.rs index ff9a7ec68..fcbedc938 100644 --- a/tests/integration/cli/tests/compile.rs +++ b/tests/integration/cli/tests/compile.rs @@ -153,7 +153,7 @@ fn object_file_engine_works() -> anyhow::Result<()> { .run() .context("Failed to link objects together")?; - let result = run_code(&executable_path).context("Failed to run generated executable")?; + let result = run_code(&executable_path, &[]).context("Failed to run generated executable")?; let result_lines = result.lines().collect::>(); assert_eq!(result_lines, vec!["Initializing...", "\"Hello, World\""],); diff --git a/tests/integration/cli/tests/create_exe.rs b/tests/integration/cli/tests/create_exe.rs index d2f50a6a9..2af9e390f 100644 --- a/tests/integration/cli/tests/create_exe.rs +++ b/tests/integration/cli/tests/create_exe.rs @@ -83,7 +83,11 @@ fn create_exe_works() -> anyhow::Result<()> { .run() .context("Failed to create-exe wasm with Wasmer")?; - let result = run_code(&executable_path).context("Failed to run generated executable")?; + let result = run_code( + &executable_path, + &["--eval".to_string(), "function greet(name) { return JSON.stringify('Hello, ' + name); }; print(greet('World'));".to_string()], + ) + .context("Failed to run generated executable")?; let result_lines = result.lines().collect::>(); assert_eq!(result_lines, vec!["Initializing...", "\"Hello, World\""],); From 309d1b671624b916ed4dde8762bbdf02515c68f3 Mon Sep 17 00:00:00 2001 From: Simon Warta Date: Thu, 10 Sep 2020 12:23:51 +0200 Subject: [PATCH 203/281] Add i32/i64 converters from unsigned ints --- lib/wasmer-types/src/values.rs | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/lib/wasmer-types/src/values.rs b/lib/wasmer-types/src/values.rs index 98389d3c1..3e774bb5d 100644 --- a/lib/wasmer-types/src/values.rs +++ b/lib/wasmer-types/src/values.rs @@ -8,10 +8,14 @@ use crate::types::Type; /// produce. #[derive(Clone, PartialEq)] pub enum Value { - /// A 32-bit integer + /// A 32-bit integer. + /// + /// In Wasm integers are sign-agnostic, i.e. this can either be signed or unsigned. I32(i32), - /// A 64-bit integer + /// A 64-bit integer. + /// + /// In Wasm integers are sign-agnostic, i.e. this can either be signed or unsigned. I64(i64), /// A 32-bit float. @@ -175,12 +179,26 @@ impl From for Value { } } +impl From for Value { + fn from(val: u32) -> Self { + // In Wasm integers are sign-agnostic, so i32 is basically a 4 byte storage we can use for signed or unsigned 32-bit integers. + Self::I32(val as i32) + } +} + impl From for Value { fn from(val: i64) -> Self { Self::I64(val) } } +impl From for Value { + fn from(val: u64) -> Self { + // In Wasm integers are sign-agnostic, so i64 is basically an 8 byte storage we can use for signed or unsigned 64-bit integers. + Self::I64(val as i64) + } +} + impl From for Value { fn from(val: f32) -> Self { Self::F32(val) From 209dbedf66a1577174f957d4099a044dfea5625e Mon Sep 17 00:00:00 2001 From: Simon Warta Date: Wed, 16 Sep 2020 08:23:18 +0200 Subject: [PATCH 204/281] Add unit tests for Value from u32/u64 --- lib/wasmer-types/src/values.rs | 75 ++++++++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) diff --git a/lib/wasmer-types/src/values.rs b/lib/wasmer-types/src/values.rs index 3e774bb5d..4f37a7128 100644 --- a/lib/wasmer-types/src/values.rs +++ b/lib/wasmer-types/src/values.rs @@ -222,3 +222,78 @@ impl From for Value { // Self::FuncRef(val) // } // } + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_value_i32_from_u32() { + let input: u32 = 0x00000000; + let value = Value::<()>::from(input); + let mut out: i128 = 0; + unsafe { + value.write_value_to(&mut out as *mut i128); + } + assert_eq!(out, 0x00000000); + + let input: u32 = 0x00000001; + let value = Value::<()>::from(input); + let mut out: i128 = 0; + unsafe { + value.write_value_to(&mut out as *mut i128); + } + assert_eq!(out, 0x00000001); + + let input: u32 = 0xaabbccdd; + let value = Value::<()>::from(input); + let mut out: i128 = 0; + unsafe { + value.write_value_to(&mut out as *mut i128); + } + assert_eq!(out, 0xaabbccdd); + + let input: u32 = 0xffffffff; + let value = Value::<()>::from(input); + let mut out: i128 = 0; + unsafe { + value.write_value_to(&mut out as *mut i128); + } + assert_eq!(out, 0xffffffff); + } + + #[test] + fn test_value_i64_from_u64() { + let input: u64 = 0x0000000000000000; + let value = Value::<()>::from(input); + let mut out: i128 = 0; + unsafe { + value.write_value_to(&mut out as *mut i128); + } + assert_eq!(out, 0x0000000000000000); + + let input: u64 = 0x0000000000000001; + let value = Value::<()>::from(input); + let mut out: i128 = 0; + unsafe { + value.write_value_to(&mut out as *mut i128); + } + assert_eq!(out, 0x0000000000000001); + + let input: u64 = 0xaabbccddeeff0011; + let value = Value::<()>::from(input); + let mut out: i128 = 0; + unsafe { + value.write_value_to(&mut out as *mut i128); + } + assert_eq!(out, 0xaabbccddeeff0011); + + let input: u64 = 0xffffffffffffffff; + let value = Value::<()>::from(input); + let mut out: i128 = 0; + unsafe { + value.write_value_to(&mut out as *mut i128); + } + assert_eq!(out, 0xffffffffffffffff); + } +} From 5cc8439487a8d5bd62542db890fbdc1f668b8464 Mon Sep 17 00:00:00 2001 From: Simon Warta Date: Sat, 10 Oct 2020 08:36:30 +0200 Subject: [PATCH 205/281] Use from_be_bytes for tests --- lib/wasmer-types/src/values.rs | 80 ++++++++++------------------------ 1 file changed, 24 insertions(+), 56 deletions(-) diff --git a/lib/wasmer-types/src/values.rs b/lib/wasmer-types/src/values.rs index 4f37a7128..bf497701b 100644 --- a/lib/wasmer-types/src/values.rs +++ b/lib/wasmer-types/src/values.rs @@ -229,71 +229,39 @@ mod tests { #[test] fn test_value_i32_from_u32() { - let input: u32 = 0x00000000; - let value = Value::<()>::from(input); - let mut out: i128 = 0; - unsafe { - value.write_value_to(&mut out as *mut i128); - } - assert_eq!(out, 0x00000000); + let bytes = [0x00, 0x00, 0x00, 0x00]; + let v = Value::<()>::from(u32::from_be_bytes(bytes.clone())); + assert_eq!(v, Value::I32(i32::from_be_bytes(bytes.clone()))); - let input: u32 = 0x00000001; - let value = Value::<()>::from(input); - let mut out: i128 = 0; - unsafe { - value.write_value_to(&mut out as *mut i128); - } - assert_eq!(out, 0x00000001); + let bytes = [0x00, 0x00, 0x00, 0x01]; + let v = Value::<()>::from(u32::from_be_bytes(bytes.clone())); + assert_eq!(v, Value::I32(i32::from_be_bytes(bytes.clone()))); - let input: u32 = 0xaabbccdd; - let value = Value::<()>::from(input); - let mut out: i128 = 0; - unsafe { - value.write_value_to(&mut out as *mut i128); - } - assert_eq!(out, 0xaabbccdd); + let bytes = [0xAA, 0xBB, 0xCC, 0xDD]; + let v = Value::<()>::from(u32::from_be_bytes(bytes.clone())); + assert_eq!(v, Value::I32(i32::from_be_bytes(bytes.clone()))); - let input: u32 = 0xffffffff; - let value = Value::<()>::from(input); - let mut out: i128 = 0; - unsafe { - value.write_value_to(&mut out as *mut i128); - } - assert_eq!(out, 0xffffffff); + let bytes = [0xFF, 0xFF, 0xFF, 0xFF]; + let v = Value::<()>::from(u32::from_be_bytes(bytes.clone())); + assert_eq!(v, Value::I32(i32::from_be_bytes(bytes.clone()))); } #[test] fn test_value_i64_from_u64() { - let input: u64 = 0x0000000000000000; - let value = Value::<()>::from(input); - let mut out: i128 = 0; - unsafe { - value.write_value_to(&mut out as *mut i128); - } - assert_eq!(out, 0x0000000000000000); + let bytes = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]; + let v = Value::<()>::from(u64::from_be_bytes(bytes.clone())); + assert_eq!(v, Value::I64(i64::from_be_bytes(bytes.clone()))); - let input: u64 = 0x0000000000000001; - let value = Value::<()>::from(input); - let mut out: i128 = 0; - unsafe { - value.write_value_to(&mut out as *mut i128); - } - assert_eq!(out, 0x0000000000000001); + let bytes = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01]; + let v = Value::<()>::from(u64::from_be_bytes(bytes.clone())); + assert_eq!(v, Value::I64(i64::from_be_bytes(bytes.clone()))); - let input: u64 = 0xaabbccddeeff0011; - let value = Value::<()>::from(input); - let mut out: i128 = 0; - unsafe { - value.write_value_to(&mut out as *mut i128); - } - assert_eq!(out, 0xaabbccddeeff0011); + let bytes = [0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, 0x00, 0x11]; + let v = Value::<()>::from(u64::from_be_bytes(bytes.clone())); + assert_eq!(v, Value::I64(i64::from_be_bytes(bytes.clone()))); - let input: u64 = 0xffffffffffffffff; - let value = Value::<()>::from(input); - let mut out: i128 = 0; - unsafe { - value.write_value_to(&mut out as *mut i128); - } - assert_eq!(out, 0xffffffffffffffff); + let bytes = [0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF]; + let v = Value::<()>::from(u64::from_be_bytes(bytes.clone())); + assert_eq!(v, Value::I64(i64::from_be_bytes(bytes.clone()))); } } From 1ecb4ca2509368d5713628e2fa540e8d3d03e7d2 Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Fri, 9 Oct 2020 14:51:53 +0200 Subject: [PATCH 206/281] feat(c-api) Implement `wasm_externtype_copy`. --- lib/c-api/src/wasm_c_api/types/extern_.rs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/lib/c-api/src/wasm_c_api/types/extern_.rs b/lib/c-api/src/wasm_c_api/types/extern_.rs index 97692de73..3f78ad11f 100644 --- a/lib/c-api/src/wasm_c_api/types/extern_.rs +++ b/lib/c-api/src/wasm_c_api/types/extern_.rs @@ -21,6 +21,15 @@ pub unsafe extern "C" fn wasm_extern_type(e: &wasm_extern_t) -> Box>) {} +#[no_mangle] +pub extern "C" fn wasm_externtype_copy( + wasm_externtype: &wasm_externtype_t, +) -> Box { + Box::new(wasm_externtype_t { + inner: wasm_externtype.inner.clone(), + }) +} + impl From for wasm_externtype_t { fn from(other: ExternType) -> Self { Self { inner: other } From 0613579426de703c294e2e536a67d745f6075446 Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Mon, 12 Oct 2020 09:55:42 +0200 Subject: [PATCH 207/281] doc(changelog) Add #1700. --- CHANGELOG.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8047c8f4c..41c7a1d46 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,10 @@ ## **[Unreleased]** +- [#1700](https://github.com/wasmerio/wasmer/pull/1700) Implement `wasm_externtype_copy` in the Wasm C API. + ## 1.0.0-alpha4 - 2020-10-08 + - [#1691](https://github.com/wasmerio/wasmer/pull/1691) Bump minimum supported Rust version to 1.46.0 - [#1690](https://github.com/wasmerio/wasmer/pull/1690) Fix `wasm_memorytype_limits` where `min` and `max` represents pages, not bytes. Additionally, fixes the max limit sentinel value. - [#1682](https://github.com/wasmerio/wasmer/pull/1682) Improve error reporting when making a memory with invalid settings. @@ -14,15 +17,18 @@ - [#1645](https://github.com/wasmerio/wasmer/pull/1645) Move the install script to https://github.com/wasmerio/wasmer-install ## 1.0.0-alpha3 - 2020-09-14 + - [#1620](https://github.com/wasmerio/wasmer/pull/1620) Fix bug causing the Wapm binary to not be packaged with the release - [#1619](https://github.com/wasmerio/wasmer/pull/1619) Improve error message in engine-native when C compiler is missing ## 1.0.0-alpha02.0 - 2020-09-11 + - [#1602](https://github.com/wasmerio/wasmer/pull/1602) Fix panic when calling host functions with negative numbers in certain situations - [#1590](https://github.com/wasmerio/wasmer/pull/1590) Fix soundness issue in API of vm::Global - [#1566](https://github.com/wasmerio/wasmer/pull/1566) Add support for opening special Unix files to the WASI FS ## TODO: 1.0.0-alpha01.0 + - Wasmer refactor lands ## TODO: 17... From 8b38dd575e01dfd288d1d73e2e60459a889efc79 Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Mon, 12 Oct 2020 11:22:54 +0200 Subject: [PATCH 208/281] feat(c-api) Implement `wasm_val_vec_t`. --- lib/c-api/src/wasm_c_api/value.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/c-api/src/wasm_c_api/value.rs b/lib/c-api/src/wasm_c_api/value.rs index cb427e78d..5ae7c449f 100644 --- a/lib/c-api/src/wasm_c_api/value.rs +++ b/lib/c-api/src/wasm_c_api/value.rs @@ -23,6 +23,8 @@ pub struct wasm_val_t { pub of: wasm_val_inner, } +wasm_declare_vec!(val); + impl Clone for wasm_val_t { fn clone(&self) -> Self { wasm_val_t { From d8dcb4133a579cdcd35bf8ada9c6dbd4cc6ef409 Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Mon, 12 Oct 2020 11:23:52 +0200 Subject: [PATCH 209/281] feat(c-api) Update the definitions of `wasm_func_callback*_t`. --- lib/c-api/src/wasm_c_api/externals/function.rs | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/lib/c-api/src/wasm_c_api/externals/function.rs b/lib/c-api/src/wasm_c_api/externals/function.rs index b64f52d87..7a95088c5 100644 --- a/lib/c-api/src/wasm_c_api/externals/function.rs +++ b/lib/c-api/src/wasm_c_api/externals/function.rs @@ -1,7 +1,7 @@ use super::super::store::wasm_store_t; use super::super::trap::wasm_trap_t; use super::super::types::{wasm_functype_t, wasm_valkind_enum}; -use super::super::value::{wasm_val_inner, wasm_val_t}; +use super::super::value::{wasm_val_inner, wasm_val_t, wasm_val_vec_t}; use std::convert::TryInto; use std::ffi::c_void; use std::sync::Arc; @@ -15,14 +15,16 @@ pub struct wasm_func_t { } #[allow(non_camel_case_types)] -pub type wasm_func_callback_t = - unsafe extern "C" fn(args: *const wasm_val_t, results: *mut wasm_val_t) -> *mut wasm_trap_t; +pub type wasm_func_callback_t = unsafe extern "C" fn( + args: *const wasm_val_vec_t, + results: *mut wasm_val_vec_t, +) -> *mut wasm_trap_t; #[allow(non_camel_case_types)] pub type wasm_func_callback_with_env_t = unsafe extern "C" fn( *mut c_void, - args: *const wasm_val_t, - results: *mut wasm_val_t, + args: *const wasm_val_vec_t, + results: *mut wasm_val_vec_t, ) -> *mut wasm_trap_t; #[allow(non_camel_case_types)] From 5dffd976f5fc770df3aae84dbdea30ace951a452 Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Mon, 12 Oct 2020 11:24:30 +0200 Subject: [PATCH 210/281] feat(c-api) Update `wasm_func_new`. --- lib/c-api/src/wasm_c_api/externals/function.rs | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/lib/c-api/src/wasm_c_api/externals/function.rs b/lib/c-api/src/wasm_c_api/externals/function.rs index 7a95088c5..015d38edc 100644 --- a/lib/c-api/src/wasm_c_api/externals/function.rs +++ b/lib/c-api/src/wasm_c_api/externals/function.rs @@ -40,31 +40,37 @@ pub unsafe extern "C" fn wasm_func_new( let func_sig = ft.sig(); let num_rets = func_sig.results().len(); let inner_callback = move |args: &[Val]| -> Result, RuntimeError> { - let processed_args = args + let processed_args: wasm_val_vec_t = args .into_iter() .map(TryInto::try_into) .collect::, _>>() - .expect("Argument conversion failed"); + .expect("Argument conversion failed") + .into(); - let mut results = vec![ + let mut results: wasm_val_vec_t = vec![ wasm_val_t { kind: wasm_valkind_enum::WASM_I64 as _, of: wasm_val_inner { int64_t: 0 }, }; num_rets - ]; + ] + .into(); + + let trap = callback(&processed_args, &mut results); - let trap = callback(processed_args.as_ptr(), results.as_mut_ptr()); if !trap.is_null() { let trap: Box = Box::from_raw(trap); RuntimeError::raise(Box::new(trap.inner)); } let processed_results = results + .into_slice() + .expect("Failed to convert `results` into a slice") .into_iter() .map(TryInto::try_into) .collect::, _>>() .expect("Result conversion failed"); + Ok(processed_results) }; let function = Function::new(&store.inner, &func_sig, inner_callback); From 7f098387e8174595e568ba13db6861a1790e978d Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Mon, 12 Oct 2020 11:24:59 +0200 Subject: [PATCH 211/281] faet(c-api) Update `wasm_func_new_with_env`. --- lib/c-api/src/wasm_c_api/externals/function.rs | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/lib/c-api/src/wasm_c_api/externals/function.rs b/lib/c-api/src/wasm_c_api/externals/function.rs index 015d38edc..74633f316 100644 --- a/lib/c-api/src/wasm_c_api/externals/function.rs +++ b/lib/c-api/src/wasm_c_api/externals/function.rs @@ -94,30 +94,36 @@ pub unsafe extern "C" fn wasm_func_new_with_env( let num_rets = func_sig.results().len(); let inner_callback = move |env: &mut *mut c_void, args: &[Val]| -> Result, RuntimeError> { - let processed_args = args + let processed_args: wasm_val_vec_t = args .into_iter() .map(TryInto::try_into) .collect::, _>>() - .expect("Argument conversion failed"); + .expect("Argument conversion failed") + .into(); - let mut results = vec![ + let mut results: wasm_val_vec_t = vec![ wasm_val_t { kind: wasm_valkind_enum::WASM_I64 as _, of: wasm_val_inner { int64_t: 0 }, }; num_rets - ]; + ] + .into(); - let _traps = callback(*env, processed_args.as_ptr(), results.as_mut_ptr()); + let _traps = callback(*env, &processed_args, &mut results); // TODO: do something with `traps` let processed_results = results + .into_slice() + .expect("Failed to convert `results` into a slice") .into_iter() .map(TryInto::try_into) .collect::, _>>() .expect("Result conversion failed"); + Ok(processed_results) }; + let function = Function::new_with_env(&store.inner, &func_sig, env, inner_callback); Some(Box::new(wasm_func_t { From e9cd7105066679eea6969f32a5eb0efa0ed9674a Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Mon, 12 Oct 2020 11:25:17 +0200 Subject: [PATCH 212/281] feat(c-api) Update `wasm_func_call`. --- .../src/wasm_c_api/externals/function.rs | 26 +++++++++++-------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/lib/c-api/src/wasm_c_api/externals/function.rs b/lib/c-api/src/wasm_c_api/externals/function.rs index 74633f316..9fddd29f2 100644 --- a/lib/c-api/src/wasm_c_api/externals/function.rs +++ b/lib/c-api/src/wasm_c_api/externals/function.rs @@ -138,21 +138,25 @@ pub unsafe extern "C" fn wasm_func_delete(_func: Option>) {} #[no_mangle] pub unsafe extern "C" fn wasm_func_call( func: &wasm_func_t, - args: *const wasm_val_t, - results: *mut wasm_val_t, + args: &wasm_val_vec_t, + results: &mut wasm_val_vec_t, ) -> Option> { - let num_params = func.inner.ty().params().len(); - let params: Vec = (0..num_params) - .map(|i| (&(*args.add(i))).try_into()) - .collect::>() - .ok()?; + let params = args + .into_slice()? + .into_iter() + .map(TryInto::try_into) + .collect::, _>>() + .expect("Argument conversion failed"); match func.inner.call(¶ms) { Ok(wasm_results) => { - for (i, actual_result) in wasm_results.iter().enumerate() { - let result_loc = &mut (*results.add(i)); - *result_loc = (&*actual_result).try_into().ok()?; - } + *results = wasm_results + .into_iter() + .map(TryInto::try_into) + .collect::, _>>() + .expect("Argument conversion failed") + .into(); + None } Err(e) => Some(Box::new(e.into())), From fa7fe83bc0b19a43138454df0d716e4e2e2b774a Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Mon, 12 Oct 2020 11:45:31 +0200 Subject: [PATCH 213/281] feat(c-api) Update `wasm_instance_new`. The `CArrayIter` type is no longer needed. This patch removes it. --- lib/c-api/src/wasm_c_api/instance.rs | 43 +++------------------------- 1 file changed, 4 insertions(+), 39 deletions(-) diff --git a/lib/c-api/src/wasm_c_api/instance.rs b/lib/c-api/src/wasm_c_api/instance.rs index a79044a4e..3b16e1eef 100644 --- a/lib/c-api/src/wasm_c_api/instance.rs +++ b/lib/c-api/src/wasm_c_api/instance.rs @@ -12,56 +12,21 @@ pub struct wasm_instance_t { pub(crate) inner: Arc, } -struct CArrayIter { - cur_entry: *const *const T, -} - -impl CArrayIter { - fn new(array: *const *const T) -> Option { - if array.is_null() { - None - } else { - Some(CArrayIter { cur_entry: array }) - } - } -} - -impl Iterator for CArrayIter { - type Item = &'static T; - - fn next(&mut self) -> Option { - let next_entry_candidate = unsafe { *self.cur_entry }; - if next_entry_candidate.is_null() { - None - } else { - self.cur_entry = unsafe { self.cur_entry.add(1) }; - Some(unsafe { &*next_entry_candidate }) - } - } -} - -// reads from null-terminated array of `wasm_extern_t`s -unsafe fn argument_import_iter( - imports: *const *const wasm_extern_t, -) -> Box> { - CArrayIter::new(imports) - .map(|it| Box::new(it) as _) - .unwrap_or_else(|| Box::new(std::iter::empty()) as _) -} - #[no_mangle] pub unsafe extern "C" fn wasm_instance_new( _store: &wasm_store_t, module: &wasm_module_t, - imports: *const *const wasm_extern_t, + imports: &wasm_extern_vec_t, // own _traps: *mut *mut wasm_trap_t, ) -> Option> { let wasm_module = &module.inner; let module_imports = wasm_module.imports(); let module_import_count = module_imports.len(); - let imports = argument_import_iter(imports); let resolver: OrderedResolver = imports + .into_slice() + .map(|imports| imports.iter()) + .unwrap_or_else(|| [].iter()) .map(|imp| &imp.inner) .take(module_import_count) .cloned() From fea156defa4fcffc60d1a808b51f8942eef9f38f Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Mon, 12 Oct 2020 11:58:53 +0200 Subject: [PATCH 214/281] =?UTF-8?q?feat(c-api)=20Update=20`wasi=5Fget=5Fim?= =?UTF-8?q?ports`=20to=20use=20a=20`wasm=5Fextern=5Fvec=5Ft`=E2=80=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit … so that it matches the definition of `wasm_instance_new`, which is much simpler and consistent. --- lib/c-api/src/wasm_c_api/wasi/mod.rs | 44 ++++++++++++++++------------ 1 file changed, 25 insertions(+), 19 deletions(-) diff --git a/lib/c-api/src/wasm_c_api/wasi/mod.rs b/lib/c-api/src/wasm_c_api/wasi/mod.rs index cf0a08b73..2db9204d0 100644 --- a/lib/c-api/src/wasm_c_api/wasi/mod.rs +++ b/lib/c-api/src/wasm_c_api/wasi/mod.rs @@ -5,7 +5,7 @@ mod capture_files; use super::{ - externals::{wasm_extern_t, wasm_func_t, wasm_memory_t}, + externals::{wasm_extern_t, wasm_extern_vec_t, wasm_func_t, wasm_memory_t}, instance::wasm_instance_t, module::wasm_module_t, store::wasm_store_t, @@ -243,7 +243,7 @@ pub unsafe extern "C" fn wasi_get_imports( store: &wasm_store_t, module: &wasm_module_t, wasi_env: &wasi_env_t, - imports: *mut *mut wasm_extern_t, + imports: &mut wasm_extern_vec_t, ) -> bool { wasi_get_imports_inner(store, module, wasi_env, imports).is_some() } @@ -253,7 +253,7 @@ unsafe fn wasi_get_imports_inner( store: &wasm_store_t, module: &wasm_module_t, wasi_env: &wasi_env_t, - imports: *mut *mut wasm_extern_t, + imports: &mut wasm_extern_vec_t, ) -> Option<()> { let store = &store.inner; @@ -265,22 +265,28 @@ unsafe fn wasi_get_imports_inner( let import_object = generate_import_object_from_env(store, wasi_env.inner.clone(), version); - for (i, it) in module.inner.imports().enumerate() { - let export = c_try!(import_object - .resolve_by_name(it.module(), it.name()) - .ok_or_else(|| CApiError { - msg: format!( - "Failed to resolve import \"{}\" \"{}\"", - it.module(), - it.name() - ), - })); - let inner = Extern::from_export(store, export); - *imports.add(i) = Box::into_raw(Box::new(wasm_extern_t { - instance: None, - inner, - })); - } + *imports = module + .inner + .imports() + .map(|import_type| { + let export = c_try!(import_object + .resolve_by_name(import_type.module(), import_type.name()) + .ok_or_else(|| CApiError { + msg: format!( + "Failed to resolve import \"{}\" \"{}\"", + import_type.module(), + import_type.name() + ), + })); + let inner = Extern::from_export(store, export); + + Some(Box::new(wasm_extern_t { + instance: None, + inner, + })) + }) + .collect::>>()? + .into(); Some(()) } From 202ffe7771cbea376bd238d5108e34de328a4735 Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Mon, 12 Oct 2020 12:20:29 +0200 Subject: [PATCH 215/281] fix(c-api) Fix `wasm_func_call` when params are empty. `wasm_$name_vec_t.into_slice` returns `None` if the vec is empty. So an empty vec of `wasm_extern_t` given to `wasm_func_call` was raising an error. This patch fixes this. --- lib/c-api/src/wasm_c_api/externals/function.rs | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/lib/c-api/src/wasm_c_api/externals/function.rs b/lib/c-api/src/wasm_c_api/externals/function.rs index 9fddd29f2..0b9ae3ff4 100644 --- a/lib/c-api/src/wasm_c_api/externals/function.rs +++ b/lib/c-api/src/wasm_c_api/externals/function.rs @@ -142,11 +142,15 @@ pub unsafe extern "C" fn wasm_func_call( results: &mut wasm_val_vec_t, ) -> Option> { let params = args - .into_slice()? - .into_iter() - .map(TryInto::try_into) - .collect::, _>>() - .expect("Argument conversion failed"); + .into_slice() + .map(|slice| { + slice + .into_iter() + .map(TryInto::try_into) + .collect::, _>>() + .expect("Argument conversion failed") + }) + .unwrap_or_else(|| Vec::new()); match func.inner.call(¶ms) { Ok(wasm_results) => { From 4584a5384054fd2f6f85f40e1f7f5365f3461973 Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Mon, 12 Oct 2020 13:12:37 +0200 Subject: [PATCH 216/281] fix(c-api) Remove `rustc` warnings. --- lib/c-api/src/wasm_c_api/engine.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/c-api/src/wasm_c_api/engine.rs b/lib/c-api/src/wasm_c_api/engine.rs index 72aacf2c5..1a72355eb 100644 --- a/lib/c-api/src/wasm_c_api/engine.rs +++ b/lib/c-api/src/wasm_c_api/engine.rs @@ -87,6 +87,7 @@ pub extern "C" fn wasm_config_set_engine(config: &mut wasm_config_t, engine: was } /// cbindgen:ignore +#[allow(non_camel_case_types)] pub struct wasm_engine_t { pub(crate) inner: Arc, } @@ -170,6 +171,7 @@ pub extern "C" fn wasm_engine_new_with_config( // TODO: return useful error messages in failure branches cfg_if! { if #[cfg(feature = "compiler")] { + #[allow(unused_mut)] let mut compiler_config: Box = match config.compiler { wasmer_compiler_t::CRANELIFT => { cfg_if! { From 5bf90558c7a59594ceb483ba4f25bfd6aae1bd82 Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Mon, 12 Oct 2020 13:17:40 +0200 Subject: [PATCH 217/281] test(c-api) Fix the `early-exit` test. --- lib/c-api/tests/wasm_c_api/test-early-exit.c | 25 ++++++++++++-------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/lib/c-api/tests/wasm_c_api/test-early-exit.c b/lib/c-api/tests/wasm_c_api/test-early-exit.c index bbc70af7d..d98b5417c 100644 --- a/lib/c-api/tests/wasm_c_api/test-early-exit.c +++ b/lib/c-api/tests/wasm_c_api/test-early-exit.c @@ -27,9 +27,9 @@ void print_frame(wasm_frame_t* frame) { wasm_store_t *store = NULL; -own wasm_trap_t *early_exit(const wasm_val_t args[], wasm_val_t results[]) { +own wasm_trap_t* early_exit(const wasm_val_vec_t* args, wasm_val_vec_t* results) { own wasm_message_t trap_message; - wasm_name_new_from_string(&trap_message, "trapping from a host import"); + wasm_name_new_from_string_nt(&trap_message, "trapping from a host import"); own wasm_trap_t *trap = wasm_trap_new(store, &trap_message); wasm_name_delete(&trap_message); return trap; @@ -77,9 +77,13 @@ int main(int argc, const char *argv[]) { wasm_functype_delete(host_func_type); - const wasm_extern_t *imports[] = {wasm_func_as_extern(host_func)}; + wasm_extern_vec_t imports; + wasm_extern_vec_new_uninitialized(&imports, 1); + imports.data[0] = wasm_func_as_extern(host_func); + own wasm_instance_t *instance = - wasm_instance_new(store, module, imports, NULL); + wasm_instance_new(store, module, &imports, NULL); + if (!instance) { printf("> Error instantiating module!\n"); print_wasmer_error(); @@ -110,12 +114,12 @@ int main(int argc, const char *argv[]) { // Call. printf("Calling export...\n"); - own const wasm_val_t args[] = { - {.kind = WASM_I32, .of = {.i32 = 1}}, - {.kind = WASM_I32, .of = {.i32 = 7}}, - }; - own wasm_val_t rets[1] = {}; - own wasm_trap_t *trap = wasm_func_call(run_func, args, rets); + wasm_val_t values[2] = { WASM_I32_VAL(1), WASM_I32_VAL(7) }; + own wasm_val_vec_t args = WASM_ARRAY_VEC(values); + wasm_val_t result = WASM_INIT_VAL; + own wasm_val_vec_t rets = { 1, &result }; + own wasm_trap_t *trap = wasm_func_call(run_func, &args, &rets); + if (!trap) { printf("> Error calling function: expected trap!\n"); return 1; @@ -151,6 +155,7 @@ int main(int argc, const char *argv[]) { wasm_name_delete(&message); wasm_extern_vec_delete(&exports); + wasm_extern_vec_delete(&imports); // Shut down. printf("Shutting down...\n"); From 4186d1ce58f9811732d059b47d22134df88bb75e Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Mon, 12 Oct 2020 13:33:46 +0200 Subject: [PATCH 218/281] test(c-api) Use `wasm_extern_vec_t` for `wasm_get_imports`. --- lib/c-api/tests/wasm_c_api/test-wasi.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/lib/c-api/tests/wasm_c_api/test-wasi.c b/lib/c-api/tests/wasm_c_api/test-wasi.c index 81c22fd92..2a21cdec9 100644 --- a/lib/c-api/tests/wasm_c_api/test-wasi.c +++ b/lib/c-api/tests/wasm_c_api/test-wasi.c @@ -18,7 +18,6 @@ void print_wasmer_error() printf("Error str: `%s`\n", error_str); } - int main(int argc, const char* argv[]) { // Initialize. printf("Initializing...\n"); @@ -71,18 +70,22 @@ int main(int argc, const char* argv[]) { printf("Instantiating module...\n"); wasm_importtype_vec_t import_types; wasm_module_imports(module, &import_types); - int num_imports = import_types.size; - wasm_extern_t** imports = malloc(num_imports * sizeof(wasm_extern_t*)); + + wasm_extern_vec_t imports; + wasm_extern_vec_new_uninitialized(&imports, import_types.size); wasm_importtype_vec_delete(&import_types); - bool get_imports_result = wasi_get_imports(store, module, wasi_env, imports); + bool get_imports_result = wasi_get_imports(store, module, wasi_env, &imports); + if (!get_imports_result) { printf("> Error getting WASI imports!\n"); print_wasmer_error(); return 1; } + own wasm_instance_t* instance = - wasm_instance_new(store, module, (const wasm_extern_t *const *) imports, NULL); + wasm_instance_new(store, module, &imports, NULL); + if (!instance) { printf("> Error instantiating module!\n"); print_wasmer_error(); From 0b4ef7add7821d29ff31cdafb01e48b3009dbdbf Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Mon, 12 Oct 2020 13:34:20 +0200 Subject: [PATCH 219/281] test(c-api) Don't pass `NULL` for zero args/results to `wasm_func_call`! We must pass an empty array. --- lib/c-api/tests/wasm_c_api/test-wasi.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/lib/c-api/tests/wasm_c_api/test-wasi.c b/lib/c-api/tests/wasm_c_api/test-wasi.c index 2a21cdec9..1c7c244db 100644 --- a/lib/c-api/tests/wasm_c_api/test-wasi.c +++ b/lib/c-api/tests/wasm_c_api/test-wasi.c @@ -117,7 +117,11 @@ int main(int argc, const char* argv[]) { // Call. printf("Calling export...\n"); printf("Evaluating \"%s\"\n", js_string); - if (wasm_func_call(run_func, NULL, NULL)) { + + wasm_val_vec_t args = WASM_EMPTY_VEC; + wasm_val_vec_t res = WASM_EMPTY_VEC; + + if (wasm_func_call(run_func, &args, &res)) { printf("> Error calling function!\n"); return 1; } @@ -134,12 +138,7 @@ int main(int argc, const char* argv[]) { printf("\n"); wasm_extern_vec_delete(&exports); - - // NEEDS REVIEW: - for(int i = 0; i < num_imports; ++i) { - wasm_extern_delete(imports[i]); - } - free(imports); + wasm_extern_vec_delete(&imports); // Shut down. printf("Shutting down...\n"); From 437426d8b18e3c9e4db1eb5fb61c7063fb01ef84 Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Mon, 12 Oct 2020 13:34:55 +0200 Subject: [PATCH 220/281] feat(c-api) Update `wasmer_wasm.h`. --- lib/c-api/wasmer_wasm.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/c-api/wasmer_wasm.h b/lib/c-api/wasmer_wasm.h index b9eea99ae..bdd06f88b 100644 --- a/lib/c-api/wasmer_wasm.h +++ b/lib/c-api/wasmer_wasm.h @@ -139,7 +139,7 @@ void wasi_env_set_memory(wasi_env_t *env, const wasm_memory_t *memory); bool wasi_get_imports(const wasm_store_t *store, const wasm_module_t *module, const wasi_env_t *wasi_env, - wasm_extern_t **imports); + wasm_extern_vec_t *imports); #endif #if defined(WASMER_WASI_ENABLED) From 202301616f8f6de300982e1861907c9bef869ef2 Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Mon, 12 Oct 2020 13:37:45 +0200 Subject: [PATCH 221/281] doc(changelog) Add #1699. --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 41c7a1d46..50a98db40 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ ## **[Unreleased]** +- [#1699](https://github.com/wasmerio/wasmer/pull/1699) Update `wasm.h` to its latest version. - [#1700](https://github.com/wasmerio/wasmer/pull/1700) Implement `wasm_externtype_copy` in the Wasm C API. ## 1.0.0-alpha4 - 2020-10-08 From 44632946c1f57b8f6f6fca041992fe096b0c2663 Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Mon, 12 Oct 2020 13:49:02 +0200 Subject: [PATCH 222/281] doc(changelog) Add #1685. --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 50a98db40..4de1ec274 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ ## **[Unreleased]** - [#1699](https://github.com/wasmerio/wasmer/pull/1699) Update `wasm.h` to its latest version. +- [#1685](https://github.com/wasmerio/wasmer/pull/1685) Implement `wasm_exporttype_delete` in the Wasm C API. - [#1700](https://github.com/wasmerio/wasmer/pull/1700) Implement `wasm_externtype_copy` in the Wasm C API. ## 1.0.0-alpha4 - 2020-10-08 From 750a1c3645478616157872111ae1c6d0083a2ecd Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Mon, 12 Oct 2020 17:52:40 +0200 Subject: [PATCH 223/281] feat(c-api) Implement `wasm_module_name` and `wasm_module_set_name`. I submited a proposal to the official `wasm.h` by the way, https://github.com/WebAssembly/wasm-c-api/pull/157. For the moment, let's keep that as a vendor specific implementation. --- lib/c-api/src/wasm_c_api/wasmer.rs | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/lib/c-api/src/wasm_c_api/wasmer.rs b/lib/c-api/src/wasm_c_api/wasmer.rs index 5d6122c05..6b811e5f2 100644 --- a/lib/c-api/src/wasm_c_api/wasmer.rs +++ b/lib/c-api/src/wasm_c_api/wasmer.rs @@ -1,9 +1,35 @@ //! Wasmer-specific extensions to the Wasm C API. -use crate::wasm_c_api::instance::wasm_instance_t; +use super::instance::wasm_instance_t; +use super::module::wasm_module_t; +use super::types::wasm_name_t; use std::ffi::c_void; +use std::str; #[no_mangle] pub unsafe extern "C" fn wasm_instance_get_vmctx_ptr(instance: &wasm_instance_t) -> *mut c_void { instance.inner.vmctx_ptr() as _ } + +#[no_mangle] +pub unsafe extern "C" fn wasm_module_name(module: &wasm_module_t, out: &mut wasm_name_t) { + let name = match module.inner.name() { + Some(name) => name, + None => return, + }; + + *out = name.as_bytes().to_vec().into(); +} + +#[no_mangle] +pub unsafe extern "C" fn wasm_module_set_name(module: &wasm_module_t, name: &wasm_name_t) -> bool { + let name = match name.into_slice() { + Some(name) => match str::from_utf8(name) { + Ok(name) => name, + Err(_) => return false, // not ideal! + }, + None => return false, + }; + + module.inner.set_name(name) +} From b9f98ce1f696088a9764704198c1606500895ecf Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Mon, 12 Oct 2020 17:54:21 +0200 Subject: [PATCH 224/281] feat(c-api) Update `.h` files. --- lib/c-api/build.rs | 8 +++++--- lib/c-api/wasmer_wasm.h | 4 ++++ 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/lib/c-api/build.rs b/lib/c-api/build.rs index 627ad9039..e43285a62 100644 --- a/lib/c-api/build.rs +++ b/lib/c-api/build.rs @@ -378,10 +378,12 @@ fn exclude_items_from_wasm_c_api(builder: Builder) -> Builder { .exclude_item("wasi_get_start_function") .exclude_item("wasi_get_wasi_version") .exclude_item("wasi_version_t") - .exclude_item("wasm_instance_get_vmctx_ptr") - .exclude_item("wasmer_compiler_t") - .exclude_item("wasmer_engine_t") .exclude_item("wasm_config_set_compiler") .exclude_item("wasm_config_set_engine") + .exclude_item("wasm_instance_get_vmctx_ptr") + .exclude_item("wasm_module_name") + .exclude_item("wasm_module_set_name") + .exclude_item("wasmer_compiler_t") + .exclude_item("wasmer_engine_t") .exclude_item("wat2wasm") } diff --git a/lib/c-api/wasmer_wasm.h b/lib/c-api/wasmer_wasm.h index b9eea99ae..024304011 100644 --- a/lib/c-api/wasmer_wasm.h +++ b/lib/c-api/wasmer_wasm.h @@ -156,6 +156,10 @@ void wasm_config_set_engine(wasm_config_t *config, wasmer_engine_t engine); void *wasm_instance_get_vmctx_ptr(const wasm_instance_t *instance); +void wasm_module_name(const wasm_module_t *module, wasm_name_t *out); + +bool wasm_module_set_name(const wasm_module_t *module, const wasm_name_t *name); + /** * Gets the length in bytes of the last error if any. * From fe70330772f8545e3f32e4c1696031c3ef2f575c Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Mon, 12 Oct 2020 18:02:32 +0200 Subject: [PATCH 225/281] fixup --- lib/c-api/src/wasm_c_api/wasmer.rs | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/lib/c-api/src/wasm_c_api/wasmer.rs b/lib/c-api/src/wasm_c_api/wasmer.rs index 6b811e5f2..b62a2ec1d 100644 --- a/lib/c-api/src/wasm_c_api/wasmer.rs +++ b/lib/c-api/src/wasm_c_api/wasmer.rs @@ -5,6 +5,7 @@ use super::module::wasm_module_t; use super::types::wasm_name_t; use std::ffi::c_void; use std::str; +use std::sync::Arc; #[no_mangle] pub unsafe extern "C" fn wasm_instance_get_vmctx_ptr(instance: &wasm_instance_t) -> *mut c_void { @@ -22,7 +23,10 @@ pub unsafe extern "C" fn wasm_module_name(module: &wasm_module_t, out: &mut wasm } #[no_mangle] -pub unsafe extern "C" fn wasm_module_set_name(module: &wasm_module_t, name: &wasm_name_t) -> bool { +pub unsafe extern "C" fn wasm_module_set_name( + module: &mut wasm_module_t, + name: &wasm_name_t, +) -> bool { let name = match name.into_slice() { Some(name) => match str::from_utf8(name) { Ok(name) => name, @@ -31,5 +35,8 @@ pub unsafe extern "C" fn wasm_module_set_name(module: &wasm_module_t, name: &was None => return false, }; - module.inner.set_name(name) + match Arc::get_mut(&mut module.inner) { + Some(module) => module.set_name(name), + None => false, + } } From f866ea39fd68d37dba6ac3ce431b37b58d75f130 Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Mon, 12 Oct 2020 18:02:45 +0200 Subject: [PATCH 226/281] fixup --- lib/c-api/wasmer_wasm.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/c-api/wasmer_wasm.h b/lib/c-api/wasmer_wasm.h index 024304011..6dffd665d 100644 --- a/lib/c-api/wasmer_wasm.h +++ b/lib/c-api/wasmer_wasm.h @@ -158,7 +158,7 @@ void *wasm_instance_get_vmctx_ptr(const wasm_instance_t *instance); void wasm_module_name(const wasm_module_t *module, wasm_name_t *out); -bool wasm_module_set_name(const wasm_module_t *module, const wasm_name_t *name); +bool wasm_module_set_name(wasm_module_t *module, const wasm_name_t *name); /** * Gets the length in bytes of the last error if any. From c6460d1d77ad4977edbeda3f48a0dc8c94e3c59e Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Mon, 12 Oct 2020 13:48:26 -0700 Subject: [PATCH 227/281] Add `target` support to `wasmer create-exe` --- lib/cli/src/commands/create_exe.rs | 37 +++++++++++++++++++++++------- 1 file changed, 29 insertions(+), 8 deletions(-) diff --git a/lib/cli/src/commands/create_exe.rs b/lib/cli/src/commands/create_exe.rs index 0238da708..b8cbf85e2 100644 --- a/lib/cli/src/commands/create_exe.rs +++ b/lib/cli/src/commands/create_exe.rs @@ -130,11 +130,13 @@ impl CreateExe { // TODO: c_src_file.write_all(WASMER_MAIN_C_SOURCE)?; } - run_c_compile(&c_src_path, &c_src_obj).context("Failed to compile C source code")?; + run_c_compile(&c_src_path, &c_src_obj, self.target_triple.clone()) + .context("Failed to compile C source code")?; LinkCode { object_paths: vec![c_src_obj, wasm_object_path], output_path, additional_libraries: self.libraries.clone(), + target: self.target_triple.clone(), ..Default::default() } .run() @@ -155,6 +157,7 @@ fn get_wasmer_include_directory() -> anyhow::Result { Ok(path) } +/// path to the static libwasmer fn get_libwasmer_path() -> anyhow::Result { let mut path = PathBuf::from(env::var("WASMER_DIR")?); path.push("lib"); @@ -168,21 +171,31 @@ fn get_libwasmer_path() -> anyhow::Result { } /// Compile the C code. -fn run_c_compile(path_to_c_src: &Path, output_name: &Path) -> anyhow::Result<()> { +fn run_c_compile( + path_to_c_src: &Path, + output_name: &Path, + target: Option, +) -> anyhow::Result<()> { #[cfg(not(windows))] let c_compiler = "cc"; #[cfg(windows)] let c_compiler = "clang++"; - let output = Command::new(c_compiler) + let mut command = Command::new(c_compiler); + let command = command .arg("-O2") .arg("-c") .arg(path_to_c_src) .arg("-I") - .arg(get_wasmer_include_directory()?) - .arg("-o") - .arg(output_name) - .output()?; + .arg(get_wasmer_include_directory()?); + + let command = if let Some(target) = target { + command.arg("-target").arg(format!("{}", target)) + } else { + command + }; + + let output = command.arg("-o").arg(output_name).output()?; if !output.status.success() { bail!( @@ -209,8 +222,10 @@ struct LinkCode { additional_libraries: Vec, /// Path to the output target. output_path: PathBuf, - /// Path to the static libwasmer library. + /// Path to the dir containing the static libwasmer library. libwasmer_path: PathBuf, + /// The target to link the executable for. + target: Option, } impl Default for LinkCode { @@ -226,6 +241,7 @@ impl Default for LinkCode { additional_libraries: vec![], output_path: PathBuf::from("a.out"), libwasmer_path: get_libwasmer_path().unwrap(), + target: None, } } } @@ -248,6 +264,11 @@ impl LinkCode { .canonicalize() .context("Failed to find libwasmer")?, ); + let command = if let Some(target) = &self.target { + command.arg("-target").arg(format!("{}", target)) + } else { + command + }; #[cfg(windows)] let command = command.arg("-luserenv").arg("-lWs2_32").arg("-ladvapi32"); #[cfg(not(windows))] From 21c17704263d6210af1e22583263c285441ea04f Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Mon, 12 Oct 2020 13:51:03 -0700 Subject: [PATCH 228/281] Improve error message when `WASMER_DIR` is not set --- lib/cli/src/commands/create_exe.rs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/lib/cli/src/commands/create_exe.rs b/lib/cli/src/commands/create_exe.rs index b8cbf85e2..3caa57944 100644 --- a/lib/cli/src/commands/create_exe.rs +++ b/lib/cli/src/commands/create_exe.rs @@ -151,15 +151,21 @@ impl CreateExe { } } +fn get_wasmer_dir() -> anyhow::Result { + Ok(PathBuf::from( + env::var("WASMER_DIR").context("Trying to read env var `WASMER_DIR`")?, + )) +} + fn get_wasmer_include_directory() -> anyhow::Result { - let mut path = PathBuf::from(env::var("WASMER_DIR")?); + let mut path = get_wasmer_dir()?; path.push("include"); Ok(path) } /// path to the static libwasmer fn get_libwasmer_path() -> anyhow::Result { - let mut path = PathBuf::from(env::var("WASMER_DIR")?); + let mut path = get_wasmer_dir()?; path.push("lib"); #[cfg(not(windows))] From fff5366e530d2c21ac4fc4912869a97a8425a855 Mon Sep 17 00:00:00 2001 From: Syrus Akbary Date: Mon, 12 Oct 2020 14:54:21 -0700 Subject: [PATCH 229/281] Update CHANGELOG format based on Keep a Changelog --- CHANGELOG.md | 74 +++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 53 insertions(+), 21 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 41c7a1d46..74d19d04d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,83 +1,115 @@ # Changelog +*The format is based on [Keep a Changelog].* + +[Keep a Changelog]: http://keepachangelog.com/en/1.0.0/ + + ## **[Unreleased]** +### Added + - [#1700](https://github.com/wasmerio/wasmer/pull/1700) Implement `wasm_externtype_copy` in the Wasm C API. ## 1.0.0-alpha4 - 2020-10-08 -- [#1691](https://github.com/wasmerio/wasmer/pull/1691) Bump minimum supported Rust version to 1.46.0 -- [#1690](https://github.com/wasmerio/wasmer/pull/1690) Fix `wasm_memorytype_limits` where `min` and `max` represents pages, not bytes. Additionally, fixes the max limit sentinel value. -- [#1682](https://github.com/wasmerio/wasmer/pull/1682) Improve error reporting when making a memory with invalid settings. +### Added - [#1635](https://github.com/wasmerio/wasmer/pull/1635) Implement `wat2wasm` in the Wasm C API. - [#1636](https://github.com/wasmerio/wasmer/pull/1636) Implement `wasm_module_validate` in the Wasm C API. +- [#1657](https://github.com/wasmerio/wasmer/pull/1657) Implement `wasm_trap_t` and `wasm_frame_t` for Wasm C API; add examples in Rust and C of exiting early with a host function. + +### Fixed +- [#1690](https://github.com/wasmerio/wasmer/pull/1690) Fix `wasm_memorytype_limits` where `min` and `max` represents pages, not bytes. Additionally, fixes the max limit sentinel value. - [#1671](https://github.com/wasmerio/wasmer/pull/1671) Fix probestack firing inappropriately, and sometimes over/under allocating stack. - [#1660](https://github.com/wasmerio/wasmer/pull/1660) Fix issue preventing map-dir aliases starting with `/` from working properly. -- [#1657](https://github.com/wasmerio/wasmer/pull/1657) Implement `wasm_trap_t` and `wasm_frame_t` for Wasm C API; add examples in Rust and C of exiting early with a host function. + +### Changed +- [#1682](https://github.com/wasmerio/wasmer/pull/1682) Improve error reporting when making a memory with invalid settings. +- [#1691](https://github.com/wasmerio/wasmer/pull/1691) Bump minimum supported Rust version to 1.46.0 - [#1645](https://github.com/wasmerio/wasmer/pull/1645) Move the install script to https://github.com/wasmerio/wasmer-install ## 1.0.0-alpha3 - 2020-09-14 +### Fixed + - [#1620](https://github.com/wasmerio/wasmer/pull/1620) Fix bug causing the Wapm binary to not be packaged with the release - [#1619](https://github.com/wasmerio/wasmer/pull/1619) Improve error message in engine-native when C compiler is missing ## 1.0.0-alpha02.0 - 2020-09-11 +### Added + +- [#1566](https://github.com/wasmerio/wasmer/pull/1566) Add support for opening special Unix files to the WASI FS + +### Fixed + - [#1602](https://github.com/wasmerio/wasmer/pull/1602) Fix panic when calling host functions with negative numbers in certain situations - [#1590](https://github.com/wasmerio/wasmer/pull/1590) Fix soundness issue in API of vm::Global -- [#1566](https://github.com/wasmerio/wasmer/pull/1566) Add support for opening special Unix files to the WASI FS ## TODO: 1.0.0-alpha01.0 - Wasmer refactor lands -## TODO: 17... +## 0.17.1 - 2020-06-24 + +### Changed +- [#1439](https://github.com/wasmerio/wasmer/pull/1439) Move `wasmer-interface-types` into its own repository + +### Fixed - [#1554](https://github.com/wasmerio/wasmer/pull/1554) Update supported stable Rust version to 1.45.2. - [#1552](https://github.com/wasmerio/wasmer/pull/1552) Disable `sigint` handler by default. -## 0.17.1 - 2020-06-24 - -- [#1439](https://github.com/wasmerio/wasmer/pull/1439) Move `wasmer-interface-types` into its own repository - ## 0.17.0 - 2020-05-11 -- [#1401](https://github.com/wasmerio/wasmer/pull/1401) Make breaking change to `RuntimeError`: `RuntimeError` is now more explicit about its possible error values allowing for better insight into why a call into Wasm failed. -- [#1382](https://github.com/wasmerio/wasmer/pull/1382) Refactored test infranstructure (part 2) -- [#1380](https://github.com/wasmerio/wasmer/pull/1380) Refactored test infranstructure (part 1) -- [#1357](https://github.com/wasmerio/wasmer/pull/1357) Refactored bin commands into separate files +### Added - [#1331](https://github.com/wasmerio/wasmer/pull/1331) Implement the `record` type and instrutions for WIT - [#1345](https://github.com/wasmerio/wasmer/pull/1345) Adding ARM testing in Azure Pipelines -- [#1335](https://github.com/wasmerio/wasmer/pull/1335) Change mutability of `memory` to `const` in `wasmer_memory_data_length` in the C API - [#1329](https://github.com/wasmerio/wasmer/pull/1329) New numbers and strings instructions for WIT -- [#1332](https://github.com/wasmerio/wasmer/pull/1332) Add option to `CompilerConfig` to force compiler IR verification off even when `debug_assertions` are enabled. This can be used to make debug builds faster, which may be important if you're creating a library that wraps Wasmer and depend on the speed of debug builds. -- [#1320](https://github.com/wasmerio/wasmer/pull/1320) Change `custom_sections` field in `ModuleInfo` to be more standards compliant by allowing multiple custom sections with the same name. To get the old behavior with the new API, you can add `.last().unwrap()` to accesses. For example, `module_info.custom_sections["custom_section_name"].last().unwrap()`. +- [#1285](https://github.com/wasmerio/wasmer/pull/1285) Greatly improve errors in `wasmer-interface-types` +- [#1303](https://github.com/wasmerio/wasmer/pull/1303) NaN canonicalization for singlepass backend. - [#1313](https://github.com/wasmerio/wasmer/pull/1313) Add new high-level public API through `wasmer` crate. Includes many updates including: - Minor improvement: `imports!` macro now handles no trailing comma as well as a trailing comma in namespaces and between namespaces. - New methods on `Module`: `exports`, `imports`, and `custom_sections`. - New way to get exports from an instance with `let func_name: Func = instance.exports.get("func_name");`. - Improved `Table` APIs including `set` which now allows setting functions directly. TODO: update this more if `Table::get` gets made public in this PR - TODO: finish the list of changes here -- [#1303](https://github.com/wasmerio/wasmer/pull/1303) NaN canonicalization for singlepass backend. -- [#1292](https://github.com/wasmerio/wasmer/pull/1292) Experimental Support for Android (x86_64 and AArch64) - [#1305](https://github.com/wasmerio/wasmer/pull/1305) Handle panics from DynamicFunc. -- [#1301](https://github.com/wasmerio/wasmer/pull/1301) Update supported stable Rust version to 1.41.1. - [#1300](https://github.com/wasmerio/wasmer/pull/1300) Add support for multiple versions of WASI tests: wasitests now test all versions of WASI. -- [#1285](https://github.com/wasmerio/wasmer/pull/1285) Greatly improve errors in `wasmer-interface-types` +- [#1292](https://github.com/wasmerio/wasmer/pull/1292) Experimental Support for Android (x86_64 and AArch64) + +### Fixed - [#1283](https://github.com/wasmerio/wasmer/pull/1283) Workaround for floating point arguments and return values in `DynamicFunc`s. +### Changed +- [#1401](https://github.com/wasmerio/wasmer/pull/1401) Make breaking change to `RuntimeError`: `RuntimeError` is now more explicit about its possible error values allowing for better insight into why a call into Wasm failed. +- [#1382](https://github.com/wasmerio/wasmer/pull/1382) Refactored test infranstructure (part 2) +- [#1380](https://github.com/wasmerio/wasmer/pull/1380) Refactored test infranstructure (part 1) +- [#1357](https://github.com/wasmerio/wasmer/pull/1357) Refactored bin commands into separate files +- [#1335](https://github.com/wasmerio/wasmer/pull/1335) Change mutability of `memory` to `const` in `wasmer_memory_data_length` in the C API +- [#1332](https://github.com/wasmerio/wasmer/pull/1332) Add option to `CompilerConfig` to force compiler IR verification off even when `debug_assertions` are enabled. This can be used to make debug builds faster, which may be important if you're creating a library that wraps Wasmer and depend on the speed of debug builds. +- [#1320](https://github.com/wasmerio/wasmer/pull/1320) Change `custom_sections` field in `ModuleInfo` to be more standards compliant by allowing multiple custom sections with the same name. To get the old behavior with the new API, you can add `.last().unwrap()` to accesses. For example, `module_info.custom_sections["custom_section_name"].last().unwrap()`. +- [#1301](https://github.com/wasmerio/wasmer/pull/1301) Update supported stable Rust version to 1.41.1. + ## 0.16.2 - 2020-03-11 +### Fixed + - [#1294](https://github.com/wasmerio/wasmer/pull/1294) Fix bug related to system calls in WASI that rely on reading from WasmPtrs as arrays of length 0. `WasmPtr` will now succeed on length 0 arrays again. ## 0.16.1 - 2020-03-11 +### Fixed + - [#1291](https://github.com/wasmerio/wasmer/pull/1291) Fix installation packaging script to package the `wax` command. ## 0.16.0 - 2020-03-11 +### Added - [#1286](https://github.com/wasmerio/wasmer/pull/1286) Updated Windows Wasmer icons. Add wax - [#1284](https://github.com/wasmerio/wasmer/pull/1284) Implement string and memory instructions in `wasmer-interface-types` + +### Fixed - [#1272](https://github.com/wasmerio/wasmer/pull/1272) Fix off-by-one error bug when accessing memory with a `WasmPtr` that contains the last valid byte of memory. Also changes the behavior of `WasmPtr` with a length of 0 and `WasmPtr` where `std::mem::size_of::()` is 0 to always return `None` ## 0.15.0 - 2020-03-04 From a0b237c1f6ddb44853772021f043aef4495cdeba Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Mon, 12 Oct 2020 15:04:25 -0700 Subject: [PATCH 230/281] Add test using mapdir and dir, fix misc bugs --- lib/cli/src/commands/wasmer_create_exe_main.c | 10 +-- tests/integration/cli/src/link_code.rs | 4 + tests/integration/cli/src/util.rs | 7 +- tests/integration/cli/tests/compile.rs | 40 +++++---- tests/integration/cli/tests/create_exe.rs | 83 +++++++++++++++++-- 5 files changed, 116 insertions(+), 28 deletions(-) diff --git a/lib/cli/src/commands/wasmer_create_exe_main.c b/lib/cli/src/commands/wasmer_create_exe_main.c index 6b56c02fc..be7936731 100644 --- a/lib/cli/src/commands/wasmer_create_exe_main.c +++ b/lib/cli/src/commands/wasmer_create_exe_main.c @@ -44,20 +44,19 @@ void pass_mapdir_arg(wasi_config_t* wasi_config, char* mapdir) { fprintf(stderr, "Expected mapdir argument of the form alias:directory\n"); exit(-1); } - // TODO: triple check for off by one errors int dir_len = strlen(mapdir) - colon_location; - char* alias = (char*)malloc(colon_location); - char* dir = (char*)malloc(dir_len); + char* alias = (char*)malloc(colon_location + 1); + char* dir = (char*)malloc(dir_len + 1); int j = 0; for (j = 0; j < colon_location; ++j) { alias[j] = mapdir[j]; } alias[j] = 0; for (j = 0; j < dir_len; ++j) { - dir[j] = mapdir[j + colon_location]; + dir[j] = mapdir[j + colon_location + 1]; } dir[j] = 0; - + wasi_config_mapdir(wasi_config, alias, dir); free(alias); free(dir); @@ -107,7 +106,6 @@ void handle_arguments(wasi_config_t* wasi_config, int argc, char* argv[]) { #endif int main(int argc, char* argv[]) { - printf("Initializing...\n"); wasm_config_t* config = wasm_config_new(); wasm_config_set_engine(config, OBJECT_FILE); wasm_engine_t* engine = wasm_engine_new_with_config(config); diff --git a/tests/integration/cli/src/link_code.rs b/tests/integration/cli/src/link_code.rs index 72fb18e1b..d900f3e66 100644 --- a/tests/integration/cli/src/link_code.rs +++ b/tests/integration/cli/src/link_code.rs @@ -6,6 +6,8 @@ use std::process::Command; /// Data used to run a linking command for generated artifacts. #[derive(Debug)] pub struct LinkCode { + /// The directory to operate in. + pub current_dir: PathBuf, /// Path to the linker used to run the linking command. pub linker_path: PathBuf, /// String used as an optimization flag. @@ -25,6 +27,7 @@ impl Default for LinkCode { #[cfg(windows)] let linker = "clang"; Self { + current_dir: std::env::current_dir().unwrap(), linker_path: PathBuf::from(linker), optimization_flag: String::from("-O2"), object_paths: vec![], @@ -38,6 +41,7 @@ impl LinkCode { pub fn run(&self) -> anyhow::Result<()> { let mut command = Command::new(&self.linker_path); let command = command + .current_dir(&self.current_dir) .arg(&self.optimization_flag) .args( self.object_paths diff --git a/tests/integration/cli/src/util.rs b/tests/integration/cli/src/util.rs index 8cfcaae20..300067327 100644 --- a/tests/integration/cli/src/util.rs +++ b/tests/integration/cli/src/util.rs @@ -36,8 +36,13 @@ impl Engine { } } -pub fn run_code(executable_path: &Path, args: &[String]) -> anyhow::Result { +pub fn run_code( + operating_dir: &Path, + executable_path: &Path, + args: &[String], +) -> anyhow::Result { let output = Command::new(executable_path.canonicalize()?) + .current_dir(operating_dir) .args(args) .output()?; diff --git a/tests/integration/cli/tests/compile.rs b/tests/integration/cli/tests/compile.rs index fcbedc938..71fa6bd58 100644 --- a/tests/integration/cli/tests/compile.rs +++ b/tests/integration/cli/tests/compile.rs @@ -18,6 +18,8 @@ fn object_file_engine_test_wasm_path() -> String { /// Data used to run the `wasmer compile` command. #[derive(Debug)] struct WasmerCompile { + /// The directory to operate in. + current_dir: PathBuf, /// Path to wasmer executable used to run the command. wasmer_path: PathBuf, /// Path to the Wasm file to compile. @@ -39,6 +41,7 @@ impl Default for WasmerCompile { #[cfg(windows)] let wasm_obj_path = "wasm.obj"; Self { + current_dir: std::env::current_dir().unwrap(), wasmer_path: get_wasmer_path(), wasm_path: PathBuf::from(object_file_engine_test_wasm_path()), wasm_object_path: PathBuf::from(wasm_obj_path), @@ -52,6 +55,7 @@ impl Default for WasmerCompile { impl WasmerCompile { fn run(&self) -> anyhow::Result<()> { let output = Command::new(&self.wasmer_path) + .current_dir(&self.current_dir) .arg("compile") .arg(&self.wasm_path.canonicalize()?) .arg(&self.compiler.to_flag()) @@ -76,13 +80,18 @@ impl WasmerCompile { } /// Compile the C code. -fn run_c_compile(path_to_c_src: &Path, output_name: &Path) -> anyhow::Result<()> { +fn run_c_compile( + current_dir: &Path, + path_to_c_src: &Path, + output_name: &Path, +) -> anyhow::Result<()> { #[cfg(not(windows))] let c_compiler = "cc"; #[cfg(windows)] let c_compiler = "clang++"; let output = Command::new(c_compiler) + .current_dir(current_dir) .arg("-O2") .arg("-c") .arg(path_to_c_src) @@ -106,18 +115,18 @@ fn run_c_compile(path_to_c_src: &Path, output_name: &Path) -> anyhow::Result<()> #[test] fn object_file_engine_works() -> anyhow::Result<()> { - let operating_dir = tempfile::tempdir()?; + let temp_dir = tempfile::tempdir()?; + let operating_dir: PathBuf = temp_dir.path().to_owned(); - std::env::set_current_dir(&operating_dir)?; - - let wasm_path = PathBuf::from(object_file_engine_test_wasm_path()); + let wasm_path = operating_dir.join(object_file_engine_test_wasm_path()); #[cfg(not(windows))] - let wasm_object_path = PathBuf::from("wasm.o"); + let wasm_object_path = operating_dir.join("wasm.o"); #[cfg(windows)] - let wasm_object_path = PathBuf::from("wasm.obj"); - let header_output_path = PathBuf::from("my_wasm.h"); + let wasm_object_path = operating_dir.join("wasm.obj"); + let header_output_path = operating_dir.join("my_wasm.h"); WasmerCompile { + current_dir: operating_dir.clone(), wasm_path: wasm_path.clone(), wasm_object_path: wasm_object_path.clone(), header_output_path, @@ -128,12 +137,12 @@ fn object_file_engine_works() -> anyhow::Result<()> { .run() .context("Failed to compile wasm with Wasmer")?; - let c_src_file_name = Path::new("c_src.c"); + let c_src_file_name = operating_dir.join("c_src.c"); #[cfg(not(windows))] - let c_object_path = PathBuf::from("c_src.o"); + let c_object_path = operating_dir.join("c_src.o"); #[cfg(windows)] - let c_object_path = PathBuf::from("c_src.obj"); - let executable_path = PathBuf::from("a.out"); + let c_object_path = operating_dir.join("c_src.obj"); + let executable_path = operating_dir.join("a.out"); // TODO: adjust C source code based on locations of things { @@ -144,8 +153,10 @@ fn object_file_engine_works() -> anyhow::Result<()> { .context("Failed to open C source code file")?; c_src_file.write_all(OBJECT_FILE_ENGINE_TEST_C_SOURCE)?; } - run_c_compile(&c_src_file_name, &c_object_path).context("Failed to compile C source code")?; + run_c_compile(&operating_dir, &c_src_file_name, &c_object_path) + .context("Failed to compile C source code")?; LinkCode { + current_dir: operating_dir.clone(), object_paths: vec![c_object_path, wasm_object_path], output_path: executable_path.clone(), ..Default::default() @@ -153,7 +164,8 @@ fn object_file_engine_works() -> anyhow::Result<()> { .run() .context("Failed to link objects together")?; - let result = run_code(&executable_path, &[]).context("Failed to run generated executable")?; + let result = run_code(&operating_dir, &executable_path, &[]) + .context("Failed to run generated executable")?; let result_lines = result.lines().collect::>(); assert_eq!(result_lines, vec!["Initializing...", "\"Hello, World\""],); diff --git a/tests/integration/cli/tests/create_exe.rs b/tests/integration/cli/tests/create_exe.rs index 2af9e390f..ec2eb54ff 100644 --- a/tests/integration/cli/tests/create_exe.rs +++ b/tests/integration/cli/tests/create_exe.rs @@ -1,6 +1,8 @@ //! Tests of the `wasmer create-exe` command. use anyhow::{bail, Context}; +use std::fs; +use std::io::prelude::*; use std::path::PathBuf; use std::process::Command; use wasmer_integration_tests_cli::*; @@ -8,10 +10,14 @@ use wasmer_integration_tests_cli::*; fn create_exe_test_wasm_path() -> String { format!("{}/{}", ASSET_PATH, "qjs.wasm") } +const JS_TEST_SRC_CODE: &[u8] = + b"function greet(name) { return JSON.stringify('Hello, ' + name); }; print(greet('World'));\n"; /// Data used to run the `wasmer compile` command. #[derive(Debug)] struct WasmerCreateExe { + /// The directory to operate in. + current_dir: PathBuf, /// Path to wasmer executable used to run the command. wasmer_path: PathBuf, /// Path to the Wasm file to compile. @@ -29,6 +35,7 @@ impl Default for WasmerCreateExe { #[cfg(windows)] let native_executable_path = PathBuf::from("wasm.exe"); Self { + current_dir: std::env::current_dir().unwrap(), wasmer_path: get_wasmer_path(), wasm_path: PathBuf::from(create_exe_test_wasm_path()), native_executable_path, @@ -40,6 +47,7 @@ impl Default for WasmerCreateExe { impl WasmerCreateExe { fn run(&self) -> anyhow::Result<()> { let output = Command::new(&self.wasmer_path) + .current_dir(&self.current_dir) .arg("create-exe") .arg(&self.wasm_path.canonicalize()?) .arg(&self.compiler.to_flag()) @@ -64,17 +72,17 @@ impl WasmerCreateExe { #[test] fn create_exe_works() -> anyhow::Result<()> { - let operating_dir = tempfile::tempdir()?; + let temp_dir = tempfile::tempdir()?; + let operating_dir: PathBuf = temp_dir.path().to_owned(); - std::env::set_current_dir(&operating_dir)?; - - let wasm_path = PathBuf::from(create_exe_test_wasm_path()); + let wasm_path = operating_dir.join(create_exe_test_wasm_path()); #[cfg(not(windows))] - let executable_path = PathBuf::from("wasm.out"); + let executable_path = operating_dir.join("wasm.out"); #[cfg(windows)] - let executable_path = PathBuf::from("wasm.exe"); + let executable_path = operating_dir.join("wasm.exe"); WasmerCreateExe { + current_dir: operating_dir.clone(), wasm_path: wasm_path.clone(), native_executable_path: executable_path.clone(), compiler: Compiler::Cranelift, @@ -84,12 +92,73 @@ fn create_exe_works() -> anyhow::Result<()> { .context("Failed to create-exe wasm with Wasmer")?; let result = run_code( + &operating_dir, &executable_path, &["--eval".to_string(), "function greet(name) { return JSON.stringify('Hello, ' + name); }; print(greet('World'));".to_string()], ) .context("Failed to run generated executable")?; let result_lines = result.lines().collect::>(); - assert_eq!(result_lines, vec!["Initializing...", "\"Hello, World\""],); + assert_eq!(result_lines, vec!["\"Hello, World\""],); + + Ok(()) +} + +#[test] +fn create_exe_works_with_file() -> anyhow::Result<()> { + let temp_dir = tempfile::tempdir()?; + let operating_dir: PathBuf = temp_dir.path().to_owned(); + + let wasm_path = operating_dir.join(create_exe_test_wasm_path()); + #[cfg(not(windows))] + let executable_path = operating_dir.join("wasm.out"); + #[cfg(windows)] + let executable_path = operating_dir.join("wasm.exe"); + + WasmerCreateExe { + current_dir: operating_dir.clone(), + wasm_path: wasm_path.clone(), + native_executable_path: executable_path.clone(), + compiler: Compiler::Cranelift, + ..Default::default() + } + .run() + .context("Failed to create-exe wasm with Wasmer")?; + + { + let mut f = fs::OpenOptions::new() + .write(true) + .create_new(true) + .open(operating_dir.join("test.js"))?; + f.write_all(JS_TEST_SRC_CODE)?; + } + + // test with `--dir` + let result = run_code( + &operating_dir, + &executable_path, + &[ + "--dir=.".to_string(), + "--script".to_string(), + "test.js".to_string(), + ], + ) + .context("Failed to run generated executable")?; + let result_lines = result.lines().collect::>(); + assert_eq!(result_lines, vec!["\"Hello, World\""],); + + // test with `--mapdir` + let result = run_code( + &operating_dir, + &executable_path, + &[ + "--mapdir=abc:.".to_string(), + "--script".to_string(), + "abc/test.js".to_string(), + ], + ) + .context("Failed to run generated executable")?; + let result_lines = result.lines().collect::>(); + assert_eq!(result_lines, vec!["\"Hello, World\""],); Ok(()) } From 82aea12849a664006904cc15333e8f1d9d762898 Mon Sep 17 00:00:00 2001 From: Nick Lewycky Date: Mon, 12 Oct 2020 15:34:27 -0700 Subject: [PATCH 231/281] Export the VM functions when building on ARM. This is needed to be able to run engine-native built object files on aarch64 linux. --- .cargo/config.toml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.cargo/config.toml b/.cargo/config.toml index d703a1426..40da867bb 100644 --- a/.cargo/config.toml +++ b/.cargo/config.toml @@ -2,3 +2,8 @@ rustflags = [ "-C", "link-arg=-Wl,-E" ] + +[target.aarch64-unknown-linux-gnu] +rustflags = [ + "-C", "link-arg=-Wl,-E" +] From 331ff2b0d11b6f9e598fd2f23373e4adb03d32da Mon Sep 17 00:00:00 2001 From: Nick Lewycky Date: Mon, 12 Oct 2020 15:39:51 -0700 Subject: [PATCH 232/281] Update the commented-out code to run tests with engine-native. --- tests/compilers/utils.rs | 5 +++++ tests/compilers/wast.rs | 15 +++++---------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/tests/compilers/utils.rs b/tests/compilers/utils.rs index 8bcbfb419..5470b23c6 100644 --- a/tests/compilers/utils.rs +++ b/tests/compilers/utils.rs @@ -3,6 +3,7 @@ use wasmer::{FunctionMiddlewareGenerator, Store}; use wasmer_compiler::CompilerConfig; use wasmer_engine::Engine; use wasmer_engine_jit::JIT; +// use wasmer_engine_native::Native; pub fn get_compiler(canonicalize_nans: bool) -> impl CompilerConfig { cfg_if::cfg_if! { @@ -35,6 +36,8 @@ pub fn get_compiler(canonicalize_nans: bool) -> impl CompilerConfig { pub fn get_engine() -> impl Engine { let compiler_config = get_compiler(false); JIT::new(&compiler_config).engine() + // let mut compiler_config = get_compiler(false); + // Native::new(&mut compiler_config).engine() } pub fn get_store() -> Store { @@ -49,9 +52,11 @@ pub fn get_store_with_middlewares Store { Store::new(&JIT::headless().engine()) + // Store::new(&Native::headless().engine()) } diff --git a/tests/compilers/wast.rs b/tests/compilers/wast.rs index 82a83dd59..8a43af147 100644 --- a/tests/compilers/wast.rs +++ b/tests/compilers/wast.rs @@ -6,7 +6,7 @@ use wasmer::{Features, Store}; #[cfg(feature = "jit")] use wasmer_engine_jit::JIT; // #[cfg(feature = "native")] -// use wasmer_engine_native::NativeEngine; +// use wasmer_engine_native::Native; use wasmer_wast::Wast; // The generated tests (from build.rs) look like: @@ -21,13 +21,6 @@ use wasmer_wast::Wast; // } include!(concat!(env!("OUT_DIR"), "/generated_spectests.rs")); -// This prefixer returns the hash of the module to prefix each of -// the functions in the shared object generated by the `NativeEngine`. -fn _native_prefixer(bytes: &[u8]) -> String { - let hash = blake3::hash(bytes); - format!("{}", hash.to_hex()) -} - pub fn run_wast(wast_path: &str, compiler: &str) -> anyhow::Result<()> { println!( "Running wast `{}` with the {} compiler", @@ -47,8 +40,10 @@ pub fn run_wast(wast_path: &str, compiler: &str) -> anyhow::Result<()> { features.multi_value(false); let compiler_config = get_compiler(try_nan_canonicalization); let store = Store::new(&JIT::new(&compiler_config).features(features).engine()); - // let mut native = NativeEngine::new(compiler_config, tunables); - // native.set_deterministic_prefixer(native_prefixer); + // let mut compiler_config = compiler_config; + // let native = Native::new(&mut compiler_config) + // .features(features) + // .engine(); // let store = Store::new(&native); let mut wast = Wast::new_with_spectest(store); if is_simd { From d4c92c3aaf65d1f7afe000a7f83184fbed70fe01 Mon Sep 17 00:00:00 2001 From: Nick Lewycky Date: Mon, 12 Oct 2020 15:45:34 -0700 Subject: [PATCH 233/281] Restore this function. --- tests/compilers/wast.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/tests/compilers/wast.rs b/tests/compilers/wast.rs index 8a43af147..726d0590b 100644 --- a/tests/compilers/wast.rs +++ b/tests/compilers/wast.rs @@ -21,6 +21,13 @@ use wasmer_wast::Wast; // } include!(concat!(env!("OUT_DIR"), "/generated_spectests.rs")); +// This prefixer returns the hash of the module to prefix each of +// the functions in the shared object generated by the `NativeEngine`. +fn _native_prefixer(bytes: &[u8]) -> String { + let hash = blake3::hash(bytes); + format!("{}", hash.to_hex()) +} + pub fn run_wast(wast_path: &str, compiler: &str) -> anyhow::Result<()> { println!( "Running wast `{}` with the {} compiler", From a36d6ede282f0726168391d70956a3425f3a38e7 Mon Sep 17 00:00:00 2001 From: Nick Lewycky Date: Mon, 12 Oct 2020 15:50:12 -0700 Subject: [PATCH 234/281] Generalize this for all CPUs. --- .cargo/config.toml | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/.cargo/config.toml b/.cargo/config.toml index 40da867bb..5ae061b86 100644 --- a/.cargo/config.toml +++ b/.cargo/config.toml @@ -1,9 +1,4 @@ -[target.x86_64-unknown-linux-gnu] -rustflags = [ - "-C", "link-arg=-Wl,-E" -] - -[target.aarch64-unknown-linux-gnu] +[target.'cfg(target_os = "linux")'] rustflags = [ "-C", "link-arg=-Wl,-E" ] From 81fd4fc0426bebaec6a5a70d55e2b82f3fb6327a Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Mon, 12 Oct 2020 15:53:46 -0700 Subject: [PATCH 235/281] Clean create-exe code a bit --- Makefile | 1 + lib/cli/src/commands/create_exe.rs | 54 ++++++++++--------- lib/cli/src/commands/wasmer_create_exe_main.c | 2 +- tests/integration/cli/src/link_code.rs | 3 +- tests/integration/cli/tests/create_exe.rs | 2 - 5 files changed, 32 insertions(+), 30 deletions(-) diff --git a/Makefile b/Makefile index 8d07bf70c..dd39c5afc 100644 --- a/Makefile +++ b/Makefile @@ -166,6 +166,7 @@ package-capi: mkdir -p "package/include" mkdir -p "package/lib" cp lib/c-api/wasmer.h* package/include + cp lib/c-api/wasm.h* package/include cp lib/c-api/doc/index.md package/include/README.md ifeq ($(OS), Windows_NT) cp target/release/wasmer_c_api.dll package/lib diff --git a/lib/cli/src/commands/create_exe.rs b/lib/cli/src/commands/create_exe.rs index 3caa57944..d4893e947 100644 --- a/lib/cli/src/commands/create_exe.rs +++ b/lib/cli/src/commands/create_exe.rs @@ -11,9 +11,6 @@ use wasmer::*; const WASMER_MAIN_C_SOURCE: &[u8] = include_bytes!("wasmer_create_exe_main.c"); -// TODO: to get this working locally I had to add wasmer_wasm.h and wasm.h to `.wasmer/include` manually. -// this needs to be fixed before we can ship this. - #[derive(Debug, StructOpt)] /// The options for the `wasmer create-exe` subcommand pub struct CreateExe { @@ -73,8 +70,6 @@ impl CreateExe { let output_path = starting_cd.join(&self.output); env::set_current_dir(&working_dir)?; - // TODO: encapsulate compile code - #[cfg(not(windows))] let wasm_object_path = PathBuf::from("wasm.o"); #[cfg(windows)] @@ -82,7 +77,6 @@ impl CreateExe { let wasm_module_path = starting_cd.join(&self.path); - let header_file_path = Path::new("my_wasm.h"); let module = Module::from_file(&store, &wasm_module_path).context("failed to compile Wasm")?; let _ = module.serialize_to_file(&wasm_object_path)?; @@ -100,19 +94,19 @@ impl CreateExe { metadata_length, ); - let header_path = header_file_path.clone(); - // for C code - let mut header = std::fs::OpenOptions::new() - .create(true) - .truncate(true) - .write(true) - .open(&header_path)?; + generate_header(header_file_src.as_bytes())?; + self.compile_c(wasm_object_path, output_path)?; + eprintln!( + "✔ Native executable compiled successfully to `{}`.", + self.output.display(), + ); + + Ok(()) + } + + fn compile_c(&self, wasm_object_path: PathBuf, output_path: PathBuf) -> anyhow::Result<()> { use std::io::Write; - header.write(header_file_src.as_bytes())?; - - // auto compilation - // // write C src to disk let c_src_path = Path::new("wasmer_main.c"); @@ -127,7 +121,6 @@ impl CreateExe { .write(true) .open(&c_src_path) .context("Failed to open C source code file")?; - // TODO: c_src_file.write_all(WASMER_MAIN_C_SOURCE)?; } run_c_compile(&c_src_path, &c_src_obj, self.target_triple.clone()) @@ -142,15 +135,24 @@ impl CreateExe { .run() .context("Failed to link objects together")?; - eprintln!( - "✔ Native executable compiled successfully to `{}`.", - self.output.display(), - ); - Ok(()) } } +fn generate_header(header_file_src: &[u8]) -> anyhow::Result<()> { + let header_file_path = Path::new("my_wasm.h"); + let mut header = std::fs::OpenOptions::new() + .create(true) + .truncate(true) + .write(true) + .open(&header_file_path)?; + + use std::io::Write; + header.write(header_file_src)?; + + Ok(()) +} + fn get_wasmer_dir() -> anyhow::Result { Ok(PathBuf::from( env::var("WASMER_DIR").context("Trying to read env var `WASMER_DIR`")?, @@ -168,6 +170,7 @@ fn get_libwasmer_path() -> anyhow::Result { let mut path = get_wasmer_dir()?; path.push("lib"); + // TODO: prefer headless Wasmer if/when it's a separate library. #[cfg(not(windows))] path.push("libwasmer.a"); #[cfg(windows)] @@ -253,8 +256,6 @@ impl Default for LinkCode { } impl LinkCode { - // TODO: `wasmer create-exe` needs a command line flag for extra libraries to link aganist - // or perhaps we just want to add a flag for passing things to the linker fn run(&self) -> anyhow::Result<()> { let mut command = Command::new(&self.linker_path); let command = command @@ -275,8 +276,11 @@ impl LinkCode { } else { command }; + // Add libraries required per platform. + // We need userenv, sockets (Ws2_32), and advapi32 to call a system call (for random numbers I think). #[cfg(windows)] let command = command.arg("-luserenv").arg("-lWs2_32").arg("-ladvapi32"); + // On unix we need dlopen-related symbols, libmath for a few things, and pthreads. #[cfg(not(windows))] let command = command.arg("-ldl").arg("-lm").arg("-pthread"); let link_aganist_extra_libs = self diff --git a/lib/cli/src/commands/wasmer_create_exe_main.c b/lib/cli/src/commands/wasmer_create_exe_main.c index be7936731..11adb1656 100644 --- a/lib/cli/src/commands/wasmer_create_exe_main.c +++ b/lib/cli/src/commands/wasmer_create_exe_main.c @@ -111,7 +111,7 @@ int main(int argc, char* argv[]) { wasm_engine_t* engine = wasm_engine_new_with_config(config); wasm_store_t* store = wasm_store_new(engine); - wasm_module_t* module = wasmer_object_file_engine_new(store, "qjs.wasm"); + wasm_module_t* module = wasmer_object_file_engine_new(store, argv[0]); if (! module) { fprintf(stderr, "Failed to create module\n"); print_wasmer_error(); diff --git a/tests/integration/cli/src/link_code.rs b/tests/integration/cli/src/link_code.rs index d900f3e66..3dce23635 100644 --- a/tests/integration/cli/src/link_code.rs +++ b/tests/integration/cli/src/link_code.rs @@ -52,8 +52,7 @@ impl LinkCode { #[cfg(windows)] let command = command.arg("-luserenv").arg("-lWs2_32").arg("-ladvapi32"); #[cfg(not(windows))] - // TODO: remove `-lffi` before shipping - let command = command.arg("-ldl").arg("-lm").arg("-pthread").arg("-lffi"); + let command = command.arg("-ldl").arg("-lm").arg("-pthread"); let output = command.arg("-o").arg(&self.output_path).output()?; if !output.status.success() { diff --git a/tests/integration/cli/tests/create_exe.rs b/tests/integration/cli/tests/create_exe.rs index ec2eb54ff..b8302bccd 100644 --- a/tests/integration/cli/tests/create_exe.rs +++ b/tests/integration/cli/tests/create_exe.rs @@ -51,8 +51,6 @@ impl WasmerCreateExe { .arg("create-exe") .arg(&self.wasm_path.canonicalize()?) .arg(&self.compiler.to_flag()) - // TODO: remove before shipping - .arg("-lffi") .arg("-o") .arg(&self.native_executable_path) .output()?; From d51cff62bdb426317ac7b035f721d63e369d2af4 Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Mon, 12 Oct 2020 15:59:27 -0700 Subject: [PATCH 236/281] Fix merge issue caused by GitHub UI --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index f213bb2f6..106e2781c 100644 --- a/Makefile +++ b/Makefile @@ -174,7 +174,7 @@ package-capi: mkdir -p "package/include" mkdir -p "package/lib" cp lib/c-api/wasmer.h* package/include - cp lib/c-api/wasmer_wasm.h* package/include + cp lib/c-api/wasmer_wasm.h* package/include cp lib/c-api/wasm.h* package/include cp lib/c-api/doc/deprecated/index.md package/include/README.md ifeq ($(OS), Windows_NT) From e430bbaf4f1ad8ee54b14faa17b9775fc6e3907d Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Mon, 12 Oct 2020 16:17:34 -0700 Subject: [PATCH 237/281] More explicitly feature gate `wasmer create-exe` --- lib/cli/src/bin/wasmer.rs | 4 ++-- lib/cli/src/commands.rs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/cli/src/bin/wasmer.rs b/lib/cli/src/bin/wasmer.rs index 6d72964bf..7c7496413 100644 --- a/lib/cli/src/bin/wasmer.rs +++ b/lib/cli/src/bin/wasmer.rs @@ -1,5 +1,5 @@ use anyhow::Result; -#[cfg(feature = "object-file")] +#[cfg(all(feature = "object-file", feature = "compiler"))] use wasmer_cli::commands::CreateExe; #[cfg(feature = "wast")] use wasmer_cli::commands::Wast; @@ -60,7 +60,7 @@ impl WasmerCLIOptions { Self::Cache(cache) => cache.execute(), Self::Validate(validate) => validate.execute(), Self::Compile(compile) => compile.execute(), - #[cfg(feature = "object-file")] + #[cfg(all(feature = "object-file", feature = "compiler"))] Self::CreateExe(create_exe) => create_exe.execute(), Self::Config(config) => config.execute(), Self::Inspect(inspect) => inspect.execute(), diff --git a/lib/cli/src/commands.rs b/lib/cli/src/commands.rs index 4d07c37e8..7107150cc 100644 --- a/lib/cli/src/commands.rs +++ b/lib/cli/src/commands.rs @@ -2,7 +2,7 @@ mod cache; mod compile; mod config; -#[cfg(feature = "object-file")] +#[cfg(all(feature = "object-file", feature = "compiler"))] mod create_exe; mod inspect; mod run; @@ -11,7 +11,7 @@ mod validate; #[cfg(feature = "wast")] mod wast; -#[cfg(feature = "object-file")] +#[cfg(all(feature = "object-file", feature = "compiler"))] pub use create_exe::*; #[cfg(feature = "wast")] pub use wast::*; From fc11c1006339a63d65764a3a40af27cfcc84929a Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Mon, 12 Oct 2020 16:25:40 -0700 Subject: [PATCH 238/281] Add comment about why Windows is using clang++ --- lib/cli/src/commands/create_exe.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/cli/src/commands/create_exe.rs b/lib/cli/src/commands/create_exe.rs index d4893e947..62b9a42bd 100644 --- a/lib/cli/src/commands/create_exe.rs +++ b/lib/cli/src/commands/create_exe.rs @@ -187,6 +187,8 @@ fn run_c_compile( ) -> anyhow::Result<()> { #[cfg(not(windows))] let c_compiler = "cc"; + // We must use a C++ compiler on Windows because wasm.h uses `static_assert` + // which isn't available in `clang` on Windows. #[cfg(windows)] let c_compiler = "clang++"; From aeb17cda6a1dbfb5b571429a55bd22b0f34340a9 Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Mon, 12 Oct 2020 16:30:13 -0700 Subject: [PATCH 239/281] Fix cfg logic in wasmer.rs again --- lib/cli/src/bin/wasmer.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/cli/src/bin/wasmer.rs b/lib/cli/src/bin/wasmer.rs index 7c7496413..509bbdede 100644 --- a/lib/cli/src/bin/wasmer.rs +++ b/lib/cli/src/bin/wasmer.rs @@ -29,7 +29,7 @@ enum WasmerCLIOptions { Compile(Compile), /// Compile a WebAssembly binary into a native executable - #[cfg(feature = "object-file")] + #[cfg(all(feature = "object-file", feature = "compiler"))] #[structopt(name = "create-exe")] CreateExe(CreateExe), From d737ad7d9f2bc11ba93b223603c5aade4b3dbace Mon Sep 17 00:00:00 2001 From: Nick Lewycky Date: Mon, 12 Oct 2020 16:46:47 -0700 Subject: [PATCH 240/281] Add the ability to run tests with either jit or native. Don't actually make `make test` run them with native though, it doesn't pass yet. --- Cargo.toml | 7 +++++++ Makefile | 24 +++++++++++++++++------- tests/compilers/utils.rs | 22 +++++++++++++++++++--- tests/compilers/wast.rs | 26 ++++++++++++++++---------- 4 files changed, 59 insertions(+), 20 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index dafadf68b..666d015e4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -129,6 +129,13 @@ test-llvm = [ "llvm", ] +test-native = [ + "native", +] +test-jit = [ + "jit", +] + # Disable trap asserts in the WAST tests. This is useful for running the tests in a # context where signal handling is a problem, such as tarpaulin for code coverage. test-no-traps = ["wasmer-wast/test-no-traps"] diff --git a/Makefile b/Makefile index 99a38fd98..2155fdb11 100644 --- a/Makefile +++ b/Makefile @@ -94,16 +94,26 @@ build-capi-llvm: # Testing # ########### -test: $(foreach compiler,$(compilers),test-$(compiler)) test-packages test-examples test-deprecated +test: $(foreach compiler,$(compilers),test-$(compiler)-jit) test-packages test-examples test-deprecated -test-singlepass: - cargo test --release $(compiler_features) --features "test-singlepass" +# Singlepass and native engine don't work together, this rule does nothing. +test-singlepass-native: + @: -test-cranelift: - cargo test --release $(compiler_features) --features "test-cranelift" +test-singlepass-jit: + cargo test --release $(compiler_features) --features "test-singlepass test-jit" -test-llvm: - cargo test --release $(compiler_features) --features "test-llvm" +test-cranelift-native: + cargo test --release $(compiler_features) --features "test-cranelift test-native" + +test-cranelift-jit: + cargo test --release $(compiler_features) --features "test-cranelift test-jit" + +test-llvm-native: + cargo test --release $(compiler_features) --features "test-llvm test-native" + +test-llvm-jit: + cargo test --release $(compiler_features) --features "test-llvm test-jit" test-packages: cargo test -p wasmer --release diff --git a/tests/compilers/utils.rs b/tests/compilers/utils.rs index 5470b23c6..b08163fec 100644 --- a/tests/compilers/utils.rs +++ b/tests/compilers/utils.rs @@ -2,8 +2,10 @@ use std::sync::Arc; use wasmer::{FunctionMiddlewareGenerator, Store}; use wasmer_compiler::CompilerConfig; use wasmer_engine::Engine; +#[cfg(feature = "test-jit")] use wasmer_engine_jit::JIT; -// use wasmer_engine_native::Native; +#[cfg(feature = "test-native")] +use wasmer_engine_native::Native; pub fn get_compiler(canonicalize_nans: bool) -> impl CompilerConfig { cfg_if::cfg_if! { @@ -33,12 +35,18 @@ pub fn get_compiler(canonicalize_nans: bool) -> impl CompilerConfig { } } -pub fn get_engine() -> impl Engine { +#[cfg(feature = "test-jit")] + pub fn get_engine() -> impl Engine { let compiler_config = get_compiler(false); JIT::new(&compiler_config).engine() // let mut compiler_config = get_compiler(false); // Native::new(&mut compiler_config).engine() } +#[cfg(feature = "test-native")] + pub fn get_engine() -> impl Engine { + let mut compiler_config = get_compiler(false); + Native::new(&mut compiler_config).engine() +} pub fn get_store() -> Store { Store::new(&get_engine()) @@ -51,12 +59,20 @@ pub fn get_store_with_middlewares Store { Store::new(&JIT::headless().engine()) // Store::new(&Native::headless().engine()) } + +#[cfg(feature = "test-native")] +pub fn get_headless_store() -> Store { + Store::new(&Native::headless().engine()) +} diff --git a/tests/compilers/wast.rs b/tests/compilers/wast.rs index 726d0590b..f200209e8 100644 --- a/tests/compilers/wast.rs +++ b/tests/compilers/wast.rs @@ -3,10 +3,10 @@ use crate::utils::get_compiler; use std::path::Path; use wasmer::{Features, Store}; -#[cfg(feature = "jit")] +#[cfg(feature = "test-jit")] use wasmer_engine_jit::JIT; -// #[cfg(feature = "native")] -// use wasmer_engine_native::Native; + #[cfg(feature = "test-native")] +use wasmer_engine_native::Native; use wasmer_wast::Wast; // The generated tests (from build.rs) look like: @@ -28,6 +28,18 @@ fn _native_prefixer(bytes: &[u8]) -> String { format!("{}", hash.to_hex()) } +#[cfg(feature = "test-jit")] +fn get_store(features: Features, try_nan_canonicalization: bool) -> Store { + let compiler_config = get_compiler(try_nan_canonicalization); + Store::new(&JIT::new(&compiler_config).features(features).engine()) +} + +#[cfg(feature = "test-native")] +fn get_store(features: Features, try_nan_canonicalization: bool) -> Store { + let mut compiler_config = get_compiler(try_nan_canonicalization); + Store::new(&Native::new(&mut compiler_config).features(features).engine()) +} + pub fn run_wast(wast_path: &str, compiler: &str) -> anyhow::Result<()> { println!( "Running wast `{}` with the {} compiler", @@ -45,13 +57,7 @@ pub fn run_wast(wast_path: &str, compiler: &str) -> anyhow::Result<()> { } #[cfg(feature = "test-singlepass")] features.multi_value(false); - let compiler_config = get_compiler(try_nan_canonicalization); - let store = Store::new(&JIT::new(&compiler_config).features(features).engine()); - // let mut compiler_config = compiler_config; - // let native = Native::new(&mut compiler_config) - // .features(features) - // .engine(); - // let store = Store::new(&native); + let store = get_store(features, try_nan_canonicalization); let mut wast = Wast::new_with_spectest(store); if is_simd { // We allow this, so tests can be run properly for `simd_const` test. From 344d082171d98323ddd8ade011dcce770ecc30ff Mon Sep 17 00:00:00 2001 From: Nick Lewycky Date: Mon, 12 Oct 2020 16:53:01 -0700 Subject: [PATCH 241/281] cargo fmt --- tests/compilers/utils.rs | 4 ++-- tests/compilers/wast.rs | 8 ++++++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/tests/compilers/utils.rs b/tests/compilers/utils.rs index b08163fec..1c0ede605 100644 --- a/tests/compilers/utils.rs +++ b/tests/compilers/utils.rs @@ -36,14 +36,14 @@ pub fn get_compiler(canonicalize_nans: bool) -> impl CompilerConfig { } #[cfg(feature = "test-jit")] - pub fn get_engine() -> impl Engine { +pub fn get_engine() -> impl Engine { let compiler_config = get_compiler(false); JIT::new(&compiler_config).engine() // let mut compiler_config = get_compiler(false); // Native::new(&mut compiler_config).engine() } #[cfg(feature = "test-native")] - pub fn get_engine() -> impl Engine { +pub fn get_engine() -> impl Engine { let mut compiler_config = get_compiler(false); Native::new(&mut compiler_config).engine() } diff --git a/tests/compilers/wast.rs b/tests/compilers/wast.rs index f200209e8..1471a990a 100644 --- a/tests/compilers/wast.rs +++ b/tests/compilers/wast.rs @@ -5,7 +5,7 @@ use std::path::Path; use wasmer::{Features, Store}; #[cfg(feature = "test-jit")] use wasmer_engine_jit::JIT; - #[cfg(feature = "test-native")] +#[cfg(feature = "test-native")] use wasmer_engine_native::Native; use wasmer_wast::Wast; @@ -37,7 +37,11 @@ fn get_store(features: Features, try_nan_canonicalization: bool) -> Store { #[cfg(feature = "test-native")] fn get_store(features: Features, try_nan_canonicalization: bool) -> Store { let mut compiler_config = get_compiler(try_nan_canonicalization); - Store::new(&Native::new(&mut compiler_config).features(features).engine()) + Store::new( + &Native::new(&mut compiler_config) + .features(features) + .engine(), + ) } pub fn run_wast(wast_path: &str, compiler: &str) -> anyhow::Result<()> { From 84c140ecd8d47f9cb360eb5095933649b8022b50 Mon Sep 17 00:00:00 2001 From: Nick Lewycky Date: Mon, 12 Oct 2020 16:56:58 -0700 Subject: [PATCH 242/281] Remove dead code. --- tests/compilers/utils.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/tests/compilers/utils.rs b/tests/compilers/utils.rs index 1c0ede605..675240b32 100644 --- a/tests/compilers/utils.rs +++ b/tests/compilers/utils.rs @@ -39,8 +39,6 @@ pub fn get_compiler(canonicalize_nans: bool) -> impl CompilerConfig { pub fn get_engine() -> impl Engine { let compiler_config = get_compiler(false); JIT::new(&compiler_config).engine() - // let mut compiler_config = get_compiler(false); - // Native::new(&mut compiler_config).engine() } #[cfg(feature = "test-native")] pub fn get_engine() -> impl Engine { From 7cf1e124ceaa00c7832585ee8722db9f09dd25a1 Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Mon, 12 Oct 2020 17:21:34 -0700 Subject: [PATCH 243/281] Attempt to fake install Wasmer for integration tests --- .github/workflows/main.yaml | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/.github/workflows/main.yaml b/.github/workflows/main.yaml index 9318e1094..333df8c69 100644 --- a/.github/workflows/main.yaml +++ b/.github/workflows/main.yaml @@ -150,19 +150,23 @@ jobs: run: | make build-wapm if: needs.setup.outputs.DOING_RELEASE == '1' + - name: Package Wasmer + run: | + make package - name: Run integration tests (Windows) shell: cmd run: | call refreshenv + cd dist + wasmer-windows.exe + cd .. make test-integration if: matrix.run_integration_tests && matrix.os == 'windows-latest' - name: Run integration tests (Unix) - run: make test-integration - if: matrix.run_integration_tests && matrix.os != 'windows-latest' - - name: Package Wasmer run: | - make package - if: needs.setup.outputs.DOING_RELEASE == '1' + export WASMER_DIR=`pwd`/package + make test-integration + if: matrix.run_integration_tests && matrix.os != 'windows-latest' - name: Upload Artifacts uses: actions/upload-artifact@v2 if: needs.setup.outputs.DOING_RELEASE == '1' From f336ac13caf61bb8608d97035316687bd30b0f7a Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Mon, 12 Oct 2020 17:30:36 -0700 Subject: [PATCH 244/281] Lie to Windows about installation of Wasmer for tests too --- .github/workflows/main.yaml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/.github/workflows/main.yaml b/.github/workflows/main.yaml index 333df8c69..8b2ce3165 100644 --- a/.github/workflows/main.yaml +++ b/.github/workflows/main.yaml @@ -157,9 +157,7 @@ jobs: shell: cmd run: | call refreshenv - cd dist - wasmer-windows.exe - cd .. + setx WASMER_DIR "%CD%/package" make test-integration if: matrix.run_integration_tests && matrix.os == 'windows-latest' - name: Run integration tests (Unix) From 30d34f1b5f2b52d8654a00858700a21c07024e69 Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Mon, 12 Oct 2020 18:02:10 -0700 Subject: [PATCH 245/281] Package wasmer without wapm for integration tests --- .github/workflows/main.yaml | 4 ++++ Makefile | 3 +++ 2 files changed, 7 insertions(+) diff --git a/.github/workflows/main.yaml b/.github/workflows/main.yaml index 8b2ce3165..246d93682 100644 --- a/.github/workflows/main.yaml +++ b/.github/workflows/main.yaml @@ -150,9 +150,13 @@ jobs: run: | make build-wapm if: needs.setup.outputs.DOING_RELEASE == '1' + - name: Package Wasmer for integration tests + run: make package-without-wapm-for-integration-tests + if: needs.setup.outputs.DOING_RELEASE != '1' - name: Package Wasmer run: | make package + if: needs.setup.outputs.DOING_RELEASE == '1' - name: Run integration tests (Windows) shell: cmd run: | diff --git a/Makefile b/Makefile index 106e2781c..d79280cc3 100644 --- a/Makefile +++ b/Makefile @@ -214,6 +214,9 @@ else cp ./wasmer.tar.gz ./dist/$(shell ./scripts/binary-name.sh) endif +# command for simulating installing Wasmer without wapm. +package-without-wapm-for-integration-tests: package-wasmer package-capi + ################# # Miscellaneous # ################# From 2a448ba1173661e96fe3a7b9480bbc65179a9d88 Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Tue, 13 Oct 2020 10:08:56 +0200 Subject: [PATCH 246/281] doc(changelog) Add #1709. --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 41c7a1d46..6041ead00 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ ## **[Unreleased]** +- [#1709](https://github.com/wasmerio/wasmer/pull/1709) Implement `wasm_module_name` and `wasm_module_set_name` in the Wasm(er) C API. - [#1700](https://github.com/wasmerio/wasmer/pull/1700) Implement `wasm_externtype_copy` in the Wasm C API. ## 1.0.0-alpha4 - 2020-10-08 From 373b7a48154bce6f265907730a41fb11ba03df5f Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Tue, 13 Oct 2020 10:10:27 +0200 Subject: [PATCH 247/281] doc(changelog) Fix merge. --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d0bedf03e..edba3e674 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,9 +7,9 @@ ## **[Unreleased]** -- [#1709](https://github.com/wasmerio/wasmer/pull/1709) Implement `wasm_module_name` and `wasm_module_set_name` in the Wasm(er) C API. ### Added +- [#1709](https://github.com/wasmerio/wasmer/pull/1709) Implement `wasm_module_name` and `wasm_module_set_name` in the Wasm(er) C API. - [#1700](https://github.com/wasmerio/wasmer/pull/1700) Implement `wasm_externtype_copy` in the Wasm C API. ## 1.0.0-alpha4 - 2020-10-08 From 954e5e849518204aa814eecd555ab4935b9ecf50 Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Tue, 13 Oct 2020 10:26:32 +0200 Subject: [PATCH 248/281] fix(c-api) Register errors from `wasm_module_serialize`. --- lib/c-api/src/wasm_c_api/module.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/c-api/src/wasm_c_api/module.rs b/lib/c-api/src/wasm_c_api/module.rs index 6e334097b..dca2d6e3f 100644 --- a/lib/c-api/src/wasm_c_api/module.rs +++ b/lib/c-api/src/wasm_c_api/module.rs @@ -108,7 +108,10 @@ pub unsafe extern "C" fn wasm_module_serialize( ) { let byte_vec = match module.inner.serialize() { Ok(byte_vec) => byte_vec, - Err(_) => return, + Err(err) => { + crate::error::update_last_error(err); + return; + } }; *out_ptr = byte_vec.into(); } From 0dc74bf922a74a77172db027cb51a137805af182 Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Tue, 13 Oct 2020 10:29:52 +0200 Subject: [PATCH 249/281] doc(changelog) Add #1715. --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 74d19d04d..ce2676920 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ ### Added +- [#1715](https://github.com/wasmerio/wasmer/pull/1715) Register errors from `wasm_module_serialize` in the Wasm C API. - [#1700](https://github.com/wasmerio/wasmer/pull/1700) Implement `wasm_externtype_copy` in the Wasm C API. ## 1.0.0-alpha4 - 2020-10-08 From 7cc4d5adbe07a712bf57a4fef5a36e976f85e809 Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Tue, 13 Oct 2020 10:49:38 +0200 Subject: [PATCH 250/281] fix(c-api) Simplify `NonNull` by `&T`. --- lib/c-api/src/wasm_c_api/types/value.rs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/lib/c-api/src/wasm_c_api/types/value.rs b/lib/c-api/src/wasm_c_api/types/value.rs index 023539c36..dbb4b3a4d 100644 --- a/lib/c-api/src/wasm_c_api/types/value.rs +++ b/lib/c-api/src/wasm_c_api/types/value.rs @@ -1,6 +1,5 @@ use super::super::value::wasm_valkind_t; use std::convert::TryInto; -use std::ptr::NonNull; use wasmer::ValType; #[allow(non_camel_case_types)] @@ -84,11 +83,8 @@ pub extern "C" fn wasm_valtype_new(kind: wasm_valkind_t) -> Option>) {} #[no_mangle] -pub unsafe extern "C" fn wasm_valtype_kind( - valtype: Option>, -) -> wasm_valkind_t { +pub unsafe extern "C" fn wasm_valtype_kind(valtype: Option<&wasm_valtype_t>) -> wasm_valkind_t { valtype .expect("`wasm_valtype_kind: argument is a null pointer") - .as_ref() .valkind as wasm_valkind_t } From 58b05a9881790ce30890d00c8e96cce1389cfd29 Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Tue, 13 Oct 2020 11:11:45 -0700 Subject: [PATCH 251/281] Fix env var setting on Windows --- .github/workflows/main.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/main.yaml b/.github/workflows/main.yaml index 246d93682..d74303e3f 100644 --- a/.github/workflows/main.yaml +++ b/.github/workflows/main.yaml @@ -161,7 +161,7 @@ jobs: shell: cmd run: | call refreshenv - setx WASMER_DIR "%CD%/package" + set WASMER_DIR=%CD%\package make test-integration if: matrix.run_integration_tests && matrix.os == 'windows-latest' - name: Run integration tests (Unix) From e3ec9f34c12f68e768ebb234a50ee76421772de3 Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Tue, 13 Oct 2020 14:21:17 -0700 Subject: [PATCH 252/281] Prevent panic when min > static bound and max is less than it --- CHANGELOG.md | 1 + lib/api/src/tunables.rs | 2 - lib/c-api/tests/wasm_c_api/test-memory.c | 60 ++++++++++++++++++++++++ 3 files changed, 61 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index edba3e674..df71323a0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ ### Added +- [#1718](https://github.com/wasmerio/wasmer/pull/1718) Fix panic in the API in some situations when the memory's min bound was greater than the memory's max bound. - [#1709](https://github.com/wasmerio/wasmer/pull/1709) Implement `wasm_module_name` and `wasm_module_set_name` in the Wasm(er) C API. - [#1700](https://github.com/wasmerio/wasmer/pull/1700) Implement `wasm_externtype_copy` in the Wasm C API. diff --git a/lib/api/src/tunables.rs b/lib/api/src/tunables.rs index 77c4c742c..2983d8042 100644 --- a/lib/api/src/tunables.rs +++ b/lib/api/src/tunables.rs @@ -1,5 +1,4 @@ use crate::{MemoryType, Pages, TableType}; -use more_asserts::assert_ge; use std::cmp::min; use std::sync::Arc; use target_lexicon::{OperatingSystem, PointerWidth}; @@ -67,7 +66,6 @@ impl BaseTunables for Tunables { // If the module doesn't declare an explicit maximum treat it as 4GiB. let maximum = memory.maximum.unwrap_or_else(Pages::max_value); if maximum <= self.static_memory_bound { - assert_ge!(self.static_memory_bound, memory.minimum); MemoryStyle::Static { bound: self.static_memory_bound, offset_guard_size: self.static_memory_offset_guard_size, diff --git a/lib/c-api/tests/wasm_c_api/test-memory.c b/lib/c-api/tests/wasm_c_api/test-memory.c index 3d4c8abe7..079768df8 100644 --- a/lib/c-api/tests/wasm_c_api/test-memory.c +++ b/lib/c-api/tests/wasm_c_api/test-memory.c @@ -62,6 +62,66 @@ int main(int argc, const char *argv[]) { wasm_memorytype_delete(memtype3); wasm_memory_delete(memory3); + // ===================== + wasm_limits_t limits4 = { + .min = 0x7FFFFFFF, + .max = 0x7FFFFFFF, + }; + own wasm_memorytype_t* memtype4 = wasm_memorytype_new(&limits4); + own wasm_memory_t* memory4 = wasm_memory_new(store, memtype4); + assert(memory4 == NULL); + error = get_wasmer_error(); + printf("Found error string: %s\n", error); + assert(0 == strcmp("The minimum requested (2147483647 pages) memory is greater than the maximum allowed memory (65536 pages)", error)); + free(error); + + wasm_memorytype_delete(memtype4); + + // ===================== + wasm_limits_t limits5 = { + .min = 0x7FFFFFFF, + .max = 0x0FFFFFFF, + }; + own wasm_memorytype_t* memtype5 = wasm_memorytype_new(&limits5); + own wasm_memory_t* memory5 = wasm_memory_new(store, memtype5); + assert(memory5 == NULL); + error = get_wasmer_error(); + printf("Found error string: %s\n", error); + assert(0 == strcmp("The minimum requested (2147483647 pages) memory is greater than the maximum allowed memory (65536 pages)", error)); + free(error); + + wasm_memorytype_delete(memtype5); + + // ===================== + wasm_limits_t limits6 = { + .min = 15, + .max = 10, + }; + own wasm_memorytype_t* memtype6 = wasm_memorytype_new(&limits6); + own wasm_memory_t* memory6 = wasm_memory_new(store, memtype6); + assert(memory6 == NULL); + error = get_wasmer_error(); + printf("Found error string: %s\n", error); + assert(0 == strcmp("The memory is invalid because the maximum (10 pages) is less than the minimum (15 pages)", error)); + free(error); + + wasm_memorytype_delete(memtype6); + + // ===================== + wasm_limits_t limits7 = { + .min = 0x7FFFFFFF, + .max = 10, + }; + own wasm_memorytype_t* memtype7 = wasm_memorytype_new(&limits7); + own wasm_memory_t* memory7 = wasm_memory_new(store, memtype7); + assert(memory7 == NULL); + error = get_wasmer_error(); + printf("Found error string: %s\n", error); + assert(0 == strcmp("The minimum requested (2147483647 pages) memory is greater than the maximum allowed memory (65536 pages)", error)); + free(error); + + wasm_memorytype_delete(memtype7); + printf("Shutting down...\n"); wasm_store_delete(store); wasm_engine_delete(engine); From 3a59e8a59d4c537856cfcbe128dd9b3be4a31f01 Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Tue, 13 Oct 2020 14:45:19 -0700 Subject: [PATCH 253/281] Fix mistake in name of C API lib on Windows --- lib/cli/src/commands/create_exe.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/cli/src/commands/create_exe.rs b/lib/cli/src/commands/create_exe.rs index 62b9a42bd..41b46d615 100644 --- a/lib/cli/src/commands/create_exe.rs +++ b/lib/cli/src/commands/create_exe.rs @@ -174,7 +174,7 @@ fn get_libwasmer_path() -> anyhow::Result { #[cfg(not(windows))] path.push("libwasmer.a"); #[cfg(windows)] - path.push("libwasmer.lib"); + path.push("wasmer_c_api.lib"); Ok(path) } From c97c70558d0dc59a8e97ad3f2fdb46635172a41d Mon Sep 17 00:00:00 2001 From: Syrus Date: Tue, 13 Oct 2020 18:27:29 -0700 Subject: [PATCH 254/281] Fixed broken intra docs attrs --- lib/api/src/lib.rs | 2 +- lib/vm/src/vmoffsets.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/api/src/lib.rs b/lib/api/src/lib.rs index 6725141ae..2a1f42c24 100644 --- a/lib/api/src/lib.rs +++ b/lib/api/src/lib.rs @@ -3,7 +3,7 @@ missing_docs, trivial_numeric_casts, unused_extern_crates, - intra_doc_link_resolution_failure + broken_intra_doc_links )] #![warn(unused_import_braces)] #![cfg_attr( diff --git a/lib/vm/src/vmoffsets.rs b/lib/vm/src/vmoffsets.rs index 1c0640843..b18408165 100644 --- a/lib/vm/src/vmoffsets.rs +++ b/lib/vm/src/vmoffsets.rs @@ -4,7 +4,7 @@ //! Offsets and sizes of various structs in wasmer-vm's vmcontext //! module. -#![deny(intra_doc_link_resolution_failure)] +#![deny(broken_intra_doc_links)] use crate::module::ModuleInfo; use crate::VMBuiltinFunctionIndex; From 38ebdb94ef3ef2a5156ae2d18851335425dac55c Mon Sep 17 00:00:00 2001 From: Syrus Date: Tue, 13 Oct 2020 18:33:51 -0700 Subject: [PATCH 255/281] added create-exe as possible cli option --- lib/cli/src/bin/wasmer.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/lib/cli/src/bin/wasmer.rs b/lib/cli/src/bin/wasmer.rs index 509bbdede..e0e51ed2d 100644 --- a/lib/cli/src/bin/wasmer.rs +++ b/lib/cli/src/bin/wasmer.rs @@ -82,9 +82,8 @@ fn main() { let args = std::env::args().collect::>(); let command = args.get(1); let options = match command.unwrap_or(&"".to_string()).as_ref() { - "run" | "cache" | "validate" | "compile" | "config" | "self-update" | "inspect" => { - WasmerCLIOptions::from_args() - } + "cache" | "compile" | "config" | "create-exe" | "help" | "inspect" | "run" + | "self-update" | "validate" | "wast" => WasmerCLIOptions::from_args(), _ => { WasmerCLIOptions::from_iter_safe(args.iter()).unwrap_or_else(|e| { match e.kind { From 773ab17a851ee755d94280d585774f48ddc3b3e2 Mon Sep 17 00:00:00 2001 From: Nick Lewycky Date: Wed, 14 Oct 2020 01:01:49 -0700 Subject: [PATCH 256/281] Add support for "on native" and "on jit" to the ignores.txt. Extend test-no-traps feature to cover tests/compiler/traps.rs and enable it when testing with the native engine. Turn on testing native engine as part of make test. --- Cargo.toml | 2 ++ Makefile | 6 +++--- tests/compilers/traps.rs | 7 +++++++ tests/ignores.txt | 4 ++++ tests/lib/test-generator/Cargo.toml | 4 ++++ tests/lib/test-generator/src/lib.rs | 13 +++++++++++-- 6 files changed, 31 insertions(+), 5 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 666d015e4..e200eceed 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -131,9 +131,11 @@ test-llvm = [ test-native = [ "native", + "test-generator/test-native", ] test-jit = [ "jit", + "test-generator/test-jit", ] # Disable trap asserts in the WAST tests. This is useful for running the tests in a diff --git a/Makefile b/Makefile index 7b7f944c5..2e7d26408 100644 --- a/Makefile +++ b/Makefile @@ -94,7 +94,7 @@ build-capi-llvm: # Testing # ########### -test: $(foreach compiler,$(compilers),test-$(compiler)-jit) test-packages test-examples test-deprecated +test: $(foreach compiler,$(compilers),test-$(compiler)-jit test-$(compiler)-native) test-packages test-examples test-deprecated # Singlepass and native engine don't work together, this rule does nothing. test-singlepass-native: @@ -104,13 +104,13 @@ test-singlepass-jit: cargo test --release $(compiler_features) --features "test-singlepass test-jit" test-cranelift-native: - cargo test --release $(compiler_features) --features "test-cranelift test-native" + cargo test --release $(compiler_features) --features "test-cranelift test-native test-no-traps" test-cranelift-jit: cargo test --release $(compiler_features) --features "test-cranelift test-jit" test-llvm-native: - cargo test --release $(compiler_features) --features "test-llvm test-native" + cargo test --release $(compiler_features) --features "test-llvm test-native test-no-traps" test-llvm-jit: cargo test --release $(compiler_features) --features "test-llvm test-jit" diff --git a/tests/compilers/traps.rs b/tests/compilers/traps.rs index cb00ffd22..78079f271 100644 --- a/tests/compilers/traps.rs +++ b/tests/compilers/traps.rs @@ -37,6 +37,7 @@ fn test_trap_return() -> Result<()> { Ok(()) } +#[cfg(not(feature = "test-no-traps"))] #[test] #[cfg_attr(feature = "test-singlepass", ignore)] fn test_trap_trace() -> Result<()> { @@ -117,6 +118,7 @@ fn test_trap_trace_cb() -> Result<()> { Ok(()) } +#[cfg(not(feature = "test-no-traps"))] #[test] #[cfg_attr(feature = "test-singlepass", ignore)] fn test_trap_stack_overflow() -> Result<()> { @@ -148,6 +150,7 @@ fn test_trap_stack_overflow() -> Result<()> { Ok(()) } +#[cfg(not(feature = "test-no-traps"))] #[test] #[cfg_attr(any(feature = "test-singlepass", feature = "test-llvm"), ignore)] fn trap_display_pretty() -> Result<()> { @@ -181,6 +184,7 @@ RuntimeError: unreachable Ok(()) } +#[cfg(not(feature = "test-no-traps"))] #[test] #[cfg_attr(any(feature = "test-singlepass", feature = "test-llvm"), ignore)] fn trap_display_multi_module() -> Result<()> { @@ -386,6 +390,7 @@ fn mismatched_arguments() -> Result<()> { Ok(()) } +#[cfg(not(feature = "test-no-traps"))] #[test] #[cfg_attr(any(feature = "test-singlepass", feature = "test-llvm"), ignore)] fn call_signature_mismatch() -> Result<()> { @@ -417,6 +422,7 @@ RuntimeError: indirect call type mismatch Ok(()) } +#[cfg(not(feature = "test-no-traps"))] #[test] #[cfg_attr(any(feature = "test-singlepass", feature = "test-llvm"), ignore)] fn start_trap_pretty() -> Result<()> { @@ -449,6 +455,7 @@ RuntimeError: unreachable Ok(()) } +#[cfg(not(feature = "test-no-traps"))] #[test] fn present_after_module_drop() -> Result<()> { let store = get_store(); diff --git a/tests/ignores.txt b/tests/ignores.txt index 38be894e1..cdc45ddad 100644 --- a/tests/ignores.txt +++ b/tests/ignores.txt @@ -22,6 +22,10 @@ singlepass on windows # Singlepass is not yet supported on Windows cranelift::spec::skip_stack_guard_page on darwin llvm::spec::skip_stack_guard_page on darwin +# TODO: traps in native engine +cranelift::spec::linking on native +llvm::spec::linking on native + # Frontends ## WASI diff --git a/tests/lib/test-generator/Cargo.toml b/tests/lib/test-generator/Cargo.toml index d9e3b4bea..6dfc8fa7d 100644 --- a/tests/lib/test-generator/Cargo.toml +++ b/tests/lib/test-generator/Cargo.toml @@ -7,3 +7,7 @@ publish = false [dependencies] anyhow = "1.0" target-lexicon = "0.10" + +[features] +test-native = [] +test-jit = [] diff --git a/tests/lib/test-generator/src/lib.rs b/tests/lib/test-generator/src/lib.rs index 0396fe8b9..f17ff21cd 100644 --- a/tests/lib/test-generator/src/lib.rs +++ b/tests/lib/test-generator/src/lib.rs @@ -47,6 +47,13 @@ pub fn build_ignores_from_textfile(path: PathBuf) -> anyhow::Result { let file = File::open(path)?; let reader = BufReader::new(file); let host = Triple::host().to_string(); + let engine = if cfg!(feature = "test-native") { + Some("native") + } else if cfg!(feature = "test-jit") { + Some("jit") + } else { + None + }; for line in reader.lines() { let line = line.unwrap(); // If the line has a `#` we discard all the content that comes after @@ -75,8 +82,10 @@ pub fn build_ignores_from_textfile(path: PathBuf) -> anyhow::Result { } // We skip the ignore if doesn't apply to the current - // host target - if target.map(|t| !host.contains(&t)).unwrap_or(false) { + // host target or engine + if target.clone().map(|t| !host.contains(&t)).unwrap_or(false) + && target.clone() != engine.map(str::to_string) + { continue; } From c24cb801053fba083e724af14f34388ceb416444 Mon Sep 17 00:00:00 2001 From: Nick Lewycky Date: Wed, 14 Oct 2020 12:40:05 -0700 Subject: [PATCH 257/281] Remove "test-no-traps" cfg! feature from test-generator, use a runtime bool instead. Rename "test-no-traps" feature to "coverage". Update .tarpaulin.toml to set coverage and also set test-jit (to fix breakage introduced in PR 1712). --- .tarpaulin.toml | 8 ++++---- Cargo.toml | 6 +++--- tests/compilers/wast.rs | 8 ++++++-- tests/lib/wast/Cargo.toml | 1 - tests/lib/wast/src/wast.rs | 28 ++++++++++++++++++---------- 5 files changed, 31 insertions(+), 20 deletions(-) diff --git a/.tarpaulin.toml b/.tarpaulin.toml index 78b59bfb0..08fe94c34 100644 --- a/.tarpaulin.toml +++ b/.tarpaulin.toml @@ -1,17 +1,17 @@ [cranelift_coverage] -features = "cranelift,singlepass,llvm,test-no-traps,test-cranelift" +features = "cranelift,singlepass,llvm,coverage,test-cranelift,test-jit" examples = ["early-exit", "engine-jit", "engine-native", "engine-headless", "cross-compilation", "compiler-cranelift", "exported-function", "wasi"] release = true [llvm_coverage] -features = "cranelift,singlepass,llvm,test-no-traps,test-llvm" +features = "cranelift,singlepass,llvm,coverage,test-llvm,test-jit" examples = ["compiler-llvm"] release = true [singlepass_coverage] -features = "cranelift,singlepass,llvm,test-no-traps,test-singlepass" +features = "cranelift,singlepass,llvm,coverage,test-singlepass,test-jit" examples = ["compiler-singlepass"] release = true [report] -out = ["Xml"] \ No newline at end of file +out = ["Xml"] diff --git a/Cargo.toml b/Cargo.toml index 666d015e4..4afe13373 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -136,9 +136,9 @@ test-jit = [ "jit", ] -# Disable trap asserts in the WAST tests. This is useful for running the tests in a -# context where signal handling is a problem, such as tarpaulin for code coverage. -test-no-traps = ["wasmer-wast/test-no-traps"] +# Specifies that we're running in coverage testing mode. This disables tests +# that raise signals because that interferes with tarpaulin. +coverage = [] [[bench]] name = "static_and_dynamic_functions" diff --git a/tests/compilers/wast.rs b/tests/compilers/wast.rs index 1471a990a..40e4d58c9 100644 --- a/tests/compilers/wast.rs +++ b/tests/compilers/wast.rs @@ -59,10 +59,14 @@ pub fn run_wast(wast_path: &str, compiler: &str) -> anyhow::Result<()> { if is_simd { features.simd(true); } - #[cfg(feature = "test-singlepass")] - features.multi_value(false); + if cfg!(feature = "test-singlepass") { + features.multi_value(false); + } let store = get_store(features, try_nan_canonicalization); let mut wast = Wast::new_with_spectest(store); + if cfg!(feature = "coverage") { + wast.disable_assert_and_exhaustion(); + } if is_simd { // We allow this, so tests can be run properly for `simd_const` test. wast.allow_instantiation_failures(&[ diff --git a/tests/lib/wast/Cargo.toml b/tests/lib/wast/Cargo.toml index de453bb9e..b9c26627f 100644 --- a/tests/lib/wast/Cargo.toml +++ b/tests/lib/wast/Cargo.toml @@ -23,7 +23,6 @@ typetag = "0.1" [features] default = ["wat"] wat = ["wasmer/wat"] -test-no-traps = [] [badges] maintenance = { status = "actively-developed" } diff --git a/tests/lib/wast/src/wast.rs b/tests/lib/wast/src/wast.rs index a53f4ce66..2c6a07f74 100644 --- a/tests/lib/wast/src/wast.rs +++ b/tests/lib/wast/src/wast.rs @@ -24,6 +24,9 @@ pub struct Wast { store: Store, /// A flag indicating if Wast tests should stop as soon as one test fails. pub fail_fast: bool, + /// A flag indicating that assert_trap and assert_exhaustion should be skipped. + /// See https://github.com/wasmerio/wasmer/issues/1550 for more info + disable_assert_trap_exhaustion: bool, } impl Wast { @@ -37,10 +40,11 @@ impl Wast { current_is_allowed_failure: false, instances: HashMap::new(), fail_fast: true, + disable_assert_trap_exhaustion: false, } } - /// A list of instantiation failures to allow + /// A list of instantiation failures to allow. pub fn allow_instantiation_failures(&mut self, failures: &[&str]) { for &failure_str in failures.iter() { self.allowed_instantiation_failures @@ -48,6 +52,11 @@ impl Wast { } } + /// Do not run any code in assert_trap or assert_exhaustion. + pub fn disable_assert_and_exhaustion(&mut self) { + self.disable_assert_trap_exhaustion = true; + } + /// Construct a new instance of `Wast` with the spectests imports. pub fn new_with_spectest(store: Store) -> Self { let import_object = spectest_importobject(&store); @@ -155,27 +164,26 @@ impl Wast { let result = self.perform_execute(exec); self.assert_return(result, &results)?; } - #[cfg(not(feature = "test-no-traps"))] AssertTrap { span: _, exec, message, } => { - let result = self.perform_execute(exec); - self.assert_trap(result, message)?; + if !self.disable_assert_trap_exhaustion { + let result = self.perform_execute(exec); + self.assert_trap(result, message)?; + } } - #[cfg(not(feature = "test-no-traps"))] AssertExhaustion { span: _, call, message, } => { - let result = self.perform_invoke(call); - self.assert_trap(result, message)?; + if !self.disable_assert_trap_exhaustion { + let result = self.perform_invoke(call); + self.assert_trap(result, message)?; + } } - // See https://github.com/wasmerio/wasmer/issues/1550 for more info - #[cfg(feature = "test-no-traps")] - AssertTrap { .. } | AssertExhaustion { .. } => {} AssertInvalid { span: _, mut module, From 1f08f66ba6e8815b92a53fa065a166f82c865c1f Mon Sep 17 00:00:00 2001 From: nlewycky Date: Wed, 14 Oct 2020 12:58:03 -0700 Subject: [PATCH 258/281] Update tests/compilers/traps.rs Ignore the test instead of skipping it. Co-authored-by: Syrus Akbary --- tests/compilers/traps.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/compilers/traps.rs b/tests/compilers/traps.rs index 78079f271..4e8db9a14 100644 --- a/tests/compilers/traps.rs +++ b/tests/compilers/traps.rs @@ -39,7 +39,7 @@ fn test_trap_return() -> Result<()> { #[cfg(not(feature = "test-no-traps"))] #[test] -#[cfg_attr(feature = "test-singlepass", ignore)] +#[cfg_attr(any(feature = "test-singlepass", feature = "test-no-traps"), ignore)] fn test_trap_trace() -> Result<()> { let store = get_store(); let wat = r#" From e6cd0ab8d47d8011de3bef2a64b8ca9b310d0ed6 Mon Sep 17 00:00:00 2001 From: Nick Lewycky Date: Wed, 14 Oct 2020 13:39:32 -0700 Subject: [PATCH 259/281] Generalize the one-off code for matching of mismatched assert_trap messages. Use this to match all the mismatching trap messages in engine-native testing. --- Makefile | 4 ++-- tests/compilers/traps.rs | 48 +++++++++++++++++++++++++++----------- tests/compilers/wast.rs | 14 +++++++++++ tests/lib/wast/src/wast.rs | 25 ++++++++++++++------ 4 files changed, 69 insertions(+), 22 deletions(-) diff --git a/Makefile b/Makefile index 2e7d26408..48c72eb17 100644 --- a/Makefile +++ b/Makefile @@ -104,13 +104,13 @@ test-singlepass-jit: cargo test --release $(compiler_features) --features "test-singlepass test-jit" test-cranelift-native: - cargo test --release $(compiler_features) --features "test-cranelift test-native test-no-traps" + cargo test --release $(compiler_features) --features "test-cranelift test-native" test-cranelift-jit: cargo test --release $(compiler_features) --features "test-cranelift test-jit" test-llvm-native: - cargo test --release $(compiler_features) --features "test-llvm test-native test-no-traps" + cargo test --release $(compiler_features) --features "test-llvm test-native" test-llvm-jit: cargo test --release $(compiler_features) --features "test-llvm test-jit" diff --git a/tests/compilers/traps.rs b/tests/compilers/traps.rs index 4e8db9a14..7922511a0 100644 --- a/tests/compilers/traps.rs +++ b/tests/compilers/traps.rs @@ -37,9 +37,8 @@ fn test_trap_return() -> Result<()> { Ok(()) } -#[cfg(not(feature = "test-no-traps"))] #[test] -#[cfg_attr(any(feature = "test-singlepass", feature = "test-no-traps"), ignore)] +#[cfg_attr(any(feature = "test-singlepass", feature = "test-native"), ignore)] fn test_trap_trace() -> Result<()> { let store = get_store(); let wat = r#" @@ -118,9 +117,8 @@ fn test_trap_trace_cb() -> Result<()> { Ok(()) } -#[cfg(not(feature = "test-no-traps"))] #[test] -#[cfg_attr(feature = "test-singlepass", ignore)] +#[cfg_attr(any(feature = "test-singlepass", feature = "test-native"), ignore)] fn test_trap_stack_overflow() -> Result<()> { let store = get_store(); let wat = r#" @@ -150,9 +148,15 @@ fn test_trap_stack_overflow() -> Result<()> { Ok(()) } -#[cfg(not(feature = "test-no-traps"))] #[test] -#[cfg_attr(any(feature = "test-singlepass", feature = "test-llvm"), ignore)] +#[cfg_attr( + any( + feature = "test-singlepass", + feature = "test-llvm", + feature = "test-native" + ), + ignore +)] fn trap_display_pretty() -> Result<()> { let store = get_store(); let wat = r#" @@ -184,9 +188,15 @@ RuntimeError: unreachable Ok(()) } -#[cfg(not(feature = "test-no-traps"))] #[test] -#[cfg_attr(any(feature = "test-singlepass", feature = "test-llvm"), ignore)] +#[cfg_attr( + any( + feature = "test-singlepass", + feature = "test-llvm", + feature = "test-native" + ), + ignore +)] fn trap_display_multi_module() -> Result<()> { let store = get_store(); let wat = r#" @@ -390,9 +400,15 @@ fn mismatched_arguments() -> Result<()> { Ok(()) } -#[cfg(not(feature = "test-no-traps"))] #[test] -#[cfg_attr(any(feature = "test-singlepass", feature = "test-llvm"), ignore)] +#[cfg_attr( + any( + feature = "test-singlepass", + feature = "test-llvm", + feature = "test-native" + ), + ignore +)] fn call_signature_mismatch() -> Result<()> { let store = get_store(); let binary = r#" @@ -422,9 +438,15 @@ RuntimeError: indirect call type mismatch Ok(()) } -#[cfg(not(feature = "test-no-traps"))] #[test] -#[cfg_attr(any(feature = "test-singlepass", feature = "test-llvm"), ignore)] +#[cfg_attr( + any( + feature = "test-singlepass", + feature = "test-llvm", + feature = "test-native" + ), + ignore +)] fn start_trap_pretty() -> Result<()> { let store = get_store(); let wat = r#" @@ -455,8 +477,8 @@ RuntimeError: unreachable Ok(()) } -#[cfg(not(feature = "test-no-traps"))] #[test] +#[cfg_attr(feature = "test-native", ignore)] fn present_after_module_drop() -> Result<()> { let store = get_store(); let module = Module::new(&store, r#"(func (export "foo") unreachable)"#)?; diff --git a/tests/compilers/wast.rs b/tests/compilers/wast.rs index 1471a990a..c41b8da16 100644 --- a/tests/compilers/wast.rs +++ b/tests/compilers/wast.rs @@ -63,6 +63,20 @@ pub fn run_wast(wast_path: &str, compiler: &str) -> anyhow::Result<()> { features.multi_value(false); let store = get_store(features, try_nan_canonicalization); let mut wast = Wast::new_with_spectest(store); + // `bulk-memory-operations/bulk.wast` checks for a message that + // specifies which element is uninitialized, but our traps don't + // shepherd that information out. + wast.allow_trap_message("uninitialized element 2", "uninitialized element"); + if cfg!(feature = "test-native") { + wast.allow_trap_message("call stack exhausted", "out of bounds memory access"); + wast.allow_trap_message("indirect call type mismatch", "call stack exhausted"); + wast.allow_trap_message("integer divide by zero", "call stack exhausted"); + wast.allow_trap_message("integer overflow", "call stack exhausted"); + wast.allow_trap_message("invalid conversion to integer", "call stack exhausted"); + wast.allow_trap_message("undefined element", "call stack exhausted"); + wast.allow_trap_message("uninitialized element", "call stack exhausted"); + wast.allow_trap_message("unreachable", "call stack exhausted"); + } if is_simd { // We allow this, so tests can be run properly for `simd_const` test. wast.allow_instantiation_failures(&[ diff --git a/tests/lib/wast/src/wast.rs b/tests/lib/wast/src/wast.rs index a53f4ce66..159d1a7b2 100644 --- a/tests/lib/wast/src/wast.rs +++ b/tests/lib/wast/src/wast.rs @@ -18,6 +18,9 @@ pub struct Wast { instances: HashMap, /// Allowed failures (ideally this should be empty) allowed_instantiation_failures: HashSet, + /// If the (expected from .wast, actual) message pair is in this list, + /// treat the strings as matching. + match_trap_messages: HashMap, /// If the current module was an allowed failure, we allow test to fail current_is_allowed_failure: bool, /// The wasm Store @@ -34,13 +37,14 @@ impl Wast { store, import_object, allowed_instantiation_failures: HashSet::new(), + match_trap_messages: HashMap::new(), current_is_allowed_failure: false, instances: HashMap::new(), fail_fast: true, } } - /// A list of instantiation failures to allow + /// A list of instantiation failures to allow. pub fn allow_instantiation_failures(&mut self, failures: &[&str]) { for &failure_str in failures.iter() { self.allowed_instantiation_failures @@ -48,6 +52,12 @@ impl Wast { } } + /// A list of alternative messages to permit for a trap failure. + pub fn allow_trap_message(&mut self, expected: &str, allowed: &str) { + self.match_trap_messages + .insert(expected.into(), allowed.into()); + } + /// Construct a new instance of `Wast` with the spectests imports. pub fn new_with_spectest(store: Store) -> Self { let import_object = spectest_importobject(&store); @@ -123,7 +133,7 @@ impl Wast { Ok(values) => bail!("expected trap, got {:?}", values), Err(t) => format!("{}", t), }; - if Self::matches_message_assert_trap(expected, &actual) { + if self.matches_message_assert_trap(expected, &actual) { return Ok(()); } bail!("expected '{}', got '{}'", expected, actual) @@ -406,12 +416,13 @@ impl Wast { } // Checks if the `assert_trap` message matches the expected one - fn matches_message_assert_trap(expected: &str, actual: &str) -> bool { + fn matches_message_assert_trap(&self, expected: &str, actual: &str) -> bool { actual.contains(expected) - // `bulk-memory-operations/bulk.wast` checks for a message that - // specifies which element is uninitialized, but our traps don't - // shepherd that information out. - || (expected.contains("uninitialized element 2") && actual.contains("uninitialized element")) + || self + .match_trap_messages + .get(expected) + .map(|alternative| actual.contains(alternative)) + .unwrap_or(false) } } From e0257785742d5b4de3123cda685d29da47a15da9 Mon Sep 17 00:00:00 2001 From: Nick Lewycky Date: Wed, 14 Oct 2020 16:20:21 -0700 Subject: [PATCH 260/281] Limit these disables to cranelift, add one test failure with link for llvm. --- tests/compilers/wast.rs | 2 +- tests/ignores.txt | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/tests/compilers/wast.rs b/tests/compilers/wast.rs index c41b8da16..9d8b88b9a 100644 --- a/tests/compilers/wast.rs +++ b/tests/compilers/wast.rs @@ -67,7 +67,7 @@ pub fn run_wast(wast_path: &str, compiler: &str) -> anyhow::Result<()> { // specifies which element is uninitialized, but our traps don't // shepherd that information out. wast.allow_trap_message("uninitialized element 2", "uninitialized element"); - if cfg!(feature = "test-native") { + if compiler == "cranelift" && cfg!(feature = "test-native") { wast.allow_trap_message("call stack exhausted", "out of bounds memory access"); wast.allow_trap_message("indirect call type mismatch", "call stack exhausted"); wast.allow_trap_message("integer divide by zero", "call stack exhausted"); diff --git a/tests/ignores.txt b/tests/ignores.txt index cdc45ddad..be05b5762 100644 --- a/tests/ignores.txt +++ b/tests/ignores.txt @@ -26,6 +26,9 @@ llvm::spec::skip_stack_guard_page on darwin cranelift::spec::linking on native llvm::spec::linking on native +# https://github.com/wasmerio/wasmer/issues/1722 +llvm::spec::skip_stack_guard_page on native + # Frontends ## WASI From 3a679b3976153c9549cd6f11ce17206429712d58 Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Wed, 14 Oct 2020 17:08:46 -0700 Subject: [PATCH 261/281] Use GITHUB_PATH, GITHUB_ENV in CI The old style is being deprecated, see: https://github.blog/changelog/2020-10-01-github-actions-deprecating-set-env-and-add-path-commands/ --- .github/workflows/benchmark.yaml | 6 +++--- .github/workflows/coverage.yaml | 4 ++-- .github/workflows/main.yaml | 18 +++++++++--------- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/.github/workflows/benchmark.yaml b/.github/workflows/benchmark.yaml index f15dbcab2..0c42290f3 100644 --- a/.github/workflows/benchmark.yaml +++ b/.github/workflows/benchmark.yaml @@ -35,7 +35,7 @@ jobs: # that are needed during the build process. Additionally, this works # around a bug in the 'cache' action that causes directories outside of # the workspace dir to be saved/restored incorrectly. - run: echo "::set-env name=CARGO_HOME::$(pwd)/.cargo_home" + run: echo "CARGO_HOME=$(pwd)/.cargo_home" >> $GITHUB_ENV - name: Cache uses: actions/cache@master with: @@ -56,8 +56,8 @@ jobs: curl --proto '=https' --tlsv1.2 -sSf https://github.com/llvm/llvm-project/releases/download/llvmorg-10.0.0/clang+llvm-10.0.0-x86_64-linux-gnu-ubuntu-18.04.tar.xz -L -o llvm.tar.xz mkdir -p /opt/llvm-10 tar xf llvm.tar.xz --strip-components=1 -C /opt/llvm-10 - echo ::add-path::/opt/llvm-10/bin - echo ::set-env name=LLVM_SYS_100_PREFIX::/opt/llvm-10 + echo '/opt/llvm-10/bin' >> $GITHUB_PATH + echo 'name=LLVM_SYS_100_PREFIX=/opt/llvm-10' >> $GITHUB_ENV - name: Install Python uses: actions/setup-python@v2 with: diff --git a/.github/workflows/coverage.yaml b/.github/workflows/coverage.yaml index cd86d13f2..2265909ac 100644 --- a/.github/workflows/coverage.yaml +++ b/.github/workflows/coverage.yaml @@ -29,8 +29,8 @@ jobs: curl --proto '=https' --tlsv1.2 -sSf https://github.com/llvm/llvm-project/releases/download/llvmorg-10.0.0/clang+llvm-10.0.0-x86_64-linux-gnu-ubuntu-18.04.tar.xz -L -o llvm.tar.xz mkdir -p /opt/llvm-10 tar xf llvm.tar.xz --strip-components=1 -C /opt/llvm-10 - echo ::add-path::/opt/llvm-10/bin - echo ::set-env name=LLVM_SYS_100_PREFIX::/opt/llvm-10 + echo '/opt/llvm-10/bin' >> $GITHUB_PATH + echo 'LLVM_SYS_100_PREFIX=/opt/llvm-10' >> $GITHUB_ENV - name: Generate Coverage Report run: | cargo install cargo-tarpaulin diff --git a/.github/workflows/main.yaml b/.github/workflows/main.yaml index 9318e1094..872f168f8 100644 --- a/.github/workflows/main.yaml +++ b/.github/workflows/main.yaml @@ -81,7 +81,7 @@ jobs: # that are needed during the build process. Additionally, this works # around a bug in the 'cache' action that causes directories outside of # the workspace dir to be saved/restored incorrectly. - run: echo "::set-env name=CARGO_HOME::$(pwd)/.cargo_home" + run: echo "CARGO_HOME=$(pwd)/.cargo_home" >> $GITHUB_ENV - name: Cache uses: actions/cache@master with: @@ -103,13 +103,13 @@ jobs: # key: cargo-sccache-bin-${{ env.CARGO_SCCACHE_VERSION }} # - name: Install sccache # run: | - # echo "::add-path::${{ runner.tool_cache }}/cargo-sccache/bin" + # echo "${{ runner.tool_cache }}/cargo-sccache/bin" >> $GITHUB_PATH # cargo install sccache --version ${{ env.CARGO_SCCACHE_VERSION }} --root ${{ runner.tool_cache }}/cargo-sccache # - name: Start sccache # run: | # ${{ runner.tool_cache }}/cargo-sccache/bin/sccache --start-server # ${{ runner.tool_cache }}/cargo-sccache/bin/sscache -s - # echo "::set-env name=RUSTC_WRAPPER::${{ runner.tool_cache }}/cargo-sccache/bin/sccache" + # echo "RUSTC_WRAPPER=${{ runner.tool_cache }}/cargo-sccache/bin/sccache" >> $GITHUB_ENV - name: Install LLVM (Windows) if: matrix.os == 'windows-latest' shell: cmd @@ -118,17 +118,17 @@ jobs: # run: | # curl --proto '=https' --tlsv1.2 -sSf https://github.com/llvm/llvm-project/releases/download/llvmorg-10.0.0/LLVM-10.0.0-win64.exe -L -o llvm-installer.exe # 7z x llvm-installer.exe -oC:/llvm-10 - # echo ::add-path::C:/llvm-10/bin - # echo ::set-env name=LLVM_SYS_100_PREFIX::C:/llvm-10 - # echo ::set-env name=LIBCLANG_PATH::C:/llvm-10/bin/libclang.dll + # echo C:/llvm-10/bin >> $GITHUB_PATH + # echo "LLVM_SYS_100_PREFIX=C:/llvm-10" >> $GITHUB_ENV + # echo "LIBCLANG_PATH=C:/llvm-10/bin/libclang.dll" >> $GITHUB_ENV - name: Install LLVM (Unix) if: matrix.os != 'windows-latest' run: | curl --proto '=https' --tlsv1.2 -sSf ${{ matrix.llvm_url }} -L -o llvm.tar.xz mkdir -p ${{ env.LLVM_DIR }} tar xf llvm.tar.xz --strip-components=1 -C ${{ env.LLVM_DIR }} - echo "::add-path::${{ env.LLVM_DIR }}/bin" - echo "::set-env name=LLVM_SYS_100_PREFIX::${{ env.LLVM_DIR }}" + echo "${{ env.LLVM_DIR }}/bin" >> $GITHUB_PATH + echo "LLVM_SYS_100_PREFIX=${{ env.LLVM_DIR }}" >> $GITHUB_ENV env: LLVM_DIR: ${{ github.workspace }}/llvm-10 - name: Set up dependencies for Mac OS @@ -242,7 +242,7 @@ jobs: path: ${{ runner.tool_cache }}/cargo-audit key: cargo-audit-bin-${{ env.CARGO_AUDIT_VERSION }} - run: | - echo "::add-path::${{ runner.tool_cache }}/cargo-audit/bin" + echo "${{ runner.tool_cache }}/cargo-audit/bin" >> $GITHUB_PATH - run: | cargo install cargo-audit --version ${{ env.CARGO_AUDIT_VERSION }} --root ${{ runner.tool_cache }}/cargo-audit cargo audit From ffff0441bc249528ffb42ab0865d86609c9965d1 Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Thu, 15 Oct 2020 15:05:26 +0200 Subject: [PATCH 262/281] feat(c-api) Implement `wasm_func_type`. This patch creates a `wasm_functype_t::new` constructor, that is used by the new `wasm_func_type` function, and the existing `wasm_functype_new_inner` function. --- lib/c-api/src/wasm_c_api/externals/function.rs | 7 ++++++- lib/c-api/src/wasm_c_api/types/function.rs | 15 +++++++++++---- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/lib/c-api/src/wasm_c_api/externals/function.rs b/lib/c-api/src/wasm_c_api/externals/function.rs index b64f52d87..33d801ced 100644 --- a/lib/c-api/src/wasm_c_api/externals/function.rs +++ b/lib/c-api/src/wasm_c_api/externals/function.rs @@ -1,6 +1,6 @@ use super::super::store::wasm_store_t; use super::super::trap::wasm_trap_t; -use super::super::types::{wasm_functype_t, wasm_valkind_enum}; +use super::super::types::{wasm_functype_t, wasm_functype_t, wasm_valkind_enum}; use super::super::value::{wasm_val_inner, wasm_val_t}; use std::convert::TryInto; use std::ffi::c_void; @@ -154,3 +154,8 @@ pub unsafe extern "C" fn wasm_func_param_arity(func: &wasm_func_t) -> usize { pub unsafe extern "C" fn wasm_func_result_arity(func: &wasm_func_t) -> usize { func.inner.ty().results().len() } + +#[no_mangle] +pub extern "C" fn wasm_func_type(func: &wasm_func_t) -> Box { + Box::new(wasm_functype_t::new(func.inner.ty().clone())) +} diff --git a/lib/c-api/src/wasm_c_api/types/function.rs b/lib/c-api/src/wasm_c_api/types/function.rs index 7e95a39a2..69f630986 100644 --- a/lib/c-api/src/wasm_c_api/types/function.rs +++ b/lib/c-api/src/wasm_c_api/types/function.rs @@ -17,6 +17,14 @@ impl wasm_functype_t { unreachable!("data corruption: `wasm_functype_t` does not contain a function") } } + + pub(crate) fn new(function_type: FunctionType) -> Self { + Self { + extern_: wasm_externtype_t { + inner: ExternType::Function(function_type), + }, + } + } } wasm_declare_vec!(functype); @@ -52,10 +60,9 @@ unsafe fn wasm_functype_new_inner( .map(Into::into) .collect::>(); - let extern_ = wasm_externtype_t { - inner: ExternType::Function(FunctionType::new(params, results)), - }; - Some(Box::new(wasm_functype_t { extern_ })) + Some(Box::new(wasm_functype_t::new(FunctionType::new( + params, results, + )))) } #[no_mangle] From 5149b2eaa83d65058036bbed35a2d07412bc7f05 Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Thu, 15 Oct 2020 15:09:44 +0200 Subject: [PATCH 263/281] doc(changelog) Add #1725. --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1130551aa..ee82b9ecd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ ### Added +- [#1725](https://github.com/wasmerio/wasmer/pull/1725) Implement `wasm_func_type` in the Wasm C API. - [#1715](https://github.com/wasmerio/wasmer/pull/1715) Register errors from `wasm_module_serialize` in the Wasm C API. - [#1709](https://github.com/wasmerio/wasmer/pull/1709) Implement `wasm_module_name` and `wasm_module_set_name` in the Wasm(er) C API. - [#1700](https://github.com/wasmerio/wasmer/pull/1700) Implement `wasm_externtype_copy` in the Wasm C API. From 571e84625004b31cbbbbe2795c6da6e3b0c3d400 Mon Sep 17 00:00:00 2001 From: Nick Lewycky Date: Thu, 15 Oct 2020 11:36:25 -0700 Subject: [PATCH 264/281] Control which engines are tested by platform detection. --- Makefile | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 48c72eb17..7e260e00a 100644 --- a/Makefile +++ b/Makefile @@ -8,13 +8,19 @@ else UNAME_S := endif +# Which compilers we build. These have dependencies that may not on the system. compilers := +# Which engines we test. We always build all engines. +engines := + ifeq ($(ARCH), x86_64) + engines += jit # In X64, Cranelift is enabled compilers += cranelift # LLVM could be enabled if not in Windows ifneq ($(OS), Windows_NT) + engines += native # Singlepass doesn't work yet on Windows compilers += singlepass # Autodetect LLVM from llvm-config @@ -32,7 +38,12 @@ ifeq ($(ARCH), x86_64) endif endif +ifeq ($(ARCH), aarch64) + engines += native +endif + compilers := $(filter-out ,$(compilers)) +engines := $(filter-out ,$(engines)) ifneq ($(OS), Windows_NT) bold := $(shell tput bold) @@ -94,7 +105,7 @@ build-capi-llvm: # Testing # ########### -test: $(foreach compiler,$(compilers),test-$(compiler)-jit test-$(compiler)-native) test-packages test-examples test-deprecated +test: $(foreach engine,$(engines),$(foreach compiler,$(compilers),test-$(compiler)-$(engine))) test-packages test-examples test-deprecated # Singlepass and native engine don't work together, this rule does nothing. test-singlepass-native: From 6d3e1a59e29c7aae648d0bbfa896d25cf95e2223 Mon Sep 17 00:00:00 2001 From: Nick Lewycky Date: Thu, 15 Oct 2020 13:34:26 -0700 Subject: [PATCH 265/281] Add links to TODOs. --- tests/ignores.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/ignores.txt b/tests/ignores.txt index be05b5762..a55c8e043 100644 --- a/tests/ignores.txt +++ b/tests/ignores.txt @@ -22,8 +22,9 @@ singlepass on windows # Singlepass is not yet supported on Windows cranelift::spec::skip_stack_guard_page on darwin llvm::spec::skip_stack_guard_page on darwin -# TODO: traps in native engine +# TODO(https://github.com/wasmerio/wasmer/issues/1727): Traps in native engine cranelift::spec::linking on native +# TODO(https://github.com/wasmerio/wasmer/pull/1710): Library is dropped too soon. llvm::spec::linking on native # https://github.com/wasmerio/wasmer/issues/1722 From 69eef6e4905a18fd6756aacc3c16ae592ff53fcd Mon Sep 17 00:00:00 2001 From: Nick Lewycky Date: Thu, 15 Oct 2020 15:19:07 -0700 Subject: [PATCH 266/281] Enable cranelift on aarch64. Add comments to tests/ignores.txt explaining why they're disabled. Add a list of engines to test so that we don't test engine-native on aarch64. Disable tests in tests/compilers/traps.rs that fail with cranelift on aarch64. Disable tests in examples/ that use cranelift + native, on aarch64. --- Makefile | 15 +++++---------- examples/engine_headless.rs | 2 +- examples/engine_native.rs | 1 + lib/compiler-cranelift/Cargo.toml | 2 +- tests/compilers/traps.rs | 27 ++++++++++++++++++++++----- tests/ignores.txt | 15 +++++++++++++++ 6 files changed, 45 insertions(+), 17 deletions(-) diff --git a/Makefile b/Makefile index 7e260e00a..63a661f48 100644 --- a/Makefile +++ b/Makefile @@ -9,18 +9,14 @@ else endif # Which compilers we build. These have dependencies that may not on the system. -compilers := +compilers := cranelift # Which engines we test. We always build all engines. -engines := +engines := jit ifeq ($(ARCH), x86_64) - engines += jit - # In X64, Cranelift is enabled - compilers += cranelift # LLVM could be enabled if not in Windows ifneq ($(OS), Windows_NT) - engines += native # Singlepass doesn't work yet on Windows compilers += singlepass # Autodetect LLVM from llvm-config @@ -35,11 +31,10 @@ ifeq ($(ARCH), x86_64) compilers += llvm endif endif - endif -endif -ifeq ($(ARCH), aarch64) - engines += native + # Native engine doesn't work yet on Windows + engines += native + endif endif compilers := $(filter-out ,$(compilers)) diff --git a/examples/engine_headless.rs b/examples/engine_headless.rs index 817dccbed..f0d7694ee 100644 --- a/examples/engine_headless.rs +++ b/examples/engine_headless.rs @@ -147,7 +147,7 @@ fn main() -> Result<(), Box> { } #[test] -#[cfg(not(windows))] +#[cfg(not(any(windows, target_arch = "aarch64")))] fn test_engine_headless() -> Result<(), Box> { main() } diff --git a/examples/engine_native.rs b/examples/engine_native.rs index 47cd2d1fa..ea69744a4 100644 --- a/examples/engine_native.rs +++ b/examples/engine_native.rs @@ -87,6 +87,7 @@ fn main() -> Result<(), Box> { } #[test] +#[cfg(not(target_arch = "aarch64"))] fn test_engine_native() -> Result<(), Box> { main() } diff --git a/lib/compiler-cranelift/Cargo.toml b/lib/compiler-cranelift/Cargo.toml index 40ed587d8..0633afa46 100644 --- a/lib/compiler-cranelift/Cargo.toml +++ b/lib/compiler-cranelift/Cargo.toml @@ -15,7 +15,7 @@ edition = "2018" wasmer-compiler = { path = "../compiler", version = "1.0.0-alpha4", features = ["translator"], default-features = false } wasmer-vm = { path = "../vm", version = "1.0.0-alpha4" } wasmer-types = { path = "../wasmer-types", version = "1.0.0-alpha4", default-features = false, features = ["std"] } -cranelift-codegen = { version = "0.65", default-features = false } +cranelift-codegen = { version = "0.65", default-features = false, features = ["x86", "arm64"] } cranelift-frontend = { version = "0.65", default-features = false } tracing = "0.1" hashbrown = { version = "0.8", optional = true } diff --git a/tests/compilers/traps.rs b/tests/compilers/traps.rs index 7922511a0..7b1944ba3 100644 --- a/tests/compilers/traps.rs +++ b/tests/compilers/traps.rs @@ -38,7 +38,14 @@ fn test_trap_return() -> Result<()> { } #[test] -#[cfg_attr(any(feature = "test-singlepass", feature = "test-native"), ignore)] +#[cfg_attr( + any( + feature = "test-singlepass", + feature = "test-native", + target_arch = "aarch64", + ), + ignore +)] fn test_trap_trace() -> Result<()> { let store = get_store(); let wat = r#" @@ -118,7 +125,14 @@ fn test_trap_trace_cb() -> Result<()> { } #[test] -#[cfg_attr(any(feature = "test-singlepass", feature = "test-native"), ignore)] +#[cfg_attr( + any( + feature = "test-singlepass", + feature = "test-native", + target_arch = "aarch64", + ), + ignore +)] fn test_trap_stack_overflow() -> Result<()> { let store = get_store(); let wat = r#" @@ -153,7 +167,8 @@ fn test_trap_stack_overflow() -> Result<()> { any( feature = "test-singlepass", feature = "test-llvm", - feature = "test-native" + feature = "test-native", + target_arch = "aarch64", ), ignore )] @@ -193,7 +208,8 @@ RuntimeError: unreachable any( feature = "test-singlepass", feature = "test-llvm", - feature = "test-native" + feature = "test-native", + target_arch = "aarch64", ), ignore )] @@ -443,7 +459,8 @@ RuntimeError: indirect call type mismatch any( feature = "test-singlepass", feature = "test-llvm", - feature = "test-native" + feature = "test-native", + target_arch = "aarch64", ), ignore )] diff --git a/tests/ignores.txt b/tests/ignores.txt index a55c8e043..f8b426a02 100644 --- a/tests/ignores.txt +++ b/tests/ignores.txt @@ -30,6 +30,21 @@ llvm::spec::linking on native # https://github.com/wasmerio/wasmer/issues/1722 llvm::spec::skip_stack_guard_page on native +# Cranelift on arm failures +cranelift::spec::align on aarch64 +cranelift::spec::memory_trap on aarch64 +cranelift::spec::simd::simd_bit_shift on aarch64 +cranelift::spec::simd::simd_boolean on aarch64 +cranelift::spec::simd::simd_const on aarch64 +cranelift::spec::simd::simd_i16x8_arith on aarch64 +cranelift::spec::simd::simd_i16x8_sat_arith on aarch64 +cranelift::spec::simd::simd_i32x4_arith on aarch64 +cranelift::spec::simd::simd_i64x2_arith on aarch64 +cranelift::spec::simd::simd_i8x16_arith on aarch64 +cranelift::spec::simd::simd_i8x16_sat_arith on aarch64 +cranelift::spec::simd::simd_lane on aarch64 +cranelift::spec::skip_stack_guard_page on aarch64 + # Frontends ## WASI From 2f692a1e2c32469d06cc0f5bc48b07b05709fc81 Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Fri, 16 Oct 2020 09:42:12 +0200 Subject: [PATCH 267/281] fix(c-api) Fix merge issue. --- lib/c-api/src/wasm_c_api/externals/function.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/c-api/src/wasm_c_api/externals/function.rs b/lib/c-api/src/wasm_c_api/externals/function.rs index 33d801ced..29e20adff 100644 --- a/lib/c-api/src/wasm_c_api/externals/function.rs +++ b/lib/c-api/src/wasm_c_api/externals/function.rs @@ -1,6 +1,6 @@ use super::super::store::wasm_store_t; use super::super::trap::wasm_trap_t; -use super::super::types::{wasm_functype_t, wasm_functype_t, wasm_valkind_enum}; +use super::super::types::{wasm_functype_t, wasm_valkind_enum}; use super::super::value::{wasm_val_inner, wasm_val_t}; use std::convert::TryInto; use std::ffi::c_void; From e29ea25dcd612e2660ce0a86d0ac5a418d86874c Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Fri, 16 Oct 2020 10:17:23 +0200 Subject: [PATCH 268/281] feat(c-api) Simplify code with `unwrap_or_default`. --- lib/c-api/src/wasm_c_api/externals/function.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/c-api/src/wasm_c_api/externals/function.rs b/lib/c-api/src/wasm_c_api/externals/function.rs index 0b9ae3ff4..33505f7d4 100644 --- a/lib/c-api/src/wasm_c_api/externals/function.rs +++ b/lib/c-api/src/wasm_c_api/externals/function.rs @@ -150,7 +150,7 @@ pub unsafe extern "C" fn wasm_func_call( .collect::, _>>() .expect("Argument conversion failed") }) - .unwrap_or_else(|| Vec::new()); + .unwrap_or_default(); match func.inner.call(¶ms) { Ok(wasm_results) => { From ddf2459632b70a25ba22d40a1401c3fcb482326e Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Fri, 16 Oct 2020 10:19:26 +0200 Subject: [PATCH 269/281] chore(changelog) Fix merge. --- CHANGELOG.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fda20f52b..40a4ce36b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,10 +7,10 @@ ## **[Unreleased]** -- [#1699](https://github.com/wasmerio/wasmer/pull/1699) Update `wasm.h` to its latest version. -- [#1685](https://github.com/wasmerio/wasmer/pull/1685) Implement `wasm_exporttype_delete` in the Wasm C API. ### Added +- [#1699](https://github.com/wasmerio/wasmer/pull/1699) Update `wasm.h` to its latest version. +- [#1685](https://github.com/wasmerio/wasmer/pull/1685) Implement `wasm_exporttype_delete` in the Wasm C API. - [#1715](https://github.com/wasmerio/wasmer/pull/1715) Register errors from `wasm_module_serialize` in the Wasm C API. - [#1709](https://github.com/wasmerio/wasmer/pull/1709) Implement `wasm_module_name` and `wasm_module_set_name` in the Wasm(er) C API. - [#1700](https://github.com/wasmerio/wasmer/pull/1700) Implement `wasm_externtype_copy` in the Wasm C API. From 4f9932c3508d6ead9f2ef2b1ca6ce89017acfba9 Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Fri, 16 Oct 2020 10:46:28 +0200 Subject: [PATCH 270/281] feat(cli) Update the `crate_exe_main.c` file to the latest Wasm C API. --- lib/cli/src/commands/wasmer_create_exe_main.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/lib/cli/src/commands/wasmer_create_exe_main.c b/lib/cli/src/commands/wasmer_create_exe_main.c index 11adb1656..27df04324 100644 --- a/lib/cli/src/commands/wasmer_create_exe_main.c +++ b/lib/cli/src/commands/wasmer_create_exe_main.c @@ -134,20 +134,22 @@ int main(int argc, char* argv[]) { wasm_importtype_vec_t import_types; wasm_module_imports(module, &import_types); - int num_imports = import_types.size; - wasm_extern_t** imports = (wasm_extern_t**) malloc(num_imports * sizeof(wasm_extern_t*)); + + wasm_extern_vec_new_uninitialized(&imports, import_type.size); wasm_importtype_vec_delete(&import_types); #ifdef WASI - bool get_imports_result = wasi_get_imports(store, module, wasi_env, imports); + bool get_imports_result = wasi_get_imports(store, module, wasi_env, &imports); + if (!get_imports_result) { fprintf(stderr, "Error getting WASI imports!\n"); print_wasmer_error(); + return 1; } #endif - wasm_instance_t* instance = wasm_instance_new(store, module, (const wasm_extern_t* const*) imports, NULL); + wasm_instance_t* instance = wasm_instance_new(store, module, &imports, NULL); if (! instance) { fprintf(stderr, "Failed to create instance\n"); print_wasmer_error(); From 5601ecb07d3cb44e508cd300dea3517801f57cec Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Fri, 16 Oct 2020 10:50:18 +0200 Subject: [PATCH 271/281] test(integration) Add `-x c` to force `clang++` to treat code as C. --- tests/integration/cli/tests/compile.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/integration/cli/tests/compile.rs b/tests/integration/cli/tests/compile.rs index 71fa6bd58..319af0bc9 100644 --- a/tests/integration/cli/tests/compile.rs +++ b/tests/integration/cli/tests/compile.rs @@ -92,6 +92,8 @@ fn run_c_compile( let output = Command::new(c_compiler) .current_dir(current_dir) + .arg("-x") + .arg("c") .arg("-O2") .arg("-c") .arg(path_to_c_src) From cb5afa1b844d48b51b06861ff20f06469948967c Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Fri, 16 Oct 2020 10:52:49 +0200 Subject: [PATCH 272/281] test(integration) Update to use the latest Wasm C API. --- .../tests/object_file_engine_test_c_source.c | 20 +++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/tests/integration/cli/tests/object_file_engine_test_c_source.c b/tests/integration/cli/tests/object_file_engine_test_c_source.c index ec00f9179..caee5c4af 100644 --- a/tests/integration/cli/tests/object_file_engine_test_c_source.c +++ b/tests/integration/cli/tests/object_file_engine_test_c_source.c @@ -30,7 +30,8 @@ int main() { wasm_store_t* store = wasm_store_new(engine); wasm_module_t* module = wasmer_object_file_engine_new(store, "qjs.wasm"); - if (! module) { + + if (!module) { printf("Failed to create module\n"); print_wasmer_error(); return -1; @@ -45,6 +46,7 @@ int main() { wasi_config_arg(wasi_config, "--eval"); wasi_config_arg(wasi_config, js_string); wasi_env_t* wasi_env = wasi_env_new(wasi_config); + if (!wasi_env) { printf("> Error building WASI env!\n"); print_wasmer_error(); @@ -53,19 +55,23 @@ int main() { wasm_importtype_vec_t import_types; wasm_module_imports(module, &import_types); - int num_imports = import_types.size; - wasm_extern_t** imports = (wasm_extern_t**) malloc(num_imports * sizeof(wasm_extern_t*)); + + wasm_extern_vec_t imports; + wasm_extern_vec_new_uninitialized(&imports, import_types.size); + wasm_importtype_vec_delete(&import_types); - bool get_imports_result = wasi_get_imports(store, module, wasi_env, imports); + bool get_imports_result = wasi_get_imports(store, module, wasi_env, &imports); + if (!get_imports_result) { printf("> Error getting WASI imports!\n"); print_wasmer_error(); return 1; } - wasm_instance_t* instance = wasm_instance_new(store, module, (const wasm_extern_t* const*) imports, NULL); - if (! instance) { + wasm_instance_t* instance = wasm_instance_new(store, module, &imports, NULL); + + if (!instance) { printf("Failed to create instance\n"); print_wasmer_error(); return -1; @@ -81,9 +87,11 @@ int main() { // We're able to call our compiled function directly through a trampoline. wasmer_trampoline_function_call__1(vmctx, wasmer_function__1, &inout); + wasm_extern_vec_delete(&imports); wasm_instance_delete(instance); wasm_module_delete(module); wasm_store_delete(store); wasm_engine_delete(engine); + return 0; } From 2fc1aaa1fe84f884c7757ccb37d5b32a38339f94 Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Fri, 16 Oct 2020 10:53:10 +0200 Subject: [PATCH 273/281] chore(test) Format code. --- .../tests/object_file_engine_test_c_source.c | 118 +++++++++--------- 1 file changed, 59 insertions(+), 59 deletions(-) diff --git a/tests/integration/cli/tests/object_file_engine_test_c_source.c b/tests/integration/cli/tests/object_file_engine_test_c_source.c index caee5c4af..7d1682624 100644 --- a/tests/integration/cli/tests/object_file_engine_test_c_source.c +++ b/tests/integration/cli/tests/object_file_engine_test_c_source.c @@ -15,83 +15,83 @@ extern "C" { void print_wasmer_error() { - int error_len = wasmer_last_error_length(); - printf("Error len: `%d`\n", error_len); - char* error_str = (char*) malloc(error_len); - wasmer_last_error_message(error_str, error_len); - printf("Error str: `%s`\n", error_str); + int error_len = wasmer_last_error_length(); + printf("Error len: `%d`\n", error_len); + char* error_str = (char*) malloc(error_len); + wasmer_last_error_message(error_str, error_len); + printf("Error str: `%s`\n", error_str); } int main() { - printf("Initializing...\n"); - wasm_config_t* config = wasm_config_new(); - wasm_config_set_engine(config, OBJECT_FILE); - wasm_engine_t* engine = wasm_engine_new_with_config(config); - wasm_store_t* store = wasm_store_new(engine); + printf("Initializing...\n"); + wasm_config_t* config = wasm_config_new(); + wasm_config_set_engine(config, OBJECT_FILE); + wasm_engine_t* engine = wasm_engine_new_with_config(config); + wasm_store_t* store = wasm_store_new(engine); - wasm_module_t* module = wasmer_object_file_engine_new(store, "qjs.wasm"); + wasm_module_t* module = wasmer_object_file_engine_new(store, "qjs.wasm"); - if (!module) { - printf("Failed to create module\n"); - print_wasmer_error(); - return -1; - } + if (!module) { + printf("Failed to create module\n"); + print_wasmer_error(); + return -1; + } - // We have now finished the memory buffer book keeping and we have a valid Module. + // We have now finished the memory buffer book keeping and we have a valid Module. - // In this example we're passing some JavaScript source code as a command line argument - // to a WASI module that can evaluate JavaScript. - wasi_config_t* wasi_config = wasi_config_new("constant_value_here"); - const char* js_string = "function greet(name) { return JSON.stringify('Hello, ' + name); }; print(greet('World'));"; - wasi_config_arg(wasi_config, "--eval"); - wasi_config_arg(wasi_config, js_string); - wasi_env_t* wasi_env = wasi_env_new(wasi_config); + // In this example we're passing some JavaScript source code as a command line argument + // to a WASI module that can evaluate JavaScript. + wasi_config_t* wasi_config = wasi_config_new("constant_value_here"); + const char* js_string = "function greet(name) { return JSON.stringify('Hello, ' + name); }; print(greet('World'));"; + wasi_config_arg(wasi_config, "--eval"); + wasi_config_arg(wasi_config, js_string); + wasi_env_t* wasi_env = wasi_env_new(wasi_config); - if (!wasi_env) { - printf("> Error building WASI env!\n"); - print_wasmer_error(); - return 1; - } + if (!wasi_env) { + printf("> Error building WASI env!\n"); + print_wasmer_error(); + return 1; + } - wasm_importtype_vec_t import_types; - wasm_module_imports(module, &import_types); + wasm_importtype_vec_t import_types; + wasm_module_imports(module, &import_types); - wasm_extern_vec_t imports; - wasm_extern_vec_new_uninitialized(&imports, import_types.size); + wasm_extern_vec_t imports; + wasm_extern_vec_new_uninitialized(&imports, import_types.size); - wasm_importtype_vec_delete(&import_types); + wasm_importtype_vec_delete(&import_types); - bool get_imports_result = wasi_get_imports(store, module, wasi_env, &imports); + bool get_imports_result = wasi_get_imports(store, module, wasi_env, &imports); - if (!get_imports_result) { - printf("> Error getting WASI imports!\n"); - print_wasmer_error(); - return 1; - } + if (!get_imports_result) { + printf("> Error getting WASI imports!\n"); + print_wasmer_error(); + return 1; + } - wasm_instance_t* instance = wasm_instance_new(store, module, &imports, NULL); + wasm_instance_t* instance = wasm_instance_new(store, module, &imports, NULL); - if (!instance) { - printf("Failed to create instance\n"); - print_wasmer_error(); - return -1; - } - wasi_env_set_instance(wasi_env, instance); + if (!instance) { + printf("Failed to create instance\n"); + print_wasmer_error(); + return -1; + } + wasi_env_set_instance(wasi_env, instance); - // WASI is now set up. + // WASI is now set up. - void* vmctx = wasm_instance_get_vmctx_ptr(instance); - wasm_val_t* inout[2] = { NULL, NULL }; + void* vmctx = wasm_instance_get_vmctx_ptr(instance); + wasm_val_t* inout[2] = { NULL, NULL }; - fflush(stdout); - // We're able to call our compiled function directly through a trampoline. - wasmer_trampoline_function_call__1(vmctx, wasmer_function__1, &inout); + fflush(stdout); + // We're able to call our compiled function directly through a trampoline. + wasmer_trampoline_function_call__1(vmctx, wasmer_function__1, &inout); - wasm_extern_vec_delete(&imports); - wasm_instance_delete(instance); - wasm_module_delete(module); - wasm_store_delete(store); - wasm_engine_delete(engine); + wasm_extern_vec_delete(&imports); + wasm_instance_delete(instance); + wasm_module_delete(module); + wasm_store_delete(store); + wasm_engine_delete(engine); - return 0; + return 0; } From 3b05c2612dfb83612838adedc6a88029872f55ec Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Fri, 16 Oct 2020 20:44:49 +0200 Subject: [PATCH 274/281] fix(c-api) Fix last edit of the `wasmer_create_exe_main.c` file. --- lib/cli/src/commands/wasmer_create_exe_main.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/cli/src/commands/wasmer_create_exe_main.c b/lib/cli/src/commands/wasmer_create_exe_main.c index 27df04324..5095fd322 100644 --- a/lib/cli/src/commands/wasmer_create_exe_main.c +++ b/lib/cli/src/commands/wasmer_create_exe_main.c @@ -135,6 +135,7 @@ int main(int argc, char* argv[]) { wasm_importtype_vec_t import_types; wasm_module_imports(module, &import_types); + wasm_extern_vec_t imports; wasm_extern_vec_new_uninitialized(&imports, import_type.size); wasm_importtype_vec_delete(&import_types); @@ -150,7 +151,8 @@ int main(int argc, char* argv[]) { #endif wasm_instance_t* instance = wasm_instance_new(store, module, &imports, NULL); - if (! instance) { + + if (!instance) { fprintf(stderr, "Failed to create instance\n"); print_wasmer_error(); return -1; From 1cdb5b58768d6203afbec90b2efb457d26dbb90c Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Fri, 16 Oct 2020 21:24:36 +0200 Subject: [PATCH 275/281] fix(c-api) Fix another typo. Damn. --- lib/cli/src/commands/wasmer_create_exe_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/cli/src/commands/wasmer_create_exe_main.c b/lib/cli/src/commands/wasmer_create_exe_main.c index 5095fd322..bc5ecf782 100644 --- a/lib/cli/src/commands/wasmer_create_exe_main.c +++ b/lib/cli/src/commands/wasmer_create_exe_main.c @@ -136,7 +136,7 @@ int main(int argc, char* argv[]) { wasm_module_imports(module, &import_types); wasm_extern_vec_t imports; - wasm_extern_vec_new_uninitialized(&imports, import_type.size); + wasm_extern_vec_new_uninitialized(&imports, import_types.size); wasm_importtype_vec_delete(&import_types); #ifdef WASI From 9955da1eccdae7a6ace28515d587ca94beff9910 Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Fri, 16 Oct 2020 21:30:53 +0200 Subject: [PATCH 276/281] test: Remove a warning fix for Windows. Windows will raise a warning because `clang++` is used to handle C code, so I previously add `-x c` to tell `clang++` to handle code as C code. Bbut if code is treated as C, it will fail because `static_assert` is not available for C on Windows. So let's live with the warning. --- tests/integration/cli/tests/compile.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/tests/integration/cli/tests/compile.rs b/tests/integration/cli/tests/compile.rs index 319af0bc9..71fa6bd58 100644 --- a/tests/integration/cli/tests/compile.rs +++ b/tests/integration/cli/tests/compile.rs @@ -92,8 +92,6 @@ fn run_c_compile( let output = Command::new(c_compiler) .current_dir(current_dir) - .arg("-x") - .arg("c") .arg("-O2") .arg("-c") .arg(path_to_c_src) From d562c2dd9c60a02122618550dff047196bf0b79d Mon Sep 17 00:00:00 2001 From: Nick Lewycky Date: Fri, 16 Oct 2020 16:29:45 -0700 Subject: [PATCH 277/281] Sometimes the store may be partially-successful before trapping, for instance if it is partways in valid memory and partways into the guard page. Use a load instruction before the store to ensure that all the memory is addressable. The loaded value is discarded. NB. We don't apply this to atomics. It's not clear whether atomic stores can be half-committed. Fixes align.wast and memory_trap.wast on aarch64. --- lib/compiler-llvm/src/translator/code.rs | 56 ++++++++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/lib/compiler-llvm/src/translator/code.rs b/lib/compiler-llvm/src/translator/code.rs index caca847da..c5e45334a 100644 --- a/lib/compiler-llvm/src/translator/code.rs +++ b/lib/compiler-llvm/src/translator/code.rs @@ -6286,6 +6286,13 @@ impl<'ctx, 'a> LLVMFunctionCodeGenerator<'ctx, 'a> { offset, 4, )?; + let dead_load = self.builder.build_load(effective_address, ""); + self.annotate_user_memaccess( + memory_index, + memarg, + 1, + dead_load.as_instruction_value().unwrap(), + )?; let store = self.builder.build_store(effective_address, value); self.annotate_user_memaccess(memory_index, memarg, 1, store)?; } @@ -6300,6 +6307,13 @@ impl<'ctx, 'a> LLVMFunctionCodeGenerator<'ctx, 'a> { offset, 8, )?; + let dead_load = self.builder.build_load(effective_address, ""); + self.annotate_user_memaccess( + memory_index, + memarg, + 1, + dead_load.as_instruction_value().unwrap(), + )?; let store = self.builder.build_store(effective_address, value); self.annotate_user_memaccess(memory_index, memarg, 1, store)?; } @@ -6315,6 +6329,13 @@ impl<'ctx, 'a> LLVMFunctionCodeGenerator<'ctx, 'a> { offset, 4, )?; + let dead_load = self.builder.build_load(effective_address, ""); + self.annotate_user_memaccess( + memory_index, + memarg, + 1, + dead_load.as_instruction_value().unwrap(), + )?; let store = self.builder.build_store(effective_address, v); self.annotate_user_memaccess(memory_index, memarg, 1, store)?; } @@ -6330,6 +6351,13 @@ impl<'ctx, 'a> LLVMFunctionCodeGenerator<'ctx, 'a> { offset, 8, )?; + let dead_load = self.builder.build_load(effective_address, ""); + self.annotate_user_memaccess( + memory_index, + memarg, + 1, + dead_load.as_instruction_value().unwrap(), + )?; let store = self.builder.build_store(effective_address, v); self.annotate_user_memaccess(memory_index, memarg, 1, store)?; } @@ -6345,6 +6373,13 @@ impl<'ctx, 'a> LLVMFunctionCodeGenerator<'ctx, 'a> { offset, 16, )?; + let dead_load = self.builder.build_load(effective_address, ""); + self.annotate_user_memaccess( + memory_index, + memarg, + 1, + dead_load.as_instruction_value().unwrap(), + )?; let store = self.builder.build_store(effective_address, v); self.annotate_user_memaccess(memory_index, memarg, 1, store)?; } @@ -6603,6 +6638,13 @@ impl<'ctx, 'a> LLVMFunctionCodeGenerator<'ctx, 'a> { offset, 1, )?; + let dead_load = self.builder.build_load(effective_address, ""); + self.annotate_user_memaccess( + memory_index, + memarg, + 1, + dead_load.as_instruction_value().unwrap(), + )?; let narrow_value = self.builder .build_int_truncate(value, self.intrinsics.i8_ty, ""); @@ -6620,6 +6662,13 @@ impl<'ctx, 'a> LLVMFunctionCodeGenerator<'ctx, 'a> { offset, 2, )?; + let dead_load = self.builder.build_load(effective_address, ""); + self.annotate_user_memaccess( + memory_index, + memarg, + 1, + dead_load.as_instruction_value().unwrap(), + )?; let narrow_value = self.builder .build_int_truncate(value, self.intrinsics.i16_ty, ""); @@ -6637,6 +6686,13 @@ impl<'ctx, 'a> LLVMFunctionCodeGenerator<'ctx, 'a> { offset, 4, )?; + let dead_load = self.builder.build_load(effective_address, ""); + self.annotate_user_memaccess( + memory_index, + memarg, + 1, + dead_load.as_instruction_value().unwrap(), + )?; let narrow_value = self.builder .build_int_truncate(value, self.intrinsics.i32_ty, ""); From 259c928c256163d5380687888c971e45c3727e6d Mon Sep 17 00:00:00 2001 From: Nick Lewycky Date: Fri, 16 Oct 2020 16:58:29 -0700 Subject: [PATCH 278/281] Thread canonicalize_nans through these utils functions and into the callers. --- tests/compilers/imports.rs | 12 ++++++------ tests/compilers/multi_value_imports.rs | 4 ++-- tests/compilers/native_functions.rs | 10 +++++----- tests/compilers/serialize.rs | 4 ++-- tests/compilers/traps.rs | 26 +++++++++++++------------- tests/compilers/utils.rs | 13 ++++++------- 6 files changed, 34 insertions(+), 35 deletions(-) diff --git a/tests/compilers/imports.rs b/tests/compilers/imports.rs index fa7a34bd4..b73501f41 100644 --- a/tests/compilers/imports.rs +++ b/tests/compilers/imports.rs @@ -43,7 +43,7 @@ fn get_module(store: &Store) -> Result { #[test] fn dynamic_function() -> Result<()> { - let store = get_store(); + let store = get_store(false); let module = get_module(&store)?; static HITS: AtomicUsize = AtomicUsize::new(0); Instance::new( @@ -83,7 +83,7 @@ fn dynamic_function() -> Result<()> { #[test] fn dynamic_function_with_env() -> Result<()> { - let store = get_store(); + let store = get_store(false); let module = get_module(&store)?; let env: Arc = Arc::new(AtomicUsize::new(0)); @@ -124,7 +124,7 @@ fn dynamic_function_with_env() -> Result<()> { #[test] fn static_function() -> Result<()> { - let store = get_store(); + let store = get_store(false); let module = get_module(&store)?; static HITS: AtomicUsize = AtomicUsize::new(0); @@ -162,7 +162,7 @@ fn static_function() -> Result<()> { #[test] fn static_function_with_results() -> Result<()> { - let store = get_store(); + let store = get_store(false); let module = get_module(&store)?; static HITS: AtomicUsize = AtomicUsize::new(0); @@ -200,7 +200,7 @@ fn static_function_with_results() -> Result<()> { #[test] fn static_function_with_env() -> Result<()> { - let store = get_store(); + let store = get_store(false); let module = get_module(&store)?; let env: Arc = Arc::new(AtomicUsize::new(0)); @@ -238,7 +238,7 @@ fn static_function_with_env() -> Result<()> { #[test] fn static_function_that_fails() -> Result<()> { - let store = get_store(); + let store = get_store(false); let wat = r#" (import "host" "0" (func)) diff --git a/tests/compilers/multi_value_imports.rs b/tests/compilers/multi_value_imports.rs index d580b01b3..7aa85a595 100644 --- a/tests/compilers/multi_value_imports.rs +++ b/tests/compilers/multi_value_imports.rs @@ -39,7 +39,7 @@ macro_rules! mvr_test { #[test] #[cfg_attr(any(feature = "test-cranelift", feature="test-singlepass"), ignore)] fn native() -> anyhow::Result<()> { - let store = get_store(); + let store = get_store(false); let module = get_module(&store)?; let instance = wasmer::Instance::new( &module, @@ -65,7 +65,7 @@ macro_rules! mvr_test { #[test] #[cfg_attr(feature="test-singlepass", ignore)] fn dynamic() -> anyhow::Result<()> { - let store = get_store(); + let store = get_store(false); let module = get_module(&store)?; let callback_fn = wasmer::Function::new(&store, &wasmer::FunctionType::new(vec![wasmer::ValType::I32], vec![ $( <$result_type>::expected_valtype() ),* ]), dynamic_callback_fn); let instance = wasmer::Instance::new( diff --git a/tests/compilers/native_functions.rs b/tests/compilers/native_functions.rs index 3a37cb31b..66b3fada8 100644 --- a/tests/compilers/native_functions.rs +++ b/tests/compilers/native_functions.rs @@ -8,7 +8,7 @@ use wasmer::*; #[test] fn native_function_works_for_wasm() -> Result<()> { - let store = get_store(); + let store = get_store(false); let wat = r#"(module (func $multiply (import "env" "multiply") (param i32 i32) (result i32)) (func (export "add") (param i32 i32) (result i32) @@ -52,7 +52,7 @@ fn native_function_works_for_wasm() -> Result<()> { #[test] fn static_host_function_without_env() -> anyhow::Result<()> { - let store = get_store(); + let store = get_store(false); fn f(a: i32, b: i64, c: f32, d: f64) -> (f64, f32, i64, i32) { (d * 4.0, c * 3.0, b * 2, a * 1) @@ -83,7 +83,7 @@ fn static_host_function_without_env() -> anyhow::Result<()> { #[test] fn static_host_function_with_env() -> anyhow::Result<()> { - let store = get_store(); + let store = get_store(false); fn f(env: &mut Env, a: i32, b: i64, c: f32, d: f64) -> (f64, f32, i64, i32) { assert_eq!(*env.0.borrow(), 100); @@ -143,7 +143,7 @@ fn static_host_function_with_env() -> anyhow::Result<()> { #[test] fn dynamic_host_function_without_env() -> anyhow::Result<()> { - let store = get_store(); + let store = get_store(false); let f = Function::new( &store, @@ -170,7 +170,7 @@ fn dynamic_host_function_without_env() -> anyhow::Result<()> { #[test] fn dynamic_host_function_with_env() -> anyhow::Result<()> { - let store = get_store(); + let store = get_store(false); #[derive(Clone)] struct Env(Rc>); diff --git a/tests/compilers/serialize.rs b/tests/compilers/serialize.rs index db1b0957b..f417226f0 100644 --- a/tests/compilers/serialize.rs +++ b/tests/compilers/serialize.rs @@ -4,7 +4,7 @@ use wasmer::*; #[test] fn test_serialize() -> Result<()> { - let store = get_store(); + let store = get_store(false); let wat = r#" (module (func $hello (import "" "hello")) @@ -20,7 +20,7 @@ fn test_serialize() -> Result<()> { #[test] fn test_deserialize() -> Result<()> { - let store = get_store(); + let store = get_store(false); let wat = r#" (module $name (import "host" "sum_part" (func (param i32 i64 i32 f32 f64) (result i64))) diff --git a/tests/compilers/traps.rs b/tests/compilers/traps.rs index 7b1944ba3..a9fb846c6 100644 --- a/tests/compilers/traps.rs +++ b/tests/compilers/traps.rs @@ -5,7 +5,7 @@ use wasmer::*; #[test] fn test_trap_return() -> Result<()> { - let store = get_store(); + let store = get_store(false); let wat = r#" (module (func $hello (import "" "hello")) @@ -47,7 +47,7 @@ fn test_trap_return() -> Result<()> { ignore )] fn test_trap_trace() -> Result<()> { - let store = get_store(); + let store = get_store(false); let wat = r#" (module $hello_mod (func (export "run") (call $hello)) @@ -83,7 +83,7 @@ fn test_trap_trace() -> Result<()> { #[test] fn test_trap_trace_cb() -> Result<()> { - let store = get_store(); + let store = get_store(false); let wat = r#" (module $hello_mod (import "" "throw" (func $throw)) @@ -134,7 +134,7 @@ fn test_trap_trace_cb() -> Result<()> { ignore )] fn test_trap_stack_overflow() -> Result<()> { - let store = get_store(); + let store = get_store(false); let wat = r#" (module $rec_mod (func $run (export "run") (call $run)) @@ -173,7 +173,7 @@ fn test_trap_stack_overflow() -> Result<()> { ignore )] fn trap_display_pretty() -> Result<()> { - let store = get_store(); + let store = get_store(false); let wat = r#" (module $m (func $die unreachable) @@ -214,7 +214,7 @@ RuntimeError: unreachable ignore )] fn trap_display_multi_module() -> Result<()> { - let store = get_store(); + let store = get_store(false); let wat = r#" (module $a (func $die unreachable) @@ -266,7 +266,7 @@ RuntimeError: unreachable #[test] fn trap_start_function_import() -> Result<()> { - let store = get_store(); + let store = get_store(false); let binary = r#" (module $a (import "" "" (func $foo)) @@ -299,7 +299,7 @@ fn trap_start_function_import() -> Result<()> { #[test] fn rust_panic_import() -> Result<()> { - let store = get_store(); + let store = get_store(false); let binary = r#" (module $a (import "" "foo" (func $foo)) @@ -344,7 +344,7 @@ fn rust_panic_import() -> Result<()> { #[test] fn rust_panic_start_function() -> Result<()> { - let store = get_store(); + let store = get_store(false); let binary = r#" (module $a (import "" "" (func $foo)) @@ -389,7 +389,7 @@ fn rust_panic_start_function() -> Result<()> { #[test] fn mismatched_arguments() -> Result<()> { - let store = get_store(); + let store = get_store(false); let binary = r#" (module $a (func (export "foo") (param i32)) @@ -426,7 +426,7 @@ fn mismatched_arguments() -> Result<()> { ignore )] fn call_signature_mismatch() -> Result<()> { - let store = get_store(); + let store = get_store(false); let binary = r#" (module $a (func $foo @@ -465,7 +465,7 @@ RuntimeError: indirect call type mismatch ignore )] fn start_trap_pretty() -> Result<()> { - let store = get_store(); + let store = get_store(false); let wat = r#" (module $m (func $die unreachable) @@ -497,7 +497,7 @@ RuntimeError: unreachable #[test] #[cfg_attr(feature = "test-native", ignore)] fn present_after_module_drop() -> Result<()> { - let store = get_store(); + let store = get_store(false); let module = Module::new(&store, r#"(func (export "foo") unreachable)"#)?; let instance = Instance::new(&module, &imports! {})?; let func: Function = instance.exports.get_function("foo")?.clone(); diff --git a/tests/compilers/utils.rs b/tests/compilers/utils.rs index 675240b32..7173ecc20 100644 --- a/tests/compilers/utils.rs +++ b/tests/compilers/utils.rs @@ -36,18 +36,18 @@ pub fn get_compiler(canonicalize_nans: bool) -> impl CompilerConfig { } #[cfg(feature = "test-jit")] -pub fn get_engine() -> impl Engine { - let compiler_config = get_compiler(false); +pub fn get_engine(canonicalize_nans: bool) -> impl Engine { + let compiler_config = get_compiler(canonicalize_nans); JIT::new(&compiler_config).engine() } #[cfg(feature = "test-native")] -pub fn get_engine() -> impl Engine { - let mut compiler_config = get_compiler(false); +pub fn get_engine(canonicalize_nans: bool) -> impl Engine { + let mut compiler_config = get_compiler(canonicalize_nans); Native::new(&mut compiler_config).engine() } -pub fn get_store() -> Store { - Store::new(&get_engine()) +pub fn get_store(canonicalize_nans: bool) -> Store { + Store::new(&get_engine(canonicalize_nans)) } pub fn get_store_with_middlewares>>( @@ -67,7 +67,6 @@ pub fn get_store_with_middlewares Store { Store::new(&JIT::headless().engine()) - // Store::new(&Native::headless().engine()) } #[cfg(feature = "test-native")] From 797db5cd650086680af88b53cec689d39df3abc2 Mon Sep 17 00:00:00 2001 From: Nick Lewycky Date: Fri, 16 Oct 2020 17:01:50 -0700 Subject: [PATCH 279/281] wasi tests should use whichever enginer we're testing. --- tests/compilers/wasi.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/tests/compilers/wasi.rs b/tests/compilers/wasi.rs index 00ab496ca..ac746826d 100644 --- a/tests/compilers/wasi.rs +++ b/tests/compilers/wasi.rs @@ -1,6 +1,6 @@ #![cfg(all(feature = "compiler", feature = "engine"))] -use crate::utils::get_compiler; +use crate::utils::get_store; use std::fs::File; use std::io::Read; use wasmer::Store; @@ -25,8 +25,7 @@ pub fn run_wasi(wast_path: &str, base_dir: &str, compiler: &str) -> anyhow::Resu "Running wasi wast `{}` with the {} compiler", wast_path, compiler ); - let compiler_config = get_compiler(true); - let store = Store::new(&JIT::new(&compiler_config).engine()); + let store = get_store(true); let source = { let mut out = String::new(); From f11f231acc1c3e947351dfab367500dbbd078aca Mon Sep 17 00:00:00 2001 From: Nick Lewycky Date: Fri, 16 Oct 2020 17:02:48 -0700 Subject: [PATCH 280/281] Remove unused imports. --- tests/compilers/wasi.rs | 3 --- 1 file changed, 3 deletions(-) diff --git a/tests/compilers/wasi.rs b/tests/compilers/wasi.rs index ac746826d..fc3497b3b 100644 --- a/tests/compilers/wasi.rs +++ b/tests/compilers/wasi.rs @@ -3,9 +3,6 @@ use crate::utils::get_store; use std::fs::File; use std::io::Read; -use wasmer::Store; -#[cfg(feature = "jit")] -use wasmer_engine_jit::JIT; use wasmer_wast::WasiTest; // The generated tests (from build.rs) look like: From 1bb3b99319633fa35541f822f92a78e3cc893bc3 Mon Sep 17 00:00:00 2001 From: Syrus Akbary Date: Fri, 16 Oct 2020 22:26:28 -0700 Subject: [PATCH 281/281] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index bb884f125..bddeba897 100644 --- a/README.md +++ b/README.md @@ -35,7 +35,7 @@ * **Pluggable**. Wasmer supports different compilation frameworks to best suit your needs (LLVM, Cranelift...). -* **Universal**. You can run Wasmer in almost any *platform* (macOS, Linux and Windows) and *chipset*. +* **Universal**. You can run Wasmer in any *platform* (macOS, Linux and Windows) and *chipset*. * **Standards compliant**. The runtime passes [official WebAssembly test suite](https://github.com/WebAssembly/testsuite) supporting [WASI](https://github.com/WebAssembly/WASI) and [Emscripten](https://emscripten.org/).