From cca551be4a3dd300244b497530f470fae61e9ec4 Mon Sep 17 00:00:00 2001 From: Syrus Date: Thu, 4 Jun 2020 13:21:08 -0700 Subject: [PATCH 01/44] Added first compiler target iteration --- lib/api/src/lib.rs | 6 +- lib/api/src/module.rs | 12 ++-- lib/compiler/src/lib.rs | 2 +- lib/compiler/src/target.rs | 8 ++- lib/engine-native/src/artifact.rs | 100 +++++++++++++++++++++++++++--- lib/engine/src/artifact.rs | 6 ++ src/commands/compile.rs | 22 ++++++- src/store.rs | 46 ++++++-------- 8 files changed, 154 insertions(+), 48 deletions(-) diff --git a/lib/api/src/lib.rs b/lib/api/src/lib.rs index f9673812bd6..d70d301ccfc 100644 --- a/lib/api/src/lib.rs +++ b/lib/api/src/lib.rs @@ -29,11 +29,13 @@ pub use crate::types::{ }; pub use crate::types::{Val as Value, ValType as Type}; -pub use target_lexicon::{Architecture, OperatingSystem, Triple, HOST}; +pub use target_lexicon::{ + Architecture, CallingConvention, OperatingSystem, ParseError as TargetParseError, Triple, HOST, +}; pub use wasm_common::{Bytes, Pages, ValueType, WasmExternType, WasmTypeList}; #[cfg(feature = "compiler")] pub use wasmer_compiler::CompilerConfig; -pub use wasmer_compiler::{Features, Target}; +pub use wasmer_compiler::{CpuFeature, Features, Target}; pub use wasmer_engine::{ ChainableNamedResolver, DeserializeError, Engine, InstantiationError, LinkError, NamedResolver, NamedResolverChain, Resolver, RuntimeError, SerializeError, diff --git a/lib/api/src/module.rs b/lib/api/src/module.rs index 26c82ffd3a2..77d9fa75304 100644 --- a/lib/api/src/module.rs +++ b/lib/api/src/module.rs @@ -167,8 +167,8 @@ impl Module { } fn compile(store: &Store, binary: &[u8]) -> Result { - let compiled = store.engine().compile(binary)?; - Ok(Self::from_compiled_module(store, compiled)) + let artifact = store.engine().compile(binary)?; + Ok(Self::from_artifact(store, artifact)) } /// Serializes a module into a binary representation that the `Engine` @@ -231,8 +231,8 @@ impl Module { /// # } /// ``` pub unsafe fn deserialize(store: &Store, bytes: &[u8]) -> Result { - let compiled = store.engine().deserialize(bytes)?; - Ok(Self::from_compiled_module(store, compiled)) + let artifact = store.engine().deserialize(bytes)?; + Ok(Self::from_artifact(store, artifact)) } /// Deserializes a a serialized Module located in a `Path` into a `Module`. @@ -257,10 +257,10 @@ impl Module { path: impl AsRef, ) -> Result { let artifact = store.engine().deserialize_from_file(path.as_ref())?; - Ok(Self::from_compiled_module(store, artifact)) + Ok(Self::from_artifact(store, artifact)) } - fn from_compiled_module(store: &Store, artifact: Arc) -> Self { + fn from_artifact(store: &Store, artifact: Arc) -> Self { Module { store: store.clone(), artifact, diff --git a/lib/compiler/src/lib.rs b/lib/compiler/src/lib.rs index c81bcfc2783..f5a29ca6d5c 100644 --- a/lib/compiler/src/lib.rs +++ b/lib/compiler/src/lib.rs @@ -80,7 +80,7 @@ pub use crate::relocation::{Relocation, RelocationKind, RelocationTarget, Reloca pub use crate::section::{CustomSection, CustomSectionProtection, SectionBody, SectionIndex}; pub use crate::sourceloc::SourceLoc; pub use crate::target::{ - Architecture, CallingConvention, CpuFeature, OperatingSystem, Target, Triple, + Architecture, BinaryFormat, CallingConvention, CpuFeature, OperatingSystem, Target, Triple, }; #[cfg(feature = "translator")] pub use crate::translator::{ diff --git a/lib/compiler/src/target.rs b/lib/compiler/src/target.rs index fe85f663305..256ecdffcb4 100644 --- a/lib/compiler/src/target.rs +++ b/lib/compiler/src/target.rs @@ -1,6 +1,6 @@ //! Target configuration use enumset::{EnumSet, EnumSetType}; -pub use target_lexicon::{Architecture, CallingConvention, OperatingSystem, Triple}; +pub use target_lexicon::{Architecture, BinaryFormat, CallingConvention, OperatingSystem, Triple}; #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] use raw_cpuid::CpuId; @@ -98,6 +98,12 @@ impl CpuFeature { // We default to an empty hash set EnumSet::new() } + + /// Retrieves an empty set of `CpuFeature`s. + pub fn set() -> EnumSet { + // We default to an empty hash set + EnumSet::new() + } } /// This is the target that we will use for compiling diff --git a/lib/engine-native/src/artifact.rs b/lib/engine-native/src/artifact.rs index f6a2cd25fe0..5752042e65c 100644 --- a/lib/engine-native/src/artifact.rs +++ b/lib/engine-native/src/artifact.rs @@ -19,8 +19,10 @@ use wasm_common::{ }; #[cfg(feature = "compiler")] use wasmer_compiler::ModuleEnvironment; -use wasmer_compiler::{CompileError, Features, RelocationTarget}; -use wasmer_engine::{Artifact, DeserializeError, Engine, SerializeError}; +use wasmer_compiler::{BinaryFormat, CompileError, Features, RelocationTarget, Triple}; +use wasmer_engine::{ + Artifact, DeserializeError, Engine, InstantiationError, LinkError, RuntimeError, SerializeError, +}; use wasmer_runtime::{MemoryPlan, TablePlan}; use wasmer_runtime::{ModuleInfo, VMFunctionBody, VMSharedSignatureIndex, VMTrampoline}; @@ -29,7 +31,7 @@ pub struct NativeArtifact { sharedobject_path: PathBuf, metadata: ModuleMetadata, #[allow(dead_code)] - library: Library, + library: Option, finished_functions: BoxedSlice, finished_dynamic_function_trampolines: BoxedSlice, signatures: BoxedSlice, @@ -139,8 +141,17 @@ impl NativeArtifact { .collect::>() .into_boxed_slice(); - let target = compiler.target().triple().clone(); - let mut obj = ArtifactBuilder::new(target) + let target = compiler.target(); + let target_triple = target.triple().clone(); + if target_triple.binary_format != BinaryFormat::Elf + && target_triple.binary_format != BinaryFormat::Macho + { + return Err(CompileError::Codegen(format!( + "Binary format {} not supported", + target_triple.binary_format + ))); + } + let mut obj = ArtifactBuilder::new(target_triple.clone()) .name("module".to_string()) .library(true) .finish(); @@ -190,7 +201,7 @@ impl NativeArtifact { "wasmer_raise_trap", "wasmer_probestack", ]; - for libcall in libcalls.into_iter() { + for libcall in libcalls.iter() { obj.declare(libcall, Decl::function_import()) .map_err(to_compile_error)?; obj.declare(&format!("_{}", libcall), Decl::function_import()) @@ -279,11 +290,40 @@ impl NativeArtifact { let shared_file = NamedTempFile::new().map_err(to_compile_error)?; let (_file, shared_filepath) = shared_file.keep().map_err(to_compile_error)?; + let wasmer_symbols = libcalls + .iter() + .map(|libcall| { + match target_triple.binary_format { + BinaryFormat::Macho => format!("-Wl,-U,_{}", libcall), + BinaryFormat::Elf => format!("-Wl,--undefined={}", libcall), + binary_format => { + // We should already be filtering only valid binary formats before + // so this should never happen. + unreachable!() + } + } + }) + .collect::>(); + + let is_cross_compiling = target_triple != Triple::host(); + let cross_compiling_args = if is_cross_compiling { + vec![ + format!("--target={}", target_triple), + "-fuse-ld=lld".to_string(), + ] + } else { + vec![] + }; let output = Command::new("gcc") .arg(&filepath) + .arg("-nostartfiles") + .arg("-nodefaultlibs") + .arg("-nostdlib") .arg("-o") .arg(&shared_filepath) + .args(&wasmer_symbols) .arg("-shared") + .args(&cross_compiling_args) .arg("-v") .output() .map_err(to_compile_error)?; @@ -294,8 +334,15 @@ impl NativeArtifact { std::str::from_utf8(&output.stderr).unwrap().trim_end() ))); } - let lib = Library::new(&shared_filepath).map_err(to_compile_error)?; - Self::from_parts(&mut engine_inner, metadata, shared_filepath, lib) + // println!("Stdout: {}", String::from_utf8(output.stdout).unwrap()); + // println!("Stderr: {}", String::from_utf8(output.stderr).unwrap()); + // println!("shared_filepath {:?}", shared_filepath); + if is_cross_compiling { + Self::from_parts_crosscompiled(&mut engine_inner, metadata, shared_filepath) + } else { + let lib = Library::new(&shared_filepath).map_err(to_compile_error)?; + Self::from_parts(&mut engine_inner, metadata, shared_filepath, lib) + } } fn get_function_name(metadata: &ModuleMetadata, index: LocalFunctionIndex) -> String { @@ -324,6 +371,30 @@ impl NativeArtifact { ) } + /// Construct a `NativeArtifact` from component parts. + pub fn from_parts_crosscompiled( + engine_inner: &mut NativeEngineInner, + metadata: ModuleMetadata, + sharedobject_path: PathBuf, + ) -> Result { + let mut finished_functions: PrimaryMap = + PrimaryMap::new(); + let mut finished_dynamic_function_trampolines: PrimaryMap< + FunctionIndex, + *const VMFunctionBody, + > = PrimaryMap::new(); + let signatures: PrimaryMap = PrimaryMap::new(); + Ok(Self { + sharedobject_path, + metadata, + library: None, + 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 `NativeArtifact` from component parts. pub fn from_parts( engine_inner: &mut NativeEngineInner, @@ -336,7 +407,7 @@ impl NativeArtifact { for (function_local_index, function_len) in metadata.function_body_lengths.iter() { let function_name = Self::get_function_name(&metadata, function_local_index); unsafe { - // We use a fake funciton signature `fn()` because we just + // We use a fake function signature `fn()` because we just // want to get the function address. let func: Symbol = lib .get(function_name.as_bytes()) @@ -411,7 +482,7 @@ impl NativeArtifact { Ok(Self { sharedobject_path, metadata, - library: lib, + library: Some(lib), finished_functions: finished_functions.into_boxed_slice(), finished_dynamic_function_trampolines: finished_dynamic_function_trampolines .into_boxed_slice(), @@ -419,6 +490,15 @@ impl NativeArtifact { }) } + 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(()) + } + /// Compile a data buffer into a `NativeArtifact`, which may then be instantiated. #[cfg(not(feature = "compiler"))] pub fn new(engine: &NativeEngine, data: &[u8]) -> Result { diff --git a/lib/engine/src/artifact.rs b/lib/engine/src/artifact.rs index c4a00a07c96..c7ac9279337 100644 --- a/lib/engine/src/artifact.rs +++ b/lib/engine/src/artifact.rs @@ -73,6 +73,11 @@ pub trait Artifact { Ok(()) } + /// Do preinstantiation logic that is executed before instantiating + fn preinstantiate(&self) -> Result<(), InstantiationError> { + Ok(()) + } + /// Crate an `Instance` from this `Artifact`. /// /// # Unsafety @@ -84,6 +89,7 @@ pub trait Artifact { resolver: &dyn Resolver, host_state: Box, ) -> Result { + let _ = self.preinstantiate()?; let module = self.module(); let imports = resolve_imports( &module, diff --git a/src/commands/compile.rs b/src/commands/compile.rs index 01771961d9d..e64a87e0367 100644 --- a/src/commands/compile.rs +++ b/src/commands/compile.rs @@ -2,9 +2,14 @@ use crate::store::StoreOptions; use crate::warning; use anyhow::{Context, Result}; use std::path::PathBuf; +use std::str::FromStr; use structopt::StructOpt; use wasmer::*; +fn parse_target_triple(src: &str) -> Result { + Triple::from_str(src) +} + #[derive(Debug, StructOpt)] /// The options for the `wasmer compile` subcommand pub struct Compile { @@ -16,6 +21,10 @@ pub struct Compile { #[structopt(name = "OUTPUT", short = "o", parse(from_os_str))] output: PathBuf, + /// Compilation Target triple + #[structopt(long = "target", parse(try_from_str = parse_target_triple))] + target_triple: Option, + #[structopt(flatten)] compiler: StoreOptions, } @@ -27,13 +36,22 @@ impl Compile { .context(format!("failed to compile `{}`", self.path.display())) } fn inner_execute(&self) -> Result<()> { - let (store, engine_name, compiler_name) = self.compiler.get_store()?; + let target = if let Some(ref target_triple) = self.target_triple { + let mut features = CpuFeature::set(); + // Cranelift requires SSE2, so we have this "hack" for now until + // we are able to pass custom features + features = features | CpuFeature::SSE2; + Target::new(target_triple.clone(), features) + } else { + Target::default() + }; + let (store, engine_name, compiler_name) = + self.compiler.get_store_for_target(target.clone())?; let output_filename = self .output .file_stem() .map(|osstr| osstr.to_string_lossy().to_string()) .unwrap_or_default(); - let target = self.compiler.get_target()?; let recommended_extension = match engine_name.as_ref() { "native" => { // TODO: Match it depending on the `BinaryFormat` instead of the diff --git a/src/store.rs b/src/store.rs index 54ce50f578c..38883b49cff 100644 --- a/src/store.rs +++ b/src/store.rs @@ -131,17 +131,12 @@ impl StoreOptions { Ok(features) } - /// Get the Target architecture - pub fn get_target(&self) -> Result { - Ok(Target::default()) - } - /// Get the Compiler Config for the current options #[allow(unused_variables)] - fn get_config(&self, compiler: Compiler) -> Result> { + fn get_compiler_config(&self, target: Target) -> Result<(Box, String)> { + let compiler = self.get_compiler()?; let features = self.get_features()?; - let target = self.get_target()?; - let config: Box = match compiler { + let compiler_config: Box = match compiler { #[cfg(feature = "singlepass")] Compiler::Singlepass => { let config = wasmer_compiler_singlepass::SinglepassConfig::new(features, target); @@ -248,14 +243,7 @@ impl StoreOptions { compiler.to_string() ), }; - Ok(config) - } - - /// Gets the compiler config - fn get_compiler_config(&self) -> Result<(Box, String)> { - let compiler = self.get_compiler()?; let compiler_name = compiler.to_string(); - let compiler_config = self.get_config(compiler)?; Ok((compiler_config, compiler_name)) } @@ -264,9 +252,15 @@ impl StoreOptions { Tunables::for_target(compiler_config.target().triple()) } - /// Gets the store, with the engine name and compiler name selected + /// Gets the store for the host target, with the engine name and compiler name selected pub fn get_store(&self) -> Result<(Store, String, String)> { - let (compiler_config, compiler_name) = self.get_compiler_config()?; + let target = Target::default(); + self.get_store_for_target(target) + } + + /// Gets the store for a given target, with the engine name and compiler name selected, as + pub fn get_store_for_target(&self, target: Target) -> Result<(Store, String, String)> { + let (compiler_config, compiler_name) = self.get_compiler_config(target)?; let tunables = self.get_tunables(&*compiler_config); let (engine, engine_name) = self.get_engine_with_compiler(tunables, compiler_config)?; let store = Store::new(engine); @@ -357,11 +351,6 @@ impl StoreOptions { return Ok((engine, engine_type.to_string())); } - /// Get the Target architecture - pub fn get_target(&self) -> Result { - Ok(Target::default()) - } - /// Get the store (headless engine) pub fn get_store(&self) -> Result<(Store, String, String)> { // Get the tunables for the current host @@ -370,18 +359,23 @@ impl StoreOptions { let store = Store::new(engine); Ok((store, engine_name, "headless".to_string())) } + + /// Gets the store for provided host target + pub fn get_store_for_target(&self, target: Target) -> Result<(Store, String, String)> { + bail!("You need compilers to run get a store in a specific target"); + } } // If we don't have any engine enabled #[cfg(not(feature = "engine"))] impl StoreOptions { - /// Get the Target architecture - pub fn get_target(&self) -> Result { + /// Get the store (headless engine) + pub fn get_store(&self) -> Result<(Store, String, String)> { bail!("No engines are enabled"); } - /// Get the store (headless engine) - pub fn get_store(&self) -> Result<(Store, String, String)> { + /// Gets the store for the host target + pub fn get_store_for_target(&self, target: Target) -> Result<(Store, String, String)> { bail!("No engines are enabled"); } } From bfb9f83fdd7cff6b984e6844d92412d1cefcae3c Mon Sep 17 00:00:00 2001 From: Syrus Date: Thu, 4 Jun 2020 13:55:33 -0700 Subject: [PATCH 02/44] Fixed linting issues --- lib/engine-native/src/artifact.rs | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/lib/engine-native/src/artifact.rs b/lib/engine-native/src/artifact.rs index 5752042e65c..572ba43c612 100644 --- a/lib/engine-native/src/artifact.rs +++ b/lib/engine-native/src/artifact.rs @@ -296,7 +296,7 @@ impl NativeArtifact { match target_triple.binary_format { BinaryFormat::Macho => format!("-Wl,-U,_{}", libcall), BinaryFormat::Elf => format!("-Wl,--undefined={}", libcall), - binary_format => { + _ => { // We should already be filtering only valid binary formats before // so this should never happen. unreachable!() @@ -338,7 +338,7 @@ impl NativeArtifact { // println!("Stderr: {}", String::from_utf8(output.stderr).unwrap()); // println!("shared_filepath {:?}", shared_filepath); if is_cross_compiling { - Self::from_parts_crosscompiled(&mut engine_inner, metadata, shared_filepath) + Self::from_parts_crosscompiled(metadata, shared_filepath) } else { let lib = Library::new(&shared_filepath).map_err(to_compile_error)?; Self::from_parts(&mut engine_inner, metadata, shared_filepath, lib) @@ -373,13 +373,12 @@ impl NativeArtifact { /// Construct a `NativeArtifact` from component parts. pub fn from_parts_crosscompiled( - engine_inner: &mut NativeEngineInner, metadata: ModuleMetadata, sharedobject_path: PathBuf, ) -> Result { - let mut finished_functions: PrimaryMap = + let finished_functions: PrimaryMap = PrimaryMap::new(); - let mut finished_dynamic_function_trampolines: PrimaryMap< + let finished_dynamic_function_trampolines: PrimaryMap< FunctionIndex, *const VMFunctionBody, > = PrimaryMap::new(); @@ -490,15 +489,6 @@ impl NativeArtifact { }) } - 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(()) - } - /// Compile a data buffer into a `NativeArtifact`, which may then be instantiated. #[cfg(not(feature = "compiler"))] pub fn new(engine: &NativeEngine, data: &[u8]) -> Result { @@ -628,6 +618,15 @@ impl Artifact for NativeArtifact { &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(()) + } + /// Serialize a NativeArtifact fn serialize(&self) -> Result, SerializeError> { Ok(std::fs::read(&self.sharedobject_path)?) From fa6de359447671a57ef8cf26da3eb8386763af50 Mon Sep 17 00:00:00 2001 From: Syrus Date: Thu, 4 Jun 2020 15:50:03 -0700 Subject: [PATCH 03/44] Added support for custom cpu features --- lib/compiler-llvm/src/config.rs | 20 +++-------- lib/compiler/src/lib.rs | 3 +- lib/compiler/src/target.rs | 62 +++++++++++++++++++++++++++++++++ src/commands/compile.rs | 13 +++++-- 4 files changed, 78 insertions(+), 20 deletions(-) diff --git a/lib/compiler-llvm/src/config.rs b/lib/compiler-llvm/src/config.rs index 21c92353f91..43b30181e0c 100644 --- a/lib/compiler-llvm/src/config.rs +++ b/lib/compiler-llvm/src/config.rs @@ -8,7 +8,7 @@ use itertools::Itertools; use std::sync::Arc; use target_lexicon::Architecture; use wasm_common::{FunctionType, LocalFunctionIndex}; -use wasmer_compiler::{Compiler, CompilerConfig, CpuFeature, Features, Target, Triple}; +use wasmer_compiler::{Compiler, CompilerConfig, Features, Target, Triple}; /// The InkWell ModuleInfo type pub type InkwellModule<'ctx> = inkwell::module::Module<'ctx>; @@ -142,23 +142,11 @@ impl LLVMConfig { } // The CPU features formatted as LLVM strings + // We can safely map to gcc-like features as the CPUFeatures + // are complaint with the same string representations as gcc. let llvm_cpu_features = cpu_features .iter() - .map(|feature| match feature { - CpuFeature::SSE2 => "+sse2", - CpuFeature::SSE3 => "+sse3", - CpuFeature::SSSE3 => "+ssse3", - CpuFeature::SSE41 => "+sse4.1", - CpuFeature::SSE42 => "+sse4.2", - CpuFeature::POPCNT => "+popcnt", - CpuFeature::AVX => "+avx", - CpuFeature::BMI1 => "+bmi", - CpuFeature::BMI2 => "+bmi2", - CpuFeature::AVX2 => "+avx2", - CpuFeature::AVX512DQ => "+avx512dq", - CpuFeature::AVX512VL => "+avx512vl", - CpuFeature::LZCNT => "+lzcnt", - }) + .map(|feature| format!("+{}", feature.to_string())) .join(","); let llvm_target = InkwellTarget::from_triple(&self.target_triple()).unwrap(); diff --git a/lib/compiler/src/lib.rs b/lib/compiler/src/lib.rs index f5a29ca6d5c..23de1e2f05e 100644 --- a/lib/compiler/src/lib.rs +++ b/lib/compiler/src/lib.rs @@ -80,7 +80,8 @@ pub use crate::relocation::{Relocation, RelocationKind, RelocationTarget, Reloca pub use crate::section::{CustomSection, CustomSectionProtection, SectionBody, SectionIndex}; pub use crate::sourceloc::SourceLoc; pub use crate::target::{ - Architecture, BinaryFormat, CallingConvention, CpuFeature, OperatingSystem, Target, Triple, + Architecture, BinaryFormat, CallingConvention, CpuFeature, OperatingSystem, + ParseCpuFeatureError, Target, Triple, }; #[cfg(feature = "translator")] pub use crate::translator::{ diff --git a/lib/compiler/src/target.rs b/lib/compiler/src/target.rs index 256ecdffcb4..b9169d93eac 100644 --- a/lib/compiler/src/target.rs +++ b/lib/compiler/src/target.rs @@ -1,6 +1,9 @@ //! Target configuration use enumset::{EnumSet, EnumSetType}; +use std::str::FromStr; +use std::string::ToString; pub use target_lexicon::{Architecture, BinaryFormat, CallingConvention, OperatingSystem, Triple}; +use thiserror::Error; #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] use raw_cpuid::CpuId; @@ -106,6 +109,65 @@ impl CpuFeature { } } +/// The error that can happen while parsing a `str` +/// to retrieve a [`CpuFeature`]. +#[derive(Error, Debug)] +pub enum ParseCpuFeatureError { + /// The provided string feature doesn't exist + #[error("CpuFeature for the {0} doesn't exist")] + Missing(String), +} + +// This options should map exactly the GCC options indicated +// here by architectures: +// +// X86: https://gcc.gnu.org/onlinedocs/gcc/x86-Options.html +// ARM: https://gcc.gnu.org/onlinedocs/gcc/gcc/ARM-Options.html +// Aarch64: https://gcc.gnu.org/onlinedocs/gcc/gcc/AArch64-Options.html +impl FromStr for CpuFeature { + type Err = ParseCpuFeatureError; + + fn from_str(s: &str) -> Result { + match s { + "sse2" => Ok(CpuFeature::SSE2), + "sse3" => Ok(CpuFeature::SSE3), + "ssse3" => Ok(CpuFeature::SSSE3), + "sse4.1" => Ok(CpuFeature::SSE41), + "sse4.2" => Ok(CpuFeature::SSE42), + "popcnt" => Ok(CpuFeature::POPCNT), + "avx" => Ok(CpuFeature::AVX), + "bmi" => Ok(CpuFeature::BMI1), + "bmi2" => Ok(CpuFeature::BMI2), + "avx2" => Ok(CpuFeature::AVX2), + "avx512dq" => Ok(CpuFeature::AVX512DQ), + "avx512vl" => Ok(CpuFeature::AVX512VL), + "lzcnt" => Ok(CpuFeature::LZCNT), + _ => Err(ParseCpuFeatureError::Missing(s.to_string())), + } + } +} + +impl ToString for CpuFeature { + fn to_string(&self) -> String { + match self { + CpuFeature::SSE2 => "sse2", + CpuFeature::SSE3 => "sse3", + CpuFeature::SSSE3 => "ssse3", + CpuFeature::SSE41 => "sse4.1", + CpuFeature::SSE42 => "sse4.2", + CpuFeature::POPCNT => "popcnt", + CpuFeature::AVX => "avx", + CpuFeature::BMI1 => "bmi", + CpuFeature::BMI2 => "bmi2", + CpuFeature::AVX2 => "avx2", + CpuFeature::AVX512DQ => "avx512dq", + CpuFeature::AVX512VL => "avx512vl", + CpuFeature::LZCNT => "lzcnt", + } + .to_string() + } +} + /// This is the target that we will use for compiling /// the WebAssembly ModuleInfo, and then run it. #[derive(Clone, Debug, PartialEq, Eq, Hash)] diff --git a/src/commands/compile.rs b/src/commands/compile.rs index e64a87e0367..2899d3f0ffb 100644 --- a/src/commands/compile.rs +++ b/src/commands/compile.rs @@ -27,6 +27,9 @@ pub struct Compile { #[structopt(flatten)] compiler: StoreOptions, + + #[structopt(short = "m", multiple = true)] + cpu_features: Vec, } impl Compile { @@ -37,9 +40,13 @@ impl Compile { } fn inner_execute(&self) -> Result<()> { let target = if let Some(ref target_triple) = self.target_triple { - let mut features = CpuFeature::set(); - // Cranelift requires SSE2, so we have this "hack" for now until - // we are able to pass custom features + 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 = features | CpuFeature::SSE2; Target::new(target_triple.clone(), features) } else { From 616d4757853dec6b2fabc8f5d5d68f2e34497254 Mon Sep 17 00:00:00 2001 From: Syrus Akbary Date: Thu, 4 Jun 2020 16:15:58 -0700 Subject: [PATCH 04/44] Update lib/compiler-llvm/src/config.rs Co-authored-by: nlewycky --- lib/compiler-llvm/src/config.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/compiler-llvm/src/config.rs b/lib/compiler-llvm/src/config.rs index 43b30181e0c..8d03c44e3bb 100644 --- a/lib/compiler-llvm/src/config.rs +++ b/lib/compiler-llvm/src/config.rs @@ -143,7 +143,7 @@ impl LLVMConfig { // The CPU features formatted as LLVM strings // We can safely map to gcc-like features as the CPUFeatures - // are complaint with the same string representations as gcc. + // are compliant with the same string representations as gcc. let llvm_cpu_features = cpu_features .iter() .map(|feature| format!("+{}", feature.to_string())) From acd6c2e693eea40adcd1fb6ba69c58a90ae5af0d Mon Sep 17 00:00:00 2001 From: Syrus Akbary Date: Thu, 4 Jun 2020 16:16:14 -0700 Subject: [PATCH 05/44] Update lib/compiler/src/target.rs Co-authored-by: nlewycky --- lib/compiler/src/target.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/compiler/src/target.rs b/lib/compiler/src/target.rs index b9169d93eac..b4564549c7e 100644 --- a/lib/compiler/src/target.rs +++ b/lib/compiler/src/target.rs @@ -114,7 +114,7 @@ impl CpuFeature { #[derive(Error, Debug)] pub enum ParseCpuFeatureError { /// The provided string feature doesn't exist - #[error("CpuFeature for the {0} doesn't exist")] + #[error("CpuFeature {0} not recognized")] Missing(String), } From 68128b9c6da867d356ceb698e2b3a4202a471e4c Mon Sep 17 00:00:00 2001 From: Syrus Akbary Date: Thu, 4 Jun 2020 16:16:56 -0700 Subject: [PATCH 06/44] Update src/commands/compile.rs Co-authored-by: nlewycky --- src/commands/compile.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/commands/compile.rs b/src/commands/compile.rs index 2899d3f0ffb..a1b130802f7 100644 --- a/src/commands/compile.rs +++ b/src/commands/compile.rs @@ -44,7 +44,7 @@ impl Compile { .cpu_features .clone() .into_iter() - .fold(CpuFeature::set(), |a, b| a | b); + .fold(CpuFeature::SSE2, |a, b| a | b); // Cranelift requires SSE2, so we have this "hack" for now to facilitate // usage features = features | CpuFeature::SSE2; From 9da983cbfc1a1bdaa9528131b1f0948109c7253e Mon Sep 17 00:00:00 2001 From: Syrus Date: Thu, 4 Jun 2020 16:23:41 -0700 Subject: [PATCH 07/44] Simplified code --- src/commands/compile.rs | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/commands/compile.rs b/src/commands/compile.rs index a1b130802f7..dfe6bf0aade 100644 --- a/src/commands/compile.rs +++ b/src/commands/compile.rs @@ -6,10 +6,6 @@ use std::str::FromStr; use structopt::StructOpt; use wasmer::*; -fn parse_target_triple(src: &str) -> Result { - Triple::from_str(src) -} - #[derive(Debug, StructOpt)] /// The options for the `wasmer compile` subcommand pub struct Compile { @@ -22,7 +18,7 @@ pub struct Compile { output: PathBuf, /// Compilation Target triple - #[structopt(long = "target", parse(try_from_str = parse_target_triple))] + #[structopt(long = "target")] target_triple: Option, #[structopt(flatten)] @@ -44,7 +40,7 @@ impl Compile { .cpu_features .clone() .into_iter() - .fold(CpuFeature::SSE2, |a, b| a | b); + .fold(CpuFeature::set(), |a, b| a | b); // Cranelift requires SSE2, so we have this "hack" for now to facilitate // usage features = features | CpuFeature::SSE2; From 80c6b5c53731b3e91b014ed1779175c1d30ec19e Mon Sep 17 00:00:00 2001 From: Syrus Date: Thu, 4 Jun 2020 16:45:43 -0700 Subject: [PATCH 08/44] Address feedback --- lib/api/src/lib.rs | 4 +--- lib/engine-native/Cargo.toml | 1 + lib/engine-native/src/artifact.rs | 6 ++---- src/commands/compile.rs | 1 - 4 files changed, 4 insertions(+), 8 deletions(-) diff --git a/lib/api/src/lib.rs b/lib/api/src/lib.rs index d70d301ccfc..56bf470a55f 100644 --- a/lib/api/src/lib.rs +++ b/lib/api/src/lib.rs @@ -29,9 +29,7 @@ pub use crate::types::{ }; pub use crate::types::{Val as Value, ValType as Type}; -pub use target_lexicon::{ - Architecture, CallingConvention, OperatingSystem, ParseError as TargetParseError, Triple, HOST, -}; +pub use target_lexicon::{Architecture, CallingConvention, OperatingSystem, Triple, HOST}; pub use wasm_common::{Bytes, Pages, ValueType, WasmExternType, WasmTypeList}; #[cfg(feature = "compiler")] pub use wasmer_compiler::CompilerConfig; diff --git a/lib/engine-native/Cargo.toml b/lib/engine-native/Cargo.toml index cacced35205..24e0d43e202 100644 --- a/lib/engine-native/Cargo.toml +++ b/lib/engine-native/Cargo.toml @@ -19,6 +19,7 @@ faerie = "0.15" serde = { version = "1.0", features = ["derive", "rc"] } serde_bytes = { version = "0.11" } cfg-if = "0.1" +tracing = "0.1" bincode = "1.2" leb128 = "0.2" libloading = "0.6" diff --git a/lib/engine-native/src/artifact.rs b/lib/engine-native/src/artifact.rs index 572ba43c612..f62aca19f96 100644 --- a/lib/engine-native/src/artifact.rs +++ b/lib/engine-native/src/artifact.rs @@ -299,7 +299,7 @@ impl NativeArtifact { _ => { // We should already be filtering only valid binary formats before // so this should never happen. - unreachable!() + unreachable!("Incorrect binary format") } } }) @@ -334,9 +334,7 @@ impl NativeArtifact { std::str::from_utf8(&output.stderr).unwrap().trim_end() ))); } - // println!("Stdout: {}", String::from_utf8(output.stdout).unwrap()); - // println!("Stderr: {}", String::from_utf8(output.stderr).unwrap()); - // println!("shared_filepath {:?}", shared_filepath); + tracing::trace!("gcc command result {:?}", output); if is_cross_compiling { Self::from_parts_crosscompiled(metadata, shared_filepath) } else { diff --git a/src/commands/compile.rs b/src/commands/compile.rs index dfe6bf0aade..862766be941 100644 --- a/src/commands/compile.rs +++ b/src/commands/compile.rs @@ -2,7 +2,6 @@ use crate::store::StoreOptions; use crate::warning; use anyhow::{Context, Result}; use std::path::PathBuf; -use std::str::FromStr; use structopt::StructOpt; use wasmer::*; From 78ef13affa281722c3591880a5f486fed328a65a Mon Sep 17 00:00:00 2001 From: Syrus Date: Thu, 4 Jun 2020 16:58:21 -0700 Subject: [PATCH 09/44] Improved store returned data --- src/commands/compile.rs | 19 ++++--- src/commands/inspect.rs | 4 +- src/commands/run.rs | 7 +-- src/commands/validate.rs | 4 +- src/commands/wast.rs | 4 +- src/store.rs | 111 +++++++++++++++++++++++---------------- 6 files changed, 85 insertions(+), 64 deletions(-) diff --git a/src/commands/compile.rs b/src/commands/compile.rs index 862766be941..d1210ebab22 100644 --- a/src/commands/compile.rs +++ b/src/commands/compile.rs @@ -1,4 +1,4 @@ -use crate::store::StoreOptions; +use crate::store::{EngineType, StoreOptions}; use crate::warning; use anyhow::{Context, Result}; use std::path::PathBuf; @@ -21,7 +21,7 @@ pub struct Compile { target_triple: Option, #[structopt(flatten)] - compiler: StoreOptions, + store: StoreOptions, #[structopt(short = "m", multiple = true)] cpu_features: Vec, @@ -47,15 +47,15 @@ impl Compile { } else { Target::default() }; - let (store, engine_name, compiler_name) = - self.compiler.get_store_for_target(target.clone())?; + let (store, engine_type, compiler_type) = + self.store.get_store_for_target(target.clone())?; let output_filename = self .output .file_stem() .map(|osstr| osstr.to_string_lossy().to_string()) .unwrap_or_default(); - let recommended_extension = match engine_name.as_ref() { - "native" => { + let recommended_extension = match engine_type { + EngineType::Native => { // TODO: Match it depending on the `BinaryFormat` instead of the // `OperatingSystem`. match target.triple().operating_system { @@ -65,8 +65,7 @@ impl Compile { _ => "so", } } - "jit" => "wjit", - _ => "?", + EngineType::JIT => "wjit", }; match self.output.extension() { Some(ext) => { @@ -78,8 +77,8 @@ impl Compile { warning!("the output file has no extension. We recommend using `{}.{}` for the chosen target", &output_filename, &recommended_extension) } } - println!("Engine: {}", engine_name); - println!("Compiler: {}", compiler_name); + 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)?; diff --git a/src/commands/inspect.rs b/src/commands/inspect.rs index e1c82f96396..b88ce2e2e80 100644 --- a/src/commands/inspect.rs +++ b/src/commands/inspect.rs @@ -13,7 +13,7 @@ pub struct Inspect { path: PathBuf, #[structopt(flatten)] - compiler: StoreOptions, + store: StoreOptions, } impl Inspect { @@ -23,7 +23,7 @@ impl Inspect { .context(format!("failed to inspect `{}`", self.path.display())) } fn inner_execute(&self) -> Result<()> { - let (store, _engine_name, _compiler_name) = self.compiler.get_store()?; + let (store, _engine_type, _compiler_type) = self.store.get_store()?; let module_contents = std::fs::read(&self.path)?; let module = Module::new(&store, &module_contents)?; println!("Type: {}", if module.from_wat { "wat" } else { "wasm" }); diff --git a/src/commands/run.rs b/src/commands/run.rs index 163d076dcae..b41f2b8f826 100644 --- a/src/commands/run.rs +++ b/src/commands/run.rs @@ -46,7 +46,7 @@ pub struct Run { cache_key: Option, #[structopt(flatten)] - compiler: StoreOptions, + store: StoreOptions, #[cfg(feature = "wasi")] #[structopt(flatten)] @@ -153,14 +153,15 @@ impl Run { return Ok(module); } } - let (store, engine_name, compiler_name) = self.compiler.get_store()?; + let (store, engine_type, compiler_type) = self.store.get_store()?; // We try to get it from cache, in case caching is enabled // and the file length is greater than 4KB. // For files smaller than 4KB caching is not worth, // as it takes space and the speedup is minimal. let mut module = if cfg!(feature = "cache") && !self.disable_cache && contents.len() > 0x1000 { - let mut cache = self.get_cache(engine_name, compiler_name)?; + let mut cache = + self.get_cache(engine_type.to_string(), compiler_type.to_string())?; // Try to get the hash from the provided `--cache-key`, otherwise // generate one from the provided file `.wasm` contents. let hash = self diff --git a/src/commands/validate.rs b/src/commands/validate.rs index 1d7fe14b43e..56b978416e7 100644 --- a/src/commands/validate.rs +++ b/src/commands/validate.rs @@ -12,7 +12,7 @@ pub struct Validate { path: PathBuf, #[structopt(flatten)] - compiler: StoreOptions, + store: StoreOptions, } impl Validate { @@ -22,7 +22,7 @@ impl Validate { .context(format!("failed to validate `{}`", self.path.display())) } fn inner_execute(&self) -> Result<()> { - let (store, _engine_name, _compiler_name) = self.compiler.get_store()?; + let (store, _engine_type, _compiler_type) = self.store.get_store()?; let module_contents = std::fs::read(&self.path)?; Module::validate(&store, &module_contents)?; eprintln!("Validation passed for `{}`.", self.path.display()); diff --git a/src/commands/wast.rs b/src/commands/wast.rs index 081384944e8..2837069f21f 100644 --- a/src/commands/wast.rs +++ b/src/commands/wast.rs @@ -13,7 +13,7 @@ pub struct Wast { path: PathBuf, #[structopt(flatten)] - compiler: StoreOptions, + store: StoreOptions, #[structopt(short, long)] /// A flag to indicate wast stop at the first error or continue. @@ -27,7 +27,7 @@ impl Wast { .context(format!("failed to test the wast `{}`", self.path.display())) } fn inner_execute(&self) -> Result<()> { - let (store, _engine_name, _compiler_name) = self.compiler.get_store()?; + let (store, _engine_name, _compiler_name) = self.store.get_store()?; let mut wast = WastSpectest::new_with_spectest(store); wast.fail_fast = self.fail_fast; wast.run_file(&self.path).with_context(|| "tests failed")?; diff --git a/src/store.rs b/src/store.rs index 38883b49cff..b9ede79f404 100644 --- a/src/store.rs +++ b/src/store.rs @@ -48,30 +48,38 @@ pub struct StoreOptions { // llvm_options: LLVMCLIOptions, } +/// The compiler used for the store #[derive(Debug)] -enum Compiler { +pub enum CompilerType { + /// Singlepass compiler Singlepass, + /// Cranelift compiler Cranelift, + /// LLVM compiler LLVM, + /// Headless compiler + Headless, } -impl ToString for Compiler { +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 Compiler { +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), } } @@ -79,30 +87,30 @@ impl FromStr for Compiler { #[cfg(all(feature = "compiler", feature = "engine"))] impl StoreOptions { - fn get_compiler(&self) -> Result { + fn get_compiler(&self) -> Result { if self.cranelift { - Ok(Compiler::Cranelift) + Ok(CompilerType::Cranelift) } else if self.llvm { - Ok(Compiler::LLVM) + Ok(CompilerType::LLVM) } else if self.singlepass { - Ok(Compiler::Singlepass) + Ok(CompilerType::Singlepass) } else if let Some(backend) = self.backend.clone() { warning!( "the `--backend={0}` flag is deprecated, please use `--{0}` instead", backend ); - Compiler::from_str(&backend) + CompilerType::from_str(&backend) } else { // Auto mode, we choose the best compiler for that platform cfg_if::cfg_if! { if #[cfg(all(feature = "cranelift", target_arch = "x86_64"))] { - return Ok(Compiler::Cranelift); + return Ok(CompilerType::Cranelift); } else if #[cfg(all(feature = "singlepass", target_arch = "x86_64"))] { - return Ok(Compiler::Singlepass); + return Ok(CompilerType::Singlepass); } else if #[cfg(feature = "llvm")] { - return Ok(Compiler::LLVM); + return Ok(CompilerType::LLVM); } else { bail!("There are no available compilers for your architecture"); } @@ -133,22 +141,26 @@ impl StoreOptions { /// Get the Compiler Config for the current options #[allow(unused_variables)] - fn get_compiler_config(&self, target: Target) -> Result<(Box, String)> { + fn get_compiler_config( + &self, + target: Target, + ) -> Result<(Box, CompilerType)> { let compiler = self.get_compiler()?; let features = self.get_features()?; let compiler_config: Box = match compiler { + CompilerType::Headless => bail!("The headless engine can't be chosen"), #[cfg(feature = "singlepass")] - Compiler::Singlepass => { + CompilerType::Singlepass => { let config = wasmer_compiler_singlepass::SinglepassConfig::new(features, target); Box::new(config) } #[cfg(feature = "cranelift")] - Compiler::Cranelift => { + CompilerType::Cranelift => { let config = wasmer_compiler_cranelift::CraneliftConfig::new(features, target); Box::new(config) } #[cfg(feature = "llvm")] - Compiler::LLVM => { + CompilerType::LLVM => { use std::fs::File; use std::io::Write; use wasm_common::entity::EntityRef; @@ -243,8 +255,7 @@ impl StoreOptions { compiler.to_string() ), }; - let compiler_name = compiler.to_string(); - Ok((compiler_config, compiler_name)) + Ok((compiler_config, compiler)) } /// Gets the tunables for the compiler target @@ -253,33 +264,36 @@ impl StoreOptions { } /// Gets the store for the host target, with the engine name and compiler name selected - pub fn get_store(&self) -> Result<(Store, String, String)> { + pub fn get_store(&self) -> Result<(Store, EngineType, CompilerType)> { let target = Target::default(); self.get_store_for_target(target) } /// Gets the store for a given target, with the engine name and compiler name selected, as - pub fn get_store_for_target(&self, target: Target) -> Result<(Store, String, String)> { - let (compiler_config, compiler_name) = self.get_compiler_config(target)?; + pub fn get_store_for_target( + &self, + target: Target, + ) -> Result<(Store, EngineType, CompilerType)> { + let (compiler_config, compiler_type) = self.get_compiler_config(target)?; let tunables = self.get_tunables(&*compiler_config); - let (engine, engine_name) = self.get_engine_with_compiler(tunables, compiler_config)?; + let (engine, engine_type) = self.get_engine_with_compiler(tunables, compiler_config)?; let store = Store::new(engine); - Ok((store, engine_name, compiler_name)) + Ok((store, engine_type, compiler_type)) } fn get_engine_with_compiler( &self, tunables: Tunables, compiler_config: Box, - ) -> Result<(Arc, String)> { + ) -> Result<(Arc, EngineType)> { let engine_type = self.get_engine()?; let engine: Arc = match engine_type { #[cfg(feature = "jit")] - EngineOptions::JIT => { + EngineType::JIT => { Arc::new(wasmer_engine_jit::JITEngine::new(compiler_config, tunables)) } #[cfg(feature = "native")] - EngineOptions::Native => Arc::new(wasmer_engine_native::NativeEngine::new( + EngineType::Native => Arc::new(wasmer_engine_native::NativeEngine::new( compiler_config, tunables, )), @@ -289,16 +303,19 @@ impl StoreOptions { engine.to_string() ), }; - return Ok((engine, engine_type.to_string())); + return Ok((engine, engine_type)); } } -enum EngineOptions { +/// The engine used for the store +pub enum EngineType { + /// JIT Engine JIT, + /// Native Engine Native, } -impl ToString for EngineOptions { +impl ToString for EngineType { fn to_string(&self) -> String { match self { Self::JIT => "jit".to_string(), @@ -309,17 +326,17 @@ impl ToString for EngineOptions { #[cfg(feature = "engine")] impl StoreOptions { - fn get_engine(&self) -> Result { + fn get_engine(&self) -> Result { if self.jit { - Ok(EngineOptions::JIT) + Ok(EngineType::JIT) } else if self.native { - Ok(EngineOptions::Native) + Ok(EngineType::Native) } else { // Auto mode, we choose the best engine for that platform if cfg!(feature = "jit") { - Ok(EngineOptions::JIT) + Ok(EngineType::JIT) } else if cfg!(feature = "native") { - Ok(EngineOptions::Native) + Ok(EngineType::Native) } else { bail!("There are no available engines for your architecture") } @@ -333,35 +350,36 @@ impl StoreOptions { fn get_engine_headless( &self, tunables: Tunables, - ) -> Result<(Arc, String)> { + ) -> Result<(Arc, EngineType)> { let engine_type = self.get_engine()?; let engine: Arc = match engine_type { #[cfg(feature = "jit")] - EngineOptions::JIT => Arc::new(wasmer_engine_jit::JITEngine::headless(tunables)), + EngineType::JIT => Arc::new(wasmer_engine_jit::JITEngine::headless(tunables)), #[cfg(feature = "native")] - EngineOptions::Native => { - Arc::new(wasmer_engine_native::NativeEngine::headless(tunables)) - } + EngineType::Native => Arc::new(wasmer_engine_native::NativeEngine::headless(tunables)), #[cfg(not(all(feature = "jit", feature = "native",)))] engine => bail!( "The `{}` engine is not included in this binary.", engine.to_string() ), }; - return Ok((engine, engine_type.to_string())); + return Ok((engine, engine_type)); } /// Get the store (headless engine) - pub fn get_store(&self) -> Result<(Store, String, String)> { + pub fn get_store(&self) -> Result<(Store, EngineType, CompilerType)> { // Get the tunables for the current host let tunables = Tunables::default(); - let (engine, engine_name) = self.get_engine_headless(tunables)?; + let (engine, engine_type) = self.get_engine_headless(tunables)?; let store = Store::new(engine); - Ok((store, engine_name, "headless".to_string())) + Ok((store, engine_type, CompilerType::Headless)) } /// Gets the store for provided host target - pub fn get_store_for_target(&self, target: Target) -> Result<(Store, String, String)> { + pub fn get_store_for_target( + &self, + target: Target, + ) -> Result<(Store, EngineType, CompilerType)> { bail!("You need compilers to run get a store in a specific target"); } } @@ -370,12 +388,15 @@ impl StoreOptions { #[cfg(not(feature = "engine"))] impl StoreOptions { /// Get the store (headless engine) - pub fn get_store(&self) -> Result<(Store, String, String)> { + pub fn get_store(&self) -> Result<(Store, EngineType, CompilerType)> { bail!("No engines are enabled"); } /// Gets the store for the host target - pub fn get_store_for_target(&self, target: Target) -> Result<(Store, String, String)> { + pub fn get_store_for_target( + &self, + target: Target, + ) -> Result<(Store, EngineType, CompilerType)> { bail!("No engines are enabled"); } } From a18f05ca15043846703c89c626966a3ff361a9e3 Mon Sep 17 00:00:00 2001 From: Syrus Date: Thu, 4 Jun 2020 17:00:51 -0700 Subject: [PATCH 10/44] Updated cargo.lock --- Cargo.lock | 1 + 1 file changed, 1 insertion(+) diff --git a/Cargo.lock b/Cargo.lock index b9ab04b60c3..2305d9511d2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2072,6 +2072,7 @@ dependencies = [ "serde", "serde_bytes", "tempfile", + "tracing", "wasm-common", "wasmer-compiler", "wasmer-engine", From 3e5a2b567367e585f52a0a01e8aeb633f701a491 Mon Sep 17 00:00:00 2001 From: Syrus Date: Thu, 4 Jun 2020 17:04:49 -0700 Subject: [PATCH 11/44] Simplified target generation --- src/commands/compile.rs | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/src/commands/compile.rs b/src/commands/compile.rs index d1210ebab22..80713023260 100644 --- a/src/commands/compile.rs +++ b/src/commands/compile.rs @@ -34,19 +34,21 @@ impl Compile { .context(format!("failed to compile `{}`", self.path.display())) } fn inner_execute(&self) -> Result<()> { - let target = if let Some(ref target_triple) = self.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 = features | CpuFeature::SSE2; - Target::new(target_triple.clone(), features) - } else { - Target::default() - }; + 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 = features | CpuFeature::SSE2; + Target::new(target_triple.clone(), features) + }) + .unwrap_or_default(); let (store, engine_type, compiler_type) = self.store.get_store_for_target(target.clone())?; let output_filename = self From ea522de15468ec6edae67c5f08667d85f0d1c0dd Mon Sep 17 00:00:00 2001 From: Syrus Date: Thu, 4 Jun 2020 17:07:16 -0700 Subject: [PATCH 12/44] Improved tracing macro call --- lib/engine-native/src/artifact.rs | 2 +- lib/engine-native/src/lib.rs | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/engine-native/src/artifact.rs b/lib/engine-native/src/artifact.rs index f62aca19f96..e394437494d 100644 --- a/lib/engine-native/src/artifact.rs +++ b/lib/engine-native/src/artifact.rs @@ -334,7 +334,7 @@ impl NativeArtifact { std::str::from_utf8(&output.stderr).unwrap().trim_end() ))); } - tracing::trace!("gcc command result {:?}", output); + trace!("gcc command result {:?}", output); if is_cross_compiling { Self::from_parts_crosscompiled(metadata, shared_filepath) } else { diff --git a/lib/engine-native/src/lib.rs b/lib/engine-native/src/lib.rs index 3568d20606f..2d54d1d8840 100644 --- a/lib/engine-native/src/lib.rs +++ b/lib/engine-native/src/lib.rs @@ -25,6 +25,9 @@ ) )] +#[macro_use] +extern crate tracing; + mod artifact; mod engine; mod serialize; From 7455f10763065a8def683949f3c208a2ca9936d2 Mon Sep 17 00:00:00 2001 From: Syrus Date: Thu, 4 Jun 2020 17:52:50 -0700 Subject: [PATCH 13/44] Fixed compilation lint --- src/store.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/store.rs b/src/store.rs index b9ede79f404..029d469ede3 100644 --- a/src/store.rs +++ b/src/store.rs @@ -378,9 +378,9 @@ impl StoreOptions { /// Gets the store for provided host target pub fn get_store_for_target( &self, - target: Target, + _target: Target, ) -> Result<(Store, EngineType, CompilerType)> { - bail!("You need compilers to run get a store in a specific target"); + bail!("You need compilers to retrieve a store for a specific target"); } } @@ -395,7 +395,7 @@ impl StoreOptions { /// Gets the store for the host target pub fn get_store_for_target( &self, - target: Target, + _target: Target, ) -> Result<(Store, EngineType, CompilerType)> { bail!("No engines are enabled"); } From fc27d75909df8b933d890e5a922787f0bcb5be76 Mon Sep 17 00:00:00 2001 From: Syrus Date: Thu, 4 Jun 2020 19:36:23 -0700 Subject: [PATCH 14/44] Improved CI by building the package --- .github/workflows/main.yaml | 10 ++- .gitignore | 5 +- Cargo.lock | 32 ++++----- Makefile | 129 +++++++++++++++++++++++++++++------- lib/c-api/Cargo.toml | 14 ++-- lib/c-api/README.md | 40 +++++++---- lib/c-api/doc/index.md | 32 ++++++--- lib/c-api/doxyfile | 2 +- src/bin/wasmer.rs | 10 ++- src/commands.rs | 3 +- src/commands/config.rs | 61 +++++++++++++++++ 11 files changed, 261 insertions(+), 77 deletions(-) create mode 100644 src/commands/config.rs diff --git a/.github/workflows/main.yaml b/.github/workflows/main.yaml index fbd1c6ea6e7..46485f39f9a 100644 --- a/.github/workflows/main.yaml +++ b/.github/workflows/main.yaml @@ -111,9 +111,15 @@ jobs: - run: make test - name: Build and Test C API run: | - make capi + make build-capi make test-capi-cranelift if: matrix.os != 'windows-latest' - name: Build C API on Windows - run: make capi + run: make build-capi if: matrix.os == 'windows-latest' + - name: Build Wasmer binary + run: | + make build-wasmer + # TODO: build wapm + # make build-wapm + make package diff --git a/.gitignore b/.gitignore index 063490ca185..2efd0d937aa 100644 --- a/.gitignore +++ b/.gitignore @@ -4,11 +4,10 @@ .DS_Store .idea **/.vscode -install/ -capi/ -api-docs/ api-docs-repo/ /.cargo_home/ +/package/ +/wapm-cli/ # Generated by tests on Android /avd diff --git a/Cargo.lock b/Cargo.lock index 2305d9511d2..e7b6d63eb40 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1927,6 +1927,22 @@ dependencies = [ "wasmer-wast", ] +[[package]] +name = "wasmer-c-api" +version = "0.16.2" +dependencies = [ + "cbindgen", + "cfg-if", + "lazy_static", + "libc", + "libffi", + "paste", + "thiserror", + "wasm-common", + "wasmer", + "wasmer-wasi", +] + [[package]] name = "wasmer-cache" version = "0.16.2" @@ -2097,22 +2113,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "wasmer-runtime-c-api" -version = "0.16.2" -dependencies = [ - "cbindgen", - "cfg-if", - "lazy_static", - "libc", - "libffi", - "paste", - "thiserror", - "wasm-common", - "wasmer", - "wasmer-wasi", -] - [[package]] name = "wasmer-wasi" version = "0.16.2" diff --git a/Makefile b/Makefile index 6afec0c970d..40b5bd00b5f 100644 --- a/Makefile +++ b/Makefile @@ -55,51 +55,130 @@ compiler_features_spaced := $(foreach compiler,$(compilers),$(compiler)) compiler_features := --features "$(compiler_features_spaced)" -tests-spec-update-testsuite: - git subtree pull --prefix tests/wast/spec https://github.com/WebAssembly/testsuite.git master --squash +############ +# Building # +############ -test: - cargo test --release $(compiler_features) - -release: +build-wasmer: cargo build --release $(compiler_features) -doc: - cargo doc --all-features --document-private-items +WAPM_VERSION = v0.5.0 +build-wapm: + git clone --branch $(WAPM_VERSION) https://github.com/wasmerio/wapm-cli.git + cargo build --release --manifest-path wapm-cli/Cargo.toml --features "telemetry update-notifications" -doc-local: - cargo doc --all-features --document-private-items --no-deps +build-docs: + cargo doc --release --all-features --document-private-items --no-deps -RUSTFLAGS := "-D dead-code -D nonstandard-style -D unused-imports -D unused-mut -D unused-variables -D unused-unsafe -D unreachable-patterns -D bad-style -D improper-ctypes -D unused-allocation -D unused-comparisons -D while-true -D unconditional-recursion -D bare-trait-objects" # TODO: add `-D missing-docs` -lint: - cargo fmt --all -- --check - RUSTFLAGS=${RUSTFLAGS} cargo clippy $(compiler_features) +build-docs-capi: + cd lib/c-api/ && doxygen doxyfile + +# We use cranelift as the default backend for the capi for now +build-capi: build-capi-cranelift -capi-singlepass: +build-capi-singlepass: cargo build --manifest-path lib/c-api/Cargo.toml --release \ --no-default-features --features singlepass-backend,wasi -capi-cranelift: +build-capi-cranelift: cargo build --manifest-path lib/c-api/Cargo.toml --release \ --no-default-features --features cranelift-backend,wasi -capi-llvm: +build-capi-llvm: cargo build --manifest-path lib/c-api/Cargo.toml --release \ --no-default-features --features llvm-backend,wasi -# We use cranelift as the default backend for the capi for now -capi: capi-cranelift -test-capi-singlepass: capi-singlepass +########### +# Testing # +########### + +test: + cargo test --release $(compiler_features) + +test-capi-singlepass: build-capi-singlepass cargo test --manifest-path lib/c-api/Cargo.toml --release \ - --no-default-features --features singlepass-backend,wasi + --no-default-features --features singlepass,wasi -test-capi-cranelift: capi-cranelift +test-capi-cranelift: build-capi-cranelift cargo test --manifest-path lib/c-api/Cargo.toml --release \ - --no-default-features --features cranelift-backend,wasi -- --nocapture --test-threads=1 + --no-default-features --features cranelift,wasi -- --nocapture --test-threads=1 -test-capi-llvm: capi-llvm +test-capi-llvm: build-capi-llvm cargo test --manifest-path lib/c-api/Cargo.toml --release \ - --no-default-features --features llvm-backend,wasi + --no-default-features --features llvm,wasi test-capi: test-capi-singlepass test-capi-cranelift test-capi-llvm test-capi-emscripten + +############# +# Packaging # +############# + +package-wasmer: + # This command doesn't build the binary, just packages it + mkdir -p ./package/bin + cp ./target/release/wasmer ./package/bin/ + + # Comment WAPM for now to speedup release process + # cp ./wapm-cli/target/release/wapm ./package/bin/ + # # Create the wax binary as symlink to wapm + # cd ./package/bin/ && ln -sf wapm wax && chmod +x wax + +package-capi: + # This command doesn't build the C-API, just packages it + mkdir -p ./package/ + mkdir -p ./package/include + mkdir -p ./package/lib +ifeq ($(OS), Windows_NT) + cp target/release/wasmer_c_api.dll ./package/lib/wasmer.dll + cp target/release/wasmer_c_api.lib ./package/lib/wasmer.lib +else +ifeq ($(UNAME_S), Darwin) + cp target/release/libwasmer_c_api.dylib ./package/lib/libwasmer.dylib + cp target/release/libwasmer_c_api.a ./package/lib/libwasmer.a + # Fix the rpath for the dylib + install_name_tool -id "@rpath/libwasmer.dylib" ./package/lib/libwasmer.dylib +else + cp target/release/libwasmer_c_api.so ./package/lib/libwasmer.so + cp target/release/libwasmer_c_api.a ./package/lib/libwasmer.a +endif +endif + find target/release/build -name 'wasmer.h*' -exec cp {} ./package/include ';' + cp lib/c-api/doc/index.md ./package/include/README.md + +package-docs: build-docs build-docs-capi + mkdir -p package/docs + mkdir -p package/docs/c + cp -R target/doc package/docs/crates + cp -R lib/c-api/doc/html package/docs/c-api + echo '' > package/docs/index.html + echo '' > package/docs/crates/index.html + +package: package-wasmer package-capi + cp LICENSE ./package/LICENSE + cp ATTRIBUTIONS.md ./package/ATTRIBUTIONS + tar -C ./package -zcvf wasmer.tar.gz bin lib include LICENSE ATTRIBUTIONS + + +################ +# Miscelaneous # +################ + +# Updates the spectests from the repo +update-testsuite: + git subtree pull --prefix tests/wast/spec https://github.com/WebAssembly/testsuite.git master --squash + +RUSTFLAGS := "-D dead-code -D nonstandard-style -D unused-imports -D unused-mut -D unused-variables -D unused-unsafe -D unreachable-patterns -D bad-style -D improper-ctypes -D unused-allocation -D unused-comparisons -D while-true -D unconditional-recursion -D bare-trait-objects" # TODO: add `-D missing-docs` +lint: + cargo fmt --all -- --check + RUSTFLAGS=${RUSTFLAGS} cargo clippy $(compiler_features) + +install-local: package + tar -C ~/.wasmer -zxvf wasmer.tar.gz + +publish-docs: + git clone -b "gh-pages" --depth=1 https://wasmerbot:$(GITHUB_DOCS_TOKEN)@github.com/wasmerio/wasmer.git api-docs-repo + cp -R package/docs/* api-docs-repo/ + cd api-docs-repo && git add index.html crates/* c-api/* + cd api-docs-repo && (git diff-index --quiet HEAD || git commit -m "Publishing GitHub Pages") + # cd api-docs-repo && git push origin gh-pages diff --git a/lib/c-api/Cargo.toml b/lib/c-api/Cargo.toml index 852084b6a09..b45c725be05 100644 --- a/lib/c-api/Cargo.toml +++ b/lib/c-api/Cargo.toml @@ -1,8 +1,8 @@ [package] -name = "wasmer-runtime-c-api" +name = "wasmer-c-api" version = "0.16.2" description = "Wasmer C API library" -documentation = "https://wasmerio.github.io/wasmer/c/runtime-c-api/" +documentation = "https://wasmerio.github.io/wasmer/c-api/" license = "MIT" authors = ["The Wasmer Engineering Team "] repository = "https://github.com/wasmerio/wasmer" @@ -49,13 +49,17 @@ optional = true [features] default = ["cranelift-backend", "wasi"] -singlepass-backend = ["wasmer/singlepass"] -cranelift-backend = ["wasmer/cranelift"] -llvm-backend = ["wasmer/llvm"] +singlepass = ["wasmer/singlepass"] +cranelift = ["wasmer/cranelift"] +llvm = ["wasmer/llvm"] wasi = ["wasmer-wasi"] #emscripten = ["wasmer-emscripten"] # used to avoid generating standard Wasm C API types in our header files ignore-wasm-c-api = [] +# This is for compatibility for old usage +singlepass-backend = ["singlepass"] +cranelift-backend = ["cranelift"] +llvm-backend = ["llvm"] [build-dependencies] cbindgen = { git = "https://github.com/eqrion/cbindgen", version = "0.14" } \ No newline at end of file diff --git a/lib/c-api/README.md b/lib/c-api/README.md index d1475b7fdea..48efce57451 100644 --- a/lib/c-api/README.md +++ b/lib/c-api/README.md @@ -14,17 +14,17 @@ Join the Wasmer Community - - Number of downloads from crates.io + + Number of downloads from crates.io - + Wasmer C API Documentation

# Wasmer Runtime C API -Wasmer is a standalone JIT WebAssembly runtime, aiming to be fully +Wasmer is a standalone WebAssembly runtime, aiming to be fully compatible with WASI, Emscripten, Rust and Go. [Learn more](https://github.com/wasmerio/wasmer). @@ -32,14 +32,30 @@ This crate exposes a C and a 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. -The runtime shared library (so, dll, dylib) can also be downloaded in Wasmer [release page](https://github.com/wasmerio/wasmer/releases). +Upon installing Wasmer, the shared object files and the headers will +be automatically available inside the Wasmer folder. -You can find the full C API documentation here: -https://wasmerio.github.io/wasmer/c/runtime-c-api/ +The C ([`wasmer.h`][wasmer_h]) and C++ ([`wasmer.hh`][wasmer_hh]) header +files can be found in the `include` directory where Wasmer is installed and also via: + +```bash +wasmer config --includedir +``` + +The runtime shared libraries (`.so`, `.dylib`, `.dll`) can be found in the +`lib` directory where Wasmer is installed and also via: + +```bash +wasmer config --libdir +``` + +You can also download the libraries or header files directly from the Wasmer +[release page]. + +[release page]: https://github.com/wasmerio/wasmer/releases + +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: @@ -118,7 +134,7 @@ The tests can be run via `cargo test`, such as: $ cargo test --release -- --nocapture ``` -To run tests manually, enter the `lib/runtime-c-api/tests` directory +To run tests manually, enter the `lib/c-api/tests` directory and run the following commands: ```sh diff --git a/lib/c-api/doc/index.md b/lib/c-api/doc/index.md index ebd5dadb7d0..074e4c8bbec 100644 --- a/lib/c-api/doc/index.md +++ b/lib/c-api/doc/index.md @@ -10,19 +10,31 @@ with the Wasmer Runtime, so you can use WebAssembly anywhere. # Usage -Since the Wasmer runtime is written in Rust, the C and C++ API are -designed to work hand-in-hand with its shared library. The C and C++ -header files, namely [`wasmer.h`][wasmer_h] and `wasmer.hh` are documented -in the docs. +Upon installing Wasmer, the shared object files and the headers will +be automatically available inside the Wasmer folder. -Their source code can be found in the source tree of the [wasmer-runtime-c-api](https://github.com/wasmerio/wasmer/tree/master/lib/runtime-c-api) -crate. -The C and C++ header files along with the runtime shared -libraries (`.so`, `.dylib`, `.dll`) can also be downloaded in the -Wasmer [release page]. +The C ([`wasmer.h`][wasmer_h]) and C++ ([`wasmer.hh`][wasmer_hh]) header +files can be found in the `include` directory where Wasmer is installed and also via: + +```bash +wasmer config --includedir +``` + +The runtime shared libraries (`.so`, `.dylib`, `.dll`) can be found in the +`lib` directory where Wasmer is installed and also via: + +```bash +wasmer config --libdir +``` + +You can also download the libraries or header files directly from the Wasmer +[release page]. [release page]: https://github.com/wasmerio/wasmer/releases +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 @@ -102,6 +114,6 @@ Wasmer is primarily distributed under the terms of the [MIT license][mit-license] ([LICENSE][license]). -[wasmer_h]: https://wasmerio.github.io/wasmer/c/runtime-c-api/wasmer_8h.html +[wasmer_h]: https://wasmerio.github.io/wasmer/c-api/wasmer_8h.html [mit-license]: http://opensource.org/licenses/MIT [license]: https://github.com/wasmerio/wasmer/blob/master/LICENSE diff --git a/lib/c-api/doxyfile b/lib/c-api/doxyfile index e38b94b7535..1ff7911ba20 100644 --- a/lib/c-api/doxyfile +++ b/lib/c-api/doxyfile @@ -4,7 +4,7 @@ # Project related configuration options #--------------------------------------------------------------------------- DOXYFILE_ENCODING = UTF-8 -PROJECT_NAME = "wasmer-runtime-c-api" +PROJECT_NAME = "wasmer-c-api" PROJECT_NUMBER = PROJECT_BRIEF = PROJECT_LOGO = ../../assets/logo.png diff --git a/src/bin/wasmer.rs b/src/bin/wasmer.rs index 8309727c368..1505c9bc1e0 100644 --- a/src/bin/wasmer.rs +++ b/src/bin/wasmer.rs @@ -1,7 +1,7 @@ use anyhow::Result; #[cfg(feature = "wast")] use wasmer_bin::commands::Wast; -use wasmer_bin::commands::{Cache, Compile, Inspect, Run, SelfUpdate, Validate}; +use wasmer_bin::commands::{Cache, Compile, Config, Inspect, Run, SelfUpdate, Validate}; use wasmer_bin::error::PrettyError; use structopt::{clap::ErrorKind, StructOpt}; @@ -26,6 +26,11 @@ enum WasmerCLIOptions { #[structopt(name = "compile")] Compile(Compile), + /// Get various configuration information needed + /// to compile programs which use Wasmer + #[structopt(name = "config")] + Config(Config), + /// Update wasmer to the latest version #[structopt(name = "self-update")] SelfUpdate(SelfUpdate), @@ -48,6 +53,7 @@ impl WasmerCLIOptions { Self::Cache(cache) => cache.execute(), Self::Validate(validate) => validate.execute(), Self::Compile(compile) => compile.execute(), + Self::Config(config) => config.execute(), Self::Inspect(inspect) => inspect.execute(), #[cfg(feature = "wast")] Self::Wast(wast) => wast.execute(), @@ -67,7 +73,7 @@ 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" | "self-update" | "inspect" => { + "run" | "cache" | "validate" | "compile" | "config" | "self-update" | "inspect" => { WasmerCLIOptions::from_args() } _ => { diff --git a/src/commands.rs b/src/commands.rs index dce0628b15f..fe7036e3625 100644 --- a/src/commands.rs +++ b/src/commands.rs @@ -1,6 +1,7 @@ //! The commands available in the Wasmer binary. mod cache; mod compile; +mod config; mod inspect; mod run; mod self_update; @@ -10,4 +11,4 @@ mod wast; #[cfg(feature = "wast")] pub use wast::*; -pub use {cache::*, compile::*, inspect::*, run::*, self_update::*, validate::*}; +pub use {cache::*, compile::*, config::*, inspect::*, run::*, self_update::*, validate::*}; diff --git a/src/commands/config.rs b/src/commands/config.rs new file mode 100644 index 00000000000..75e6f95892c --- /dev/null +++ b/src/commands/config.rs @@ -0,0 +1,61 @@ +use anyhow::{Context, Result}; +use std::env; +use std::path::PathBuf; +use structopt::StructOpt; + +#[derive(Debug, StructOpt)] +/// The options for the `wasmer config` subcommand +pub struct Config { + /// Print the installation prefix. + #[structopt(long)] + prefix: bool, + + /// Directory containing Wasmer executables. + #[structopt(long)] + bindir: bool, + + /// Directory containing Wasmer headers. + #[structopt(long)] + includedir: bool, + + /// Directory containing Wasmer libraries. + #[structopt(long)] + libdir: bool, +} + +impl Config { + /// Runs logic for the `config` subcommand + pub fn execute(&self) -> Result<()> { + self.inner_execute() + .context(format!("failed to retrieve the wasmer config")) + } + fn inner_execute(&self) -> Result<()> { + let key = "WASMER_DIR"; + let wasmer_dir = env::var(key).context(format!( + "failed to retrieve the {} environment variable", + key + ))?; + let mut prefix = PathBuf::new(); + prefix.push(wasmer_dir); + + if self.prefix { + println!("{}", prefix.display()); + } + if self.bindir { + let mut bindir = prefix.clone(); + bindir.push("bin"); + println!("{}", bindir.display()); + } + if self.includedir { + let mut includedir = prefix.clone(); + includedir.push("include"); + println!("{}", includedir.display()); + } + if self.libdir { + let mut libdir = prefix.clone(); + libdir.push("lib"); + println!("{}", libdir.display()); + } + Ok(()) + } +} From 43534aebc8f65a6df41b6eadf741d6e41155d147 Mon Sep 17 00:00:00 2001 From: Syrus Date: Thu, 4 Jun 2020 19:48:58 -0700 Subject: [PATCH 15/44] Improved docs a bit more --- lib/c-api/README.md | 19 ++++++++++--------- lib/c-api/doc/index.md | 20 +++++++++++--------- 2 files changed, 21 insertions(+), 18 deletions(-) diff --git a/lib/c-api/README.md b/lib/c-api/README.md index 48efce57451..00f67bd1f70 100644 --- a/lib/c-api/README.md +++ b/lib/c-api/README.md @@ -32,27 +32,27 @@ This crate exposes a C and a C++ API for the Wasmer runtime. # Usage -Upon installing Wasmer, the shared object files and the headers will -be automatically available inside the Wasmer folder. +The shared object files and the headers will +be automatically available **inside the Wasmer installed path**. + +> Please check the following docs to see how to [install Wasmer in your system][https://github.com/wasmerio/wasmer#1-install-wasmer]. The C ([`wasmer.h`][wasmer_h]) and C++ ([`wasmer.hh`][wasmer_hh]) header -files can be found in the `include` directory where Wasmer is installed and also via: +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 -`lib` directory where Wasmer is installed and also via: +The runtime shared libraries (`.so`, `.dylib`, `.dll`) can be found in the Wasmer +`lib` directory: ```bash wasmer config --libdir ``` -You can also download the libraries or header files directly from the Wasmer -[release page]. - -[release page]: https://github.com/wasmerio/wasmer/releases +> 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/ @@ -154,3 +154,4 @@ license][mit-license] ([LICENSE][license]). [wasmer_hh]: ./wasmer.hh [mit-license]: http://opensource.org/licenses/MIT [license]: https://github.com/wasmerio/wasmer/blob/master/LICENSE +[release page]: https://github.com/wasmerio/wasmer/releases diff --git a/lib/c-api/doc/index.md b/lib/c-api/doc/index.md index 074e4c8bbec..3a86e1b73db 100644 --- a/lib/c-api/doc/index.md +++ b/lib/c-api/doc/index.md @@ -10,27 +10,27 @@ with the Wasmer Runtime, so you can use WebAssembly anywhere. # Usage -Upon installing Wasmer, the shared object files and the headers will -be automatically available inside the Wasmer folder. +The shared object files and the headers will +be automatically available **inside the Wasmer installed path**. + +> Please check the following docs to see how to [install Wasmer in your system][https://github.com/wasmerio/wasmer#1-install-wasmer]. The C ([`wasmer.h`][wasmer_h]) and C++ ([`wasmer.hh`][wasmer_hh]) header -files can be found in the `include` directory where Wasmer is installed and also via: +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 -`lib` directory where Wasmer is installed and also via: +The runtime shared libraries (`.so`, `.dylib`, `.dll`) can be found in the Wasmer +`lib` directory: ```bash wasmer config --libdir ``` -You can also download the libraries or header files directly from the Wasmer -[release page]. - -[release page]: https://github.com/wasmerio/wasmer/releases +> 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/ @@ -115,5 +115,7 @@ license][mit-license] ([LICENSE][license]). [wasmer_h]: https://wasmerio.github.io/wasmer/c-api/wasmer_8h.html +[wasmer_hh]: https://wasmerio.github.io/wasmer/c-api/wasmer_8hh.html [mit-license]: http://opensource.org/licenses/MIT [license]: https://github.com/wasmerio/wasmer/blob/master/LICENSE +[release page]: https://github.com/wasmerio/wasmer/releases From d3b69b6aea5e2d34e5c3510ce236baaf597487a1 Mon Sep 17 00:00:00 2001 From: Syrus Date: Thu, 4 Jun 2020 19:54:02 -0700 Subject: [PATCH 16/44] Improved docs --- lib/c-api/README.md | 4 ++-- lib/c-api/doc/index.md | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/c-api/README.md b/lib/c-api/README.md index 00f67bd1f70..c9e9e3b8e15 100644 --- a/lib/c-api/README.md +++ b/lib/c-api/README.md @@ -35,7 +35,7 @@ This crate exposes a C and a C++ API for the Wasmer runtime. The shared object files and the headers will be automatically available **inside the Wasmer installed path**. -> Please check the following docs to see how to [install Wasmer in your system][https://github.com/wasmerio/wasmer#1-install-wasmer]. +> Please check the following docs to see how to [install Wasmer in your system](https://github.com/wasmerio/wasmer#1-install-wasmer). The C ([`wasmer.h`][wasmer_h]) and C++ ([`wasmer.hh`][wasmer_hh]) header files can be found in the Wasmer `include` directory: @@ -154,4 +154,4 @@ license][mit-license] ([LICENSE][license]). [wasmer_hh]: ./wasmer.hh [mit-license]: http://opensource.org/licenses/MIT [license]: https://github.com/wasmerio/wasmer/blob/master/LICENSE -[release page]: https://github.com/wasmerio/wasmer/releases +[Wasmer release page]: https://github.com/wasmerio/wasmer/releases diff --git a/lib/c-api/doc/index.md b/lib/c-api/doc/index.md index 3a86e1b73db..539973938ec 100644 --- a/lib/c-api/doc/index.md +++ b/lib/c-api/doc/index.md @@ -13,7 +13,7 @@ with the Wasmer Runtime, so you can use WebAssembly anywhere. The shared object files and the headers will be automatically available **inside the Wasmer installed path**. -> Please check the following docs to see how to [install Wasmer in your system][https://github.com/wasmerio/wasmer#1-install-wasmer]. +> Please check the following docs to see how to [install Wasmer in your system](https://github.com/wasmerio/wasmer#1-install-wasmer). The C ([`wasmer.h`][wasmer_h]) and C++ ([`wasmer.hh`][wasmer_hh]) header files can be found in the Wasmer `include` directory: @@ -118,4 +118,4 @@ license][mit-license] ([LICENSE][license]). [wasmer_hh]: https://wasmerio.github.io/wasmer/c-api/wasmer_8hh.html [mit-license]: http://opensource.org/licenses/MIT [license]: https://github.com/wasmerio/wasmer/blob/master/LICENSE -[release page]: https://github.com/wasmerio/wasmer/releases +[Wasmer release page]: https://github.com/wasmerio/wasmer/releases From 04aa944e0a2fd7007928e655a1a11cc8da0cd5b6 Mon Sep 17 00:00:00 2001 From: Syrus Date: Thu, 4 Jun 2020 20:22:07 -0700 Subject: [PATCH 17/44] Fixed capi compilation --- Makefile | 6 +++--- lib/c-api/src/wasm_c_api.rs | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Makefile b/Makefile index 40b5bd00b5f..559b0fcea35 100644 --- a/Makefile +++ b/Makefile @@ -160,9 +160,9 @@ package: package-wasmer package-capi tar -C ./package -zcvf wasmer.tar.gz bin lib include LICENSE ATTRIBUTIONS -################ -# Miscelaneous # -################ +################# +# Miscellaneous # +################# # Updates the spectests from the repo update-testsuite: diff --git a/lib/c-api/src/wasm_c_api.rs b/lib/c-api/src/wasm_c_api.rs index 037dfcf1c7b..16ea5ea7d06 100644 --- a/lib/c-api/src/wasm_c_api.rs +++ b/lib/c-api/src/wasm_c_api.rs @@ -49,11 +49,11 @@ pub struct wasm_engine_t { fn get_default_compiler_config() -> Box { cfg_if! { - if #[cfg(feature = "cranelift-backend")] { + if #[cfg(feature = "cranelift")] { Box::new(wasmer::CraneliftConfig::default()) - } else if #[cfg(feature = "llvm-backend")] { + } else if #[cfg(feature = "llvm")] { Box::new(wasmer::LLVMConfig::default()) - } else if #[cfg(feature = "singlepass-backend")] { + } else if #[cfg(feature = "singlepass")] { Box::new(wasmer::SinglepassConfig::default()) } else { compile_error!("Please enable one of the compiler backends") From fb51aeee83efafd676a43b0ca4ab7944486be193 Mon Sep 17 00:00:00 2001 From: Syrus Date: Thu, 4 Jun 2020 21:22:36 -0700 Subject: [PATCH 18/44] Fixed c-api tests --- lib/c-api/tests/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/c-api/tests/CMakeLists.txt b/lib/c-api/tests/CMakeLists.txt index 71b605ac910..3aa095020f7 100644 --- a/lib/c-api/tests/CMakeLists.txt +++ b/lib/c-api/tests/CMakeLists.txt @@ -43,7 +43,7 @@ include_directories(wasm-c-api/include) find_library( - WASMER_LIB NAMES libwasmer_runtime_c_api.dylib libwasmer_runtime_c_api.so wasmer_runtime_c_api.dll + WASMER_LIB NAMES libwasmer_c_api.dylib libwasmer_c_api.so wasmer_c_api.dll PATHS ${CMAKE_SOURCE_DIR}/../../../target/release/ ) From c7673e9e415ef9e0d8ffb95ffc17a204fd6dc041 Mon Sep 17 00:00:00 2001 From: Syrus Date: Thu, 4 Jun 2020 21:45:54 -0700 Subject: [PATCH 19/44] Improved Windows support --- Makefile | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 559b0fcea35..cd89837c2c4 100644 --- a/Makefile +++ b/Makefile @@ -117,8 +117,11 @@ test-capi: test-capi-singlepass test-capi-cranelift test-capi-llvm test-capi-ems package-wasmer: # This command doesn't build the binary, just packages it mkdir -p ./package/bin +ifeq ($(OS), Windows_NT) + cp ./target/release/wasmer.exe ./package/bin/ +else cp ./target/release/wasmer ./package/bin/ - +endif # Comment WAPM for now to speedup release process # cp ./wapm-cli/target/release/wapm ./package/bin/ # # Create the wax binary as symlink to wapm @@ -157,8 +160,11 @@ package-docs: build-docs build-docs-capi package: package-wasmer package-capi cp LICENSE ./package/LICENSE cp ATTRIBUTIONS.md ./package/ATTRIBUTIONS +ifeq ($(OS), Windows_NT) + iscc wasmer.iss +else tar -C ./package -zcvf wasmer.tar.gz bin lib include LICENSE ATTRIBUTIONS - +endif ################# # Miscellaneous # From 16c3f3b3550916708912255d83f89219bdc62dc7 Mon Sep 17 00:00:00 2001 From: Syrus Date: Thu, 4 Jun 2020 21:50:45 -0700 Subject: [PATCH 20/44] Use tabs in Makefile --- Makefile | 62 ++++++++++++++++++++++++++++---------------------------- 1 file changed, 31 insertions(+), 31 deletions(-) diff --git a/Makefile b/Makefile index cd89837c2c4..59b2e784cdd 100644 --- a/Makefile +++ b/Makefile @@ -1,11 +1,11 @@ # uname only works in *Unix like systems ifneq ($(OS), Windows_NT) - ARCH := $(shell uname -m) - UNAME_S := $(shell uname -s) + ARCH := $(shell uname -m) + UNAME_S := $(shell uname -s) else - # We can assume, if in windows it will likely be in x86_64 - ARCH := x86_64 - UNAME_S := + # We can assume, if in windows it will likely be in x86_64 + ARCH := x86_64 + UNAME_S := endif compilers := @@ -14,38 +14,38 @@ compilers := RUST_VERSION := $(shell rustc -V) ifneq (, $(findstring nightly,$(RUST_VERSION))) - # Singlepass doesn't work yet on Windows - ifneq ($(OS), Windows_NT) - compilers += singlepass - endif + # Singlepass doesn't work yet on Windows + ifneq ($(OS), Windows_NT) + compilers += singlepass + endif endif ifeq ($(ARCH), x86_64) - # In X64, Cranelift is enabled - compilers += cranelift - # LLVM could be enabled if not in Windows - ifneq ($(OS), Windows_NT) - # Autodetect LLVM from llvm-config - ifneq (, $(shell which llvm-config)) - LLVM_VERSION := $(shell llvm-config --version) - # If findstring is not empty, then it have found the value - ifneq (, $(findstring 10,$(LLVM_VERSION))) - compilers += llvm - endif - else - ifneq (, $(shell which llvm-config-10)) - compilers += llvm - endif - endif - endif + # In X64, Cranelift is enabled + compilers += cranelift + # LLVM could be enabled if not in Windows + ifneq ($(OS), Windows_NT) + # Autodetect LLVM from llvm-config + ifneq (, $(shell which llvm-config)) + LLVM_VERSION := $(shell llvm-config --version) + # If findstring is not empty, then it have found the value + ifneq (, $(findstring 10,$(LLVM_VERSION))) + compilers += llvm + endif + else + ifneq (, $(shell which llvm-config-10)) + compilers += llvm + endif + endif + endif endif compilers := $(filter-out ,$(compilers)) ifneq ($(OS), Windows_NT) - bold := $(shell tput bold) - green := $(shell tput setaf 2) - reset := $(shell tput sgr0) + bold := $(shell tput bold) + green := $(shell tput setaf 2) + reset := $(shell tput sgr0) endif @@ -122,7 +122,7 @@ ifeq ($(OS), Windows_NT) else cp ./target/release/wasmer ./package/bin/ endif - # Comment WAPM for now to speedup release process + # Comment WAPM for now to speedup release process # cp ./wapm-cli/target/release/wapm ./package/bin/ # # Create the wax binary as symlink to wapm # cd ./package/bin/ && ln -sf wapm wax && chmod +x wax @@ -161,7 +161,7 @@ package: package-wasmer package-capi cp LICENSE ./package/LICENSE cp ATTRIBUTIONS.md ./package/ATTRIBUTIONS ifeq ($(OS), Windows_NT) - iscc wasmer.iss + iscc wasmer.iss else tar -C ./package -zcvf wasmer.tar.gz bin lib include LICENSE ATTRIBUTIONS endif From 79cf6868ad3c75f75f1b5969a9afcedc8db29db5 Mon Sep 17 00:00:00 2001 From: Syrus Date: Thu, 4 Jun 2020 22:03:10 -0700 Subject: [PATCH 21/44] Fix package windows --- Makefile | 1 - 1 file changed, 1 deletion(-) diff --git a/Makefile b/Makefile index 59b2e784cdd..93ba043183b 100644 --- a/Makefile +++ b/Makefile @@ -128,7 +128,6 @@ endif # cd ./package/bin/ && ln -sf wapm wax && chmod +x wax package-capi: - # This command doesn't build the C-API, just packages it mkdir -p ./package/ mkdir -p ./package/include mkdir -p ./package/lib From 9bcff76dd23d2f76e5ec67abd6c717579922e56a Mon Sep 17 00:00:00 2001 From: Syrus Date: Thu, 4 Jun 2020 22:08:51 -0700 Subject: [PATCH 22/44] Trying to fix issues --- Makefile | 46 +++++++++++++++++++++++----------------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/Makefile b/Makefile index 93ba043183b..aed87e04365 100644 --- a/Makefile +++ b/Makefile @@ -115,38 +115,38 @@ test-capi: test-capi-singlepass test-capi-cranelift test-capi-llvm test-capi-ems ############# package-wasmer: - # This command doesn't build the binary, just packages it - mkdir -p ./package/bin + mkdir -p package/bin ifeq ($(OS), Windows_NT) - cp ./target/release/wasmer.exe ./package/bin/ + cp target/release/wasmer.exe package/bin/ else - cp ./target/release/wasmer ./package/bin/ + cp target/release/wasmer package/bin/ endif - # Comment WAPM for now to speedup release process - # cp ./wapm-cli/target/release/wapm ./package/bin/ - # # Create the wax binary as symlink to wapm - # cd ./package/bin/ && ln -sf wapm wax && chmod +x wax + +# Comment WAPM for now to speedup release process +# cp ./wapm-cli/target/release/wapm package/bin/ +# # Create the wax binary as symlink to wapm +# cd package/bin/ && ln -sf wapm wax && chmod +x wax package-capi: - mkdir -p ./package/ - mkdir -p ./package/include - mkdir -p ./package/lib + mkdir -p package/ + mkdir -p package/include + mkdir -p package/lib ifeq ($(OS), Windows_NT) - cp target/release/wasmer_c_api.dll ./package/lib/wasmer.dll - cp target/release/wasmer_c_api.lib ./package/lib/wasmer.lib + cp target/release/wasmer_c_api.dll package/lib/wasmer.dll + cp target/release/wasmer_c_api.lib package/lib/wasmer.lib else ifeq ($(UNAME_S), Darwin) - cp target/release/libwasmer_c_api.dylib ./package/lib/libwasmer.dylib - cp target/release/libwasmer_c_api.a ./package/lib/libwasmer.a + cp target/release/libwasmer_c_api.dylib package/lib/libwasmer.dylib + cp target/release/libwasmer_c_api.a package/lib/libwasmer.a # Fix the rpath for the dylib - install_name_tool -id "@rpath/libwasmer.dylib" ./package/lib/libwasmer.dylib + install_name_tool -id "@rpath/libwasmer.dylib" package/lib/libwasmer.dylib else - cp target/release/libwasmer_c_api.so ./package/lib/libwasmer.so - cp target/release/libwasmer_c_api.a ./package/lib/libwasmer.a + cp target/release/libwasmer_c_api.so package/lib/libwasmer.so + cp target/release/libwasmer_c_api.a package/lib/libwasmer.a endif endif - find target/release/build -name 'wasmer.h*' -exec cp {} ./package/include ';' - cp lib/c-api/doc/index.md ./package/include/README.md + find target/release/build -name 'wasmer.h*' -exec cp {} package/include ';' + cp lib/c-api/doc/index.md package/include/README.md package-docs: build-docs build-docs-capi mkdir -p package/docs @@ -157,12 +157,12 @@ package-docs: build-docs build-docs-capi echo '' > package/docs/crates/index.html package: package-wasmer package-capi - cp LICENSE ./package/LICENSE - cp ATTRIBUTIONS.md ./package/ATTRIBUTIONS + cp LICENSE package/LICENSE + cp ATTRIBUTIONS.md package/ATTRIBUTIONS ifeq ($(OS), Windows_NT) iscc wasmer.iss else - tar -C ./package -zcvf wasmer.tar.gz bin lib include LICENSE ATTRIBUTIONS + tar -C package -zcvf wasmer.tar.gz bin lib include LICENSE ATTRIBUTIONS endif ################# From 02cd167530eed27bcb9704de8e501a8ddb663158 Mon Sep 17 00:00:00 2001 From: Syrus Date: Thu, 4 Jun 2020 22:10:26 -0700 Subject: [PATCH 23/44] Improved mkdir --- Makefile | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Makefile b/Makefile index aed87e04365..54ad7101ec3 100644 --- a/Makefile +++ b/Makefile @@ -128,9 +128,9 @@ endif # cd package/bin/ && ln -sf wapm wax && chmod +x wax package-capi: - mkdir -p package/ - mkdir -p package/include - mkdir -p package/lib + mkdir -p "package/" + mkdir -p "package/include" + mkdir -p "package/lib" ifeq ($(OS), Windows_NT) cp target/release/wasmer_c_api.dll package/lib/wasmer.dll cp target/release/wasmer_c_api.lib package/lib/wasmer.lib @@ -149,8 +149,8 @@ endif cp lib/c-api/doc/index.md package/include/README.md package-docs: build-docs build-docs-capi - mkdir -p package/docs - mkdir -p package/docs/c + mkdir -p "package/docs" + mkdir -p "package/docs/c" cp -R target/doc package/docs/crates cp -R lib/c-api/doc/html package/docs/c-api echo '' > package/docs/index.html From 2c0e58d887823792b1c97d47c2d47f9a1e84760f Mon Sep 17 00:00:00 2001 From: Syrus Date: Fri, 5 Jun 2020 00:21:25 -0700 Subject: [PATCH 24/44] Trying to improve Windows packaging --- Makefile | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/Makefile b/Makefile index 54ad7101ec3..574f69543dd 100644 --- a/Makefile +++ b/Makefile @@ -115,10 +115,12 @@ test-capi: test-capi-singlepass test-capi-cranelift test-capi-llvm test-capi-ems ############# package-wasmer: - mkdir -p package/bin ifeq ($(OS), Windows_NT) + if not exist "package" mkdir "package" + if not exist "package/bin" mkdir "package/bin" cp target/release/wasmer.exe package/bin/ else + mkdir -p "package/bin" cp target/release/wasmer package/bin/ endif @@ -128,13 +130,15 @@ endif # cd package/bin/ && ln -sf wapm wax && chmod +x wax package-capi: - mkdir -p "package/" - mkdir -p "package/include" - mkdir -p "package/lib" ifeq ($(OS), Windows_NT) + if not exist "package" mkdir "package" + if not exist "package/include" mkdir "package/include" + if not exist "package/lib" mkdir "package/lib" cp target/release/wasmer_c_api.dll package/lib/wasmer.dll cp target/release/wasmer_c_api.lib package/lib/wasmer.lib else + mkdir -p "package/include" + mkdir -p "package/lib" ifeq ($(UNAME_S), Darwin) cp target/release/libwasmer_c_api.dylib package/lib/libwasmer.dylib cp target/release/libwasmer_c_api.a package/lib/libwasmer.a @@ -145,12 +149,18 @@ else cp target/release/libwasmer_c_api.a package/lib/libwasmer.a endif endif - find target/release/build -name 'wasmer.h*' -exec cp {} package/include ';' + cp lib/c-api/wasmer.h package/include + cp lib/c-api/wasmer.hh package/include cp lib/c-api/doc/index.md package/include/README.md package-docs: build-docs build-docs-capi +ifeq ($(OS), Windows_NT) + if not exist "package" mkdir "package" + if not exist "package/docs" mkdir "package/docs" +else mkdir -p "package/docs" mkdir -p "package/docs/c" +endif cp -R target/doc package/docs/crates cp -R lib/c-api/doc/html package/docs/c-api echo '' > package/docs/index.html From 09cc8e42be37c6aa9d2cace8f598b60e93799758 Mon Sep 17 00:00:00 2001 From: Syrus Date: Fri, 5 Jun 2020 00:42:48 -0700 Subject: [PATCH 25/44] Improved windows commands --- Makefile | 23 ++++++++++++++--------- src/windows-installer/wasmer.iss | 7 +++++-- 2 files changed, 19 insertions(+), 11 deletions(-) diff --git a/Makefile b/Makefile index 574f69543dd..84b1e4e0f28 100644 --- a/Makefile +++ b/Makefile @@ -118,7 +118,7 @@ package-wasmer: ifeq ($(OS), Windows_NT) if not exist "package" mkdir "package" if not exist "package/bin" mkdir "package/bin" - cp target/release/wasmer.exe package/bin/ + copy "target\release\wasmer.exe" "package\bin" else mkdir -p "package/bin" cp target/release/wasmer package/bin/ @@ -134,11 +134,17 @@ ifeq ($(OS), Windows_NT) if not exist "package" mkdir "package" if not exist "package/include" mkdir "package/include" if not exist "package/lib" mkdir "package/lib" - cp target/release/wasmer_c_api.dll package/lib/wasmer.dll - cp target/release/wasmer_c_api.lib package/lib/wasmer.lib + copy ".\target\release\wasmer_c_api.dll" ".\package\lib\wasmer.dll" + copy ".\target\release\wasmer_c_api.lib" ".\package\lib\wasmer.lib" + copy ".\lib\c-api\wasmer.h" ".\package\include" + copy ".\lib\c-api\wasmer.hh" ".\package\include" + copy ".\lib\c-api\doc\index.md" ".\package\include\README.md" else mkdir -p "package/include" mkdir -p "package/lib" + cp lib/c-api/wasmer.h package/include + cp lib/c-api/wasmer.hh package/include + cp lib/c-api/doc/index.md package/include/README.md ifeq ($(UNAME_S), Darwin) cp target/release/libwasmer_c_api.dylib package/lib/libwasmer.dylib cp target/release/libwasmer_c_api.a package/lib/libwasmer.a @@ -149,9 +155,6 @@ else cp target/release/libwasmer_c_api.a package/lib/libwasmer.a endif endif - cp lib/c-api/wasmer.h package/include - cp lib/c-api/wasmer.hh package/include - cp lib/c-api/doc/index.md package/include/README.md package-docs: build-docs build-docs-capi ifeq ($(OS), Windows_NT) @@ -167,11 +170,13 @@ endif echo '' > package/docs/crates/index.html package: package-wasmer package-capi - cp LICENSE package/LICENSE - cp ATTRIBUTIONS.md package/ATTRIBUTIONS ifeq ($(OS), Windows_NT) - iscc wasmer.iss + copy ".\LICENSE" ".\package\LICENSE" + copy ".\ATTRIBUTIONS.md" ".\package\ATTRIBUTIONS" + cd src\windows-installer && iscc wasmer.iss else + cp LICENSE package/LICENSE + cp ATTRIBUTIONS.md package/ATTRIBUTIONS tar -C package -zcvf wasmer.tar.gz bin lib include LICENSE ATTRIBUTIONS endif diff --git a/src/windows-installer/wasmer.iss b/src/windows-installer/wasmer.iss index 76740958493..062052d8b85 100644 --- a/src/windows-installer/wasmer.iss +++ b/src/windows-installer/wasmer.iss @@ -21,8 +21,11 @@ Root: HKCU; Subkey: "Environment"; ValueType:string; ValueName: "WASMER_CACHE_DI ValueData: "{%USERPROFILE}\.wasmer\cache"; Flags: preservestringtype [Files] -Source: "..\..\target\release\wasmer.exe"; DestDir: "{app}\bin" -Source: "..\..\wapm-cli\target\release\wapm.exe"; DestDir: "{app}\bin" +Source: "..\..\package\bin\*"; DestDir: "{app}\bin" +Source: "..\..\package\include\*"; DestDir: "{app}\include" +Source: "..\..\package\lib\*"; DestDir: "{app}\lib" +Source: "..\..\package\LICENSE"; DestDir: "{app}" +Source: "..\..\package\ATTRIBUTIONS"; DestDir: "{app}" Source: "wax.cmd"; DestDir: "{app}\bin" [Dirs] From ae46b165ef74503f72fe2987c68d1d61d0263560 Mon Sep 17 00:00:00 2001 From: Syrus Date: Fri, 5 Jun 2020 00:52:27 -0700 Subject: [PATCH 26/44] Improved artifacts --- .gitignore | 2 +- Makefile | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index 2efd0d937aa..a0cf38ad90f 100644 --- a/.gitignore +++ b/.gitignore @@ -1,12 +1,12 @@ **/target **/*.rs.bk -/artifacts .DS_Store .idea **/.vscode api-docs-repo/ /.cargo_home/ /package/ +/dist/ /wapm-cli/ # Generated by tests on Android diff --git a/Makefile b/Makefile index 84b1e4e0f28..e0600907474 100644 --- a/Makefile +++ b/Makefile @@ -173,11 +173,15 @@ package: package-wasmer package-capi ifeq ($(OS), Windows_NT) copy ".\LICENSE" ".\package\LICENSE" copy ".\ATTRIBUTIONS.md" ".\package\ATTRIBUTIONS" - cd src\windows-installer && iscc wasmer.iss + iscc src\windows-installer\wasmer.iss + if not exist "dist" mkdir "dist" + copy ".\src\windows-installer\WasmerInstaller.exe" ".\dist\wasmer-windows.exe" else cp LICENSE package/LICENSE cp ATTRIBUTIONS.md package/ATTRIBUTIONS tar -C package -zcvf wasmer.tar.gz bin lib include LICENSE ATTRIBUTIONS + mkdir -p "dist" + cp ./wasmer.tar.gz ./dist/$(./scripts/capi-name.sh) endif ################# From 55a2ff231fc796dda3d4254538765a17f11071fd Mon Sep 17 00:00:00 2001 From: Syrus Date: Fri, 5 Jun 2020 01:20:13 -0700 Subject: [PATCH 27/44] Improved install script --- Makefile | 41 +++++++++++++---------------------------- 1 file changed, 13 insertions(+), 28 deletions(-) diff --git a/Makefile b/Makefile index e0600907474..ecfbfe7922e 100644 --- a/Makefile +++ b/Makefile @@ -115,12 +115,10 @@ test-capi: test-capi-singlepass test-capi-cranelift test-capi-llvm test-capi-ems ############# package-wasmer: + mkdir -p "package/bin" ifeq ($(OS), Windows_NT) - if not exist "package" mkdir "package" - if not exist "package/bin" mkdir "package/bin" - copy "target\release\wasmer.exe" "package\bin" + cp target/release/wasmer.exe package/bin/ else - mkdir -p "package/bin" cp target/release/wasmer package/bin/ endif @@ -130,21 +128,14 @@ endif # cd package/bin/ && ln -sf wapm wax && chmod +x wax package-capi: -ifeq ($(OS), Windows_NT) - if not exist "package" mkdir "package" - if not exist "package/include" mkdir "package/include" - if not exist "package/lib" mkdir "package/lib" - copy ".\target\release\wasmer_c_api.dll" ".\package\lib\wasmer.dll" - copy ".\target\release\wasmer_c_api.lib" ".\package\lib\wasmer.lib" - copy ".\lib\c-api\wasmer.h" ".\package\include" - copy ".\lib\c-api\wasmer.hh" ".\package\include" - copy ".\lib\c-api\doc\index.md" ".\package\include\README.md" -else mkdir -p "package/include" mkdir -p "package/lib" - cp lib/c-api/wasmer.h package/include - cp lib/c-api/wasmer.hh package/include + cp lib/c-api/wasmer.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 + cp target/release/wasmer_c_api.lib package/lib +else ifeq ($(UNAME_S), Darwin) cp target/release/libwasmer_c_api.dylib package/lib/libwasmer.dylib cp target/release/libwasmer_c_api.a package/lib/libwasmer.a @@ -157,31 +148,25 @@ endif endif package-docs: build-docs build-docs-capi -ifeq ($(OS), Windows_NT) - if not exist "package" mkdir "package" - if not exist "package/docs" mkdir "package/docs" -else mkdir -p "package/docs" mkdir -p "package/docs/c" -endif cp -R target/doc package/docs/crates cp -R lib/c-api/doc/html package/docs/c-api echo '' > package/docs/index.html echo '' > package/docs/crates/index.html package: package-wasmer package-capi + cp LICENSE package/LICENSE + cp ATTRIBUTIONS.md package/ATTRIBUTIONS + mkdir -p dist ifeq ($(OS), Windows_NT) - copy ".\LICENSE" ".\package\LICENSE" - copy ".\ATTRIBUTIONS.md" ".\package\ATTRIBUTIONS" - iscc src\windows-installer\wasmer.iss - if not exist "dist" mkdir "dist" - copy ".\src\windows-installer\WasmerInstaller.exe" ".\dist\wasmer-windows.exe" + iscc src/windows-installer/wasmer.iss + cp src/windows-installer/WasmerInstaller.exe dist/wasmer-windows.exe else cp LICENSE package/LICENSE cp ATTRIBUTIONS.md package/ATTRIBUTIONS tar -C package -zcvf wasmer.tar.gz bin lib include LICENSE ATTRIBUTIONS - mkdir -p "dist" - cp ./wasmer.tar.gz ./dist/$(./scripts/capi-name.sh) + cp ./wasmer.tar.gz ./dist/$(shell ./scripts/binary-name.sh) endif ################# From d63f2b70fb325cf4764852fff56a55780fcafe27 Mon Sep 17 00:00:00 2001 From: Syrus Date: Fri, 5 Jun 2020 01:29:37 -0700 Subject: [PATCH 28/44] Added scripts folder --- scripts/binary-name.sh | 46 ++++ scripts/install.sh | 475 ++++++++++++++++++++++++++++++++++++++ scripts/update-version.sh | 22 ++ 3 files changed, 543 insertions(+) create mode 100755 scripts/binary-name.sh create mode 100755 scripts/install.sh create mode 100755 scripts/update-version.sh diff --git a/scripts/binary-name.sh b/scripts/binary-name.sh new file mode 100755 index 00000000000..0245690b726 --- /dev/null +++ b/scripts/binary-name.sh @@ -0,0 +1,46 @@ +#!/bin/sh + +initArch() { + ARCH=$(uname -m) + if [ -n "$WASMER_ARCH" ]; then + ARCH="$WASMER_ARCH" + fi + # If you modify this list, please also modify install.sh + case $ARCH in + amd64) ARCH="amd64";; + x86_64) ARCH="amd64";; + aarch64) ARCH="arm64";; + i386) ARCH="386";; + *) echo "Architecture ${ARCH} is not supported by this installation script"; exit 1;; + esac +} + +initOS() { + OS=$(uname | tr '[:upper:]' '[:lower:]') + if [ -n "$WASMER_OS" ]; then + echo "Using WASMER_OS" + OS="$WASMER_OS" + fi + case "$OS" in + darwin) OS='darwin';; + linux) OS='linux';; + freebsd) OS='freebsd';; + # mingw*) OS='windows';; + # msys*) OS='windows';; + *) echo "OS ${OS} is not supported by this installation script"; exit 1;; + esac +} + +# identify platform based on uname output +initArch +initOS + +# determine install directory if required +BINARY="wasmer-${OS}-${ARCH}.tar.gz" + +# add .exe if on windows +# if [ "$OS" = "windows" ]; then +# BINARY="$BINARY.exe" +# fi + +echo "${BINARY}" diff --git a/scripts/install.sh b/scripts/install.sh new file mode 100755 index 00000000000..e7c7d7f9ac5 --- /dev/null +++ b/scripts/install.sh @@ -0,0 +1,475 @@ +#!/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 -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 -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) ARCH="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 diff --git a/scripts/update-version.sh b/scripts/update-version.sh new file mode 100755 index 00000000000..e12ac547c04 --- /dev/null +++ b/scripts/update-version.sh @@ -0,0 +1,22 @@ +# A script to update the version of all the crates at the same time +PREVIOUS_VERSION='0.16.2' +NEXT_VERSION='0.17.0' + +# quick hack +fd Cargo.toml --exec sed -i '' "s/version = \"$PREVIOUS_VERSION\"/version = \"$NEXT_VERSION\"/" +echo "manually check changes to Cargo.toml" + +fd wasmer.iss --exec sed -i '' "s/AppVersion=$PREVIOUS_VERSION/AppVersion=$NEXT_VERSION/" +echo "manually check changes to wasmer.iss" + +# Order to upload packages in +## runtime-core +## win-exception-handler +## middleware-common +## clif-backend +## llvm-backend +## singlepass-backend +## emscripten +## wasi +## runtime +## runtime-c-api From 7c1d7dcb065e717a136ca7f874e988441db25636 Mon Sep 17 00:00:00 2001 From: Syrus Date: Fri, 5 Jun 2020 11:36:45 -0700 Subject: [PATCH 29/44] Improved based on feedback --- Makefile | 2 +- lib/c-api/README.md | 10 ++++++ lib/c-api/doc/index.md | 9 ++++++ scripts/binary-name.sh | 7 ++--- scripts/install.sh | 7 ++--- src/commands/config.rs | 69 +++++++++++++++++++++++++++++++----------- 6 files changed, 78 insertions(+), 26 deletions(-) diff --git a/Makefile b/Makefile index ecfbfe7922e..8daf38b2b77 100644 --- a/Makefile +++ b/Makefile @@ -122,7 +122,7 @@ else cp target/release/wasmer package/bin/ endif -# Comment WAPM for now to speedup release process +# Comment out WAPM for now to speed up release process. # cp ./wapm-cli/target/release/wapm package/bin/ # # Create the wax binary as symlink to wapm # cd package/bin/ && ln -sf wapm wax && chmod +x wax diff --git a/lib/c-api/README.md b/lib/c-api/README.md index c9e9e3b8e15..0db0f144740 100644 --- a/lib/c-api/README.md +++ b/lib/c-api/README.md @@ -143,6 +143,16 @@ $ 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 diff --git a/lib/c-api/doc/index.md b/lib/c-api/doc/index.md index 539973938ec..168f00e881c 100644 --- a/lib/c-api/doc/index.md +++ b/lib/c-api/doc/index.md @@ -106,7 +106,16 @@ You can check more examples of how to use the Wasmer C API here: https://docs.wasmer.io/integrations/c/examples +## 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 diff --git a/scripts/binary-name.sh b/scripts/binary-name.sh index 0245690b726..79e1ff5c6ef 100755 --- a/scripts/binary-name.sh +++ b/scripts/binary-name.sh @@ -7,10 +7,9 @@ initArch() { fi # If you modify this list, please also modify install.sh case $ARCH in - amd64) ARCH="amd64";; - x86_64) ARCH="amd64";; + amd64|x86_64) ARCH="amd64";; aarch64) ARCH="arm64";; - i386) ARCH="386";; + # i386) ARCH="386";; *) echo "Architecture ${ARCH} is not supported by this installation script"; exit 1;; esac } @@ -18,7 +17,7 @@ initArch() { initOS() { OS=$(uname | tr '[:upper:]' '[:lower:]') if [ -n "$WASMER_OS" ]; then - echo "Using WASMER_OS" + echo "Using WASMER_OS (${WASMER_OS})" OS="$WASMER_OS" fi case "$OS" in diff --git a/scripts/install.sh b/scripts/install.sh index e7c7d7f9ac5..0e2f4f4813e 100755 --- a/scripts/install.sh +++ b/scripts/install.sh @@ -44,12 +44,12 @@ wasmer_download_json() { # echo "Fetching $url.." if test -x "$(command -v curl)"; then - response=$(curl -s -L -w 'HTTPSTATUS:%{http_code}' -H 'Accept: application/json' "$url") + 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 -q --header='Accept: application/json' -O - --server-response "$url" 2> "$temp") + 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 @@ -210,8 +210,7 @@ initArch() { fi # If you modify this list, please also modify scripts/binary-name.sh case $ARCH in - amd64) ARCH="amd64";; - x86_64) ARCH="amd64";; + 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;; diff --git a/src/commands/config.rs b/src/commands/config.rs index 75e6f95892c..071b0017857 100644 --- a/src/commands/config.rs +++ b/src/commands/config.rs @@ -1,3 +1,4 @@ +use crate::VERSION; use anyhow::{Context, Result}; use std::env; use std::path::PathBuf; @@ -7,20 +8,33 @@ use structopt::StructOpt; /// The options for the `wasmer config` subcommand pub struct Config { /// Print the installation prefix. - #[structopt(long)] + #[structopt(long, conflicts_with = "pkg_config")] prefix: bool, /// Directory containing Wasmer executables. - #[structopt(long)] + #[structopt(long, conflicts_with = "pkg_config")] bindir: bool, /// Directory containing Wasmer headers. - #[structopt(long)] + #[structopt(long, conflicts_with = "pkg_config")] includedir: bool, /// Directory containing Wasmer libraries. - #[structopt(long)] + #[structopt(long, conflicts_with = "pkg_config")] libdir: bool, + + /// Libraries needed to link against Wasmer components. + #[structopt(long, conflicts_with = "pkg_config")] + libs: bool, + + /// C compiler flags for files that include Wasmer headers. + #[structopt(long, conflicts_with = "pkg_config")] + cflags: bool, + + /// It outputs the necessary details for compiling + /// and linking a program to Wasmer, using the `pkg-config` format. + #[structopt(long)] + pkg_config: bool, } impl Config { @@ -32,29 +46,50 @@ impl Config { fn inner_execute(&self) -> Result<()> { let key = "WASMER_DIR"; let wasmer_dir = env::var(key).context(format!( - "failed to retrieve the {} environment variable", + "failed to retrieve the {} environment variables", key ))?; - let mut prefix = PathBuf::new(); - prefix.push(wasmer_dir); + + let prefix = PathBuf::from(wasmer_dir); + + let prefixdir = prefix.display().to_string(); + let bindir = prefix.join("bin").display().to_string(); + let includedir = prefix.join("include").display().to_string(); + let libdir = prefix.join("lib").display().to_string(); + let cflags = format!("-I{}/wasmer", includedir); + let libs = format!("-L{} -lwasmer", libdir); + + if self.pkg_config { + println!("prefix={}", prefixdir); + println!("exec_prefix={}", bindir); + println!("includedir={}", includedir); + println!("libdir={}", libdir); + println!(""); + println!("Name: wasmer"); + println!("Description: The Wasmer library for running WebAssembly"); + println!("Version: {}", VERSION); + println!("Cflags: {}", cflags); + println!("Libs: {}", libs); + return Ok(()); + } if self.prefix { - println!("{}", prefix.display()); + println!("{}", prefixdir); } if self.bindir { - let mut bindir = prefix.clone(); - bindir.push("bin"); - println!("{}", bindir.display()); + println!("{}", bindir); } if self.includedir { - let mut includedir = prefix.clone(); - includedir.push("include"); - println!("{}", includedir.display()); + println!("{}", includedir); } if self.libdir { - let mut libdir = prefix.clone(); - libdir.push("lib"); - println!("{}", libdir.display()); + println!("{}", libdir); + } + if self.libs { + println!("{}", libs); + } + if self.cflags { + println!("{}", cflags); } Ok(()) } From f94696b2ce30a21503b7b826701e7e678988c27a Mon Sep 17 00:00:00 2001 From: Nick Lewycky Date: Sat, 6 Jun 2020 17:22:26 -0700 Subject: [PATCH 30/44] Fix repeated typo "funciton". --- lib/api/src/externals/function.rs | 2 +- lib/api/src/module.rs | 2 +- lib/compiler-cranelift/src/translator/translation_utils.rs | 2 +- lib/engine/src/artifact.rs | 2 +- lib/engine/src/resolver.rs | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/api/src/externals/function.rs b/lib/api/src/externals/function.rs index fcd8ce6f740..590a9c280aa 100644 --- a/lib/api/src/externals/function.rs +++ b/lib/api/src/externals/function.rs @@ -306,7 +306,7 @@ impl std::fmt::Debug for Function { } } -/// This trait is one that all dynamic funcitons must fulfill. +/// This trait is one that all dynamic functions must fulfill. trait VMDynamicFunction { fn call(&self, args: &[Val]) -> Result, RuntimeError>; fn function_type(&self) -> &FunctionType; diff --git a/lib/api/src/module.rs b/lib/api/src/module.rs index 77d9fa75304..45d01767e28 100644 --- a/lib/api/src/module.rs +++ b/lib/api/src/module.rs @@ -414,7 +414,7 @@ impl Module { } /// The ABI of the ModuleInfo is very unstable, we refactor it very often. - /// This funciton is public because in some cases it can be useful to get some + /// This function is public because in some cases it can be useful to get some /// extra information from the module. /// /// However, the usage is highly discouraged. diff --git a/lib/compiler-cranelift/src/translator/translation_utils.rs b/lib/compiler-cranelift/src/translator/translation_utils.rs index 3872646c714..7b871021c94 100644 --- a/lib/compiler-cranelift/src/translator/translation_utils.rs +++ b/lib/compiler-cranelift/src/translator/translation_utils.rs @@ -15,7 +15,7 @@ use wasmer_compiler::{JumpTable, RelocationKind}; use wasmer_compiler::{WasmError, WasmResult}; use wasmer_runtime::libcalls::LibCall; -/// Helper function translate a Funciton signature into Cranelift Ir +/// Helper function translate a Function signature into Cranelift Ir pub fn signature_to_cranelift_ir( signature: &FunctionType, target_config: &TargetFrontendConfig, diff --git a/lib/engine/src/artifact.rs b/lib/engine/src/artifact.rs index c7ac9279337..840d81fe4bb 100644 --- a/lib/engine/src/artifact.rs +++ b/lib/engine/src/artifact.rs @@ -54,7 +54,7 @@ pub trait Artifact { /// ready to be run. fn finished_functions(&self) -> &BoxedSlice; - /// Returns the dynamic funciton trampolines allocated in memory + /// Returns the dynamic function trampolines allocated in memory /// for this `Artifact`, ready to be run. fn finished_dynamic_function_trampolines( &self, diff --git a/lib/engine/src/resolver.rs b/lib/engine/src/resolver.rs index a3bf04bf9ae..17f50584f79 100644 --- a/lib/engine/src/resolver.rs +++ b/lib/engine/src/resolver.rs @@ -163,7 +163,7 @@ pub fn resolve_imports( let address = match f.kind { VMFunctionKind::Dynamic => { // If this is a dynamic imported function, - // the address of the funciton is the address of the + // the address of the function is the address of the // reverse trampoline. let index = FunctionIndex::new(function_imports.len()); finished_dynamic_function_trampolines[index] From b2c0ef4f950b7c74f299a0e00aa54438330557c6 Mon Sep 17 00:00:00 2001 From: Nick Lewycky Date: Wed, 3 Jun 2020 09:36:57 -0700 Subject: [PATCH 31/44] NFC. Use const_zero() method or free function instead of const_int(0) and const_float(0.0). --- lib/compiler-llvm/src/translator/code.rs | 34 ++++++------------------ 1 file changed, 8 insertions(+), 26 deletions(-) diff --git a/lib/compiler-llvm/src/translator/code.rs b/lib/compiler-llvm/src/translator/code.rs index eb67f04619b..c220af2e765 100644 --- a/lib/compiler-llvm/src/translator/code.rs +++ b/lib/compiler-llvm/src/translator/code.rs @@ -606,7 +606,7 @@ impl<'ctx, 'a> LLVMFunctionCodeGenerator<'ctx, 'a> { let divisor_is_zero = self.builder.build_int_compare( IntPredicate::EQ, right, - int_type.const_int(0, false), + int_type.const_zero(), "divisor_is_zero", ); let should_trap = self.builder.build_or( @@ -631,10 +631,7 @@ impl<'ctx, 'a> LLVMFunctionCodeGenerator<'ctx, 'a> { self.intrinsics.expect_i1, &[ should_trap.as_basic_value_enum(), - self.intrinsics - .i1_ty - .const_int(0, false) - .as_basic_value_enum(), + self.intrinsics.i1_ty.const_zero().as_basic_value_enum(), ], "should_trap_expect", ) @@ -669,7 +666,7 @@ impl<'ctx, 'a> LLVMFunctionCodeGenerator<'ctx, 'a> { let should_trap = self.builder.build_int_compare( IntPredicate::EQ, value, - int_type.const_int(0, false), + int_type.const_zero(), "divisor_is_zero", ); @@ -679,10 +676,7 @@ impl<'ctx, 'a> LLVMFunctionCodeGenerator<'ctx, 'a> { self.intrinsics.expect_i1, &[ should_trap.as_basic_value_enum(), - self.intrinsics - .i1_ty - .const_int(0, false) - .as_basic_value_enum(), + self.intrinsics.i1_ty.const_zero().as_basic_value_enum(), ], "should_trap_expect", ) @@ -1177,7 +1171,7 @@ fn emit_stack_map<'ctx>( .const_int(stackmap_id as u64, false) .as_basic_value_enum(), ); - params.push(intrinsics.i32_ty.const_int(0, false).as_basic_value_enum()); + params.push(intrinsics.i32_ty.const_zero().as_basic_value_enum()); let locals: Vec<_> = locals.iter().map(|x| x.as_basic_value_enum()).collect(); let mut value_semantics: Vec = @@ -1224,7 +1218,7 @@ fn finalize_opcode_stack_map<'ctx>( .i64_ty .const_int(stackmap_id as u64, false) .as_basic_value_enum(), - intrinsics.i32_ty.const_int(0, false).as_basic_value_enum(), + intrinsics.i32_ty.const_zero().as_basic_value_enum(), ], "opcode_stack_map_end", ); @@ -1388,7 +1382,7 @@ impl<'ctx, 'a> LLVMFunctionCodeGenerator<'ctx, 'a> { ); let signal_mem = ctx.signal_mem(); let iv = self.builder - .build_store(signal_mem, self.context.i8_type().const_int(0 as u64, false)); + .build_store(signal_mem, self.context.i8_type().const_zero()); // Any 'store' can be made volatile. iv.set_volatile(true).unwrap(); finalize_opcode_stack_map( @@ -1694,19 +1688,7 @@ impl<'ctx, 'a> LLVMFunctionCodeGenerator<'ctx, 'a> { self.state.push1(phi.as_basic_value()); } else { let basic_ty = phi.as_basic_value().get_type(); - let placeholder_value = match basic_ty { - BasicTypeEnum::IntType(int_ty) => { - int_ty.const_int(0, false).as_basic_value_enum() - } - BasicTypeEnum::FloatType(float_ty) => { - float_ty.const_float(0.0).as_basic_value_enum() - } - _ => { - return Err(CompileError::Codegen( - "Operator::End phi type unimplemented".to_string(), - )); - } - }; + let placeholder_value = const_zero(basic_ty); self.state.push1(placeholder_value); phi.as_instruction().erase_from_basic_block(); } From ce543fd4edc65deb1c73ac7447b936dcaf1ba081 Mon Sep 17 00:00:00 2001 From: Nick Lewycky Date: Wed, 3 Jun 2020 11:10:48 -0700 Subject: [PATCH 32/44] NFC. Don't re-lookup frame. It can't have changed, simply reorder operations. --- lib/compiler-llvm/src/translator/code.rs | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/lib/compiler-llvm/src/translator/code.rs b/lib/compiler-llvm/src/translator/code.rs index c220af2e765..c62b1a83156 100644 --- a/lib/compiler-llvm/src/translator/code.rs +++ b/lib/compiler-llvm/src/translator/code.rs @@ -1609,14 +1609,13 @@ impl<'ctx, 'a> LLVMFunctionCodeGenerator<'ctx, 'a> { let current_block = self.builder.get_insert_block().ok_or_else(|| { CompileError::Codegen("not currently in a block".to_string()) })?; + self.builder.build_unconditional_branch(*frame.code_after()); for phi in frame.phis().to_vec().iter().rev() { let (value, info) = self.state.pop1_extra()?; let value = self.apply_pending_canonicalization(value, info); phi.add_incoming(&[(&value, current_block)]) } - let frame = self.state.frame_at_depth(0)?; - self.builder.build_unconditional_branch(*frame.code_after()); } let (if_else_block, if_else_state) = if let ControlFrame::IfElse { @@ -1701,15 +1700,13 @@ impl<'ctx, 'a> LLVMFunctionCodeGenerator<'ctx, 'a> { .ok_or_else(|| CompileError::Codegen("not currently in a block".to_string()))?; let frame = self.state.outermost_frame()?; + self.builder.build_unconditional_branch(*frame.br_dest()); for phi in frame.phis().to_vec().iter().rev() { let (arg, info) = self.state.pop1_extra()?; let arg = self.apply_pending_canonicalization(arg, info); phi.add_incoming(&[(&arg, current_block)]); } - let frame = self.state.outermost_frame()?; - self.builder.build_unconditional_branch(*frame.br_dest()); - self.state.reachable = false; } From cbc7dc84544034f708af095913edfabac161583d Mon Sep 17 00:00:00 2001 From: Nick Lewycky Date: Wed, 3 Jun 2020 17:07:20 -0700 Subject: [PATCH 33/44] Add multi-value-import tests. Also fix implementation of trampolines in LLVM. --- lib/compiler-llvm/src/trampoline/wasm.rs | 102 ++++++++---- tests/compilers/main.rs | 1 + tests/compilers/multi_value_imports.rs | 204 +++++++++++++++++++++++ 3 files changed, 275 insertions(+), 32 deletions(-) create mode 100644 tests/compilers/multi_value_imports.rs diff --git a/lib/compiler-llvm/src/trampoline/wasm.rs b/lib/compiler-llvm/src/trampoline/wasm.rs index cb5671ef8b4..3a578013be1 100644 --- a/lib/compiler-llvm/src/trampoline/wasm.rs +++ b/lib/compiler-llvm/src/trampoline/wasm.rs @@ -1,6 +1,9 @@ use crate::config::{CompiledFunctionKind, LLVMConfig}; use crate::object_file::load_object_file; -use crate::translator::abi::{func_type_to_llvm, is_sret, rets_from_call}; +use crate::translator::abi::{ + func_type_to_llvm, get_vmctx_ptr_param, is_sret, pack_values_for_register_return, + rets_from_call, +}; use crate::translator::intrinsics::{type_to_llvm, type_to_llvm_ptr, Intrinsics}; use inkwell::{ attributes::{Attribute, AttributeLoc}, @@ -14,7 +17,6 @@ use inkwell::{ }; use std::cmp; use std::convert::TryInto; -use std::iter; use wasm_common::{FunctionType, Type}; use wasmer_compiler::{CompileError, FunctionBody}; @@ -134,16 +136,11 @@ impl FuncTrampoline { module.set_data_layout(&target_machine.get_target_data().get_data_layout()); let intrinsics = Intrinsics::declare(&module, &self.ctx); - let params = iter::once(Ok(intrinsics.ctx_ptr_ty.as_basic_type_enum())) - .chain( - ty.params() - .iter() - .map(|param_ty| type_to_llvm(&intrinsics, *param_ty)), - ) - .collect::, _>>()?; - let trampoline_ty = intrinsics.void_ty.fn_type(params.as_slice(), false); - + let (trampoline_ty, trampoline_attrs) = func_type_to_llvm(&self.ctx, &intrinsics, ty)?; let trampoline_func = module.add_function("", trampoline_ty, Some(Linkage::External)); + for (attr, attr_loc) in trampoline_attrs { + trampoline_func.add_attribute(attr_loc, attr); + } trampoline_func .as_global_value() .set_section(FUNCTION_SECTION); @@ -343,7 +340,12 @@ fn generate_dynamic_trampoline<'ctx>( let ptr = builder .build_bitcast(ptr, type_to_llvm_ptr(intrinsics, func_sig.params()[i])?, "") .into_pointer_value(); - builder.build_store(ptr, trampoline_func.get_nth_param(i as u32 + 1).unwrap()); + builder.build_store( + ptr, + trampoline_func + .get_nth_param(i as u32 + if is_sret(func_sig)? { 2 } else { 1 }) + .unwrap(), + ); } let callee_ty = intrinsics @@ -358,7 +360,7 @@ fn generate_dynamic_trampoline<'ctx>( .ptr_type(AddressSpace::Generic) .ptr_type(AddressSpace::Generic); - let vmctx = trampoline_func.get_nth_param(0).unwrap(); + let vmctx = get_vmctx_ptr_param(&trampoline_func); let callee = builder .build_load( builder @@ -368,32 +370,68 @@ fn generate_dynamic_trampoline<'ctx>( ) .into_pointer_value(); + let values_ptr = builder.build_pointer_cast(values, intrinsics.i128_ptr_ty, ""); builder.build_call( callee, - &[vmctx.as_basic_value_enum(), values.as_basic_value_enum()], + &[ + vmctx.as_basic_value_enum(), + values_ptr.as_basic_value_enum(), + ], "", ); - match func_sig.results() { - [] => { - builder.build_return(None); - } - [ty] => { - let ptr = unsafe { - builder.build_in_bounds_gep( - values, - &[intrinsics.i32_zero, intrinsics.i32_ty.const_int(0, false)], - "", - ) - }; - let ptr = builder - .build_bitcast(ptr, type_to_llvm_ptr(intrinsics, *ty)?, "") + if func_sig.results().is_empty() { + builder.build_return(None); + } else { + let results = func_sig + .results() + .iter() + .enumerate() + .map(|(idx, ty)| { + let ptr = unsafe { + builder.build_gep( + values, + &[intrinsics.i32_ty.const_int(idx.try_into().unwrap(), false)], + "", + ) + }; + let ptr = builder.build_pointer_cast(ptr, type_to_llvm_ptr(intrinsics, *ty)?, ""); + Ok(builder.build_load(ptr, "")) + }) + .collect::, CompileError>>()?; + + if is_sret(func_sig)? { + let sret = trampoline_func + .get_first_param() + .unwrap() .into_pointer_value(); - let ret = builder.build_load(ptr, ""); - builder.build_return(Some(&ret)); + let mut struct_value = sret + .get_type() + .get_element_type() + .into_struct_type() + .get_undef(); + for (idx, value) in results.iter().enumerate() { + let value = builder.build_bitcast( + *value, + type_to_llvm(&intrinsics, func_sig.results()[idx])?, + "", + ); + struct_value = builder + .build_insert_value(struct_value, value, idx as u32, "") + .unwrap() + .into_struct_value(); + } + builder.build_store(sret, struct_value); + builder.build_return(None); + } else { + builder.build_return(Some(&pack_values_for_register_return( + &intrinsics, + &builder, + &results.as_slice(), + &trampoline_func.get_type(), + )?)); } - _ => unimplemented!("multi-value return is not yet implemented"), - }; + } Ok(()) } diff --git a/tests/compilers/main.rs b/tests/compilers/main.rs index a02d5995a00..cd64133079f 100644 --- a/tests/compilers/main.rs +++ b/tests/compilers/main.rs @@ -5,4 +5,5 @@ #[macro_use] mod macros; mod imports; +mod multi_value_imports; mod wast; diff --git a/tests/compilers/multi_value_imports.rs b/tests/compilers/multi_value_imports.rs new file mode 100644 index 00000000000..7e4df360b8e --- /dev/null +++ b/tests/compilers/multi_value_imports.rs @@ -0,0 +1,204 @@ +//! Testing the imports with different provided functions. +//! This tests checks that the provided functions (both native and +//! dynamic ones) work properly. + +macro_rules! mvr_test { + ($test_name:ident, $( $result_type:ty ),* ) => { + mod $test_name { + use super::*; + + fn get_module(store: &Store) -> anyhow::Result { + let wat: String = r#" + (type $type (func (param i32) (result +"#.to_string() + + &stringify!( $( $result_type ),* ).replace(",", "").replace("(", "").replace(")", "") + &r#"))) + (import "host" "callback_fn" (func $callback_fn (type $type))) + (func (export "test_call") (type $type) + get_local 0 + call $callback_fn) + (func (export "test_call_indirect") (type $type) + (i32.const 1) + (call_indirect (type $type) (i32.const 0)) + ) + (table funcref + (elem + $callback_fn + ) + ) +"#.to_string(); + Ok(wasmer::Module::new(&store, &wat)?) + } + + fn callback_fn(n: i32) -> ( $( $result_type ),* ) { + ( $( <$result_type>::expected_value(n) ),* ) + } + + #[test] + fn native() -> anyhow::Result<()> { + let store = get_store(); + let module = get_module(&store)?; + let instance = wasmer::Instance::new( + &module, + &wasmer::imports! { + "host" => { + "callback_fn" => wasmer::Function::new(&store, callback_fn) + } + } + )?; + let expected_value = vec![ $( <$result_type>::expected_val(1) ),* ].into_boxed_slice(); + assert_eq!(instance.exports.get_function("test_call")?.call(&[wasmer::Val::I32(1)])?, + expected_value); + assert_eq!(instance.exports.get_function("test_call_indirect")?.call(&[wasmer::Val::I32(1)])?, + expected_value); + Ok(()) + } + + fn dynamic_callback_fn(values: &[wasmer::Value]) -> Result, wasmer::RuntimeError> { + assert_eq!(values[0], wasmer::Value::I32(1)); + Ok(vec![ $( <$result_type>::expected_val(1) ),* ]) + } + + #[test] + fn dynamic() -> anyhow::Result<()> { + let store = get_store(); + let module = get_module(&store)?; + let instance = wasmer::Instance::new( + &module, + &wasmer::imports! { + "host" => { + "callback_fn" => wasmer::Function::new_dynamic(&store, &wasmer::FunctionType::new(vec![wasmer::ValType::I32], vec![ $( <$result_type>::expected_valtype() ),* ]), dynamic_callback_fn) + } + } + )?; + let expected_value = vec![ $( <$result_type>::expected_val(1) ),* ].into_boxed_slice(); + assert_eq!(instance.exports.get_function("test_call")?.call(&[wasmer::Val::I32(1)])?, + expected_value); + assert_eq!(instance.exports.get_function("test_call_indirect")?.call(&[wasmer::Val::I32(1)])?, + expected_value); + Ok(()) + } + } + } +} + +wasmer_compilers! { +trait ExpectedExpr { + fn expected_value(n: i32) -> Self; + fn expected_val(n: i32) -> wasmer::Val; + fn expected_valtype() -> wasmer::ValType; +} +impl ExpectedExpr for i32 { + fn expected_value(n: i32) -> i32 { + n + 1 + } + fn expected_val(n: i32) -> wasmer::Val { + wasmer::Val::I32(Self::expected_value(n)) + } + fn expected_valtype() -> wasmer::ValType { + wasmer::ValType::I32 + } +} +impl ExpectedExpr for i64 { + fn expected_value(n: i32) -> i64 { + n as i64 + 2i64 + } + fn expected_val(n: i32) -> wasmer::Val { + wasmer::Val::I64(Self::expected_value(n)) + } + fn expected_valtype() -> wasmer::ValType { + wasmer::ValType::I64 + } +} +impl ExpectedExpr for f32 { + fn expected_value(n: i32) -> f32 { + n as f32 * 0.1 + } + fn expected_val(n: i32) -> wasmer::Val { + wasmer::Val::F32(Self::expected_value(n)) + } + fn expected_valtype() -> wasmer::ValType { + wasmer::ValType::F32 + } +} +impl ExpectedExpr for f64 { + fn expected_value(n: i32) -> f64 { + n as f64 * 0.12 + } + fn expected_val(n: i32) -> wasmer::Val { + wasmer::Val::F64(Self::expected_value(n)) + } + fn expected_valtype() -> wasmer::ValType { + wasmer::ValType::F64 + } +} + + mvr_test!(test_mvr_i32_i32, i32, i32); +mvr_test!(test_mvr_i32_f32, i32, f32); +mvr_test!(test_mvr_f32_i32, f32, i32); +mvr_test!(test_mvr_f32_f32, f32, f32); + +mvr_test!(test_mvr_i64_i32, i64, i32); +mvr_test!(test_mvr_i64_f32, i64, f32); +mvr_test!(test_mvr_f64_i32, f64, i32); +mvr_test!(test_mvr_f64_f32, f64, f32); + +mvr_test!(test_mvr_i32_i64, i32, i64); +mvr_test!(test_mvr_f32_i64, f32, i64); +mvr_test!(test_mvr_i32_f64, i32, f64); +mvr_test!(test_mvr_f32_f64, f32, f64); + +mvr_test!(test_mvr_i32_i32_i32, i32, i32, i32); +mvr_test!(test_mvr_i32_i32_f32, i32, i32, f32); +mvr_test!(test_mvr_i32_f32_i32, i32, f32, i32); +mvr_test!(test_mvr_i32_f32_f32, i32, f32, f32); +mvr_test!(test_mvr_f32_i32_i32, f32, i32, i32); +mvr_test!(test_mvr_f32_i32_f32, f32, i32, f32); +mvr_test!(test_mvr_f32_f32_i32, f32, f32, i32); +mvr_test!(test_mvr_f32_f32_f32, f32, f32, f32); + +mvr_test!(test_mvr_i32_i32_i64, i32, i32, i64); +mvr_test!(test_mvr_i32_f32_i64, i32, f32, i64); +mvr_test!(test_mvr_f32_i32_i64, f32, i32, i64); +mvr_test!(test_mvr_f32_f32_i64, f32, f32, i64); +mvr_test!(test_mvr_i32_i32_f64, i32, i32, f64); +mvr_test!(test_mvr_i32_f32_f64, i32, f32, f64); +mvr_test!(test_mvr_f32_i32_f64, f32, i32, f64); +mvr_test!(test_mvr_f32_f32_f64, f32, f32, f64); + +mvr_test!(test_mvr_i32_i64_i32, i32, i64, i32); +mvr_test!(test_mvr_i32_i64_f32, i32, i64, f32); +mvr_test!(test_mvr_f32_i64_i32, f32, i64, i32); +mvr_test!(test_mvr_f32_i64_f32, f32, i64, f32); +mvr_test!(test_mvr_i32_f64_i32, i32, f64, i32); +mvr_test!(test_mvr_i32_f64_f32, i32, f64, f32); +mvr_test!(test_mvr_f32_f64_i32, f32, f64, i32); +mvr_test!(test_mvr_f32_f64_f32, f32, f64, f32); + +mvr_test!(test_mvr_i64_i32_i32, i64, i32, i32); +mvr_test!(test_mvr_i64_i32_f32, i64, i32, f32); +mvr_test!(test_mvr_i64_f32_i32, i64, f32, i32); +mvr_test!(test_mvr_i64_f32_f32, i64, f32, f32); +mvr_test!(test_mvr_f64_i32_i32, f64, i32, i32); +mvr_test!(test_mvr_f64_i32_f32, f64, i32, f32); +mvr_test!(test_mvr_f64_f32_i32, f64, f32, i32); +mvr_test!(test_mvr_f64_f32_f32, f64, f32, f32); + +mvr_test!(test_mvr_i32_i32_i32_i32, i32, i32, i32, i32); +mvr_test!(test_mvr_i32_i32_i32_f32, i32, i32, i32, f32); +mvr_test!(test_mvr_i32_i32_f32_i32, i32, i32, f32, i32); +mvr_test!(test_mvr_i32_i32_f32_f32, i32, i32, f32, f32); +mvr_test!(test_mvr_i32_f32_i32_i32, i32, f32, i32, i32); +mvr_test!(test_mvr_i32_f32_i32_f32, i32, f32, i32, f32); +mvr_test!(test_mvr_i32_f32_f32_i32, i32, f32, f32, i32); +mvr_test!(test_mvr_i32_f32_f32_f32, i32, f32, f32, f32); +mvr_test!(test_mvr_f32_i32_i32_i32, f32, i32, i32, i32); +mvr_test!(test_mvr_f32_i32_i32_f32, f32, i32, i32, f32); +mvr_test!(test_mvr_f32_i32_f32_i32, f32, i32, f32, i32); +mvr_test!(test_mvr_f32_i32_f32_f32, f32, i32, f32, f32); +mvr_test!(test_mvr_f32_f32_i32_i32, f32, f32, i32, i32); +mvr_test!(test_mvr_f32_f32_i32_f32, f32, f32, i32, f32); +mvr_test!(test_mvr_f32_f32_f32_i32, f32, f32, f32, i32); +mvr_test!(test_mvr_f32_f32_f32_f32, f32, f32, f32, f32); + +mvr_test!(test_mvr_i32_i32_i32_i32_i32, i32, i32, i32, i32, i32); +} From 56b0c8e29ac22b16943c6c81a57b50f4103d2d09 Mon Sep 17 00:00:00 2001 From: Nick Lewycky Date: Fri, 5 Jun 2020 09:22:43 -0700 Subject: [PATCH 34/44] rustfmt doesn't touch this file. Indent it. --- tests/compilers/multi_value_imports.rs | 328 ++++++++++++------------- 1 file changed, 164 insertions(+), 164 deletions(-) diff --git a/tests/compilers/multi_value_imports.rs b/tests/compilers/multi_value_imports.rs index 7e4df360b8e..d95f62e6343 100644 --- a/tests/compilers/multi_value_imports.rs +++ b/tests/compilers/multi_value_imports.rs @@ -7,11 +7,11 @@ macro_rules! mvr_test { mod $test_name { use super::*; - fn get_module(store: &Store) -> anyhow::Result { - let wat: String = r#" + fn get_module(store: &Store) -> anyhow::Result { + let wat: String = r#" (type $type (func (param i32) (result "#.to_string() + - &stringify!( $( $result_type ),* ).replace(",", "").replace("(", "").replace(")", "") + &r#"))) + &stringify!( $( $result_type ),* ).replace(",", "").replace("(", "").replace(")", "") + &r#"))) (import "host" "callback_fn" (func $callback_fn (type $type))) (func (export "test_call") (type $type) get_local 0 @@ -26,179 +26,179 @@ macro_rules! mvr_test { ) ) "#.to_string(); - Ok(wasmer::Module::new(&store, &wat)?) - } - - fn callback_fn(n: i32) -> ( $( $result_type ),* ) { - ( $( <$result_type>::expected_value(n) ),* ) - } - - #[test] - fn native() -> anyhow::Result<()> { - let store = get_store(); - let module = get_module(&store)?; - let instance = wasmer::Instance::new( - &module, - &wasmer::imports! { - "host" => { - "callback_fn" => wasmer::Function::new(&store, callback_fn) + Ok(wasmer::Module::new(&store, &wat)?) + } + + fn callback_fn(n: i32) -> ( $( $result_type ),* ) { + ( $( <$result_type>::expected_value(n) ),* ) + } + + #[test] + fn native() -> anyhow::Result<()> { + let store = get_store(); + let module = get_module(&store)?; + let instance = wasmer::Instance::new( + &module, + &wasmer::imports! { + "host" => { + "callback_fn" => wasmer::Function::new(&store, callback_fn) + } } - } - )?; - let expected_value = vec![ $( <$result_type>::expected_val(1) ),* ].into_boxed_slice(); - assert_eq!(instance.exports.get_function("test_call")?.call(&[wasmer::Val::I32(1)])?, - expected_value); - assert_eq!(instance.exports.get_function("test_call_indirect")?.call(&[wasmer::Val::I32(1)])?, - expected_value); - Ok(()) - } - - fn dynamic_callback_fn(values: &[wasmer::Value]) -> Result, wasmer::RuntimeError> { - assert_eq!(values[0], wasmer::Value::I32(1)); - Ok(vec![ $( <$result_type>::expected_val(1) ),* ]) - } - - #[test] - fn dynamic() -> anyhow::Result<()> { - let store = get_store(); - let module = get_module(&store)?; - let instance = wasmer::Instance::new( - &module, - &wasmer::imports! { - "host" => { - "callback_fn" => wasmer::Function::new_dynamic(&store, &wasmer::FunctionType::new(vec![wasmer::ValType::I32], vec![ $( <$result_type>::expected_valtype() ),* ]), dynamic_callback_fn) + )?; + let expected_value = vec![ $( <$result_type>::expected_val(1) ),* ].into_boxed_slice(); + assert_eq!(instance.exports.get_function("test_call")?.call(&[wasmer::Val::I32(1)])?, + expected_value); + assert_eq!(instance.exports.get_function("test_call_indirect")?.call(&[wasmer::Val::I32(1)])?, + expected_value); + Ok(()) + } + + fn dynamic_callback_fn(values: &[wasmer::Value]) -> Result, wasmer::RuntimeError> { + assert_eq!(values[0], wasmer::Value::I32(1)); + Ok(vec![ $( <$result_type>::expected_val(1) ),* ]) + } + + #[test] + fn dynamic() -> anyhow::Result<()> { + let store = get_store(); + let module = get_module(&store)?; + let instance = wasmer::Instance::new( + &module, + &wasmer::imports! { + "host" => { + "callback_fn" => wasmer::Function::new_dynamic(&store, &wasmer::FunctionType::new(vec![wasmer::ValType::I32], vec![ $( <$result_type>::expected_valtype() ),* ]), dynamic_callback_fn) + } } - } - )?; - let expected_value = vec![ $( <$result_type>::expected_val(1) ),* ].into_boxed_slice(); - assert_eq!(instance.exports.get_function("test_call")?.call(&[wasmer::Val::I32(1)])?, - expected_value); - assert_eq!(instance.exports.get_function("test_call_indirect")?.call(&[wasmer::Val::I32(1)])?, - expected_value); - Ok(()) - } + )?; + let expected_value = vec![ $( <$result_type>::expected_val(1) ),* ].into_boxed_slice(); + assert_eq!(instance.exports.get_function("test_call")?.call(&[wasmer::Val::I32(1)])?, + expected_value); + assert_eq!(instance.exports.get_function("test_call_indirect")?.call(&[wasmer::Val::I32(1)])?, + expected_value); + Ok(()) + } } } } wasmer_compilers! { -trait ExpectedExpr { - fn expected_value(n: i32) -> Self; - fn expected_val(n: i32) -> wasmer::Val; - fn expected_valtype() -> wasmer::ValType; -} -impl ExpectedExpr for i32 { - fn expected_value(n: i32) -> i32 { - n + 1 - } - fn expected_val(n: i32) -> wasmer::Val { - wasmer::Val::I32(Self::expected_value(n)) - } - fn expected_valtype() -> wasmer::ValType { - wasmer::ValType::I32 - } -} -impl ExpectedExpr for i64 { - fn expected_value(n: i32) -> i64 { - n as i64 + 2i64 - } - fn expected_val(n: i32) -> wasmer::Val { - wasmer::Val::I64(Self::expected_value(n)) + trait ExpectedExpr { + fn expected_value(n: i32) -> Self; + fn expected_val(n: i32) -> wasmer::Val; + fn expected_valtype() -> wasmer::ValType; } - fn expected_valtype() -> wasmer::ValType { - wasmer::ValType::I64 - } -} -impl ExpectedExpr for f32 { - fn expected_value(n: i32) -> f32 { - n as f32 * 0.1 - } - fn expected_val(n: i32) -> wasmer::Val { - wasmer::Val::F32(Self::expected_value(n)) - } - fn expected_valtype() -> wasmer::ValType { - wasmer::ValType::F32 + impl ExpectedExpr for i32 { + fn expected_value(n: i32) -> i32 { + n + 1 + } + fn expected_val(n: i32) -> wasmer::Val { + wasmer::Val::I32(Self::expected_value(n)) + } + fn expected_valtype() -> wasmer::ValType { + wasmer::ValType::I32 + } } -} -impl ExpectedExpr for f64 { - fn expected_value(n: i32) -> f64 { - n as f64 * 0.12 + impl ExpectedExpr for i64 { + fn expected_value(n: i32) -> i64 { + n as i64 + 2i64 + } + fn expected_val(n: i32) -> wasmer::Val { + wasmer::Val::I64(Self::expected_value(n)) + } + fn expected_valtype() -> wasmer::ValType { + wasmer::ValType::I64 + } } - fn expected_val(n: i32) -> wasmer::Val { - wasmer::Val::F64(Self::expected_value(n)) + impl ExpectedExpr for f32 { + fn expected_value(n: i32) -> f32 { + n as f32 * 0.1 + } + fn expected_val(n: i32) -> wasmer::Val { + wasmer::Val::F32(Self::expected_value(n)) + } + fn expected_valtype() -> wasmer::ValType { + wasmer::ValType::F32 + } } - fn expected_valtype() -> wasmer::ValType { - wasmer::ValType::F64 + impl ExpectedExpr for f64 { + fn expected_value(n: i32) -> f64 { + n as f64 * 0.12 + } + fn expected_val(n: i32) -> wasmer::Val { + wasmer::Val::F64(Self::expected_value(n)) + } + fn expected_valtype() -> wasmer::ValType { + wasmer::ValType::F64 + } } -} mvr_test!(test_mvr_i32_i32, i32, i32); -mvr_test!(test_mvr_i32_f32, i32, f32); -mvr_test!(test_mvr_f32_i32, f32, i32); -mvr_test!(test_mvr_f32_f32, f32, f32); - -mvr_test!(test_mvr_i64_i32, i64, i32); -mvr_test!(test_mvr_i64_f32, i64, f32); -mvr_test!(test_mvr_f64_i32, f64, i32); -mvr_test!(test_mvr_f64_f32, f64, f32); - -mvr_test!(test_mvr_i32_i64, i32, i64); -mvr_test!(test_mvr_f32_i64, f32, i64); -mvr_test!(test_mvr_i32_f64, i32, f64); -mvr_test!(test_mvr_f32_f64, f32, f64); - -mvr_test!(test_mvr_i32_i32_i32, i32, i32, i32); -mvr_test!(test_mvr_i32_i32_f32, i32, i32, f32); -mvr_test!(test_mvr_i32_f32_i32, i32, f32, i32); -mvr_test!(test_mvr_i32_f32_f32, i32, f32, f32); -mvr_test!(test_mvr_f32_i32_i32, f32, i32, i32); -mvr_test!(test_mvr_f32_i32_f32, f32, i32, f32); -mvr_test!(test_mvr_f32_f32_i32, f32, f32, i32); -mvr_test!(test_mvr_f32_f32_f32, f32, f32, f32); - -mvr_test!(test_mvr_i32_i32_i64, i32, i32, i64); -mvr_test!(test_mvr_i32_f32_i64, i32, f32, i64); -mvr_test!(test_mvr_f32_i32_i64, f32, i32, i64); -mvr_test!(test_mvr_f32_f32_i64, f32, f32, i64); -mvr_test!(test_mvr_i32_i32_f64, i32, i32, f64); -mvr_test!(test_mvr_i32_f32_f64, i32, f32, f64); -mvr_test!(test_mvr_f32_i32_f64, f32, i32, f64); -mvr_test!(test_mvr_f32_f32_f64, f32, f32, f64); - -mvr_test!(test_mvr_i32_i64_i32, i32, i64, i32); -mvr_test!(test_mvr_i32_i64_f32, i32, i64, f32); -mvr_test!(test_mvr_f32_i64_i32, f32, i64, i32); -mvr_test!(test_mvr_f32_i64_f32, f32, i64, f32); -mvr_test!(test_mvr_i32_f64_i32, i32, f64, i32); -mvr_test!(test_mvr_i32_f64_f32, i32, f64, f32); -mvr_test!(test_mvr_f32_f64_i32, f32, f64, i32); -mvr_test!(test_mvr_f32_f64_f32, f32, f64, f32); - -mvr_test!(test_mvr_i64_i32_i32, i64, i32, i32); -mvr_test!(test_mvr_i64_i32_f32, i64, i32, f32); -mvr_test!(test_mvr_i64_f32_i32, i64, f32, i32); -mvr_test!(test_mvr_i64_f32_f32, i64, f32, f32); -mvr_test!(test_mvr_f64_i32_i32, f64, i32, i32); -mvr_test!(test_mvr_f64_i32_f32, f64, i32, f32); -mvr_test!(test_mvr_f64_f32_i32, f64, f32, i32); -mvr_test!(test_mvr_f64_f32_f32, f64, f32, f32); - -mvr_test!(test_mvr_i32_i32_i32_i32, i32, i32, i32, i32); -mvr_test!(test_mvr_i32_i32_i32_f32, i32, i32, i32, f32); -mvr_test!(test_mvr_i32_i32_f32_i32, i32, i32, f32, i32); -mvr_test!(test_mvr_i32_i32_f32_f32, i32, i32, f32, f32); -mvr_test!(test_mvr_i32_f32_i32_i32, i32, f32, i32, i32); -mvr_test!(test_mvr_i32_f32_i32_f32, i32, f32, i32, f32); -mvr_test!(test_mvr_i32_f32_f32_i32, i32, f32, f32, i32); -mvr_test!(test_mvr_i32_f32_f32_f32, i32, f32, f32, f32); -mvr_test!(test_mvr_f32_i32_i32_i32, f32, i32, i32, i32); -mvr_test!(test_mvr_f32_i32_i32_f32, f32, i32, i32, f32); -mvr_test!(test_mvr_f32_i32_f32_i32, f32, i32, f32, i32); -mvr_test!(test_mvr_f32_i32_f32_f32, f32, i32, f32, f32); -mvr_test!(test_mvr_f32_f32_i32_i32, f32, f32, i32, i32); -mvr_test!(test_mvr_f32_f32_i32_f32, f32, f32, i32, f32); -mvr_test!(test_mvr_f32_f32_f32_i32, f32, f32, f32, i32); -mvr_test!(test_mvr_f32_f32_f32_f32, f32, f32, f32, f32); - -mvr_test!(test_mvr_i32_i32_i32_i32_i32, i32, i32, i32, i32, i32); + mvr_test!(test_mvr_i32_f32, i32, f32); + mvr_test!(test_mvr_f32_i32, f32, i32); + mvr_test!(test_mvr_f32_f32, f32, f32); + + mvr_test!(test_mvr_i64_i32, i64, i32); + mvr_test!(test_mvr_i64_f32, i64, f32); + mvr_test!(test_mvr_f64_i32, f64, i32); + mvr_test!(test_mvr_f64_f32, f64, f32); + + mvr_test!(test_mvr_i32_i64, i32, i64); + mvr_test!(test_mvr_f32_i64, f32, i64); + mvr_test!(test_mvr_i32_f64, i32, f64); + mvr_test!(test_mvr_f32_f64, f32, f64); + + mvr_test!(test_mvr_i32_i32_i32, i32, i32, i32); + mvr_test!(test_mvr_i32_i32_f32, i32, i32, f32); + mvr_test!(test_mvr_i32_f32_i32, i32, f32, i32); + mvr_test!(test_mvr_i32_f32_f32, i32, f32, f32); + mvr_test!(test_mvr_f32_i32_i32, f32, i32, i32); + mvr_test!(test_mvr_f32_i32_f32, f32, i32, f32); + mvr_test!(test_mvr_f32_f32_i32, f32, f32, i32); + mvr_test!(test_mvr_f32_f32_f32, f32, f32, f32); + + mvr_test!(test_mvr_i32_i32_i64, i32, i32, i64); + mvr_test!(test_mvr_i32_f32_i64, i32, f32, i64); + mvr_test!(test_mvr_f32_i32_i64, f32, i32, i64); + mvr_test!(test_mvr_f32_f32_i64, f32, f32, i64); + mvr_test!(test_mvr_i32_i32_f64, i32, i32, f64); + mvr_test!(test_mvr_i32_f32_f64, i32, f32, f64); + mvr_test!(test_mvr_f32_i32_f64, f32, i32, f64); + mvr_test!(test_mvr_f32_f32_f64, f32, f32, f64); + + mvr_test!(test_mvr_i32_i64_i32, i32, i64, i32); + mvr_test!(test_mvr_i32_i64_f32, i32, i64, f32); + mvr_test!(test_mvr_f32_i64_i32, f32, i64, i32); + mvr_test!(test_mvr_f32_i64_f32, f32, i64, f32); + mvr_test!(test_mvr_i32_f64_i32, i32, f64, i32); + mvr_test!(test_mvr_i32_f64_f32, i32, f64, f32); + mvr_test!(test_mvr_f32_f64_i32, f32, f64, i32); + mvr_test!(test_mvr_f32_f64_f32, f32, f64, f32); + + mvr_test!(test_mvr_i64_i32_i32, i64, i32, i32); + mvr_test!(test_mvr_i64_i32_f32, i64, i32, f32); + mvr_test!(test_mvr_i64_f32_i32, i64, f32, i32); + mvr_test!(test_mvr_i64_f32_f32, i64, f32, f32); + mvr_test!(test_mvr_f64_i32_i32, f64, i32, i32); + mvr_test!(test_mvr_f64_i32_f32, f64, i32, f32); + mvr_test!(test_mvr_f64_f32_i32, f64, f32, i32); + mvr_test!(test_mvr_f64_f32_f32, f64, f32, f32); + + mvr_test!(test_mvr_i32_i32_i32_i32, i32, i32, i32, i32); + mvr_test!(test_mvr_i32_i32_i32_f32, i32, i32, i32, f32); + mvr_test!(test_mvr_i32_i32_f32_i32, i32, i32, f32, i32); + mvr_test!(test_mvr_i32_i32_f32_f32, i32, i32, f32, f32); + mvr_test!(test_mvr_i32_f32_i32_i32, i32, f32, i32, i32); + mvr_test!(test_mvr_i32_f32_i32_f32, i32, f32, i32, f32); + mvr_test!(test_mvr_i32_f32_f32_i32, i32, f32, f32, i32); + mvr_test!(test_mvr_i32_f32_f32_f32, i32, f32, f32, f32); + mvr_test!(test_mvr_f32_i32_i32_i32, f32, i32, i32, i32); + mvr_test!(test_mvr_f32_i32_i32_f32, f32, i32, i32, f32); + mvr_test!(test_mvr_f32_i32_f32_i32, f32, i32, f32, i32); + mvr_test!(test_mvr_f32_i32_f32_f32, f32, i32, f32, f32); + mvr_test!(test_mvr_f32_f32_i32_i32, f32, f32, i32, i32); + mvr_test!(test_mvr_f32_f32_i32_f32, f32, f32, i32, f32); + mvr_test!(test_mvr_f32_f32_f32_i32, f32, f32, f32, i32); + mvr_test!(test_mvr_f32_f32_f32_f32, f32, f32, f32, f32); + + mvr_test!(test_mvr_i32_i32_i32_i32_i32, i32, i32, i32, i32, i32); } From 51007692d612b4aac3e2a557bc3d61a579ec1405 Mon Sep 17 00:00:00 2001 From: Nick Lewycky Date: Fri, 5 Jun 2020 12:05:37 -0700 Subject: [PATCH 35/44] Factor out value expensive to compute value. --- lib/compiler-llvm/src/trampoline/wasm.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/compiler-llvm/src/trampoline/wasm.rs b/lib/compiler-llvm/src/trampoline/wasm.rs index 3a578013be1..d631934218e 100644 --- a/lib/compiler-llvm/src/trampoline/wasm.rs +++ b/lib/compiler-llvm/src/trampoline/wasm.rs @@ -326,6 +326,7 @@ fn generate_dynamic_trampoline<'ctx>( ); // Copy params to 'values'. + let first_user_param = if is_sret(func_sig)? { 2 } else { 1 }; for i in 0..func_sig.params().len() { let ptr = unsafe { builder.build_in_bounds_gep( @@ -343,7 +344,7 @@ fn generate_dynamic_trampoline<'ctx>( builder.build_store( ptr, trampoline_func - .get_nth_param(i as u32 + if is_sret(func_sig)? { 2 } else { 1 }) + .get_nth_param(i as u32 + first_user_param) .unwrap(), ); } From b3617d308f54c869ce38009d2ba4d4ab1411c8e8 Mon Sep 17 00:00:00 2001 From: Nick Lewycky Date: Fri, 5 Jun 2020 13:57:36 -0700 Subject: [PATCH 36/44] Skip known-failing tests. --- Cargo.toml | 1 + tests/compilers/main.rs | 2 + tests/compilers/multi_value_imports.rs | 52 ++++++++++++++++++++++++++ 3 files changed, 55 insertions(+) diff --git a/Cargo.toml b/Cargo.toml index ea890e80965..df0d30a70b2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -48,6 +48,7 @@ distance = "0.4" # For the inspect subcommand bytesize = "1.0" cfg-if = "0.1" +lazy_static = "1.4" [workspace] members = [ diff --git a/tests/compilers/main.rs b/tests/compilers/main.rs index cd64133079f..cef5b241de9 100644 --- a/tests/compilers/main.rs +++ b/tests/compilers/main.rs @@ -7,3 +7,5 @@ mod macros; mod imports; mod multi_value_imports; mod wast; +#[macro_use] +extern crate lazy_static; diff --git a/tests/compilers/multi_value_imports.rs b/tests/compilers/multi_value_imports.rs index d95f62e6343..fa986db6153 100644 --- a/tests/compilers/multi_value_imports.rs +++ b/tests/compilers/multi_value_imports.rs @@ -2,6 +2,48 @@ //! This tests checks that the provided functions (both native and //! dynamic ones) work properly. +use std::collections::HashSet; + +// These tests are skipped because they are known failing. +lazy_static! { + static ref SKIP_TESTS: HashSet<&'static str> = [ + ("compilers::multi_value_imports::cranelift::test_mvr_f32_f32_f32::native"), + ("compilers::multi_value_imports::cranelift::test_mvr_f32_f32_f32_f32::native"), + ("compilers::multi_value_imports::cranelift::test_mvr_f32_f32_f32_i32::native"), + ("compilers::multi_value_imports::cranelift::test_mvr_f32_f32_f64::native"), + ("compilers::multi_value_imports::cranelift::test_mvr_f32_f32_i32_f32::native"), + ("compilers::multi_value_imports::cranelift::test_mvr_f32_f64_i32::native"), + ("compilers::multi_value_imports::cranelift::test_mvr_f32_i32::native"), + ("compilers::multi_value_imports::cranelift::test_mvr_f32_i32_f32::native"), + ("compilers::multi_value_imports::cranelift::test_mvr_f32_i32_f32_f32::native"), + ("compilers::multi_value_imports::cranelift::test_mvr_f32_i32_f32_i32::native"), + ("compilers::multi_value_imports::cranelift::test_mvr_f32_i32_f64::native"), + ("compilers::multi_value_imports::cranelift::test_mvr_f32_i32_i32::native"), + ("compilers::multi_value_imports::cranelift::test_mvr_f32_i32_i32_f32::native"), + ("compilers::multi_value_imports::cranelift::test_mvr_f32_i32_i32_i32::native"), + ("compilers::multi_value_imports::cranelift::test_mvr_f32_i32_i64::native"), + ("compilers::multi_value_imports::cranelift::test_mvr_f32_i64_f32::native"), + ("compilers::multi_value_imports::cranelift::test_mvr_f32_i64_i32::native"), + ("compilers::multi_value_imports::cranelift::test_mvr_f64_f32_f32::native"), + ("compilers::multi_value_imports::cranelift::test_mvr_f64_f32_i32::native"), + ("compilers::multi_value_imports::cranelift::test_mvr_i32_f32_f32_f32::native"), + ("compilers::multi_value_imports::cranelift::test_mvr_i32_f32_f32_i32::native"), + ("compilers::multi_value_imports::cranelift::test_mvr_i32_f32_f64::native"), + ("compilers::multi_value_imports::cranelift::test_mvr_i32_f64_f32::native"), + ("compilers::multi_value_imports::cranelift::test_mvr_i32_f64_i32::native"), + ("compilers::multi_value_imports::cranelift::test_mvr_i32_i32_f32_i32::native"), + ("compilers::multi_value_imports::cranelift::test_mvr_i32_i32_i32_i32::native"), + ("compilers::multi_value_imports::cranelift::test_mvr_i32_i32_i64::native"), + ("compilers::multi_value_imports::cranelift::test_mvr_i32_i64_f32::native"), + ("compilers::multi_value_imports::cranelift::test_mvr_i32_i64_i32::native"), + ("compilers::multi_value_imports::cranelift::test_mvr_i64_f32_i32::native"), + ("compilers::multi_value_imports::cranelift::test_mvr_i64_i32_i32::native"), + ] + .iter() + .copied() + .collect(); +} + macro_rules! mvr_test { ($test_name:ident, $( $result_type:ty ),* ) => { mod $test_name { @@ -35,6 +77,11 @@ macro_rules! mvr_test { #[test] fn native() -> anyhow::Result<()> { + if crate::multi_value_imports::SKIP_TESTS.contains(concat!(module_path!(), "::native")) { + println!("skipped"); + return Ok(()); + } + let store = get_store(); let module = get_module(&store)?; let instance = wasmer::Instance::new( @@ -60,6 +107,11 @@ macro_rules! mvr_test { #[test] fn dynamic() -> anyhow::Result<()> { + if crate::multi_value_imports::SKIP_TESTS.contains(concat!(module_path!(), "::dynamic")) { + println!("skipped"); + return Ok(()); + } + let store = get_store(); let module = get_module(&store)?; let instance = wasmer::Instance::new( From 1c3ea9f8676caf1fbc2c892c44c71fdb2ef83672 Mon Sep 17 00:00:00 2001 From: Nick Lewycky Date: Sat, 6 Jun 2020 22:39:52 -0700 Subject: [PATCH 37/44] Fix bug packing return values in dynamic function trampoline. --- lib/compiler-llvm/src/trampoline/wasm.rs | 23 ++++++++--------------- 1 file changed, 8 insertions(+), 15 deletions(-) diff --git a/lib/compiler-llvm/src/trampoline/wasm.rs b/lib/compiler-llvm/src/trampoline/wasm.rs index d631934218e..2de47e18e6a 100644 --- a/lib/compiler-llvm/src/trampoline/wasm.rs +++ b/lib/compiler-llvm/src/trampoline/wasm.rs @@ -50,7 +50,7 @@ impl FuncTrampoline { let (callee_ty, callee_attrs) = func_type_to_llvm(&self.ctx, &intrinsics, ty)?; let trampoline_ty = intrinsics.void_ty.fn_type( &[ - intrinsics.ctx_ptr_ty.as_basic_type_enum(), // callee_vmctx ptr + intrinsics.ctx_ptr_ty.as_basic_type_enum(), // vmctx ptr callee_ty .ptr_type(AddressSpace::Generic) .as_basic_type_enum(), // callee function address @@ -308,14 +308,6 @@ fn generate_dynamic_trampoline<'ctx>( let builder = context.create_builder(); builder.position_at_end(entry_block); - /* - // TODO: remove debugging - builder.build_call( - intrinsics.debug_trap, - &[], - ""); - */ - // Allocate stack space for the params and results. let values = builder.build_alloca( intrinsics.i128_ty.array_type(cmp::max( @@ -353,19 +345,17 @@ fn generate_dynamic_trampoline<'ctx>( .void_ty .fn_type( &[ - intrinsics.ctx_ptr_ty.as_basic_type_enum(), - intrinsics.i128_ptr_ty.as_basic_type_enum(), + intrinsics.ctx_ptr_ty.as_basic_type_enum(), // vmctx ptr + intrinsics.i128_ptr_ty.as_basic_type_enum(), // in/out values ptr ], false, ) - .ptr_type(AddressSpace::Generic) .ptr_type(AddressSpace::Generic); - let vmctx = get_vmctx_ptr_param(&trampoline_func); let callee = builder .build_load( builder - .build_bitcast(vmctx, callee_ty, "") + .build_bitcast(vmctx, callee_ty.ptr_type(AddressSpace::Generic), "") .into_pointer_value(), "", ) @@ -392,7 +382,10 @@ fn generate_dynamic_trampoline<'ctx>( let ptr = unsafe { builder.build_gep( values, - &[intrinsics.i32_ty.const_int(idx.try_into().unwrap(), false)], + &[ + intrinsics.i32_ty.const_zero(), + intrinsics.i32_ty.const_int(idx.try_into().unwrap(), false), + ], "", ) }; From 4cdcc0d1914cee9cf0a42f932ac4ec3f9932750e Mon Sep 17 00:00:00 2001 From: Nick Lewycky Date: Sun, 7 Jun 2020 09:45:49 -0700 Subject: [PATCH 38/44] We're only using lazy_static! in a test, move it to dev-dependencies. --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index df0d30a70b2..c89eb11f223 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -48,7 +48,6 @@ distance = "0.4" # For the inspect subcommand bytesize = "1.0" cfg-if = "0.1" -lazy_static = "1.4" [workspace] members = [ @@ -64,6 +63,7 @@ rustc_version = "0.2" [dev-dependencies] anyhow = "1.0" blake3 = "0.3" +lazy_static = "1.4" test-utils = { path = "tests/lib/test-utils" } wasmer-engine-dummy = { path = "tests/lib/engine-dummy" } From 28f5aed6343a347e39cfd486d7ea38d82886dbbb Mon Sep 17 00:00:00 2001 From: Nick Lewycky Date: Sun, 7 Jun 2020 09:46:07 -0700 Subject: [PATCH 39/44] Update list of failing tests: * include singlepass because multi-value isn't implemented yet. * add some tests that are failing on cranelift but weren't included. * add a comment on why the cranelift tests are failing * hard-code less of the skipped test name --- tests/compilers/multi_value_imports.rs | 199 +++++++++++++++++++++---- 1 file changed, 168 insertions(+), 31 deletions(-) diff --git a/tests/compilers/multi_value_imports.rs b/tests/compilers/multi_value_imports.rs index fa986db6153..85c7c5c1461 100644 --- a/tests/compilers/multi_value_imports.rs +++ b/tests/compilers/multi_value_imports.rs @@ -7,37 +7,173 @@ use std::collections::HashSet; // These tests are skipped because they are known failing. lazy_static! { static ref SKIP_TESTS: HashSet<&'static str> = [ - ("compilers::multi_value_imports::cranelift::test_mvr_f32_f32_f32::native"), - ("compilers::multi_value_imports::cranelift::test_mvr_f32_f32_f32_f32::native"), - ("compilers::multi_value_imports::cranelift::test_mvr_f32_f32_f32_i32::native"), - ("compilers::multi_value_imports::cranelift::test_mvr_f32_f32_f64::native"), - ("compilers::multi_value_imports::cranelift::test_mvr_f32_f32_i32_f32::native"), - ("compilers::multi_value_imports::cranelift::test_mvr_f32_f64_i32::native"), - ("compilers::multi_value_imports::cranelift::test_mvr_f32_i32::native"), - ("compilers::multi_value_imports::cranelift::test_mvr_f32_i32_f32::native"), - ("compilers::multi_value_imports::cranelift::test_mvr_f32_i32_f32_f32::native"), - ("compilers::multi_value_imports::cranelift::test_mvr_f32_i32_f32_i32::native"), - ("compilers::multi_value_imports::cranelift::test_mvr_f32_i32_f64::native"), - ("compilers::multi_value_imports::cranelift::test_mvr_f32_i32_i32::native"), - ("compilers::multi_value_imports::cranelift::test_mvr_f32_i32_i32_f32::native"), - ("compilers::multi_value_imports::cranelift::test_mvr_f32_i32_i32_i32::native"), - ("compilers::multi_value_imports::cranelift::test_mvr_f32_i32_i64::native"), - ("compilers::multi_value_imports::cranelift::test_mvr_f32_i64_f32::native"), - ("compilers::multi_value_imports::cranelift::test_mvr_f32_i64_i32::native"), - ("compilers::multi_value_imports::cranelift::test_mvr_f64_f32_f32::native"), - ("compilers::multi_value_imports::cranelift::test_mvr_f64_f32_i32::native"), - ("compilers::multi_value_imports::cranelift::test_mvr_i32_f32_f32_f32::native"), - ("compilers::multi_value_imports::cranelift::test_mvr_i32_f32_f32_i32::native"), - ("compilers::multi_value_imports::cranelift::test_mvr_i32_f32_f64::native"), - ("compilers::multi_value_imports::cranelift::test_mvr_i32_f64_f32::native"), - ("compilers::multi_value_imports::cranelift::test_mvr_i32_f64_i32::native"), - ("compilers::multi_value_imports::cranelift::test_mvr_i32_i32_f32_i32::native"), - ("compilers::multi_value_imports::cranelift::test_mvr_i32_i32_i32_i32::native"), - ("compilers::multi_value_imports::cranelift::test_mvr_i32_i32_i64::native"), - ("compilers::multi_value_imports::cranelift::test_mvr_i32_i64_f32::native"), - ("compilers::multi_value_imports::cranelift::test_mvr_i32_i64_i32::native"), - ("compilers::multi_value_imports::cranelift::test_mvr_i64_f32_i32::native"), - ("compilers::multi_value_imports::cranelift::test_mvr_i64_i32_i32::native"), + // https://github.com/bytecodealliance/wasmtime/issues/1178 + (concat!(module_path!(), "::cranelift::test_mvr_f32_f32_f32::native")), + (concat!(module_path!(), "::cranelift::test_mvr_f32_f32_f32_f32::native")), + (concat!(module_path!(), "::cranelift::test_mvr_f32_f32_f32_i32::native")), + (concat!(module_path!(), "::cranelift::test_mvr_f32_f32_f64::native")), + (concat!(module_path!(), "::cranelift::test_mvr_f32_f32_i32::native")), + (concat!(module_path!(), "::cranelift::test_mvr_f32_f32_i32_f32::native")), + (concat!(module_path!(), "::cranelift::test_mvr_f32_f32_i32_i32::native")), + (concat!(module_path!(), "::cranelift::test_mvr_f32_f32_i64::native")), + (concat!(module_path!(), "::cranelift::test_mvr_f32_f64_i32::native")), + (concat!(module_path!(), "::cranelift::test_mvr_f32_i32::native")), + (concat!(module_path!(), "::cranelift::test_mvr_f32_i32_f32::native")), + (concat!(module_path!(), "::cranelift::test_mvr_f32_i32_f32_f32::native")), + (concat!(module_path!(), "::cranelift::test_mvr_f32_i32_f32_i32::native")), + (concat!(module_path!(), "::cranelift::test_mvr_f32_i32_f64::native")), + (concat!(module_path!(), "::cranelift::test_mvr_f32_i32_i32::native")), + (concat!(module_path!(), "::cranelift::test_mvr_f32_i32_i32_f32::native")), + (concat!(module_path!(), "::cranelift::test_mvr_f32_i32_i32_i32::native")), + (concat!(module_path!(), "::cranelift::test_mvr_f32_i32_i64::native")), + (concat!(module_path!(), "::cranelift::test_mvr_f32_i64_f32::native")), + (concat!(module_path!(), "::cranelift::test_mvr_f32_i64_i32::native")), + (concat!(module_path!(), "::cranelift::test_mvr_f64_f32_f32::native")), + (concat!(module_path!(), "::cranelift::test_mvr_f64_f32_i32::native")), + (concat!(module_path!(), "::cranelift::test_mvr_f64_i32_f32::native")), + (concat!(module_path!(), "::cranelift::test_mvr_f64_i32_i32::native")), + (concat!(module_path!(), "::cranelift::test_mvr_i32_f32_f32_f32::native")), + (concat!(module_path!(), "::cranelift::test_mvr_i32_f32_f32_i32::native")), + (concat!(module_path!(), "::cranelift::test_mvr_i32_f32_f64::native")), + (concat!(module_path!(), "::cranelift::test_mvr_i32_f64_f32::native")), + (concat!(module_path!(), "::cranelift::test_mvr_i32_f64_i32::native")), + (concat!(module_path!(), "::cranelift::test_mvr_i32_i32::native")), + (concat!(module_path!(), "::cranelift::test_mvr_i32_i32_f32::native")), + (concat!(module_path!(), "::cranelift::test_mvr_i32_i32_f32_f32::native")), + (concat!(module_path!(), "::cranelift::test_mvr_i32_i32_f32_i32::native")), + (concat!(module_path!(), "::cranelift::test_mvr_i32_i32_f64::native")), + (concat!(module_path!(), "::cranelift::test_mvr_i32_i32_i32::native")), + (concat!(module_path!(), "::cranelift::test_mvr_i32_i32_i32_f32::native")), + (concat!(module_path!(), "::cranelift::test_mvr_i32_i32_i32_i32::native")), + (concat!(module_path!(), "::cranelift::test_mvr_i32_i32_i64::native")), + (concat!(module_path!(), "::cranelift::test_mvr_i32_i64_f32::native")), + (concat!(module_path!(), "::cranelift::test_mvr_i32_i64_i32::native")), + (concat!(module_path!(), "::cranelift::test_mvr_i64_f32_i32::native")), + (concat!(module_path!(), "::cranelift::test_mvr_i64_i32_i32::native")), + + // Multi-value is not implemented in singlepass yet. + (concat!(module_path!(), "::singlepass::test_mvr_f32_f32::dynamic")), + (concat!(module_path!(), "::singlepass::test_mvr_f32_f32::native")), + (concat!(module_path!(), "::singlepass::test_mvr_f32_f32_f32::dynamic")), + (concat!(module_path!(), "::singlepass::test_mvr_f32_f32_f32::native")), + (concat!(module_path!(), "::singlepass::test_mvr_f32_f32_f32_f32::dynamic")), + (concat!(module_path!(), "::singlepass::test_mvr_f32_f32_f32_f32::native")), + (concat!(module_path!(), "::singlepass::test_mvr_f32_f32_f32_i32::dynamic")), + (concat!(module_path!(), "::singlepass::test_mvr_f32_f32_f32_i32::native")), + (concat!(module_path!(), "::singlepass::test_mvr_f32_f32_f64::dynamic")), + (concat!(module_path!(), "::singlepass::test_mvr_f32_f32_f64::native")), + (concat!(module_path!(), "::singlepass::test_mvr_f32_f32_i32::dynamic")), + (concat!(module_path!(), "::singlepass::test_mvr_f32_f32_i32::native")), + (concat!(module_path!(), "::singlepass::test_mvr_f32_f32_i32_f32::dynamic")), + (concat!(module_path!(), "::singlepass::test_mvr_f32_f32_i32_f32::native")), + (concat!(module_path!(), "::singlepass::test_mvr_f32_f32_i32_i32::dynamic")), + (concat!(module_path!(), "::singlepass::test_mvr_f32_f32_i32_i32::native")), + (concat!(module_path!(), "::singlepass::test_mvr_f32_f32_i64::dynamic")), + (concat!(module_path!(), "::singlepass::test_mvr_f32_f32_i64::native")), + (concat!(module_path!(), "::singlepass::test_mvr_f32_f64::dynamic")), + (concat!(module_path!(), "::singlepass::test_mvr_f32_f64::native")), + (concat!(module_path!(), "::singlepass::test_mvr_f32_f64_f32::dynamic")), + (concat!(module_path!(), "::singlepass::test_mvr_f32_f64_f32::native")), + (concat!(module_path!(), "::singlepass::test_mvr_f32_f64_i32::dynamic")), + (concat!(module_path!(), "::singlepass::test_mvr_f32_f64_i32::native")), + (concat!(module_path!(), "::singlepass::test_mvr_f32_i32::dynamic")), + (concat!(module_path!(), "::singlepass::test_mvr_f32_i32::native")), + (concat!(module_path!(), "::singlepass::test_mvr_f32_i32_f32::dynamic")), + (concat!(module_path!(), "::singlepass::test_mvr_f32_i32_f32::native")), + (concat!(module_path!(), "::singlepass::test_mvr_f32_i32_f32_f32::dynamic")), + (concat!(module_path!(), "::singlepass::test_mvr_f32_i32_f32_f32::native")), + (concat!(module_path!(), "::singlepass::test_mvr_f32_i32_f32_i32::dynamic")), + (concat!(module_path!(), "::singlepass::test_mvr_f32_i32_f32_i32::native")), + (concat!(module_path!(), "::singlepass::test_mvr_f32_i32_f64::dynamic")), + (concat!(module_path!(), "::singlepass::test_mvr_f32_i32_f64::native")), + (concat!(module_path!(), "::singlepass::test_mvr_f32_i32_i32::dynamic")), + (concat!(module_path!(), "::singlepass::test_mvr_f32_i32_i32::native")), + (concat!(module_path!(), "::singlepass::test_mvr_f32_i32_i32_f32::dynamic")), + (concat!(module_path!(), "::singlepass::test_mvr_f32_i32_i32_f32::native")), + (concat!(module_path!(), "::singlepass::test_mvr_f32_i32_i32_i32::dynamic")), + (concat!(module_path!(), "::singlepass::test_mvr_f32_i32_i32_i32::native")), + (concat!(module_path!(), "::singlepass::test_mvr_f32_i32_i64::dynamic")), + (concat!(module_path!(), "::singlepass::test_mvr_f32_i32_i64::native")), + (concat!(module_path!(), "::singlepass::test_mvr_f32_i64::dynamic")), + (concat!(module_path!(), "::singlepass::test_mvr_f32_i64::native")), + (concat!(module_path!(), "::singlepass::test_mvr_f32_i64_f32::dynamic")), + (concat!(module_path!(), "::singlepass::test_mvr_f32_i64_f32::native")), + (concat!(module_path!(), "::singlepass::test_mvr_f32_i64_i32::dynamic")), + (concat!(module_path!(), "::singlepass::test_mvr_f32_i64_i32::native")), + (concat!(module_path!(), "::singlepass::test_mvr_f64_f32::dynamic")), + (concat!(module_path!(), "::singlepass::test_mvr_f64_f32::native")), + (concat!(module_path!(), "::singlepass::test_mvr_f64_f32_f32::dynamic")), + (concat!(module_path!(), "::singlepass::test_mvr_f64_f32_f32::native")), + (concat!(module_path!(), "::singlepass::test_mvr_f64_f32_i32::dynamic")), + (concat!(module_path!(), "::singlepass::test_mvr_f64_f32_i32::native")), + (concat!(module_path!(), "::singlepass::test_mvr_f64_i32::dynamic")), + (concat!(module_path!(), "::singlepass::test_mvr_f64_i32::native")), + (concat!(module_path!(), "::singlepass::test_mvr_f64_i32_f32::dynamic")), + (concat!(module_path!(), "::singlepass::test_mvr_f64_i32_f32::native")), + (concat!(module_path!(), "::singlepass::test_mvr_f64_i32_i32::dynamic")), + (concat!(module_path!(), "::singlepass::test_mvr_f64_i32_i32::native")), + (concat!(module_path!(), "::singlepass::test_mvr_i32_f32::dynamic")), + (concat!(module_path!(), "::singlepass::test_mvr_i32_f32::native")), + (concat!(module_path!(), "::singlepass::test_mvr_i32_f32_f32::dynamic")), + (concat!(module_path!(), "::singlepass::test_mvr_i32_f32_f32::native")), + (concat!(module_path!(), "::singlepass::test_mvr_i32_f32_f32_f32::dynamic")), + (concat!(module_path!(), "::singlepass::test_mvr_i32_f32_f32_f32::native")), + (concat!(module_path!(), "::singlepass::test_mvr_i32_f32_f32_i32::dynamic")), + (concat!(module_path!(), "::singlepass::test_mvr_i32_f32_f32_i32::native")), + (concat!(module_path!(), "::singlepass::test_mvr_i32_f32_f64::dynamic")), + (concat!(module_path!(), "::singlepass::test_mvr_i32_f32_f64::native")), + (concat!(module_path!(), "::singlepass::test_mvr_i32_f32_i32::dynamic")), + (concat!(module_path!(), "::singlepass::test_mvr_i32_f32_i32::native")), + (concat!(module_path!(), "::singlepass::test_mvr_i32_f32_i32_f32::dynamic")), + (concat!(module_path!(), "::singlepass::test_mvr_i32_f32_i32_f32::native")), + (concat!(module_path!(), "::singlepass::test_mvr_i32_f32_i32_i32::dynamic")), + (concat!(module_path!(), "::singlepass::test_mvr_i32_f32_i32_i32::native")), + (concat!(module_path!(), "::singlepass::test_mvr_i32_f32_i64::dynamic")), + (concat!(module_path!(), "::singlepass::test_mvr_i32_f32_i64::native")), + (concat!(module_path!(), "::singlepass::test_mvr_i32_f64::dynamic")), + (concat!(module_path!(), "::singlepass::test_mvr_i32_f64::native")), + (concat!(module_path!(), "::singlepass::test_mvr_i32_f64_f32::dynamic")), + (concat!(module_path!(), "::singlepass::test_mvr_i32_f64_f32::native")), + (concat!(module_path!(), "::singlepass::test_mvr_i32_f64_i32::dynamic")), + (concat!(module_path!(), "::singlepass::test_mvr_i32_f64_i32::native")), + (concat!(module_path!(), "::singlepass::test_mvr_i32_i32::dynamic")), + (concat!(module_path!(), "::singlepass::test_mvr_i32_i32::native")), + (concat!(module_path!(), "::singlepass::test_mvr_i32_i32_f32::dynamic")), + (concat!(module_path!(), "::singlepass::test_mvr_i32_i32_f32::native")), + (concat!(module_path!(), "::singlepass::test_mvr_i32_i32_f32_f32::dynamic")), + (concat!(module_path!(), "::singlepass::test_mvr_i32_i32_f32_f32::native")), + (concat!(module_path!(), "::singlepass::test_mvr_i32_i32_f32_i32::dynamic")), + (concat!(module_path!(), "::singlepass::test_mvr_i32_i32_f32_i32::native")), + (concat!(module_path!(), "::singlepass::test_mvr_i32_i32_f64::dynamic")), + (concat!(module_path!(), "::singlepass::test_mvr_i32_i32_f64::native")), + (concat!(module_path!(), "::singlepass::test_mvr_i32_i32_i32::dynamic")), + (concat!(module_path!(), "::singlepass::test_mvr_i32_i32_i32::native")), + (concat!(module_path!(), "::singlepass::test_mvr_i32_i32_i32_f32::dynamic")), + (concat!(module_path!(), "::singlepass::test_mvr_i32_i32_i32_f32::native")), + (concat!(module_path!(), "::singlepass::test_mvr_i32_i32_i32_i32::dynamic")), + (concat!(module_path!(), "::singlepass::test_mvr_i32_i32_i32_i32::native")), + (concat!(module_path!(), "::singlepass::test_mvr_i32_i32_i32_i32_i32::dynamic")), + (concat!(module_path!(), "::singlepass::test_mvr_i32_i32_i32_i32_i32::native")), + (concat!(module_path!(), "::singlepass::test_mvr_i32_i32_i64::dynamic")), + (concat!(module_path!(), "::singlepass::test_mvr_i32_i32_i64::native")), + (concat!(module_path!(), "::singlepass::test_mvr_i32_i64::dynamic")), + (concat!(module_path!(), "::singlepass::test_mvr_i32_i64::native")), + (concat!(module_path!(), "::singlepass::test_mvr_i32_i64_f32::dynamic")), + (concat!(module_path!(), "::singlepass::test_mvr_i32_i64_f32::native")), + (concat!(module_path!(), "::singlepass::test_mvr_i32_i64_i32::dynamic")), + (concat!(module_path!(), "::singlepass::test_mvr_i32_i64_i32::native")), + (concat!(module_path!(), "::singlepass::test_mvr_i64_f32::dynamic")), + (concat!(module_path!(), "::singlepass::test_mvr_i64_f32::native")), + (concat!(module_path!(), "::singlepass::test_mvr_i64_f32_f32::dynamic")), + (concat!(module_path!(), "::singlepass::test_mvr_i64_f32_f32::native")), + (concat!(module_path!(), "::singlepass::test_mvr_i64_f32_i32::dynamic")), + (concat!(module_path!(), "::singlepass::test_mvr_i64_f32_i32::native")), + (concat!(module_path!(), "::singlepass::test_mvr_i64_i32::dynamic")), + (concat!(module_path!(), "::singlepass::test_mvr_i64_i32::native")), + (concat!(module_path!(), "::singlepass::test_mvr_i64_i32_f32::dynamic")), + (concat!(module_path!(), "::singlepass::test_mvr_i64_i32_f32::native")), + (concat!(module_path!(), "::singlepass::test_mvr_i64_i32_i32::dynamic")), + (concat!(module_path!(), "::singlepass::test_mvr_i64_i32_i32::native")), ] .iter() .copied() @@ -77,6 +213,7 @@ macro_rules! mvr_test { #[test] fn native() -> anyhow::Result<()> { + dbg!(concat!(module_path!(), "::native")); if crate::multi_value_imports::SKIP_TESTS.contains(concat!(module_path!(), "::native")) { println!("skipped"); return Ok(()); From 94c546d8b96bb9c3761a5c9188f89340f88897da Mon Sep 17 00:00:00 2001 From: Nick Lewycky Date: Sun, 7 Jun 2020 10:00:37 -0700 Subject: [PATCH 40/44] These two cranelift tests also fail on Windows. --- tests/compilers/multi_value_imports.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/compilers/multi_value_imports.rs b/tests/compilers/multi_value_imports.rs index 85c7c5c1461..559a3a519c5 100644 --- a/tests/compilers/multi_value_imports.rs +++ b/tests/compilers/multi_value_imports.rs @@ -8,6 +8,7 @@ use std::collections::HashSet; lazy_static! { static ref SKIP_TESTS: HashSet<&'static str> = [ // https://github.com/bytecodealliance/wasmtime/issues/1178 + (concat!(module_path!(), "::cranelift::test_mvr_f32_f32::native")), (concat!(module_path!(), "::cranelift::test_mvr_f32_f32_f32::native")), (concat!(module_path!(), "::cranelift::test_mvr_f32_f32_f32_f32::native")), (concat!(module_path!(), "::cranelift::test_mvr_f32_f32_f32_i32::native")), @@ -32,6 +33,7 @@ lazy_static! { (concat!(module_path!(), "::cranelift::test_mvr_f64_f32_i32::native")), (concat!(module_path!(), "::cranelift::test_mvr_f64_i32_f32::native")), (concat!(module_path!(), "::cranelift::test_mvr_f64_i32_i32::native")), + (concat!(module_path!(), "::cranelift::test_mvr_i32_f32::native")), (concat!(module_path!(), "::cranelift::test_mvr_i32_f32_f32_f32::native")), (concat!(module_path!(), "::cranelift::test_mvr_i32_f32_f32_i32::native")), (concat!(module_path!(), "::cranelift::test_mvr_i32_f32_f64::native")), From dc5c6dd10aebcb68160a13c8dfc31f23e6e1f14d Mon Sep 17 00:00:00 2001 From: Nick Lewycky Date: Mon, 8 Jun 2020 21:58:33 -0700 Subject: [PATCH 41/44] Always put allocas at the beginning of the entry block. Fixes a bug where we allocated stck space for struct return in every call of a function in a loop. --- lib/compiler-llvm/src/translator/code.rs | 26 ++++++++---- tests/wast/wasmer/README.md | 5 +++ tests/wast/wasmer/stack-overflow-sret.wast | 47 ++++++++++++++++++++++ 3 files changed, 70 insertions(+), 8 deletions(-) create mode 100644 tests/wast/wasmer/stack-overflow-sret.wast diff --git a/lib/compiler-llvm/src/translator/code.rs b/lib/compiler-llvm/src/translator/code.rs index c62b1a83156..ff1d0efbf26 100644 --- a/lib/compiler-llvm/src/translator/code.rs +++ b/lib/compiler-llvm/src/translator/code.rs @@ -110,10 +110,12 @@ impl FuncTranslator { let entry = self.ctx.append_basic_block(func, "entry"); let start_of_code = self.ctx.append_basic_block(func, "start_of_code"); let return_ = self.ctx.append_basic_block(func, "return"); + let alloca_builder = self.ctx.create_builder(); let cache_builder = self.ctx.create_builder(); let builder = self.ctx.create_builder(); cache_builder.position_at_end(entry); let br = cache_builder.build_unconditional_branch(start_of_code); + alloca_builder.position_before(&br); cache_builder.position_before(&br); builder.position_at_end(start_of_code); @@ -137,14 +139,23 @@ impl FuncTranslator { } else { 1 }; + let mut is_first_alloca = true; + let mut insert_alloca = |ty, name| { + let alloca = alloca_builder.build_alloca(ty, name); + if is_first_alloca { + alloca_builder.position_at(entry, &alloca.as_instruction_value().unwrap()); + is_first_alloca = false; + } + alloca + }; + for idx in 0..wasm_fn_type.params().len() { let ty = wasm_fn_type.params()[idx]; let ty = type_to_llvm(&intrinsics, ty)?; let value = func .get_nth_param((idx as u32).checked_add(first_param).unwrap()) .unwrap(); - // TODO: don't interleave allocas and stores. - let alloca = cache_builder.build_alloca(ty, "param"); + let alloca = insert_alloca(ty, "param"); cache_builder.build_store(alloca, value); params.push(alloca); } @@ -158,9 +169,8 @@ impl FuncTranslator { .map_err(to_wasm_error)?; let ty = wptype_to_type(ty).map_err(to_compile_error)?; let ty = type_to_llvm(&intrinsics, ty)?; - // TODO: don't interleave allocas and stores. for _ in 0..count { - let alloca = cache_builder.build_alloca(ty, "local"); + let alloca = insert_alloca(ty, "local"); cache_builder.build_store(alloca, const_zero(ty)); locals.push(alloca); } @@ -172,6 +182,7 @@ impl FuncTranslator { let mut fcg = LLVMFunctionCodeGenerator { context: &self.ctx, builder, + alloca_builder, intrinsics: &intrinsics, state, function: func, @@ -1237,6 +1248,7 @@ fn finalize_opcode_stack_map<'ctx>( pub struct LLVMFunctionCodeGenerator<'ctx, 'a> { context: &'ctx Context, builder: Builder<'ctx>, + alloca_builder: Builder<'ctx>, intrinsics: &'a Intrinsics<'ctx>, state: State<'ctx>, function: FunctionValue<'ctx>, @@ -2067,8 +2079,7 @@ impl<'ctx, 'a> LLVMFunctionCodeGenerator<'ctx, 'a> { }); let params = abi::args_to_call( - // TODO: should be an alloca_builder. - &self.builder, + &self.alloca_builder, func_type, callee_vmctx.into_pointer_value(), &func.get_type().get_element_type().into_function_type(), @@ -2311,8 +2322,7 @@ impl<'ctx, 'a> LLVMFunctionCodeGenerator<'ctx, 'a> { }); let params = abi::args_to_call( - // TODO: should be an alloca_builder. - &self.builder, + &self.alloca_builder, func_type, ctx_ptr.into_pointer_value(), &llvm_func_type, diff --git a/tests/wast/wasmer/README.md b/tests/wast/wasmer/README.md index 83998bc0c25..976146c247b 100644 --- a/tests/wast/wasmer/README.md +++ b/tests/wast/wasmer/README.md @@ -23,3 +23,8 @@ This is a test assuring functions that trap can be called multiple times. ## Fac: `fac.wast` This is a simple factorial program. + +## Check that struct-return on the stack doesn't overflow: `stack-overflow-sret.wast` + +Stack space for a structure returning function call should be allocated once up +front, not once in each call. diff --git a/tests/wast/wasmer/stack-overflow-sret.wast b/tests/wast/wasmer/stack-overflow-sret.wast new file mode 100644 index 00000000000..dc75d77eae3 --- /dev/null +++ b/tests/wast/wasmer/stack-overflow-sret.wast @@ -0,0 +1,47 @@ +(module + (func $sret + (result i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 + i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 + i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 + i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64) + i64.const 0 i64.const 0 i64.const 0 i64.const 0 + i64.const 0 i64.const 0 i64.const 0 i64.const 0 + i64.const 0 i64.const 0 i64.const 0 i64.const 0 + i64.const 0 i64.const 0 i64.const 0 i64.const 0 + + i64.const 0 i64.const 0 i64.const 0 i64.const 0 + i64.const 0 i64.const 0 i64.const 0 i64.const 0 + i64.const 0 i64.const 0 i64.const 0 i64.const 0 + i64.const 0 i64.const 0 i64.const 0 i64.const 0 + + i64.const 0 i64.const 0 i64.const 0 i64.const 0 + i64.const 0 i64.const 0 i64.const 0 i64.const 0 + i64.const 0 i64.const 0 i64.const 0 i64.const 0 + i64.const 0 i64.const 0 i64.const 0 i64.const 0 + + i64.const 0 i64.const 0 i64.const 0 i64.const 0 + i64.const 0 i64.const 0 i64.const 0 i64.const 0 + i64.const 0 i64.const 0 i64.const 0 i64.const 0 + i64.const 0 i64.const 0 i64.const 0 i64.const 0 + ) + + (func (export "long-loop") + (local i32) + i32.const 1000000 + local.set 0 + (loop + call $sret + drop drop drop drop drop drop drop drop drop drop drop drop drop drop drop drop + drop drop drop drop drop drop drop drop drop drop drop drop drop drop drop drop + drop drop drop drop drop drop drop drop drop drop drop drop drop drop drop drop + drop drop drop drop drop drop drop drop drop drop drop drop drop drop drop drop + local.get 0 + i32.const -1 + i32.add + local.tee 0 + br_if 0 + ) + ) +) + +(assert_return (invoke "long-loop")) From cfbddeec03e3b4a6b053b896471205a1348bbefc Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Tue, 9 Jun 2020 12:03:51 +0200 Subject: [PATCH 42/44] chore(runtime) Move `TableElements`, `TableStyle` and `TablePlan` to the `table` module. --- lib/runtime/src/export.rs | 4 ++-- lib/runtime/src/lib.rs | 7 ++----- lib/runtime/src/module.rs | 31 +------------------------------ lib/runtime/src/table.rs | 34 ++++++++++++++++++++++++++++++++-- 4 files changed, 37 insertions(+), 39 deletions(-) diff --git a/lib/runtime/src/export.rs b/lib/runtime/src/export.rs index a278fe6767c..64f017f4a02 100644 --- a/lib/runtime/src/export.rs +++ b/lib/runtime/src/export.rs @@ -1,6 +1,6 @@ use crate::memory::LinearMemory; -use crate::module::{MemoryPlan, TablePlan}; -use crate::table::Table; +use crate::module::MemoryPlan; +use crate::table::{Table, TablePlan}; use crate::vmcontext::{ VMContext, VMFunctionBody, VMFunctionKind, VMGlobalDefinition, VMMemoryDefinition, VMTableDefinition, diff --git a/lib/runtime/src/lib.rs b/lib/runtime/src/lib.rs index 254ab8fe545..1818622b56d 100644 --- a/lib/runtime/src/lib.rs +++ b/lib/runtime/src/lib.rs @@ -41,13 +41,10 @@ pub use crate::imports::Imports; pub use crate::instance::InstanceHandle; pub use crate::memory::{LinearMemory, MemoryError}; pub use crate::mmap::Mmap; -pub use crate::module::{ - ExportsIterator, ImportsIterator, MemoryPlan, MemoryStyle, ModuleInfo, TableElements, - TablePlan, TableStyle, -}; +pub use crate::module::{ExportsIterator, ImportsIterator, MemoryPlan, MemoryStyle, ModuleInfo}; pub use crate::probestack::PROBESTACK; pub use crate::sig_registry::SignatureRegistry; -pub use crate::table::Table; +pub use crate::table::{Table, TableElements, TablePlan, TableStyle}; pub use crate::trap::*; pub use crate::vmcontext::{ VMBuiltinFunctionIndex, VMCallerCheckedAnyfunc, VMContext, VMDynamicFunctionImportContext, diff --git a/lib/runtime/src/module.rs b/lib/runtime/src/module.rs index e2b028a27bb..11687492bb0 100644 --- a/lib/runtime/src/module.rs +++ b/lib/runtime/src/module.rs @@ -1,6 +1,7 @@ //! Data structure for representing WebAssembly modules //! in a [`Module`]. +use crate::table::TableElements; use indexmap::IndexMap; use serde::{Deserialize, Serialize}; use std::collections::HashMap; @@ -16,19 +17,6 @@ use wasm_common::{ SignatureIndex, TableIndex, TableType, }; -/// A WebAssembly table initializer. -#[derive(Clone, Debug, Hash, Serialize, Deserialize)] -pub struct TableElements { - /// The index of a table to initialize. - pub table_index: TableIndex, - /// Optionally, a global variable giving a base index. - pub base: Option, - /// The offset to add to the base. - pub offset: usize, - /// The values to write into the table elements. - pub elements: Box<[FunctionIndex]>, -} - /// Implementation styles for WebAssembly linear memory. #[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)] pub enum MemoryStyle { @@ -53,23 +41,6 @@ pub struct MemoryPlan { pub offset_guard_size: u64, } -/// Implementation styles for WebAssembly tables. -#[derive(Debug, Clone, Hash, Serialize, Deserialize)] -pub enum TableStyle { - /// Signatures are stored in the table and checked in the caller. - CallerChecksSignature, -} - -/// A WebAssembly table description along with our chosen style for -/// implementing it. -#[derive(Debug, Clone, Hash, Serialize, Deserialize)] -pub struct TablePlan { - /// The WebAssembly table description. - pub table: TableType, - /// Our chosen implementation style. - pub style: TableStyle, -} - #[derive(Debug)] pub struct ModuleId { id: usize, diff --git a/lib/runtime/src/table.rs b/lib/runtime/src/table.rs index ff9718905dc..9c2b4c663ed 100644 --- a/lib/runtime/src/table.rs +++ b/lib/runtime/src/table.rs @@ -2,12 +2,42 @@ //! //! `Table` is to WebAssembly tables what `LinearMemory` is to WebAssembly linear memories. -use crate::module::{TablePlan, TableStyle}; use crate::trap::{Trap, TrapCode}; use crate::vmcontext::{VMCallerCheckedAnyfunc, VMTableDefinition}; +use serde::{Deserialize, Serialize}; use std::cell::RefCell; use std::convert::{TryFrom, TryInto}; -use wasm_common::Type; +use wasm_common::{FunctionIndex, GlobalIndex, TableIndex, TableType, Type}; + +/// A WebAssembly table initializer. +#[derive(Clone, Debug, Hash, Serialize, Deserialize)] +pub struct TableElements { + /// The index of a table to initialize. + pub table_index: TableIndex, + /// Optionally, a global variable giving a base index. + pub base: Option, + /// The offset to add to the base. + pub offset: usize, + /// The values to write into the table elements. + pub elements: Box<[FunctionIndex]>, +} + +/// Implementation styles for WebAssembly tables. +#[derive(Debug, Clone, Hash, Serialize, Deserialize)] +pub enum TableStyle { + /// Signatures are stored in the table and checked in the caller. + CallerChecksSignature, +} + +/// A WebAssembly table description along with our chosen style for +/// implementing it. +#[derive(Debug, Clone, Hash, Serialize, Deserialize)] +pub struct TablePlan { + /// The WebAssembly table description. + pub table: TableType, + /// Our chosen implementation style. + pub style: TableStyle, +} /// A table instance. #[derive(Debug)] From 12fbd55e5fdf8ba5087788209d158ea7d7aca872 Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Tue, 9 Jun 2020 12:07:18 +0200 Subject: [PATCH 43/44] chore(runtime) Move `MemoryStyle` and `MemoryPlan` into the `memory` module. --- lib/runtime/src/export.rs | 3 +-- lib/runtime/src/lib.rs | 4 ++-- lib/runtime/src/memory.rs | 28 ++++++++++++++++++++++++++-- lib/runtime/src/module.rs | 28 ++-------------------------- 4 files changed, 31 insertions(+), 32 deletions(-) diff --git a/lib/runtime/src/export.rs b/lib/runtime/src/export.rs index 64f017f4a02..3396279daf7 100644 --- a/lib/runtime/src/export.rs +++ b/lib/runtime/src/export.rs @@ -1,5 +1,4 @@ -use crate::memory::LinearMemory; -use crate::module::MemoryPlan; +use crate::memory::{LinearMemory, MemoryPlan}; use crate::table::{Table, TablePlan}; use crate::vmcontext::{ VMContext, VMFunctionBody, VMFunctionKind, VMGlobalDefinition, VMMemoryDefinition, diff --git a/lib/runtime/src/lib.rs b/lib/runtime/src/lib.rs index 1818622b56d..b029c90782c 100644 --- a/lib/runtime/src/lib.rs +++ b/lib/runtime/src/lib.rs @@ -39,9 +39,9 @@ pub mod libcalls; pub use crate::export::*; pub use crate::imports::Imports; pub use crate::instance::InstanceHandle; -pub use crate::memory::{LinearMemory, MemoryError}; +pub use crate::memory::{LinearMemory, MemoryError, MemoryPlan, MemoryStyle}; pub use crate::mmap::Mmap; -pub use crate::module::{ExportsIterator, ImportsIterator, MemoryPlan, MemoryStyle, ModuleInfo}; +pub use crate::module::{ExportsIterator, ImportsIterator, ModuleInfo}; pub use crate::probestack::PROBESTACK; pub use crate::sig_registry::SignatureRegistry; pub use crate::table::{Table, TableElements, TablePlan, TableStyle}; diff --git a/lib/runtime/src/memory.rs b/lib/runtime/src/memory.rs index 513de069bd5..7642a730506 100644 --- a/lib/runtime/src/memory.rs +++ b/lib/runtime/src/memory.rs @@ -3,12 +3,12 @@ //! `LinearMemory` is to WebAssembly linear memories what `Table` is to WebAssembly tables. use crate::mmap::Mmap; -use crate::module::{MemoryPlan, MemoryStyle}; use crate::vmcontext::VMMemoryDefinition; use more_asserts::{assert_ge, assert_le}; +use serde::{Deserialize, Serialize}; use std::cell::RefCell; use thiserror::Error; -use wasm_common::{Bytes, Pages}; +use wasm_common::{Bytes, MemoryType, Pages}; /// Error type describing things that can go wrong when operating on Wasm Memories. #[derive(Error, Debug, Clone, PartialEq, Hash)] @@ -36,6 +36,30 @@ pub enum MemoryError { Generic(String), } +/// Implementation styles for WebAssembly linear memory. +#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)] +pub enum MemoryStyle { + /// The actual memory can be resized and moved. + Dynamic, + /// Address space is allocated up front. + Static { + /// The number of mapped and unmapped pages. + bound: Pages, + }, +} + +/// A WebAssembly linear memory description along with our chosen style for +/// implementing it. +#[derive(Debug, Clone, Hash, Serialize, Deserialize)] +pub struct MemoryPlan { + /// The WebAssembly linear memory description. + pub memory: MemoryType, + /// Our chosen implementation style. + pub style: MemoryStyle, + /// Our chosen offset-guard size. + pub offset_guard_size: u64, +} + /// A linear memory instance. #[derive(Debug)] pub struct LinearMemory { diff --git a/lib/runtime/src/module.rs b/lib/runtime/src/module.rs index 11687492bb0..17a61be30bb 100644 --- a/lib/runtime/src/module.rs +++ b/lib/runtime/src/module.rs @@ -13,34 +13,10 @@ use wasm_common::entity::{EntityRef, PrimaryMap}; use wasm_common::{ CustomSectionIndex, DataIndex, ElemIndex, ExportIndex, ExportType, ExternType, FunctionIndex, FunctionType, GlobalIndex, GlobalInit, GlobalType, ImportIndex, ImportType, LocalFunctionIndex, - LocalGlobalIndex, LocalMemoryIndex, LocalTableIndex, MemoryIndex, MemoryType, Pages, - SignatureIndex, TableIndex, TableType, + LocalGlobalIndex, LocalMemoryIndex, LocalTableIndex, MemoryIndex, MemoryType, SignatureIndex, + TableIndex, TableType, }; -/// Implementation styles for WebAssembly linear memory. -#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)] -pub enum MemoryStyle { - /// The actual memory can be resized and moved. - Dynamic, - /// Address space is allocated up front. - Static { - /// The number of mapped and unmapped pages. - bound: Pages, - }, -} - -/// A WebAssembly linear memory description along with our chosen style for -/// implementing it. -#[derive(Debug, Clone, Hash, Serialize, Deserialize)] -pub struct MemoryPlan { - /// The WebAssembly linear memory description. - pub memory: MemoryType, - /// Our chosen implementation style. - pub style: MemoryStyle, - /// Our chosen offset-guard size. - pub offset_guard_size: u64, -} - #[derive(Debug)] pub struct ModuleId { id: usize, From 9e61e925275ff47a93afb4689677fc890e32dbc8 Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Tue, 9 Jun 2020 13:31:50 +0200 Subject: [PATCH 44/44] chore(wasm-common) Simplify and rename the `convert_value_impl`. This macro had two patterns while one is enough. Also, rename the macro to `impl_value_type_for!`. --- lib/wasm-common/src/native.rs | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/lib/wasm-common/src/native.rs b/lib/wasm-common/src/native.rs index 48715f19732..5d4650974cc 100644 --- a/lib/wasm-common/src/native.rs +++ b/lib/wasm-common/src/native.rs @@ -147,18 +147,15 @@ where { } -macro_rules! convert_value_impl { - ($t:ty) => { - unsafe impl ValueType for $t {} - }; - ( $($t:ty),* ) => { +macro_rules! impl_value_type_for { + ( $($type:ty),* ) => { $( - convert_value_impl!($t); + unsafe impl ValueType for $type {} )* }; } -convert_value_impl!(u8, i8, u16, i16, u32, i32, u64, i64, f32, f64); +impl_value_type_for!(u8, i8, u16, i16, u32, i32, u64, i64, f32, f64); /// Represents a list of WebAssembly values. pub trait WasmTypeList {