From c0acd5be11547be4aa128db16e1cdce943ab488b Mon Sep 17 00:00:00 2001 From: Nick Lewycky Date: Thu, 17 Oct 2019 12:20:34 -0700 Subject: [PATCH 1/9] Show the full hex value of a float that fails assert returns arithmetic nan or assert returns canonical nan. --- lib/spectests/tests/spectest.rs | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/lib/spectests/tests/spectest.rs b/lib/spectests/tests/spectest.rs index 62bfc7d53..587d576f8 100644 --- a/lib/spectests/tests/spectest.rs +++ b/lib/spectests/tests/spectest.rs @@ -445,8 +445,9 @@ mod tests { "AssertReturnCanonicalNan" ), message: format!( - "value is not canonical nan {:?}", - v + "value is not canonical nan {:?} ({:?})", + v, + value_to_hex(v.clone()), ), }, &test_key, @@ -512,8 +513,9 @@ mod tests { "AssertReturnArithmeticNan" ), message: format!( - "value is not arithmetic nan {:?}", - v + "value is not arithmetic nan {:?} ({:?})", + v, + value_to_hex(v.clone()), ), }, &test_key, @@ -945,6 +947,16 @@ mod tests { } } + fn value_to_hex(val: wasmer_runtime_core::types::Value) -> String { + match val { + wasmer_runtime_core::types::Value::I32(x) => format!("{:#x}", x), + wasmer_runtime_core::types::Value::I64(x) => format!("{:#x}", x), + wasmer_runtime_core::types::Value::F32(x) => format!("{:#x}", x.to_bits()), + wasmer_runtime_core::types::Value::F64(x) => format!("{:#x}", x.to_bits()), + wasmer_runtime_core::types::Value::V128(x) => format!("{:#x}", x), + } + } + #[derive(Debug, Clone, Eq, PartialEq)] pub enum SpectestValue { I32(i32), From f101775380cff87a6f0e59e01b62249d2af03bf4 Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Thu, 17 Oct 2019 22:55:30 +0200 Subject: [PATCH 2/9] fix(cranelift-backend) Remove broken (and useless?) debug code. This debug code is broken (it doesn't compile). It can be assumed nobody uses it, and can be considered as dead code. As such, this PR removes it. --- lib/clif-backend/src/code.rs | 160 ------------------------------- lib/clif-backend/src/resolver.rs | 48 ++-------- 2 files changed, 7 insertions(+), 201 deletions(-) diff --git a/lib/clif-backend/src/code.rs b/lib/clif-backend/src/code.rs index b2ccc6652..f1d8489da 100644 --- a/lib/clif-backend/src/code.rs +++ b/lib/clif-backend/src/code.rs @@ -128,166 +128,6 @@ impl ModuleCodeGenerator .state .initialize(&builder.func.signature, exit_block); - #[cfg(feature = "debug")] - { - use cranelift_codegen::cursor::{Cursor, FuncCursor}; - use cranelift_codegen::ir::InstBuilder; - let entry_ebb = func.layout.entry_block().unwrap(); - let ebb = func.dfg.make_ebb(); - func.layout.insert_ebb(ebb, entry_ebb); - let mut pos = FuncCursor::new(&mut func).at_first_insertion_point(ebb); - let params = pos.func.dfg.ebb_params(entry_ebb).to_vec(); - - let new_ebb_params: Vec<_> = params - .iter() - .map(|¶m| { - pos.func - .dfg - .append_ebb_param(ebb, pos.func.dfg.value_type(param)) - }) - .collect(); - - let start_debug = { - let signature = pos.func.import_signature(ir::Signature { - call_conv: self.target_config().default_call_conv, - params: vec![ - ir::AbiParam::special(ir::types::I64, ir::ArgumentPurpose::VMContext), - ir::AbiParam::new(ir::types::I32), - ], - returns: vec![], - }); - - let name = ir::ExternalName::testcase("strtdbug"); - - pos.func.import_function(ir::ExtFuncData { - name, - signature, - colocated: false, - }) - }; - - let end_debug = { - let signature = pos.func.import_signature(ir::Signature { - call_conv: self.target_config().default_call_conv, - params: vec![ir::AbiParam::special( - ir::types::I64, - ir::ArgumentPurpose::VMContext, - )], - returns: vec![], - }); - - let name = ir::ExternalName::testcase("enddbug"); - - pos.func.import_function(ir::ExtFuncData { - name, - signature, - colocated: false, - }) - }; - - let i32_print = { - let signature = pos.func.import_signature(ir::Signature { - call_conv: self.target_config().default_call_conv, - params: vec![ - ir::AbiParam::special(ir::types::I64, ir::ArgumentPurpose::VMContext), - ir::AbiParam::new(ir::types::I32), - ], - returns: vec![], - }); - - let name = ir::ExternalName::testcase("i32print"); - - pos.func.import_function(ir::ExtFuncData { - name, - signature, - colocated: false, - }) - }; - - let i64_print = { - let signature = pos.func.import_signature(ir::Signature { - call_conv: self.target_config().default_call_conv, - params: vec![ - ir::AbiParam::special(ir::types::I64, ir::ArgumentPurpose::VMContext), - ir::AbiParam::new(ir::types::I64), - ], - returns: vec![], - }); - - let name = ir::ExternalName::testcase("i64print"); - - pos.func.import_function(ir::ExtFuncData { - name, - signature, - colocated: false, - }) - }; - - let f32_print = { - let signature = pos.func.import_signature(ir::Signature { - call_conv: self.target_config().default_call_conv, - params: vec![ - ir::AbiParam::special(ir::types::I64, ir::ArgumentPurpose::VMContext), - ir::AbiParam::new(ir::types::F32), - ], - returns: vec![], - }); - - let name = ir::ExternalName::testcase("f32print"); - - pos.func.import_function(ir::ExtFuncData { - name, - signature, - colocated: false, - }) - }; - - let f64_print = { - let signature = pos.func.import_signature(ir::Signature { - call_conv: self.target_config().default_call_conv, - params: vec![ - ir::AbiParam::special(ir::types::I64, ir::ArgumentPurpose::VMContext), - ir::AbiParam::new(ir::types::F64), - ], - returns: vec![], - }); - - let name = ir::ExternalName::testcase("f64print"); - - pos.func.import_function(ir::ExtFuncData { - name, - signature, - colocated: false, - }) - }; - - let vmctx = pos - .func - .special_param(ir::ArgumentPurpose::VMContext) - .expect("missing vmctx parameter"); - - let func_index = pos.ins().iconst( - ir::types::I32, - func_index.index() as i64 + self.module.info.imported_functions.len() as i64, - ); - - pos.ins().call(start_debug, &[vmctx, func_index]); - - for param in new_ebb_params.iter().cloned() { - match pos.func.dfg.value_type(param) { - ir::types::I32 => pos.ins().call(i32_print, &[vmctx, param]), - ir::types::I64 => pos.ins().call(i64_print, &[vmctx, param]), - ir::types::F32 => pos.ins().call(f32_print, &[vmctx, param]), - ir::types::F64 => pos.ins().call(f64_print, &[vmctx, param]), - _ => unimplemented!(), - }; - } - - pos.ins().call(end_debug, &[vmctx]); - - pos.ins().jump(entry_ebb, new_ebb_params.as_slice()); - } - self.functions.push(func_env); Ok(self.functions.last_mut().unwrap()) } diff --git a/lib/clif-backend/src/resolver.rs b/lib/clif-backend/src/resolver.rs index 7a868f35e..efc038d58 100644 --- a/lib/clif-backend/src/resolver.rs +++ b/lib/clif-backend/src/resolver.rs @@ -1,32 +1,31 @@ -use crate::{cache::BackendCache, trampoline::Trampolines}; use crate::{ + cache::BackendCache, libcalls, relocation::{ ExternalRelocation, LibCall, LocalRelocation, LocalTrapSink, Reloc, RelocSink, RelocationType, TrapSink, VmCall, VmCallKind, }, signal::HandlerData, + trampoline::Trampolines, }; -use rayon::prelude::*; - use byteorder::{ByteOrder, LittleEndian}; use cranelift_codegen::{ binemit::{Stackmap, StackmapSink}, ir, isa, Context, }; +use rayon::prelude::*; use std::{ mem, ptr::{write_unaligned, NonNull}, sync::Arc, }; - -use wasmer_runtime_core::cache::Error as CacheError; use wasmer_runtime_core::{ self, backend::{ sys::{Memory, Protect}, SigRegistry, }, + cache::Error as CacheError, error::{CompileError, CompileResult}, module::ModuleInfo, structures::{Map, SliceMap, TypedIndex}, @@ -250,17 +249,9 @@ impl FuncResolverBuilder { #[cfg(not(target_os = "windows"))] LibCall::Probestack => __rust_probestack as isize, }, - RelocationType::Intrinsic(ref name) => match name.as_str() { - "i32print" => i32_print as isize, - "i64print" => i64_print as isize, - "f32print" => f32_print as isize, - "f64print" => f64_print as isize, - "strtdbug" => start_debug as isize, - "enddbug" => end_debug as isize, - _ => Err(CompileError::InternalError { - msg: format!("unexpected intrinsic: {}", name), - })?, - }, + RelocationType::Intrinsic(ref name) => Err(CompileError::InternalError { + msg: format!("unexpected intrinsic: {}", name), + })?, RelocationType::VmCall(vmcall) => match vmcall { VmCall::Local(kind) => match kind { VmCallKind::StaticMemoryGrow | VmCallKind::SharedStaticMemoryGrow => { @@ -371,28 +362,3 @@ impl FuncResolver { fn round_up(n: usize, multiple: usize) -> usize { (n + multiple - 1) & !(multiple - 1) } - -extern "C" fn i32_print(_ctx: &mut vm::Ctx, n: i32) { - eprint!(" i32: {},", n); -} -extern "C" fn i64_print(_ctx: &mut vm::Ctx, n: i64) { - eprint!(" i64: {},", n); -} -extern "C" fn f32_print(_ctx: &mut vm::Ctx, n: f32) { - eprint!(" f32: {},", n); -} -extern "C" fn f64_print(_ctx: &mut vm::Ctx, n: f64) { - eprint!(" f64: {},", n); -} -extern "C" fn start_debug(ctx: &mut vm::Ctx, func_index: u32) { - if let Some(symbol_map) = unsafe { ctx.borrow_symbol_map() } { - if let Some(fn_name) = symbol_map.get(&func_index) { - eprint!("func ({} ({})), args: [", fn_name, func_index); - return; - } - } - eprint!("func ({}), args: [", func_index); -} -extern "C" fn end_debug(_ctx: &mut vm::Ctx) { - eprintln!(" ]"); -} From 87d272e31e3cb33b0f9e0f757fbcc8ba960f8fbe Mon Sep 17 00:00:00 2001 From: Nick Lewycky Date: Fri, 4 Oct 2019 12:37:31 -0700 Subject: [PATCH 3/9] Initial implementation of AssertUninstantiable. Fixes linking.wast:387. --- lib/spectests/tests/excludes.txt | 3 --- lib/spectests/tests/spectest.rs | 42 +++++++++++++++++++++++++++++--- 2 files changed, 38 insertions(+), 7 deletions(-) diff --git a/lib/spectests/tests/excludes.txt b/lib/spectests/tests/excludes.txt index 6cd94753b..3da022b01 100644 --- a/lib/spectests/tests/excludes.txt +++ b/lib/spectests/tests/excludes.txt @@ -32,7 +32,6 @@ clif:fail:linking.wast:147 # AssertTrap - expected trap, got Runtime:Error "unkn clif:fail:linking.wast:149 # AssertTrap - expected trap, got Runtime:Error "unknown trap at 0x106883037 - illegal instruction" clif:fail:linking.wast:185 # AssertTrap - expected trap, got Runtime:Error "unknown trap at 0x106883062 - illegal instruction" clif:fail:linking.wast:187 # AssertTrap - expected trap, got Runtime:Error "unknown trap at 0x106883062 - illegal instruction" -clif:fail:linking.wast:387 # AssertReturn - result I32(0) ("0x0") does not match expected I32(104) ("0x68") clif:fail:linking.wast:388 # AssertReturn - Call failed RuntimeError: WebAssembly trap occurred during runtime: `call_indirect` out-of-bounds # clif:skip:skip-stack-guard-page.wast:2 # Slow test @@ -269,7 +268,6 @@ llvm:fail:f32.wast:1621 # AssertReturn - result F32(0) ("0x0") does not match ex llvm:fail:f32.wast:2020 # AssertReturn - result F32(2147483648) ("0x80000000") does not match expected F32(0) ("0x0") llvm:fail:f64.wast:1621 # AssertReturn - result F64(0) ("0x0") does not match expected F64(9223372036854775808) ("0x8000000000000000") llvm:fail:f64.wast:2020 # AssertReturn - result F64(9223372036854775808) ("0x8000000000000000") does not match expected F64(0) ("0x0") -llvm:fail:linking.wast:387 # AssertReturn - result I32(0) ("0x0") does not match expected I32(104) ("0x68") llvm:fail:linking.wast:388 # AssertReturn - Call failed RuntimeError: WebAssembly trap occurred during runtime: incorrect `call_indirect` signature # LLVM Windows @@ -957,7 +955,6 @@ singlepass:fail:linking.wast:190 # AssertTrap - expected trap, got Runtime:Error singlepass:fail:linking.wast:225 # AssertTrap - expected trap, got Runtime:Error unknown error singlepass:fail:linking.wast:236 # AssertTrap - expected trap, got Runtime:Error unknown error singlepass:fail:linking.wast:248 # AssertTrap - expected trap, got Runtime:Error unknown error -singlepass:fail:linking.wast:387 # AssertReturn - result I32(0) ("0x0") does not match expected I32(104) ("0x68") singlepass:fail:linking.wast:388 # AssertReturn - Call failed RuntimeError: unknown error singlepass:fail:memory_grow.wast:15 # AssertTrap - expected trap, got Runtime:Error unknown error singlepass:fail:memory_grow.wast:16 # AssertTrap - expected trap, got Runtime:Error unknown error diff --git a/lib/spectests/tests/spectest.rs b/lib/spectests/tests/spectest.rs index 587d576f8..19114ff67 100644 --- a/lib/spectests/tests/spectest.rs +++ b/lib/spectests/tests/spectest.rs @@ -720,10 +720,44 @@ mod tests { } } } - CommandKind::AssertUninstantiable { - module: _, - message: _, - } => println!("AssertUninstantiable not yet implmented "), + CommandKind::AssertUninstantiable { module, message: _ } => { + let spectest_import_object = get_spectest_import_object(®istered_modules); + let config = CompilerConfig { + features: Features { + simd: true, + threads: true, + }, + ..Default::default() + }; + let module = wasmer_runtime_core::compile_with_config( + &module.into_vec(), + &get_compiler(), + config, + ) + .expect("WASM can't be compiled"); + let result = panic::catch_unwind(AssertUnwindSafe(|| { + module + .instantiate(&spectest_import_object) + .expect("WASM can't be instantiated"); + })); + match result { + Err(_) => test_report.count_passed(), + Ok(_) => { + test_report.add_failure( + SpecFailure { + file: filename.to_string(), + line: line, + kind: format!("{}", "AssertUninstantiable"), + message: format!( + "instantiate successful, expected uninstantiable" + ), + }, + &test_key, + excludes, + ); + } + }; + } CommandKind::AssertExhaustion { action, message: _ } => { match action { Action::Invoke { From 675399909af7a1f2f73f330f659db1e53217ae5d Mon Sep 17 00:00:00 2001 From: Nick Lewycky Date: Thu, 17 Oct 2019 18:38:11 -0700 Subject: [PATCH 4/9] Skip this test on windows + cranelift. It crashes the whole spectest runner. This exclusion is no worse than before where this test was silently ignored. --- lib/spectests/tests/excludes.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/spectests/tests/excludes.txt b/lib/spectests/tests/excludes.txt index 3da022b01..5432534f9 100644 --- a/lib/spectests/tests/excludes.txt +++ b/lib/spectests/tests/excludes.txt @@ -82,6 +82,7 @@ clif:fail:data.wast:227:windows # AssertUnlinkable - caught panic Any clif:fail:data.wast:258:windows # AssertUnlinkable - caught panic Any clif:fail:data.wast:273:windows # AssertUnlinkable - caught panic Any clif:fail:start.wast:92:windows # Module - caught panic Any +clif:fail:start.wast:98:windows clif:fail:align.wast:3:windows # Module - caught panic Any clif:fail:align.wast:4:windows # Module - caught panic Any From fbe2701a937d4cc932dcc8bfe32095fc863b12ea Mon Sep 17 00:00:00 2001 From: Nick Lewycky Date: Thu, 17 Oct 2019 19:23:36 -0700 Subject: [PATCH 5/9] I meant 'skip' not 'fail'. --- lib/spectests/tests/excludes.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/spectests/tests/excludes.txt b/lib/spectests/tests/excludes.txt index 5432534f9..a54b3df49 100644 --- a/lib/spectests/tests/excludes.txt +++ b/lib/spectests/tests/excludes.txt @@ -82,7 +82,7 @@ clif:fail:data.wast:227:windows # AssertUnlinkable - caught panic Any clif:fail:data.wast:258:windows # AssertUnlinkable - caught panic Any clif:fail:data.wast:273:windows # AssertUnlinkable - caught panic Any clif:fail:start.wast:92:windows # Module - caught panic Any -clif:fail:start.wast:98:windows +clif:skip:start.wast:98:windows clif:fail:align.wast:3:windows # Module - caught panic Any clif:fail:align.wast:4:windows # Module - caught panic Any From 8424b61444bc634386a36b90fdaefd93c8c3617c Mon Sep 17 00:00:00 2001 From: Nick Lewycky Date: Fri, 2 Aug 2019 14:03:19 -0700 Subject: [PATCH 6/9] Fix typo in comment. --- lib/runtime-core/src/module.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/runtime-core/src/module.rs b/lib/runtime-core/src/module.rs index 6cc02343f..1bf914a46 100644 --- a/lib/runtime-core/src/module.rs +++ b/lib/runtime-core/src/module.rs @@ -29,7 +29,7 @@ pub struct ModuleInner { #[derive(Clone, Debug, Serialize, Deserialize)] pub struct ModuleInfo { - // This are strictly local and the typsystem ensures that. + // This are strictly local and the typesystem ensures that. pub memories: Map, pub globals: Map, pub tables: Map, From 961684a8e0b2959f0aa0bf2f64e89454005bc40e Mon Sep 17 00:00:00 2001 From: Nick Lewycky Date: Wed, 21 Aug 2019 15:48:13 -0700 Subject: [PATCH 7/9] Adjust comment rulers. --- lib/runtime-core/src/vmcalls.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/runtime-core/src/vmcalls.rs b/lib/runtime-core/src/vmcalls.rs index 5205a0d69..33d473aa0 100644 --- a/lib/runtime-core/src/vmcalls.rs +++ b/lib/runtime-core/src/vmcalls.rs @@ -10,7 +10,7 @@ use crate::{ // +*****************************+ // | LOCAL MEMORIES | -// +****************************+ +// +*****************************+ pub unsafe extern "C" fn local_static_memory_grow( ctx: &mut vm::Ctx, @@ -72,7 +72,7 @@ pub unsafe extern "C" fn local_dynamic_memory_size( // +*****************************+ // | IMPORTED MEMORIES | -// +****************************+ +// +*****************************+ pub unsafe extern "C" fn imported_static_memory_grow( ctx: &mut vm::Ctx, @@ -140,7 +140,7 @@ pub unsafe extern "C" fn imported_dynamic_memory_size( // +*****************************+ // | LOCAL TABLES | -// +****************************+ +// +*****************************+ pub unsafe extern "C" fn local_table_grow( ctx: &mut vm::Ctx, From 10dddf99048873405c8934ab7d71a4cbe5f0d47b Mon Sep 17 00:00:00 2001 From: Nick Lewycky Date: Fri, 18 Oct 2019 16:34:45 -0700 Subject: [PATCH 8/9] Fix repeated typo in comment. --- lib/llvm-backend/src/code.rs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/lib/llvm-backend/src/code.rs b/lib/llvm-backend/src/code.rs index 9ccb0c990..7ce0459b9 100644 --- a/lib/llvm-backend/src/code.rs +++ b/lib/llvm-backend/src/code.rs @@ -2682,7 +2682,7 @@ impl FunctionCodeGenerator for LLVMFunctionCodeGenerator { } Operator::F32Min => { // This implements the same logic as LLVM's @llvm.minimum - // intrinsic would, but x86 lowering of that intrinsics + // intrinsic would, but x86 lowering of that intrinsic // encounters a fatal error in LLVM 8 and LLVM 9. let (v1, v2) = state.pop2()?; let v1 = canonicalize_nans(builder, intrinsics, v1); @@ -2728,7 +2728,7 @@ impl FunctionCodeGenerator for LLVMFunctionCodeGenerator { } Operator::F64Min => { // This implements the same logic as LLVM's @llvm.minimum - // intrinsic would, but x86 lowering of that intrinsics + // intrinsic would, but x86 lowering of that intrinsic // encounters a fatal error in LLVM 8 and LLVM 9. let (v1, v2) = state.pop2()?; let v1 = canonicalize_nans(builder, intrinsics, v1); @@ -2774,7 +2774,7 @@ impl FunctionCodeGenerator for LLVMFunctionCodeGenerator { } Operator::F32x4Min => { // This implements the same logic as LLVM's @llvm.minimum - // intrinsic would, but x86 lowering of that intrinsics + // intrinsic would, but x86 lowering of that intrinsic // encounters a fatal error in LLVM 8 and LLVM 9. let (v1, v2) = state.pop2()?; let v1 = builder.build_bitcast(v1, intrinsics.f32x4_ty, ""); @@ -2829,7 +2829,7 @@ impl FunctionCodeGenerator for LLVMFunctionCodeGenerator { } Operator::F64x2Min => { // This implements the same logic as LLVM's @llvm.minimum - // intrinsic would, but x86 lowering of that intrinsics + // intrinsic would, but x86 lowering of that intrinsic // encounters a fatal error in LLVM 8 and LLVM 9. let (v1, v2) = state.pop2()?; let v1 = builder.build_bitcast(v1, intrinsics.f64x2_ty, ""); @@ -2884,7 +2884,7 @@ impl FunctionCodeGenerator for LLVMFunctionCodeGenerator { } Operator::F32Max => { // This implements the same logic as LLVM's @llvm.maximum - // intrinsic would, but x86 lowering of that intrinsics + // intrinsic would, but x86 lowering of that intrinsic // encounters a fatal error in LLVM 8 and LLVM 9. let (v1, v2) = state.pop2()?; let v1 = canonicalize_nans(builder, intrinsics, v1); @@ -2929,7 +2929,7 @@ impl FunctionCodeGenerator for LLVMFunctionCodeGenerator { } Operator::F64Max => { // This implements the same logic as LLVM's @llvm.maximum - // intrinsic would, but x86 lowering of that intrinsics + // intrinsic would, but x86 lowering of that intrinsic // encounters a fatal error in LLVM 8 and LLVM 9. let (v1, v2) = state.pop2()?; let v1 = canonicalize_nans(builder, intrinsics, v1); @@ -2974,7 +2974,7 @@ impl FunctionCodeGenerator for LLVMFunctionCodeGenerator { } Operator::F32x4Max => { // This implements the same logic as LLVM's @llvm.maximum - // intrinsic would, but x86 lowering of that intrinsics + // intrinsic would, but x86 lowering of that intrinsic // encounters a fatal error in LLVM 8 and LLVM 9. let (v1, v2) = state.pop2()?; let v1 = builder.build_bitcast(v1, intrinsics.f32x4_ty, ""); @@ -3029,7 +3029,7 @@ impl FunctionCodeGenerator for LLVMFunctionCodeGenerator { } Operator::F64x2Max => { // This implements the same logic as LLVM's @llvm.maximum - // intrinsic would, but x86 lowering of that intrinsics + // intrinsic would, but x86 lowering of that intrinsic // encounters a fatal error in LLVM 8 and LLVM 9. let (v1, v2) = state.pop2()?; let v1 = builder.build_bitcast(v1, intrinsics.f64x2_ty, ""); From 33a2b361b046af6ae79a233d9d296f0994dac5c3 Mon Sep 17 00:00:00 2001 From: Syrus Date: Mon, 21 Oct 2019 12:09:10 -0700 Subject: [PATCH 9/9] Added JavaScript to the list of supported implementations --- README.md | 1 + docs/assets/languages/js.svg | 8 ++++++++ 2 files changed, 9 insertions(+) create mode 100755 docs/assets/languages/js.svg diff --git a/README.md b/README.md index e69fe2d1c..7e7f39cb1 100644 --- a/README.md +++ b/README.md @@ -44,6 +44,7 @@ Wasmer runtime can be used as a library embedded in different languages, so you | ![PHP logo](./docs/assets/languages/php.svg) | [**PHP**](https://github.com/wasmerio/php-ext-wasm) | Wasmer | actively developed | ![last release](https://img.shields.io/github/v/release/wasmerio/php-ext-wasm?style=flat-square) | ![number of Github stars](https://img.shields.io/github/stars/wasmerio/php-ext-wasm?style=flat-square) | | ![Ruby logo](./docs/assets/languages/ruby.svg) | [**Ruby**](https://github.com/wasmerio/ruby-ext-wasm) | Wasmer | actively developed | ![last release](https://img.shields.io/gem/v/wasmer?style=flat-square) | ![number of Github stars](https://img.shields.io/github/stars/wasmerio/ruby-ext-wasm?style=flat-square) | | ![Postgres logo](./docs/assets/languages/postgres.svg) | [**Postgres**](https://github.com/wasmerio/postgres-ext-wasm) | Wasmer | actively developed | ![last release](https://img.shields.io/github/v/release/wasmerio/postgres-ext-wasm?style=flat-square) | ![number of Github stars](https://img.shields.io/github/stars/wasmerio/postgres-ext-wasm?style=flat-square) | +| ![JS Logo](./docs/assets/languages/js.svg) | [**JavaScript**](https://github.com/wasmerio/wasmer-js) | Wasmer | actively developed | ![last release](https://img.shields.io/npm/v/@wasmer/wasi?style=flat-square) | ![number of Github stars](https://img.shields.io/github/stars/wasmerio/wasmer-js?style=flat-square) | | ![C# logo](./docs/assets/languages/csharp.svg) | [**C#/.Net**](https://github.com/migueldeicaza/WasmerSharp) | [Miguel de Icaza](https://github.com/migueldeicaza) | actively developed | ![last release](https://img.shields.io/nuget/v/WasmerSharp?style=flat-square) | ![number of Github stars](https://img.shields.io/github/stars/migueldeicaza/WasmerSharp?style=flat-square) | | ![R logo](./docs/assets/languages/r.svg) | [**R**](https://github.com/dirkschumacher/wasmr) | [Dirk Schumacher](https://github.com/dirkschumacher) | actively developed | | ![number of Github stars](https://img.shields.io/github/stars/dirkschumacher/wasmr?style=flat-square) | | ![Swift logo](./docs/assets/languages/swift.svg) | [**Swift**](https://github.com/markmals/swift-ext-wasm) | [Mark Malström](https://github.com/markmals/) | passively maintained | | ![number of Github stars](https://img.shields.io/github/stars/markmals/swift-ext-wasm?style=flat-square) | diff --git a/docs/assets/languages/js.svg b/docs/assets/languages/js.svg new file mode 100755 index 000000000..6a186f383 --- /dev/null +++ b/docs/assets/languages/js.svg @@ -0,0 +1,8 @@ + + + + + + + +