From aa90a33501a57850a8728672a8c92624f2798284 Mon Sep 17 00:00:00 2001 From: Lachlan Sneff Date: Fri, 8 Feb 2019 14:19:58 -0800 Subject: [PATCH 01/75] Make module info store FuncSig, not Arc --- lib/clif-backend/src/module_env.rs | 5 +---- lib/clif-backend/src/resolver.rs | 6 +++--- lib/clif-backend/src/signal/mod.rs | 8 ++++---- lib/runtime-core/src/backend.rs | 1 + lib/runtime-core/src/backing.rs | 26 ++++++++++++++------------ lib/runtime-core/src/error.rs | 18 +++++------------- lib/runtime-core/src/instance.rs | 20 ++++++++++---------- lib/runtime-core/src/module.rs | 2 +- lib/runtime-core/src/sig_registry.rs | 16 ++++++++++++++++ 9 files changed, 55 insertions(+), 47 deletions(-) diff --git a/lib/clif-backend/src/module_env.rs b/lib/clif-backend/src/module_env.rs index 8a26b2731..de625cc23 100644 --- a/lib/clif-backend/src/module_env.rs +++ b/lib/clif-backend/src/module_env.rs @@ -62,10 +62,7 @@ impl<'module, 'isa, 'data> ModuleEnvironment<'data> for ModuleEnv<'module, 'isa> /// Declares a function signature to the environment. fn declare_signature(&mut self, sig: &ir::Signature) { self.signatures.push(sig.clone()); - self.module - .info - .signatures - .push(Arc::new(Converter(sig).into())); + self.module.info.signatures.push(Converter(sig).into()); } /// Return the signature with the given index. diff --git a/lib/clif-backend/src/resolver.rs b/lib/clif-backend/src/resolver.rs index 315bd154a..034f0f540 100644 --- a/lib/clif-backend/src/resolver.rs +++ b/lib/clif-backend/src/resolver.rs @@ -201,7 +201,7 @@ impl FuncResolverBuilder { pub fn finalize( mut self, - signatures: &SliceMap>, + signatures: &SliceMap, ) -> CompileResult { for (index, relocs) in self.external_relocs.iter() { for ref reloc in relocs.iter() { @@ -263,8 +263,8 @@ impl FuncResolverBuilder { }, }, RelocationType::Signature(sig_index) => { - let sig_index = - SigRegistry.lookup_sig_index(Arc::clone(&signatures[sig_index])); + let signature = SigRegistry.lookup_signature_ref(&signatures[sig_index]); + let sig_index = SigRegistry.lookup_sig_index(signature); sig_index.index() as _ } }; diff --git a/lib/clif-backend/src/signal/mod.rs b/lib/clif-backend/src/signal/mod.rs index eab9e62e7..0767f9527 100644 --- a/lib/clif-backend/src/signal/mod.rs +++ b/lib/clif-backend/src/signal/mod.rs @@ -137,11 +137,11 @@ impl ProtectedCaller for Caller { } } -fn get_func_from_index( - module: &ModuleInner, +fn get_func_from_index<'a>( + module: &'a ModuleInner, import_backing: &ImportBacking, func_index: FuncIndex, -) -> (*const vm::Func, Context, Arc, SigIndex) { +) -> (*const vm::Func, Context, &'a FuncSig, SigIndex) { let sig_index = *module .info .func_assoc @@ -167,7 +167,7 @@ fn get_func_from_index( } }; - let signature = Arc::clone(&module.info.signatures[sig_index]); + let signature = &module.info.signatures[sig_index]; (func_ptr, ctx, signature, sig_index) } diff --git a/lib/runtime-core/src/backend.rs b/lib/runtime-core/src/backend.rs index 9b5ec049e..f69ef2361 100644 --- a/lib/runtime-core/src/backend.rs +++ b/lib/runtime-core/src/backend.rs @@ -23,6 +23,7 @@ pub use crate::sig_registry::SigRegistry; #[derive(Debug, Copy, Clone, PartialEq, Eq)] pub enum Backend { Cranelift, + LLVM, } /// This type cannot be constructed from diff --git a/lib/runtime-core/src/backing.rs b/lib/runtime-core/src/backing.rs index d81e33065..46f1fe982 100644 --- a/lib/runtime-core/src/backing.rs +++ b/lib/runtime-core/src/backing.rs @@ -14,7 +14,7 @@ use crate::{ }, vm, }; -use std::{slice, sync::Arc}; +use std::slice; #[derive(Debug)] pub struct LocalBacking { @@ -172,10 +172,11 @@ impl LocalBacking { table.anyfunc_direct_access_mut(|elements| { for (i, &func_index) in init.elements.iter().enumerate() { let sig_index = module.info.func_assoc[func_index]; - let signature = &module.info.signatures[sig_index]; - let sig_id = vm::SigId( - SigRegistry.lookup_sig_index(Arc::clone(&signature)).index() as u32, - ); + // let signature = &module.info.signatures[sig_index]; + let signature = SigRegistry + .lookup_signature_ref(&module.info.signatures[sig_index]); + let sig_id = + vm::SigId(SigRegistry.lookup_sig_index(signature).index() as u32); let (func, ctx) = match func_index.local_or_import(module) { LocalOrImport::Local(local_func_index) => ( @@ -210,10 +211,11 @@ impl LocalBacking { table.anyfunc_direct_access_mut(|elements| { for (i, &func_index) in init.elements.iter().enumerate() { let sig_index = module.info.func_assoc[func_index]; - let signature = &module.info.signatures[sig_index]; - let sig_id = vm::SigId( - SigRegistry.lookup_sig_index(Arc::clone(&signature)).index() as u32, - ); + let signature = SigRegistry + .lookup_signature_ref(&module.info.signatures[sig_index]); + // let signature = &module.info.signatures[sig_index]; + let sig_id = + vm::SigId(SigRegistry.lookup_sig_index(signature).index() as u32); let (func, ctx) = match func_index.local_or_import(module) { LocalOrImport::Local(local_func_index) => ( @@ -379,7 +381,7 @@ fn import_functions( ctx, signature, }) => { - if *expected_sig == signature { + if *expected_sig == *signature { functions.push(vm::ImportedFunc { func: func.inner(), vmctx: match ctx { @@ -391,8 +393,8 @@ fn import_functions( link_errors.push(LinkError::IncorrectImportSignature { namespace: namespace.to_string(), name: name.to_string(), - expected: expected_sig.clone(), - found: signature.clone(), + expected: (*expected_sig).clone(), + found: (*signature).clone(), }); } } diff --git a/lib/runtime-core/src/error.rs b/lib/runtime-core/src/error.rs index b72c74242..ec9c5e772 100644 --- a/lib/runtime-core/src/error.rs +++ b/lib/runtime-core/src/error.rs @@ -1,7 +1,6 @@ use crate::types::{ FuncSig, GlobalDescriptor, MemoryDescriptor, MemoryIndex, TableDescriptor, TableIndex, Type, }; -use std::sync::Arc; pub type Result = std::result::Result; pub type CompileResult = std::result::Result; @@ -42,8 +41,8 @@ pub enum LinkError { IncorrectImportSignature { namespace: String, name: String, - expected: Arc, - found: Arc, + expected: FuncSig, + found: FuncSig, }, ImportNotFound { namespace: String, @@ -117,16 +116,9 @@ impl PartialEq for RuntimeError { /// Comparing two `ResolveError`s always evaluates to false. #[derive(Debug, Clone)] pub enum ResolveError { - Signature { - expected: Arc, - found: Vec, - }, - ExportNotFound { - name: String, - }, - ExportWrongType { - name: String, - }, + Signature { expected: FuncSig, found: Vec }, + ExportNotFound { name: String }, + ExportWrongType { name: String }, } impl PartialEq for ResolveError { diff --git a/lib/runtime-core/src/instance.rs b/lib/runtime-core/src/instance.rs index a8f36325a..8255c125d 100644 --- a/lib/runtime-core/src/instance.rs +++ b/lib/runtime-core/src/instance.rs @@ -7,6 +7,7 @@ use crate::{ import::{ImportObject, LikeNamespace}, memory::Memory, module::{ExportIndex, Module, ModuleInner}, + sig_registry::SigRegistry, table::Table, typed_func::{Func, Safe, WasmTypeList}, types::{FuncIndex, FuncSig, GlobalIndex, LocalOrImport, MemoryIndex, TableIndex, Value}, @@ -112,11 +113,12 @@ impl Instance { .func_assoc .get(*func_index) .expect("broken invariant, incorrect func index"); - let signature = &self.module.info.signatures[sig_index]; + let signature = + SigRegistry.lookup_signature_ref(&self.module.info.signatures[sig_index]); if signature.params() != Args::types() || signature.returns() != Rets::types() { Err(ResolveError::Signature { - expected: Arc::clone(&signature), + expected: (*signature).clone(), found: Args::types().to_vec(), })?; } @@ -183,7 +185,8 @@ impl Instance { .func_assoc .get(*func_index) .expect("broken invariant, incorrect func index"); - let signature = Arc::clone(&self.module.info.signatures[sig_index]); + let signature = + SigRegistry.lookup_signature_ref(&self.module.info.signatures[sig_index]); Ok(DynFunc { signature, @@ -374,13 +377,10 @@ impl InstanceInner { } }; - let signature = &module.info.signatures[sig_index]; + let signature = SigRegistry.lookup_signature_ref(&module.info.signatures[sig_index]); + // let signature = &module.info.signatures[sig_index]; - ( - unsafe { FuncPointer::new(func_ptr) }, - ctx, - Arc::clone(signature), - ) + (unsafe { FuncPointer::new(func_ptr) }, ctx, signature) } fn get_memory_from_index(&self, module: &ModuleInner, mem_index: MemoryIndex) -> Memory { @@ -457,7 +457,7 @@ impl<'a> DynFunc<'a> { pub fn call(&mut self, params: &[Value]) -> CallResult> { if !self.signature.check_param_value_types(params) { Err(ResolveError::Signature { - expected: self.signature.clone(), + expected: (*self.signature).clone(), found: params.iter().map(|val| val.ty()).collect(), })? } diff --git a/lib/runtime-core/src/module.rs b/lib/runtime-core/src/module.rs index 0fdb24018..54306153b 100644 --- a/lib/runtime-core/src/module.rs +++ b/lib/runtime-core/src/module.rs @@ -46,7 +46,7 @@ pub struct ModuleInfo { pub start_func: Option, pub func_assoc: Map, - pub signatures: Map>, + pub signatures: Map, pub backend: Backend, pub namespace_table: StringTable, diff --git a/lib/runtime-core/src/sig_registry.rs b/lib/runtime-core/src/sig_registry.rs index 77c9a0d3c..1f6d87b4f 100644 --- a/lib/runtime-core/src/sig_registry.rs +++ b/lib/runtime-core/src/sig_registry.rs @@ -49,4 +49,20 @@ impl SigRegistry { let global = (*GLOBAL_SIG_REGISTRY).read(); Arc::clone(&global.sig_assoc[sig_index]) } + + pub fn lookup_signature_ref(&self, func_sig: &FuncSig) -> Arc { + let mut global = (*GLOBAL_SIG_REGISTRY).write(); + let global = &mut *global; + + let func_table = &mut global.func_table; + let sig_assoc = &mut global.sig_assoc; + + if func_table.contains_key(func_sig) { + Arc::clone(&sig_assoc[func_table[func_sig]]) + } else { + let arc = Arc::new(func_sig.clone()); + func_table.insert(Arc::clone(&arc), sig_assoc.push(Arc::clone(&arc))); + arc + } + } } From 327e3a4a1aeddb6ea07a753eed8046d7daed3673 Mon Sep 17 00:00:00 2001 From: Lachlan Sneff Date: Sat, 9 Feb 2019 15:53:40 -0800 Subject: [PATCH 02/75] Implement many wasm instructions --- Cargo.lock | 169 ++++++- Cargo.toml | 2 +- lib/clif-backend/src/func_env.rs | 134 ++--- lib/clif-backend/src/module_env.rs | 6 +- lib/clif-backend/src/signal/mod.rs | 2 +- lib/llvm-backend/.llvmenv | 1 + lib/llvm-backend/Cargo.toml | 17 + lib/llvm-backend/src/code.rs | 765 +++++++++++++++++++++++++++++ lib/llvm-backend/src/example.rs | 61 +++ lib/llvm-backend/src/intrinsics.rs | 99 ++++ lib/llvm-backend/src/lib.rs | 52 ++ lib/llvm-backend/src/read_info.rs | 333 +++++++++++++ lib/llvm-backend/src/state.rs | 105 ++++ lib/runtime-core/src/backing.rs | 10 +- lib/runtime-core/src/instance.rs | 18 +- lib/runtime-core/src/types.rs | 19 +- lib/runtime-core/src/vm.rs | 2 +- 17 files changed, 1700 insertions(+), 95 deletions(-) create mode 100644 lib/llvm-backend/.llvmenv create mode 100644 lib/llvm-backend/Cargo.toml create mode 100644 lib/llvm-backend/src/code.rs create mode 100644 lib/llvm-backend/src/example.rs create mode 100644 lib/llvm-backend/src/intrinsics.rs create mode 100644 lib/llvm-backend/src/lib.rs create mode 100644 lib/llvm-backend/src/read_info.rs create mode 100644 lib/llvm-backend/src/state.rs diff --git a/Cargo.lock b/Cargo.lock index d061df27b..209d06782 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,3 +1,11 @@ +[[package]] +name = "aho-corasick" +version = "0.6.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "memchr 2.1.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "ansi_term" version = "0.11.0" @@ -28,7 +36,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "block-buffer" -version = "0.7.2" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "block-padding 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -178,6 +186,20 @@ dependencies = [ "generic-array 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "either" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "enum-methods" +version = "0.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "errno" version = "0.2.4" @@ -281,6 +303,27 @@ name = "indexmap" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "inkwell" +version = "0.1.0" +source = "git+https://github.com/TheDan64/inkwell?branch=llvm7-0#83b9188bad1e098f97e6aad8f6d45becb6d1ccdd" +dependencies = [ + "either 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "enum-methods 0.0.8 (registry+https://github.com/rust-lang/crates.io-index)", + "inkwell_internal_macros 0.1.0 (git+https://github.com/TheDan64/inkwell?branch=llvm7-0)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "llvm-sys 70.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "inkwell_internal_macros" +version = "0.1.0" +source = "git+https://github.com/TheDan64/inkwell?branch=llvm7-0#83b9188bad1e098f97e6aad8f6d45becb6d1ccdd" +dependencies = [ + "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "itoa" version = "0.4.3" @@ -310,6 +353,29 @@ name = "libc" version = "0.2.48" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "llvm-backend" +version = "0.1.0" +dependencies = [ + "hashbrown 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "inkwell 0.1.0 (git+https://github.com/TheDan64/inkwell?branch=llvm7-0)", + "wabt 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)", + "wasmer-runtime-core 0.1.2", + "wasmparser 0.28.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "llvm-sys" +version = "70.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cc 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "lock_api" version = "0.1.5" @@ -327,6 +393,15 @@ dependencies = [ "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "memchr" +version = "2.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "memmap" version = "0.7.0" @@ -412,6 +487,11 @@ dependencies = [ "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "quote" +version = "0.3.15" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "quote" version = "0.6.11" @@ -547,6 +627,26 @@ dependencies = [ "redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "regex" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "aho-corasick 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 2.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "regex-syntax 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "utf8-ranges 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "regex-syntax" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "ucd-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "rustc_version" version = "0.2.3" @@ -625,7 +725,7 @@ name = "sha2" version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "block-buffer 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "block-buffer 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "digest 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "opaque-debug 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -669,6 +769,16 @@ dependencies = [ "syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "syn" +version = "0.11.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", + "synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "syn" version = "0.15.26" @@ -679,6 +789,14 @@ dependencies = [ "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "synom" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "synstructure" version = "0.10.1" @@ -718,6 +836,14 @@ dependencies = [ "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "thread_local" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "time" version = "0.1.42" @@ -733,6 +859,11 @@ name = "typenum" version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "ucd-util" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "unicode-segmentation" version = "1.2.1" @@ -743,6 +874,11 @@ name = "unicode-width" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "unicode-xid" +version = "0.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "unicode-xid" version = "0.1.0" @@ -756,6 +892,11 @@ dependencies = [ "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "utf8-ranges" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "vec_map" version = "0.8.1" @@ -886,6 +1027,11 @@ name = "wasmparser" version = "0.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "wasmparser" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "winapi" version = "0.2.8" @@ -916,11 +1062,12 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" [metadata] +"checksum aho-corasick 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)" = "1e9a933f4e58658d7b12defcf96dc5c720f20832deebe3e0a19efd3b6aaeeb9e" "checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" "checksum atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "9a7d5b8723950951411ee34d271d99dddcc2035a16ab25310ea2c8cfd4369652" "checksum autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a6d640bee2da49f60a4068a7fae53acde8982514ab7bae8b8cea9e88cbcfd799" "checksum bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12" -"checksum block-buffer 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "509de513cca6d92b6aacf9c61acfe7eaa160837323a81068d690cc1f8e5740da" +"checksum block-buffer 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "49665c62e0e700857531fa5d3763e91b539ff1abeebd56808d378b495870d60d" "checksum block-padding 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d75255892aeb580d3c566f213a2b6fdc1c66667839f45719ee1d30ebf2aea591" "checksum byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" "checksum byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a019b10a2a7cdeb292db131fc8113e57ea2a908f6e7894b0c3c671893b65dbeb" @@ -938,6 +1085,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum cranelift-native 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)" = "474bee81d620a473bf43411a3d6f10ffbf7965141dc5e5b76d8d2151dde3285d" "checksum cranelift-wasm 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)" = "49723365dab9a48b354bdc24cb6d9d5719bc1d3b858ffd2ea179d0d7d885804a" "checksum digest 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "05f47366984d3ad862010e22c7ce81a7dbcaebbdfb37241a620f8b6596ee135c" +"checksum either 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3be565ca5c557d7f59e7cfcf1844f9e3033650c929c6566f511e8005f205c1d0" +"checksum enum-methods 0.0.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7798e7da2d4cb0d6d6fc467e8d6b5bf247e9e989f786dde1732d79899c32bb10" "checksum errno 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "c2a071601ed01b988f896ab14b95e67335d1eeb50190932a1320f7fe3cadc84e" "checksum errno-dragonfly 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "14ca354e36190500e1e1fb267c647932382b54053c50b14970856c0b00a35067" "checksum failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "795bd83d3abeb9220f257e597aa0080a508b27533824adf336529648f6abf7e2" @@ -952,13 +1101,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum hashbrown 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "3bae29b6653b3412c2e71e9d486db9f9df5d701941d86683005efb9f2d28e3da" "checksum heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205" "checksum indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7e81a7c05f79578dbc15793d8b619db9ba32b4577003ef3af1a91c416798c58d" +"checksum inkwell 0.1.0 (git+https://github.com/TheDan64/inkwell?branch=llvm7-0)" = "" +"checksum inkwell_internal_macros 0.1.0 (git+https://github.com/TheDan64/inkwell?branch=llvm7-0)" = "" "checksum itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1306f3464951f30e30d12373d31c79fbd52d236e5e896fd92f96ec7babbbe60b" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" "checksum lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a374c89b9db55895453a74c1e38861d9deec0b01b405a82516e9d5de4820dea1" "checksum libc 0.2.48 (git+https://github.com/rust-lang/libc)" = "" "checksum libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)" = "e962c7641008ac010fa60a7dfdc1712449f29c44ef2d4702394aea943ee75047" +"checksum llvm-sys 70.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "60a9ee82fe0fa72ae6ef6d018b407296085863836451c7a97384f84ed7e26b9f" "checksum lock_api 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "62ebf1391f6acad60e5c8b43706dde4582df75c06698ab44511d15016bc2442c" "checksum log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c84ec4b527950aa83a329754b01dbe3f58361d1c5efacd1f6d68c494d08a17c6" +"checksum memchr 2.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e1dd4eaac298c32ce07eb6ed9242eda7d82955b9170b7d6db59b2e02cc63fcb8" "checksum memmap 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6585fd95e7bb50d6cc31e20d4cf9afb4e2ba16c5846fc76793f11218da9c475b" "checksum nix 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "921f61dc817b379d0834e45d5ec45beaacfae97082090a49c2cf30dcbc30206f" "checksum nix 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "46f0f3210768d796e8fa79ec70ee6af172dacbe7147f5e69be5240a47778302b" @@ -968,6 +1121,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ab41b4aed082705d1056416ae4468b6ea99d52599ecf3169b00088d43113e337" "checksum parking_lot_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "94c8c7923936b28d546dfd14d4472eaf34c99b14e1c973a32b3e6d4eb04298c9" "checksum proc-macro2 0.4.26 (registry+https://github.com/rust-lang/crates.io-index)" = "38fddd23d98b2144d197c0eca5705632d4fe2667d14a6be5df8934f8d74f1978" +"checksum quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a" "checksum quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)" = "cdd8e04bd9c52e0342b406469d494fcb033be4bdbe5c606016defbb1681411e1" "checksum rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca" "checksum rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef" @@ -983,6 +1137,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" "checksum redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)" = "423e376fffca3dfa06c9e9790a9ccd282fafb3cc6e6397d01dbf64f9bacc6b85" "checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76" +"checksum regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "37e7cbbd370869ce2e8dff25c7018702d10b21a20ef7135316f8daecd6c25b7f" +"checksum regex-syntax 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "8c2f35eedad5295fdf00a63d7d4b238135723f92b434ec06774dad15c7ab0861" "checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" "checksum ryu 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "eb9e9b8cde282a9fe6a42dd4681319bfb63f121b8a8ee9439c6f4107e58a46f7" "checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27" @@ -999,23 +1155,30 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4f380125926a99e52bc279241539c018323fab05ad6368b56f93d9369ff550" "checksum structopt 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "670ad348dc73012fcf78c71f06f9d942232cdd4c859d4b6975e27836c3efc0c3" "checksum structopt-derive 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "ef98172b1a00b0bec738508d3726540edcbd186d50dfd326f2b1febbb3559f04" +"checksum syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d3b891b9015c88c576343b9b3e41c2c11a51c219ef067b264bd9c8aa9b441dad" "checksum syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)" = "f92e629aa1d9c827b2bb8297046c1ccffc57c99b947a680d3ccff1f136a3bee9" +"checksum synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a393066ed9010ebaed60b9eafa373d4b1baac186dd7e008555b0f702b51945b6" "checksum synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "73687139bf99285483c96ac0add482c3776528beac1d97d444f6e91f203a2015" "checksum target-lexicon 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4af5e2227f0b887d591d3724b796a96eff04226104d872f5b3883fcd427d64b9" "checksum termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "689a3bdfaab439fd92bc87df5c4c78417d3cbe537487274e9b0b2dce76e92096" "checksum textwrap 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "307686869c93e71f94da64286f9a9524c0f308a9e1c87a583de8e9c9039ad3f6" +"checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b" "checksum time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "db8dcfca086c1143c9270ac42a2bbd8a7ee477b78ac8e45b19abfb0cbede4b6f" "checksum typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "612d636f949607bdf9b123b4a6f6d966dedf3ff669f7f045890d3a4a73948169" +"checksum ucd-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "535c204ee4d8434478593480b8f86ab45ec9aae0e83c568ca81abf0fd0e88f86" "checksum unicode-segmentation 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "aa6024fc12ddfd1c6dbc14a80fa2324d4568849869b779f6bd37e5e4c03344d1" "checksum unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "882386231c45df4700b275c7ff55b6f3698780a650026380e72dabe76fa46526" +"checksum unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f860d7d29cf02cb2f3f359fd35991af3d30bac52c57d265a3c461074cb4dc" "checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" "checksum unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "382810877fe448991dfc7f0dd6e3ae5d58088fd0ea5e35189655f84e6814fa56" +"checksum utf8-ranges 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "796f7e48bef87609f7ade7e06495a87d5cd06c7866e6a5cbfceffc558a243737" "checksum vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a" "checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" "checksum wabt 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)" = "74e463a508e390cc7447e70f640fbf44ad52e1bd095314ace1fdf99516d32add" "checksum wabt-sys 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)" = "a6265b25719e82598d104b3717375e37661d41753e2c84cde3f51050c7ed7e3c" "checksum wasmparser 0.22.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f46e666ecb4a406483a59a49f9d0c17f327e70da53a128eccddae2eadb95865c" "checksum wasmparser 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b5e01c420bc7d36e778bd242e1167b079562ba8b34087122cc9057187026d060" +"checksum wasmparser 0.28.0 (registry+https://github.com/rust-lang/crates.io-index)" = "40f426b1929bd26517fb10702e2a8e520d1845c49567aa4d244f426f10b206c1" "checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" "checksum winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "92c1eb33641e276cfa214a0522acad57be5c56b10cb348b3c5117db75f3ac4b0" "checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" diff --git a/Cargo.toml b/Cargo.toml index b570c9b09..77bf8a4b8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -27,7 +27,7 @@ wasmer-runtime-core = { path = "lib/runtime-core" } wasmer-emscripten = { path = "lib/emscripten" } [workspace] -members = ["lib/clif-backend", "lib/runtime", "lib/runtime-core", "lib/emscripten", "lib/spectests"] +members = ["lib/clif-backend", "lib/runtime", "lib/runtime-core", "lib/emscripten", "lib/spectests", "lib/llvm-backend"] [build-dependencies] wabt = "0.7.2" diff --git a/lib/clif-backend/src/func_env.rs b/lib/clif-backend/src/func_env.rs index 789195264..f24cfc433 100644 --- a/lib/clif-backend/src/func_env.rs +++ b/lib/clif-backend/src/func_env.rs @@ -75,7 +75,7 @@ impl<'env, 'module, 'isa> FuncEnvironment for FuncEnv<'env, 'module, 'isa> { let vmctx = func.create_global_value(ir::GlobalValueData::VMContext); let ptr_type = self.pointer_type(); - let local_global_addr = match global_index.local_or_import(self.env.module) { + let local_global_addr = match global_index.local_or_import(&self.env.module.info) { LocalOrImport::Local(local_global_index) => { let globals_base_addr = func.create_global_value(ir::GlobalValueData::Load { base: vmctx, @@ -145,48 +145,49 @@ impl<'env, 'module, 'isa> FuncEnvironment for FuncEnv<'env, 'module, 'isa> { let vmctx = func.create_global_value(ir::GlobalValueData::VMContext); let ptr_type = self.pointer_type(); - let (local_memory_ptr_ptr, description) = match mem_index.local_or_import(self.env.module) { - LocalOrImport::Local(local_mem_index) => { - let memories_base_addr = func.create_global_value(ir::GlobalValueData::Load { - base: vmctx, - offset: (vm::Ctx::offset_memories() as i32).into(), - global_type: ptr_type, - readonly: true, - }); - - let local_memory_ptr_offset = - local_mem_index.index() * mem::size_of::<*mut vm::LocalMemory>(); - - ( - func.create_global_value(ir::GlobalValueData::IAddImm { - base: memories_base_addr, - offset: (local_memory_ptr_offset as i64).into(), + let (local_memory_ptr_ptr, description) = + match mem_index.local_or_import(&self.env.module.info) { + LocalOrImport::Local(local_mem_index) => { + let memories_base_addr = func.create_global_value(ir::GlobalValueData::Load { + base: vmctx, + offset: (vm::Ctx::offset_memories() as i32).into(), global_type: ptr_type, - }), - self.env.module.info.memories[local_mem_index], - ) - } - LocalOrImport::Import(import_mem_index) => { - let memories_base_addr = func.create_global_value(ir::GlobalValueData::Load { - base: vmctx, - offset: (vm::Ctx::offset_imported_memories() as i32).into(), - global_type: ptr_type, - readonly: true, - }); + readonly: true, + }); - let local_memory_ptr_offset = - import_mem_index.index() * mem::size_of::<*mut vm::LocalMemory>(); + let local_memory_ptr_offset = + local_mem_index.index() * mem::size_of::<*mut vm::LocalMemory>(); - ( - func.create_global_value(ir::GlobalValueData::IAddImm { - base: memories_base_addr, - offset: (local_memory_ptr_offset as i64).into(), + ( + func.create_global_value(ir::GlobalValueData::IAddImm { + base: memories_base_addr, + offset: (local_memory_ptr_offset as i64).into(), + global_type: ptr_type, + }), + self.env.module.info.memories[local_mem_index], + ) + } + LocalOrImport::Import(import_mem_index) => { + let memories_base_addr = func.create_global_value(ir::GlobalValueData::Load { + base: vmctx, + offset: (vm::Ctx::offset_imported_memories() as i32).into(), global_type: ptr_type, - }), - self.env.module.info.imported_memories[import_mem_index].1, - ) - } - }; + readonly: true, + }); + + let local_memory_ptr_offset = + import_mem_index.index() * mem::size_of::<*mut vm::LocalMemory>(); + + ( + func.create_global_value(ir::GlobalValueData::IAddImm { + base: memories_base_addr, + offset: (local_memory_ptr_offset as i64).into(), + global_type: ptr_type, + }), + self.env.module.info.imported_memories[import_mem_index].1, + ) + } + }; let (local_memory_ptr, local_memory_base) = { let local_memory_ptr = func.create_global_value(ir::GlobalValueData::Load { @@ -253,7 +254,8 @@ impl<'env, 'module, 'isa> FuncEnvironment for FuncEnv<'env, 'module, 'isa> { let vmctx = func.create_global_value(ir::GlobalValueData::VMContext); let ptr_type = self.pointer_type(); - let (table_struct_ptr_ptr, description) = match table_index.local_or_import(self.env.module) + let (table_struct_ptr_ptr, description) = match table_index + .local_or_import(&self.env.module.info) { LocalOrImport::Local(local_table_index) => { let tables_base = func.create_global_value(ir::GlobalValueData::Load { @@ -476,7 +478,7 @@ impl<'env, 'module, 'isa> FuncEnvironment for FuncEnv<'env, 'module, 'isa> { ) -> cranelift_wasm::WasmResult { let callee_index: FuncIndex = Converter(clif_callee_index).into(); - match callee_index.local_or_import(self.env.module) { + match callee_index.local_or_import(&self.env.module.info) { LocalOrImport::Local(_) => { // this is an internal function let vmctx = pos @@ -568,18 +570,19 @@ impl<'env, 'module, 'isa> FuncEnvironment for FuncEnv<'env, 'module, 'isa> { let mem_index: MemoryIndex = Converter(clif_mem_index).into(); - let (namespace, mem_index, description) = match mem_index.local_or_import(self.env.module) { - LocalOrImport::Local(local_mem_index) => ( - call_names::LOCAL_NAMESPACE, - local_mem_index.index(), - self.env.module.info.memories[local_mem_index], - ), - LocalOrImport::Import(import_mem_index) => ( - call_names::IMPORT_NAMESPACE, - import_mem_index.index(), - self.env.module.info.imported_memories[import_mem_index].1, - ), - }; + let (namespace, mem_index, description) = + match mem_index.local_or_import(&self.env.module.info) { + LocalOrImport::Local(local_mem_index) => ( + call_names::LOCAL_NAMESPACE, + local_mem_index.index(), + self.env.module.info.memories[local_mem_index], + ), + LocalOrImport::Import(import_mem_index) => ( + call_names::IMPORT_NAMESPACE, + import_mem_index.index(), + self.env.module.info.imported_memories[import_mem_index].1, + ), + }; let name_index = match description.memory_type() { MemoryType::Dynamic => call_names::DYNAMIC_MEM_GROW, @@ -631,18 +634,19 @@ impl<'env, 'module, 'isa> FuncEnvironment for FuncEnv<'env, 'module, 'isa> { let mem_index: MemoryIndex = Converter(clif_mem_index).into(); - let (namespace, mem_index, description) = match mem_index.local_or_import(self.env.module) { - LocalOrImport::Local(local_mem_index) => ( - call_names::LOCAL_NAMESPACE, - local_mem_index.index(), - self.env.module.info.memories[local_mem_index], - ), - LocalOrImport::Import(import_mem_index) => ( - call_names::IMPORT_NAMESPACE, - import_mem_index.index(), - self.env.module.info.imported_memories[import_mem_index].1, - ), - }; + let (namespace, mem_index, description) = + match mem_index.local_or_import(&self.env.module.info) { + LocalOrImport::Local(local_mem_index) => ( + call_names::LOCAL_NAMESPACE, + local_mem_index.index(), + self.env.module.info.memories[local_mem_index], + ), + LocalOrImport::Import(import_mem_index) => ( + call_names::IMPORT_NAMESPACE, + import_mem_index.index(), + self.env.module.info.imported_memories[import_mem_index].1, + ), + }; let name_index = match description.memory_type() { MemoryType::Dynamic => call_names::DYNAMIC_MEM_SIZE, diff --git a/lib/clif-backend/src/module_env.rs b/lib/clif-backend/src/module_env.rs index de625cc23..9ff85dcf3 100644 --- a/lib/clif-backend/src/module_env.rs +++ b/lib/clif-backend/src/module_env.rs @@ -136,7 +136,7 @@ impl<'module, 'isa, 'data> ModuleEnvironment<'data> for ModuleEnv<'module, 'isa> // assert!(!desc.mutable); let global_index: GlobalIndex = Converter(global_index).into(); let imported_global_index = global_index - .local_or_import(self.module) + .local_or_import(&self.module.info) .import() .expect("invalid global initializer when declaring an imported global"); Initializer::GetGlobal(imported_global_index) @@ -246,7 +246,7 @@ impl<'module, 'isa, 'data> ModuleEnvironment<'data> for ModuleEnv<'module, 'isa> let base = match base { Some(global_index) => { let global_index: GlobalIndex = Converter(global_index).into(); - Initializer::GetGlobal(match global_index.local_or_import(self.module) { + Initializer::GetGlobal(match global_index.local_or_import(&self.module.info) { LocalOrImport::Import(imported_global_index) => imported_global_index, LocalOrImport::Local(_) => { panic!("invalid global initializer when declaring an imported global") @@ -316,7 +316,7 @@ impl<'module, 'isa, 'data> ModuleEnvironment<'data> for ModuleEnv<'module, 'isa> let base = match base { Some(global_index) => { let global_index: GlobalIndex = Converter(global_index).into(); - Initializer::GetGlobal(match global_index.local_or_import(self.module) { + Initializer::GetGlobal(match global_index.local_or_import(&self.module.info) { LocalOrImport::Import(imported_global_index) => imported_global_index, LocalOrImport::Local(_) => { panic!("invalid global initializer when declaring an imported global") diff --git a/lib/clif-backend/src/signal/mod.rs b/lib/clif-backend/src/signal/mod.rs index 0767f9527..1ff73e055 100644 --- a/lib/clif-backend/src/signal/mod.rs +++ b/lib/clif-backend/src/signal/mod.rs @@ -148,7 +148,7 @@ fn get_func_from_index<'a>( .get(func_index) .expect("broken invariant, incorrect func index"); - let (func_ptr, ctx) = match func_index.local_or_import(module) { + let (func_ptr, ctx) = match func_index.local_or_import(&module.info) { LocalOrImport::Local(local_func_index) => ( module .func_resolver diff --git a/lib/llvm-backend/.llvmenv b/lib/llvm-backend/.llvmenv new file mode 100644 index 000000000..6d1e3080f --- /dev/null +++ b/lib/llvm-backend/.llvmenv @@ -0,0 +1 @@ +/usr/local/opt/llvm/bin \ No newline at end of file diff --git a/lib/llvm-backend/Cargo.toml b/lib/llvm-backend/Cargo.toml new file mode 100644 index 000000000..000265b7d --- /dev/null +++ b/lib/llvm-backend/Cargo.toml @@ -0,0 +1,17 @@ +[package] +name = "llvm-backend" +version = "0.1.0" +authors = ["Lachlan Sneff "] +edition = "2018" + +[dependencies] +wasmer-runtime-core = { path = "../runtime-core", version = "0.1.2" } +wasmparser = "0.28.0" +inkwell = { git = "https://github.com/TheDan64/inkwell", branch = "llvm7-0" } +hashbrown = "0.1.8" + +[dev-dependencies] +wabt = "0.7.4" + +[features] +debug = ["wasmer-runtime-core/debug"] \ No newline at end of file diff --git a/lib/llvm-backend/src/code.rs b/lib/llvm-backend/src/code.rs new file mode 100644 index 000000000..50a31065a --- /dev/null +++ b/lib/llvm-backend/src/code.rs @@ -0,0 +1,765 @@ +use hashbrown::HashMap; +use inkwell::{ + basic_block::BasicBlock, + builder::Builder, + context::Context, + module::Module, + types::{BasicType, BasicTypeEnum, FunctionType}, + values::{AggregateValue, BasicValue, BasicValueEnum, FunctionValue}, + IntPredicate, +}; +use wasmer_runtime_core::{ + module::ModuleInfo, + structures::{Map, SliceMap, TypedIndex}, + types::{FuncIndex, FuncSig, LocalFuncIndex, LocalOrImport, SigIndex, Type}, +}; +use wasmparser::{BinaryReaderError, CodeSectionReader, LocalsReader, Operator, OperatorsReader}; + +use crate::intrinsics::Intrinsics; +use crate::read_info::type_to_type; +use crate::state::State; + +fn func_sig_to_llvm(context: &Context, sig: &FuncSig) -> FunctionType { + let param_types: Vec<_> = sig + .params() + .iter() + .map(|&ty| type_to_llvm(context, ty)) + .collect(); + + match sig.returns() { + [] => context.void_type().fn_type(¶m_types, false), + [single_value] => type_to_llvm(context, *single_value).fn_type(¶m_types, false), + returns @ _ => { + let basic_types: Vec<_> = returns + .iter() + .map(|&ty| type_to_llvm(context, ty)) + .collect(); + + context + .struct_type(&basic_types, false) + .fn_type(¶m_types, false) + } + } +} + +fn type_to_llvm(context: &Context, ty: Type) -> BasicTypeEnum { + match ty { + Type::I32 => context.i32_type().as_basic_type_enum(), + Type::I64 => context.i64_type().as_basic_type_enum(), + Type::F32 => context.f32_type().as_basic_type_enum(), + Type::F64 => context.f64_type().as_basic_type_enum(), + } +} + +pub fn parse_function_bodies( + info: &ModuleInfo, + code_reader: CodeSectionReader, +) -> Result<(), BinaryReaderError> { + let context = Context::create(); + let module = context.create_module("module"); + let builder = context.create_builder(); + + let intrinsics = Intrinsics::declare(&module, &context); + + let signatures: Map = info + .signatures + .iter() + .map(|(_, sig)| func_sig_to_llvm(&context, sig)) + .collect(); + let functions: Map = info + .func_assoc + .iter() + .skip(info.imported_functions.len()) + .map(|(func_index, &sig_index)| { + module.add_function( + &format!("fn:{}", func_index.index()), + signatures[sig_index], + None, + ) + }) + .collect(); + + for (local_func_index, body) in code_reader.into_iter().enumerate() { + let body = body?; + + let locals_reader = body.get_locals_reader()?; + let op_reader = body.get_operators_reader()?; + + parse_function( + &context, + &module, + &builder, + &intrinsics, + info, + &signatures, + &functions, + LocalFuncIndex::new(local_func_index), + locals_reader, + op_reader, + )?; + } + + Ok(()) +} + +fn parse_function( + context: &Context, + module: &Module, + builder: &Builder, + intrinsics: &Intrinsics, + info: &ModuleInfo, + signatures: &SliceMap, + functions: &SliceMap, + func_index: LocalFuncIndex, + locals_reader: LocalsReader, + op_reader: OperatorsReader, +) -> Result<(), BinaryReaderError> { + let llvm_sig = &signatures[info.func_assoc[func_index.convert_up(info)]]; + + let function = functions[func_index]; + let entry_block = context.append_basic_block(&function, "entry"); + builder.position_at_end(&entry_block); + + let mut state = State::new(); + + let mut locals = Vec::with_capacity(locals_reader.get_count() as usize); + locals.extend(function.get_param_iter().enumerate().map(|(index, param)| { + let ty = param.get_type(); + + let alloca = builder.build_alloca(ty, &state.var_name()); + builder.build_store(alloca, param); + alloca + })); + + for (index, local) in locals_reader.into_iter().enumerate().skip(locals.len()) { + let (_, ty) = local?; + + let wasmer_ty = type_to_type(ty)?; + + let ty = type_to_llvm(context, wasmer_ty); + + let alloca = builder.build_alloca(ty, &state.var_name()); + + let default_value = match wasmer_ty { + Type::I32 => context.i32_type().const_int(0, false).as_basic_value_enum(), + Type::I64 => context.i64_type().const_int(0, false).as_basic_value_enum(), + Type::F32 => context.f32_type().const_float(0.0).as_basic_value_enum(), + Type::F64 => context.f64_type().const_float(0.0).as_basic_value_enum(), + }; + + builder.build_store(alloca, default_value); + + locals.push(alloca); + } + + for op in op_reader { + match op? { + /*************************** + * Basic instructions. + * https://github.com/sunfishcode/wasm-reference-manual/blob/master/WebAssembly.md#basic-instructions + ***************************/ + Operator::Nop => { + // Do nothing. + } + Operator::Drop => { + state.pop1()?; + } + + // Generate const values. + Operator::I32Const { value } => { + let i = context.i32_type().const_int(value as u64, false); + state.push1(i); + } + Operator::I64Const { value } => { + let i = context.i64_type().const_int(value as u64, false); + state.push1(i); + } + Operator::F32Const { value } => { + let f = context + .f32_type() + .const_float(f64::from_bits(value.bits() as u64)); + state.push1(f); + } + Operator::F64Const { value } => { + let f = context.f64_type().const_float(f64::from_bits(value.bits())); + state.push1(f); + } + + // Operate on locals. + Operator::GetLocal { local_index } => { + let pointer_value = locals[local_index as usize]; + let v = builder.build_load(pointer_value, &state.var_name()); + state.push1(v); + } + Operator::SetLocal { local_index } => { + let pointer_value = locals[local_index as usize]; + let v = state.pop1()?; + builder.build_store(pointer_value, v); + } + Operator::TeeLocal { local_index } => { + let pointer_value = locals[local_index as usize]; + let v = state.peek1()?; + builder.build_store(pointer_value, v); + } + + Operator::GetGlobal { global_index } => unimplemented!(), + Operator::SetGlobal { global_index } => unimplemented!(), + + Operator::Select => { + let (v1, v2, cond) = state.pop3()?; + let cond = cond.into_int_value(); + let res = builder.build_select(cond, v1, v2, &state.var_name()); + state.push1(res); + } + Operator::Call { function_index } => { + let func_index = FuncIndex::new(function_index as usize); + let sigindex = info.func_assoc[func_index]; + let llvm_sig = signatures[sigindex]; + + match func_index.local_or_import(info) { + LocalOrImport::Local(local_func_index) => { + let func_sig = &info.signatures[sigindex]; + let func_value = functions[local_func_index]; + let call_site = builder.build_call( + func_value, + &state.peekn(func_sig.params().len())?.to_vec(), + &state.var_name(), + ); + if let Some(basic_value) = call_site.try_as_basic_value().left() { + match func_sig.returns().len() { + 1 => state.push1(basic_value), + count @ _ => { + // This is a multi-value return. + let struct_value = basic_value.into_struct_value(); + for i in 0..(count as u32) { + let value = builder.build_extract_value( + struct_value, + i, + &state.var_name(), + ); + state.push1(value); + } + } + } + } + } + LocalOrImport::Import(import_func_index) => { + // unimplemented!() + } + } + } + Operator::CallIndirect { index, table_index } => { + unimplemented!("{}, {}", index, table_index); + } + + /*************************** + * Integer Arithmetic instructions. + * https://github.com/sunfishcode/wasm-reference-manual/blob/master/WebAssembly.md#integer-arithmetic-instructions + ***************************/ + Operator::I32Add | Operator::I64Add => { + let (v1, v2) = state.pop2()?; + let (v1, v2) = (v1.into_int_value(), v2.into_int_value()); + let res = builder.build_int_add(v1, v2, &state.var_name()); + state.push1(res); + } + Operator::I32Sub | Operator::I64Sub => { + let (v1, v2) = state.pop2()?; + let (v1, v2) = (v1.into_int_value(), v2.into_int_value()); + let res = builder.build_int_sub(v1, v2, &state.var_name()); + state.push1(res); + } + Operator::I32Mul | Operator::I64Mul => { + let (v1, v2) = state.pop2()?; + let (v1, v2) = (v1.into_int_value(), v2.into_int_value()); + let res = builder.build_int_mul(v1, v2, &state.var_name()); + state.push1(res); + } + Operator::I32DivS | Operator::I64DivS => { + let (v1, v2) = state.pop2()?; + let (v1, v2) = (v1.into_int_value(), v2.into_int_value()); + let res = builder.build_int_signed_div(v1, v2, &state.var_name()); + state.push1(res); + } + Operator::I32DivU | Operator::I64DivU => { + let (v1, v2) = state.pop2()?; + let (v1, v2) = (v1.into_int_value(), v2.into_int_value()); + let res = builder.build_int_unsigned_div(v1, v2, &state.var_name()); + state.push1(res); + } + Operator::I32RemS | Operator::I64RemS => { + let (v1, v2) = state.pop2()?; + let (v1, v2) = (v1.into_int_value(), v2.into_int_value()); + let res = builder.build_int_signed_rem(v1, v2, &state.var_name()); + state.push1(res); + } + Operator::I32RemU | Operator::I64RemU => { + let (v1, v2) = state.pop2()?; + let (v1, v2) = (v1.into_int_value(), v2.into_int_value()); + let res = builder.build_int_unsigned_rem(v1, v2, &state.var_name()); + state.push1(res); + } + Operator::I32And | Operator::I64And => { + let (v1, v2) = state.pop2()?; + let (v1, v2) = (v1.into_int_value(), v2.into_int_value()); + let res = builder.build_and(v1, v2, &state.var_name()); + state.push1(res); + } + Operator::I32Or | Operator::I64Or => { + let (v1, v2) = state.pop2()?; + let (v1, v2) = (v1.into_int_value(), v2.into_int_value()); + let res = builder.build_or(v1, v2, &state.var_name()); + state.push1(res); + } + Operator::I32Xor | Operator::I64Xor => { + let (v1, v2) = state.pop2()?; + let (v1, v2) = (v1.into_int_value(), v2.into_int_value()); + let res = builder.build_xor(v1, v2, &state.var_name()); + state.push1(res); + } + Operator::I32Shl | Operator::I64Shl => { + let (v1, v2) = state.pop2()?; + let (v1, v2) = (v1.into_int_value(), v2.into_int_value()); + let res = builder.build_left_shift(v1, v2, &state.var_name()); + state.push1(res); + } + Operator::I32ShrS | Operator::I64ShrS => { + let (v1, v2) = state.pop2()?; + let (v1, v2) = (v1.into_int_value(), v2.into_int_value()); + let res = builder.build_right_shift(v1, v2, true, &state.var_name()); + state.push1(res); + } + Operator::I32ShrU | Operator::I64ShrU => { + let (v1, v2) = state.pop2()?; + let (v1, v2) = (v1.into_int_value(), v2.into_int_value()); + let res = builder.build_right_shift(v1, v2, false, &state.var_name()); + state.push1(res); + } + Operator::I32Rotl => { + let (v1, v2) = state.pop2()?; + let (v1, v2) = (v1.into_int_value(), v2.into_int_value()); + let lhs = builder.build_left_shift(v1, v2, &state.var_name()); + let rhs = { + let int_width = context.i32_type().const_int(32 as u64, false); + let rhs = builder.build_int_sub(int_width, v2, &state.var_name()); + builder.build_right_shift(v1, rhs, false, &state.var_name()) + }; + let res = builder.build_or(lhs, rhs, &state.var_name()); + state.push1(res); + } + Operator::I64Rotl => { + let (v1, v2) = state.pop2()?; + let (v1, v2) = (v1.into_int_value(), v2.into_int_value()); + let lhs = builder.build_left_shift(v1, v2, &state.var_name()); + let rhs = { + let int_width = context.i64_type().const_int(64 as u64, false); + let rhs = builder.build_int_sub(int_width, v2, &state.var_name()); + builder.build_right_shift(v1, rhs, false, &state.var_name()) + }; + let res = builder.build_or(lhs, rhs, &state.var_name()); + state.push1(res); + } + Operator::I32Rotr => { + let (v1, v2) = state.pop2()?; + let (v1, v2) = (v1.into_int_value(), v2.into_int_value()); + let lhs = builder.build_right_shift(v1, v2, false, &state.var_name()); + let rhs = { + let int_width = context.i32_type().const_int(32 as u64, false); + let rhs = builder.build_int_sub(int_width, v2, &state.var_name()); + builder.build_left_shift(v1, rhs, &state.var_name()) + }; + let res = builder.build_or(lhs, rhs, &state.var_name()); + state.push1(res); + } + Operator::I64Rotr => { + let (v1, v2) = state.pop2()?; + let (v1, v2) = (v1.into_int_value(), v2.into_int_value()); + let lhs = builder.build_right_shift(v1, v2, false, &state.var_name()); + let rhs = { + let int_width = context.i64_type().const_int(64 as u64, false); + let rhs = builder.build_int_sub(int_width, v2, &state.var_name()); + builder.build_left_shift(v1, rhs, &state.var_name()) + }; + let res = builder.build_or(lhs, rhs, &state.var_name()); + state.push1(res); + } + Operator::I32Clz => { + let input = state.pop1()?; + let ensure_defined_zero = context + .bool_type() + .const_int(1 as u64, false) + .as_basic_value_enum(); + let res = builder + .build_call( + intrinsics.ctlz_i32, + &[input, ensure_defined_zero], + &state.var_name(), + ) + .try_as_basic_value() + .left() + .unwrap(); + state.push1(res); + } + Operator::I64Clz => { + let input = state.pop1()?; + let ensure_defined_zero = context + .bool_type() + .const_int(1 as u64, false) + .as_basic_value_enum(); + let res = builder + .build_call( + intrinsics.ctlz_i64, + &[input, ensure_defined_zero], + &state.var_name(), + ) + .try_as_basic_value() + .left() + .unwrap(); + state.push1(res); + } + Operator::I32Ctz => { + let input = state.pop1()?; + let ensure_defined_zero = context + .bool_type() + .const_int(1 as u64, false) + .as_basic_value_enum(); + let res = builder + .build_call( + intrinsics.cttz_i32, + &[input, ensure_defined_zero], + &state.var_name(), + ) + .try_as_basic_value() + .left() + .unwrap(); + state.push1(res); + } + Operator::I64Ctz => { + let input = state.pop1()?; + let ensure_defined_zero = context + .bool_type() + .const_int(1 as u64, false) + .as_basic_value_enum(); + let res = builder + .build_call( + intrinsics.cttz_i64, + &[input, ensure_defined_zero], + &state.var_name(), + ) + .try_as_basic_value() + .left() + .unwrap(); + state.push1(res); + } + Operator::I32Popcnt => { + let input = state.pop1()?; + let res = builder + .build_call(intrinsics.ctpop_i32, &[input], &state.var_name()) + .try_as_basic_value() + .left() + .unwrap(); + state.push1(res); + } + Operator::I64Popcnt => { + let input = state.pop1()?; + let res = builder + .build_call(intrinsics.ctpop_i64, &[input], &state.var_name()) + .try_as_basic_value() + .left() + .unwrap(); + state.push1(res); + } + Operator::I32Eqz => { + let input = state.pop1()?.into_int_value(); + let zero = context.i32_type().const_int(0, false); + let res = + builder.build_int_compare(IntPredicate::EQ, input, zero, &state.var_name()); + state.push1(res); + } + Operator::I64Eqz => { + let input = state.pop1()?.into_int_value(); + let zero = context.i64_type().const_int(0, false); + let res = + builder.build_int_compare(IntPredicate::EQ, input, zero, &state.var_name()); + state.push1(res); + } + + /*************************** + * Floating-Point Arithmetic instructions. + * https://github.com/sunfishcode/wasm-reference-manual/blob/master/WebAssembly.md#floating-point-arithmetic-instructions + ***************************/ + Operator::F32Add | Operator::F64Add => { + let (v1, v2) = state.pop2()?; + let (v1, v2) = (v1.into_float_value(), v2.into_float_value()); + let res = builder.build_float_add(v1, v2, &state.var_name()); + state.push1(res); + } + Operator::F32Sub | Operator::F32Sub => { + let (v1, v2) = state.pop2()?; + let (v1, v2) = (v1.into_float_value(), v2.into_float_value()); + let res = builder.build_float_sub(v1, v2, &state.var_name()); + state.push1(res); + } + Operator::F32Mul | Operator::F64Mul => { + let (v1, v2) = state.pop2()?; + let (v1, v2) = (v1.into_float_value(), v2.into_float_value()); + let res = builder.build_float_mul(v1, v2, &state.var_name()); + state.push1(res); + } + Operator::F32Div | Operator::F64Div => { + let (v1, v2) = state.pop2()?; + let (v1, v2) = (v1.into_float_value(), v2.into_float_value()); + let res = builder.build_float_div(v1, v2, &state.var_name()); + state.push1(res); + } + Operator::F32Sqrt => { + let input = state.pop1()?; + let res = builder + .build_call(intrinsics.sqrt_f32, &[input], &state.var_name()) + .try_as_basic_value() + .left() + .unwrap(); + state.push1(res); + } + Operator::F64Sqrt => { + let input = state.pop1()?; + let res = builder + .build_call(intrinsics.sqrt_f64, &[input], &state.var_name()) + .try_as_basic_value() + .left() + .unwrap(); + state.push1(res); + } + Operator::F32Min => { + let (v1, v2) = state.pop2()?; + let res = builder + .build_call(intrinsics.minimum_f32, &[v1, v2], &state.var_name()) + .try_as_basic_value() + .left() + .unwrap(); + state.push1(res); + } + Operator::F64Min => { + let (v1, v2) = state.pop2()?; + let res = builder + .build_call(intrinsics.minimum_f64, &[v1, v2], &state.var_name()) + .try_as_basic_value() + .left() + .unwrap(); + state.push1(res); + } + Operator::F32Max => { + let (v1, v2) = state.pop2()?; + let res = builder + .build_call(intrinsics.maximum_f32, &[v1, v2], &state.var_name()) + .try_as_basic_value() + .left() + .unwrap(); + state.push1(res); + } + Operator::F64Max => { + let (v1, v2) = state.pop2()?; + let res = builder + .build_call(intrinsics.maximum_f64, &[v1, v2], &state.var_name()) + .try_as_basic_value() + .left() + .unwrap(); + state.push1(res); + } + Operator::F32Ceil => { + let input = state.pop1()?; + let res = builder + .build_call(intrinsics.ceil_f32, &[input], &state.var_name()) + .try_as_basic_value() + .left() + .unwrap(); + state.push1(res); + } + Operator::F64Ceil => { + let input = state.pop1()?; + let res = builder + .build_call(intrinsics.ceil_f64, &[input], &state.var_name()) + .try_as_basic_value() + .left() + .unwrap(); + state.push1(res); + } + Operator::F32Floor => { + let input = state.pop1()?; + let res = builder + .build_call(intrinsics.floor_f32, &[input], &state.var_name()) + .try_as_basic_value() + .left() + .unwrap(); + state.push1(res); + } + Operator::F64Floor => { + let input = state.pop1()?; + let res = builder + .build_call(intrinsics.floor_f64, &[input], &state.var_name()) + .try_as_basic_value() + .left() + .unwrap(); + state.push1(res); + } + Operator::F32Trunc => { + let input = state.pop1()?; + let res = builder + .build_call(intrinsics.trunc_f32, &[input], &state.var_name()) + .try_as_basic_value() + .left() + .unwrap(); + state.push1(res); + } + Operator::F64Trunc => { + let input = state.pop1()?; + let res = builder + .build_call(intrinsics.trunc_f64, &[input], &state.var_name()) + .try_as_basic_value() + .left() + .unwrap(); + state.push1(res); + } + Operator::F32Nearest => { + let input = state.pop1()?; + let res = builder + .build_call(intrinsics.nearbyint_f32, &[input], &state.var_name()) + .try_as_basic_value() + .left() + .unwrap(); + state.push1(res); + } + Operator::F64Nearest => { + let input = state.pop1()?; + let res = builder + .build_call(intrinsics.nearbyint_f64, &[input], &state.var_name()) + .try_as_basic_value() + .left() + .unwrap(); + state.push1(res); + } + Operator::F32Abs => { + let input = state.pop1()?; + let res = builder + .build_call(intrinsics.fabs_f32, &[input], &state.var_name()) + .try_as_basic_value() + .left() + .unwrap(); + state.push1(res); + } + Operator::F64Abs => { + let input = state.pop1()?; + let res = builder + .build_call(intrinsics.fabs_f64, &[input], &state.var_name()) + .try_as_basic_value() + .left() + .unwrap(); + state.push1(res); + } + Operator::F32Neg | Operator::F64Neg => { + let input = state.pop1()?.into_float_value(); + let res = builder.build_float_neg(input, &state.var_name()); + state.push1(res); + } + Operator::F32Copysign => { + let input = state.pop1()?; + let res = builder + .build_call(intrinsics.copysign_f32, &[input], &state.var_name()) + .try_as_basic_value() + .left() + .unwrap(); + state.push1(res); + } + Operator::F64Copysign => { + let input = state.pop1()?; + let res = builder + .build_call(intrinsics.copysign_f64, &[input], &state.var_name()) + .try_as_basic_value() + .left() + .unwrap(); + state.push1(res); + } + + /*************************** + * Integer Comparison instructions. + * https://github.com/sunfishcode/wasm-reference-manual/blob/master/WebAssembly.md#integer-comparison-instructions + ***************************/ + Operator::I32Eq | Operator::I64Eq => { + let (v1, v2) = state.pop2()?; + let (v1, v2) = (v1.into_int_value(), v2.into_int_value()); + let res = builder.build_int_compare(IntPredicate::EQ, v1, v2, &state.var_name()); + state.push1(res); + } + Operator::I32Ne | Operator::I64Ne => { + let (v1, v2) = state.pop2()?; + let (v1, v2) = (v1.into_int_value(), v2.into_int_value()); + let res = builder.build_int_compare(IntPredicate::NE, v1, v2, &state.var_name()); + state.push1(res); + } + Operator::I32LtS | Operator::I64LtS => { + let (v1, v2) = state.pop2()?; + let (v1, v2) = (v1.into_int_value(), v2.into_int_value()); + let res = builder.build_int_compare(IntPredicate::SLT, v1, v2, &state.var_name()); + state.push1(res); + } + Operator::I32LtU | Operator::I64LtU => { + let (v1, v2) = state.pop2()?; + let (v1, v2) = (v1.into_int_value(), v2.into_int_value()); + let res = builder.build_int_compare(IntPredicate::ULT, v1, v2, &state.var_name()); + state.push1(res); + } + Operator::I32LeS | Operator::I64LeS => { + let (v1, v2) = state.pop2()?; + let (v1, v2) = (v1.into_int_value(), v2.into_int_value()); + let res = builder.build_int_compare(IntPredicate::SLE, v1, v2, &state.var_name()); + state.push1(res); + } + Operator::I32LeU | Operator::I64LeU => { + let (v1, v2) = state.pop2()?; + let (v1, v2) = (v1.into_int_value(), v2.into_int_value()); + let res = builder.build_int_compare(IntPredicate::ULE, v1, v2, &state.var_name()); + state.push1(res); + } + Operator::I32GtS | Operator::I64GtS => { + let (v1, v2) = state.pop2()?; + let (v1, v2) = (v1.into_int_value(), v2.into_int_value()); + let res = builder.build_int_compare(IntPredicate::SGT, v1, v2, &state.var_name()); + state.push1(res); + } + Operator::I32GtU | Operator::I64GtU => { + let (v1, v2) = state.pop2()?; + let (v1, v2) = (v1.into_int_value(), v2.into_int_value()); + let res = builder.build_int_compare(IntPredicate::UGT, v1, v2, &state.var_name()); + state.push1(res); + } + Operator::I32GeS | Operator::I64GeS => { + let (v1, v2) = state.pop2()?; + let (v1, v2) = (v1.into_int_value(), v2.into_int_value()); + let res = builder.build_int_compare(IntPredicate::SGE, v1, v2, &state.var_name()); + state.push1(res); + } + Operator::I32GeU | Operator::I64GeU => { + let (v1, v2) = state.pop2()?; + let (v1, v2) = (v1.into_int_value(), v2.into_int_value()); + let res = builder.build_int_compare(IntPredicate::UGE, v1, v2, &state.var_name()); + state.push1(res); + } + + /*************************** + * Floating-Point Comparison instructions. + * https://github.com/sunfishcode/wasm-reference-manual/blob/master/WebAssembly.md#floating-point-comparison-instructions + ***************************/ + Operator::Unreachable => { + // Emit an unreachable instruction. + // If llvm cannot prove that this is never touched, + // it will emit a `ud2` instruction on x86_64 arches. + builder.build_unreachable(); + } + op @ _ => { + println!("{}", module.print_to_string().to_string()); + unimplemented!("{:?}", op); + } + } + } + + Ok(()) +} diff --git a/lib/llvm-backend/src/example.rs b/lib/llvm-backend/src/example.rs new file mode 100644 index 000000000..5ce3c9a5f --- /dev/null +++ b/lib/llvm-backend/src/example.rs @@ -0,0 +1,61 @@ +use inkwell::OptimizationLevel; +use inkwell::builder::Builder; +use inkwell::context::Context; +use inkwell::execution_engine::{ExecutionEngine, JitFunction}; +use inkwell::module::Module; +use inkwell::targets::{InitializationConfig, Target}; +use std::error::Error; + +/// Convenience type alias for the `sum` function. +/// +/// Calling this is innately `unsafe` because there's no guarantee it doesn't +/// do `unsafe` operations internally. +type SumFunc = unsafe extern "C" fn(u64, u64, u64) -> u64; + +#[test] +fn test_sum() -> Result<(), Box> { + let context = Context::create(); + let module = context.create_module("sum"); + let builder = context.create_builder(); + let execution_engine = module.create_jit_execution_engine(OptimizationLevel::Aggressive)?; + + let sum = jit_compile_sum(&context, &module, &builder, &execution_engine) + .ok_or("Unable to JIT compile `sum`")?; + + let x = 1u64; + let y = 2u64; + let z = 3u64; + + unsafe { + println!("{} + {} + {} = {}", x, y, z, sum.call(x, y, z)); + assert_eq!(sum.call(x, y, z), x + y + z); + } + + Ok(()) +} + +fn jit_compile_sum( + context: &Context, + module: &Module, + builder: &Builder, + execution_engine: &ExecutionEngine, +) -> Option> { + let i64_type = context.i64_type(); + let fn_type = i64_type.fn_type(&[i64_type.into(), i64_type.into(), i64_type.into()], false); + + let function = module.add_function("sum", fn_type, None); + let basic_block = context.append_basic_block(&function, "entry"); + + builder.position_at_end(&basic_block); + + let x = function.get_nth_param(0)?.into_int_value(); + let y = function.get_nth_param(1)?.into_int_value(); + let z = function.get_nth_param(2)?.into_int_value(); + + let sum = builder.build_int_add(x, y, "sum"); + let sum = builder.build_int_add(sum, z, "sum"); + + builder.build_return(Some(&sum)); + + unsafe { execution_engine.get_function("sum").ok() } +} diff --git a/lib/llvm-backend/src/intrinsics.rs b/lib/llvm-backend/src/intrinsics.rs new file mode 100644 index 000000000..824317e8e --- /dev/null +++ b/lib/llvm-backend/src/intrinsics.rs @@ -0,0 +1,99 @@ +use inkwell::{context::Context, module::Module, types::BasicType, values::FunctionValue}; + +pub struct Intrinsics { + pub ctlz_i32: FunctionValue, + pub ctlz_i64: FunctionValue, + + pub cttz_i32: FunctionValue, + pub cttz_i64: FunctionValue, + + pub ctpop_i32: FunctionValue, + pub ctpop_i64: FunctionValue, + + pub sqrt_f32: FunctionValue, + pub sqrt_f64: FunctionValue, + + pub minimum_f32: FunctionValue, + pub minimum_f64: FunctionValue, + + pub maximum_f32: FunctionValue, + pub maximum_f64: FunctionValue, + + pub ceil_f32: FunctionValue, + pub ceil_f64: FunctionValue, + + pub floor_f32: FunctionValue, + pub floor_f64: FunctionValue, + + pub trunc_f32: FunctionValue, + pub trunc_f64: FunctionValue, + + pub nearbyint_f32: FunctionValue, + pub nearbyint_f64: FunctionValue, + + pub fabs_f32: FunctionValue, + pub fabs_f64: FunctionValue, + + pub copysign_f32: FunctionValue, + pub copysign_f64: FunctionValue, +} + +impl Intrinsics { + pub fn declare(module: &Module, context: &Context) -> Self { + let i1_ty = context.bool_type().as_basic_type_enum(); + let i32_ty = context.i32_type().as_basic_type_enum(); + let i64_ty = context.i64_type().as_basic_type_enum(); + let f32_ty = context.f32_type().as_basic_type_enum(); + let f64_ty = context.f64_type().as_basic_type_enum(); + + let ret_i32_take_i32_i1 = i32_ty.fn_type(&[i32_ty, i1_ty], false); + let ret_i64_take_i64_i1 = i64_ty.fn_type(&[i64_ty, i1_ty], false); + + let ret_i32_take_i32 = i32_ty.fn_type(&[i32_ty], false); + let ret_i64_take_i64 = i64_ty.fn_type(&[i64_ty], false); + + let ret_f32_take_f32 = f32_ty.fn_type(&[f32_ty], false); + let ret_f64_take_f64 = f64_ty.fn_type(&[f64_ty], false); + + let ret_f32_take_f32_f32 = f32_ty.fn_type(&[f32_ty, f32_ty], false); + let ret_f64_take_f64_f64 = f64_ty.fn_type(&[f64_ty, f64_ty], false); + + Self { + ctlz_i32: module.add_function("llvm.ctlz.i32", ret_i32_take_i32_i1, None), + ctlz_i64: module.add_function("llvm.ctlz.i64", ret_i64_take_i64_i1, None), + + cttz_i32: module.add_function("llvm.cttz.i32", ret_i32_take_i32_i1, None), + cttz_i64: module.add_function("llvm.cttz.i64", ret_i64_take_i64_i1, None), + + ctpop_i32: module.add_function("llvm.ctpop.i32", ret_i32_take_i32, None), + ctpop_i64: module.add_function("llvm.ctpop.i64", ret_i64_take_i64, None), + + sqrt_f32: module.add_function("llvm.sqrt.f32", ret_f32_take_f32, None), + sqrt_f64: module.add_function("llvm.sqrt.f64", ret_f64_take_f64, None), + + minimum_f32: module.add_function("llvm.minimum.f32", ret_f32_take_f32_f32, None), + minimum_f64: module.add_function("llvm.minimum.f64", ret_f64_take_f64_f64, None), + + maximum_f32: module.add_function("llvm.maximum.f32", ret_f32_take_f32_f32, None), + maximum_f64: module.add_function("llvm.maximum.f64", ret_f64_take_f64_f64, None), + + ceil_f32: module.add_function("llvm.ceil.f32", ret_f32_take_f32, None), + ceil_f64: module.add_function("llvm.ceil.f64", ret_f64_take_f64, None), + + floor_f32: module.add_function("llvm.floor.f32", ret_f32_take_f32, None), + floor_f64: module.add_function("llvm.floor.f64", ret_f64_take_f64, None), + + trunc_f32: module.add_function("llvm.trunc.f32", ret_f32_take_f32, None), + trunc_f64: module.add_function("llvm.trunc.f64", ret_f64_take_f64, None), + + nearbyint_f32: module.add_function("llvm.nearbyint.f32", ret_f32_take_f32, None), + nearbyint_f64: module.add_function("llvm.nearbyint.f64", ret_f64_take_f64, None), + + fabs_f32: module.add_function("llvm.fabs.f32", ret_f32_take_f32, None), + fabs_f64: module.add_function("llvm.fabs.f64", ret_f64_take_f64, None), + + copysign_f32: module.add_function("llvm.copysign.f32", ret_f32_take_f32_f32, None), + copysign_f64: module.add_function("llvm.copysign.f64", ret_f64_take_f64_f64, None), + } + } +} diff --git a/lib/llvm-backend/src/lib.rs b/lib/llvm-backend/src/lib.rs new file mode 100644 index 000000000..9b1b3eab6 --- /dev/null +++ b/lib/llvm-backend/src/lib.rs @@ -0,0 +1,52 @@ +use wasmer_runtime_core::{ + backend::{Compiler, Token}, + error::CompileError, + module::{ModuleInfo, ModuleInner}, +}; + +mod code; +mod intrinsics; +mod read_info; +mod state; + +pub struct LLVMCompiler { + _private: (), +} + +impl LLVMCompiler { + pub fn new() -> Self { + Self { _private: () } + } +} + +impl Compiler for LLVMCompiler { + fn compile(&self, wasm: &[u8], _: Token) -> Result { + let (_info, _code_reader) = read_info::read_module(wasm).unwrap(); + + unimplemented!() + } +} + +#[test] +fn test_read_module() { + use wabt::wat2wasm; + let WAT: &'static str = r#" + (module + (type $t0 (func (param i32) (result i32))) + (import "env" "memory" (memory 1 1)) + (import "env" "table" (table 10 anyfunc)) + (import "env" "global" (global i32)) + (import "env" "print_i32" (func $print_i32 (type $t0))) + (func $identity (type $t0) (param $p0 i32) (result i32) + get_local $p0) + (func $print_num (export "print_num") (type $t0) (param $p0 i32) (result i32) + get_global 0 + call $identity + call $print_i32)) + "#; + let wasm = wat2wasm(WAT).unwrap(); + + let (info, code_reader) = read_info::read_module(&wasm).unwrap(); + + code::parse_function_bodies(&info, code_reader).unwrap(); +} diff --git a/lib/llvm-backend/src/read_info.rs b/lib/llvm-backend/src/read_info.rs new file mode 100644 index 000000000..c1ac2cf6b --- /dev/null +++ b/lib/llvm-backend/src/read_info.rs @@ -0,0 +1,333 @@ +use wasmer_runtime_core::{ + backend::Backend, + module::{ + DataInitializer, ExportIndex, ImportName, ModuleInfo, StringTable, StringTableBuilder, + TableInitializer, + }, + structures::{Map, TypedIndex}, + types::{ + ElementType, FuncIndex, FuncSig, GlobalDescriptor, GlobalIndex, GlobalInit, + ImportedGlobalIndex, Initializer, MemoryDescriptor, MemoryIndex, SigIndex, TableDescriptor, + TableIndex, Type, Value, + }, + units::Pages, +}; +use wasmparser::{ + BinaryReaderError, CodeSectionReader, Data, DataKind, Element, ElementKind, Export, + ExternalKind, FuncType, Import, ImportSectionEntryType, InitExpr, ModuleReader, Operator, + SectionCode, Type as WpType, +}; + +pub fn read_module(wasm: &[u8]) -> Result<(ModuleInfo, CodeSectionReader), BinaryReaderError> { + let mut info = ModuleInfo { + memories: Map::new(), + globals: Map::new(), + tables: Map::new(), + + imported_functions: Map::new(), + imported_memories: Map::new(), + imported_tables: Map::new(), + imported_globals: Map::new(), + + exports: Default::default(), + + data_initializers: Vec::new(), + elem_initializers: Vec::new(), + + start_func: None, + + func_assoc: Map::new(), + signatures: Map::new(), + backend: Backend::LLVM, + + namespace_table: StringTable::new(), + name_table: StringTable::new(), + }; + + let mut reader = ModuleReader::new(wasm)?; + let mut code_reader = None; + + loop { + if reader.eof() { + return Ok((info, code_reader.unwrap())); + } + + let section = reader.read()?; + + match section.code { + SectionCode::Type => { + let type_reader = section.get_type_section_reader()?; + + for ty in type_reader { + let ty = ty?; + info.signatures.push(func_type_to_func_sig(ty)?); + } + } + SectionCode::Import => { + let import_reader = section.get_import_section_reader()?; + let mut namespace_builder = StringTableBuilder::new(); + let mut name_builder = StringTableBuilder::new(); + + for import in import_reader { + let Import { module, field, ty } = import?; + + let namespace_index = namespace_builder.register(module); + let name_index = name_builder.register(field); + let import_name = ImportName { + namespace_index, + name_index, + }; + + match ty { + ImportSectionEntryType::Function(sigindex) => { + let sigindex = SigIndex::new(sigindex as usize); + info.imported_functions.push(import_name); + info.func_assoc.push(sigindex); + } + ImportSectionEntryType::Table(table_ty) => { + assert_eq!(table_ty.element_type, WpType::AnyFunc); + let table_desc = TableDescriptor { + element: ElementType::Anyfunc, + minimum: table_ty.limits.initial, + maximum: table_ty.limits.maximum, + }; + + info.imported_tables.push((import_name, table_desc)); + } + ImportSectionEntryType::Memory(memory_ty) => { + let mem_desc = MemoryDescriptor { + minimum: Pages(memory_ty.limits.initial), + maximum: memory_ty.limits.maximum.map(|max| Pages(max)), + shared: memory_ty.shared, + }; + info.imported_memories.push((import_name, mem_desc)); + } + ImportSectionEntryType::Global(global_ty) => { + let global_desc = GlobalDescriptor { + mutable: global_ty.mutable, + ty: type_to_type(global_ty.content_type)?, + }; + info.imported_globals.push((import_name, global_desc)); + } + } + } + } + SectionCode::Function => { + let func_decl_reader = section.get_function_section_reader()?; + + for sigindex in func_decl_reader { + let sigindex = sigindex?; + + let sigindex = SigIndex::new(sigindex as usize); + info.func_assoc.push(sigindex); + } + } + SectionCode::Table => { + let table_decl_reader = section.get_table_section_reader()?; + + for table_ty in table_decl_reader { + let table_ty = table_ty?; + + let table_desc = TableDescriptor { + element: ElementType::Anyfunc, + minimum: table_ty.limits.initial, + maximum: table_ty.limits.maximum, + }; + + info.tables.push(table_desc); + } + } + SectionCode::Memory => { + let mem_decl_reader = section.get_memory_section_reader()?; + + for memory_ty in mem_decl_reader { + let memory_ty = memory_ty?; + + let mem_desc = MemoryDescriptor { + minimum: Pages(memory_ty.limits.initial), + maximum: memory_ty.limits.maximum.map(|max| Pages(max)), + shared: memory_ty.shared, + }; + + info.memories.push(mem_desc); + } + } + SectionCode::Global => { + let global_decl_reader = section.get_global_section_reader()?; + + for global in global_decl_reader { + let global = global?; + + let desc = GlobalDescriptor { + mutable: global.ty.mutable, + ty: type_to_type(global.ty.content_type)?, + }; + + let global_init = GlobalInit { + desc, + init: eval_init_expr(&global.init_expr)?, + }; + + info.globals.push(global_init); + } + } + SectionCode::Export => { + let export_reader = section.get_export_section_reader()?; + + for export in export_reader { + let Export { field, kind, index } = export?; + + let export_index = match kind { + ExternalKind::Function => ExportIndex::Func(FuncIndex::new(index as usize)), + ExternalKind::Table => ExportIndex::Table(TableIndex::new(index as usize)), + ExternalKind::Memory => { + ExportIndex::Memory(MemoryIndex::new(index as usize)) + } + ExternalKind::Global => { + ExportIndex::Global(GlobalIndex::new(index as usize)) + } + }; + + info.exports.insert(field.to_string(), export_index); + } + } + SectionCode::Start => { + let start_index = section.get_start_section_content()?; + + info.start_func = Some(FuncIndex::new(start_index as usize)); + } + SectionCode::Element => { + let element_reader = section.get_element_section_reader()?; + + for element in element_reader { + let Element { kind, items } = element?; + + match kind { + ElementKind::Active { + table_index, + init_expr, + } => { + let table_index = TableIndex::new(table_index as usize); + let base = eval_init_expr(&init_expr)?; + let items_reader = items.get_items_reader()?; + + let elements: Vec<_> = items_reader + .into_iter() + .map(|res| res.map(|index| FuncIndex::new(index as usize))) + .collect::>()?; + + let table_init = TableInitializer { + table_index, + base, + elements, + }; + + info.elem_initializers.push(table_init); + } + ElementKind::Passive(_ty) => { + return Err(BinaryReaderError { + message: "passive tables are not yet supported", + offset: -1isize as usize, + }); + } + } + } + } + SectionCode::Code => { + code_reader = Some(section.get_code_section_reader()?); + } + SectionCode::Data => { + let data_reader = section.get_data_section_reader()?; + + for data in data_reader { + let Data { kind, data } = data?; + + match kind { + DataKind::Active { + memory_index, + init_expr, + } => { + let memory_index = MemoryIndex::new(memory_index as usize); + let base = eval_init_expr(&init_expr)?; + + let data_init = DataInitializer { + memory_index, + base, + data: data.to_vec(), + }; + + info.data_initializers.push(data_init); + } + DataKind::Passive => { + return Err(BinaryReaderError { + message: "passive memories are not yet supported", + offset: -1isize as usize, + }); + } + } + } + } + SectionCode::DataCount => {} + SectionCode::Custom { .. } => {} + } + } +} + +pub fn type_to_type(ty: WpType) -> Result { + Ok(match ty { + WpType::I32 => Type::I32, + WpType::I64 => Type::I64, + WpType::F32 => Type::F32, + WpType::F64 => Type::F64, + WpType::V128 => { + return Err(BinaryReaderError { + message: "the wasmer llvm backend does not yet support the simd extension", + offset: -1isize as usize, + }); + } + _ => panic!("broken invariant, invalid type"), + }) +} + +fn func_type_to_func_sig(func_ty: FuncType) -> Result { + assert_eq!(func_ty.form, WpType::Func); + + Ok(FuncSig::new( + func_ty + .params + .iter() + .cloned() + .map(type_to_type) + .collect::, _>>()?, + func_ty + .returns + .iter() + .cloned() + .map(type_to_type) + .collect::, _>>()?, + )) +} + +fn eval_init_expr(expr: &InitExpr) -> Result { + let mut reader = expr.get_operators_reader(); + let (op, offset) = reader.read_with_offset()?; + Ok(match op { + Operator::GetGlobal { global_index } => { + Initializer::GetGlobal(ImportedGlobalIndex::new(global_index as usize)) + } + Operator::I32Const { value } => Initializer::Const(Value::I32(value)), + Operator::I64Const { value } => Initializer::Const(Value::I64(value)), + Operator::F32Const { value } => { + Initializer::Const(Value::F32(f32::from_bits(value.bits()))) + } + Operator::F64Const { value } => { + Initializer::Const(Value::F64(f64::from_bits(value.bits()))) + } + _ => { + return Err(BinaryReaderError { + message: "init expr evaluation failed: unsupported opcode", + offset, + }); + } + }) +} diff --git a/lib/llvm-backend/src/state.rs b/lib/llvm-backend/src/state.rs new file mode 100644 index 000000000..38b1178ce --- /dev/null +++ b/lib/llvm-backend/src/state.rs @@ -0,0 +1,105 @@ +use inkwell::{ + basic_block::BasicBlock, + values::{BasicValue, BasicValueEnum}, +}; +use wasmparser::BinaryReaderError; + +enum ControlFrame { + If { + dest: BasicBlock, + stack_size_snapshot: usize, + }, + Block { + dest: BasicBlock, + stack_size_snapshot: usize, + num_ret_values: usize, + }, +} + +pub struct State { + stack: Vec, + control_stack: Vec, + value_counter: usize, +} + +impl State { + pub fn new() -> Self { + Self { + stack: vec![], + control_stack: vec![], + value_counter: 0, + } + } + + pub fn var_name(&mut self) -> String { + let s = self.value_counter.to_string(); + self.value_counter += 1; + s + } + + pub fn push1(&mut self, value: T) { + self.stack.push(value.as_basic_value_enum()) + } + + pub fn pop1(&mut self) -> Result { + self.stack.pop().ok_or_else(|| BinaryReaderError { + message: "invalid value stack", + offset: -1isize as usize, + }) + } + + pub fn pop2(&mut self) -> Result<(BasicValueEnum, BasicValueEnum), BinaryReaderError> { + let v2 = self.pop1()?; + let v1 = self.pop1()?; + Ok((v1, v2)) + } + + pub fn pop3( + &mut self, + ) -> Result<(BasicValueEnum, BasicValueEnum, BasicValueEnum), BinaryReaderError> { + let v3 = self.pop1()?; + let v2 = self.pop1()?; + let v1 = self.pop1()?; + Ok((v1, v2, v3)) + } + + pub fn peek1(&self) -> Result { + self.stack + .get(self.stack.len() - 1) + .ok_or_else(|| BinaryReaderError { + message: "invalid value stack", + offset: -1isize as usize, + }) + .map(|v| *v) + } + + pub fn peekn(&self, n: usize) -> Result<&[BasicValueEnum], BinaryReaderError> { + self.stack + .get(self.stack.len() - n..) + .ok_or_else(|| BinaryReaderError { + message: "invalid value stack", + offset: -1isize as usize, + }) + } + + pub fn popn(&mut self, n: usize) -> Result<(), BinaryReaderError> { + if self.stack.len() < n { + return Err(BinaryReaderError { + message: "invalid value stack", + offset: -1isize as usize, + }); + } + + let new_len = self.stack.len() - n; + self.stack.truncate(new_len); + Ok(()) + } + + pub fn push_block(&mut self, dest: BasicBlock, num_ret_values: usize) { + self.control_stack.push(ControlFrame::Block { + dest, + stack_size_snapshot: self.stack.len(), + num_ret_values, + }); + } +} diff --git a/lib/runtime-core/src/backing.rs b/lib/runtime-core/src/backing.rs index 46f1fe982..9734f0c02 100644 --- a/lib/runtime-core/src/backing.rs +++ b/lib/runtime-core/src/backing.rs @@ -91,7 +91,7 @@ impl LocalBacking { } } as usize; - match init.memory_index.local_or_import(module) { + match init.memory_index.local_or_import(&module.info) { LocalOrImport::Local(local_memory_index) => { let memory_desc = module.info.memories[local_memory_index]; let data_top = init_base + init.data.len(); @@ -159,7 +159,7 @@ impl LocalBacking { } } as usize; - match init.table_index.local_or_import(module) { + match init.table_index.local_or_import(&module.info) { LocalOrImport::Local(local_table_index) => { let table = &tables[local_table_index]; @@ -178,7 +178,7 @@ impl LocalBacking { let sig_id = vm::SigId(SigRegistry.lookup_sig_index(signature).index() as u32); - let (func, ctx) = match func_index.local_or_import(module) { + let (func, ctx) = match func_index.local_or_import(&module.info) { LocalOrImport::Local(local_func_index) => ( module .func_resolver @@ -217,7 +217,7 @@ impl LocalBacking { let sig_id = vm::SigId(SigRegistry.lookup_sig_index(signature).index() as u32); - let (func, ctx) = match func_index.local_or_import(module) { + let (func, ctx) = match func_index.local_or_import(&module.info) { LocalOrImport::Local(local_func_index) => ( module .func_resolver @@ -366,7 +366,7 @@ fn import_functions( }, ) in &module.info.imported_functions { - let sig_index = module.info.func_assoc[index.convert_up(module)]; + let sig_index = module.info.func_assoc[index.convert_up(&module.info)]; let expected_sig = &module.info.signatures[sig_index]; let namespace = module.info.namespace_table.get(*namespace_index); diff --git a/lib/runtime-core/src/instance.rs b/lib/runtime-core/src/instance.rs index 8255c125d..6a4d5d438 100644 --- a/lib/runtime-core/src/instance.rs +++ b/lib/runtime-core/src/instance.rs @@ -123,14 +123,14 @@ impl Instance { })?; } - let ctx = match func_index.local_or_import(&*self.module) { + let ctx = match func_index.local_or_import(&self.module.info) { LocalOrImport::Local(_) => self.inner.vmctx, LocalOrImport::Import(imported_func_index) => { self.inner.import_backing.vm_functions[imported_func_index].vmctx } }; - let func_ptr = match func_index.local_or_import(&self.module) { + let func_ptr = match func_index.local_or_import(&self.module.info) { LocalOrImport::Local(local_func_index) => self .module .func_resolver @@ -291,7 +291,7 @@ impl Instance { })? } - let vmctx = match func_index.local_or_import(&self.module) { + let vmctx = match func_index.local_or_import(&self.module.info) { LocalOrImport::Local(_) => self.inner.vmctx, LocalOrImport::Import(imported_func_index) => { self.inner.import_backing.vm_functions[imported_func_index].vmctx @@ -358,7 +358,7 @@ impl InstanceInner { .get(func_index) .expect("broken invariant, incorrect func index"); - let (func_ptr, ctx) = match func_index.local_or_import(module) { + let (func_ptr, ctx) = match func_index.local_or_import(&module.info) { LocalOrImport::Local(local_func_index) => ( module .func_resolver @@ -384,7 +384,7 @@ impl InstanceInner { } fn get_memory_from_index(&self, module: &ModuleInner, mem_index: MemoryIndex) -> Memory { - match mem_index.local_or_import(module) { + match mem_index.local_or_import(&module.info) { LocalOrImport::Local(local_mem_index) => self.backing.memories[local_mem_index].clone(), LocalOrImport::Import(imported_mem_index) => { self.import_backing.memories[imported_mem_index].clone() @@ -393,7 +393,7 @@ impl InstanceInner { } fn get_global_from_index(&self, module: &ModuleInner, global_index: GlobalIndex) -> Global { - match global_index.local_or_import(module) { + match global_index.local_or_import(&module.info) { LocalOrImport::Local(local_global_index) => { self.backing.globals[local_global_index].clone() } @@ -404,7 +404,7 @@ impl InstanceInner { } fn get_table_from_index(&self, module: &ModuleInner, table_index: TableIndex) -> Table { - match table_index.local_or_import(module) { + match table_index.local_or_import(&module.info) { LocalOrImport::Local(local_table_index) => { self.backing.tables[local_table_index].clone() } @@ -462,7 +462,7 @@ impl<'a> DynFunc<'a> { })? } - let vmctx = match self.func_index.local_or_import(self.module) { + let vmctx = match self.func_index.local_or_import(&self.module.info) { LocalOrImport::Local(_) => self.instance_inner.vmctx, LocalOrImport::Import(imported_func_index) => { self.instance_inner.import_backing.vm_functions[imported_func_index].vmctx @@ -488,7 +488,7 @@ impl<'a> DynFunc<'a> { } pub fn raw(&self) -> *const vm::Func { - match self.func_index.local_or_import(self.module) { + match self.func_index.local_or_import(&self.module.info) { LocalOrImport::Local(local_func_index) => self .module .func_resolver diff --git a/lib/runtime-core/src/types.rs b/lib/runtime-core/src/types.rs index c6b3f0a2b..bec1500b6 100644 --- a/lib/runtime-core/src/types.rs +++ b/lib/runtime-core/src/types.rs @@ -1,4 +1,9 @@ -use crate::{memory::MemoryType, module::ModuleInner, structures::TypedIndex, units::Pages}; +use crate::{ + memory::MemoryType, + module::{ModuleInfo, ModuleInner}, + structures::TypedIndex, + units::Pages, +}; use std::{borrow::Cow, mem}; /// Represents a WebAssembly type. @@ -340,23 +345,23 @@ define_map_index![ macro_rules! define_local_or_import { ($ty:ident, $local_ty:ident, $imported_ty:ident, $imports:ident) => { impl $ty { - pub fn local_or_import(self, module: &ModuleInner) -> LocalOrImport<$ty> { - if self.index() < module.info.$imports.len() { + pub fn local_or_import(self, info: &ModuleInfo) -> LocalOrImport<$ty> { + if self.index() < info.$imports.len() { LocalOrImport::Import(::Import::new(self.index())) } else { - LocalOrImport::Local(::Local::new(self.index() - module.info.$imports.len())) + LocalOrImport::Local(::Local::new(self.index() - info.$imports.len())) } } } impl $local_ty { - pub fn convert_up(self, module: &ModuleInner) -> $ty { - $ty ((self.index() + module.info.$imports.len()) as u32) + pub fn convert_up(self, info: &ModuleInfo) -> $ty { + $ty ((self.index() + info.$imports.len()) as u32) } } impl $imported_ty { - pub fn convert_up(self, _module: &ModuleInner) -> $ty { + pub fn convert_up(self, _module: &ModuleInfo) -> $ty { $ty (self.index() as u32) } } diff --git a/lib/runtime-core/src/vm.rs b/lib/runtime-core/src/vm.rs index 8cb9f0986..eaa76fd22 100644 --- a/lib/runtime-core/src/vm.rs +++ b/lib/runtime-core/src/vm.rs @@ -116,7 +116,7 @@ impl Ctx { pub fn memory(&self, mem_index: u32) -> &Memory { let module = unsafe { &*self.module }; let mem_index = MemoryIndex::new(mem_index as usize); - match mem_index.local_or_import(module) { + match mem_index.local_or_import(&module.info) { LocalOrImport::Local(local_mem_index) => unsafe { let local_backing = &*self.local_backing; &local_backing.memories[local_mem_index] From 5ee19e55a5adb0ffec3b27d6a51fd02f31a9f947 Mon Sep 17 00:00:00 2001 From: Lachlan Sneff Date: Mon, 11 Feb 2019 19:34:04 -0800 Subject: [PATCH 03/75] Add some branching instructions --- Cargo.lock | 1 + lib/llvm-backend/Cargo.toml | 1 + lib/llvm-backend/src/code.rs | 387 ++++++++++++++++++++++++----- lib/llvm-backend/src/intrinsics.rs | 72 ++++-- lib/llvm-backend/src/lib.rs | 2 +- lib/llvm-backend/src/state.rs | 85 +++++-- 6 files changed, 454 insertions(+), 94 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 209d06782..6adb5581c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -359,6 +359,7 @@ version = "0.1.0" dependencies = [ "hashbrown 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "inkwell 0.1.0 (git+https://github.com/TheDan64/inkwell?branch=llvm7-0)", + "smallvec 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", "wabt 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)", "wasmer-runtime-core 0.1.2", "wasmparser 0.28.0 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/lib/llvm-backend/Cargo.toml b/lib/llvm-backend/Cargo.toml index 000265b7d..bcf2175e2 100644 --- a/lib/llvm-backend/Cargo.toml +++ b/lib/llvm-backend/Cargo.toml @@ -9,6 +9,7 @@ wasmer-runtime-core = { path = "../runtime-core", version = "0.1.2" } wasmparser = "0.28.0" inkwell = { git = "https://github.com/TheDan64/inkwell", branch = "llvm7-0" } hashbrown = "0.1.8" +smallvec = "0.6.8" [dev-dependencies] wabt = "0.7.4" diff --git a/lib/llvm-backend/src/code.rs b/lib/llvm-backend/src/code.rs index 50a31065a..7a24f9fbf 100644 --- a/lib/llvm-backend/src/code.rs +++ b/lib/llvm-backend/src/code.rs @@ -1,13 +1,12 @@ -use hashbrown::HashMap; use inkwell::{ - basic_block::BasicBlock, builder::Builder, context::Context, module::Module, types::{BasicType, BasicTypeEnum, FunctionType}, - values::{AggregateValue, BasicValue, BasicValueEnum, FunctionValue}, - IntPredicate, + values::{BasicValue, FunctionValue}, + FloatPredicate, IntPredicate, }; +use smallvec::SmallVec; use wasmer_runtime_core::{ module::ModuleInfo, structures::{Map, SliceMap, TypedIndex}, @@ -19,20 +18,18 @@ use crate::intrinsics::Intrinsics; use crate::read_info::type_to_type; use crate::state::State; -fn func_sig_to_llvm(context: &Context, sig: &FuncSig) -> FunctionType { - let param_types: Vec<_> = sig - .params() - .iter() - .map(|&ty| type_to_llvm(context, ty)) - .collect(); +fn func_sig_to_llvm(context: &Context, intrinsics: &Intrinsics, sig: &FuncSig) -> FunctionType { + let user_param_types = sig.params().iter().map(|&ty| type_to_llvm(intrinsics, ty)); + + let param_types: Vec<_> = user_param_types.collect(); match sig.returns() { - [] => context.void_type().fn_type(¶m_types, false), - [single_value] => type_to_llvm(context, *single_value).fn_type(¶m_types, false), + [] => intrinsics.void_ty.fn_type(¶m_types, false), + [single_value] => type_to_llvm(intrinsics, *single_value).fn_type(¶m_types, false), returns @ _ => { let basic_types: Vec<_> = returns .iter() - .map(|&ty| type_to_llvm(context, ty)) + .map(|&ty| type_to_llvm(intrinsics, ty)) .collect(); context @@ -42,12 +39,12 @@ fn func_sig_to_llvm(context: &Context, sig: &FuncSig) -> FunctionType { } } -fn type_to_llvm(context: &Context, ty: Type) -> BasicTypeEnum { +fn type_to_llvm(intrinsics: &Intrinsics, ty: Type) -> BasicTypeEnum { match ty { - Type::I32 => context.i32_type().as_basic_type_enum(), - Type::I64 => context.i64_type().as_basic_type_enum(), - Type::F32 => context.f32_type().as_basic_type_enum(), - Type::F64 => context.f64_type().as_basic_type_enum(), + Type::I32 => intrinsics.i32_ty.as_basic_type_enum(), + Type::I64 => intrinsics.i64_ty.as_basic_type_enum(), + Type::F32 => intrinsics.f32_ty.as_basic_type_enum(), + Type::F64 => intrinsics.f64_ty.as_basic_type_enum(), } } @@ -64,7 +61,7 @@ pub fn parse_function_bodies( let signatures: Map = info .signatures .iter() - .map(|(_, sig)| func_sig_to_llvm(&context, sig)) + .map(|(_, sig)| func_sig_to_llvm(&context, &intrinsics, sig)) .collect(); let functions: Map = info .func_assoc @@ -72,7 +69,7 @@ pub fn parse_function_bodies( .skip(info.imported_functions.len()) .map(|(func_index, &sig_index)| { module.add_function( - &format!("fn:{}", func_index.index()), + &format!("fn{}", func_index.index()), signatures[sig_index], None, ) @@ -114,7 +111,9 @@ fn parse_function( locals_reader: LocalsReader, op_reader: OperatorsReader, ) -> Result<(), BinaryReaderError> { - let llvm_sig = &signatures[info.func_assoc[func_index.convert_up(info)]]; + let sig_index = info.func_assoc[func_index.convert_up(info)]; + let func_sig = &info.signatures[sig_index]; + let llvm_sig = &signatures[sig_index]; let function = functions[func_index]; let entry_block = context.append_basic_block(&function, "entry"); @@ -126,7 +125,7 @@ fn parse_function( locals.extend(function.get_param_iter().enumerate().map(|(index, param)| { let ty = param.get_type(); - let alloca = builder.build_alloca(ty, &state.var_name()); + let alloca = builder.build_alloca(ty, &format!("local{}", index)); builder.build_store(alloca, param); alloca })); @@ -136,15 +135,15 @@ fn parse_function( let wasmer_ty = type_to_type(ty)?; - let ty = type_to_llvm(context, wasmer_ty); + let ty = type_to_llvm(intrinsics, wasmer_ty); - let alloca = builder.build_alloca(ty, &state.var_name()); + let alloca = builder.build_alloca(ty, &format!("local{}", index)); let default_value = match wasmer_ty { - Type::I32 => context.i32_type().const_int(0, false).as_basic_value_enum(), - Type::I64 => context.i64_type().const_int(0, false).as_basic_value_enum(), - Type::F32 => context.f32_type().const_float(0.0).as_basic_value_enum(), - Type::F64 => context.f64_type().const_float(0.0).as_basic_value_enum(), + Type::I32 => intrinsics.i32_zero.as_basic_value_enum(), + Type::I64 => intrinsics.i64_zero.as_basic_value_enum(), + Type::F32 => intrinsics.f32_zero.as_basic_value_enum(), + Type::F64 => intrinsics.f64_zero.as_basic_value_enum(), }; builder.build_store(alloca, default_value); @@ -154,6 +153,149 @@ fn parse_function( for op in op_reader { match op? { + /*************************** + * Control Flow instructions. + * https://github.com/sunfishcode/wasm-reference-manual/blob/master/WebAssembly.md#control-flow-instructions + ***************************/ + Operator::Block { ty } => { + let current_block = builder.get_insert_block().ok_or(BinaryReaderError { + message: "not currently in a block", + offset: -1isize as usize, + })?; + + let end_block = context.append_basic_block(&function, &state.block_name()); + builder.position_at_end(&end_block); + + let phis = if let Ok(wasmer_ty) = type_to_type(ty) { + let llvm_ty = type_to_llvm(intrinsics, wasmer_ty); + [llvm_ty] + .iter() + .map(|&ty| builder.build_phi(ty, &state.var_name())) + .collect() + } else { + SmallVec::new() + }; + + state.push_block(end_block, phis); + builder.position_at_end(¤t_block); + } + Operator::Loop { ty } => { + + // let loop_body = context.append_basic_block(&function, &state.block_name()); + // let next = context.append_basic_block(&function, &state.block_name()); + // builder.build_unconditional_branch(&body); + // let num_return_values = if ty == wasmparser::Type::EmptyBlockType { 0 } else { 1 }; + // state.push_loop(loop_body, next, num_return_values); + } + Operator::Br { relative_depth } => { + let frame = state.frame_at_depth(relative_depth)?; + + let current_block = builder.get_insert_block().ok_or(BinaryReaderError { + message: "not currently in a block", + offset: -1isize as usize, + })?; + + let values = state.peekn(frame.phis().len())?; + + // For each result of the block we're branching to, + // pop a value off the value stack and load it into + // the corresponding phi. + for (phi, value) in frame.phis().iter().zip(values.iter()) { + phi.add_incoming(&[(value, ¤t_block)]); + } + + builder.build_unconditional_branch(frame.dest()); + + state.popn(frame.phis().len())?; + + builder.build_unreachable(); + } + Operator::BrIf { relative_depth } => { + let cond = state.pop1()?; + let frame = state.frame_at_depth(relative_depth)?; + + let current_block = builder.get_insert_block().ok_or(BinaryReaderError { + message: "not currently in a block", + offset: -1isize as usize, + })?; + + let param_stack = state.peekn(frame.phis().len())?; + + for (phi, value) in frame.phis().iter().zip(param_stack.iter()) { + phi.add_incoming(&[(value, ¤t_block)]); + } + + let false_block = context.append_basic_block(&function, &state.block_name()); + + let cond_value = builder.build_int_compare( + IntPredicate::NE, + cond.into_int_value(), + intrinsics.i32_zero, + &state.var_name(), + ); + builder.build_conditional_branch(cond_value, frame.dest(), &false_block); + builder.position_at_end(&false_block); + } + Operator::BrTable { ref table } => { + let current_block = builder.get_insert_block().ok_or(BinaryReaderError { + message: "not currently in a block", + offset: -1isize as usize, + })?; + + let (label_depths, default_depth) = table.read_table()?; + + let index = state.pop1()?; + + let default_frame = state.frame_at_depth(default_depth)?; + + let res_len = default_frame.phis().len(); + + let args = state.peekn(res_len)?; + + for (phi, value) in default_frame.phis().iter().zip(args.iter()) { + phi.add_incoming(&[(value, ¤t_block)]); + } + + let cases: Vec<_> = label_depths + .iter() + .enumerate() + .map(|(case_index, &depth)| { + let frame = state.frame_at_depth(depth)?; + let case_index_literal = + context.i32_type().const_int(case_index as u64, false); + + for (phi, value) in frame.phis().iter().zip(args.iter()) { + phi.add_incoming(&[(value, ¤t_block)]); + } + + Ok((case_index_literal, frame.dest())) + }) + .collect::>()?; + + builder.build_switch(index.into_int_value(), default_frame.dest(), &cases[..]); + + state.popn(res_len)?; + builder.build_unreachable(); + } + + Operator::End => { + let frame = state.pop_frame()?; + + // Push each phi value to the value stack. + for phi in frame.phis() { + state.push1(phi.as_basic_value()); + } + + state.reset_stack(&frame); + } + + Operator::Unreachable => { + // Emit an unreachable instruction. + // If llvm cannot prove that this is never touched, + // it will emit a `ud2` instruction on x86_64 arches. + builder.build_unreachable(); + } + /*************************** * Basic instructions. * https://github.com/sunfishcode/wasm-reference-manual/blob/master/WebAssembly.md#basic-instructions @@ -167,21 +309,21 @@ fn parse_function( // Generate const values. Operator::I32Const { value } => { - let i = context.i32_type().const_int(value as u64, false); + let i = intrinsics.i32_ty.const_int(value as u64, false); state.push1(i); } Operator::I64Const { value } => { - let i = context.i64_type().const_int(value as u64, false); + let i = intrinsics.i64_ty.const_int(value as u64, false); state.push1(i); } Operator::F32Const { value } => { - let f = context - .f32_type() + let f = intrinsics + .f32_ty .const_float(f64::from_bits(value.bits() as u64)); state.push1(f); } Operator::F64Const { value } => { - let f = context.f64_type().const_float(f64::from_bits(value.bits())); + let f = intrinsics.f64_ty.const_float(f64::from_bits(value.bits())); state.push1(f); } @@ -243,9 +385,7 @@ fn parse_function( } } } - LocalOrImport::Import(import_func_index) => { - // unimplemented!() - } + LocalOrImport::Import(import_func_index) => unimplemented!(), } } Operator::CallIndirect { index, table_index } => { @@ -339,7 +479,7 @@ fn parse_function( let (v1, v2) = (v1.into_int_value(), v2.into_int_value()); let lhs = builder.build_left_shift(v1, v2, &state.var_name()); let rhs = { - let int_width = context.i32_type().const_int(32 as u64, false); + let int_width = intrinsics.i32_ty.const_int(32 as u64, false); let rhs = builder.build_int_sub(int_width, v2, &state.var_name()); builder.build_right_shift(v1, rhs, false, &state.var_name()) }; @@ -351,7 +491,7 @@ fn parse_function( let (v1, v2) = (v1.into_int_value(), v2.into_int_value()); let lhs = builder.build_left_shift(v1, v2, &state.var_name()); let rhs = { - let int_width = context.i64_type().const_int(64 as u64, false); + let int_width = intrinsics.i64_ty.const_int(64 as u64, false); let rhs = builder.build_int_sub(int_width, v2, &state.var_name()); builder.build_right_shift(v1, rhs, false, &state.var_name()) }; @@ -363,7 +503,7 @@ fn parse_function( let (v1, v2) = (v1.into_int_value(), v2.into_int_value()); let lhs = builder.build_right_shift(v1, v2, false, &state.var_name()); let rhs = { - let int_width = context.i32_type().const_int(32 as u64, false); + let int_width = intrinsics.i32_ty.const_int(32 as u64, false); let rhs = builder.build_int_sub(int_width, v2, &state.var_name()); builder.build_left_shift(v1, rhs, &state.var_name()) }; @@ -375,7 +515,7 @@ fn parse_function( let (v1, v2) = (v1.into_int_value(), v2.into_int_value()); let lhs = builder.build_right_shift(v1, v2, false, &state.var_name()); let rhs = { - let int_width = context.i64_type().const_int(64 as u64, false); + let int_width = intrinsics.i64_ty.const_int(64 as u64, false); let rhs = builder.build_int_sub(int_width, v2, &state.var_name()); builder.build_left_shift(v1, rhs, &state.var_name()) }; @@ -384,8 +524,8 @@ fn parse_function( } Operator::I32Clz => { let input = state.pop1()?; - let ensure_defined_zero = context - .bool_type() + let ensure_defined_zero = intrinsics + .i1_ty .const_int(1 as u64, false) .as_basic_value_enum(); let res = builder @@ -401,8 +541,8 @@ fn parse_function( } Operator::I64Clz => { let input = state.pop1()?; - let ensure_defined_zero = context - .bool_type() + let ensure_defined_zero = intrinsics + .i1_ty .const_int(1 as u64, false) .as_basic_value_enum(); let res = builder @@ -418,8 +558,8 @@ fn parse_function( } Operator::I32Ctz => { let input = state.pop1()?; - let ensure_defined_zero = context - .bool_type() + let ensure_defined_zero = intrinsics + .i1_ty .const_int(1 as u64, false) .as_basic_value_enum(); let res = builder @@ -435,8 +575,8 @@ fn parse_function( } Operator::I64Ctz => { let input = state.pop1()?; - let ensure_defined_zero = context - .bool_type() + let ensure_defined_zero = intrinsics + .i1_ty .const_int(1 as u64, false) .as_basic_value_enum(); let res = builder @@ -470,16 +610,22 @@ fn parse_function( } Operator::I32Eqz => { let input = state.pop1()?.into_int_value(); - let zero = context.i32_type().const_int(0, false); - let res = - builder.build_int_compare(IntPredicate::EQ, input, zero, &state.var_name()); + let res = builder.build_int_compare( + IntPredicate::EQ, + input, + intrinsics.i32_zero, + &state.var_name(), + ); state.push1(res); } Operator::I64Eqz => { let input = state.pop1()?.into_int_value(); - let zero = context.i64_type().const_int(0, false); - let res = - builder.build_int_compare(IntPredicate::EQ, input, zero, &state.var_name()); + let res = builder.build_int_compare( + IntPredicate::EQ, + input, + intrinsics.i64_zero, + &state.var_name(), + ); state.push1(res); } @@ -493,7 +639,7 @@ fn parse_function( let res = builder.build_float_add(v1, v2, &state.var_name()); state.push1(res); } - Operator::F32Sub | Operator::F32Sub => { + Operator::F32Sub | Operator::F64Sub => { let (v1, v2) = state.pop2()?; let (v1, v2) = (v1.into_float_value(), v2.into_float_value()); let res = builder.build_float_sub(v1, v2, &state.var_name()); @@ -748,12 +894,133 @@ fn parse_function( * Floating-Point Comparison instructions. * https://github.com/sunfishcode/wasm-reference-manual/blob/master/WebAssembly.md#floating-point-comparison-instructions ***************************/ - Operator::Unreachable => { - // Emit an unreachable instruction. - // If llvm cannot prove that this is never touched, - // it will emit a `ud2` instruction on x86_64 arches. - builder.build_unreachable(); + Operator::F32Eq | Operator::F64Eq => { + let (v1, v2) = state.pop2()?; + let (v1, v2) = (v1.into_float_value(), v2.into_float_value()); + let res = + builder.build_float_compare(FloatPredicate::OEQ, v1, v2, &state.var_name()); + state.push1(res); } + Operator::F32Ne | Operator::F64Ne => { + let (v1, v2) = state.pop2()?; + let (v1, v2) = (v1.into_float_value(), v2.into_float_value()); + let res = + builder.build_float_compare(FloatPredicate::UNE, v1, v2, &state.var_name()); + state.push1(res); + } + Operator::F32Lt | Operator::F64Lt => { + let (v1, v2) = state.pop2()?; + let (v1, v2) = (v1.into_float_value(), v2.into_float_value()); + let res = + builder.build_float_compare(FloatPredicate::OLT, v1, v2, &state.var_name()); + state.push1(res); + } + Operator::F32Le | Operator::F64Le => { + let (v1, v2) = state.pop2()?; + let (v1, v2) = (v1.into_float_value(), v2.into_float_value()); + let res = + builder.build_float_compare(FloatPredicate::OLE, v1, v2, &state.var_name()); + state.push1(res); + } + Operator::F32Gt | Operator::F64Gt => { + let (v1, v2) = state.pop2()?; + let (v1, v2) = (v1.into_float_value(), v2.into_float_value()); + let res = + builder.build_float_compare(FloatPredicate::OGT, v1, v2, &state.var_name()); + state.push1(res); + } + Operator::F32Ge | Operator::F64Ge => { + let (v1, v2) = state.pop2()?; + let (v1, v2) = (v1.into_float_value(), v2.into_float_value()); + let res = + builder.build_float_compare(FloatPredicate::OGE, v1, v2, &state.var_name()); + state.push1(res); + } + + /*************************** + * Conversion instructions. + * https://github.com/sunfishcode/wasm-reference-manual/blob/master/WebAssembly.md#conversion-instructions + ***************************/ + Operator::I32WrapI64 => { + let v1 = state.pop1()?.into_int_value(); + let res = builder.build_int_truncate(v1, intrinsics.i32_ty, &state.var_name()); + state.push1(res); + } + Operator::I64ExtendSI32 => { + let v1 = state.pop1()?.into_int_value(); + let res = builder.build_int_s_extend(v1, intrinsics.i64_ty, &state.var_name()); + state.push1(res); + } + Operator::I64ExtendUI32 => { + let v1 = state.pop1()?.into_int_value(); + let res = builder.build_int_z_extend(v1, intrinsics.i64_ty, &state.var_name()); + state.push1(res); + } + Operator::I32TruncSF32 | Operator::I32TruncSF64 => { + let v1 = state.pop1()?.into_float_value(); + let res = + builder.build_float_to_signed_int(v1, intrinsics.i32_ty, &state.var_name()); + state.push1(res); + } + Operator::I64TruncSF32 | Operator::I64TruncSF64 => { + let v1 = state.pop1()?.into_float_value(); + let res = + builder.build_float_to_signed_int(v1, intrinsics.i64_ty, &state.var_name()); + state.push1(res); + } + Operator::I32TruncUF32 | Operator::I32TruncUF64 => { + let v1 = state.pop1()?.into_float_value(); + let res = + builder.build_float_to_unsigned_int(v1, intrinsics.i32_ty, &state.var_name()); + state.push1(res); + } + Operator::I64TruncUF32 | Operator::I64TruncUF64 => { + let v1 = state.pop1()?.into_float_value(); + let res = + builder.build_float_to_unsigned_int(v1, intrinsics.i64_ty, &state.var_name()); + state.push1(res); + } + Operator::F32DemoteF64 => { + let v1 = state.pop1()?.into_float_value(); + let res = builder.build_float_trunc(v1, intrinsics.f32_ty, &state.var_name()); + state.push1(res); + } + Operator::F64PromoteF32 => { + let v1 = state.pop1()?.into_float_value(); + let res = builder.build_float_ext(v1, intrinsics.f64_ty, &state.var_name()); + state.push1(res); + } + Operator::F32ConvertSI32 | Operator::F32ConvertSI64 => { + let v1 = state.pop1()?.into_int_value(); + let res = + builder.build_signed_int_to_float(v1, intrinsics.f32_ty, &state.var_name()); + state.push1(res); + } + Operator::F64ConvertSI32 | Operator::F64ConvertSI64 => { + let v1 = state.pop1()?.into_int_value(); + let res = + builder.build_signed_int_to_float(v1, intrinsics.f64_ty, &state.var_name()); + state.push1(res); + } + Operator::F32ConvertUI32 | Operator::F32ConvertUI64 => { + let v1 = state.pop1()?.into_int_value(); + let res = + builder.build_unsigned_int_to_float(v1, intrinsics.f32_ty, &state.var_name()); + state.push1(res); + } + Operator::F64ConvertUI32 | Operator::F64ConvertUI64 => { + let v1 = state.pop1()?.into_int_value(); + let res = + builder.build_unsigned_int_to_float(v1, intrinsics.f64_ty, &state.var_name()); + state.push1(res); + } + Operator::I32ReinterpretF32 + | Operator::F32ReinterpretI32 + | Operator::I64ReinterpretF64 + | Operator::F64ReinterpretI64 => { + unimplemented!("waiting on better bitcasting support in inkwell") + } + op @ _ => { println!("{}", module.print_to_string().to_string()); unimplemented!("{:?}", op); diff --git a/lib/llvm-backend/src/intrinsics.rs b/lib/llvm-backend/src/intrinsics.rs index 824317e8e..8eab37071 100644 --- a/lib/llvm-backend/src/intrinsics.rs +++ b/lib/llvm-backend/src/intrinsics.rs @@ -1,4 +1,9 @@ -use inkwell::{context::Context, module::Module, types::BasicType, values::FunctionValue}; +use inkwell::{ + context::Context, + module::Module, + types::{BasicType, FloatType, IntType, VoidType}, + values::{FloatValue, FunctionValue, IntValue}, +}; pub struct Intrinsics { pub ctlz_i32: FunctionValue, @@ -36,27 +41,53 @@ pub struct Intrinsics { pub copysign_f32: FunctionValue, pub copysign_f64: FunctionValue, + + pub void_ty: VoidType, + pub i1_ty: IntType, + pub i32_ty: IntType, + pub i64_ty: IntType, + pub f32_ty: FloatType, + pub f64_ty: FloatType, + + pub i1_zero: IntValue, + pub i32_zero: IntValue, + pub i64_zero: IntValue, + pub f32_zero: FloatValue, + pub f64_zero: FloatValue, } impl Intrinsics { pub fn declare(module: &Module, context: &Context) -> Self { - let i1_ty = context.bool_type().as_basic_type_enum(); - let i32_ty = context.i32_type().as_basic_type_enum(); - let i64_ty = context.i64_type().as_basic_type_enum(); - let f32_ty = context.f32_type().as_basic_type_enum(); - let f64_ty = context.f64_type().as_basic_type_enum(); + let void_ty = context.void_type(); + let i1_ty = context.bool_type(); + let i32_ty = context.i32_type(); + let i64_ty = context.i64_type(); + let f32_ty = context.f32_type(); + let f64_ty = context.f64_type(); - let ret_i32_take_i32_i1 = i32_ty.fn_type(&[i32_ty, i1_ty], false); - let ret_i64_take_i64_i1 = i64_ty.fn_type(&[i64_ty, i1_ty], false); + let i1_zero = i1_ty.const_int(0, false); + let i32_zero = i32_ty.const_int(0, false); + let i64_zero = i64_ty.const_int(0, false); + let f32_zero = f32_ty.const_float(0.0); + let f64_zero = f64_ty.const_float(0.0); - let ret_i32_take_i32 = i32_ty.fn_type(&[i32_ty], false); - let ret_i64_take_i64 = i64_ty.fn_type(&[i64_ty], false); + let i1_ty_basic = i1_ty.as_basic_type_enum(); + let i32_ty_basic = i32_ty.as_basic_type_enum(); + let i64_ty_basic = i64_ty.as_basic_type_enum(); + let f32_ty_basic = f32_ty.as_basic_type_enum(); + let f64_ty_basic = f64_ty.as_basic_type_enum(); - let ret_f32_take_f32 = f32_ty.fn_type(&[f32_ty], false); - let ret_f64_take_f64 = f64_ty.fn_type(&[f64_ty], false); + let ret_i32_take_i32_i1 = i32_ty.fn_type(&[i32_ty_basic, i1_ty_basic], false); + let ret_i64_take_i64_i1 = i64_ty.fn_type(&[i64_ty_basic, i1_ty_basic], false); - let ret_f32_take_f32_f32 = f32_ty.fn_type(&[f32_ty, f32_ty], false); - let ret_f64_take_f64_f64 = f64_ty.fn_type(&[f64_ty, f64_ty], false); + let ret_i32_take_i32 = i32_ty.fn_type(&[i32_ty_basic], false); + let ret_i64_take_i64 = i64_ty.fn_type(&[i64_ty_basic], false); + + let ret_f32_take_f32 = f32_ty.fn_type(&[f32_ty_basic], false); + let ret_f64_take_f64 = f64_ty.fn_type(&[f64_ty_basic], false); + + let ret_f32_take_f32_f32 = f32_ty.fn_type(&[f32_ty_basic, f32_ty_basic], false); + let ret_f64_take_f64_f64 = f64_ty.fn_type(&[f64_ty_basic, f64_ty_basic], false); Self { ctlz_i32: module.add_function("llvm.ctlz.i32", ret_i32_take_i32_i1, None), @@ -94,6 +125,19 @@ impl Intrinsics { copysign_f32: module.add_function("llvm.copysign.f32", ret_f32_take_f32_f32, None), copysign_f64: module.add_function("llvm.copysign.f64", ret_f64_take_f64_f64, None), + + void_ty, + i1_ty, + i32_ty, + i64_ty, + f32_ty, + f64_ty, + + i1_zero, + i32_zero, + i64_zero, + f32_zero, + f64_zero, } } } diff --git a/lib/llvm-backend/src/lib.rs b/lib/llvm-backend/src/lib.rs index 9b1b3eab6..69ed0fa0d 100644 --- a/lib/llvm-backend/src/lib.rs +++ b/lib/llvm-backend/src/lib.rs @@ -1,7 +1,7 @@ use wasmer_runtime_core::{ backend::{Compiler, Token}, error::CompileError, - module::{ModuleInfo, ModuleInner}, + module::ModuleInner, }; mod code; diff --git a/lib/llvm-backend/src/state.rs b/lib/llvm-backend/src/state.rs index 38b1178ce..e85c7a23c 100644 --- a/lib/llvm-backend/src/state.rs +++ b/lib/llvm-backend/src/state.rs @@ -1,25 +1,38 @@ use inkwell::{ basic_block::BasicBlock, - values::{BasicValue, BasicValueEnum}, + values::{BasicValue, BasicValueEnum, PhiValue}, }; +use smallvec::SmallVec; +use std::cell::Cell; use wasmparser::BinaryReaderError; -enum ControlFrame { - If { - dest: BasicBlock, - stack_size_snapshot: usize, - }, +pub enum ControlFrame { Block { - dest: BasicBlock, + end_label: BasicBlock, + phis: SmallVec<[PhiValue; 1]>, stack_size_snapshot: usize, - num_ret_values: usize, }, } +impl ControlFrame { + pub fn dest(&self) -> &BasicBlock { + match self { + ControlFrame::Block { ref end_label, .. } => end_label, + } + } + + pub fn phis(&self) -> &[PhiValue] { + match self { + ControlFrame::Block { ref phis, .. } => phis.as_slice(), + } + } +} + pub struct State { stack: Vec, control_stack: Vec, - value_counter: usize, + value_counter: Cell, + block_counter: Cell, } impl State { @@ -27,13 +40,47 @@ impl State { Self { stack: vec![], control_stack: vec![], - value_counter: 0, + value_counter: Cell::new(0), + block_counter: Cell::new(0), } } - pub fn var_name(&mut self) -> String { - let s = self.value_counter.to_string(); - self.value_counter += 1; + pub fn reset_stack(&mut self, frame: &ControlFrame) { + let stack_size_snapshot = match frame { + ControlFrame::Block { + stack_size_snapshot, + .. + } => *stack_size_snapshot, + }; + self.stack.truncate(stack_size_snapshot); + } + + pub fn frame_at_depth(&self, depth: u32) -> Result<&ControlFrame, BinaryReaderError> { + let index = self.control_stack.len() - 1 - (depth as usize); + self.control_stack.get(index).ok_or(BinaryReaderError { + message: "invalid control stack depth", + offset: -1isize as usize, + }) + } + + pub fn pop_frame(&mut self) -> Result { + self.control_stack.pop().ok_or(BinaryReaderError { + message: "cannot pop from control stack", + offset: -1isize as usize, + }) + } + + pub fn block_name(&self) -> String { + let counter = self.block_counter.get(); + let s = format!("block{}", counter); + self.block_counter.set(counter + 1); + s + } + + pub fn var_name(&self) -> String { + let counter = self.value_counter.get(); + let s = format!("s{}", counter); + self.value_counter.set(counter + 1); s } @@ -42,7 +89,7 @@ impl State { } pub fn pop1(&mut self) -> Result { - self.stack.pop().ok_or_else(|| BinaryReaderError { + self.stack.pop().ok_or(BinaryReaderError { message: "invalid value stack", offset: -1isize as usize, }) @@ -66,7 +113,7 @@ impl State { pub fn peek1(&self) -> Result { self.stack .get(self.stack.len() - 1) - .ok_or_else(|| BinaryReaderError { + .ok_or(BinaryReaderError { message: "invalid value stack", offset: -1isize as usize, }) @@ -76,7 +123,7 @@ impl State { pub fn peekn(&self, n: usize) -> Result<&[BasicValueEnum], BinaryReaderError> { self.stack .get(self.stack.len() - n..) - .ok_or_else(|| BinaryReaderError { + .ok_or(BinaryReaderError { message: "invalid value stack", offset: -1isize as usize, }) @@ -95,11 +142,11 @@ impl State { Ok(()) } - pub fn push_block(&mut self, dest: BasicBlock, num_ret_values: usize) { + pub fn push_block(&mut self, end_label: BasicBlock, phis: SmallVec<[PhiValue; 1]>) { self.control_stack.push(ControlFrame::Block { - dest, + end_label, + phis, stack_size_snapshot: self.stack.len(), - num_ret_values, }); } } From 2572a0259b87e0852332b18026674dc178985313 Mon Sep 17 00:00:00 2001 From: Lachlan Sneff Date: Tue, 12 Feb 2019 18:02:00 -0800 Subject: [PATCH 04/75] Get control flow working (fingers crossed) --- lib/llvm-backend/src/code.rs | 233 ++++++++++++++++++++++++++--- lib/llvm-backend/src/intrinsics.rs | 39 +++++ lib/llvm-backend/src/lib.rs | 29 ++-- lib/llvm-backend/src/read_info.rs | 7 +- lib/llvm-backend/src/state.rs | 121 +++++++++++++-- 5 files changed, 377 insertions(+), 52 deletions(-) diff --git a/lib/llvm-backend/src/code.rs b/lib/llvm-backend/src/code.rs index 7a24f9fbf..e177cc375 100644 --- a/lib/llvm-backend/src/code.rs +++ b/lib/llvm-backend/src/code.rs @@ -2,21 +2,22 @@ use inkwell::{ builder::Builder, context::Context, module::Module, + passes::PassManager, types::{BasicType, BasicTypeEnum, FunctionType}, - values::{BasicValue, FunctionValue}, + values::{BasicValue, FunctionValue, PhiValue}, FloatPredicate, IntPredicate, }; use smallvec::SmallVec; use wasmer_runtime_core::{ module::ModuleInfo, structures::{Map, SliceMap, TypedIndex}, - types::{FuncIndex, FuncSig, LocalFuncIndex, LocalOrImport, SigIndex, Type}, + types::{FuncIndex, MemoryIndex, FuncSig, LocalFuncIndex, LocalOrImport, SigIndex, Type, MemoryType}, }; use wasmparser::{BinaryReaderError, CodeSectionReader, LocalsReader, Operator, OperatorsReader}; use crate::intrinsics::Intrinsics; use crate::read_info::type_to_type; -use crate::state::State; +use crate::state::{ControlFrame, IfElseState, State}; fn func_sig_to_llvm(context: &Context, intrinsics: &Intrinsics, sig: &FuncSig) -> FunctionType { let user_param_types = sig.params().iter().map(|&ty| type_to_llvm(intrinsics, ty)); @@ -116,10 +117,37 @@ fn parse_function( let llvm_sig = &signatures[sig_index]; let function = functions[func_index]; - let entry_block = context.append_basic_block(&function, "entry"); - builder.position_at_end(&entry_block); - let mut state = State::new(); + let entry_block = context.append_basic_block(&function, "entry"); + + let return_block = context.append_basic_block(&function, "return"); + builder.position_at_end(&return_block); + + let phis: SmallVec<[PhiValue; 1]> = func_sig + .returns() + .iter() + .map(|&wasmer_ty| type_to_llvm(intrinsics, wasmer_ty)) + .map(|ty| builder.build_phi(ty, &state.var_name())) + .collect(); + + match phis.as_slice() { + // No returns. + &[] => { + builder.build_return(None); + } + &[one_value] => { + let value = one_value.as_basic_value(); + builder.build_return(Some(&value)); + } + returns @ _ => { + // let struct_ty = llvm_sig.get_return_type().as_struct_type(); + // let ret_struct = struct_ty.const_zero(); + unimplemented!("multi-value returns not yet implemented") + } + } + + state.push_block(return_block, phis); + builder.position_at_end(&entry_block); let mut locals = Vec::with_capacity(locals_reader.get_count() as usize); locals.extend(function.get_param_iter().enumerate().map(|(index, param)| { @@ -163,7 +191,7 @@ fn parse_function( offset: -1isize as usize, })?; - let end_block = context.append_basic_block(&function, &state.block_name()); + let end_block = context.append_basic_block(&function, "end"); builder.position_at_end(&end_block); let phis = if let Ok(wasmer_ty) = type_to_type(ty) { @@ -180,12 +208,24 @@ fn parse_function( builder.position_at_end(¤t_block); } Operator::Loop { ty } => { + let loop_body = context.append_basic_block(&function, "loop_body"); + let loop_next = context.append_basic_block(&function, "loop_outer"); - // let loop_body = context.append_basic_block(&function, &state.block_name()); - // let next = context.append_basic_block(&function, &state.block_name()); - // builder.build_unconditional_branch(&body); - // let num_return_values = if ty == wasmparser::Type::EmptyBlockType { 0 } else { 1 }; - // state.push_loop(loop_body, next, num_return_values); + builder.build_unconditional_branch(&loop_body); + + builder.position_at_end(&loop_next); + let phis = if let Ok(wasmer_ty) = type_to_type(ty) { + let llvm_ty = type_to_llvm(intrinsics, wasmer_ty); + [llvm_ty] + .iter() + .map(|&ty| builder.build_phi(ty, &state.var_name())) + .collect() + } else { + SmallVec::new() + }; + + builder.position_at_end(&loop_body); + state.push_loop(loop_body, loop_next, phis); } Operator::Br { relative_depth } => { let frame = state.frame_at_depth(relative_depth)?; @@ -195,7 +235,13 @@ fn parse_function( offset: -1isize as usize, })?; - let values = state.peekn(frame.phis().len())?; + let value_len = if frame.is_loop() { + 0 + } else { + frame.phis().len() + }; + + let values = state.peekn(value_len)?; // For each result of the block we're branching to, // pop a value off the value stack and load it into @@ -204,11 +250,10 @@ fn parse_function( phi.add_incoming(&[(value, ¤t_block)]); } - builder.build_unconditional_branch(frame.dest()); + builder.build_unconditional_branch(frame.br_dest()); - state.popn(frame.phis().len())?; - - builder.build_unreachable(); + state.popn(value_len)?; + state.reachable = false; } Operator::BrIf { relative_depth } => { let cond = state.pop1()?; @@ -219,13 +264,19 @@ fn parse_function( offset: -1isize as usize, })?; - let param_stack = state.peekn(frame.phis().len())?; + let value_len = if frame.is_loop() { + 0 + } else { + frame.phis().len() + }; + + let param_stack = state.peekn(value_len)?; for (phi, value) in frame.phis().iter().zip(param_stack.iter()) { phi.add_incoming(&[(value, ¤t_block)]); } - let false_block = context.append_basic_block(&function, &state.block_name()); + let else_block = context.append_basic_block(&function, "else"); let cond_value = builder.build_int_compare( IntPredicate::NE, @@ -233,8 +284,8 @@ fn parse_function( intrinsics.i32_zero, &state.var_name(), ); - builder.build_conditional_branch(cond_value, frame.dest(), &false_block); - builder.position_at_end(&false_block); + builder.build_conditional_branch(cond_value, frame.br_dest(), &else_block); + builder.position_at_end(&else_block); } Operator::BrTable { ref table } => { let current_block = builder.get_insert_block().ok_or(BinaryReaderError { @@ -268,25 +319,131 @@ fn parse_function( phi.add_incoming(&[(value, ¤t_block)]); } - Ok((case_index_literal, frame.dest())) + Ok((case_index_literal, frame.br_dest())) }) .collect::>()?; - builder.build_switch(index.into_int_value(), default_frame.dest(), &cases[..]); + builder.build_switch(index.into_int_value(), default_frame.br_dest(), &cases[..]); state.popn(res_len)?; builder.build_unreachable(); } + Operator::If { ty } => { + let current_block = builder.get_insert_block().ok_or(BinaryReaderError { + message: "not currently in a block", + offset: -1isize as usize, + })?; + let if_then_block = context.append_basic_block(&function, "if_then"); + let if_else_block = context.append_basic_block(&function, "if_else"); + let end_block = context.append_basic_block(&function, "if_end"); + + let end_phis = { + builder.position_at_end(&end_block); + + let phis = if let Ok(wasmer_ty) = type_to_type(ty) { + let llvm_ty = type_to_llvm(intrinsics, wasmer_ty); + [llvm_ty] + .iter() + .map(|&ty| builder.build_phi(ty, &state.var_name())) + .collect() + } else { + SmallVec::new() + }; + + builder.position_at_end(¤t_block); + phis + }; + + let cond = state.pop1()?; + + let cond_value = builder.build_int_compare( + IntPredicate::NE, + cond.into_int_value(), + intrinsics.i32_zero, + &state.var_name(), + ); + + builder.build_conditional_branch(cond_value, &if_then_block, &if_else_block); + builder.position_at_end(&if_then_block); + state.push_if(if_then_block, if_else_block, end_block, end_phis); + } + Operator::Else => { + if state.reachable { + let frame = state.frame_at_depth(0)?; + builder.build_unconditional_branch(frame.code_after()); + let current_block = builder.get_insert_block().ok_or(BinaryReaderError { + message: "not currently in a block", + offset: -1isize as usize, + })?; + + for phi in frame.phis().to_vec().iter().rev() { + let value = state.pop1()?; + phi.add_incoming(&[(&value, ¤t_block)]) + } + } + + let (if_else_block, if_else_state) = if let ControlFrame::IfElse { + if_else, + if_else_state, + .. + } = state.frame_at_depth_mut(0)? + { + (if_else, if_else_state) + } else { + unreachable!() + }; + + *if_else_state = IfElseState::Else; + + builder.position_at_end(if_else_block); + state.reachable = true; + } Operator::End => { let frame = state.pop_frame()?; + let current_block = builder.get_insert_block().ok_or(BinaryReaderError { + message: "not currently in a block", + offset: -1isize as usize, + })?; + + if state.reachable { + builder.build_unconditional_branch(frame.code_after()); + + for phi in frame.phis().iter().rev() { + let value = state.pop1()?; + phi.add_incoming(&[(&value, ¤t_block)]) + } + } + + if let ControlFrame::IfElse { + if_else, + next, + phis, + if_else_state, + .. + } = &frame + { + if let IfElseState::If = if_else_state { + builder.position_at_end(if_else); + builder.build_unconditional_branch(next); + } + } + + builder.position_at_end(frame.code_after()); + state.reset_stack(&frame); + + state.reachable = true; // Push each phi value to the value stack. for phi in frame.phis() { state.push1(phi.as_basic_value()); } + } + Operator::Return => { + let frame = state.outermost_frame()?; - state.reset_stack(&frame); + builder.build_unconditional_branch(frame.br_dest()); + state.reachable = false; } Operator::Unreachable => { @@ -294,6 +451,7 @@ fn parse_function( // If llvm cannot prove that this is never touched, // it will emit a `ud2` instruction on x86_64 arches. builder.build_unreachable(); + state.reachable = false; } /*************************** @@ -1021,6 +1179,26 @@ fn parse_function( unimplemented!("waiting on better bitcasting support in inkwell") } + Operator::MemoryGrow { reserved } => { + + let memory_grow_const = intrinsics.i32_ty.const_int(reserved as u64, false); + + let memory_index = MemoryIndex::new(reserved); + match memory_index.local_or_import(info) { + LocalOrImport::Local(local_mem_index) => { + let mem_desc = &info.memories[local_mem_index]; + match mem_desc.memory_type() { + MemoryType::Dynamic => { + + } + } + }, + LocalOrImport::Import(import_mem_index) => { + + }, + } + } + op @ _ => { println!("{}", module.print_to_string().to_string()); unimplemented!("{:?}", op); @@ -1028,5 +1206,12 @@ fn parse_function( } } + let pass_manager = PassManager::create_for_module(); + pass_manager.add_promote_memory_to_register_pass(); + pass_manager.add_cfg_simplification_pass(); + pass_manager.run_on_module(module); + + println!("{}", module.print_to_string().to_string()); + Ok(()) } diff --git a/lib/llvm-backend/src/intrinsics.rs b/lib/llvm-backend/src/intrinsics.rs index 8eab37071..ff6847b3b 100644 --- a/lib/llvm-backend/src/intrinsics.rs +++ b/lib/llvm-backend/src/intrinsics.rs @@ -54,6 +54,22 @@ pub struct Intrinsics { pub i64_zero: IntValue, pub f32_zero: FloatValue, pub f64_zero: FloatValue, + + // VM intrinsics. + pub memory_grow_dynamic_local: FunctionValue, + pub memory_grow_static_local: FunctionValue, + pub memory_grow_shared_local: FunctionValue, + pub memory_grow_dynamic_import: FunctionValue, + pub memory_grow_static_import: FunctionValue, + pub memory_grow_shared_import: FunctionValue, + + pub memory_size_dynamic_local: FunctionValue, + pub memory_size_static_local: FunctionValue, + pub memory_size_shared_local: FunctionValue, + pub memory_size_dynamic_import: FunctionValue, + pub memory_size_static_import: FunctionValue, + pub memory_size_shared_import: FunctionValue, + // pub ctx_ty: StructType, } impl Intrinsics { @@ -64,6 +80,7 @@ impl Intrinsics { let i64_ty = context.i64_type(); let f32_ty = context.f32_type(); let f64_ty = context.f64_type(); + // let ctx_ty = context.struct_type(&[], false); let i1_zero = i1_ty.const_int(0, false); let i32_zero = i32_ty.const_int(0, false); @@ -89,6 +106,9 @@ impl Intrinsics { let ret_f32_take_f32_f32 = f32_ty.fn_type(&[f32_ty_basic, f32_ty_basic], false); let ret_f64_take_f64_f64 = f64_ty.fn_type(&[f64_ty_basic, f64_ty_basic], false); + let ret_i32_take_i64_i32_i32 = i32_ty.fn_type(&[i64_ty, i32_ty, i32_ty], false); + let ret_i32_take_i64_i32 = i32_ty.fn_type(&[i64_ty, i32_ty], false); + Self { ctlz_i32: module.add_function("llvm.ctlz.i32", ret_i32_take_i32_i1, None), ctlz_i64: module.add_function("llvm.ctlz.i64", ret_i64_take_i64_i1, None), @@ -138,6 +158,25 @@ impl Intrinsics { i64_zero, f32_zero, f64_zero, + + // VM intrinsics. + memory_grow_dynamic_local: module.add_function("vm.memory.grow.dynamic.local", ret_i32_take_i64_i32_i32, None), + memory_grow_static_local: module.add_function("vm.memory.grow.static.local", ret_i32_take_i64_i32_i32, None), + memory_grow_shared_local: module.add_function("vm.memory.grow.shared.local", ret_i32_take_i64_i32_i32, None), + memory_grow_dynamic_import: module.add_function("vm.memory.grow.dynamic.import", ret_i32_take_i64_i32_i32, None), + memory_grow_static_import: module.add_function("vm.memory.grow.static.import", ret_i32_take_i64_i32_i32, None), + memory_grow_shared_import: module.add_function("vm.memory.grow.shared.import", ret_i32_take_i64_i32_i32, None), + + memory_size_dynamic_local: module.add_function("vm.memory.size.dynamic.local", ret_i32_take_i64_i32, None), + memory_size_static_local: module.add_function("vm.memory.size.static.local", ret_i32_take_i64_i32, None), + memory_size_shared_local: module.add_function("vm.memory.size.shared.local", ret_i32_take_i64_i32, None), + memory_size_dynamic_import: module.add_function("vm.memory.size.dynamic.import", ret_i32_take_i64_i32, None), + memory_size_static_import: module.add_function("vm.memory.size.static.import", ret_i32_take_i64_i32, None), + memory_size_shared_import: module.add_function("vm.memory.size.shared.import", ret_i32_take_i64_i32, None), } } } + +// pub struct CtxType { +// ctx_ty: StructType, +// } diff --git a/lib/llvm-backend/src/lib.rs b/lib/llvm-backend/src/lib.rs index 69ed0fa0d..b02b39cbf 100644 --- a/lib/llvm-backend/src/lib.rs +++ b/lib/llvm-backend/src/lib.rs @@ -30,21 +30,26 @@ impl Compiler for LLVMCompiler { #[test] fn test_read_module() { use wabt::wat2wasm; - let WAT: &'static str = r#" + let wat = r#" (module (type $t0 (func (param i32) (result i32))) - (import "env" "memory" (memory 1 1)) - (import "env" "table" (table 10 anyfunc)) - (import "env" "global" (global i32)) - (import "env" "print_i32" (func $print_i32 (type $t0))) - (func $identity (type $t0) (param $p0 i32) (result i32) - get_local $p0) - (func $print_num (export "print_num") (type $t0) (param $p0 i32) (result i32) - get_global 0 - call $identity - call $print_i32)) + (type $t1 (func (result i32))) + (func $foo (type $t0) (param i32) (result i32) + get_local 0 + (if + (then + i32.const 42 + set_local 0 + ) + (else + i32.const 24 + set_local 0 + ) + ) + get_local 0 + )) "#; - let wasm = wat2wasm(WAT).unwrap(); + let wasm = wat2wasm(wat).unwrap(); let (info, code_reader) = read_info::read_module(&wasm).unwrap(); diff --git a/lib/llvm-backend/src/read_info.rs b/lib/llvm-backend/src/read_info.rs index c1ac2cf6b..bed91aa90 100644 --- a/lib/llvm-backend/src/read_info.rs +++ b/lib/llvm-backend/src/read_info.rs @@ -285,7 +285,12 @@ pub fn type_to_type(ty: WpType) -> Result { offset: -1isize as usize, }); } - _ => panic!("broken invariant, invalid type"), + _ => { + return Err(BinaryReaderError { + message: "that type is not supported as a wasmer type", + offset: -1isize as usize, + }); + } }) } diff --git a/lib/llvm-backend/src/state.rs b/lib/llvm-backend/src/state.rs index e85c7a23c..674eee04c 100644 --- a/lib/llvm-backend/src/state.rs +++ b/lib/llvm-backend/src/state.rs @@ -6,33 +6,73 @@ use smallvec::SmallVec; use std::cell::Cell; use wasmparser::BinaryReaderError; +#[derive(Debug)] pub enum ControlFrame { Block { - end_label: BasicBlock, + next: BasicBlock, phis: SmallVec<[PhiValue; 1]>, stack_size_snapshot: usize, }, + Loop { + body: BasicBlock, + next: BasicBlock, + phis: SmallVec<[PhiValue; 1]>, + stack_size_snapshot: usize, + }, + IfElse { + if_then: BasicBlock, + if_else: BasicBlock, + next: BasicBlock, + phis: SmallVec<[PhiValue; 1]>, + stack_size_snapshot: usize, + if_else_state: IfElseState, + }, +} + +#[derive(Debug)] +pub enum IfElseState { + If, + Else, } impl ControlFrame { - pub fn dest(&self) -> &BasicBlock { + pub fn code_after(&self) -> &BasicBlock { match self { - ControlFrame::Block { ref end_label, .. } => end_label, + ControlFrame::Block { ref next, .. } + | ControlFrame::Loop { ref next, .. } + | ControlFrame::IfElse { ref next, .. } => next, + } + } + + pub fn br_dest(&self) -> &BasicBlock { + match self { + ControlFrame::Block { ref next, .. } | ControlFrame::IfElse { ref next, .. } => next, + ControlFrame::Loop { ref body, .. } => body, } } pub fn phis(&self) -> &[PhiValue] { match self { - ControlFrame::Block { ref phis, .. } => phis.as_slice(), + ControlFrame::Block { ref phis, .. } + | ControlFrame::Loop { ref phis, .. } + | ControlFrame::IfElse { ref phis, .. } => phis.as_slice(), + } + } + + pub fn is_loop(&self) -> bool { + match self { + ControlFrame::Loop { .. } => true, + _ => false, } } } +#[derive(Debug)] pub struct State { stack: Vec, control_stack: Vec, value_counter: Cell, - block_counter: Cell, + pub reachable: bool, } impl State { @@ -41,7 +81,7 @@ impl State { stack: vec![], control_stack: vec![], value_counter: Cell::new(0), - block_counter: Cell::new(0), + reachable: true, } } @@ -50,11 +90,26 @@ impl State { ControlFrame::Block { stack_size_snapshot, .. + } + | ControlFrame::Loop { + stack_size_snapshot, + .. + } + | ControlFrame::IfElse { + stack_size_snapshot, + .. } => *stack_size_snapshot, }; self.stack.truncate(stack_size_snapshot); } + pub fn outermost_frame(&self) -> Result<&ControlFrame, BinaryReaderError> { + self.control_stack.get(0).ok_or(BinaryReaderError { + message: "invalid control stack depth", + offset: -1isize as usize, + }) + } + pub fn frame_at_depth(&self, depth: u32) -> Result<&ControlFrame, BinaryReaderError> { let index = self.control_stack.len() - 1 - (depth as usize); self.control_stack.get(index).ok_or(BinaryReaderError { @@ -63,6 +118,17 @@ impl State { }) } + pub fn frame_at_depth_mut( + &mut self, + depth: u32, + ) -> Result<&mut ControlFrame, BinaryReaderError> { + let index = self.control_stack.len() - 1 - (depth as usize); + self.control_stack.get_mut(index).ok_or(BinaryReaderError { + message: "invalid control stack depth", + offset: -1isize as usize, + }) + } + pub fn pop_frame(&mut self) -> Result { self.control_stack.pop().ok_or(BinaryReaderError { message: "cannot pop from control stack", @@ -70,13 +136,6 @@ impl State { }) } - pub fn block_name(&self) -> String { - let counter = self.block_counter.get(); - let s = format!("block{}", counter); - self.block_counter.set(counter + 1); - s - } - pub fn var_name(&self) -> String { let counter = self.value_counter.get(); let s = format!("s{}", counter); @@ -129,6 +188,12 @@ impl State { }) } + pub fn popn_save(&mut self, n: usize) -> Result, BinaryReaderError> { + let v = self.peekn(n)?.to_vec(); + self.popn(n)?; + Ok(v) + } + pub fn popn(&mut self, n: usize) -> Result<(), BinaryReaderError> { if self.stack.len() < n { return Err(BinaryReaderError { @@ -142,11 +207,37 @@ impl State { Ok(()) } - pub fn push_block(&mut self, end_label: BasicBlock, phis: SmallVec<[PhiValue; 1]>) { + pub fn push_block(&mut self, next: BasicBlock, phis: SmallVec<[PhiValue; 1]>) { self.control_stack.push(ControlFrame::Block { - end_label, + next, phis, stack_size_snapshot: self.stack.len(), }); } + + pub fn push_loop(&mut self, body: BasicBlock, next: BasicBlock, phis: SmallVec<[PhiValue; 1]>) { + self.control_stack.push(ControlFrame::Loop { + body, + next, + phis, + stack_size_snapshot: self.stack.len(), + }); + } + + pub fn push_if( + &mut self, + if_then: BasicBlock, + if_else: BasicBlock, + next: BasicBlock, + phis: SmallVec<[PhiValue; 1]>, + ) { + self.control_stack.push(ControlFrame::IfElse { + if_then, + if_else, + next, + phis, + stack_size_snapshot: self.stack.len(), + if_else_state: IfElseState::If, + }); + } } From 8827830aba96b5f9a99cf98f8b94eff2a7e5f6f5 Mon Sep 17 00:00:00 2001 From: Lachlan Sneff Date: Thu, 14 Feb 2019 15:13:58 -0800 Subject: [PATCH 05/75] implement load* and store* instructions --- Cargo.lock | 126 ++++---- lib/llvm-backend/src/code.rs | 463 +++++++++++++++++++++++++++-- lib/llvm-backend/src/intrinsics.rs | 334 +++++++++++++++++++-- lib/llvm-backend/src/lib.rs | 19 +- lib/llvm-backend/src/state.rs | 1 + 5 files changed, 811 insertions(+), 132 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 6adb5581c..758c7ac56 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3,7 +3,7 @@ name = "aho-corasick" version = "0.6.9" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "memchr 2.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -70,7 +70,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "cc" -version = "1.0.28" +version = "1.0.29" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -105,7 +105,7 @@ name = "cmake" version = "0.1.35" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -232,7 +232,7 @@ name = "failure_derive" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.26 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", "syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)", "synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -249,17 +249,8 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] -name = "fuchsia-zircon" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "fuchsia-zircon-sys" -version = "0.3.3" +name = "fuchsia-cprng" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -287,7 +278,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.85 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -306,7 +297,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "inkwell" version = "0.1.0" -source = "git+https://github.com/TheDan64/inkwell?branch=llvm7-0#83b9188bad1e098f97e6aad8f6d45becb6d1ccdd" +source = "git+https://github.com/TheDan64/inkwell?branch=llvm7-0#715423bc67f46518ec489343b52455a27c1ff761" dependencies = [ "either 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "enum-methods 0.0.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -318,7 +309,7 @@ dependencies = [ [[package]] name = "inkwell_internal_macros" version = "0.1.0" -source = "git+https://github.com/TheDan64/inkwell?branch=llvm7-0#83b9188bad1e098f97e6aad8f6d45becb6d1ccdd" +source = "git+https://github.com/TheDan64/inkwell?branch=llvm7-0#715423bc67f46518ec489343b52455a27c1ff761" dependencies = [ "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", "syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)", @@ -346,12 +337,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "libc" version = "0.2.48" -source = "git+https://github.com/rust-lang/libc#42cd3ba27254c423e03f6f4324de57075047f6a0" +source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "libc" -version = "0.2.48" -source = "registry+https://github.com/rust-lang/crates.io-index" +version = "0.2.49" +source = "git+https://github.com/rust-lang/libc#9a9e2e05c9532557362e5b24b0622259851392fa" [[package]] name = "llvm-backend" @@ -370,7 +361,7 @@ name = "llvm-sys" version = "70.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -396,12 +387,8 @@ dependencies = [ [[package]] name = "memchr" -version = "2.1.3" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", -] [[package]] name = "memmap" @@ -418,7 +405,7 @@ version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "cc 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)", "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -430,7 +417,7 @@ version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "cc 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)", "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -482,7 +469,7 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "0.4.26" +version = "0.4.27" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -498,7 +485,7 @@ name = "quote" version = "0.6.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.26 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -512,8 +499,8 @@ dependencies = [ "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_jitter 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_os 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_jitter 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_os 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "rand_pcg 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -559,7 +546,7 @@ dependencies = [ [[package]] name = "rand_jitter" -version = "0.1.0" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", @@ -569,13 +556,13 @@ dependencies = [ [[package]] name = "rand_os" -version = "0.1.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -603,7 +590,7 @@ version = "6.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "cc 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -634,7 +621,7 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "aho-corasick 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", - "memchr 2.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "regex-syntax 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "utf8-ranges 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -681,7 +668,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "serde" -version = "1.0.85" +version = "1.0.87" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -690,7 +677,7 @@ version = "0.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.85 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -698,27 +685,27 @@ name = "serde_bytes" version = "0.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "serde 1.0.85 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "serde_derive" -version = "1.0.85" +version = "1.0.87" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.26 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", "syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "serde_json" -version = "1.0.37" +version = "1.0.38" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", "ryu 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.85 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -765,7 +752,7 @@ version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro2 0.4.26 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", "syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -785,7 +772,7 @@ name = "syn" version = "0.15.26" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.26 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -803,7 +790,7 @@ name = "synstructure" version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.26 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", "syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -816,7 +803,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -913,9 +900,9 @@ name = "wabt" version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "serde 1.0.85 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.85 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)", "wabt-sys 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -924,7 +911,7 @@ name = "wabt-sys" version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)", "cmake 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)", "glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -954,10 +941,10 @@ dependencies = [ "hashbrown 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", "nix 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.85 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", "serde-bench 0.0.7 (registry+https://github.com/rust-lang/crates.io-index)", "serde_bytes 0.10.4 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.85 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", "target-lexicon 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "wasmer-runtime-core 0.1.2", "wasmparser 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -969,7 +956,7 @@ version = "0.1.0" dependencies = [ "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.48 (git+https://github.com/rust-lang/libc)", + "libc 0.2.49 (git+https://github.com/rust-lang/libc)", "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", "wabt 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)", "wasmer-clif-backend 0.1.2", @@ -999,10 +986,10 @@ dependencies = [ "nix 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "page_size 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.85 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", "serde-bench 0.0.7 (registry+https://github.com/rust-lang/crates.io-index)", "serde_bytes 0.10.4 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.85 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "wasmer-clif-backend 0.1.2", "wasmparser 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1073,7 +1060,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" "checksum byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a019b10a2a7cdeb292db131fc8113e57ea2a908f6e7894b0c3c671893b65dbeb" "checksum cast 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "926013f2860c46252efceabb19f4a6b308197505082c609025aa6706c011d427" -"checksum cc 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4a8b715cb4597106ea87c7c84b2f1d452c7492033765df7f32651e66fcf749" +"checksum cc 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)" = "4390a3b5f4f6bce9c1d0c00128379df433e53777fdd30e92f16a529332baec4e" "checksum cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "082bb9b28e00d3c9d39cc03e64ce4cea0f1bb9b3fde493f0cbc008472d22bdf4" "checksum clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b957d88f4b6a63b9d70d5f454ac8011819c6efa7727858f458ab71c756ce2d3e" "checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" @@ -1094,8 +1081,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "ea1063915fd7ef4309e222a5a07cf9c319fb9c7836b1f89b85458672dbb127e1" "checksum fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" "checksum field-offset 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "64e9bc339e426139e02601fa69d101e96a92aee71b58bc01697ec2a63a5c9e68" -"checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" -"checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" +"checksum fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" "checksum gcc 0.3.55 (registry+https://github.com/rust-lang/crates.io-index)" = "8f5f3913fa0bfe7ee1fd8248b6b9f42a5af4b9d65ec2dd2c3c26132b950ecfc2" "checksum generic-array 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3c0f28c2f5bfb5960175af447a2da7c18900693738343dc896ffbcabd9839592" "checksum glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "8be18de09a56b60ed0edf84bc9df007e30040691af7acd1c41874faac5895bfb" @@ -1107,12 +1093,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1306f3464951f30e30d12373d31c79fbd52d236e5e896fd92f96ec7babbbe60b" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" "checksum lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a374c89b9db55895453a74c1e38861d9deec0b01b405a82516e9d5de4820dea1" -"checksum libc 0.2.48 (git+https://github.com/rust-lang/libc)" = "" "checksum libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)" = "e962c7641008ac010fa60a7dfdc1712449f29c44ef2d4702394aea943ee75047" +"checksum libc 0.2.49 (git+https://github.com/rust-lang/libc)" = "" "checksum llvm-sys 70.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "60a9ee82fe0fa72ae6ef6d018b407296085863836451c7a97384f84ed7e26b9f" "checksum lock_api 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "62ebf1391f6acad60e5c8b43706dde4582df75c06698ab44511d15016bc2442c" "checksum log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c84ec4b527950aa83a329754b01dbe3f58361d1c5efacd1f6d68c494d08a17c6" -"checksum memchr 2.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e1dd4eaac298c32ce07eb6ed9242eda7d82955b9170b7d6db59b2e02cc63fcb8" +"checksum memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2efc7bc57c883d4a4d6e3246905283d8dae951bb3bd32f49d6ef297f546e1c39" "checksum memmap 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6585fd95e7bb50d6cc31e20d4cf9afb4e2ba16c5846fc76793f11218da9c475b" "checksum nix 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "921f61dc817b379d0834e45d5ec45beaacfae97082090a49c2cf30dcbc30206f" "checksum nix 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "46f0f3210768d796e8fa79ec70ee6af172dacbe7147f5e69be5240a47778302b" @@ -1121,7 +1107,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum page_size 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f89ef58b3d32420dbd1a43d2f38ae92f6239ef12bb556ab09ca55445f5a67242" "checksum parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ab41b4aed082705d1056416ae4468b6ea99d52599ecf3169b00088d43113e337" "checksum parking_lot_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "94c8c7923936b28d546dfd14d4472eaf34c99b14e1c973a32b3e6d4eb04298c9" -"checksum proc-macro2 0.4.26 (registry+https://github.com/rust-lang/crates.io-index)" = "38fddd23d98b2144d197c0eca5705632d4fe2667d14a6be5df8934f8d74f1978" +"checksum proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)" = "4d317f9caece796be1980837fd5cb3dfec5613ebdb04ad0956deea83ce168915" "checksum quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a" "checksum quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)" = "cdd8e04bd9c52e0342b406469d494fcb033be4bdbe5c606016defbb1681411e1" "checksum rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca" @@ -1130,8 +1116,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d0e7a549d590831370895ab7ba4ea0c1b6b011d106b5ff2da6eee112615e6dc0" "checksum rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b40677c7be09ae76218dc623efbf7b18e34bced3f38883af07bb75630a21bc4" "checksum rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ded997c9d5f13925be2a6fd7e66bf1872597f759fd9dd93513dd7e92e5a5ee08" -"checksum rand_jitter 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f47842851e13bd803b506bdd1345328e0a1394733ee58e627b5e39332b9afafe" -"checksum rand_os 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f46fbd5550acf75b0c2730f5dd1873751daf9beb8f11b44027778fae50d7feca" +"checksum rand_jitter 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7b9ea758282efe12823e0d952ddb269d2e1897227e464919a554f2a03ef1b832" +"checksum rand_os 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b7c690732391ae0abafced5015ffb53656abfaec61b342290e5eb56b286a679d" "checksum rand_pcg 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "086bd09a33c7044e56bb44d5bdde5a60e7f119a9e95b0775f545de759a32fe05" "checksum rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c" "checksum raw-cpuid 6.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "30a9d219c32c9132f7be513c18be77c9881c7107d2ab5569d205a6a0f0e6dc7d" @@ -1145,11 +1131,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27" "checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" "checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" -"checksum serde 1.0.85 (registry+https://github.com/rust-lang/crates.io-index)" = "534b8b91a95e0f71bca3ed5824752d558da048d4248c91af873b63bd60519752" +"checksum serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)" = "2e20fde37801e83c891a2dc4ebd3b81f0da4d1fb67a9e0a2a3b921e2536a58ee" "checksum serde-bench 0.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "d733da87e79faaac25616e33d26299a41143fd4cd42746cbb0e91d8feea243fd" "checksum serde_bytes 0.10.4 (registry+https://github.com/rust-lang/crates.io-index)" = "adb6e51a6b3696b301bc221d785f898b4457c619b51d7ce195a6d20baecb37b3" -"checksum serde_derive 1.0.85 (registry+https://github.com/rust-lang/crates.io-index)" = "a915306b0f1ac5607797697148c223bedeaa36bcc2e28a01441cd638cc6567b4" -"checksum serde_json 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)" = "4b90a9fbe1211e57d3e1c15670f1cb00802988fb23a1a4aad7a2b63544f1920e" +"checksum serde_derive 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)" = "633e97856567e518b59ffb2ad7c7a4fd4c5d91d9c7f32dd38a27b2bf7e8114ea" +"checksum serde_json 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)" = "27dce848e7467aa0e2fcaf0a413641499c0b745452aaca1194d24dedde9e13c9" "checksum sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b4d8bfd0e469f417657573d8451fb33d16cfe0989359b93baf3a1ffc639543d" "checksum smallvec 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)" = "88aea073965ab29f6edb5493faf96ad662fb18aa9eeb186a3b7057951605ed15" "checksum stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dba1a27d3efae4351c8051072d619e3ade2820635c3958d826bfea39d59b54c8" diff --git a/lib/llvm-backend/src/code.rs b/lib/llvm-backend/src/code.rs index e177cc375..fb9e53520 100644 --- a/lib/llvm-backend/src/code.rs +++ b/lib/llvm-backend/src/code.rs @@ -3,30 +3,35 @@ use inkwell::{ context::Context, module::Module, passes::PassManager, - types::{BasicType, BasicTypeEnum, FunctionType}, - values::{BasicValue, FunctionValue, PhiValue}, + types::{BasicType, BasicTypeEnum, FunctionType, PointerType}, + values::{BasicValue, FunctionValue, PhiValue, PointerValue}, FloatPredicate, IntPredicate, }; use smallvec::SmallVec; use wasmer_runtime_core::{ + memory::MemoryType, module::ModuleInfo, structures::{Map, SliceMap, TypedIndex}, - types::{FuncIndex, MemoryIndex, FuncSig, LocalFuncIndex, LocalOrImport, SigIndex, Type, MemoryType}, + types::{FuncIndex, FuncSig, LocalFuncIndex, LocalOrImport, MemoryIndex, SigIndex, Type}, +}; +use wasmparser::{ + BinaryReaderError, CodeSectionReader, LocalsReader, MemoryImmediate, Operator, OperatorsReader, }; -use wasmparser::{BinaryReaderError, CodeSectionReader, LocalsReader, Operator, OperatorsReader}; -use crate::intrinsics::Intrinsics; +use crate::intrinsics::{CtxType, Intrinsics}; use crate::read_info::type_to_type; use crate::state::{ControlFrame, IfElseState, State}; fn func_sig_to_llvm(context: &Context, intrinsics: &Intrinsics, sig: &FuncSig) -> FunctionType { let user_param_types = sig.params().iter().map(|&ty| type_to_llvm(intrinsics, ty)); - let param_types: Vec<_> = user_param_types.collect(); + let param_types: Vec<_> = std::iter::once(intrinsics.ctx_ptr_ty.as_basic_type_enum()) + .chain(user_param_types) + .collect(); match sig.returns() { - [] => intrinsics.void_ty.fn_type(¶m_types, false), - [single_value] => type_to_llvm(intrinsics, *single_value).fn_type(¶m_types, false), + &[] => intrinsics.void_ty.fn_type(¶m_types, false), + &[single_value] => type_to_llvm(intrinsics, single_value).fn_type(¶m_types, false), returns @ _ => { let basic_types: Vec<_> = returns .iter() @@ -149,14 +154,22 @@ fn parse_function( state.push_block(return_block, phis); builder.position_at_end(&entry_block); - let mut locals = Vec::with_capacity(locals_reader.get_count() as usize); - locals.extend(function.get_param_iter().enumerate().map(|(index, param)| { - let ty = param.get_type(); + let mut ctx = intrinsics.ctx(info, builder, &function); - let alloca = builder.build_alloca(ty, &format!("local{}", index)); - builder.build_store(alloca, param); - alloca - })); + let mut locals = Vec::with_capacity(locals_reader.get_count() as usize); + locals.extend( + function + .get_param_iter() + .skip(1) + .enumerate() + .map(|(index, param)| { + let ty = param.get_type(); + + let alloca = builder.build_alloca(ty, &format!("local{}", index)); + builder.build_store(alloca, param); + alloca + }), + ); for (index, local) in locals_reader.into_iter().enumerate().skip(locals.len()) { let (_, ty) = local?; @@ -520,11 +533,13 @@ fn parse_function( LocalOrImport::Local(local_func_index) => { let func_sig = &info.signatures[sigindex]; let func_value = functions[local_func_index]; - let call_site = builder.build_call( - func_value, - &state.peekn(func_sig.params().len())?.to_vec(), - &state.var_name(), - ); + let params: Vec<_> = [ctx.basic()] + .iter() + .chain(state.peekn(func_sig.params().len())?.iter()) + .map(|v| *v) + .collect(); + + let call_site = builder.build_call(func_value, ¶ms, &state.var_name()); if let Some(basic_value) = call_site.try_as_basic_value().left() { match func_sig.returns().len() { 1 => state.push1(basic_value), @@ -1179,24 +1194,378 @@ fn parse_function( unimplemented!("waiting on better bitcasting support in inkwell") } + /*************************** + * Load and Store instructions. + * https://github.com/sunfishcode/wasm-reference-manual/blob/master/WebAssembly.md#load-and-store-instructions + ***************************/ + Operator::I32Load { memarg } => { + let effective_address = resolve_memory_ptr( + builder, + intrinsics, + &mut state, + &mut ctx, + memarg, + intrinsics.i32_ptr_ty, + )?; + let result = builder.build_load(effective_address, &state.var_name()); + state.push1(result); + } + Operator::I64Load { memarg } => { + let effective_address = resolve_memory_ptr( + builder, + intrinsics, + &mut state, + &mut ctx, + memarg, + intrinsics.i64_ptr_ty, + )?; + let result = builder.build_load(effective_address, &state.var_name()); + state.push1(result); + } + Operator::F32Load { memarg } => { + let effective_address = resolve_memory_ptr( + builder, + intrinsics, + &mut state, + &mut ctx, + memarg, + intrinsics.i32_ptr_ty, + )?; + let result = builder.build_load(effective_address, &state.var_name()); + state.push1(result); + } + Operator::F64Load { memarg } => { + let effective_address = resolve_memory_ptr( + builder, + intrinsics, + &mut state, + &mut ctx, + memarg, + intrinsics.f64_ptr_ty, + )?; + let result = builder.build_load(effective_address, &state.var_name()); + state.push1(result); + } + + Operator::I32Store { memarg } => { + let value = state.pop1()?; + let effective_address = resolve_memory_ptr( + builder, + intrinsics, + &mut state, + &mut ctx, + memarg, + intrinsics.i32_ptr_ty, + )?; + builder.build_store(effective_address, value); + } + Operator::I64Store { memarg } => { + let value = state.pop1()?; + let effective_address = resolve_memory_ptr( + builder, + intrinsics, + &mut state, + &mut ctx, + memarg, + intrinsics.i64_ptr_ty, + )?; + builder.build_store(effective_address, value); + } + Operator::F32Store { memarg } => { + let value = state.pop1()?; + let effective_address = resolve_memory_ptr( + builder, + intrinsics, + &mut state, + &mut ctx, + memarg, + intrinsics.f32_ptr_ty, + )?; + builder.build_store(effective_address, value); + } + Operator::F64Store { memarg } => { + let value = state.pop1()?; + let effective_address = resolve_memory_ptr( + builder, + intrinsics, + &mut state, + &mut ctx, + memarg, + intrinsics.f64_ptr_ty, + )?; + builder.build_store(effective_address, value); + } + + Operator::I32Load8S { memarg } => { + let effective_address = resolve_memory_ptr( + builder, + intrinsics, + &mut state, + &mut ctx, + memarg, + intrinsics.i8_ptr_ty, + )?; + let narrow_result = builder + .build_load(effective_address, &state.var_name()) + .into_int_value(); + let result = + builder.build_int_s_extend(narrow_result, intrinsics.i32_ty, &state.var_name()); + state.push1(result); + } + Operator::I32Load16S { memarg } => { + let effective_address = resolve_memory_ptr( + builder, + intrinsics, + &mut state, + &mut ctx, + memarg, + intrinsics.i16_ptr_ty, + )?; + let narrow_result = builder + .build_load(effective_address, &state.var_name()) + .into_int_value(); + let result = + builder.build_int_s_extend(narrow_result, intrinsics.i32_ty, &state.var_name()); + state.push1(result); + } + Operator::I64Load8S { memarg } => { + let effective_address = resolve_memory_ptr( + builder, + intrinsics, + &mut state, + &mut ctx, + memarg, + intrinsics.i8_ptr_ty, + )?; + let narrow_result = builder + .build_load(effective_address, &state.var_name()) + .into_int_value(); + let result = + builder.build_int_s_extend(narrow_result, intrinsics.i64_ty, &state.var_name()); + state.push1(result); + } + Operator::I64Load16S { memarg } => { + let effective_address = resolve_memory_ptr( + builder, + intrinsics, + &mut state, + &mut ctx, + memarg, + intrinsics.i16_ptr_ty, + )?; + let narrow_result = builder + .build_load(effective_address, &state.var_name()) + .into_int_value(); + let result = + builder.build_int_s_extend(narrow_result, intrinsics.i64_ty, &state.var_name()); + state.push1(result); + } + Operator::I64Load32S { memarg } => { + let effective_address = resolve_memory_ptr( + builder, + intrinsics, + &mut state, + &mut ctx, + memarg, + intrinsics.i32_ptr_ty, + )?; + let narrow_result = builder + .build_load(effective_address, &state.var_name()) + .into_int_value(); + let result = + builder.build_int_s_extend(narrow_result, intrinsics.i64_ty, &state.var_name()); + state.push1(result); + } + + Operator::I32Load8U { memarg } => { + let effective_address = resolve_memory_ptr( + builder, + intrinsics, + &mut state, + &mut ctx, + memarg, + intrinsics.i8_ptr_ty, + )?; + let narrow_result = builder + .build_load(effective_address, &state.var_name()) + .into_int_value(); + let result = + builder.build_int_z_extend(narrow_result, intrinsics.i32_ty, &state.var_name()); + state.push1(result); + } + Operator::I32Load16U { memarg } => { + let effective_address = resolve_memory_ptr( + builder, + intrinsics, + &mut state, + &mut ctx, + memarg, + intrinsics.i16_ptr_ty, + )?; + let narrow_result = builder + .build_load(effective_address, &state.var_name()) + .into_int_value(); + let result = + builder.build_int_z_extend(narrow_result, intrinsics.i32_ty, &state.var_name()); + state.push1(result); + } + Operator::I64Load8U { memarg } => { + let effective_address = resolve_memory_ptr( + builder, + intrinsics, + &mut state, + &mut ctx, + memarg, + intrinsics.i8_ptr_ty, + )?; + let narrow_result = builder + .build_load(effective_address, &state.var_name()) + .into_int_value(); + let result = + builder.build_int_z_extend(narrow_result, intrinsics.i64_ty, &state.var_name()); + state.push1(result); + } + Operator::I64Load16U { memarg } => { + let effective_address = resolve_memory_ptr( + builder, + intrinsics, + &mut state, + &mut ctx, + memarg, + intrinsics.i16_ptr_ty, + )?; + let narrow_result = builder + .build_load(effective_address, &state.var_name()) + .into_int_value(); + let result = + builder.build_int_z_extend(narrow_result, intrinsics.i64_ty, &state.var_name()); + state.push1(result); + } + Operator::I64Load32U { memarg } => { + let effective_address = resolve_memory_ptr( + builder, + intrinsics, + &mut state, + &mut ctx, + memarg, + intrinsics.i32_ptr_ty, + )?; + let narrow_result = builder + .build_load(effective_address, &state.var_name()) + .into_int_value(); + let result = + builder.build_int_z_extend(narrow_result, intrinsics.i64_ty, &state.var_name()); + state.push1(result); + } + + Operator::I32Store8 { memarg } | Operator::I64Store8 { memarg } => { + let value = state.pop1()?.into_int_value(); + let effective_address = resolve_memory_ptr( + builder, + intrinsics, + &mut state, + &mut ctx, + memarg, + intrinsics.i8_ptr_ty, + )?; + let narrow_value = + builder.build_int_truncate(value, intrinsics.i8_ty, &state.var_name()); + builder.build_store(effective_address, narrow_value); + } + Operator::I32Store16 { memarg } | Operator::I64Store16 { memarg } => { + let value = state.pop1()?.into_int_value(); + let effective_address = resolve_memory_ptr( + builder, + intrinsics, + &mut state, + &mut ctx, + memarg, + intrinsics.i16_ptr_ty, + )?; + let narrow_value = + builder.build_int_truncate(value, intrinsics.i16_ty, &state.var_name()); + builder.build_store(effective_address, narrow_value); + } + Operator::I64Store32 { memarg } => { + let value = state.pop1()?.into_int_value(); + let effective_address = resolve_memory_ptr( + builder, + intrinsics, + &mut state, + &mut ctx, + memarg, + intrinsics.i32_ptr_ty, + )?; + let narrow_value = + builder.build_int_truncate(value, intrinsics.i32_ty, &state.var_name()); + builder.build_store(effective_address, narrow_value); + } + Operator::MemoryGrow { reserved } => { - - let memory_grow_const = intrinsics.i32_ty.const_int(reserved as u64, false); - - let memory_index = MemoryIndex::new(reserved); - match memory_index.local_or_import(info) { + let memory_index = MemoryIndex::new(reserved as usize); + let func_value = match memory_index.local_or_import(info) { LocalOrImport::Local(local_mem_index) => { let mem_desc = &info.memories[local_mem_index]; match mem_desc.memory_type() { - MemoryType::Dynamic => { - - } + MemoryType::Dynamic => intrinsics.memory_grow_dynamic_local, + MemoryType::Static => intrinsics.memory_grow_static_local, + MemoryType::SharedStatic => intrinsics.memory_grow_shared_local, } - }, + } LocalOrImport::Import(import_mem_index) => { + let mem_desc = &info.imported_memories[import_mem_index].1; + match mem_desc.memory_type() { + MemoryType::Dynamic => intrinsics.memory_grow_dynamic_import, + MemoryType::Static => intrinsics.memory_grow_static_import, + MemoryType::SharedStatic => intrinsics.memory_grow_shared_import, + } + } + }; - }, - } + let memory_index_const = intrinsics + .i32_ty + .const_int(reserved as u64, false) + .as_basic_value_enum(); + let delta = state.pop1()?; + + let result = builder.build_call( + func_value, + &[ctx.basic(), memory_index_const, delta], + &state.var_name(), + ); + state.push1(result.try_as_basic_value().left().unwrap()); + } + Operator::MemorySize { reserved } => { + let memory_index = MemoryIndex::new(reserved as usize); + let func_value = match memory_index.local_or_import(info) { + LocalOrImport::Local(local_mem_index) => { + let mem_desc = &info.memories[local_mem_index]; + match mem_desc.memory_type() { + MemoryType::Dynamic => intrinsics.memory_size_dynamic_local, + MemoryType::Static => intrinsics.memory_size_static_local, + MemoryType::SharedStatic => intrinsics.memory_size_shared_local, + } + } + LocalOrImport::Import(import_mem_index) => { + let mem_desc = &info.imported_memories[import_mem_index].1; + match mem_desc.memory_type() { + MemoryType::Dynamic => intrinsics.memory_size_dynamic_import, + MemoryType::Static => intrinsics.memory_size_static_import, + MemoryType::SharedStatic => intrinsics.memory_size_shared_import, + } + } + }; + + let memory_index_const = intrinsics + .i32_ty + .const_int(reserved as u64, false) + .as_basic_value_enum(); + let result = builder.build_call( + func_value, + &[ctx.basic(), memory_index_const], + &state.var_name(), + ); + state.push1(result.try_as_basic_value().left().unwrap()); } op @ _ => { @@ -1209,9 +1578,41 @@ fn parse_function( let pass_manager = PassManager::create_for_module(); pass_manager.add_promote_memory_to_register_pass(); pass_manager.add_cfg_simplification_pass(); + pass_manager.add_instruction_combining_pass(); + // pass_manager.add_aggressive_inst_combiner_pass(); + // pass_manager.add_merged_load_store_motion_pass(); + // pass_manager.add_sccp_pass(); + pass_manager.add_gvn_pass(); + pass_manager.add_new_gvn_pass(); + pass_manager.add_aggressive_dce_pass(); pass_manager.run_on_module(module); println!("{}", module.print_to_string().to_string()); Ok(()) } + +fn resolve_memory_ptr( + builder: &Builder, + intrinsics: &Intrinsics, + state: &mut State, + ctx: &mut CtxType, + memarg: MemoryImmediate, + ptr_ty: PointerType, +) -> Result { + // Ignore alignment hint for the time being. + let imm_offset = intrinsics.i64_ty.const_int(memarg.offset as u64, false); + let var_offset_i32 = state.pop1()?.into_int_value(); + let var_offset = + builder.build_int_z_extend(var_offset_i32, intrinsics.i64_ty, &state.var_name()); + let effective_offset = builder.build_int_add(var_offset, imm_offset, &state.var_name()); + let (mem_base, mem_bound) = ctx.memory(MemoryIndex::new(0)); + let mem_base_int = builder.build_ptr_to_int(mem_base, intrinsics.i64_ty, &state.var_name()); + let effective_address_int = + builder.build_int_add(mem_base_int, effective_offset, &state.var_name()); + Ok(builder.build_int_to_ptr( + effective_address_int, + intrinsics.i32_ptr_ty, + &state.var_name(), + )) +} diff --git a/lib/llvm-backend/src/intrinsics.rs b/lib/llvm-backend/src/intrinsics.rs index ff6847b3b..f2e681f38 100644 --- a/lib/llvm-backend/src/intrinsics.rs +++ b/lib/llvm-backend/src/intrinsics.rs @@ -1,8 +1,18 @@ +use hashbrown::HashMap; use inkwell::{ + builder::Builder, context::Context, module::Module, - types::{BasicType, FloatType, IntType, VoidType}, - values::{FloatValue, FunctionValue, IntValue}, + types::{BasicType, FloatType, IntType, PointerType, StructType, VoidType}, + values::{BasicValue, BasicValueEnum, FloatValue, FunctionValue, IntValue, PointerValue}, + AddressSpace, +}; +use std::marker::PhantomData; +use wasmer_runtime_core::{ + memory::MemoryType, + module::ModuleInfo, + structures::TypedIndex, + types::{LocalOrImport, MemoryIndex}, }; pub struct Intrinsics { @@ -44,11 +54,20 @@ pub struct Intrinsics { pub void_ty: VoidType, pub i1_ty: IntType, + pub i8_ty: IntType, + pub i16_ty: IntType, pub i32_ty: IntType, pub i64_ty: IntType, pub f32_ty: FloatType, pub f64_ty: FloatType, + pub i8_ptr_ty: PointerType, + pub i16_ptr_ty: PointerType, + pub i32_ptr_ty: PointerType, + pub i64_ptr_ty: PointerType, + pub f32_ptr_ty: PointerType, + pub f64_ptr_ty: PointerType, + pub i1_zero: IntValue, pub i32_zero: IntValue, pub i64_zero: IntValue, @@ -69,18 +88,30 @@ pub struct Intrinsics { pub memory_size_dynamic_import: FunctionValue, pub memory_size_static_import: FunctionValue, pub memory_size_shared_import: FunctionValue, - // pub ctx_ty: StructType, + + ctx_ty: StructType, + pub ctx_ptr_ty: PointerType, } impl Intrinsics { pub fn declare(module: &Module, context: &Context) -> Self { let void_ty = context.void_type(); let i1_ty = context.bool_type(); + let i8_ty = context.i8_type(); + let i16_ty = context.i16_type(); let i32_ty = context.i32_type(); let i64_ty = context.i64_type(); let f32_ty = context.f32_type(); let f64_ty = context.f64_type(); - // let ctx_ty = context.struct_type(&[], false); + + let i8_ptr_ty = i8_ty.ptr_type(AddressSpace::Generic); + let i16_ptr_ty = i16_ty.ptr_type(AddressSpace::Generic); + let i32_ptr_ty = i32_ty.ptr_type(AddressSpace::Generic); + let i64_ptr_ty = i64_ty.ptr_type(AddressSpace::Generic); + let f32_ptr_ty = f32_ty.ptr_type(AddressSpace::Generic); + let f64_ptr_ty = f64_ty.ptr_type(AddressSpace::Generic); + + let opaque_ptr_ty = void_ty.ptr_type(AddressSpace::Generic); let i1_zero = i1_ty.const_int(0, false); let i32_zero = i32_ty.const_int(0, false); @@ -93,6 +124,53 @@ impl Intrinsics { let i64_ty_basic = i64_ty.as_basic_type_enum(); let f32_ty_basic = f32_ty.as_basic_type_enum(); let f64_ty_basic = f64_ty.as_basic_type_enum(); + let i8_ptr_ty_basic = i8_ptr_ty.as_basic_type_enum(); + let opaque_ptr_ty_basic = opaque_ptr_ty.as_basic_type_enum(); + + let ctx_ty = context.opaque_struct_type("ctx"); + let ctx_ptr_ty = ctx_ty.ptr_type(AddressSpace::Generic); + + let local_memory_ty = + context.struct_type(&[i8_ptr_ty_basic, i64_ty_basic, opaque_ptr_ty_basic], false); + let local_table_ty = local_memory_ty; + let local_global_ty = i64_ty; + let imported_func_ty = context.struct_type( + &[opaque_ptr_ty_basic, ctx_ptr_ty.as_basic_type_enum()], + false, + ); + ctx_ty.set_body( + &[ + local_memory_ty + .ptr_type(AddressSpace::Generic) + .ptr_type(AddressSpace::Generic) + .as_basic_type_enum(), + local_table_ty + .ptr_type(AddressSpace::Generic) + .ptr_type(AddressSpace::Generic) + .as_basic_type_enum(), + local_global_ty + .ptr_type(AddressSpace::Generic) + .ptr_type(AddressSpace::Generic) + .as_basic_type_enum(), + local_memory_ty + .ptr_type(AddressSpace::Generic) + .ptr_type(AddressSpace::Generic) + .as_basic_type_enum(), + local_table_ty + .ptr_type(AddressSpace::Generic) + .ptr_type(AddressSpace::Generic) + .as_basic_type_enum(), + local_global_ty + .ptr_type(AddressSpace::Generic) + .ptr_type(AddressSpace::Generic) + .as_basic_type_enum(), + imported_func_ty + .ptr_type(AddressSpace::Generic) + .ptr_type(AddressSpace::Generic) + .as_basic_type_enum(), + ], + false, + ); let ret_i32_take_i32_i1 = i32_ty.fn_type(&[i32_ty_basic, i1_ty_basic], false); let ret_i64_take_i64_i1 = i64_ty.fn_type(&[i64_ty_basic, i1_ty_basic], false); @@ -106,8 +184,9 @@ impl Intrinsics { let ret_f32_take_f32_f32 = f32_ty.fn_type(&[f32_ty_basic, f32_ty_basic], false); let ret_f64_take_f64_f64 = f64_ty.fn_type(&[f64_ty_basic, f64_ty_basic], false); - let ret_i32_take_i64_i32_i32 = i32_ty.fn_type(&[i64_ty, i32_ty, i32_ty], false); - let ret_i32_take_i64_i32 = i32_ty.fn_type(&[i64_ty, i32_ty], false); + let ret_i32_take_i64_i32_i32 = + i32_ty.fn_type(&[i64_ty_basic, i32_ty_basic, i32_ty_basic], false); + let ret_i32_take_i64_i32 = i32_ty.fn_type(&[i64_ty_basic, i32_ty_basic], false); Self { ctlz_i32: module.add_function("llvm.ctlz.i32", ret_i32_take_i32_i1, None), @@ -148,11 +227,20 @@ impl Intrinsics { void_ty, i1_ty, + i8_ty, + i16_ty, i32_ty, i64_ty, f32_ty, f64_ty, + i8_ptr_ty, + i16_ptr_ty, + i32_ptr_ty, + i64_ptr_ty, + f32_ptr_ty, + f64_ptr_ty, + i1_zero, i32_zero, i64_zero, @@ -160,23 +248,229 @@ impl Intrinsics { f64_zero, // VM intrinsics. - memory_grow_dynamic_local: module.add_function("vm.memory.grow.dynamic.local", ret_i32_take_i64_i32_i32, None), - memory_grow_static_local: module.add_function("vm.memory.grow.static.local", ret_i32_take_i64_i32_i32, None), - memory_grow_shared_local: module.add_function("vm.memory.grow.shared.local", ret_i32_take_i64_i32_i32, None), - memory_grow_dynamic_import: module.add_function("vm.memory.grow.dynamic.import", ret_i32_take_i64_i32_i32, None), - memory_grow_static_import: module.add_function("vm.memory.grow.static.import", ret_i32_take_i64_i32_i32, None), - memory_grow_shared_import: module.add_function("vm.memory.grow.shared.import", ret_i32_take_i64_i32_i32, None), + memory_grow_dynamic_local: module.add_function( + "vm.memory.grow.dynamic.local", + ret_i32_take_i64_i32_i32, + None, + ), + memory_grow_static_local: module.add_function( + "vm.memory.grow.static.local", + ret_i32_take_i64_i32_i32, + None, + ), + memory_grow_shared_local: module.add_function( + "vm.memory.grow.shared.local", + ret_i32_take_i64_i32_i32, + None, + ), + memory_grow_dynamic_import: module.add_function( + "vm.memory.grow.dynamic.import", + ret_i32_take_i64_i32_i32, + None, + ), + memory_grow_static_import: module.add_function( + "vm.memory.grow.static.import", + ret_i32_take_i64_i32_i32, + None, + ), + memory_grow_shared_import: module.add_function( + "vm.memory.grow.shared.import", + ret_i32_take_i64_i32_i32, + None, + ), - memory_size_dynamic_local: module.add_function("vm.memory.size.dynamic.local", ret_i32_take_i64_i32, None), - memory_size_static_local: module.add_function("vm.memory.size.static.local", ret_i32_take_i64_i32, None), - memory_size_shared_local: module.add_function("vm.memory.size.shared.local", ret_i32_take_i64_i32, None), - memory_size_dynamic_import: module.add_function("vm.memory.size.dynamic.import", ret_i32_take_i64_i32, None), - memory_size_static_import: module.add_function("vm.memory.size.static.import", ret_i32_take_i64_i32, None), - memory_size_shared_import: module.add_function("vm.memory.size.shared.import", ret_i32_take_i64_i32, None), + memory_size_dynamic_local: module.add_function( + "vm.memory.size.dynamic.local", + ret_i32_take_i64_i32, + None, + ), + memory_size_static_local: module.add_function( + "vm.memory.size.static.local", + ret_i32_take_i64_i32, + None, + ), + memory_size_shared_local: module.add_function( + "vm.memory.size.shared.local", + ret_i32_take_i64_i32, + None, + ), + memory_size_dynamic_import: module.add_function( + "vm.memory.size.dynamic.import", + ret_i32_take_i64_i32, + None, + ), + memory_size_static_import: module.add_function( + "vm.memory.size.static.import", + ret_i32_take_i64_i32, + None, + ), + memory_size_shared_import: module.add_function( + "vm.memory.size.shared.import", + ret_i32_take_i64_i32, + None, + ), + + ctx_ty, + ctx_ptr_ty, + } + } + + pub fn ctx<'a>( + &'a self, + info: &'a ModuleInfo, + builder: &'a Builder, + func_value: &'a FunctionValue, + ) -> CtxType<'a> { + CtxType { + ctx_ty: self.ctx_ty, + ctx_ptr_ty: self.ctx_ptr_ty, + + ctx_ptr_value: func_value.get_nth_param(0).unwrap().into_pointer_value(), + + builder, + intrinsics: self, + info, + + cached_memories: HashMap::new(), + + _phantom: PhantomData, } } } -// pub struct CtxType { -// ctx_ty: StructType, +enum MemoryCache { + /// The memory moves around. + Dynamic { + ptr_to_base_ptr: PointerValue, + ptr_to_bounds: PointerValue, + }, + /// The memory is always in the same place. + Static { + base_ptr: PointerValue, + bounds: IntValue, + }, +} + +pub struct CtxType<'a> { + ctx_ty: StructType, + ctx_ptr_ty: PointerType, + + ctx_ptr_value: PointerValue, + + builder: &'a Builder, + intrinsics: &'a Intrinsics, + info: &'a ModuleInfo, + + cached_memories: HashMap, + + _phantom: PhantomData<&'a FunctionValue>, +} + +impl<'a> CtxType<'a> { + pub fn basic(&self) -> BasicValueEnum { + self.ctx_ptr_value.as_basic_value_enum() + } + + pub fn memory(&mut self, index: MemoryIndex) -> (PointerValue, IntValue) { + let (cached_memories, builder, info, ctx_ptr_value, intrinsics) = ( + &mut self.cached_memories, + self.builder, + self.info, + self.ctx_ptr_value, + self.intrinsics, + ); + + let memory_cache = cached_memories.entry(index).or_insert_with(|| { + let (memory_array_ptr_ptr, index, memory_type) = match index.local_or_import(info) { + LocalOrImport::Local(local_mem_index) => ( + unsafe { builder.build_struct_gep(ctx_ptr_value, 0, "memory_array_ptr_ptr") }, + local_mem_index.index() as u64, + info.memories[local_mem_index].memory_type(), + ), + LocalOrImport::Import(import_mem_index) => ( + unsafe { builder.build_struct_gep(ctx_ptr_value, 3, "memory_array_ptr_ptr") }, + import_mem_index.index() as u64, + info.imported_memories[import_mem_index].1.memory_type(), + ), + }; + + let memory_array_ptr = builder + .build_load(memory_array_ptr_ptr, "memory_array_ptr") + .into_pointer_value(); + let const_index = intrinsics.i32_ty.const_int(index, false); + let memory_ptr_ptr = unsafe { + builder.build_in_bounds_gep(memory_array_ptr, &[const_index], "memory_ptr_ptr") + }; + let memory_ptr = builder + .build_load(memory_ptr_ptr, "memory_ptr") + .into_pointer_value(); + + let (ptr_to_base_ptr, ptr_to_bounds) = unsafe { + ( + builder.build_struct_gep(memory_ptr, 0, "base_ptr"), + builder.build_struct_gep(memory_ptr, 1, "bounds_ptr"), + ) + }; + + match memory_type { + MemoryType::Dynamic => MemoryCache::Dynamic { + ptr_to_base_ptr, + ptr_to_bounds, + }, + MemoryType::Static | MemoryType::SharedStatic => MemoryCache::Static { + base_ptr: builder + .build_load(ptr_to_base_ptr, "base") + .into_pointer_value(), + bounds: builder.build_load(ptr_to_bounds, "bounds").into_int_value(), + }, + } + }); + + match memory_cache { + MemoryCache::Dynamic { + ptr_to_base_ptr, + ptr_to_bounds, + } => { + let base = builder + .build_load(*ptr_to_base_ptr, "base") + .into_pointer_value(); + let bounds = builder + .build_load(*ptr_to_bounds, "bounds") + .into_int_value(); + + (base, bounds) + } + MemoryCache::Static { base_ptr, bounds } => (*base_ptr, *bounds), + } + } +} + +// pub struct Ctx { +// /// A pointer to an array of locally-defined memories, indexed by `MemoryIndex`. +// pub(crate) memories: *mut *mut LocalMemory, + +// /// A pointer to an array of locally-defined tables, indexed by `TableIndex`. +// pub(crate) tables: *mut *mut LocalTable, + +// /// A pointer to an array of locally-defined globals, indexed by `GlobalIndex`. +// pub(crate) globals: *mut *mut LocalGlobal, + +// /// A pointer to an array of imported memories, indexed by `MemoryIndex, +// pub(crate) imported_memories: *mut *mut LocalMemory, + +// /// A pointer to an array of imported tables, indexed by `TableIndex`. +// pub(crate) imported_tables: *mut *mut LocalTable, + +// /// A pointer to an array of imported globals, indexed by `GlobalIndex`. +// pub(crate) imported_globals: *mut *mut LocalGlobal, + +// /// A pointer to an array of imported functions, indexed by `FuncIndex`. +// pub(crate) imported_funcs: *mut ImportedFunc, + +// local_backing: *mut LocalBacking, +// import_backing: *mut ImportBacking, +// module: *const ModuleInner, + +// pub data: *mut c_void, +// pub data_finalizer: Option, // } diff --git a/lib/llvm-backend/src/lib.rs b/lib/llvm-backend/src/lib.rs index b02b39cbf..e691acebb 100644 --- a/lib/llvm-backend/src/lib.rs +++ b/lib/llvm-backend/src/lib.rs @@ -34,19 +34,16 @@ fn test_read_module() { (module (type $t0 (func (param i32) (result i32))) (type $t1 (func (result i32))) + (memory 1) (func $foo (type $t0) (param i32) (result i32) get_local 0 - (if - (then - i32.const 42 - set_local 0 - ) - (else - i32.const 24 - set_local 0 - ) - ) - get_local 0 + i32.load offset=16 + i32.const 1 + memory.grow + drop + i32.const 0 + i32.load offset=4 + i32.add )) "#; let wasm = wat2wasm(wat).unwrap(); diff --git a/lib/llvm-backend/src/state.rs b/lib/llvm-backend/src/state.rs index 674eee04c..47da54a6d 100644 --- a/lib/llvm-backend/src/state.rs +++ b/lib/llvm-backend/src/state.rs @@ -72,6 +72,7 @@ pub struct State { stack: Vec, control_stack: Vec, value_counter: Cell, + pub reachable: bool, } From 73b4f7d33796a3318968752ae792e0e54e666531 Mon Sep 17 00:00:00 2001 From: Lachlan Sneff Date: Thu, 14 Feb 2019 18:08:20 -0800 Subject: [PATCH 06/75] Implement memory and global operations --- Cargo.lock | 1358 ++++++++++++++++++++++++++++ lib/llvm-backend/src/code.rs | 171 +++- lib/llvm-backend/src/intrinsics.rs | 190 +++- lib/llvm-backend/src/lib.rs | 11 +- 4 files changed, 1665 insertions(+), 65 deletions(-) create mode 100644 Cargo.lock diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 000000000..065209f0b --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,1358 @@ +[[package]] +name = "aho-corasick" +version = "0.6.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "ansi_term" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "atty" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "autocfg" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "backtrace" +version = "0.3.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "backtrace-sys 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-demangle 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "backtrace-sys" +version = "0.1.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cc 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "bindgen" +version = "0.46.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "cexpr 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "clang-sys 0.26.4 (registry+https://github.com/rust-lang/crates.io-index)", + "clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)", + "env_logger 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "hashbrown 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "peeking_take_while 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "which 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "bitflags" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "block-buffer" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "block-padding 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "generic-array 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "block-padding" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "byte-tools" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "byteorder" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "cast" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "cc" +version = "1.0.29" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "cexpr" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "nom 4.2.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "cfg-if" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "clang-sys" +version = "0.26.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "libloading 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "clap" +version = "2.32.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "textwrap 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "cloudabi" +version = "0.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "cmake" +version = "0.1.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cc 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "cranelift-bforest" +version = "0.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cranelift-entity 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "cranelift-codegen" +version = "0.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cranelift-bforest 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cranelift-codegen-meta 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cranelift-entity 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)", + "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "target-lexicon 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "cranelift-codegen-meta" +version = "0.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cranelift-entity 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "cranelift-entity" +version = "0.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "cranelift-frontend" +version = "0.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cranelift-codegen 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "target-lexicon 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "cranelift-native" +version = "0.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cranelift-codegen 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)", + "raw-cpuid 6.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "target-lexicon 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "cranelift-wasm" +version = "0.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cast 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "cranelift-codegen 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cranelift-entity 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cranelift-frontend 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)", + "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "wasmparser 0.22.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "digest" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "generic-array 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "either" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "enum-methods" +version = "0.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "env_logger" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "humantime 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "termcolor 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "errno" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "errno-dragonfly 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "errno-dragonfly" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "gcc 0.3.55 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "failure" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "backtrace 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)", + "failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "failure_derive" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)", + "synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "fake-simd" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "field-offset" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "fuchsia-cprng" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "gcc" +version = "0.3.55" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "generic-array" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "glob" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "hashbrown" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "heck" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "unicode-segmentation 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "humantime" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "indexmap" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "inkwell" +version = "0.1.0" +source = "git+https://github.com/TheDan64/inkwell?branch=llvm7-0#715423bc67f46518ec489343b52455a27c1ff761" +dependencies = [ + "either 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "enum-methods 0.0.8 (registry+https://github.com/rust-lang/crates.io-index)", + "inkwell_internal_macros 0.1.0 (git+https://github.com/TheDan64/inkwell?branch=llvm7-0)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "llvm-sys 70.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "inkwell_internal_macros" +version = "0.1.0" +source = "git+https://github.com/TheDan64/inkwell?branch=llvm7-0#715423bc67f46518ec489343b52455a27c1ff761" +dependencies = [ + "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "itoa" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "kernel32-sys" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "lazy_static" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "libc" +version = "0.2.48" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "libc" +version = "0.2.49" +source = "git+https://github.com/rust-lang/libc#9a9e2e05c9532557362e5b24b0622259851392fa" + +[[package]] +name = "libloading" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cc 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "llvm-backend" +version = "0.1.0" +dependencies = [ + "hashbrown 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "inkwell 0.1.0 (git+https://github.com/TheDan64/inkwell?branch=llvm7-0)", + "smallvec 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", + "wabt 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)", + "wasmer-runtime-core 0.1.2", + "wasmparser 0.28.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "llvm-sys" +version = "70.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cc 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "lock_api" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "owning_ref 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "log" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "memchr" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "memmap" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "nix" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "nix" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "nom" +version = "4.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "opaque-debug" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "owning_ref" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "page_size" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "parking_lot" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "lock_api 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "parking_lot_core" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "peeking_take_while" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "proc-macro2" +version = "0.4.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "quick-error" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "quote" +version = "0.3.15" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "quote" +version = "0.6.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_jitter 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_os 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_pcg 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand_chacha" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand_core" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand_core" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "rand_hc" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand_isaac" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand_jitter" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand_os" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand_pcg" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand_xorshift" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "raw-cpuid" +version = "6.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rdrand" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "redox_syscall" +version = "0.1.51" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "redox_termios" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "regex" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "aho-corasick 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "regex-syntax 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "utf8-ranges 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "regex-syntax" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "ucd-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rustc-demangle" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "rustc_version" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "ryu" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "scopeguard" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "semver" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "semver-parser" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "serde" +version = "1.0.87" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "serde-bench" +version = "0.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "serde_bytes" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "serde_derive" +version = "1.0.87" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "serde_json" +version = "1.0.38" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", + "ryu 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "sha2" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "block-buffer 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "digest 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "opaque-debug 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "smallvec" +version = "0.6.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "stable_deref_trait" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "strsim" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "structopt" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)", + "structopt-derive 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "structopt-derive" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "syn" +version = "0.11.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", + "synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "syn" +version = "0.15.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "synom" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "synstructure" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "target-lexicon" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "termcolor" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "wincolor 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "termion" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "textwrap" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "thread_local" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "time" +version = "0.1.42" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "typenum" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "ucd-util" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "unicode-segmentation" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "unicode-width" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "unicode-xid" +version = "0.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "unicode-xid" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "unreachable" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "utf8-ranges" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "vec_map" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "version_check" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "void" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "wabt" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)", + "wabt-sys 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "wabt-sys" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cc 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)", + "cmake 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)", + "glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "wasmer" +version = "0.1.4" +dependencies = [ + "glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "structopt 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", + "wabt 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)", + "wasmer-clif-backend 0.1.2", + "wasmer-emscripten 0.1.0", + "wasmer-runtime 0.1.4", + "wasmer-runtime-core 0.1.2", +] + +[[package]] +name = "wasmer-clif-backend" +version = "0.1.2" +dependencies = [ + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "cranelift-codegen 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cranelift-entity 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cranelift-native 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cranelift-wasm 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)", + "hashbrown 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "nix 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", + "serde-bench 0.0.7 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_bytes 0.10.4 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", + "target-lexicon 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "wasmer-runtime-core 0.1.2", + "wasmer-win-exception-handler 0.0.1", + "wasmparser 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "wasmer-emscripten" +version = "0.1.0" +dependencies = [ + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.49 (git+https://github.com/rust-lang/libc)", + "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", + "wabt 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)", + "wasmer-clif-backend 0.1.2", + "wasmer-runtime-core 0.1.2", +] + +[[package]] +name = "wasmer-runtime" +version = "0.1.4" +dependencies = [ + "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "wasmer-clif-backend 0.1.2", + "wasmer-runtime-core 0.1.2", +] + +[[package]] +name = "wasmer-runtime-core" +version = "0.1.2" +dependencies = [ + "errno 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", + "field-offset 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "hashbrown 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "memmap 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "nix 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", + "page_size 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", + "serde-bench 0.0.7 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_bytes 0.10.4 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", + "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "wasmer-clif-backend 0.1.2", + "wasmparser 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "wasmer-spectests" +version = "0.1.2" +dependencies = [ + "wabt 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)", + "wasmer-clif-backend 0.1.2", + "wasmer-runtime-core 0.1.2", +] + +[[package]] +name = "wasmer-win-exception-handler" +version = "0.0.1" +dependencies = [ + "bindgen 0.46.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cmake 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "wasmer-runtime-core 0.1.2", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "wasmparser" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "wasmparser" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "wasmparser" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "which" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "winapi" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "winapi" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "winapi-build" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "winapi-util" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "wincolor" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[metadata] +"checksum aho-corasick 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)" = "1e9a933f4e58658d7b12defcf96dc5c720f20832deebe3e0a19efd3b6aaeeb9e" +"checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" +"checksum atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "9a7d5b8723950951411ee34d271d99dddcc2035a16ab25310ea2c8cfd4369652" +"checksum autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a6d640bee2da49f60a4068a7fae53acde8982514ab7bae8b8cea9e88cbcfd799" +"checksum backtrace 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)" = "b5b493b66e03090ebc4343eb02f94ff944e0cbc9ac6571491d170ba026741eb5" +"checksum backtrace-sys 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)" = "797c830ac25ccc92a7f8a7b9862bde440715531514594a6154e3d4a54dd769b6" +"checksum bindgen 0.46.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8f7f7f0701772b17de73e4f5cbcb1dd6926f4706cba4c1ab62c5367f8bdc94e1" +"checksum bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12" +"checksum block-buffer 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "49665c62e0e700857531fa5d3763e91b539ff1abeebd56808d378b495870d60d" +"checksum block-padding 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d75255892aeb580d3c566f213a2b6fdc1c66667839f45719ee1d30ebf2aea591" +"checksum byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" +"checksum byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a019b10a2a7cdeb292db131fc8113e57ea2a908f6e7894b0c3c671893b65dbeb" +"checksum cast 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "926013f2860c46252efceabb19f4a6b308197505082c609025aa6706c011d427" +"checksum cc 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)" = "4390a3b5f4f6bce9c1d0c00128379df433e53777fdd30e92f16a529332baec4e" +"checksum cexpr 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "644d693ecfa91955ed32dcc7eda4914e1be97a641fb6f0645a37348e20b230da" +"checksum cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "082bb9b28e00d3c9d39cc03e64ce4cea0f1bb9b3fde493f0cbc008472d22bdf4" +"checksum clang-sys 0.26.4 (registry+https://github.com/rust-lang/crates.io-index)" = "6ef0c1bcf2e99c649104bd7a7012d8f8802684400e03db0ec0af48583c6fa0e4" +"checksum clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b957d88f4b6a63b9d70d5f454ac8011819c6efa7727858f458ab71c756ce2d3e" +"checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" +"checksum cmake 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)" = "6ec65ee4f9c9d16f335091d23693457ed4928657ba4982289d7fafee03bc614a" +"checksum cranelift-bforest 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)" = "40f8ff24e9a6c89b8a846b14df9a34d2cac17cea7bdb5c81ed6b4744ee0e38bf" +"checksum cranelift-codegen 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)" = "42f5b809bd885c368e01aeec8fe04f21dcb07569834b907d75b4a7bed8d067eb" +"checksum cranelift-codegen-meta 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)" = "014c23ed3ebdc8377d41540af638245207dd169f421df042dfccc867465734ed" +"checksum cranelift-entity 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d4df40e26c0cf7b4d86919cb995bb412ee3001cc18e4f3c83a903f30b7007d8b" +"checksum cranelift-frontend 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)" = "789907218eeebebcea8122c2053d71affac91c96ce72cea35ebfdbbf547e82af" +"checksum cranelift-native 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)" = "474bee81d620a473bf43411a3d6f10ffbf7965141dc5e5b76d8d2151dde3285d" +"checksum cranelift-wasm 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)" = "49723365dab9a48b354bdc24cb6d9d5719bc1d3b858ffd2ea179d0d7d885804a" +"checksum digest 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "05f47366984d3ad862010e22c7ce81a7dbcaebbdfb37241a620f8b6596ee135c" +"checksum either 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3be565ca5c557d7f59e7cfcf1844f9e3033650c929c6566f511e8005f205c1d0" +"checksum enum-methods 0.0.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7798e7da2d4cb0d6d6fc467e8d6b5bf247e9e989f786dde1732d79899c32bb10" +"checksum env_logger 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "afb070faf94c85d17d50ca44f6ad076bce18ae92f0037d350947240a36e9d42e" +"checksum errno 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "c2a071601ed01b988f896ab14b95e67335d1eeb50190932a1320f7fe3cadc84e" +"checksum errno-dragonfly 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "14ca354e36190500e1e1fb267c647932382b54053c50b14970856c0b00a35067" +"checksum failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "795bd83d3abeb9220f257e597aa0080a508b27533824adf336529648f6abf7e2" +"checksum failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "ea1063915fd7ef4309e222a5a07cf9c319fb9c7836b1f89b85458672dbb127e1" +"checksum fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" +"checksum field-offset 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "64e9bc339e426139e02601fa69d101e96a92aee71b58bc01697ec2a63a5c9e68" +"checksum fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" +"checksum gcc 0.3.55 (registry+https://github.com/rust-lang/crates.io-index)" = "8f5f3913fa0bfe7ee1fd8248b6b9f42a5af4b9d65ec2dd2c3c26132b950ecfc2" +"checksum generic-array 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3c0f28c2f5bfb5960175af447a2da7c18900693738343dc896ffbcabd9839592" +"checksum glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "8be18de09a56b60ed0edf84bc9df007e30040691af7acd1c41874faac5895bfb" +"checksum hashbrown 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "3bae29b6653b3412c2e71e9d486db9f9df5d701941d86683005efb9f2d28e3da" +"checksum heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205" +"checksum humantime 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3ca7e5f2e110db35f93b837c81797f3714500b81d517bf20c431b16d3ca4f114" +"checksum indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7e81a7c05f79578dbc15793d8b619db9ba32b4577003ef3af1a91c416798c58d" +"checksum inkwell 0.1.0 (git+https://github.com/TheDan64/inkwell?branch=llvm7-0)" = "" +"checksum inkwell_internal_macros 0.1.0 (git+https://github.com/TheDan64/inkwell?branch=llvm7-0)" = "" +"checksum itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1306f3464951f30e30d12373d31c79fbd52d236e5e896fd92f96ec7babbbe60b" +"checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" +"checksum lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a374c89b9db55895453a74c1e38861d9deec0b01b405a82516e9d5de4820dea1" +"checksum libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)" = "e962c7641008ac010fa60a7dfdc1712449f29c44ef2d4702394aea943ee75047" +"checksum libc 0.2.49 (git+https://github.com/rust-lang/libc)" = "" +"checksum libloading 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9c3ad660d7cb8c5822cd83d10897b0f1f1526792737a179e73896152f85b88c2" +"checksum llvm-sys 70.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "60a9ee82fe0fa72ae6ef6d018b407296085863836451c7a97384f84ed7e26b9f" +"checksum lock_api 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "62ebf1391f6acad60e5c8b43706dde4582df75c06698ab44511d15016bc2442c" +"checksum log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c84ec4b527950aa83a329754b01dbe3f58361d1c5efacd1f6d68c494d08a17c6" +"checksum memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2efc7bc57c883d4a4d6e3246905283d8dae951bb3bd32f49d6ef297f546e1c39" +"checksum memmap 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6585fd95e7bb50d6cc31e20d4cf9afb4e2ba16c5846fc76793f11218da9c475b" +"checksum nix 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "921f61dc817b379d0834e45d5ec45beaacfae97082090a49c2cf30dcbc30206f" +"checksum nix 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "46f0f3210768d796e8fa79ec70ee6af172dacbe7147f5e69be5240a47778302b" +"checksum nom 4.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b30adc557058ce00c9d0d7cb3c6e0b5bc6f36e2e2eabe74b0ba726d194abd588" +"checksum opaque-debug 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "93f5bb2e8e8dec81642920ccff6b61f1eb94fa3020c5a325c9851ff604152409" +"checksum owning_ref 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "49a4b8ea2179e6a2e27411d3bca09ca6dd630821cf6894c6c7c8467a8ee7ef13" +"checksum page_size 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f89ef58b3d32420dbd1a43d2f38ae92f6239ef12bb556ab09ca55445f5a67242" +"checksum parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ab41b4aed082705d1056416ae4468b6ea99d52599ecf3169b00088d43113e337" +"checksum parking_lot_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "94c8c7923936b28d546dfd14d4472eaf34c99b14e1c973a32b3e6d4eb04298c9" +"checksum peeking_take_while 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099" +"checksum proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)" = "4d317f9caece796be1980837fd5cb3dfec5613ebdb04ad0956deea83ce168915" +"checksum quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9274b940887ce9addde99c4eee6b5c44cc494b182b97e73dc8ffdcb3397fd3f0" +"checksum quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a" +"checksum quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)" = "cdd8e04bd9c52e0342b406469d494fcb033be4bdbe5c606016defbb1681411e1" +"checksum rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca" +"checksum rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef" +"checksum rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b" +"checksum rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d0e7a549d590831370895ab7ba4ea0c1b6b011d106b5ff2da6eee112615e6dc0" +"checksum rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b40677c7be09ae76218dc623efbf7b18e34bced3f38883af07bb75630a21bc4" +"checksum rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ded997c9d5f13925be2a6fd7e66bf1872597f759fd9dd93513dd7e92e5a5ee08" +"checksum rand_jitter 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7b9ea758282efe12823e0d952ddb269d2e1897227e464919a554f2a03ef1b832" +"checksum rand_os 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b7c690732391ae0abafced5015ffb53656abfaec61b342290e5eb56b286a679d" +"checksum rand_pcg 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "086bd09a33c7044e56bb44d5bdde5a60e7f119a9e95b0775f545de759a32fe05" +"checksum rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c" +"checksum raw-cpuid 6.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "30a9d219c32c9132f7be513c18be77c9881c7107d2ab5569d205a6a0f0e6dc7d" +"checksum rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" +"checksum redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)" = "423e376fffca3dfa06c9e9790a9ccd282fafb3cc6e6397d01dbf64f9bacc6b85" +"checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76" +"checksum regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "37e7cbbd370869ce2e8dff25c7018702d10b21a20ef7135316f8daecd6c25b7f" +"checksum regex-syntax 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "8c2f35eedad5295fdf00a63d7d4b238135723f92b434ec06774dad15c7ab0861" +"checksum rustc-demangle 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "adacaae16d02b6ec37fdc7acfcddf365978de76d1983d3ee22afc260e1ca9619" +"checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" +"checksum ryu 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "eb9e9b8cde282a9fe6a42dd4681319bfb63f121b8a8ee9439c6f4107e58a46f7" +"checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27" +"checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" +"checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" +"checksum serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)" = "2e20fde37801e83c891a2dc4ebd3b81f0da4d1fb67a9e0a2a3b921e2536a58ee" +"checksum serde-bench 0.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "d733da87e79faaac25616e33d26299a41143fd4cd42746cbb0e91d8feea243fd" +"checksum serde_bytes 0.10.4 (registry+https://github.com/rust-lang/crates.io-index)" = "adb6e51a6b3696b301bc221d785f898b4457c619b51d7ce195a6d20baecb37b3" +"checksum serde_derive 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)" = "633e97856567e518b59ffb2ad7c7a4fd4c5d91d9c7f32dd38a27b2bf7e8114ea" +"checksum serde_json 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)" = "27dce848e7467aa0e2fcaf0a413641499c0b745452aaca1194d24dedde9e13c9" +"checksum sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b4d8bfd0e469f417657573d8451fb33d16cfe0989359b93baf3a1ffc639543d" +"checksum smallvec 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)" = "88aea073965ab29f6edb5493faf96ad662fb18aa9eeb186a3b7057951605ed15" +"checksum stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dba1a27d3efae4351c8051072d619e3ade2820635c3958d826bfea39d59b54c8" +"checksum strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4f380125926a99e52bc279241539c018323fab05ad6368b56f93d9369ff550" +"checksum structopt 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "670ad348dc73012fcf78c71f06f9d942232cdd4c859d4b6975e27836c3efc0c3" +"checksum structopt-derive 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "ef98172b1a00b0bec738508d3726540edcbd186d50dfd326f2b1febbb3559f04" +"checksum syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d3b891b9015c88c576343b9b3e41c2c11a51c219ef067b264bd9c8aa9b441dad" +"checksum syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)" = "f92e629aa1d9c827b2bb8297046c1ccffc57c99b947a680d3ccff1f136a3bee9" +"checksum synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a393066ed9010ebaed60b9eafa373d4b1baac186dd7e008555b0f702b51945b6" +"checksum synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "73687139bf99285483c96ac0add482c3776528beac1d97d444f6e91f203a2015" +"checksum target-lexicon 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4af5e2227f0b887d591d3724b796a96eff04226104d872f5b3883fcd427d64b9" +"checksum termcolor 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "4096add70612622289f2fdcdbd5086dc81c1e2675e6ae58d6c4f62a16c6d7f2f" +"checksum termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "689a3bdfaab439fd92bc87df5c4c78417d3cbe537487274e9b0b2dce76e92096" +"checksum textwrap 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "307686869c93e71f94da64286f9a9524c0f308a9e1c87a583de8e9c9039ad3f6" +"checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b" +"checksum time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "db8dcfca086c1143c9270ac42a2bbd8a7ee477b78ac8e45b19abfb0cbede4b6f" +"checksum typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "612d636f949607bdf9b123b4a6f6d966dedf3ff669f7f045890d3a4a73948169" +"checksum ucd-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "535c204ee4d8434478593480b8f86ab45ec9aae0e83c568ca81abf0fd0e88f86" +"checksum unicode-segmentation 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "aa6024fc12ddfd1c6dbc14a80fa2324d4568849869b779f6bd37e5e4c03344d1" +"checksum unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "882386231c45df4700b275c7ff55b6f3698780a650026380e72dabe76fa46526" +"checksum unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f860d7d29cf02cb2f3f359fd35991af3d30bac52c57d265a3c461074cb4dc" +"checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" +"checksum unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "382810877fe448991dfc7f0dd6e3ae5d58088fd0ea5e35189655f84e6814fa56" +"checksum utf8-ranges 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "796f7e48bef87609f7ade7e06495a87d5cd06c7866e6a5cbfceffc558a243737" +"checksum vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a" +"checksum version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd" +"checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" +"checksum wabt 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)" = "74e463a508e390cc7447e70f640fbf44ad52e1bd095314ace1fdf99516d32add" +"checksum wabt-sys 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)" = "a6265b25719e82598d104b3717375e37661d41753e2c84cde3f51050c7ed7e3c" +"checksum wasmparser 0.22.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f46e666ecb4a406483a59a49f9d0c17f327e70da53a128eccddae2eadb95865c" +"checksum wasmparser 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b5e01c420bc7d36e778bd242e1167b079562ba8b34087122cc9057187026d060" +"checksum wasmparser 0.28.0 (registry+https://github.com/rust-lang/crates.io-index)" = "40f426b1929bd26517fb10702e2a8e520d1845c49567aa4d244f426f10b206c1" +"checksum which 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b57acb10231b9493c8472b20cb57317d0679a49e0bdbee44b3b803a6473af164" +"checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" +"checksum winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "92c1eb33641e276cfa214a0522acad57be5c56b10cb348b3c5117db75f3ac4b0" +"checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" +"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" +"checksum winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7168bab6e1daee33b4557efd0e95d5ca70a03706d39fa5f3fe7a236f584b03c9" +"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +"checksum wincolor 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "561ed901ae465d6185fa7864d63fbd5720d0ef718366c9a4dc83cf6170d7e9ba" diff --git a/lib/llvm-backend/src/code.rs b/lib/llvm-backend/src/code.rs index fb9e53520..48aac8dc2 100644 --- a/lib/llvm-backend/src/code.rs +++ b/lib/llvm-backend/src/code.rs @@ -5,20 +5,22 @@ use inkwell::{ passes::PassManager, types::{BasicType, BasicTypeEnum, FunctionType, PointerType}, values::{BasicValue, FunctionValue, PhiValue, PointerValue}, - FloatPredicate, IntPredicate, + AddressSpace, FloatPredicate, IntPredicate, }; use smallvec::SmallVec; use wasmer_runtime_core::{ memory::MemoryType, module::ModuleInfo, structures::{Map, SliceMap, TypedIndex}, - types::{FuncIndex, FuncSig, LocalFuncIndex, LocalOrImport, MemoryIndex, SigIndex, Type}, + types::{ + FuncIndex, FuncSig, GlobalIndex, LocalFuncIndex, LocalOrImport, MemoryIndex, SigIndex, Type, + }, }; use wasmparser::{ BinaryReaderError, CodeSectionReader, LocalsReader, MemoryImmediate, Operator, OperatorsReader, }; -use crate::intrinsics::{CtxType, Intrinsics}; +use crate::intrinsics::{CtxType, GlobalCache, Intrinsics}; use crate::read_info::type_to_type; use crate::state::{ControlFrame, IfElseState, State}; @@ -515,8 +517,32 @@ fn parse_function( builder.build_store(pointer_value, v); } - Operator::GetGlobal { global_index } => unimplemented!(), - Operator::SetGlobal { global_index } => unimplemented!(), + Operator::GetGlobal { global_index } => { + let index = GlobalIndex::new(global_index as usize); + let global_cache = ctx.global_cache(index); + match global_cache { + GlobalCache::Const { value } => { + state.push1(value.as_basic_value_enum()); + } + GlobalCache::Mut { ptr_to_value } => { + let value = builder.build_load(ptr_to_value, "global_value"); + state.push1(value); + } + } + } + Operator::SetGlobal { global_index } => { + let value = state.pop1()?; + let index = GlobalIndex::new(global_index as usize); + let global_cache = ctx.global_cache(index); + match global_cache { + GlobalCache::Mut { ptr_to_value } => { + builder.build_store(ptr_to_value, value); + } + GlobalCache::Const { value: _ } => { + unreachable!("cannot set non-mutable globals") + } + } + } Operator::Select => { let (v1, v2, cond) = state.pop3()?; @@ -528,10 +554,10 @@ fn parse_function( let func_index = FuncIndex::new(function_index as usize); let sigindex = info.func_assoc[func_index]; let llvm_sig = signatures[sigindex]; + let func_sig = &info.signatures[sig_index]; - match func_index.local_or_import(info) { + let call_site = match func_index.local_or_import(info) { LocalOrImport::Local(local_func_index) => { - let func_sig = &info.signatures[sigindex]; let func_value = functions[local_func_index]; let params: Vec<_> = [ctx.basic()] .iter() @@ -539,26 +565,45 @@ fn parse_function( .map(|v| *v) .collect(); - let call_site = builder.build_call(func_value, ¶ms, &state.var_name()); - if let Some(basic_value) = call_site.try_as_basic_value().left() { - match func_sig.returns().len() { - 1 => state.push1(basic_value), - count @ _ => { - // This is a multi-value return. - let struct_value = basic_value.into_struct_value(); - for i in 0..(count as u32) { - let value = builder.build_extract_value( - struct_value, - i, - &state.var_name(), - ); - state.push1(value); - } - } + builder.build_call(func_value, ¶ms, &state.var_name()) + } + LocalOrImport::Import(import_func_index) => { + let (func_ptr_untyped, ctx_ptr) = ctx.imported_func(import_func_index); + let params: Vec<_> = [ctx_ptr.as_basic_value_enum()] + .iter() + .chain(state.peekn(func_sig.params().len())?.iter()) + .map(|v| *v) + .collect(); + + let func_ptr_ty = llvm_sig.ptr_type(AddressSpace::Generic); + + // Once we can just bitcast between pointer types, remove this. + let func_ptr = { + let ptr_int = builder.build_ptr_to_int( + func_ptr_untyped, + intrinsics.i64_ty, + "func_ptr_int", + ); + builder.build_int_to_ptr(ptr_int, func_ptr_ty, "typed_func_ptr") + }; + + builder.build_call(func_ptr, ¶ms, &state.var_name()) + } + }; + + if let Some(basic_value) = call_site.try_as_basic_value().left() { + match func_sig.returns().len() { + 1 => state.push1(basic_value), + count @ _ => { + // This is a multi-value return. + let struct_value = basic_value.into_struct_value(); + for i in 0..(count as u32) { + let value = + builder.build_extract_value(struct_value, i, &state.var_name()); + state.push1(value); } } } - LocalOrImport::Import(import_func_index) => unimplemented!(), } } Operator::CallIndirect { index, table_index } => { @@ -1129,25 +1174,37 @@ fn parse_function( let res = builder.build_int_z_extend(v1, intrinsics.i64_ty, &state.var_name()); state.push1(res); } - Operator::I32TruncSF32 | Operator::I32TruncSF64 => { + Operator::I32TruncSF32 + | Operator::I32TruncSF64 + | Operator::I32TruncSSatF32 + | Operator::I32TruncSSatF64 => { let v1 = state.pop1()?.into_float_value(); let res = builder.build_float_to_signed_int(v1, intrinsics.i32_ty, &state.var_name()); state.push1(res); } - Operator::I64TruncSF32 | Operator::I64TruncSF64 => { + Operator::I64TruncSF32 + | Operator::I64TruncSF64 + | Operator::I64TruncSSatF32 + | Operator::I64TruncSSatF64 => { let v1 = state.pop1()?.into_float_value(); let res = builder.build_float_to_signed_int(v1, intrinsics.i64_ty, &state.var_name()); state.push1(res); } - Operator::I32TruncUF32 | Operator::I32TruncUF64 => { + Operator::I32TruncUF32 + | Operator::I32TruncUF64 + | Operator::I32TruncUSatF32 + | Operator::I32TruncUSatF64 => { let v1 = state.pop1()?.into_float_value(); let res = builder.build_float_to_unsigned_int(v1, intrinsics.i32_ty, &state.var_name()); state.push1(res); } - Operator::I64TruncUF32 | Operator::I64TruncUF64 => { + Operator::I64TruncUF32 + | Operator::I64TruncUF64 + | Operator::I64TruncUSatF32 + | Operator::I64TruncUSatF64 => { let v1 = state.pop1()?.into_float_value(); let res = builder.build_float_to_unsigned_int(v1, intrinsics.i64_ty, &state.var_name()); @@ -1194,6 +1251,51 @@ fn parse_function( unimplemented!("waiting on better bitcasting support in inkwell") } + /*************************** + * Sign-extension operators. + * https://github.com/WebAssembly/sign-extension-ops/blob/master/proposals/sign-extension-ops/Overview.md + ***************************/ + Operator::I32Extend8S => { + let value = state.pop1()?.into_int_value(); + let narrow_value = + builder.build_int_truncate(value, intrinsics.i8_ty, &state.var_name()); + let extended_value = + builder.build_int_s_extend(narrow_value, intrinsics.i32_ty, &state.var_name()); + state.push1(extended_value); + } + Operator::I32Extend16S => { + let value = state.pop1()?.into_int_value(); + let narrow_value = + builder.build_int_truncate(value, intrinsics.i16_ty, &state.var_name()); + let extended_value = + builder.build_int_s_extend(narrow_value, intrinsics.i32_ty, &state.var_name()); + state.push1(extended_value); + } + Operator::I64Extend8S => { + let value = state.pop1()?.into_int_value(); + let narrow_value = + builder.build_int_truncate(value, intrinsics.i8_ty, &state.var_name()); + let extended_value = + builder.build_int_s_extend(narrow_value, intrinsics.i64_ty, &state.var_name()); + state.push1(extended_value); + } + Operator::I64Extend16S => { + let value = state.pop1()?.into_int_value(); + let narrow_value = + builder.build_int_truncate(value, intrinsics.i16_ty, &state.var_name()); + let extended_value = + builder.build_int_s_extend(narrow_value, intrinsics.i64_ty, &state.var_name()); + state.push1(extended_value); + } + Operator::I64Extend32S => { + let value = state.pop1()?.into_int_value(); + let narrow_value = + builder.build_int_truncate(value, intrinsics.i32_ty, &state.var_name()); + let extended_value = + builder.build_int_s_extend(narrow_value, intrinsics.i64_ty, &state.var_name()); + state.push1(extended_value); + } + /*************************** * Load and Store instructions. * https://github.com/sunfishcode/wasm-reference-manual/blob/master/WebAssembly.md#load-and-store-instructions @@ -1566,15 +1668,15 @@ fn parse_function( &state.var_name(), ); state.push1(result.try_as_basic_value().left().unwrap()); - } - - op @ _ => { - println!("{}", module.print_to_string().to_string()); - unimplemented!("{:?}", op); - } + } // op @ _ => { + // println!("{}", module.print_to_string().to_string()); + // unimplemented!("{:?}", op); + // } } } + println!("finished translating"); + let pass_manager = PassManager::create_for_module(); pass_manager.add_promote_memory_to_register_pass(); pass_manager.add_cfg_simplification_pass(); @@ -1585,6 +1687,7 @@ fn parse_function( pass_manager.add_gvn_pass(); pass_manager.add_new_gvn_pass(); pass_manager.add_aggressive_dce_pass(); + pass_manager.add_verifier_pass(); pass_manager.run_on_module(module); println!("{}", module.print_to_string().to_string()); diff --git a/lib/llvm-backend/src/intrinsics.rs b/lib/llvm-backend/src/intrinsics.rs index f2e681f38..6ffbb6ea6 100644 --- a/lib/llvm-backend/src/intrinsics.rs +++ b/lib/llvm-backend/src/intrinsics.rs @@ -12,9 +12,18 @@ use wasmer_runtime_core::{ memory::MemoryType, module::ModuleInfo, structures::TypedIndex, - types::{LocalOrImport, MemoryIndex}, + types::{GlobalIndex, ImportedFuncIndex, LocalOrImport, MemoryIndex, TableIndex, Type}, }; +fn type_to_llvm_ptr(intrinsics: &Intrinsics, ty: Type) -> PointerType { + match ty { + Type::I32 => intrinsics.i32_ptr_ty, + Type::I64 => intrinsics.i64_ptr_ty, + Type::F32 => intrinsics.f32_ptr_ty, + Type::F64 => intrinsics.f64_ptr_ty, + } +} + pub struct Intrinsics { pub ctlz_i32: FunctionValue, pub ctlz_i64: FunctionValue, @@ -111,8 +120,6 @@ impl Intrinsics { let f32_ptr_ty = f32_ty.ptr_type(AddressSpace::Generic); let f64_ptr_ty = f64_ty.ptr_type(AddressSpace::Generic); - let opaque_ptr_ty = void_ty.ptr_type(AddressSpace::Generic); - let i1_zero = i1_ty.const_int(0, false); let i32_zero = i32_ty.const_int(0, false); let i64_zero = i64_ty.const_int(0, false); @@ -125,19 +132,16 @@ impl Intrinsics { let f32_ty_basic = f32_ty.as_basic_type_enum(); let f64_ty_basic = f64_ty.as_basic_type_enum(); let i8_ptr_ty_basic = i8_ptr_ty.as_basic_type_enum(); - let opaque_ptr_ty_basic = opaque_ptr_ty.as_basic_type_enum(); let ctx_ty = context.opaque_struct_type("ctx"); let ctx_ptr_ty = ctx_ty.ptr_type(AddressSpace::Generic); let local_memory_ty = - context.struct_type(&[i8_ptr_ty_basic, i64_ty_basic, opaque_ptr_ty_basic], false); + context.struct_type(&[i8_ptr_ty_basic, i64_ty_basic, i8_ptr_ty_basic], false); let local_table_ty = local_memory_ty; let local_global_ty = i64_ty; - let imported_func_ty = context.struct_type( - &[opaque_ptr_ty_basic, ctx_ptr_ty.as_basic_type_enum()], - false, - ); + let imported_func_ty = + context.struct_type(&[i8_ptr_ty_basic, ctx_ptr_ty.as_basic_type_enum()], false); ctx_ty.set_body( &[ local_memory_ty @@ -184,9 +188,12 @@ impl Intrinsics { let ret_f32_take_f32_f32 = f32_ty.fn_type(&[f32_ty_basic, f32_ty_basic], false); let ret_f64_take_f64_f64 = f64_ty.fn_type(&[f64_ty_basic, f64_ty_basic], false); - let ret_i32_take_i64_i32_i32 = - i32_ty.fn_type(&[i64_ty_basic, i32_ty_basic, i32_ty_basic], false); - let ret_i32_take_i64_i32 = i32_ty.fn_type(&[i64_ty_basic, i32_ty_basic], false); + let ret_i32_take_ctx_i32_i32 = i32_ty.fn_type( + &[ctx_ptr_ty.as_basic_type_enum(), i32_ty_basic, i32_ty_basic], + false, + ); + let ret_i32_take_ctx_i32 = + i32_ty.fn_type(&[ctx_ptr_ty.as_basic_type_enum(), i32_ty_basic], false); Self { ctlz_i32: module.add_function("llvm.ctlz.i32", ret_i32_take_i32_i1, None), @@ -250,63 +257,63 @@ impl Intrinsics { // VM intrinsics. memory_grow_dynamic_local: module.add_function( "vm.memory.grow.dynamic.local", - ret_i32_take_i64_i32_i32, + ret_i32_take_ctx_i32_i32, None, ), memory_grow_static_local: module.add_function( "vm.memory.grow.static.local", - ret_i32_take_i64_i32_i32, + ret_i32_take_ctx_i32_i32, None, ), memory_grow_shared_local: module.add_function( "vm.memory.grow.shared.local", - ret_i32_take_i64_i32_i32, + ret_i32_take_ctx_i32_i32, None, ), memory_grow_dynamic_import: module.add_function( "vm.memory.grow.dynamic.import", - ret_i32_take_i64_i32_i32, + ret_i32_take_ctx_i32_i32, None, ), memory_grow_static_import: module.add_function( "vm.memory.grow.static.import", - ret_i32_take_i64_i32_i32, + ret_i32_take_ctx_i32_i32, None, ), memory_grow_shared_import: module.add_function( "vm.memory.grow.shared.import", - ret_i32_take_i64_i32_i32, + ret_i32_take_ctx_i32_i32, None, ), memory_size_dynamic_local: module.add_function( "vm.memory.size.dynamic.local", - ret_i32_take_i64_i32, + ret_i32_take_ctx_i32, None, ), memory_size_static_local: module.add_function( "vm.memory.size.static.local", - ret_i32_take_i64_i32, + ret_i32_take_ctx_i32, None, ), memory_size_shared_local: module.add_function( "vm.memory.size.shared.local", - ret_i32_take_i64_i32, + ret_i32_take_ctx_i32, None, ), memory_size_dynamic_import: module.add_function( "vm.memory.size.dynamic.import", - ret_i32_take_i64_i32, + ret_i32_take_ctx_i32, None, ), memory_size_static_import: module.add_function( "vm.memory.size.static.import", - ret_i32_take_i64_i32, + ret_i32_take_ctx_i32, None, ), memory_size_shared_import: module.add_function( "vm.memory.size.shared.import", - ret_i32_take_i64_i32, + ret_i32_take_ctx_i32, None, ), @@ -332,6 +339,9 @@ impl Intrinsics { info, cached_memories: HashMap::new(), + cached_tables: HashMap::new(), + cached_globals: HashMap::new(), + cached_imported_functions: HashMap::new(), _phantom: PhantomData, } @@ -351,6 +361,22 @@ enum MemoryCache { }, } +struct TableCache { + ptr_to_base_ptr: PointerValue, + ptr_to_bounds: PointerValue, +} + +#[derive(Clone, Copy)] +pub enum GlobalCache { + Mut { ptr_to_value: PointerValue }, + Const { value: IntValue }, +} + +struct ImportedFuncCache { + func_ptr: PointerValue, + ctx_ptr: PointerValue, +} + pub struct CtxType<'a> { ctx_ty: StructType, ctx_ptr_ty: PointerType, @@ -362,6 +388,9 @@ pub struct CtxType<'a> { info: &'a ModuleInfo, cached_memories: HashMap, + cached_tables: HashMap, + cached_globals: HashMap, + cached_imported_functions: HashMap, _phantom: PhantomData<&'a FunctionValue>, } @@ -443,6 +472,119 @@ impl<'a> CtxType<'a> { MemoryCache::Static { base_ptr, bounds } => (*base_ptr, *bounds), } } + + pub fn global_cache(&mut self, index: GlobalIndex) -> GlobalCache { + let (cached_globals, builder, ctx_ptr_value, info, intrinsics) = ( + &mut self.cached_globals, + self.builder, + self.ctx_ptr_value, + self.info, + self.intrinsics, + ); + + *cached_globals.entry(index).or_insert_with(|| { + let (globals_array_ptr_ptr, index, mutable, wasmer_ty) = + match index.local_or_import(info) { + LocalOrImport::Local(local_global_index) => { + let desc = info.globals[local_global_index].desc; + ( + unsafe { + builder.build_struct_gep(ctx_ptr_value, 2, "globals_array_ptr_ptr") + }, + local_global_index.index() as u64, + desc.mutable, + desc.ty, + ) + } + LocalOrImport::Import(import_global_index) => { + let desc = info.imported_globals[import_global_index].1; + ( + unsafe { + builder.build_struct_gep(ctx_ptr_value, 5, "globals_array_ptr_ptr") + }, + import_global_index.index() as u64, + desc.mutable, + desc.ty, + ) + } + }; + + let llvm_ptr_ty = type_to_llvm_ptr(intrinsics, wasmer_ty); + + let global_array_ptr = builder + .build_load(globals_array_ptr_ptr, "global_array_ptr") + .into_pointer_value(); + let const_index = intrinsics.i32_ty.const_int(index, false); + let global_ptr_ptr = unsafe { + builder.build_in_bounds_gep(global_array_ptr, &[const_index], "global_ptr_ptr") + }; + let global_ptr = builder + .build_load(global_ptr_ptr, "global_ptr") + .into_pointer_value(); + + let global_ptr_typed = { + let int = builder.build_ptr_to_int(global_ptr, intrinsics.i64_ty, "global_ptr_int"); + builder.build_int_to_ptr(int, llvm_ptr_ty, "global_ptr_typed") + }; + println!("global_ptr: {:?}", global_ptr_typed); + + if mutable { + GlobalCache::Mut { + ptr_to_value: global_ptr_typed, + } + } else { + GlobalCache::Const { + value: builder + .build_load(global_ptr_typed, "global_value") + .into_int_value(), + } + } + }) + } + + pub fn imported_func(&mut self, index: ImportedFuncIndex) -> (PointerValue, PointerValue) { + let (cached_imported_functions, builder, ctx_ptr_value, intrinsics) = ( + &mut self.cached_imported_functions, + self.builder, + self.ctx_ptr_value, + self.intrinsics, + ); + + let imported_func_cache = cached_imported_functions.entry(index).or_insert_with(|| { + let func_array_ptr_ptr = unsafe { + builder.build_struct_gep(ctx_ptr_value, 6, "imported_func_array_ptr_ptr") + }; + let func_array_ptr = builder + .build_load(func_array_ptr_ptr, "func_array_ptr") + .into_pointer_value(); + let const_index = intrinsics.i32_ty.const_int(index.index() as u64, false); + let imported_func_ptr_ptr = unsafe { + builder.build_in_bounds_gep(func_array_ptr, &[const_index], "imported_func_ptr_ptr") + }; + let imported_func_ptr = builder + .build_load(imported_func_ptr_ptr, "imported_func_ptr") + .into_pointer_value(); + let (func_ptr_ptr, ctx_ptr_ptr) = unsafe { + ( + builder.build_struct_gep(imported_func_ptr, 0, "func_ptr_ptr"), + builder.build_struct_gep(imported_func_ptr, 1, "ctx_ptr_ptr"), + ) + }; + + let func_ptr = builder + .build_load(func_ptr_ptr, "func_ptr") + .into_pointer_value(); + let ctx_ptr = builder + .build_load(ctx_ptr_ptr, "ctx_ptr") + .into_pointer_value(); + + ImportedFuncCache { func_ptr, ctx_ptr } + }); + + (imported_func_cache.func_ptr, imported_func_cache.ctx_ptr) + } + + // pub fn table(&mut self, table_index: TableIndex, elem_index: IntValue) -> } // pub struct Ctx { diff --git a/lib/llvm-backend/src/lib.rs b/lib/llvm-backend/src/lib.rs index e691acebb..cd43c6aef 100644 --- a/lib/llvm-backend/src/lib.rs +++ b/lib/llvm-backend/src/lib.rs @@ -30,20 +30,17 @@ impl Compiler for LLVMCompiler { #[test] fn test_read_module() { use wabt::wat2wasm; + // let wasm = include_bytes!("../../spectests/examples/simple/simple.wasm") as &[u8]; let wat = r#" (module (type $t0 (func (param i32) (result i32))) (type $t1 (func (result i32))) (memory 1) + (global $g0 (mut i32) (i32.const 0)) (func $foo (type $t0) (param i32) (result i32) get_local 0 - i32.load offset=16 - i32.const 1 - memory.grow - drop - i32.const 0 - i32.load offset=4 - i32.add + set_global $g0 + get_global $g0 )) "#; let wasm = wat2wasm(wat).unwrap(); From 108973dabecf0dabef3f5ba36ce81a9ad69a074c Mon Sep 17 00:00:00 2001 From: Lachlan Sneff Date: Fri, 15 Feb 2019 16:02:20 -0800 Subject: [PATCH 07/75] Start producing object files with llvm --- Cargo.lock | 39 +++++++++++++++++ lib/llvm-backend/Cargo.toml | 1 + lib/llvm-backend/src/backend.rs | 45 ++++++++++++++++++++ lib/llvm-backend/src/code.rs | 45 ++++++++++---------- lib/llvm-backend/src/lib.rs | 75 +++++++++++++++++++++++++++++++-- lib/runtime-core/src/types.rs | 2 +- 6 files changed, 180 insertions(+), 27 deletions(-) create mode 100644 lib/llvm-backend/src/backend.rs diff --git a/Cargo.lock b/Cargo.lock index 065209f0b..402ff214c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -345,6 +345,16 @@ name = "glob" version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "goblin" +version = "0.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "plain 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "scroll 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "hashbrown" version = "0.1.8" @@ -439,6 +449,7 @@ dependencies = [ name = "llvm-backend" version = "0.1.0" dependencies = [ + "goblin 0.0.20 (registry+https://github.com/rust-lang/crates.io-index)", "hashbrown 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "inkwell 0.1.0 (git+https://github.com/TheDan64/inkwell?branch=llvm7-0)", "smallvec 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -572,6 +583,11 @@ name = "peeking_take_while" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "plain" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "proc-macro2" version = "0.4.27" @@ -768,6 +784,25 @@ name = "scopeguard" version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "scroll" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "scroll_derive 0.9.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "scroll_derive" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "semver" version = "0.9.0" @@ -1259,6 +1294,7 @@ dependencies = [ "checksum gcc 0.3.55 (registry+https://github.com/rust-lang/crates.io-index)" = "8f5f3913fa0bfe7ee1fd8248b6b9f42a5af4b9d65ec2dd2c3c26132b950ecfc2" "checksum generic-array 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3c0f28c2f5bfb5960175af447a2da7c18900693738343dc896ffbcabd9839592" "checksum glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "8be18de09a56b60ed0edf84bc9df007e30040691af7acd1c41874faac5895bfb" +"checksum goblin 0.0.20 (registry+https://github.com/rust-lang/crates.io-index)" = "84473a5302fa5094d3d9911c2f312f522f9a37462a777f195f63fae1bf7faf4d" "checksum hashbrown 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "3bae29b6653b3412c2e71e9d486db9f9df5d701941d86683005efb9f2d28e3da" "checksum heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205" "checksum humantime 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3ca7e5f2e110db35f93b837c81797f3714500b81d517bf20c431b16d3ca4f114" @@ -1285,6 +1321,7 @@ dependencies = [ "checksum parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ab41b4aed082705d1056416ae4468b6ea99d52599ecf3169b00088d43113e337" "checksum parking_lot_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "94c8c7923936b28d546dfd14d4472eaf34c99b14e1c973a32b3e6d4eb04298c9" "checksum peeking_take_while 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099" +"checksum plain 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "b4596b6d070b27117e987119b4dac604f3c58cfb0b191112e24771b2faeac1a6" "checksum proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)" = "4d317f9caece796be1980837fd5cb3dfec5613ebdb04ad0956deea83ce168915" "checksum quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9274b940887ce9addde99c4eee6b5c44cc494b182b97e73dc8ffdcb3397fd3f0" "checksum quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a" @@ -1309,6 +1346,8 @@ dependencies = [ "checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" "checksum ryu 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "eb9e9b8cde282a9fe6a42dd4681319bfb63f121b8a8ee9439c6f4107e58a46f7" "checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27" +"checksum scroll 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2f84d114ef17fd144153d608fba7c446b0145d038985e7a8cc5d08bb0ce20383" +"checksum scroll_derive 0.9.5 (registry+https://github.com/rust-lang/crates.io-index)" = "8f1aa96c45e7f5a91cb7fabe7b279f02fea7126239fc40b732316e8b6a2d0fcb" "checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" "checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" "checksum serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)" = "2e20fde37801e83c891a2dc4ebd3b81f0da4d1fb67a9e0a2a3b921e2536a58ee" diff --git a/lib/llvm-backend/Cargo.toml b/lib/llvm-backend/Cargo.toml index bcf2175e2..8ffac375f 100644 --- a/lib/llvm-backend/Cargo.toml +++ b/lib/llvm-backend/Cargo.toml @@ -10,6 +10,7 @@ wasmparser = "0.28.0" inkwell = { git = "https://github.com/TheDan64/inkwell", branch = "llvm7-0" } hashbrown = "0.1.8" smallvec = "0.6.8" +goblin = "0.0.20" [dev-dependencies] wabt = "0.7.4" diff --git a/lib/llvm-backend/src/backend.rs b/lib/llvm-backend/src/backend.rs new file mode 100644 index 000000000..9821eabf6 --- /dev/null +++ b/lib/llvm-backend/src/backend.rs @@ -0,0 +1,45 @@ +use inkwell::{ + module::Module, + execution_engine::{ExecutionEngine, JitFunction}, +}; +use crate::intrinsics::Intrinsics; +use std::ptr::NonNull; +use wasmer_runtime_core::{ + module::ModuleInner, + types::LocalFuncIndex, + structures::TypedIndex, + backend::{FuncResolver, vm}, +}; + +pub struct LLVMBackend { + exec_engine: ExecutionEngine, +} + +impl LLVMBackend { + pub fn new(module: Module, intrinsics: Intrinsics) -> Self { + let exec_engine = module.create_jit_execution_engine(OptimizationLevel::Default).unwrap(); + + exec_engine.add_global_mapping(&intrinsics.memory_grow_dynamic_local, vmcalls::local_dynamic_memory_grow as usize); + exec_engine.add_global_mapping(&intrinsics.memory_grow_static_local, vmcalls::local_static_memory_grow as usize); + exec_engine.add_global_mapping(&intrinsics.memory_grow_dynamic_import, vmcalls::imported_dynamic_memory_grow as usize); + exec_engine.add_global_mapping(&intrinsics.memory_grow_static_import, vmcalls::imported_static_memory_grow as usize); + exec_engine.add_global_mapping(&intrinsics.memory_size_dynamic_local, vmcalls::local_dynamic_memory_size as usize); + exec_engine.add_global_mapping(&intrinsics.memory_size_static_local, vmcalls::local_static_memory_size as usize); + exec_engine.add_global_mapping(&intrinsics.memory_size_dynamic_import, vmcalls::imported_dynamic_memory_size as usize); + exec_engine.add_global_mapping(&intrinsics.memory_size_static_import, vmcalls::imported_static_memory_size as usize); + + Self { exec_engine } + } +} + +impl FuncResolver for LLVMBackend { + fn get(&self, module: &ModuleInner, local_func_index: LocalFuncIndex) -> Option> { + let index = module.info.imported_functions.len() + local_func_index.index(); + let name = format!("fn{}", index); + + unsafe { + let func: JitFunction = self.exec_engine.get_function(&name).ok()?; + + } + } +} \ No newline at end of file diff --git a/lib/llvm-backend/src/code.rs b/lib/llvm-backend/src/code.rs index 48aac8dc2..48c477f4a 100644 --- a/lib/llvm-backend/src/code.rs +++ b/lib/llvm-backend/src/code.rs @@ -59,7 +59,7 @@ fn type_to_llvm(intrinsics: &Intrinsics, ty: Type) -> BasicTypeEnum { pub fn parse_function_bodies( info: &ModuleInfo, code_reader: CodeSectionReader, -) -> Result<(), BinaryReaderError> { +) -> Result<(Module, Intrinsics), BinaryReaderError> { let context = Context::create(); let module = context.create_module("module"); let builder = context.create_builder(); @@ -104,7 +104,22 @@ pub fn parse_function_bodies( )?; } - Ok(()) + let pass_manager = PassManager::create_for_module(); + pass_manager.add_promote_memory_to_register_pass(); + pass_manager.add_cfg_simplification_pass(); + pass_manager.add_instruction_combining_pass(); + // pass_manager.add_aggressive_inst_combiner_pass(); + // pass_manager.add_merged_load_store_motion_pass(); + // pass_manager.add_sccp_pass(); + pass_manager.add_gvn_pass(); + pass_manager.add_new_gvn_pass(); + pass_manager.add_aggressive_dce_pass(); + pass_manager.add_verifier_pass(); + pass_manager.run_on_module(&module); + + println!("{}", module.print_to_string().to_string()); + + Ok((module, intrinsics)) } fn parse_function( @@ -1668,30 +1683,14 @@ fn parse_function( &state.var_name(), ); state.push1(result.try_as_basic_value().left().unwrap()); - } // op @ _ => { - // println!("{}", module.print_to_string().to_string()); - // unimplemented!("{:?}", op); - // } + } + op @ _ => { + println!("{}", module.print_to_string().to_string()); + unimplemented!("{:?}", op); + } } } - println!("finished translating"); - - let pass_manager = PassManager::create_for_module(); - pass_manager.add_promote_memory_to_register_pass(); - pass_manager.add_cfg_simplification_pass(); - pass_manager.add_instruction_combining_pass(); - // pass_manager.add_aggressive_inst_combiner_pass(); - // pass_manager.add_merged_load_store_motion_pass(); - // pass_manager.add_sccp_pass(); - pass_manager.add_gvn_pass(); - pass_manager.add_new_gvn_pass(); - pass_manager.add_aggressive_dce_pass(); - pass_manager.add_verifier_pass(); - pass_manager.run_on_module(module); - - println!("{}", module.print_to_string().to_string()); - Ok(()) } diff --git a/lib/llvm-backend/src/lib.rs b/lib/llvm-backend/src/lib.rs index cd43c6aef..6279aa8e1 100644 --- a/lib/llvm-backend/src/lib.rs +++ b/lib/llvm-backend/src/lib.rs @@ -3,11 +3,17 @@ use wasmer_runtime_core::{ error::CompileError, module::ModuleInner, }; +use inkwell::{ + execution_engine::JitFunction, + targets::{TargetMachine, Target, RelocMode, CodeModel, InitializationConfig, FileType}, + OptimizationLevel, +}; mod code; mod intrinsics; mod read_info; mod state; +// mod backend; pub struct LLVMCompiler { _private: (), @@ -29,6 +35,7 @@ impl Compiler for LLVMCompiler { #[test] fn test_read_module() { + use wasmer_runtime_core::vmcalls; use wabt::wat2wasm; // let wasm = include_bytes!("../../spectests/examples/simple/simple.wasm") as &[u8]; let wat = r#" @@ -39,13 +46,75 @@ fn test_read_module() { (global $g0 (mut i32) (i32.const 0)) (func $foo (type $t0) (param i32) (result i32) get_local 0 - set_global $g0 - get_global $g0 + call $foobar + memory.grow + ) + (func $foobar (type $t0) + get_local 0 + ) + (func $bar (type $t0) (param i32) (result i32) + get_local 0 + call $foo )) "#; let wasm = wat2wasm(wat).unwrap(); let (info, code_reader) = read_info::read_module(&wasm).unwrap(); - code::parse_function_bodies(&info, code_reader).unwrap(); + let (module, intrinsics) = code::parse_function_bodies(&info, code_reader).unwrap(); + + { + Target::initialize_x86(&InitializationConfig { + asm_parser: true, + asm_printer: true, + base: true, + disassembler: true, + info: true, + machine_code: true, + }); + let triple = TargetMachine::get_default_triple().to_string(); + let target = Target::from_triple(&triple).unwrap(); + let target_machine = target.create_target_machine( + &triple, + &TargetMachine::get_host_cpu_name().to_string(), + &TargetMachine::get_host_cpu_features().to_string(), + OptimizationLevel::Default, + RelocMode::PIC, + CodeModel::Default, + ).unwrap(); + + let memory_buffer = target_machine.write_to_memory_buffer(&module, FileType::Object).unwrap(); + // std::fs::write("memory_buffer", memory_buffer.as_slice()).unwrap(); + let mem_buf_slice = memory_buffer.as_slice(); + + let macho = goblin::mach::MachO::parse(mem_buf_slice, 0).unwrap(); + let symbols = macho.symbols.as_ref().unwrap(); + let relocations = macho.relocations().unwrap(); + for (_, reloc_iter, section) in relocations.into_iter() { + println!("section: {:#?}", section); + for reloc_info in reloc_iter { + let reloc_info = reloc_info.unwrap(); + println!("\treloc_info: {:#?}", reloc_info); + println!("\tsymbol: {:#?}", symbols.get(reloc_info.r_symbolnum()).unwrap()); + } + } + } + + + let exec_engine = module.create_jit_execution_engine(OptimizationLevel::Default).unwrap(); + + exec_engine.add_global_mapping(&intrinsics.memory_grow_dynamic_local, vmcalls::local_dynamic_memory_grow as usize); + exec_engine.add_global_mapping(&intrinsics.memory_grow_static_local, vmcalls::local_static_memory_grow as usize); + exec_engine.add_global_mapping(&intrinsics.memory_grow_dynamic_import, vmcalls::imported_dynamic_memory_grow as usize); + exec_engine.add_global_mapping(&intrinsics.memory_grow_static_import, vmcalls::imported_static_memory_grow as usize); + exec_engine.add_global_mapping(&intrinsics.memory_size_dynamic_local, vmcalls::local_dynamic_memory_size as usize); + exec_engine.add_global_mapping(&intrinsics.memory_size_static_local, vmcalls::local_static_memory_size as usize); + exec_engine.add_global_mapping(&intrinsics.memory_size_dynamic_import, vmcalls::imported_dynamic_memory_size as usize); + exec_engine.add_global_mapping(&intrinsics.memory_size_static_import, vmcalls::imported_static_memory_size as usize); + + // unsafe { + // let func: JitFunction i32> = exec_engine.get_function("fn0").unwrap(); + // let result = func.call(0 as _, 0); + // println!("result: {}", result); + // } } diff --git a/lib/runtime-core/src/types.rs b/lib/runtime-core/src/types.rs index bec1500b6..d3cd937bc 100644 --- a/lib/runtime-core/src/types.rs +++ b/lib/runtime-core/src/types.rs @@ -1,6 +1,6 @@ use crate::{ memory::MemoryType, - module::{ModuleInfo, ModuleInner}, + module::ModuleInfo, structures::TypedIndex, units::Pages, }; From 07c8975304524dba8c6c6e790f61bc4a9b9bade2 Mon Sep 17 00:00:00 2001 From: Lachlan Sneff Date: Fri, 22 Feb 2019 16:20:26 -0800 Subject: [PATCH 08/75] Fix clif backend --- lib/clif-backend/src/lib.rs | 2 +- lib/clif-backend/src/module.rs | 4 ++-- lib/clif-backend/src/module_env.rs | 1 - lib/clif-backend/src/resolver.rs | 2 +- 4 files changed, 4 insertions(+), 5 deletions(-) diff --git a/lib/clif-backend/src/lib.rs b/lib/clif-backend/src/lib.rs index df2e4e208..967cdd5ed 100644 --- a/lib/clif-backend/src/lib.rs +++ b/lib/clif-backend/src/lib.rs @@ -43,7 +43,7 @@ impl Compiler for CraneliftCompiler { let isa = get_isa(); - let mut module = module::Module::new(wasm); + let mut module = module::Module::new(); let module_env = module_env::ModuleEnv::new(&mut module, &*isa); let func_bodies = module_env.translate(wasm)?; diff --git a/lib/clif-backend/src/module.rs b/lib/clif-backend/src/module.rs index 38a657625..9e934ee0a 100644 --- a/lib/clif-backend/src/module.rs +++ b/lib/clif-backend/src/module.rs @@ -7,7 +7,7 @@ use cranelift_wasm; use hashbrown::HashMap; use std::sync::Arc; -use wasmer_runtime_core::cache::{Artifact, Error as CacheError, WasmHash}; +use wasmer_runtime_core::cache::{Artifact, Error as CacheError}; use wasmer_runtime_core::{ backend::Backend, @@ -25,7 +25,7 @@ pub struct Module { } impl Module { - pub fn new(wasm: &[u8]) -> Self { + pub fn new() -> Self { Self { info: ModuleInfo { memories: Map::new(), diff --git a/lib/clif-backend/src/module_env.rs b/lib/clif-backend/src/module_env.rs index 643679a5f..7c6cd6731 100644 --- a/lib/clif-backend/src/module_env.rs +++ b/lib/clif-backend/src/module_env.rs @@ -4,7 +4,6 @@ use crate::{ }; use cranelift_codegen::{ir, isa}; use cranelift_wasm::{self, translate_module, FuncTranslator, ModuleEnvironment}; -use std::sync::Arc; use wasmer_runtime_core::{ error::{CompileError, CompileResult}, module::{ diff --git a/lib/clif-backend/src/resolver.rs b/lib/clif-backend/src/resolver.rs index 05af6e3d0..3095e8882 100644 --- a/lib/clif-backend/src/resolver.rs +++ b/lib/clif-backend/src/resolver.rs @@ -202,7 +202,7 @@ impl FuncResolverBuilder { pub fn finalize( mut self, - signatures: &SliceMap>, + signatures: &SliceMap, trampolines: Arc, handler_data: HandlerData, ) -> CompileResult<(FuncResolver, BackendCache)> { From 2a913f5663a90d0255ee2a116c7a4fe2c5364d64 Mon Sep 17 00:00:00 2001 From: Lachlan Sneff Date: Fri, 22 Feb 2019 17:34:55 -0800 Subject: [PATCH 09/75] Implement table, partial call_indirect --- Cargo.lock | 177 ++++++++++++++++------------- lib/llvm-backend/src/code.rs | 79 ++++++++++++- lib/llvm-backend/src/intrinsics.rs | 113 +++++++++++++++++- lib/llvm-backend/src/lib.rs | 98 +++++++++++----- 4 files changed, 356 insertions(+), 111 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f4394c573..ca2129890 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,6 +1,6 @@ [[package]] name = "aho-corasick" -version = "0.6.9" +version = "0.6.10" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -19,7 +19,7 @@ name = "atty" version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", "termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -31,13 +31,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "backtrace" -version = "0.3.13" +version = "0.3.14" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "backtrace-sys 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-demangle 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -48,7 +48,7 @@ version = "0.1.28" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cc 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -118,11 +118,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.85 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.58 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)", "syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)", - "tempfile 3.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "tempfile 3.0.7 (registry+https://github.com/rust-lang/crates.io-index)", "toml 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -150,7 +150,7 @@ version = "0.26.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", "libloading 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -264,7 +264,7 @@ dependencies = [ [[package]] name = "either" -version = "1.5.0" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -294,7 +294,7 @@ version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "errno-dragonfly 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -304,7 +304,7 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "gcc 0.3.55 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -312,7 +312,7 @@ name = "failure" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "backtrace 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)", + "backtrace 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", "failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -377,7 +377,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -409,19 +409,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "inkwell" version = "0.1.0" -source = "git+https://github.com/TheDan64/inkwell?branch=llvm7-0#715423bc67f46518ec489343b52455a27c1ff761" +source = "git+https://github.com/TheDan64/inkwell?branch=llvm7-0#e66f8941061a45299ef73533c747c32bcd5d696a" dependencies = [ - "either 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "either 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "enum-methods 0.0.8 (registry+https://github.com/rust-lang/crates.io-index)", "inkwell_internal_macros 0.1.0 (git+https://github.com/TheDan64/inkwell?branch=llvm7-0)", - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", "llvm-sys 70.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "inkwell_internal_macros" version = "0.1.0" -source = "git+https://github.com/TheDan64/inkwell?branch=llvm7-0#715423bc67f46518ec489343b52455a27c1ff761" +source = "git+https://github.com/TheDan64/inkwell?branch=llvm7-0#e66f8941061a45299ef73533c747c32bcd5d696a" dependencies = [ "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", "syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)", @@ -448,13 +448,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "libc" -version = "0.2.48" -source = "registry+https://github.com/rust-lang/crates.io-index" +version = "0.2.49" +source = "git+https://github.com/rust-lang/libc#68701e7e673da580de8ba6197c544316bd38e84a" [[package]] name = "libc" version = "0.2.49" -source = "git+https://github.com/rust-lang/libc#9a9e2e05c9532557362e5b24b0622259851392fa" +source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "libloading" @@ -472,7 +472,7 @@ dependencies = [ "goblin 0.0.20 (registry+https://github.com/rust-lang/crates.io-index)", "hashbrown 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "inkwell 0.1.0 (git+https://github.com/TheDan64/inkwell?branch=llvm7-0)", - "smallvec 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", "wabt 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)", "wasmer-runtime-core 0.1.2", "wasmparser 0.28.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -485,7 +485,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cc 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -517,7 +517,7 @@ name = "memmap" version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -529,7 +529,7 @@ dependencies = [ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "cc 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)", "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -541,7 +541,7 @@ dependencies = [ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "cc 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)", "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -573,7 +573,7 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -591,10 +591,10 @@ name = "parking_lot_core" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -608,6 +608,14 @@ name = "plain" version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "proc-macro2" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "proc-macro2" version = "0.4.27" @@ -626,6 +634,14 @@ name = "quote" version = "0.3.15" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "quote" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "quote" version = "0.6.11" @@ -640,7 +656,7 @@ version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", "rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -695,7 +711,7 @@ name = "rand_jitter" version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -707,7 +723,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -766,7 +782,7 @@ name = "regex" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "aho-corasick 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", + "aho-corasick 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", "memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "regex-syntax 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -846,7 +862,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "serde" -version = "1.0.87" +version = "1.0.88" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "serde_derive 1.0.58 (registry+https://github.com/rust-lang/crates.io-index)", @@ -858,7 +874,7 @@ version = "0.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -866,17 +882,17 @@ name = "serde_bytes" version = "0.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "serde_derive" -version = "1.0.87" +version = "1.0.58" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.13.11 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -886,7 +902,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", "ryu 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -902,11 +918,8 @@ dependencies = [ [[package]] name = "smallvec" -version = "0.6.8" +version = "0.6.9" source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", -] [[package]] name = "stable_deref_trait" @@ -948,6 +961,16 @@ dependencies = [ "unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "syn" +version = "0.13.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "syn" version = "0.15.26" @@ -989,11 +1012,11 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.0.6" +version = "3.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)", "remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1013,7 +1036,7 @@ name = "termion" version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)", "redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1039,7 +1062,7 @@ name = "time" version = "0.1.42" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1049,7 +1072,7 @@ name = "toml" version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "serde 1.0.85 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1082,14 +1105,6 @@ name = "unicode-xid" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "unreachable" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "utf8-ranges" version = "1.0.2" @@ -1115,8 +1130,8 @@ name = "wabt" version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.58 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)", "wabt-sys 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1154,12 +1169,12 @@ dependencies = [ "cranelift-native 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)", "cranelift-wasm 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)", "hashbrown 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", "nix 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)", "serde-bench 0.0.7 (registry+https://github.com/rust-lang/crates.io-index)", "serde_bytes 0.10.4 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.58 (registry+https://github.com/rust-lang/crates.io-index)", "target-lexicon 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "wasmer-runtime-core 0.1.2", "wasmer-win-exception-handler 0.0.1", @@ -1173,8 +1188,8 @@ version = "0.1.0" dependencies = [ "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.49 (git+https://github.com/rust-lang/libc)", "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.49 (git+https://github.com/rust-lang/libc)", "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", "wabt 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1197,7 +1212,7 @@ name = "wasmer-runtime-c-api" version = "0.1.4" dependencies = [ "cbindgen 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", "wasmer-runtime 0.1.4", "wasmer-runtime-core 0.1.2", ] @@ -1212,14 +1227,14 @@ dependencies = [ "hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", "nix 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "page_size 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)", "serde-bench 0.0.7 (registry+https://github.com/rust-lang/crates.io-index)", "serde_bytes 0.10.4 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.58 (registry+https://github.com/rust-lang/crates.io-index)", "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "wasmer-clif-backend 0.1.2", "wasmparser 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1241,7 +1256,7 @@ version = "0.0.1" dependencies = [ "bindgen 0.46.0 (registry+https://github.com/rust-lang/crates.io-index)", "cmake 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "wasmer-runtime-core 0.1.2", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1268,7 +1283,7 @@ version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1318,11 +1333,11 @@ dependencies = [ ] [metadata] -"checksum aho-corasick 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)" = "1e9a933f4e58658d7b12defcf96dc5c720f20832deebe3e0a19efd3b6aaeeb9e" +"checksum aho-corasick 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "81ce3d38065e618af2d7b77e10c5ad9a069859b4be3c2250f674af3840d9c8a5" "checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" "checksum atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "9a7d5b8723950951411ee34d271d99dddcc2035a16ab25310ea2c8cfd4369652" "checksum autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a6d640bee2da49f60a4068a7fae53acde8982514ab7bae8b8cea9e88cbcfd799" -"checksum backtrace 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)" = "b5b493b66e03090ebc4343eb02f94ff944e0cbc9ac6571491d170ba026741eb5" +"checksum backtrace 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)" = "cd5a90e2b463010cd0e0ce9a11d4a9d5d58d9f41d4a6ba3dcaf9e68b466e88b4" "checksum backtrace-sys 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)" = "797c830ac25ccc92a7f8a7b9862bde440715531514594a6154e3d4a54dd769b6" "checksum bindgen 0.46.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8f7f7f0701772b17de73e4f5cbcb1dd6926f4706cba4c1ab62c5367f8bdc94e1" "checksum bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12" @@ -1331,8 +1346,8 @@ dependencies = [ "checksum byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" "checksum byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a019b10a2a7cdeb292db131fc8113e57ea2a908f6e7894b0c3c671893b65dbeb" "checksum cast 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "926013f2860c46252efceabb19f4a6b308197505082c609025aa6706c011d427" -"checksum cc 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)" = "4390a3b5f4f6bce9c1d0c00128379df433e53777fdd30e92f16a529332baec4e" "checksum cbindgen 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "32e01024aaf5390d6a8145047371a4f5b0063a14c1e411bc731353bd2278ca44" +"checksum cc 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)" = "4390a3b5f4f6bce9c1d0c00128379df433e53777fdd30e92f16a529332baec4e" "checksum cexpr 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "644d693ecfa91955ed32dcc7eda4914e1be97a641fb6f0645a37348e20b230da" "checksum cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "082bb9b28e00d3c9d39cc03e64ce4cea0f1bb9b3fde493f0cbc008472d22bdf4" "checksum clang-sys 0.26.4 (registry+https://github.com/rust-lang/crates.io-index)" = "6ef0c1bcf2e99c649104bd7a7012d8f8802684400e03db0ec0af48583c6fa0e4" @@ -1347,7 +1362,7 @@ dependencies = [ "checksum cranelift-native 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)" = "474bee81d620a473bf43411a3d6f10ffbf7965141dc5e5b76d8d2151dde3285d" "checksum cranelift-wasm 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)" = "49723365dab9a48b354bdc24cb6d9d5719bc1d3b858ffd2ea179d0d7d885804a" "checksum digest 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "05f47366984d3ad862010e22c7ce81a7dbcaebbdfb37241a620f8b6596ee135c" -"checksum either 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3be565ca5c557d7f59e7cfcf1844f9e3033650c929c6566f511e8005f205c1d0" +"checksum either 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c67353c641dc847124ea1902d69bd753dee9bb3beff9aa3662ecf86c971d1fac" "checksum enum-methods 0.0.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7798e7da2d4cb0d6d6fc467e8d6b5bf247e9e989f786dde1732d79899c32bb10" "checksum env_logger 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "afb070faf94c85d17d50ca44f6ad076bce18ae92f0037d350947240a36e9d42e" "checksum errno 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "c2a071601ed01b988f896ab14b95e67335d1eeb50190932a1320f7fe3cadc84e" @@ -1371,8 +1386,8 @@ dependencies = [ "checksum itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1306f3464951f30e30d12373d31c79fbd52d236e5e896fd92f96ec7babbbe60b" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" "checksum lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a374c89b9db55895453a74c1e38861d9deec0b01b405a82516e9d5de4820dea1" -"checksum libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)" = "e962c7641008ac010fa60a7dfdc1712449f29c44ef2d4702394aea943ee75047" "checksum libc 0.2.49 (git+https://github.com/rust-lang/libc)" = "" +"checksum libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)" = "413f3dfc802c5dc91dc570b05125b6cda9855edfaa9825c9849807876376e70e" "checksum libloading 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9c3ad660d7cb8c5822cd83d10897b0f1f1526792737a179e73896152f85b88c2" "checksum llvm-sys 70.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "60a9ee82fe0fa72ae6ef6d018b407296085863836451c7a97384f84ed7e26b9f" "checksum lock_api 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "62ebf1391f6acad60e5c8b43706dde4582df75c06698ab44511d15016bc2442c" @@ -1389,9 +1404,11 @@ dependencies = [ "checksum parking_lot_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "94c8c7923936b28d546dfd14d4472eaf34c99b14e1c973a32b3e6d4eb04298c9" "checksum peeking_take_while 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099" "checksum plain 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "b4596b6d070b27117e987119b4dac604f3c58cfb0b191112e24771b2faeac1a6" +"checksum proc-macro2 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "1b06e2f335f48d24442b35a19df506a835fb3547bc3c06ef27340da9acf5cae7" "checksum proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)" = "4d317f9caece796be1980837fd5cb3dfec5613ebdb04ad0956deea83ce168915" "checksum quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9274b940887ce9addde99c4eee6b5c44cc494b182b97e73dc8ffdcb3397fd3f0" "checksum quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a" +"checksum quote 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9949cfe66888ffe1d53e6ec9d9f3b70714083854be20fd5e271b232a017401e8" "checksum quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)" = "cdd8e04bd9c52e0342b406469d494fcb033be4bdbe5c606016defbb1681411e1" "checksum rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca" "checksum rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef" @@ -1418,23 +1435,24 @@ dependencies = [ "checksum scroll_derive 0.9.5 (registry+https://github.com/rust-lang/crates.io-index)" = "8f1aa96c45e7f5a91cb7fabe7b279f02fea7126239fc40b732316e8b6a2d0fcb" "checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" "checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" -"checksum serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)" = "2e20fde37801e83c891a2dc4ebd3b81f0da4d1fb67a9e0a2a3b921e2536a58ee" +"checksum serde 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)" = "9f301d728f2b94c9a7691c90f07b0b4e8a4517181d9461be94c04bddeb4bd850" "checksum serde-bench 0.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "d733da87e79faaac25616e33d26299a41143fd4cd42746cbb0e91d8feea243fd" "checksum serde_bytes 0.10.4 (registry+https://github.com/rust-lang/crates.io-index)" = "adb6e51a6b3696b301bc221d785f898b4457c619b51d7ce195a6d20baecb37b3" -"checksum serde_derive 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)" = "633e97856567e518b59ffb2ad7c7a4fd4c5d91d9c7f32dd38a27b2bf7e8114ea" +"checksum serde_derive 1.0.58 (registry+https://github.com/rust-lang/crates.io-index)" = "ac38f51a52a556cd17545798e29536885fb1a3fa63d6399f5ef650f4a7d35901" "checksum serde_json 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)" = "27dce848e7467aa0e2fcaf0a413641499c0b745452aaca1194d24dedde9e13c9" "checksum sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b4d8bfd0e469f417657573d8451fb33d16cfe0989359b93baf3a1ffc639543d" -"checksum smallvec 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)" = "88aea073965ab29f6edb5493faf96ad662fb18aa9eeb186a3b7057951605ed15" +"checksum smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)" = "c4488ae950c49d403731982257768f48fada354a5203fe81f9bb6f43ca9002be" "checksum stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dba1a27d3efae4351c8051072d619e3ade2820635c3958d826bfea39d59b54c8" "checksum strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4f380125926a99e52bc279241539c018323fab05ad6368b56f93d9369ff550" "checksum structopt 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "670ad348dc73012fcf78c71f06f9d942232cdd4c859d4b6975e27836c3efc0c3" "checksum structopt-derive 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "ef98172b1a00b0bec738508d3726540edcbd186d50dfd326f2b1febbb3559f04" "checksum syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d3b891b9015c88c576343b9b3e41c2c11a51c219ef067b264bd9c8aa9b441dad" +"checksum syn 0.13.11 (registry+https://github.com/rust-lang/crates.io-index)" = "14f9bf6292f3a61d2c716723fdb789a41bbe104168e6f496dc6497e531ea1b9b" "checksum syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)" = "f92e629aa1d9c827b2bb8297046c1ccffc57c99b947a680d3ccff1f136a3bee9" "checksum synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a393066ed9010ebaed60b9eafa373d4b1baac186dd7e008555b0f702b51945b6" "checksum synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "73687139bf99285483c96ac0add482c3776528beac1d97d444f6e91f203a2015" "checksum target-lexicon 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4af5e2227f0b887d591d3724b796a96eff04226104d872f5b3883fcd427d64b9" -"checksum tempfile 3.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "37daa55a7240c4931c84559f03b3cad7d19535840d1c4a0cc4e9b2fb0dcf70ff" +"checksum tempfile 3.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "b86c784c88d98c801132806dadd3819ed29d8600836c4088e855cdf3e178ed8a" "checksum termcolor 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "4096add70612622289f2fdcdbd5086dc81c1e2675e6ae58d6c4f62a16c6d7f2f" "checksum termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "689a3bdfaab439fd92bc87df5c4c78417d3cbe537487274e9b0b2dce76e92096" "checksum textwrap 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "307686869c93e71f94da64286f9a9524c0f308a9e1c87a583de8e9c9039ad3f6" @@ -1447,7 +1465,6 @@ dependencies = [ "checksum unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "882386231c45df4700b275c7ff55b6f3698780a650026380e72dabe76fa46526" "checksum unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f860d7d29cf02cb2f3f359fd35991af3d30bac52c57d265a3c461074cb4dc" "checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" -"checksum unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "382810877fe448991dfc7f0dd6e3ae5d58088fd0ea5e35189655f84e6814fa56" "checksum utf8-ranges 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "796f7e48bef87609f7ade7e06495a87d5cd06c7866e6a5cbfceffc558a243737" "checksum vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a" "checksum version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd" diff --git a/lib/llvm-backend/src/code.rs b/lib/llvm-backend/src/code.rs index 48c477f4a..d72659fd9 100644 --- a/lib/llvm-backend/src/code.rs +++ b/lib/llvm-backend/src/code.rs @@ -13,7 +13,8 @@ use wasmer_runtime_core::{ module::ModuleInfo, structures::{Map, SliceMap, TypedIndex}, types::{ - FuncIndex, FuncSig, GlobalIndex, LocalFuncIndex, LocalOrImport, MemoryIndex, SigIndex, Type, + FuncIndex, FuncSig, GlobalIndex, LocalFuncIndex, LocalOrImport, MemoryIndex, SigIndex, + TableIndex, Type, }, }; use wasmparser::{ @@ -622,6 +623,82 @@ fn parse_function( } } Operator::CallIndirect { index, table_index } => { + let expected_dynamic_sigindex = ctx.dynamic_sigindex(SigIndex::new(index as usize)); + let (table_base, table_bound) = ctx.table(TableIndex::new(table_index as usize)); + let func_index = state.pop1()?.into_int_value(); + + // We assume the table has the `anyfunc` element type. + let casted_table_base = builder.build_pointer_cast( + table_base, + intrinsics.anyfunc_ty.ptr_type(AddressSpace::Generic), + "casted_table_base", + ); + + let anyfunc_struct_ptr = unsafe { + builder.build_in_bounds_gep( + casted_table_base, + &[func_index], + "anyfunc_struct_ptr", + ) + }; + + // Load things from the anyfunc data structure. + let (func_ptr, ctx_ptr, found_dynamic_sigindex) = unsafe { + ( + builder + .build_load( + builder.build_struct_gep(anyfunc_struct_ptr, 0, "func_ptr_ptr"), + "func_ptr", + ) + .into_pointer_value(), + builder + .build_load( + builder.build_struct_gep(anyfunc_struct_ptr, 1, "ctx_ptr_ptr"), + "ctx_ptr", + ) + .into_pointer_value(), + builder + .build_load( + builder.build_struct_gep(anyfunc_struct_ptr, 2, "sigindex_ptr"), + "sigindex", + ) + .into_int_value(), + ) + }; + + let sigindices_equal = builder.build_int_compare( + IntPredicate::EQ, + expected_dynamic_sigindex, + found_dynamic_sigindex, + "sigindices_equal", + ); + + // Tell llvm that `expected_dynamic_sigindex` should equal `found_dynamic_sigindex`. + let sigindices_equal = builder + .build_call( + intrinsics.expect_i1, + &[ + sigindices_equal.as_basic_value_enum(), + intrinsics.i1_ty.const_int(1, false).as_basic_value_enum(), + ], + "sigindices_equal_expect", + ) + .try_as_basic_value() + .left() + .unwrap(); + + let continue_block = context.append_basic_block(&function, "continue_block"); + let sigindices_notequal_block = + context.append_basic_block(&function, "sigindices_notequal_block"); + + builder.position_at_end(&sigindices_notequal_block); + builder.build_unreachable(); + builder.position_at_end(&continue_block); + + println!("func ptr: {:#?}", func_ptr); + println!("ctx ptr: {:#?}", ctx_ptr); + println!("found dynamic sigindex: {:#?}", found_dynamic_sigindex); + unimplemented!("{}, {}", index, table_index); } diff --git a/lib/llvm-backend/src/intrinsics.rs b/lib/llvm-backend/src/intrinsics.rs index 6ffbb6ea6..ccc0081bf 100644 --- a/lib/llvm-backend/src/intrinsics.rs +++ b/lib/llvm-backend/src/intrinsics.rs @@ -12,7 +12,9 @@ use wasmer_runtime_core::{ memory::MemoryType, module::ModuleInfo, structures::TypedIndex, - types::{GlobalIndex, ImportedFuncIndex, LocalOrImport, MemoryIndex, TableIndex, Type}, + types::{ + GlobalIndex, ImportedFuncIndex, LocalOrImport, MemoryIndex, SigIndex, TableIndex, Type, + }, }; fn type_to_llvm_ptr(intrinsics: &Intrinsics, ty: Type) -> PointerType { @@ -61,6 +63,8 @@ pub struct Intrinsics { pub copysign_f32: FunctionValue, pub copysign_f64: FunctionValue, + pub expect_i1: FunctionValue, + pub void_ty: VoidType, pub i1_ty: IntType, pub i8_ty: IntType, @@ -77,6 +81,8 @@ pub struct Intrinsics { pub f32_ptr_ty: PointerType, pub f64_ptr_ty: PointerType, + pub anyfunc_ty: StructType, + pub i1_zero: IntValue, pub i32_zero: IntValue, pub i64_zero: IntValue, @@ -142,6 +148,17 @@ impl Intrinsics { let local_global_ty = i64_ty; let imported_func_ty = context.struct_type(&[i8_ptr_ty_basic, ctx_ptr_ty.as_basic_type_enum()], false); + let sigindex_ty = i32_ty; + + let anyfunc_ty = context.struct_type( + &[ + i8_ptr_ty_basic, + ctx_ptr_ty.as_basic_type_enum(), + sigindex_ty.as_basic_type_enum(), + ], + false, + ); + ctx_ty.set_body( &[ local_memory_ty @@ -172,6 +189,9 @@ impl Intrinsics { .ptr_type(AddressSpace::Generic) .ptr_type(AddressSpace::Generic) .as_basic_type_enum(), + sigindex_ty + .ptr_type(AddressSpace::Generic) + .as_basic_type_enum(), ], false, ); @@ -195,6 +215,8 @@ impl Intrinsics { let ret_i32_take_ctx_i32 = i32_ty.fn_type(&[ctx_ptr_ty.as_basic_type_enum(), i32_ty_basic], false); + let ret_i1_take_i1_i1 = i1_ty.fn_type(&[i1_ty_basic, i1_ty_basic], false); + Self { ctlz_i32: module.add_function("llvm.ctlz.i32", ret_i32_take_i32_i1, None), ctlz_i64: module.add_function("llvm.ctlz.i64", ret_i64_take_i64_i1, None), @@ -232,6 +254,8 @@ impl Intrinsics { copysign_f32: module.add_function("llvm.copysign.f32", ret_f32_take_f32_f32, None), copysign_f64: module.add_function("llvm.copysign.f64", ret_f64_take_f64_f64, None), + expect_i1: module.add_function("llvm.expect.i1", ret_i1_take_i1_i1, None), + void_ty, i1_ty, i8_ty, @@ -248,6 +272,8 @@ impl Intrinsics { f32_ptr_ty, f64_ptr_ty, + anyfunc_ty, + i1_zero, i32_zero, i64_zero, @@ -340,6 +366,7 @@ impl Intrinsics { cached_memories: HashMap::new(), cached_tables: HashMap::new(), + cached_sigindices: HashMap::new(), cached_globals: HashMap::new(), cached_imported_functions: HashMap::new(), @@ -389,6 +416,7 @@ pub struct CtxType<'a> { cached_memories: HashMap, cached_tables: HashMap, + cached_sigindices: HashMap, cached_globals: HashMap, cached_imported_functions: HashMap, @@ -473,6 +501,89 @@ impl<'a> CtxType<'a> { } } + pub fn table(&mut self, index: TableIndex) -> (PointerValue, IntValue) { + let (cached_tables, builder, info, ctx_ptr_value, intrinsics) = ( + &mut self.cached_tables, + self.builder, + self.info, + self.ctx_ptr_value, + self.intrinsics, + ); + + let TableCache { + ptr_to_base_ptr, + ptr_to_bounds, + } = *cached_tables.entry(index).or_insert_with(|| { + let (table_array_ptr_ptr, index) = match index.local_or_import(info) { + LocalOrImport::Local(local_table_index) => ( + unsafe { builder.build_struct_gep(ctx_ptr_value, 1, "table_array_ptr_ptr") }, + local_table_index.index() as u64, + ), + LocalOrImport::Import(import_table_index) => ( + unsafe { builder.build_struct_gep(ctx_ptr_value, 4, "table_array_ptr_ptr") }, + import_table_index.index() as u64, + ), + }; + + let table_array_ptr = builder + .build_load(table_array_ptr_ptr, "table_array_ptr") + .into_pointer_value(); + let const_index = intrinsics.i32_ty.const_int(index, false); + let table_ptr_ptr = unsafe { + builder.build_in_bounds_gep(table_array_ptr, &[const_index], "table_ptr_ptr") + }; + let table_ptr = builder + .build_load(table_ptr_ptr, "table_ptr") + .into_pointer_value(); + + let (ptr_to_base_ptr, ptr_to_bounds) = unsafe { + ( + builder.build_struct_gep(table_ptr, 0, "base_ptr"), + builder.build_struct_gep(table_ptr, 1, "bounds_ptr"), + ) + }; + + TableCache { + ptr_to_base_ptr, + ptr_to_bounds, + } + }); + + ( + builder + .build_load(ptr_to_base_ptr, "base_ptr") + .into_pointer_value(), + builder.build_load(ptr_to_bounds, "bounds").into_int_value(), + ) + } + + pub fn dynamic_sigindex(&mut self, index: SigIndex) -> IntValue { + let (cached_sigindices, builder, info, ctx_ptr_value, intrinsics) = ( + &mut self.cached_sigindices, + self.builder, + self.info, + self.ctx_ptr_value, + self.intrinsics, + ); + + *cached_sigindices.entry(index).or_insert_with(|| { + let sigindex_array_ptr_ptr = + unsafe { builder.build_struct_gep(ctx_ptr_value, 7, "sigindex_array_ptr_ptr") }; + let sigindex_array_ptr = builder + .build_load(sigindex_array_ptr_ptr, "sigindex_array_ptr") + .into_pointer_value(); + let const_index = intrinsics.i32_ty.const_int(index.index() as u64, false); + + let sigindex_ptr = unsafe { + builder.build_in_bounds_gep(sigindex_array_ptr, &[const_index], "sigindex_ptr") + }; + + builder + .build_load(sigindex_ptr, "sigindex") + .into_int_value() + }) + } + pub fn global_cache(&mut self, index: GlobalIndex) -> GlobalCache { let (cached_globals, builder, ctx_ptr_value, info, intrinsics) = ( &mut self.cached_globals, diff --git a/lib/llvm-backend/src/lib.rs b/lib/llvm-backend/src/lib.rs index 6279aa8e1..e70af96c0 100644 --- a/lib/llvm-backend/src/lib.rs +++ b/lib/llvm-backend/src/lib.rs @@ -1,13 +1,14 @@ -use wasmer_runtime_core::{ - backend::{Compiler, Token}, - error::CompileError, - module::ModuleInner, -}; use inkwell::{ execution_engine::JitFunction, - targets::{TargetMachine, Target, RelocMode, CodeModel, InitializationConfig, FileType}, + targets::{CodeModel, FileType, InitializationConfig, RelocMode, Target, TargetMachine}, OptimizationLevel, }; +use wasmer_runtime_core::{ + backend::{Compiler, Token}, + cache::{Artifact, Error as CacheError}, + error::CompileError, + module::ModuleInner, +}; mod code; mod intrinsics; @@ -31,22 +32,29 @@ impl Compiler for LLVMCompiler { unimplemented!() } + + unsafe fn from_cache(&self, _artifact: Artifact, _: Token) -> Result { + unimplemented!() + } } #[test] fn test_read_module() { - use wasmer_runtime_core::vmcalls; use wabt::wat2wasm; + use wasmer_runtime_core::vmcalls; // let wasm = include_bytes!("../../spectests/examples/simple/simple.wasm") as &[u8]; let wat = r#" (module (type $t0 (func (param i32) (result i32))) (type $t1 (func (result i32))) (memory 1) + (table 10 anyfunc) + (elem (i32.const 0) $foobar) (global $g0 (mut i32) (i32.const 0)) (func $foo (type $t0) (param i32) (result i32) get_local 0 - call $foobar + i32.const 0 + call_indirect (type $t0) memory.grow ) (func $foobar (type $t0) @@ -74,19 +82,23 @@ fn test_read_module() { }); let triple = TargetMachine::get_default_triple().to_string(); let target = Target::from_triple(&triple).unwrap(); - let target_machine = target.create_target_machine( - &triple, - &TargetMachine::get_host_cpu_name().to_string(), - &TargetMachine::get_host_cpu_features().to_string(), - OptimizationLevel::Default, - RelocMode::PIC, - CodeModel::Default, - ).unwrap(); + let target_machine = target + .create_target_machine( + &triple, + &TargetMachine::get_host_cpu_name().to_string(), + &TargetMachine::get_host_cpu_features().to_string(), + OptimizationLevel::Default, + RelocMode::PIC, + CodeModel::Default, + ) + .unwrap(); - let memory_buffer = target_machine.write_to_memory_buffer(&module, FileType::Object).unwrap(); + let memory_buffer = target_machine + .write_to_memory_buffer(&module, FileType::Object) + .unwrap(); // std::fs::write("memory_buffer", memory_buffer.as_slice()).unwrap(); let mem_buf_slice = memory_buffer.as_slice(); - + let macho = goblin::mach::MachO::parse(mem_buf_slice, 0).unwrap(); let symbols = macho.symbols.as_ref().unwrap(); let relocations = macho.relocations().unwrap(); @@ -95,22 +107,50 @@ fn test_read_module() { for reloc_info in reloc_iter { let reloc_info = reloc_info.unwrap(); println!("\treloc_info: {:#?}", reloc_info); - println!("\tsymbol: {:#?}", symbols.get(reloc_info.r_symbolnum()).unwrap()); + println!( + "\tsymbol: {:#?}", + symbols.get(reloc_info.r_symbolnum()).unwrap() + ); } } } - - let exec_engine = module.create_jit_execution_engine(OptimizationLevel::Default).unwrap(); + let exec_engine = module + .create_jit_execution_engine(OptimizationLevel::Default) + .unwrap(); - exec_engine.add_global_mapping(&intrinsics.memory_grow_dynamic_local, vmcalls::local_dynamic_memory_grow as usize); - exec_engine.add_global_mapping(&intrinsics.memory_grow_static_local, vmcalls::local_static_memory_grow as usize); - exec_engine.add_global_mapping(&intrinsics.memory_grow_dynamic_import, vmcalls::imported_dynamic_memory_grow as usize); - exec_engine.add_global_mapping(&intrinsics.memory_grow_static_import, vmcalls::imported_static_memory_grow as usize); - exec_engine.add_global_mapping(&intrinsics.memory_size_dynamic_local, vmcalls::local_dynamic_memory_size as usize); - exec_engine.add_global_mapping(&intrinsics.memory_size_static_local, vmcalls::local_static_memory_size as usize); - exec_engine.add_global_mapping(&intrinsics.memory_size_dynamic_import, vmcalls::imported_dynamic_memory_size as usize); - exec_engine.add_global_mapping(&intrinsics.memory_size_static_import, vmcalls::imported_static_memory_size as usize); + exec_engine.add_global_mapping( + &intrinsics.memory_grow_dynamic_local, + vmcalls::local_dynamic_memory_grow as usize, + ); + exec_engine.add_global_mapping( + &intrinsics.memory_grow_static_local, + vmcalls::local_static_memory_grow as usize, + ); + exec_engine.add_global_mapping( + &intrinsics.memory_grow_dynamic_import, + vmcalls::imported_dynamic_memory_grow as usize, + ); + exec_engine.add_global_mapping( + &intrinsics.memory_grow_static_import, + vmcalls::imported_static_memory_grow as usize, + ); + exec_engine.add_global_mapping( + &intrinsics.memory_size_dynamic_local, + vmcalls::local_dynamic_memory_size as usize, + ); + exec_engine.add_global_mapping( + &intrinsics.memory_size_static_local, + vmcalls::local_static_memory_size as usize, + ); + exec_engine.add_global_mapping( + &intrinsics.memory_size_dynamic_import, + vmcalls::imported_dynamic_memory_size as usize, + ); + exec_engine.add_global_mapping( + &intrinsics.memory_size_static_import, + vmcalls::imported_static_memory_size as usize, + ); // unsafe { // let func: JitFunction i32> = exec_engine.get_function("fn0").unwrap(); From 44b8d0b1ee4efe198d9ca200e6210c31a7a973ae Mon Sep 17 00:00:00 2001 From: Lachlan Sneff Date: Mon, 25 Feb 2019 18:07:22 -0800 Subject: [PATCH 10/75] Start work on object loader using llvm's RuntimeDyld api. --- Cargo.lock | 30 ++++ lib/llvm-backend/Cargo.toml | 8 + lib/llvm-backend/build.rs | 203 +++++++++++++++++++++++++ lib/llvm-backend/cpp/object_loader.cpp | 96 ++++++++++++ lib/llvm-backend/cpp/object_loader.hh | 40 +++++ lib/llvm-backend/src/backend.rs | 79 +++++++--- lib/llvm-backend/src/code.rs | 52 +++++-- lib/llvm-backend/src/intrinsics.rs | 6 +- lib/llvm-backend/src/lib.rs | 177 ++++++++++----------- 9 files changed, 569 insertions(+), 122 deletions(-) create mode 100644 lib/llvm-backend/build.rs create mode 100644 lib/llvm-backend/cpp/object_loader.cpp create mode 100644 lib/llvm-backend/cpp/object_loader.hh diff --git a/Cargo.lock b/Cargo.lock index ca2129890..9d743e96c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -262,6 +262,28 @@ dependencies = [ "generic-array 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "dlopen" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "dlopen_derive 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "dlopen_derive" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "either" version = "1.5.1" @@ -469,10 +491,16 @@ dependencies = [ name = "llvm-backend" version = "0.1.0" dependencies = [ + "cc 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)", + "dlopen 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "goblin 0.0.20 (registry+https://github.com/rust-lang/crates.io-index)", "hashbrown 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "inkwell 0.1.0 (git+https://github.com/TheDan64/inkwell?branch=llvm7-0)", + "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", + "tempfile 3.0.7 (registry+https://github.com/rust-lang/crates.io-index)", "wabt 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)", "wasmer-runtime-core 0.1.2", "wasmparser 0.28.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1362,6 +1390,8 @@ dependencies = [ "checksum cranelift-native 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)" = "474bee81d620a473bf43411a3d6f10ffbf7965141dc5e5b76d8d2151dde3285d" "checksum cranelift-wasm 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)" = "49723365dab9a48b354bdc24cb6d9d5719bc1d3b858ffd2ea179d0d7d885804a" "checksum digest 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "05f47366984d3ad862010e22c7ce81a7dbcaebbdfb37241a620f8b6596ee135c" +"checksum dlopen 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "f8c301a18a3404a48d5d078e86b011ac834a6c4c742217e9aa8ceadd8a7e09e0" +"checksum dlopen_derive 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6e16e4e343d6090ba47113c55bf6aa94e9b1eb5ab0c5abc9510d4c15074f30e9" "checksum either 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c67353c641dc847124ea1902d69bd753dee9bb3beff9aa3662ecf86c971d1fac" "checksum enum-methods 0.0.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7798e7da2d4cb0d6d6fc467e8d6b5bf247e9e989f786dde1732d79899c32bb10" "checksum env_logger 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "afb070faf94c85d17d50ca44f6ad076bce18ae92f0037d350947240a36e9d42e" diff --git a/lib/llvm-backend/Cargo.toml b/lib/llvm-backend/Cargo.toml index 8ffac375f..3ec83d77c 100644 --- a/lib/llvm-backend/Cargo.toml +++ b/lib/llvm-backend/Cargo.toml @@ -11,6 +11,14 @@ inkwell = { git = "https://github.com/TheDan64/inkwell", branch = "llvm7-0" } hashbrown = "0.1.8" smallvec = "0.6.8" goblin = "0.0.20" +dlopen = "0.1.6" +tempfile = "3.0.7" + +[build-dependencies] +cc = "1.0" +lazy_static = "1.2.0" +regex = "1.1.0" +semver = "0.9" [dev-dependencies] wabt = "0.7.4" diff --git a/lib/llvm-backend/build.rs b/lib/llvm-backend/build.rs new file mode 100644 index 000000000..e38cec034 --- /dev/null +++ b/lib/llvm-backend/build.rs @@ -0,0 +1,203 @@ +//! This file was mostly taken from the llvm-sys crate. +//! (https://bitbucket.org/tari/llvm-sys.rs/src/21ab524ec4df1450035df895209c3f8fbeb8775f/build.rs?at=default&fileviewer=file-view-default) + +use regex::Regex; +use lazy_static::lazy_static; +use semver::Version; +use std::env; +use std::ffi::OsStr; +use std::io::{self, ErrorKind}; +use std::path::PathBuf; +use std::process::Command; + +lazy_static! { + /// LLVM version used by this version of the crate. + static ref CRATE_VERSION: Version = { + let crate_version = Version::parse(env!("CARGO_PKG_VERSION")) + .expect("Crate version is somehow not valid semver"); + Version { + major: crate_version.major / 10, + minor: crate_version.major % 10, + .. crate_version + } + }; + + static ref LLVM_CONFIG_BINARY_NAMES: Vec = { + vec![ + "llvm-config".into(), + // format!("llvm-config-{}", CRATE_VERSION.major), + // format!("llvm-config-{}.{}", CRATE_VERSION.major, CRATE_VERSION.minor), + ] + }; + + /// Filesystem path to an llvm-config binary for the correct version. + static ref LLVM_CONFIG_PATH: PathBuf = { + // Try llvm-config via PATH first. + if let Some(name) = locate_system_llvm_config() { + return name.into(); + } else { + println!("Didn't find usable system-wide LLVM."); + } + + // Did the user give us a binary path to use? If yes, try + // to use that and fail if it doesn't work. + let binary_prefix_var = "LLVM_SYS_70_PREFIX"; + + let path = if let Some(path) = env::var_os(&binary_prefix_var) { + Some(path.to_str().unwrap().to_owned()) + } else if let Ok(mut file) = std::fs::File::open(".llvmenv") { + use std::io::Read; + let mut s = String::new(); + file.read_to_string(&mut s).unwrap(); + Some(s) + } else { + None + }; + + if let Some(path) = path { + for binary_name in LLVM_CONFIG_BINARY_NAMES.iter() { + let mut pb: PathBuf = path.clone().into(); + pb.push("bin"); + pb.push(binary_name); + + let ver = llvm_version(&pb) + .expect(&format!("Failed to execute {:?}", &pb)); + if is_compatible_llvm(&ver) { + return pb; + } else { + println!("LLVM binaries specified by {} are the wrong version. + (Found {}, need {}.)", binary_prefix_var, ver, *CRATE_VERSION); + } + } + } + + println!("No suitable version of LLVM was found system-wide or pointed + to by {}. + + Consider using `llvmenv` to compile an appropriate copy of LLVM, and + refer to the llvm-sys documentation for more information. + + llvm-sys: https://crates.io/crates/llvm-sys + llvmenv: https://crates.io/crates/llvmenv", binary_prefix_var); + panic!("Could not find a compatible version of LLVM"); + }; +} + +/// Try to find a system-wide version of llvm-config that is compatible with +/// this crate. +/// +/// Returns None on failure. +fn locate_system_llvm_config() -> Option<&'static str> { + for binary_name in LLVM_CONFIG_BINARY_NAMES.iter() { + match llvm_version(binary_name) { + Ok(ref version) if is_compatible_llvm(version) => { + // Compatible version found. Nice. + return Some(binary_name); + } + Ok(version) => { + // Version mismatch. Will try further searches, but warn that + // we're not using the system one. + println!("Found LLVM version {} on PATH, but need {}.", + version, + *CRATE_VERSION); + } + Err(ref e) if e.kind() == ErrorKind::NotFound => { + // Looks like we failed to execute any llvm-config. Keep + // searching. + } + // Some other error, probably a weird failure. Give up. + Err(e) => panic!("Failed to search PATH for llvm-config: {}", e), + } + } + + None +} + +/// Check whether the given LLVM version is compatible with this version of +/// the crate. +fn is_compatible_llvm(llvm_version: &Version) -> bool { + let strict = env::var_os(format!("LLVM_SYS_{}_STRICT_VERSIONING", + env!("CARGO_PKG_VERSION_MAJOR"))) + .is_some() || cfg!(feature = "strict-versioning"); + if strict { + llvm_version.major == CRATE_VERSION.major && llvm_version.minor == CRATE_VERSION.minor + } else { + llvm_version.major >= CRATE_VERSION.major || + (llvm_version.major == CRATE_VERSION.major && llvm_version.minor >= CRATE_VERSION.minor) + } +} + +/// Get the output from running `llvm-config` with the given argument. +/// +/// Lazily searches for or compiles LLVM as configured by the environment +/// variables. +fn llvm_config(arg: &str) -> String { + llvm_config_ex(&*LLVM_CONFIG_PATH, arg).expect("Surprising failure from llvm-config") +} + +/// Invoke the specified binary as llvm-config. +/// +/// Explicit version of the `llvm_config` function that bubbles errors +/// up. +fn llvm_config_ex>(binary: S, arg: &str) -> io::Result { + Command::new(binary) + .arg(arg) + .arg("--link-static") // Don't use dylib for >= 3.9 + .output() + .map(|output| String::from_utf8(output.stdout) + .expect("Output from llvm-config was not valid UTF-8")) +} + +/// Get the LLVM version using llvm-config. +fn llvm_version>(binary: S) -> io::Result { + let version_str = llvm_config_ex(binary.as_ref(), "--version")?; + + // LLVM isn't really semver and uses version suffixes to build + // version strings like '3.8.0svn', so limit what we try to parse + // to only the numeric bits. + let re = Regex::new(r"^(?P\d+)\.(?P\d+)(?:\.(?P\d+))??").unwrap(); + let c = re.captures(&version_str).expect("Could not determine LLVM version from llvm-config."); + + // some systems don't have a patch number but Version wants it so we just append .0 if it isn't + // there + let s = match c.name("patch") { + None => format!("{}.0", &c[0]), + Some(_) => c[0].to_string(), + }; + Ok(Version::parse(&s).unwrap()) +} + +fn get_llvm_cxxflags() -> String { + let output = llvm_config("--cxxflags"); + + // llvm-config includes cflags from its own compilation with --cflags that + // may not be relevant to us. In particularly annoying cases, these might + // include flags that aren't understood by the default compiler we're + // using. Unless requested otherwise, clean CFLAGS of options that are + // known to be possibly-harmful. + let no_clean = env::var_os(format!("LLVM_SYS_{}_NO_CLEAN_CFLAGS", + env!("CARGO_PKG_VERSION_MAJOR"))) + .is_some(); + if no_clean || cfg!(target_env = "msvc") { + // MSVC doesn't accept -W... options, so don't try to strip them and + // possibly strip something that should be retained. Also do nothing if + // the user requests it. + return output; + } + + output + .split(&[' ', '\n'][..]) + .filter(|word| !word.starts_with("-W")) + .collect::>() + .join(" ") +} + +fn main() { + std::env::set_var("CXXFLAGS", get_llvm_cxxflags()); + cc::Build::new() + .cpp(true) + .file("cpp/object_loader.cpp") + .compile("llvm-backend"); + + println!("cargo:rustc-link-lib=static=llvm-backend"); +} \ No newline at end of file diff --git a/lib/llvm-backend/cpp/object_loader.cpp b/lib/llvm-backend/cpp/object_loader.cpp new file mode 100644 index 000000000..9ab36f4c3 --- /dev/null +++ b/lib/llvm-backend/cpp/object_loader.cpp @@ -0,0 +1,96 @@ +#include "object_loader.hh" +#include +#include + +class MemoryManager : llvm::RuntimeDyld::MemoryManager { +public: + MemoryManager() {} + + virtual ~MemoryManager() {} + + virtual uint8_t* allocateCodeSection(uintptr_t Size, unsigned Alignment, unsigned SectionID, llvm::StringRef SectionName) override { + return nullptr; + } + + virtual uint8_t* allocateDataSection(uintptr_t Size, unsigned Alignment, unsigned SectionID, llvm::StringRef SectionName, bool isReadOnly) override { + return nullptr; + } + + virtual void reserveAllocationSpace( + uintptr_t code_size, + uint32_t code_align, + uintptr_t read_data_size, + uint32_t read_data_align, + uintptr_t read_write_data_size, + uint32_t read_write_data_align + ) override { + + } + + /* Turn on the `reserveAllocationSpace` callback. */ + virtual bool needsToReserveAllocationSpace() override { + return true; + } + + virtual void registerEHFrames(uint8_t* Addr, uint64_t LoadAddr, size_t Size) override { + + } + + virtual void deregisterEHFrames() override { + + } + + virtual bool finalizeMemory(std::string *ErrMsg = nullptr) override { + + + return false; + } + + virtual void notifyObjectLoaded(llvm::RuntimeDyld &RTDyld, const llvm::object::ObjectFile &Obj) override { + + } +private: + struct Section { + uint8_t* base; + size_t num_pages; + size_t num_commited_bytes; + }; + + uint8_t *image_base; + size_t num_allocated_pages; + + Section code_section, read_section, readwrite_section; + + +}; + +class SymbolLookup : llvm::JITSymbolResolver { +public: + virtual llvm::Expected lookup(const LookupSet& symbols) override { + LookupResult result; + + for (auto symbol : symbols) { + result.emplace(symbol, symbol_lookup(symbol)); + } + + return result; + } + + virtual llvm::Expected lookupFlags(const LookupSet& symbols) override { + LookupFlagsResult result; + + for (auto symbol : symbols) { + result.emplace(symbol, symbol_lookup(symbol).getFlags()); + } + + return result; + } + +private: + llvm::JITEvaluatedSymbol symbol_lookup(llvm::StringRef name) { + std::cout << "symbol name: " << (std::string)name << std::endl; + uint64_t addr = 0; + + return llvm::JITEvaluatedSymbol(addr, llvm::JITSymbolFlags::None); + } +}; \ No newline at end of file diff --git a/lib/llvm-backend/cpp/object_loader.hh b/lib/llvm-backend/cpp/object_loader.hh new file mode 100644 index 000000000..50b618b38 --- /dev/null +++ b/lib/llvm-backend/cpp/object_loader.hh @@ -0,0 +1,40 @@ +#include +#include + +typedef enum { + PROTECT_NONE, + PROTECT_READ, + PROTECT_READ_WRITE, + PROTECT_READ_EXECUTE, +} mem_protect_t; + +typedef enum { + RESULT_OK, + RESULT_ALLOCATE_FAILURE, + RESULT_PROTECT_FAILURE, + RESULT_DEALLOC_FAILURE, + RESULT_OBJECT_LOAD_FAILURE, +} result_t; + +typedef result_t (*alloc_memory_t)(size_t size, mem_protect_t protect, uint8_t** ptr_out, size_t* size_out); +typedef result_t (*protect_memory_t)(uint8_t* ptr, size_t size, mem_protect_t protect); +typedef result_t (*dealloc_memory_t)(uint8_t* ptr, size_t size); +typedef uintptr_t (*lookup_vm_symbol_t)(char* name_ptr, size_t name_size); + +typedef struct { + /* Memory management. */ + alloc_memory_t alloc_memory; + protect_memory_t protect_memory; + dealloc_memory_t dealloc_memory; + + lookup_vm_symbol_t lookup_vm_symbol; +} callbacks_t; + +extern "C" { + result_t object_load(uint8_t* mem_ptr, size_t mem_size, callbacks_t* callbacks) { + return RESULT_OK; + } + + void test_cpp() { + } +} \ No newline at end of file diff --git a/lib/llvm-backend/src/backend.rs b/lib/llvm-backend/src/backend.rs index 9821eabf6..2b4bb7023 100644 --- a/lib/llvm-backend/src/backend.rs +++ b/lib/llvm-backend/src/backend.rs @@ -1,45 +1,76 @@ +use crate::intrinsics::Intrinsics; +use dlopen::symbor::Library; use inkwell::{ module::Module, - execution_engine::{ExecutionEngine, JitFunction}, + targets::{CodeModel, FileType, InitializationConfig, RelocMode, Target, TargetMachine}, + OptimizationLevel, }; -use crate::intrinsics::Intrinsics; -use std::ptr::NonNull; +use std::{io::Write, ptr::NonNull}; +use tempfile::NamedTempFile; use wasmer_runtime_core::{ - module::ModuleInner, - types::LocalFuncIndex, - structures::TypedIndex, - backend::{FuncResolver, vm}, + backend::FuncResolver, module::ModuleInner, structures::TypedIndex, types::LocalFuncIndex, vm, }; pub struct LLVMBackend { - exec_engine: ExecutionEngine, + tempfile: NamedTempFile, + library: Library, } impl LLVMBackend { pub fn new(module: Module, intrinsics: Intrinsics) -> Self { - let exec_engine = module.create_jit_execution_engine(OptimizationLevel::Default).unwrap(); + Target::initialize_x86(&InitializationConfig { + asm_parser: true, + asm_printer: true, + base: true, + disassembler: true, + info: true, + machine_code: true, + }); + let triple = TargetMachine::get_default_triple().to_string(); + let target = Target::from_triple(&triple).unwrap(); + let target_machine = target + .create_target_machine( + &triple, + &TargetMachine::get_host_cpu_name().to_string(), + &TargetMachine::get_host_cpu_features().to_string(), + OptimizationLevel::Default, + RelocMode::PIC, + CodeModel::Default, + ) + .unwrap(); - exec_engine.add_global_mapping(&intrinsics.memory_grow_dynamic_local, vmcalls::local_dynamic_memory_grow as usize); - exec_engine.add_global_mapping(&intrinsics.memory_grow_static_local, vmcalls::local_static_memory_grow as usize); - exec_engine.add_global_mapping(&intrinsics.memory_grow_dynamic_import, vmcalls::imported_dynamic_memory_grow as usize); - exec_engine.add_global_mapping(&intrinsics.memory_grow_static_import, vmcalls::imported_static_memory_grow as usize); - exec_engine.add_global_mapping(&intrinsics.memory_size_dynamic_local, vmcalls::local_dynamic_memory_size as usize); - exec_engine.add_global_mapping(&intrinsics.memory_size_static_local, vmcalls::local_static_memory_size as usize); - exec_engine.add_global_mapping(&intrinsics.memory_size_dynamic_import, vmcalls::imported_dynamic_memory_size as usize); - exec_engine.add_global_mapping(&intrinsics.memory_size_static_import, vmcalls::imported_static_memory_size as usize); + let memory_buffer = target_machine + .write_to_memory_buffer(&module, FileType::Object) + .unwrap(); - Self { exec_engine } + let mut tempfile = NamedTempFile::new().unwrap(); + tempfile.write_all(memory_buffer.as_slice()).unwrap(); + tempfile.flush().unwrap(); + + let library = Library::open(tempfile.path()).unwrap(); + + Self { tempfile, library } } } impl FuncResolver for LLVMBackend { - fn get(&self, module: &ModuleInner, local_func_index: LocalFuncIndex) -> Option> { + fn get( + &self, + module: &ModuleInner, + local_func_index: LocalFuncIndex, + ) -> Option> { let index = module.info.imported_functions.len() + local_func_index.index(); - let name = format!("fn{}", index); - + let name = if cfg!(macos) { + format!("_fn{}", index) + } else { + format!("fn{}", index) + }; + unsafe { - let func: JitFunction = self.exec_engine.get_function(&name).ok()?; - + self.library + .symbol::>(&name) + .ok() + .map(|symbol| *symbol) } } -} \ No newline at end of file +} diff --git a/lib/llvm-backend/src/code.rs b/lib/llvm-backend/src/code.rs index d72659fd9..e0f4d984f 100644 --- a/lib/llvm-backend/src/code.rs +++ b/lib/llvm-backend/src/code.rs @@ -481,6 +481,7 @@ fn parse_function( // Emit an unreachable instruction. // If llvm cannot prove that this is never touched, // it will emit a `ud2` instruction on x86_64 arches. + ctx.build_trap(); builder.build_unreachable(); state.reachable = false; } @@ -623,7 +624,8 @@ fn parse_function( } } Operator::CallIndirect { index, table_index } => { - let expected_dynamic_sigindex = ctx.dynamic_sigindex(SigIndex::new(index as usize)); + let sig_index = SigIndex::new(index as usize); + let expected_dynamic_sigindex = ctx.dynamic_sigindex(sig_index); let (table_base, table_bound) = ctx.table(TableIndex::new(table_index as usize)); let func_index = state.pop1()?.into_int_value(); @@ -651,12 +653,10 @@ fn parse_function( "func_ptr", ) .into_pointer_value(), - builder - .build_load( - builder.build_struct_gep(anyfunc_struct_ptr, 1, "ctx_ptr_ptr"), - "ctx_ptr", - ) - .into_pointer_value(), + builder.build_load( + builder.build_struct_gep(anyfunc_struct_ptr, 1, "ctx_ptr_ptr"), + "ctx_ptr", + ), builder .build_load( builder.build_struct_gep(anyfunc_struct_ptr, 2, "sigindex_ptr"), @@ -685,21 +685,49 @@ fn parse_function( ) .try_as_basic_value() .left() - .unwrap(); + .unwrap() + .into_int_value(); let continue_block = context.append_basic_block(&function, "continue_block"); let sigindices_notequal_block = context.append_basic_block(&function, "sigindices_notequal_block"); + builder.build_conditional_branch( + sigindices_equal, + &continue_block, + &sigindices_notequal_block, + ); builder.position_at_end(&sigindices_notequal_block); + ctx.build_trap(); builder.build_unreachable(); builder.position_at_end(&continue_block); - println!("func ptr: {:#?}", func_ptr); - println!("ctx ptr: {:#?}", ctx_ptr); - println!("found dynamic sigindex: {:#?}", found_dynamic_sigindex); + let wasmer_fn_sig = &info.signatures[sig_index]; + let fn_ty = signatures[sig_index]; - unimplemented!("{}, {}", index, table_index); + let pushed_args = state.popn_save(wasmer_fn_sig.params().len())?; + + let args: Vec<_> = std::iter::once(ctx_ptr) + .chain(pushed_args.into_iter()) + .collect(); + println!("args: {:?}", args); + + let typed_func_ptr = builder.build_pointer_cast( + func_ptr, + fn_ty.ptr_type(AddressSpace::Generic), + "typed_func_ptr", + ); + + let call_site = builder.build_call(typed_func_ptr, &args, "indirect_call"); + + match wasmer_fn_sig.returns() { + [] => {} + [_] => { + let value = call_site.try_as_basic_value().left().unwrap(); + state.push1(value); + } + returns @ _ => unimplemented!("multi-value returns"), + } } /*************************** diff --git a/lib/llvm-backend/src/intrinsics.rs b/lib/llvm-backend/src/intrinsics.rs index ccc0081bf..f2ec8fd05 100644 --- a/lib/llvm-backend/src/intrinsics.rs +++ b/lib/llvm-backend/src/intrinsics.rs @@ -64,6 +64,7 @@ pub struct Intrinsics { pub copysign_f64: FunctionValue, pub expect_i1: FunctionValue, + pub trap: FunctionValue, pub void_ty: VoidType, pub i1_ty: IntType, @@ -255,6 +256,7 @@ impl Intrinsics { copysign_f64: module.add_function("llvm.copysign.f64", ret_f64_take_f64_f64, None), expect_i1: module.add_function("llvm.expect.i1", ret_i1_take_i1_i1, None), + trap: module.add_function("llvm.trap", void_ty.fn_type(&[], false), None), void_ty, i1_ty, @@ -695,7 +697,9 @@ impl<'a> CtxType<'a> { (imported_func_cache.func_ptr, imported_func_cache.ctx_ptr) } - // pub fn table(&mut self, table_index: TableIndex, elem_index: IntValue) -> + pub fn build_trap(&self) { + self.builder.build_call(self.intrinsics.trap, &[], "trap"); + } } // pub struct Ctx { diff --git a/lib/llvm-backend/src/lib.rs b/lib/llvm-backend/src/lib.rs index e70af96c0..e06b081af 100644 --- a/lib/llvm-backend/src/lib.rs +++ b/lib/llvm-backend/src/lib.rs @@ -10,11 +10,11 @@ use wasmer_runtime_core::{ module::ModuleInner, }; +mod backend; mod code; mod intrinsics; mod read_info; mod state; -// mod backend; pub struct LLVMCompiler { _private: (), @@ -28,13 +28,61 @@ impl LLVMCompiler { impl Compiler for LLVMCompiler { fn compile(&self, wasm: &[u8], _: Token) -> Result { - let (_info, _code_reader) = read_info::read_module(wasm).unwrap(); + let (info, code_reader) = read_info::read_module(wasm).unwrap(); + let (module, intrinsics) = code::parse_function_bodies(&info, code_reader).unwrap(); - unimplemented!() + let backend = backend::LLVMBackend::new(module, intrinsics); + + // Create placeholder values here. + let (protected_caller, cache_gen) = { + use wasmer_runtime_core::backend::{ + sys::Memory, CacheGen, ProtectedCaller, UserTrapper, + }; + use wasmer_runtime_core::cache::Error as CacheError; + use wasmer_runtime_core::error::RuntimeResult; + use wasmer_runtime_core::module::ModuleInfo; + use wasmer_runtime_core::types::{FuncIndex, Value}; + use wasmer_runtime_core::vm; + struct Placeholder; + impl ProtectedCaller for Placeholder { + fn call( + &self, + _module: &ModuleInner, + _func_index: FuncIndex, + _params: &[Value], + _import_backing: &vm::ImportBacking, + _vmctx: *mut vm::Ctx, + _: Token, + ) -> RuntimeResult> { + Ok(vec![]) + } + fn get_early_trapper(&self) -> Box { + unimplemented!() + } + } + impl CacheGen for Placeholder { + fn generate_cache( + &self, + module: &ModuleInner, + ) -> Result<(Box, Box<[u8]>, Memory), CacheError> { + unimplemented!() + } + } + + (Box::new(Placeholder), Box::new(Placeholder)) + }; + + Ok(ModuleInner { + func_resolver: Box::new(backend), + protected_caller, + cache_gen, + + info, + }) } unsafe fn from_cache(&self, _artifact: Artifact, _: Token) -> Result { - unimplemented!() + unimplemented!("the llvm backend doesn't support caching yet") } } @@ -55,14 +103,9 @@ fn test_read_module() { get_local 0 i32.const 0 call_indirect (type $t0) - memory.grow ) (func $foobar (type $t0) get_local 0 - ) - (func $bar (type $t0) (param i32) (result i32) - get_local 0 - call $foo )) "#; let wasm = wat2wasm(wat).unwrap(); @@ -71,86 +114,50 @@ fn test_read_module() { let (module, intrinsics) = code::parse_function_bodies(&info, code_reader).unwrap(); - { - Target::initialize_x86(&InitializationConfig { - asm_parser: true, - asm_printer: true, - base: true, - disassembler: true, - info: true, - machine_code: true, - }); - let triple = TargetMachine::get_default_triple().to_string(); - let target = Target::from_triple(&triple).unwrap(); - let target_machine = target - .create_target_machine( - &triple, - &TargetMachine::get_host_cpu_name().to_string(), - &TargetMachine::get_host_cpu_features().to_string(), - OptimizationLevel::Default, - RelocMode::PIC, - CodeModel::Default, - ) - .unwrap(); + // let backend = backend::LLVMBackend::new(module, intrinsics); - let memory_buffer = target_machine - .write_to_memory_buffer(&module, FileType::Object) - .unwrap(); - // std::fs::write("memory_buffer", memory_buffer.as_slice()).unwrap(); - let mem_buf_slice = memory_buffer.as_slice(); - - let macho = goblin::mach::MachO::parse(mem_buf_slice, 0).unwrap(); - let symbols = macho.symbols.as_ref().unwrap(); - let relocations = macho.relocations().unwrap(); - for (_, reloc_iter, section) in relocations.into_iter() { - println!("section: {:#?}", section); - for reloc_info in reloc_iter { - let reloc_info = reloc_info.unwrap(); - println!("\treloc_info: {:#?}", reloc_info); - println!( - "\tsymbol: {:#?}", - symbols.get(reloc_info.r_symbolnum()).unwrap() - ); - } - } + extern "C" { + fn test_cpp(); } - let exec_engine = module - .create_jit_execution_engine(OptimizationLevel::Default) - .unwrap(); + unsafe { test_cpp() }; - exec_engine.add_global_mapping( - &intrinsics.memory_grow_dynamic_local, - vmcalls::local_dynamic_memory_grow as usize, - ); - exec_engine.add_global_mapping( - &intrinsics.memory_grow_static_local, - vmcalls::local_static_memory_grow as usize, - ); - exec_engine.add_global_mapping( - &intrinsics.memory_grow_dynamic_import, - vmcalls::imported_dynamic_memory_grow as usize, - ); - exec_engine.add_global_mapping( - &intrinsics.memory_grow_static_import, - vmcalls::imported_static_memory_grow as usize, - ); - exec_engine.add_global_mapping( - &intrinsics.memory_size_dynamic_local, - vmcalls::local_dynamic_memory_size as usize, - ); - exec_engine.add_global_mapping( - &intrinsics.memory_size_static_local, - vmcalls::local_static_memory_size as usize, - ); - exec_engine.add_global_mapping( - &intrinsics.memory_size_dynamic_import, - vmcalls::imported_dynamic_memory_size as usize, - ); - exec_engine.add_global_mapping( - &intrinsics.memory_size_static_import, - vmcalls::imported_static_memory_size as usize, - ); + // let exec_engine = module + // .create_jit_execution_engine(OptimizationLevel::Default) + // .unwrap(); + + // exec_engine.add_global_mapping( + // &intrinsics.memory_grow_dynamic_local, + // vmcalls::local_dynamic_memory_grow as usize, + // ); + // exec_engine.add_global_mapping( + // &intrinsics.memory_grow_static_local, + // vmcalls::local_static_memory_grow as usize, + // ); + // exec_engine.add_global_mapping( + // &intrinsics.memory_grow_dynamic_import, + // vmcalls::imported_dynamic_memory_grow as usize, + // ); + // exec_engine.add_global_mapping( + // &intrinsics.memory_grow_static_import, + // vmcalls::imported_static_memory_grow as usize, + // ); + // exec_engine.add_global_mapping( + // &intrinsics.memory_size_dynamic_local, + // vmcalls::local_dynamic_memory_size as usize, + // ); + // exec_engine.add_global_mapping( + // &intrinsics.memory_size_static_local, + // vmcalls::local_static_memory_size as usize, + // ); + // exec_engine.add_global_mapping( + // &intrinsics.memory_size_dynamic_import, + // vmcalls::imported_dynamic_memory_size as usize, + // ); + // exec_engine.add_global_mapping( + // &intrinsics.memory_size_static_import, + // vmcalls::imported_static_memory_size as usize, + // ); // unsafe { // let func: JitFunction i32> = exec_engine.get_function("fn0").unwrap(); From 4f833876e0911fac307371537209708df1da5d9c Mon Sep 17 00:00:00 2001 From: Lachlan Sneff Date: Mon, 25 Feb 2019 18:07:22 -0800 Subject: [PATCH 11/75] Start work on object loader using llvm's RuntimeDyld api. --- Cargo.lock | 30 ++++ lib/llvm-backend/Cargo.toml | 8 + lib/llvm-backend/build.rs | 213 +++++++++++++++++++++++++ lib/llvm-backend/cpp/object_loader.cpp | 96 +++++++++++ lib/llvm-backend/cpp/object_loader.hh | 40 +++++ lib/llvm-backend/src/backend.rs | 79 ++++++--- lib/llvm-backend/src/code.rs | 52 ++++-- lib/llvm-backend/src/intrinsics.rs | 6 +- lib/llvm-backend/src/lib.rs | 177 ++++++++++---------- 9 files changed, 579 insertions(+), 122 deletions(-) create mode 100644 lib/llvm-backend/build.rs create mode 100644 lib/llvm-backend/cpp/object_loader.cpp create mode 100644 lib/llvm-backend/cpp/object_loader.hh diff --git a/Cargo.lock b/Cargo.lock index ca2129890..9d743e96c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -262,6 +262,28 @@ dependencies = [ "generic-array 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "dlopen" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "dlopen_derive 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "dlopen_derive" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "either" version = "1.5.1" @@ -469,10 +491,16 @@ dependencies = [ name = "llvm-backend" version = "0.1.0" dependencies = [ + "cc 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)", + "dlopen 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "goblin 0.0.20 (registry+https://github.com/rust-lang/crates.io-index)", "hashbrown 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "inkwell 0.1.0 (git+https://github.com/TheDan64/inkwell?branch=llvm7-0)", + "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", + "tempfile 3.0.7 (registry+https://github.com/rust-lang/crates.io-index)", "wabt 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)", "wasmer-runtime-core 0.1.2", "wasmparser 0.28.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1362,6 +1390,8 @@ dependencies = [ "checksum cranelift-native 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)" = "474bee81d620a473bf43411a3d6f10ffbf7965141dc5e5b76d8d2151dde3285d" "checksum cranelift-wasm 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)" = "49723365dab9a48b354bdc24cb6d9d5719bc1d3b858ffd2ea179d0d7d885804a" "checksum digest 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "05f47366984d3ad862010e22c7ce81a7dbcaebbdfb37241a620f8b6596ee135c" +"checksum dlopen 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "f8c301a18a3404a48d5d078e86b011ac834a6c4c742217e9aa8ceadd8a7e09e0" +"checksum dlopen_derive 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6e16e4e343d6090ba47113c55bf6aa94e9b1eb5ab0c5abc9510d4c15074f30e9" "checksum either 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c67353c641dc847124ea1902d69bd753dee9bb3beff9aa3662ecf86c971d1fac" "checksum enum-methods 0.0.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7798e7da2d4cb0d6d6fc467e8d6b5bf247e9e989f786dde1732d79899c32bb10" "checksum env_logger 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "afb070faf94c85d17d50ca44f6ad076bce18ae92f0037d350947240a36e9d42e" diff --git a/lib/llvm-backend/Cargo.toml b/lib/llvm-backend/Cargo.toml index 8ffac375f..3ec83d77c 100644 --- a/lib/llvm-backend/Cargo.toml +++ b/lib/llvm-backend/Cargo.toml @@ -11,6 +11,14 @@ inkwell = { git = "https://github.com/TheDan64/inkwell", branch = "llvm7-0" } hashbrown = "0.1.8" smallvec = "0.6.8" goblin = "0.0.20" +dlopen = "0.1.6" +tempfile = "3.0.7" + +[build-dependencies] +cc = "1.0" +lazy_static = "1.2.0" +regex = "1.1.0" +semver = "0.9" [dev-dependencies] wabt = "0.7.4" diff --git a/lib/llvm-backend/build.rs b/lib/llvm-backend/build.rs new file mode 100644 index 000000000..0f4d1f195 --- /dev/null +++ b/lib/llvm-backend/build.rs @@ -0,0 +1,213 @@ +//! This file was mostly taken from the llvm-sys crate. +//! (https://bitbucket.org/tari/llvm-sys.rs/src/21ab524ec4df1450035df895209c3f8fbeb8775f/build.rs?at=default&fileviewer=file-view-default) + +use lazy_static::lazy_static; +use regex::Regex; +use semver::Version; +use std::env; +use std::ffi::OsStr; +use std::io::{self, ErrorKind}; +use std::path::PathBuf; +use std::process::Command; + +lazy_static! { + /// LLVM version used by this version of the crate. + static ref CRATE_VERSION: Version = { + let crate_version = Version::parse(env!("CARGO_PKG_VERSION")) + .expect("Crate version is somehow not valid semver"); + Version { + major: crate_version.major / 10, + minor: crate_version.major % 10, + .. crate_version + } + }; + + static ref LLVM_CONFIG_BINARY_NAMES: Vec = { + vec![ + "llvm-config".into(), + // format!("llvm-config-{}", CRATE_VERSION.major), + // format!("llvm-config-{}.{}", CRATE_VERSION.major, CRATE_VERSION.minor), + ] + }; + + /// Filesystem path to an llvm-config binary for the correct version. + static ref LLVM_CONFIG_PATH: PathBuf = { + // Try llvm-config via PATH first. + if let Some(name) = locate_system_llvm_config() { + return name.into(); + } else { + println!("Didn't find usable system-wide LLVM."); + } + + // Did the user give us a binary path to use? If yes, try + // to use that and fail if it doesn't work. + let binary_prefix_var = "LLVM_SYS_70_PREFIX"; + + let path = if let Some(path) = env::var_os(&binary_prefix_var) { + Some(path.to_str().unwrap().to_owned()) + } else if let Ok(mut file) = std::fs::File::open(".llvmenv") { + use std::io::Read; + let mut s = String::new(); + file.read_to_string(&mut s).unwrap(); + Some(s) + } else { + None + }; + + if let Some(path) = path { + for binary_name in LLVM_CONFIG_BINARY_NAMES.iter() { + let mut pb: PathBuf = path.clone().into(); + pb.push("bin"); + pb.push(binary_name); + + let ver = llvm_version(&pb) + .expect(&format!("Failed to execute {:?}", &pb)); + if is_compatible_llvm(&ver) { + return pb; + } else { + println!("LLVM binaries specified by {} are the wrong version. + (Found {}, need {}.)", binary_prefix_var, ver, *CRATE_VERSION); + } + } + } + + println!("No suitable version of LLVM was found system-wide or pointed + to by {}. + + Consider using `llvmenv` to compile an appropriate copy of LLVM, and + refer to the llvm-sys documentation for more information. + + llvm-sys: https://crates.io/crates/llvm-sys + llvmenv: https://crates.io/crates/llvmenv", binary_prefix_var); + panic!("Could not find a compatible version of LLVM"); + }; +} + +/// Try to find a system-wide version of llvm-config that is compatible with +/// this crate. +/// +/// Returns None on failure. +fn locate_system_llvm_config() -> Option<&'static str> { + for binary_name in LLVM_CONFIG_BINARY_NAMES.iter() { + match llvm_version(binary_name) { + Ok(ref version) if is_compatible_llvm(version) => { + // Compatible version found. Nice. + return Some(binary_name); + } + Ok(version) => { + // Version mismatch. Will try further searches, but warn that + // we're not using the system one. + println!( + "Found LLVM version {} on PATH, but need {}.", + version, *CRATE_VERSION + ); + } + Err(ref e) if e.kind() == ErrorKind::NotFound => { + // Looks like we failed to execute any llvm-config. Keep + // searching. + } + // Some other error, probably a weird failure. Give up. + Err(e) => panic!("Failed to search PATH for llvm-config: {}", e), + } + } + + None +} + +/// Check whether the given LLVM version is compatible with this version of +/// the crate. +fn is_compatible_llvm(llvm_version: &Version) -> bool { + let strict = env::var_os(format!( + "LLVM_SYS_{}_STRICT_VERSIONING", + env!("CARGO_PKG_VERSION_MAJOR") + )) + .is_some() + || cfg!(feature = "strict-versioning"); + if strict { + llvm_version.major == CRATE_VERSION.major && llvm_version.minor == CRATE_VERSION.minor + } else { + llvm_version.major >= CRATE_VERSION.major + || (llvm_version.major == CRATE_VERSION.major + && llvm_version.minor >= CRATE_VERSION.minor) + } +} + +/// Get the output from running `llvm-config` with the given argument. +/// +/// Lazily searches for or compiles LLVM as configured by the environment +/// variables. +fn llvm_config(arg: &str) -> String { + llvm_config_ex(&*LLVM_CONFIG_PATH, arg).expect("Surprising failure from llvm-config") +} + +/// Invoke the specified binary as llvm-config. +/// +/// Explicit version of the `llvm_config` function that bubbles errors +/// up. +fn llvm_config_ex>(binary: S, arg: &str) -> io::Result { + Command::new(binary) + .arg(arg) + .arg("--link-static") // Don't use dylib for >= 3.9 + .output() + .map(|output| { + String::from_utf8(output.stdout).expect("Output from llvm-config was not valid UTF-8") + }) +} + +/// Get the LLVM version using llvm-config. +fn llvm_version>(binary: S) -> io::Result { + let version_str = llvm_config_ex(binary.as_ref(), "--version")?; + + // LLVM isn't really semver and uses version suffixes to build + // version strings like '3.8.0svn', so limit what we try to parse + // to only the numeric bits. + let re = Regex::new(r"^(?P\d+)\.(?P\d+)(?:\.(?P\d+))??").unwrap(); + let c = re + .captures(&version_str) + .expect("Could not determine LLVM version from llvm-config."); + + // some systems don't have a patch number but Version wants it so we just append .0 if it isn't + // there + let s = match c.name("patch") { + None => format!("{}.0", &c[0]), + Some(_) => c[0].to_string(), + }; + Ok(Version::parse(&s).unwrap()) +} + +fn get_llvm_cxxflags() -> String { + let output = llvm_config("--cxxflags"); + + // llvm-config includes cflags from its own compilation with --cflags that + // may not be relevant to us. In particularly annoying cases, these might + // include flags that aren't understood by the default compiler we're + // using. Unless requested otherwise, clean CFLAGS of options that are + // known to be possibly-harmful. + let no_clean = env::var_os(format!( + "LLVM_SYS_{}_NO_CLEAN_CFLAGS", + env!("CARGO_PKG_VERSION_MAJOR") + )) + .is_some(); + if no_clean || cfg!(target_env = "msvc") { + // MSVC doesn't accept -W... options, so don't try to strip them and + // possibly strip something that should be retained. Also do nothing if + // the user requests it. + return output; + } + + output + .split(&[' ', '\n'][..]) + .filter(|word| !word.starts_with("-W")) + .collect::>() + .join(" ") +} + +fn main() { + std::env::set_var("CXXFLAGS", get_llvm_cxxflags()); + cc::Build::new() + .cpp(true) + .file("cpp/object_loader.cpp") + .compile("llvm-backend"); + + println!("cargo:rustc-link-lib=static=llvm-backend"); +} diff --git a/lib/llvm-backend/cpp/object_loader.cpp b/lib/llvm-backend/cpp/object_loader.cpp new file mode 100644 index 000000000..9ab36f4c3 --- /dev/null +++ b/lib/llvm-backend/cpp/object_loader.cpp @@ -0,0 +1,96 @@ +#include "object_loader.hh" +#include +#include + +class MemoryManager : llvm::RuntimeDyld::MemoryManager { +public: + MemoryManager() {} + + virtual ~MemoryManager() {} + + virtual uint8_t* allocateCodeSection(uintptr_t Size, unsigned Alignment, unsigned SectionID, llvm::StringRef SectionName) override { + return nullptr; + } + + virtual uint8_t* allocateDataSection(uintptr_t Size, unsigned Alignment, unsigned SectionID, llvm::StringRef SectionName, bool isReadOnly) override { + return nullptr; + } + + virtual void reserveAllocationSpace( + uintptr_t code_size, + uint32_t code_align, + uintptr_t read_data_size, + uint32_t read_data_align, + uintptr_t read_write_data_size, + uint32_t read_write_data_align + ) override { + + } + + /* Turn on the `reserveAllocationSpace` callback. */ + virtual bool needsToReserveAllocationSpace() override { + return true; + } + + virtual void registerEHFrames(uint8_t* Addr, uint64_t LoadAddr, size_t Size) override { + + } + + virtual void deregisterEHFrames() override { + + } + + virtual bool finalizeMemory(std::string *ErrMsg = nullptr) override { + + + return false; + } + + virtual void notifyObjectLoaded(llvm::RuntimeDyld &RTDyld, const llvm::object::ObjectFile &Obj) override { + + } +private: + struct Section { + uint8_t* base; + size_t num_pages; + size_t num_commited_bytes; + }; + + uint8_t *image_base; + size_t num_allocated_pages; + + Section code_section, read_section, readwrite_section; + + +}; + +class SymbolLookup : llvm::JITSymbolResolver { +public: + virtual llvm::Expected lookup(const LookupSet& symbols) override { + LookupResult result; + + for (auto symbol : symbols) { + result.emplace(symbol, symbol_lookup(symbol)); + } + + return result; + } + + virtual llvm::Expected lookupFlags(const LookupSet& symbols) override { + LookupFlagsResult result; + + for (auto symbol : symbols) { + result.emplace(symbol, symbol_lookup(symbol).getFlags()); + } + + return result; + } + +private: + llvm::JITEvaluatedSymbol symbol_lookup(llvm::StringRef name) { + std::cout << "symbol name: " << (std::string)name << std::endl; + uint64_t addr = 0; + + return llvm::JITEvaluatedSymbol(addr, llvm::JITSymbolFlags::None); + } +}; \ No newline at end of file diff --git a/lib/llvm-backend/cpp/object_loader.hh b/lib/llvm-backend/cpp/object_loader.hh new file mode 100644 index 000000000..50b618b38 --- /dev/null +++ b/lib/llvm-backend/cpp/object_loader.hh @@ -0,0 +1,40 @@ +#include +#include + +typedef enum { + PROTECT_NONE, + PROTECT_READ, + PROTECT_READ_WRITE, + PROTECT_READ_EXECUTE, +} mem_protect_t; + +typedef enum { + RESULT_OK, + RESULT_ALLOCATE_FAILURE, + RESULT_PROTECT_FAILURE, + RESULT_DEALLOC_FAILURE, + RESULT_OBJECT_LOAD_FAILURE, +} result_t; + +typedef result_t (*alloc_memory_t)(size_t size, mem_protect_t protect, uint8_t** ptr_out, size_t* size_out); +typedef result_t (*protect_memory_t)(uint8_t* ptr, size_t size, mem_protect_t protect); +typedef result_t (*dealloc_memory_t)(uint8_t* ptr, size_t size); +typedef uintptr_t (*lookup_vm_symbol_t)(char* name_ptr, size_t name_size); + +typedef struct { + /* Memory management. */ + alloc_memory_t alloc_memory; + protect_memory_t protect_memory; + dealloc_memory_t dealloc_memory; + + lookup_vm_symbol_t lookup_vm_symbol; +} callbacks_t; + +extern "C" { + result_t object_load(uint8_t* mem_ptr, size_t mem_size, callbacks_t* callbacks) { + return RESULT_OK; + } + + void test_cpp() { + } +} \ No newline at end of file diff --git a/lib/llvm-backend/src/backend.rs b/lib/llvm-backend/src/backend.rs index 9821eabf6..2b4bb7023 100644 --- a/lib/llvm-backend/src/backend.rs +++ b/lib/llvm-backend/src/backend.rs @@ -1,45 +1,76 @@ +use crate::intrinsics::Intrinsics; +use dlopen::symbor::Library; use inkwell::{ module::Module, - execution_engine::{ExecutionEngine, JitFunction}, + targets::{CodeModel, FileType, InitializationConfig, RelocMode, Target, TargetMachine}, + OptimizationLevel, }; -use crate::intrinsics::Intrinsics; -use std::ptr::NonNull; +use std::{io::Write, ptr::NonNull}; +use tempfile::NamedTempFile; use wasmer_runtime_core::{ - module::ModuleInner, - types::LocalFuncIndex, - structures::TypedIndex, - backend::{FuncResolver, vm}, + backend::FuncResolver, module::ModuleInner, structures::TypedIndex, types::LocalFuncIndex, vm, }; pub struct LLVMBackend { - exec_engine: ExecutionEngine, + tempfile: NamedTempFile, + library: Library, } impl LLVMBackend { pub fn new(module: Module, intrinsics: Intrinsics) -> Self { - let exec_engine = module.create_jit_execution_engine(OptimizationLevel::Default).unwrap(); + Target::initialize_x86(&InitializationConfig { + asm_parser: true, + asm_printer: true, + base: true, + disassembler: true, + info: true, + machine_code: true, + }); + let triple = TargetMachine::get_default_triple().to_string(); + let target = Target::from_triple(&triple).unwrap(); + let target_machine = target + .create_target_machine( + &triple, + &TargetMachine::get_host_cpu_name().to_string(), + &TargetMachine::get_host_cpu_features().to_string(), + OptimizationLevel::Default, + RelocMode::PIC, + CodeModel::Default, + ) + .unwrap(); - exec_engine.add_global_mapping(&intrinsics.memory_grow_dynamic_local, vmcalls::local_dynamic_memory_grow as usize); - exec_engine.add_global_mapping(&intrinsics.memory_grow_static_local, vmcalls::local_static_memory_grow as usize); - exec_engine.add_global_mapping(&intrinsics.memory_grow_dynamic_import, vmcalls::imported_dynamic_memory_grow as usize); - exec_engine.add_global_mapping(&intrinsics.memory_grow_static_import, vmcalls::imported_static_memory_grow as usize); - exec_engine.add_global_mapping(&intrinsics.memory_size_dynamic_local, vmcalls::local_dynamic_memory_size as usize); - exec_engine.add_global_mapping(&intrinsics.memory_size_static_local, vmcalls::local_static_memory_size as usize); - exec_engine.add_global_mapping(&intrinsics.memory_size_dynamic_import, vmcalls::imported_dynamic_memory_size as usize); - exec_engine.add_global_mapping(&intrinsics.memory_size_static_import, vmcalls::imported_static_memory_size as usize); + let memory_buffer = target_machine + .write_to_memory_buffer(&module, FileType::Object) + .unwrap(); - Self { exec_engine } + let mut tempfile = NamedTempFile::new().unwrap(); + tempfile.write_all(memory_buffer.as_slice()).unwrap(); + tempfile.flush().unwrap(); + + let library = Library::open(tempfile.path()).unwrap(); + + Self { tempfile, library } } } impl FuncResolver for LLVMBackend { - fn get(&self, module: &ModuleInner, local_func_index: LocalFuncIndex) -> Option> { + fn get( + &self, + module: &ModuleInner, + local_func_index: LocalFuncIndex, + ) -> Option> { let index = module.info.imported_functions.len() + local_func_index.index(); - let name = format!("fn{}", index); - + let name = if cfg!(macos) { + format!("_fn{}", index) + } else { + format!("fn{}", index) + }; + unsafe { - let func: JitFunction = self.exec_engine.get_function(&name).ok()?; - + self.library + .symbol::>(&name) + .ok() + .map(|symbol| *symbol) } } -} \ No newline at end of file +} diff --git a/lib/llvm-backend/src/code.rs b/lib/llvm-backend/src/code.rs index d72659fd9..e0f4d984f 100644 --- a/lib/llvm-backend/src/code.rs +++ b/lib/llvm-backend/src/code.rs @@ -481,6 +481,7 @@ fn parse_function( // Emit an unreachable instruction. // If llvm cannot prove that this is never touched, // it will emit a `ud2` instruction on x86_64 arches. + ctx.build_trap(); builder.build_unreachable(); state.reachable = false; } @@ -623,7 +624,8 @@ fn parse_function( } } Operator::CallIndirect { index, table_index } => { - let expected_dynamic_sigindex = ctx.dynamic_sigindex(SigIndex::new(index as usize)); + let sig_index = SigIndex::new(index as usize); + let expected_dynamic_sigindex = ctx.dynamic_sigindex(sig_index); let (table_base, table_bound) = ctx.table(TableIndex::new(table_index as usize)); let func_index = state.pop1()?.into_int_value(); @@ -651,12 +653,10 @@ fn parse_function( "func_ptr", ) .into_pointer_value(), - builder - .build_load( - builder.build_struct_gep(anyfunc_struct_ptr, 1, "ctx_ptr_ptr"), - "ctx_ptr", - ) - .into_pointer_value(), + builder.build_load( + builder.build_struct_gep(anyfunc_struct_ptr, 1, "ctx_ptr_ptr"), + "ctx_ptr", + ), builder .build_load( builder.build_struct_gep(anyfunc_struct_ptr, 2, "sigindex_ptr"), @@ -685,21 +685,49 @@ fn parse_function( ) .try_as_basic_value() .left() - .unwrap(); + .unwrap() + .into_int_value(); let continue_block = context.append_basic_block(&function, "continue_block"); let sigindices_notequal_block = context.append_basic_block(&function, "sigindices_notequal_block"); + builder.build_conditional_branch( + sigindices_equal, + &continue_block, + &sigindices_notequal_block, + ); builder.position_at_end(&sigindices_notequal_block); + ctx.build_trap(); builder.build_unreachable(); builder.position_at_end(&continue_block); - println!("func ptr: {:#?}", func_ptr); - println!("ctx ptr: {:#?}", ctx_ptr); - println!("found dynamic sigindex: {:#?}", found_dynamic_sigindex); + let wasmer_fn_sig = &info.signatures[sig_index]; + let fn_ty = signatures[sig_index]; - unimplemented!("{}, {}", index, table_index); + let pushed_args = state.popn_save(wasmer_fn_sig.params().len())?; + + let args: Vec<_> = std::iter::once(ctx_ptr) + .chain(pushed_args.into_iter()) + .collect(); + println!("args: {:?}", args); + + let typed_func_ptr = builder.build_pointer_cast( + func_ptr, + fn_ty.ptr_type(AddressSpace::Generic), + "typed_func_ptr", + ); + + let call_site = builder.build_call(typed_func_ptr, &args, "indirect_call"); + + match wasmer_fn_sig.returns() { + [] => {} + [_] => { + let value = call_site.try_as_basic_value().left().unwrap(); + state.push1(value); + } + returns @ _ => unimplemented!("multi-value returns"), + } } /*************************** diff --git a/lib/llvm-backend/src/intrinsics.rs b/lib/llvm-backend/src/intrinsics.rs index ccc0081bf..f2ec8fd05 100644 --- a/lib/llvm-backend/src/intrinsics.rs +++ b/lib/llvm-backend/src/intrinsics.rs @@ -64,6 +64,7 @@ pub struct Intrinsics { pub copysign_f64: FunctionValue, pub expect_i1: FunctionValue, + pub trap: FunctionValue, pub void_ty: VoidType, pub i1_ty: IntType, @@ -255,6 +256,7 @@ impl Intrinsics { copysign_f64: module.add_function("llvm.copysign.f64", ret_f64_take_f64_f64, None), expect_i1: module.add_function("llvm.expect.i1", ret_i1_take_i1_i1, None), + trap: module.add_function("llvm.trap", void_ty.fn_type(&[], false), None), void_ty, i1_ty, @@ -695,7 +697,9 @@ impl<'a> CtxType<'a> { (imported_func_cache.func_ptr, imported_func_cache.ctx_ptr) } - // pub fn table(&mut self, table_index: TableIndex, elem_index: IntValue) -> + pub fn build_trap(&self) { + self.builder.build_call(self.intrinsics.trap, &[], "trap"); + } } // pub struct Ctx { diff --git a/lib/llvm-backend/src/lib.rs b/lib/llvm-backend/src/lib.rs index e70af96c0..e06b081af 100644 --- a/lib/llvm-backend/src/lib.rs +++ b/lib/llvm-backend/src/lib.rs @@ -10,11 +10,11 @@ use wasmer_runtime_core::{ module::ModuleInner, }; +mod backend; mod code; mod intrinsics; mod read_info; mod state; -// mod backend; pub struct LLVMCompiler { _private: (), @@ -28,13 +28,61 @@ impl LLVMCompiler { impl Compiler for LLVMCompiler { fn compile(&self, wasm: &[u8], _: Token) -> Result { - let (_info, _code_reader) = read_info::read_module(wasm).unwrap(); + let (info, code_reader) = read_info::read_module(wasm).unwrap(); + let (module, intrinsics) = code::parse_function_bodies(&info, code_reader).unwrap(); - unimplemented!() + let backend = backend::LLVMBackend::new(module, intrinsics); + + // Create placeholder values here. + let (protected_caller, cache_gen) = { + use wasmer_runtime_core::backend::{ + sys::Memory, CacheGen, ProtectedCaller, UserTrapper, + }; + use wasmer_runtime_core::cache::Error as CacheError; + use wasmer_runtime_core::error::RuntimeResult; + use wasmer_runtime_core::module::ModuleInfo; + use wasmer_runtime_core::types::{FuncIndex, Value}; + use wasmer_runtime_core::vm; + struct Placeholder; + impl ProtectedCaller for Placeholder { + fn call( + &self, + _module: &ModuleInner, + _func_index: FuncIndex, + _params: &[Value], + _import_backing: &vm::ImportBacking, + _vmctx: *mut vm::Ctx, + _: Token, + ) -> RuntimeResult> { + Ok(vec![]) + } + fn get_early_trapper(&self) -> Box { + unimplemented!() + } + } + impl CacheGen for Placeholder { + fn generate_cache( + &self, + module: &ModuleInner, + ) -> Result<(Box, Box<[u8]>, Memory), CacheError> { + unimplemented!() + } + } + + (Box::new(Placeholder), Box::new(Placeholder)) + }; + + Ok(ModuleInner { + func_resolver: Box::new(backend), + protected_caller, + cache_gen, + + info, + }) } unsafe fn from_cache(&self, _artifact: Artifact, _: Token) -> Result { - unimplemented!() + unimplemented!("the llvm backend doesn't support caching yet") } } @@ -55,14 +103,9 @@ fn test_read_module() { get_local 0 i32.const 0 call_indirect (type $t0) - memory.grow ) (func $foobar (type $t0) get_local 0 - ) - (func $bar (type $t0) (param i32) (result i32) - get_local 0 - call $foo )) "#; let wasm = wat2wasm(wat).unwrap(); @@ -71,86 +114,50 @@ fn test_read_module() { let (module, intrinsics) = code::parse_function_bodies(&info, code_reader).unwrap(); - { - Target::initialize_x86(&InitializationConfig { - asm_parser: true, - asm_printer: true, - base: true, - disassembler: true, - info: true, - machine_code: true, - }); - let triple = TargetMachine::get_default_triple().to_string(); - let target = Target::from_triple(&triple).unwrap(); - let target_machine = target - .create_target_machine( - &triple, - &TargetMachine::get_host_cpu_name().to_string(), - &TargetMachine::get_host_cpu_features().to_string(), - OptimizationLevel::Default, - RelocMode::PIC, - CodeModel::Default, - ) - .unwrap(); + // let backend = backend::LLVMBackend::new(module, intrinsics); - let memory_buffer = target_machine - .write_to_memory_buffer(&module, FileType::Object) - .unwrap(); - // std::fs::write("memory_buffer", memory_buffer.as_slice()).unwrap(); - let mem_buf_slice = memory_buffer.as_slice(); - - let macho = goblin::mach::MachO::parse(mem_buf_slice, 0).unwrap(); - let symbols = macho.symbols.as_ref().unwrap(); - let relocations = macho.relocations().unwrap(); - for (_, reloc_iter, section) in relocations.into_iter() { - println!("section: {:#?}", section); - for reloc_info in reloc_iter { - let reloc_info = reloc_info.unwrap(); - println!("\treloc_info: {:#?}", reloc_info); - println!( - "\tsymbol: {:#?}", - symbols.get(reloc_info.r_symbolnum()).unwrap() - ); - } - } + extern "C" { + fn test_cpp(); } - let exec_engine = module - .create_jit_execution_engine(OptimizationLevel::Default) - .unwrap(); + unsafe { test_cpp() }; - exec_engine.add_global_mapping( - &intrinsics.memory_grow_dynamic_local, - vmcalls::local_dynamic_memory_grow as usize, - ); - exec_engine.add_global_mapping( - &intrinsics.memory_grow_static_local, - vmcalls::local_static_memory_grow as usize, - ); - exec_engine.add_global_mapping( - &intrinsics.memory_grow_dynamic_import, - vmcalls::imported_dynamic_memory_grow as usize, - ); - exec_engine.add_global_mapping( - &intrinsics.memory_grow_static_import, - vmcalls::imported_static_memory_grow as usize, - ); - exec_engine.add_global_mapping( - &intrinsics.memory_size_dynamic_local, - vmcalls::local_dynamic_memory_size as usize, - ); - exec_engine.add_global_mapping( - &intrinsics.memory_size_static_local, - vmcalls::local_static_memory_size as usize, - ); - exec_engine.add_global_mapping( - &intrinsics.memory_size_dynamic_import, - vmcalls::imported_dynamic_memory_size as usize, - ); - exec_engine.add_global_mapping( - &intrinsics.memory_size_static_import, - vmcalls::imported_static_memory_size as usize, - ); + // let exec_engine = module + // .create_jit_execution_engine(OptimizationLevel::Default) + // .unwrap(); + + // exec_engine.add_global_mapping( + // &intrinsics.memory_grow_dynamic_local, + // vmcalls::local_dynamic_memory_grow as usize, + // ); + // exec_engine.add_global_mapping( + // &intrinsics.memory_grow_static_local, + // vmcalls::local_static_memory_grow as usize, + // ); + // exec_engine.add_global_mapping( + // &intrinsics.memory_grow_dynamic_import, + // vmcalls::imported_dynamic_memory_grow as usize, + // ); + // exec_engine.add_global_mapping( + // &intrinsics.memory_grow_static_import, + // vmcalls::imported_static_memory_grow as usize, + // ); + // exec_engine.add_global_mapping( + // &intrinsics.memory_size_dynamic_local, + // vmcalls::local_dynamic_memory_size as usize, + // ); + // exec_engine.add_global_mapping( + // &intrinsics.memory_size_static_local, + // vmcalls::local_static_memory_size as usize, + // ); + // exec_engine.add_global_mapping( + // &intrinsics.memory_size_dynamic_import, + // vmcalls::imported_dynamic_memory_size as usize, + // ); + // exec_engine.add_global_mapping( + // &intrinsics.memory_size_static_import, + // vmcalls::imported_static_memory_size as usize, + // ); // unsafe { // let func: JitFunction i32> = exec_engine.get_function("fn0").unwrap(); From 5d777693816b92c92ba24ab6f297eb267ccc521e Mon Sep 17 00:00:00 2001 From: Lachlan Sneff Date: Wed, 27 Feb 2019 17:21:20 -0800 Subject: [PATCH 12/75] Hopefully finish the memory manager implementation for llvm RuntimeDyLd --- Cargo.lock | 50 ++++----- lib/llvm-backend/build.rs | 1 + lib/llvm-backend/cpp/object_loader.cpp | 122 ++++++++++++++++++---- lib/llvm-backend/src/code.rs | 2 +- lib/llvm-backend/src/platform/mod.rs | 8 ++ lib/llvm-backend/src/platform/unix/mod.rs | 40 +++++++ 6 files changed, 176 insertions(+), 47 deletions(-) create mode 100644 lib/llvm-backend/src/platform/mod.rs create mode 100644 lib/llvm-backend/src/platform/unix/mod.rs diff --git a/Cargo.lock b/Cargo.lock index 9d743e96c..566a1514b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -63,7 +63,7 @@ dependencies = [ "clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "hashbrown 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "peeking_take_while 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", @@ -136,7 +136,7 @@ name = "cexpr" version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "nom 4.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "nom 4.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -269,7 +269,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "dlopen_derive 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -431,7 +431,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "inkwell" version = "0.1.0" -source = "git+https://github.com/TheDan64/inkwell?branch=llvm7-0#e66f8941061a45299ef73533c747c32bcd5d696a" +source = "git+https://github.com/TheDan64/inkwell?branch=llvm7-0#b8699b0ee594e4162ce850fbedb37892e9cdb7e4" dependencies = [ "either 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "enum-methods 0.0.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -443,7 +443,7 @@ dependencies = [ [[package]] name = "inkwell_internal_macros" version = "0.1.0" -source = "git+https://github.com/TheDan64/inkwell?branch=llvm7-0#e66f8941061a45299ef73533c747c32bcd5d696a" +source = "git+https://github.com/TheDan64/inkwell?branch=llvm7-0#b8699b0ee594e4162ce850fbedb37892e9cdb7e4" dependencies = [ "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", "syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)", @@ -465,13 +465,13 @@ dependencies = [ [[package]] name = "lazy_static" -version = "1.2.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "libc" version = "0.2.49" -source = "git+https://github.com/rust-lang/libc#68701e7e673da580de8ba6197c544316bd38e84a" +source = "git+https://github.com/rust-lang/libc#b905aef34008c962ef8a4410216eae65bbb7f68f" [[package]] name = "libc" @@ -496,7 +496,7 @@ dependencies = [ "goblin 0.0.20 (registry+https://github.com/rust-lang/crates.io-index)", "hashbrown 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "inkwell 0.1.0 (git+https://github.com/TheDan64/inkwell?branch=llvm7-0)", - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", @@ -512,7 +512,7 @@ version = "70.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cc 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -575,7 +575,7 @@ dependencies = [ [[package]] name = "nom" -version = "4.2.0" +version = "4.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -691,7 +691,7 @@ dependencies = [ "rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "rand_jitter 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "rand_os 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_pcg 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_pcg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -759,11 +759,11 @@ dependencies = [ [[package]] name = "rand_pcg" -version = "0.1.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -907,7 +907,7 @@ dependencies = [ [[package]] name = "serde_bytes" -version = "0.10.4" +version = "0.10.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "serde 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1082,7 +1082,7 @@ name = "thread_local" version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1201,7 +1201,7 @@ dependencies = [ "nix 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)", "serde-bench 0.0.7 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_bytes 0.10.4 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_bytes 0.10.5 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.58 (registry+https://github.com/rust-lang/crates.io-index)", "target-lexicon 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "wasmer-runtime-core 0.1.2", @@ -1216,7 +1216,7 @@ version = "0.1.0" dependencies = [ "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.49 (git+https://github.com/rust-lang/libc)", "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1229,7 +1229,7 @@ dependencies = [ name = "wasmer-runtime" version = "0.1.4" dependencies = [ - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "memmap 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "wasmer-clif-backend 0.1.2", "wasmer-runtime-core 0.1.2", @@ -1254,14 +1254,14 @@ dependencies = [ "hashbrown 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", "nix 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "page_size 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)", "serde-bench 0.0.7 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_bytes 0.10.4 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_bytes 0.10.5 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.58 (registry+https://github.com/rust-lang/crates.io-index)", "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "wasmer-clif-backend 0.1.2", @@ -1415,7 +1415,7 @@ dependencies = [ "checksum inkwell_internal_macros 0.1.0 (git+https://github.com/TheDan64/inkwell?branch=llvm7-0)" = "" "checksum itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1306f3464951f30e30d12373d31c79fbd52d236e5e896fd92f96ec7babbbe60b" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" -"checksum lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a374c89b9db55895453a74c1e38861d9deec0b01b405a82516e9d5de4820dea1" +"checksum lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bc5729f27f159ddd61f4df6228e827e86643d4d3e7c32183cb30a1c08f604a14" "checksum libc 0.2.49 (git+https://github.com/rust-lang/libc)" = "" "checksum libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)" = "413f3dfc802c5dc91dc570b05125b6cda9855edfaa9825c9849807876376e70e" "checksum libloading 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9c3ad660d7cb8c5822cd83d10897b0f1f1526792737a179e73896152f85b88c2" @@ -1426,7 +1426,7 @@ dependencies = [ "checksum memmap 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6585fd95e7bb50d6cc31e20d4cf9afb4e2ba16c5846fc76793f11218da9c475b" "checksum nix 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "921f61dc817b379d0834e45d5ec45beaacfae97082090a49c2cf30dcbc30206f" "checksum nix 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "46f0f3210768d796e8fa79ec70ee6af172dacbe7147f5e69be5240a47778302b" -"checksum nom 4.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b30adc557058ce00c9d0d7cb3c6e0b5bc6f36e2e2eabe74b0ba726d194abd588" +"checksum nom 4.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4836e9d6036552017e107edc598c97b2dee245161ff1b1ad4af215004774b354" "checksum opaque-debug 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "93f5bb2e8e8dec81642920ccff6b61f1eb94fa3020c5a325c9851ff604152409" "checksum owning_ref 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "49a4b8ea2179e6a2e27411d3bca09ca6dd630821cf6894c6c7c8467a8ee7ef13" "checksum page_size 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f89ef58b3d32420dbd1a43d2f38ae92f6239ef12bb556ab09ca55445f5a67242" @@ -1448,7 +1448,7 @@ dependencies = [ "checksum rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ded997c9d5f13925be2a6fd7e66bf1872597f759fd9dd93513dd7e92e5a5ee08" "checksum rand_jitter 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7b9ea758282efe12823e0d952ddb269d2e1897227e464919a554f2a03ef1b832" "checksum rand_os 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b7c690732391ae0abafced5015ffb53656abfaec61b342290e5eb56b286a679d" -"checksum rand_pcg 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "086bd09a33c7044e56bb44d5bdde5a60e7f119a9e95b0775f545de759a32fe05" +"checksum rand_pcg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "abf9b09b01790cfe0364f52bf32995ea3c39f4d2dd011eac241d2914146d0b44" "checksum rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c" "checksum raw-cpuid 6.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "30a9d219c32c9132f7be513c18be77c9881c7107d2ab5569d205a6a0f0e6dc7d" "checksum rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" @@ -1467,7 +1467,7 @@ dependencies = [ "checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" "checksum serde 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)" = "9f301d728f2b94c9a7691c90f07b0b4e8a4517181d9461be94c04bddeb4bd850" "checksum serde-bench 0.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "d733da87e79faaac25616e33d26299a41143fd4cd42746cbb0e91d8feea243fd" -"checksum serde_bytes 0.10.4 (registry+https://github.com/rust-lang/crates.io-index)" = "adb6e51a6b3696b301bc221d785f898b4457c619b51d7ce195a6d20baecb37b3" +"checksum serde_bytes 0.10.5 (registry+https://github.com/rust-lang/crates.io-index)" = "defbb8a83d7f34cc8380751eeb892b825944222888aff18996ea7901f24aec88" "checksum serde_derive 1.0.58 (registry+https://github.com/rust-lang/crates.io-index)" = "ac38f51a52a556cd17545798e29536885fb1a3fa63d6399f5ef650f4a7d35901" "checksum serde_json 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)" = "27dce848e7467aa0e2fcaf0a413641499c0b745452aaca1194d24dedde9e13c9" "checksum sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b4d8bfd0e469f417657573d8451fb33d16cfe0989359b93baf3a1ffc639543d" diff --git a/lib/llvm-backend/build.rs b/lib/llvm-backend/build.rs index 0f4d1f195..33ce4525d 100644 --- a/lib/llvm-backend/build.rs +++ b/lib/llvm-backend/build.rs @@ -49,6 +49,7 @@ lazy_static! { use std::io::Read; let mut s = String::new(); file.read_to_string(&mut s).unwrap(); + s.truncate(s.len() - 4); Some(s) } else { None diff --git a/lib/llvm-backend/cpp/object_loader.cpp b/lib/llvm-backend/cpp/object_loader.cpp index 9ab36f4c3..52625b64b 100644 --- a/lib/llvm-backend/cpp/object_loader.cpp +++ b/lib/llvm-backend/cpp/object_loader.cpp @@ -1,19 +1,35 @@ #include "object_loader.hh" #include #include +#include -class MemoryManager : llvm::RuntimeDyld::MemoryManager { +struct MemoryManager : llvm::RuntimeDyld::MemoryManager { public: - MemoryManager() {} + MemoryManager(callbacks_t *callbacks) : callbacks(callbacks) {} - virtual ~MemoryManager() {} - - virtual uint8_t* allocateCodeSection(uintptr_t Size, unsigned Alignment, unsigned SectionID, llvm::StringRef SectionName) override { - return nullptr; + virtual ~MemoryManager() { + // Deallocate all of the allocated memory. + callbacks->dealloc_memory(code_section.base, code_section.size); + callbacks->dealloc_memory(read_section.base, read_section.size); + callbacks->dealloc_memory(readwrite_section.base, readwrite_section.size); } - virtual uint8_t* allocateDataSection(uintptr_t Size, unsigned Alignment, unsigned SectionID, llvm::StringRef SectionName, bool isReadOnly) override { - return nullptr; + virtual uint8_t* allocateCodeSection(uintptr_t size, unsigned alignment, unsigned section_id, llvm::StringRef section_name) override { + std::cout << "code section name: " << (std::string)section_name << std::endl; + + return allocate_bump(code_section, code_bump_ptr, size, alignment); + } + + virtual uint8_t* allocateDataSection(uintptr_t size, unsigned alignment, unsigned section_id, llvm::StringRef section_name, bool read_only) override { + std::cout << "data section name: " << (std::string)section_name << std::endl; + + // Allocate from the read-only section or the read-write section, depending on if this allocation + // should be read-only or not. + if (read_only) { + return allocate_bump(read_section, read_bump_ptr, size, alignment); + } else { + return allocate_bump(readwrite_section, readwrite_bump_ptr, size, alignment); + } } virtual void reserveAllocationSpace( @@ -24,7 +40,20 @@ public: uintptr_t read_write_data_size, uint32_t read_write_data_align ) override { - + uint8_t *ptr_out = nullptr; + size_t size_out = 0; + + auto code_result = callbacks->alloc_memory(code_size, PROTECT_READ_WRITE, &ptr_out, &size_out); + code_section = Section { ptr_out, size_out }; + code_bump_ptr = (uintptr_t)ptr_out; + + auto read_result = callbacks->alloc_memory(read_data_size, PROTECT_READ_WRITE, &ptr_out, &size_out); + read_section = Section { ptr_out, size_out }; + read_bump_ptr = (uintptr_t)ptr_out; + + auto readwrite_result = callbacks->alloc_memory(read_write_data_size, PROTECT_READ_WRITE, &ptr_out, &size_out); + readwrite_section = Section { ptr_out, size_out }; + readwrite_bump_ptr = (uintptr_t)ptr_out; } /* Turn on the `reserveAllocationSpace` callback. */ @@ -33,38 +62,59 @@ public: } virtual void registerEHFrames(uint8_t* Addr, uint64_t LoadAddr, size_t Size) override { - + std::cout << "should register eh frames" << std::endl; } virtual void deregisterEHFrames() override { - + std::cout << "should deregister eh frames" << std::endl; } virtual bool finalizeMemory(std::string *ErrMsg = nullptr) override { - + auto code_result = callbacks->protect_memory(code_section.base, code_section.size, mem_protect_t::PROTECT_READ_EXECUTE); + if (code_result != RESULT_OK) { + return false; + } + + auto read_result = callbacks->protect_memory(read_section.base, read_section.size, mem_protect_t::PROTECT_READ); + if (read_result != RESULT_OK) { + return false; + } + + // The readwrite section is already mapped as read-write. return false; } - virtual void notifyObjectLoaded(llvm::RuntimeDyld &RTDyld, const llvm::object::ObjectFile &Obj) override { - - } + virtual void notifyObjectLoaded(llvm::RuntimeDyld &RTDyld, const llvm::object::ObjectFile &Obj) override {} private: struct Section { uint8_t* base; - size_t num_pages; - size_t num_commited_bytes; + size_t size; }; - uint8_t *image_base; - size_t num_allocated_pages; + uint8_t* allocate_bump(Section& section, uintptr_t& bump_ptr, size_t size, size_t align) { + auto aligner = [](uintptr_t& ptr, size_t align) { + ptr = (ptr + align - 1) & ~(align - 1); + }; + + // Align the bump pointer to the requires alignment. + aligner(bump_ptr, align); + + auto ret_ptr = bump_ptr; + bump_ptr += size; + + assert(bump_ptr <= (uintptr_t)section.base + section.size); + + return (uint8_t*)ret_ptr; + } Section code_section, read_section, readwrite_section; + uintptr_t code_bump_ptr, read_bump_ptr, readwrite_bump_ptr; - + callbacks_t *callbacks; }; -class SymbolLookup : llvm::JITSymbolResolver { +struct SymbolLookup : llvm::JITSymbolResolver { public: virtual llvm::Expected lookup(const LookupSet& symbols) override { LookupResult result; @@ -93,4 +143,34 @@ private: return llvm::JITEvaluatedSymbol(addr, llvm::JITSymbolFlags::None); } +}; + +class WasmModule { +public: + WasmModule( + const uint8_t *object_start, + size_t object_size, + callbacks_t *callbacks + + ) : memory_manager(std::unique_ptr(new MemoryManager(callbacks))) { + object_file = llvm::cantFail(llvm::object::ObjectFile::createObjectFile(llvm::MemoryBufferRef( + llvm::StringRef((const char *)object_start, object_size), "object" + ))); + + SymbolLookup symbol_resolver; + llvm::RuntimeDyld loader(*memory_manager, symbol_resolver); + + loader.setProcessAllSections(true); + + auto loaded_object_info = loader.loadObject(*object_file); + loader.finalizeWithMemoryManagerLocking(); + + assert(!loader.hasError()); + + + + } +private: + std::unique_ptr memory_manager; + std::unique_ptr object_file; }; \ No newline at end of file diff --git a/lib/llvm-backend/src/code.rs b/lib/llvm-backend/src/code.rs index e0f4d984f..b0e8f2912 100644 --- a/lib/llvm-backend/src/code.rs +++ b/lib/llvm-backend/src/code.rs @@ -616,7 +616,7 @@ fn parse_function( let struct_value = basic_value.into_struct_value(); for i in 0..(count as u32) { let value = - builder.build_extract_value(struct_value, i, &state.var_name()); + builder.build_extract_value(struct_value, i, &state.var_name()).unwrap(); state.push1(value); } } diff --git a/lib/llvm-backend/src/platform/mod.rs b/lib/llvm-backend/src/platform/mod.rs new file mode 100644 index 000000000..bcc0378c2 --- /dev/null +++ b/lib/llvm-backend/src/platform/mod.rs @@ -0,0 +1,8 @@ + +#[cfg(target_family = "unix")] +mod unix; +#[cfg(target_family = "unix")] +pub use self::unix::*; + +#[cfg(target_family = "windows")] +compile_error!("windows not yet supported for the llvm-based compiler backend"); \ No newline at end of file diff --git a/lib/llvm-backend/src/platform/unix/mod.rs b/lib/llvm-backend/src/platform/unix/mod.rs new file mode 100644 index 000000000..c0e86f7ef --- /dev/null +++ b/lib/llvm-backend/src/platform/unix/mod.rs @@ -0,0 +1,40 @@ + +extern "C" { + fn __register_frame(frame: *const u8); + fn __deregister_frame(frame: *const u8); +} + +pub unsafe fn register_eh_frames(eh_frames: *const u8, num_bytes: usize) { + visit_frame_desc_entries(eh_frames, num_bytes, |frame| __register_frame(frame)); +} + +unsafe fn visit_frame_desc_entries(eh_frames: *const u8, num_bytes: usize, visitor: F) +where + F: Fn(*const u8), +{ + let mut next = eh_frames; + let mut end = eh_frames.add(num_bytes); + + loop { + if next >= end { + break; + } + + let cfi = next; + let mut cfi_num_bytes = (next as *const u32).read_unaligned() as u64; + assert!(cfi_num_bytes != 0); + + next = next.add(4); + if num_bytes == 0xffffffff { + let cfi_num_bytes64 = (next as *const u64).read_unaligned(); + cfi_num_bytes = cfi_num_bytes64; + next = next.add(8); + } + + let cie_offset = (next as *const u32).read_unaligned(); + if cie_offset != 0 { + visitor(cfi); + } + next = next.add(cfi_num_bytes as usize); + } +} From d4ae5cdd409fefdb4cf8a684389c3ae31f4a9d31 Mon Sep 17 00:00:00 2001 From: Lachlan Sneff Date: Thu, 28 Feb 2019 12:31:39 -0800 Subject: [PATCH 13/75] Get function addresses from llvm-compiled code --- Cargo.lock | 46 +++-- lib/llvm-backend/Cargo.toml | 4 +- lib/llvm-backend/cpp/object_loader.cpp | 74 ++++---- lib/llvm-backend/cpp/object_loader.hh | 27 ++- lib/llvm-backend/src/backend.rs | 235 ++++++++++++++++++++++--- lib/llvm-backend/src/code.rs | 5 +- lib/llvm-backend/src/lib.rs | 67 ++----- 7 files changed, 313 insertions(+), 145 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 566a1514b..5e7852448 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -106,6 +106,22 @@ name = "byteorder" version = "1.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "capstone" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "capstone-sys 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "capstone-sys" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cc 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "cast" version = "0.2.2" @@ -262,28 +278,6 @@ dependencies = [ "generic-array 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "dlopen" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "dlopen_derive 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "dlopen_derive" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "either" version = "1.5.1" @@ -491,16 +485,16 @@ dependencies = [ name = "llvm-backend" version = "0.1.0" dependencies = [ + "capstone 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "cc 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)", - "dlopen 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "goblin 0.0.20 (registry+https://github.com/rust-lang/crates.io-index)", "hashbrown 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "inkwell 0.1.0 (git+https://github.com/TheDan64/inkwell?branch=llvm7-0)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", - "tempfile 3.0.7 (registry+https://github.com/rust-lang/crates.io-index)", "wabt 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)", "wasmer-runtime-core 0.1.2", "wasmparser 0.28.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1373,6 +1367,8 @@ dependencies = [ "checksum block-padding 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d75255892aeb580d3c566f213a2b6fdc1c66667839f45719ee1d30ebf2aea591" "checksum byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" "checksum byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a019b10a2a7cdeb292db131fc8113e57ea2a908f6e7894b0c3c671893b65dbeb" +"checksum capstone 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "00be9d203fa0e078b93b24603633fb081851dfe0c1086364431f52587a47157e" +"checksum capstone-sys 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2dc8d32bc5c1e6d0fcde10af411c98b07d93498d51654f678757f08fa2acd6a6" "checksum cast 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "926013f2860c46252efceabb19f4a6b308197505082c609025aa6706c011d427" "checksum cbindgen 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "32e01024aaf5390d6a8145047371a4f5b0063a14c1e411bc731353bd2278ca44" "checksum cc 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)" = "4390a3b5f4f6bce9c1d0c00128379df433e53777fdd30e92f16a529332baec4e" @@ -1390,8 +1386,6 @@ dependencies = [ "checksum cranelift-native 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)" = "474bee81d620a473bf43411a3d6f10ffbf7965141dc5e5b76d8d2151dde3285d" "checksum cranelift-wasm 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)" = "49723365dab9a48b354bdc24cb6d9d5719bc1d3b858ffd2ea179d0d7d885804a" "checksum digest 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "05f47366984d3ad862010e22c7ce81a7dbcaebbdfb37241a620f8b6596ee135c" -"checksum dlopen 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "f8c301a18a3404a48d5d078e86b011ac834a6c4c742217e9aa8ceadd8a7e09e0" -"checksum dlopen_derive 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6e16e4e343d6090ba47113c55bf6aa94e9b1eb5ab0c5abc9510d4c15074f30e9" "checksum either 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c67353c641dc847124ea1902d69bd753dee9bb3beff9aa3662ecf86c971d1fac" "checksum enum-methods 0.0.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7798e7da2d4cb0d6d6fc467e8d6b5bf247e9e989f786dde1732d79899c32bb10" "checksum env_logger 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "afb070faf94c85d17d50ca44f6ad076bce18ae92f0037d350947240a36e9d42e" diff --git a/lib/llvm-backend/Cargo.toml b/lib/llvm-backend/Cargo.toml index 3ec83d77c..eadc2c12f 100644 --- a/lib/llvm-backend/Cargo.toml +++ b/lib/llvm-backend/Cargo.toml @@ -11,8 +11,8 @@ inkwell = { git = "https://github.com/TheDan64/inkwell", branch = "llvm7-0" } hashbrown = "0.1.8" smallvec = "0.6.8" goblin = "0.0.20" -dlopen = "0.1.6" -tempfile = "3.0.7" +libc = "0.2.49" +capstone = "0.5.0" [build-dependencies] cc = "1.0" diff --git a/lib/llvm-backend/cpp/object_loader.cpp b/lib/llvm-backend/cpp/object_loader.cpp index 52625b64b..9265f8739 100644 --- a/lib/llvm-backend/cpp/object_loader.cpp +++ b/lib/llvm-backend/cpp/object_loader.cpp @@ -1,5 +1,4 @@ #include "object_loader.hh" -#include #include #include @@ -40,20 +39,26 @@ public: uintptr_t read_write_data_size, uint32_t read_write_data_align ) override { - uint8_t *ptr_out = nullptr; - size_t size_out = 0; + uint8_t *code_ptr_out = nullptr; + size_t code_size_out = 0; + auto code_result = callbacks->alloc_memory(code_size, PROTECT_READ_WRITE, &code_ptr_out, &code_size_out); + assert(code_result == RESULT_OK); + code_section = Section { code_ptr_out, code_size_out }; + code_bump_ptr = (uintptr_t)code_ptr_out; - auto code_result = callbacks->alloc_memory(code_size, PROTECT_READ_WRITE, &ptr_out, &size_out); - code_section = Section { ptr_out, size_out }; - code_bump_ptr = (uintptr_t)ptr_out; + uint8_t *read_ptr_out = nullptr; + size_t read_size_out = 0; + auto read_result = callbacks->alloc_memory(read_data_size, PROTECT_READ_WRITE, &read_ptr_out, &read_size_out); + assert(read_result == RESULT_OK); + read_section = Section { read_ptr_out, read_size_out }; + read_bump_ptr = (uintptr_t)read_ptr_out; - auto read_result = callbacks->alloc_memory(read_data_size, PROTECT_READ_WRITE, &ptr_out, &size_out); - read_section = Section { ptr_out, size_out }; - read_bump_ptr = (uintptr_t)ptr_out; - - auto readwrite_result = callbacks->alloc_memory(read_write_data_size, PROTECT_READ_WRITE, &ptr_out, &size_out); - readwrite_section = Section { ptr_out, size_out }; - readwrite_bump_ptr = (uintptr_t)ptr_out; + uint8_t *readwrite_ptr_out = nullptr; + size_t readwrite_size_out = 0; + auto readwrite_result = callbacks->alloc_memory(read_write_data_size, PROTECT_READ_WRITE, &readwrite_ptr_out, &readwrite_size_out); + assert(readwrite_result == RESULT_OK); + readwrite_section = Section { readwrite_ptr_out, readwrite_size_out }; + readwrite_bump_ptr = (uintptr_t)readwrite_ptr_out; } /* Turn on the `reserveAllocationSpace` callback. */ @@ -145,32 +150,37 @@ private: } }; -class WasmModule { -public: - WasmModule( +WasmModule::WasmModule( const uint8_t *object_start, size_t object_size, callbacks_t *callbacks +) : memory_manager(std::unique_ptr(new MemoryManager(callbacks))) +{ + object_file = llvm::cantFail(llvm::object::ObjectFile::createObjectFile(llvm::MemoryBufferRef( + llvm::StringRef((const char *)object_start, object_size), "object" + ))); - ) : memory_manager(std::unique_ptr(new MemoryManager(callbacks))) { - object_file = llvm::cantFail(llvm::object::ObjectFile::createObjectFile(llvm::MemoryBufferRef( - llvm::StringRef((const char *)object_start, object_size), "object" - ))); + SymbolLookup symbol_resolver; + llvm::RuntimeDyld loader(*memory_manager, symbol_resolver); - SymbolLookup symbol_resolver; - llvm::RuntimeDyld loader(*memory_manager, symbol_resolver); + loader.setProcessAllSections(true); - loader.setProcessAllSections(true); + auto loaded_object_info = loader.loadObject(*object_file); + loader.finalizeWithMemoryManagerLocking(); - auto loaded_object_info = loader.loadObject(*object_file); - loader.finalizeWithMemoryManagerLocking(); + assert(!loader.hasError()); - assert(!loader.hasError()); - - + symbol_table = loader.getSymbolTable(); + for (auto const& pair : symbol_table) { + std::cout << "symbol: (" << (std::string)pair.first << ") => " << (void*)pair.second.getAddress() << std::endl; } -private: - std::unique_ptr memory_manager; - std::unique_ptr object_file; -}; \ No newline at end of file +} + +void* WasmModule::get_func(llvm::StringRef name) const { + try { + return (void*)symbol_table.at(name).getAddress(); + } catch (const std::out_of_range& e) { + return nullptr; + } +} \ No newline at end of file diff --git a/lib/llvm-backend/cpp/object_loader.hh b/lib/llvm-backend/cpp/object_loader.hh index 50b618b38..9db12ce96 100644 --- a/lib/llvm-backend/cpp/object_loader.hh +++ b/lib/llvm-backend/cpp/object_loader.hh @@ -1,5 +1,6 @@ #include #include +#include typedef enum { PROTECT_NONE, @@ -19,7 +20,7 @@ typedef enum { typedef result_t (*alloc_memory_t)(size_t size, mem_protect_t protect, uint8_t** ptr_out, size_t* size_out); typedef result_t (*protect_memory_t)(uint8_t* ptr, size_t size, mem_protect_t protect); typedef result_t (*dealloc_memory_t)(uint8_t* ptr, size_t size); -typedef uintptr_t (*lookup_vm_symbol_t)(char* name_ptr, size_t name_size); +typedef uintptr_t (*lookup_vm_symbol_t)(char* name_ptr); typedef struct { /* Memory management. */ @@ -30,11 +31,31 @@ typedef struct { lookup_vm_symbol_t lookup_vm_symbol; } callbacks_t; + + +class WasmModule { +public: + WasmModule( + const uint8_t *object_start, + size_t object_size, + callbacks_t *callbacks + ); + + void *get_func(llvm::StringRef name) const; +private: + std::unique_ptr memory_manager; + std::unique_ptr object_file; + std::map symbol_table; +}; + extern "C" { - result_t object_load(uint8_t* mem_ptr, size_t mem_size, callbacks_t* callbacks) { + result_t object_load(const uint8_t* mem_ptr, size_t mem_size, callbacks_t* callbacks, WasmModule** module_out) { + *module_out = new WasmModule(mem_ptr, mem_size, callbacks); + return RESULT_OK; } - void test_cpp() { + void* get_func_symbol(WasmModule* module, const char* name) { + return module->get_func(llvm::StringRef(name)); } } \ No newline at end of file diff --git a/lib/llvm-backend/src/backend.rs b/lib/llvm-backend/src/backend.rs index 2b4bb7023..94310fd79 100644 --- a/lib/llvm-backend/src/backend.rs +++ b/lib/llvm-backend/src/backend.rs @@ -1,19 +1,153 @@ use crate::intrinsics::Intrinsics; -use dlopen::symbor::Library; use inkwell::{ module::Module, targets::{CodeModel, FileType, InitializationConfig, RelocMode, Target, TargetMachine}, OptimizationLevel, }; -use std::{io::Write, ptr::NonNull}; -use tempfile::NamedTempFile; +use libc::{ + c_char, mmap, mprotect, munmap, MAP_ANON, MAP_PRIVATE, PROT_EXEC, PROT_NONE, PROT_READ, + PROT_WRITE, +}; +use std::{ + ffi::CString, + ptr::{self, NonNull}, +}; use wasmer_runtime_core::{ - backend::FuncResolver, module::ModuleInner, structures::TypedIndex, types::LocalFuncIndex, vm, + backend::FuncResolver, + module::{ModuleInfo, ModuleInner}, + structures::TypedIndex, + types::LocalFuncIndex, + vm, }; +#[repr(C)] +struct LLVMModule { + _private: [u8; 0], +} + +#[derive(Debug, Copy, Clone, PartialEq, Eq)] +#[repr(C)] +enum MemProtect { + NONE, + READ, + READ_WRITE, + READ_EXECUTE, +} + +#[derive(Debug, Copy, Clone, PartialEq, Eq)] +#[repr(C)] +enum LLVMResult { + OK, + ALLOCATE_FAILURE, + PROTECT_FAILURE, + DEALLOC_FAILURE, + OBJECT_LOAD_FAILURE, +} + +#[repr(C)] +struct Callbacks { + alloc_memory: extern "C" fn(usize, MemProtect, &mut *mut u8, &mut usize) -> LLVMResult, + protect_memory: extern "C" fn(*mut u8, usize, MemProtect) -> LLVMResult, + dealloc_memory: extern "C" fn(*mut u8, usize) -> LLVMResult, + + lookup_vm_symbol: extern "C" fn(*const c_char) -> *const vm::Func, +} + +extern "C" { + fn object_load( + mem_ptr: *const u8, + mem_size: usize, + callbacks: *const Callbacks, + module_out: &mut *mut LLVMModule, + ) -> LLVMResult; + fn get_func_symbol(module: *mut LLVMModule, name: *const c_char) -> *const vm::Func; +} + +fn get_callbacks() -> Callbacks { + fn round_up_to_page_size(size: usize) -> usize { + (size + (4096 - 1)) & !(4096 - 1) + } + + extern "C" fn alloc_memory( + size: usize, + protect: MemProtect, + ptr_out: &mut *mut u8, + size_out: &mut usize, + ) -> LLVMResult { + println!("size: {}", size); + let ptr = unsafe { + mmap( + ptr::null_mut(), + round_up_to_page_size(size), + match protect { + MemProtect::NONE => PROT_NONE, + MemProtect::READ => PROT_READ, + MemProtect::READ_WRITE => PROT_READ | PROT_WRITE, + MemProtect::READ_EXECUTE => PROT_READ | PROT_EXEC, + }, + MAP_PRIVATE | MAP_ANON, + -1, + 0, + ) + }; + if ptr as isize == -1 { + return LLVMResult::ALLOCATE_FAILURE; + } + *ptr_out = ptr as _; + *size_out = size; + LLVMResult::OK + } + + extern "C" fn protect_memory(ptr: *mut u8, size: usize, protect: MemProtect) -> LLVMResult { + println!("protect memory: {:p}:{} -> {:?}", ptr, size, protect); + let res = unsafe { + mprotect( + ptr as _, + round_up_to_page_size(size), + match protect { + MemProtect::NONE => PROT_NONE, + MemProtect::READ => PROT_READ, + MemProtect::READ_WRITE => PROT_READ | PROT_WRITE, + MemProtect::READ_EXECUTE => PROT_READ | PROT_EXEC, + }, + ) + }; + + if res == 0 { + LLVMResult::OK + } else { + LLVMResult::PROTECT_FAILURE + } + } + + extern "C" fn dealloc_memory(ptr: *mut u8, size: usize) -> LLVMResult { + println!("dealloc_memory"); + let res = unsafe { munmap(ptr as _, round_up_to_page_size(size)) }; + + if res == 0 { + LLVMResult::OK + } else { + LLVMResult::DEALLOC_FAILURE + } + } + + extern "C" fn lookup_vm_symbol(_name_ptr: *const c_char) -> *const vm::Func { + ptr::null() + } + + Callbacks { + alloc_memory, + protect_memory, + dealloc_memory, + lookup_vm_symbol, + } +} + +unsafe impl Send for LLVMBackend {} +unsafe impl Sync for LLVMBackend {} + pub struct LLVMBackend { - tempfile: NamedTempFile, - library: Library, + module: *mut LLVMModule, } impl LLVMBackend { @@ -42,14 +176,50 @@ impl LLVMBackend { let memory_buffer = target_machine .write_to_memory_buffer(&module, FileType::Object) .unwrap(); + let mem_buf_slice = memory_buffer.as_slice(); - let mut tempfile = NamedTempFile::new().unwrap(); - tempfile.write_all(memory_buffer.as_slice()).unwrap(); - tempfile.flush().unwrap(); + let callbacks = get_callbacks(); + let mut module: *mut LLVMModule = ptr::null_mut(); - let library = Library::open(tempfile.path()).unwrap(); + let res = unsafe { + object_load( + mem_buf_slice.as_ptr(), + mem_buf_slice.len(), + &callbacks, + &mut module, + ) + }; - Self { tempfile, library } + if res != LLVMResult::OK { + panic!("failed to load object") + } + + Self { module } + } + + pub fn get_func( + &self, + info: &ModuleInfo, + local_func_index: LocalFuncIndex, + ) -> Option> { + let index = local_func_index.index(); + let name = if cfg!(target_os = "macos") { + format!("_fn{}", index) + } else { + format!("fn{}", index) + }; + + println!("name: {}", name); + + let c_str = CString::new(name).ok()?; + + let ptr = unsafe { get_func_symbol(self.module, c_str.as_ptr()) }; + + unsafe { + disass_ptr(ptr as _, 0x20, 4); + } + + NonNull::new(ptr as _) } } @@ -59,18 +229,35 @@ impl FuncResolver for LLVMBackend { module: &ModuleInner, local_func_index: LocalFuncIndex, ) -> Option> { - let index = module.info.imported_functions.len() + local_func_index.index(); - let name = if cfg!(macos) { - format!("_fn{}", index) - } else { - format!("fn{}", index) - }; - - unsafe { - self.library - .symbol::>(&name) - .ok() - .map(|symbol| *symbol) - } + self.get_func(&module.info, local_func_index) + } +} + +unsafe fn disass_ptr(ptr: *const u8, size: usize, inst_count: usize) { + use capstone::arch::BuildsCapstone; + let mut cs = capstone::Capstone::new() // Call builder-pattern + .x86() // X86 architecture + .mode(capstone::arch::x86::ArchMode::Mode64) // 64-bit mode + .detail(true) // Generate extra instruction details + .build() + .expect("Failed to create Capstone object"); + + // Get disassembled instructions + let insns = cs + .disasm_count( + std::slice::from_raw_parts(ptr, size), + ptr as u64, + inst_count, + ) + .expect("Failed to disassemble"); + + println!("count = {}", insns.len()); + for insn in insns.iter() { + println!( + "0x{:x}: {:6} {}", + insn.address(), + insn.mnemonic().unwrap_or(""), + insn.op_str().unwrap_or("") + ); } } diff --git a/lib/llvm-backend/src/code.rs b/lib/llvm-backend/src/code.rs index b0e8f2912..70382bd0b 100644 --- a/lib/llvm-backend/src/code.rs +++ b/lib/llvm-backend/src/code.rs @@ -615,8 +615,9 @@ fn parse_function( // This is a multi-value return. let struct_value = basic_value.into_struct_value(); for i in 0..(count as u32) { - let value = - builder.build_extract_value(struct_value, i, &state.var_name()).unwrap(); + let value = builder + .build_extract_value(struct_value, i, &state.var_name()) + .unwrap(); state.push1(value); } } diff --git a/lib/llvm-backend/src/lib.rs b/lib/llvm-backend/src/lib.rs index e06b081af..692ba091f 100644 --- a/lib/llvm-backend/src/lib.rs +++ b/lib/llvm-backend/src/lib.rs @@ -88,24 +88,18 @@ impl Compiler for LLVMCompiler { #[test] fn test_read_module() { + use std::mem::transmute; use wabt::wat2wasm; - use wasmer_runtime_core::vmcalls; + use wasmer_runtime_core::{structures::TypedIndex, types::LocalFuncIndex, vm, vmcalls}; // let wasm = include_bytes!("../../spectests/examples/simple/simple.wasm") as &[u8]; let wat = r#" (module (type $t0 (func (param i32) (result i32))) (type $t1 (func (result i32))) (memory 1) - (table 10 anyfunc) - (elem (i32.const 0) $foobar) (global $g0 (mut i32) (i32.const 0)) (func $foo (type $t0) (param i32) (result i32) get_local 0 - i32.const 0 - call_indirect (type $t0) - ) - (func $foobar (type $t0) - get_local 0 )) "#; let wasm = wat2wasm(wat).unwrap(); @@ -114,54 +108,15 @@ fn test_read_module() { let (module, intrinsics) = code::parse_function_bodies(&info, code_reader).unwrap(); - // let backend = backend::LLVMBackend::new(module, intrinsics); + let backend = backend::LLVMBackend::new(module, intrinsics); - extern "C" { - fn test_cpp(); + let func_ptr = backend.get_func(&info, LocalFuncIndex::new(0)).unwrap(); + + println!("func_ptr: {:p}", func_ptr.as_ptr()); + + unsafe { + let func: unsafe extern "C" fn(*mut vm::Ctx, i32) -> i32 = transmute(func_ptr); + let result = func(0 as _, 42); + println!("result: {}", result); } - - unsafe { test_cpp() }; - - // let exec_engine = module - // .create_jit_execution_engine(OptimizationLevel::Default) - // .unwrap(); - - // exec_engine.add_global_mapping( - // &intrinsics.memory_grow_dynamic_local, - // vmcalls::local_dynamic_memory_grow as usize, - // ); - // exec_engine.add_global_mapping( - // &intrinsics.memory_grow_static_local, - // vmcalls::local_static_memory_grow as usize, - // ); - // exec_engine.add_global_mapping( - // &intrinsics.memory_grow_dynamic_import, - // vmcalls::imported_dynamic_memory_grow as usize, - // ); - // exec_engine.add_global_mapping( - // &intrinsics.memory_grow_static_import, - // vmcalls::imported_static_memory_grow as usize, - // ); - // exec_engine.add_global_mapping( - // &intrinsics.memory_size_dynamic_local, - // vmcalls::local_dynamic_memory_size as usize, - // ); - // exec_engine.add_global_mapping( - // &intrinsics.memory_size_static_local, - // vmcalls::local_static_memory_size as usize, - // ); - // exec_engine.add_global_mapping( - // &intrinsics.memory_size_dynamic_import, - // vmcalls::imported_dynamic_memory_size as usize, - // ); - // exec_engine.add_global_mapping( - // &intrinsics.memory_size_static_import, - // vmcalls::imported_static_memory_size as usize, - // ); - - // unsafe { - // let func: JitFunction i32> = exec_engine.get_function("fn0").unwrap(); - // let result = func.call(0 as _, 0); - // println!("result: {}", result); - // } } From 359ac5abec85f85a7c7d078db63858250681bf74 Mon Sep 17 00:00:00 2001 From: Lachlan Sneff Date: Thu, 28 Feb 2019 13:18:00 -0800 Subject: [PATCH 14/75] Connect part of the llvm backend to the runtime --- .gitignore | 1 + Cargo.lock | 40 +++++++++++++++++++----------------- lib/llvm-backend/Cargo.toml | 2 +- lib/llvm-backend/src/lib.rs | 9 ++++++-- lib/runtime/Cargo.toml | 6 ++++++ lib/runtime/examples/call.rs | 38 ++++++++++++++++++++++++++++++++++ lib/runtime/src/lib.rs | 5 +++-- 7 files changed, 77 insertions(+), 24 deletions(-) create mode 100644 lib/runtime/examples/call.rs diff --git a/.gitignore b/.gitignore index dd8330f3e..f0538a823 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,4 @@ /artifacts .DS_Store .idea +**/.vscode \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock index 5e7852448..977f7280b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -481,25 +481,6 @@ dependencies = [ "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "llvm-backend" -version = "0.1.0" -dependencies = [ - "capstone 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", - "cc 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)", - "goblin 0.0.20 (registry+https://github.com/rust-lang/crates.io-index)", - "hashbrown 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "inkwell 0.1.0 (git+https://github.com/TheDan64/inkwell?branch=llvm7-0)", - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", - "wabt 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)", - "wasmer-runtime-core 0.1.2", - "wasmparser 0.28.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "llvm-sys" version = "70.1.0" @@ -1219,13 +1200,34 @@ dependencies = [ "wasmer-runtime-core 0.1.2", ] +[[package]] +name = "wasmer-llvm-backend" +version = "0.1.0" +dependencies = [ + "capstone 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)", + "goblin 0.0.20 (registry+https://github.com/rust-lang/crates.io-index)", + "hashbrown 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "inkwell 0.1.0 (git+https://github.com/TheDan64/inkwell?branch=llvm7-0)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", + "wabt 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)", + "wasmer-runtime-core 0.1.2", + "wasmparser 0.28.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "wasmer-runtime" version = "0.1.4" dependencies = [ "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "memmap 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "wabt 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)", "wasmer-clif-backend 0.1.2", + "wasmer-llvm-backend 0.1.0", "wasmer-runtime-core 0.1.2", ] diff --git a/lib/llvm-backend/Cargo.toml b/lib/llvm-backend/Cargo.toml index eadc2c12f..81301872b 100644 --- a/lib/llvm-backend/Cargo.toml +++ b/lib/llvm-backend/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "llvm-backend" +name = "wasmer-llvm-backend" version = "0.1.0" authors = ["Lachlan Sneff "] edition = "2018" diff --git a/lib/llvm-backend/src/lib.rs b/lib/llvm-backend/src/lib.rs index 692ba091f..66d8e5753 100644 --- a/lib/llvm-backend/src/lib.rs +++ b/lib/llvm-backend/src/lib.rs @@ -54,10 +54,10 @@ impl Compiler for LLVMCompiler { _vmctx: *mut vm::Ctx, _: Token, ) -> RuntimeResult> { - Ok(vec![]) + unimplemented!("the llvm-based backend does not yet implement ProtectedCaller") } fn get_early_trapper(&self) -> Box { - unimplemented!() + Box::new(Placeholder) } } impl CacheGen for Placeholder { @@ -68,6 +68,11 @@ impl Compiler for LLVMCompiler { unimplemented!() } } + impl UserTrapper for Placeholder { + unsafe fn do_early_trap(&self, msg: String) -> ! { + unimplemented!("do early trap: {}", msg) + } + } (Box::new(Placeholder), Box::new(Placeholder)) }; diff --git a/lib/runtime/Cargo.toml b/lib/runtime/Cargo.toml index e4169a652..e0c23af11 100644 --- a/lib/runtime/Cargo.toml +++ b/lib/runtime/Cargo.toml @@ -20,5 +20,11 @@ version = "0.1.2" path = "../clif-backend" version = "0.1.2" +[dependencies.wasmer-llvm-backend] +path = "../llvm-backend" + [features] debug = ["wasmer-clif-backend/debug", "wasmer-runtime-core/debug"] + +[dev-dependencies] +wabt = "0.7.4" \ No newline at end of file diff --git a/lib/runtime/examples/call.rs b/lib/runtime/examples/call.rs new file mode 100644 index 000000000..a209c12dc --- /dev/null +++ b/lib/runtime/examples/call.rs @@ -0,0 +1,38 @@ +use wasmer_runtime::{compile, error, imports, Func}; + +use wabt::wat2wasm; + +static WAT: &'static str = r#" + (module + (type $t0 (func (param i32) (result i32))) + (type $t1 (func (result i32))) + (memory 1) + (global $g0 (mut i32) (i32.const 0)) + (export "foo" (func $foo)) + (func $foo (type $t0) (param i32) (result i32) + get_local 0 + ) + ) +"#; + +fn get_wasm() -> Vec { + wat2wasm(WAT).unwrap() +} + +fn main() -> Result<(), error::Error> { + let wasm = get_wasm(); + + let module = compile(&wasm)?; + + let imports = imports! {}; + + let instance = module.instantiate(&imports)?; + + let foo: Func = instance.func("foo")?; + + let result = foo.call(42); + + println!("result: {:?}", result); + + Ok(()) +} diff --git a/lib/runtime/src/lib.rs b/lib/runtime/src/lib.rs index c7e3b3826..4c5ce88cd 100644 --- a/lib/runtime/src/lib.rs +++ b/lib/runtime/src/lib.rs @@ -154,10 +154,11 @@ pub fn instantiate(wasm: &[u8], import_object: &ImportObject) -> error::Result &'static dyn Compiler { use lazy_static::lazy_static; - use wasmer_clif_backend::CraneliftCompiler; + // use wasmer_clif_backend::CraneliftCompiler; + use wasmer_llvm_backend::LLVMCompiler; lazy_static! { - static ref DEFAULT_COMPILER: CraneliftCompiler = { CraneliftCompiler::new() }; + static ref DEFAULT_COMPILER: LLVMCompiler = { LLVMCompiler::new() }; } &*DEFAULT_COMPILER as &dyn Compiler From 6a20676fa975c91f240e95cbb4d6f1a9e957d597 Mon Sep 17 00:00:00 2001 From: Lachlan Sneff Date: Thu, 28 Feb 2019 17:20:18 -0800 Subject: [PATCH 15/75] Actually unmap the code after it's done being used --- Cargo.lock | 2 + lib/llvm-backend/cpp/object_loader.cpp | 54 +++++++++++--------------- lib/llvm-backend/cpp/object_loader.hh | 14 ++++--- lib/llvm-backend/src/backend.rs | 38 ++++++++++-------- lib/llvm-backend/src/code.rs | 14 +++---- lib/runtime/examples/call.rs | 6 +++ 6 files changed, 66 insertions(+), 62 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 977f7280b..c3cf75ae4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,3 +1,5 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. [[package]] name = "aho-corasick" version = "0.6.10" diff --git a/lib/llvm-backend/cpp/object_loader.cpp b/lib/llvm-backend/cpp/object_loader.cpp index 9265f8739..9d1d8c731 100644 --- a/lib/llvm-backend/cpp/object_loader.cpp +++ b/lib/llvm-backend/cpp/object_loader.cpp @@ -4,24 +4,20 @@ struct MemoryManager : llvm::RuntimeDyld::MemoryManager { public: - MemoryManager(callbacks_t *callbacks) : callbacks(callbacks) {} + MemoryManager(callbacks_t callbacks) : callbacks(callbacks) {} - virtual ~MemoryManager() { + virtual ~MemoryManager() override { // Deallocate all of the allocated memory. - callbacks->dealloc_memory(code_section.base, code_section.size); - callbacks->dealloc_memory(read_section.base, read_section.size); - callbacks->dealloc_memory(readwrite_section.base, readwrite_section.size); + callbacks.dealloc_memory(code_section.base, code_section.size); + callbacks.dealloc_memory(read_section.base, read_section.size); + callbacks.dealloc_memory(readwrite_section.base, readwrite_section.size); } virtual uint8_t* allocateCodeSection(uintptr_t size, unsigned alignment, unsigned section_id, llvm::StringRef section_name) override { - std::cout << "code section name: " << (std::string)section_name << std::endl; - return allocate_bump(code_section, code_bump_ptr, size, alignment); } virtual uint8_t* allocateDataSection(uintptr_t size, unsigned alignment, unsigned section_id, llvm::StringRef section_name, bool read_only) override { - std::cout << "data section name: " << (std::string)section_name << std::endl; - // Allocate from the read-only section or the read-write section, depending on if this allocation // should be read-only or not. if (read_only) { @@ -41,21 +37,21 @@ public: ) override { uint8_t *code_ptr_out = nullptr; size_t code_size_out = 0; - auto code_result = callbacks->alloc_memory(code_size, PROTECT_READ_WRITE, &code_ptr_out, &code_size_out); + auto code_result = callbacks.alloc_memory(code_size, PROTECT_READ_WRITE, &code_ptr_out, &code_size_out); assert(code_result == RESULT_OK); code_section = Section { code_ptr_out, code_size_out }; code_bump_ptr = (uintptr_t)code_ptr_out; uint8_t *read_ptr_out = nullptr; size_t read_size_out = 0; - auto read_result = callbacks->alloc_memory(read_data_size, PROTECT_READ_WRITE, &read_ptr_out, &read_size_out); + auto read_result = callbacks.alloc_memory(read_data_size, PROTECT_READ_WRITE, &read_ptr_out, &read_size_out); assert(read_result == RESULT_OK); read_section = Section { read_ptr_out, read_size_out }; read_bump_ptr = (uintptr_t)read_ptr_out; uint8_t *readwrite_ptr_out = nullptr; size_t readwrite_size_out = 0; - auto readwrite_result = callbacks->alloc_memory(read_write_data_size, PROTECT_READ_WRITE, &readwrite_ptr_out, &readwrite_size_out); + auto readwrite_result = callbacks.alloc_memory(read_write_data_size, PROTECT_READ_WRITE, &readwrite_ptr_out, &readwrite_size_out); assert(readwrite_result == RESULT_OK); readwrite_section = Section { readwrite_ptr_out, readwrite_size_out }; readwrite_bump_ptr = (uintptr_t)readwrite_ptr_out; @@ -75,12 +71,12 @@ public: } virtual bool finalizeMemory(std::string *ErrMsg = nullptr) override { - auto code_result = callbacks->protect_memory(code_section.base, code_section.size, mem_protect_t::PROTECT_READ_EXECUTE); + auto code_result = callbacks.protect_memory(code_section.base, code_section.size, mem_protect_t::PROTECT_READ_EXECUTE); if (code_result != RESULT_OK) { return false; } - auto read_result = callbacks->protect_memory(read_section.base, read_section.size, mem_protect_t::PROTECT_READ); + auto read_result = callbacks.protect_memory(read_section.base, read_section.size, mem_protect_t::PROTECT_READ); if (read_result != RESULT_OK) { return false; } @@ -116,7 +112,7 @@ private: Section code_section, read_section, readwrite_section; uintptr_t code_bump_ptr, read_bump_ptr, readwrite_bump_ptr; - callbacks_t *callbacks; + callbacks_t callbacks; }; struct SymbolLookup : llvm::JITSymbolResolver { @@ -153,34 +149,28 @@ private: WasmModule::WasmModule( const uint8_t *object_start, size_t object_size, - callbacks_t *callbacks -) : memory_manager(std::unique_ptr(new MemoryManager(callbacks))) + callbacks_t callbacks +) : memory_manager(new MemoryManager(callbacks)) { object_file = llvm::cantFail(llvm::object::ObjectFile::createObjectFile(llvm::MemoryBufferRef( llvm::StringRef((const char *)object_start, object_size), "object" ))); SymbolLookup symbol_resolver; - llvm::RuntimeDyld loader(*memory_manager, symbol_resolver); + runtime_dyld = std::unique_ptr(new llvm::RuntimeDyld(*memory_manager, symbol_resolver)); - loader.setProcessAllSections(true); + runtime_dyld->setProcessAllSections(true); - auto loaded_object_info = loader.loadObject(*object_file); - loader.finalizeWithMemoryManagerLocking(); + runtime_dyld->loadObject(*object_file); + runtime_dyld->finalizeWithMemoryManagerLocking(); - assert(!loader.hasError()); - - symbol_table = loader.getSymbolTable(); - - for (auto const& pair : symbol_table) { - std::cout << "symbol: (" << (std::string)pair.first << ") => " << (void*)pair.second.getAddress() << std::endl; + if (runtime_dyld->hasError()) { + std::cout << "RuntimeDyld error: " << (std::string)runtime_dyld->getErrorString() << std::endl; + abort(); } } void* WasmModule::get_func(llvm::StringRef name) const { - try { - return (void*)symbol_table.at(name).getAddress(); - } catch (const std::out_of_range& e) { - return nullptr; - } + auto symbol = runtime_dyld->getSymbol(name); + return (void*)symbol.getAddress(); } \ No newline at end of file diff --git a/lib/llvm-backend/cpp/object_loader.hh b/lib/llvm-backend/cpp/object_loader.hh index 9db12ce96..969f16150 100644 --- a/lib/llvm-backend/cpp/object_loader.hh +++ b/lib/llvm-backend/cpp/object_loader.hh @@ -31,30 +31,32 @@ typedef struct { lookup_vm_symbol_t lookup_vm_symbol; } callbacks_t; - - class WasmModule { public: WasmModule( const uint8_t *object_start, size_t object_size, - callbacks_t *callbacks + callbacks_t callbacks ); void *get_func(llvm::StringRef name) const; private: - std::unique_ptr memory_manager; + llvm::RuntimeDyld::MemoryManager* memory_manager; std::unique_ptr object_file; - std::map symbol_table; + std::unique_ptr runtime_dyld; }; extern "C" { - result_t object_load(const uint8_t* mem_ptr, size_t mem_size, callbacks_t* callbacks, WasmModule** module_out) { + result_t module_load(const uint8_t* mem_ptr, size_t mem_size, callbacks_t callbacks, WasmModule** module_out) { *module_out = new WasmModule(mem_ptr, mem_size, callbacks); return RESULT_OK; } + void module_delete(WasmModule* module) { + delete module; + } + void* get_func_symbol(WasmModule* module, const char* name) { return module->get_func(llvm::StringRef(name)); } diff --git a/lib/llvm-backend/src/backend.rs b/lib/llvm-backend/src/backend.rs index 94310fd79..6e55d55fe 100644 --- a/lib/llvm-backend/src/backend.rs +++ b/lib/llvm-backend/src/backend.rs @@ -1,5 +1,6 @@ use crate::intrinsics::Intrinsics; use inkwell::{ + memory_buffer::MemoryBuffer, module::Module, targets::{CodeModel, FileType, InitializationConfig, RelocMode, Target, TargetMachine}, OptimizationLevel, @@ -25,6 +26,7 @@ struct LLVMModule { _private: [u8; 0], } +#[allow(non_camel_case_types, dead_code)] #[derive(Debug, Copy, Clone, PartialEq, Eq)] #[repr(C)] enum MemProtect { @@ -34,6 +36,7 @@ enum MemProtect { READ_EXECUTE, } +#[allow(non_camel_case_types, dead_code)] #[derive(Debug, Copy, Clone, PartialEq, Eq)] #[repr(C)] enum LLVMResult { @@ -54,12 +57,13 @@ struct Callbacks { } extern "C" { - fn object_load( + fn module_load( mem_ptr: *const u8, mem_size: usize, - callbacks: *const Callbacks, + callbacks: Callbacks, module_out: &mut *mut LLVMModule, ) -> LLVMResult; + fn module_delete(module: *mut LLVMModule); fn get_func_symbol(module: *mut LLVMModule, name: *const c_char) -> *const vm::Func; } @@ -74,11 +78,11 @@ fn get_callbacks() -> Callbacks { ptr_out: &mut *mut u8, size_out: &mut usize, ) -> LLVMResult { - println!("size: {}", size); + let size = round_up_to_page_size(size); let ptr = unsafe { mmap( ptr::null_mut(), - round_up_to_page_size(size), + size, match protect { MemProtect::NONE => PROT_NONE, MemProtect::READ => PROT_READ, @@ -99,7 +103,6 @@ fn get_callbacks() -> Callbacks { } extern "C" fn protect_memory(ptr: *mut u8, size: usize, protect: MemProtect) -> LLVMResult { - println!("protect memory: {:p}:{} -> {:?}", ptr, size, protect); let res = unsafe { mprotect( ptr as _, @@ -121,7 +124,6 @@ fn get_callbacks() -> Callbacks { } extern "C" fn dealloc_memory(ptr: *mut u8, size: usize) -> LLVMResult { - println!("dealloc_memory"); let res = unsafe { munmap(ptr as _, round_up_to_page_size(size)) }; if res == 0 { @@ -148,6 +150,8 @@ unsafe impl Sync for LLVMBackend {} pub struct LLVMBackend { module: *mut LLVMModule, + #[allow(dead_code)] + memory_buffer: MemoryBuffer, } impl LLVMBackend { @@ -182,10 +186,10 @@ impl LLVMBackend { let mut module: *mut LLVMModule = ptr::null_mut(); let res = unsafe { - object_load( + module_load( mem_buf_slice.as_ptr(), mem_buf_slice.len(), - &callbacks, + callbacks, &mut module, ) }; @@ -194,7 +198,10 @@ impl LLVMBackend { panic!("failed to load object") } - Self { module } + Self { + module, + memory_buffer, + } } pub fn get_func( @@ -209,20 +216,19 @@ impl LLVMBackend { format!("fn{}", index) }; - println!("name: {}", name); - let c_str = CString::new(name).ok()?; - let ptr = unsafe { get_func_symbol(self.module, c_str.as_ptr()) }; - unsafe { - disass_ptr(ptr as _, 0x20, 4); - } - NonNull::new(ptr as _) } } +impl Drop for LLVMBackend { + fn drop(&mut self) { + unsafe { module_delete(self.module) } + } +} + impl FuncResolver for LLVMBackend { fn get( &self, diff --git a/lib/llvm-backend/src/code.rs b/lib/llvm-backend/src/code.rs index 70382bd0b..3b72dd309 100644 --- a/lib/llvm-backend/src/code.rs +++ b/lib/llvm-backend/src/code.rs @@ -1,7 +1,7 @@ use inkwell::{ builder::Builder, context::Context, - module::Module, + module::{Linkage, Module}, passes::PassManager, types::{BasicType, BasicTypeEnum, FunctionType, PointerType}, values::{BasicValue, FunctionValue, PhiValue, PointerValue}, @@ -10,7 +10,7 @@ use inkwell::{ use smallvec::SmallVec; use wasmer_runtime_core::{ memory::MemoryType, - module::ModuleInfo, + module::{ExportIndex, ModuleInfo}, structures::{Map, SliceMap, TypedIndex}, types::{ FuncIndex, FuncSig, GlobalIndex, LocalFuncIndex, LocalOrImport, MemoryIndex, SigIndex, @@ -80,7 +80,7 @@ pub fn parse_function_bodies( module.add_function( &format!("fn{}", func_index.index()), signatures[sig_index], - None, + Some(Linkage::External), ) }) .collect(); @@ -106,6 +106,7 @@ pub fn parse_function_bodies( } let pass_manager = PassManager::create_for_module(); + pass_manager.add_function_inlining_pass(); pass_manager.add_promote_memory_to_register_pass(); pass_manager.add_cfg_simplification_pass(); pass_manager.add_instruction_combining_pass(); @@ -113,13 +114,11 @@ pub fn parse_function_bodies( // pass_manager.add_merged_load_store_motion_pass(); // pass_manager.add_sccp_pass(); pass_manager.add_gvn_pass(); - pass_manager.add_new_gvn_pass(); + // pass_manager.add_new_gvn_pass(); pass_manager.add_aggressive_dce_pass(); - pass_manager.add_verifier_pass(); + // pass_manager.add_verifier_pass(); pass_manager.run_on_module(&module); - println!("{}", module.print_to_string().to_string()); - Ok((module, intrinsics)) } @@ -1791,7 +1790,6 @@ fn parse_function( state.push1(result.try_as_basic_value().left().unwrap()); } op @ _ => { - println!("{}", module.print_to_string().to_string()); unimplemented!("{:?}", op); } } diff --git a/lib/runtime/examples/call.rs b/lib/runtime/examples/call.rs index a209c12dc..6015a4bb1 100644 --- a/lib/runtime/examples/call.rs +++ b/lib/runtime/examples/call.rs @@ -11,6 +11,12 @@ static WAT: &'static str = r#" (export "foo" (func $foo)) (func $foo (type $t0) (param i32) (result i32) get_local 0 + call $bar + ) + (func $bar (type $t0) (param i32) (result i32) + get_local 0 + i32.const 10 + i32.add ) ) "#; From 51c9091fc5a452f38727ebffb9d2f3faa46ea477 Mon Sep 17 00:00:00 2001 From: Lachlan Sneff Date: Thu, 28 Feb 2019 18:26:47 -0800 Subject: [PATCH 16/75] Start work on generating trampolines --- lib/llvm-backend/src/trampolines.rs | 38 +++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 lib/llvm-backend/src/trampolines.rs diff --git a/lib/llvm-backend/src/trampolines.rs b/lib/llvm-backend/src/trampolines.rs new file mode 100644 index 000000000..34ce9eb15 --- /dev/null +++ b/lib/llvm-backend/src/trampolines.rs @@ -0,0 +1,38 @@ +use inkwell::{ + builder::Builder, + context::Context, + module::{Linkage, Module}, + passes::PassManager, + types::{BasicType, BasicTypeEnum, FunctionType, PointerType}, + values::{BasicValue, FunctionValue, PhiValue, PointerValue}, + AddressSpace, FloatPredicate, IntPredicate, +}; +use wasmer_runtime_core::{ + module::ModuleInfo, + types::{SigIndex, FuncSig}, + structures::{TypedIndex, SliceMap}, +}; +use crate::intrinsics::Intrinsics; + +pub fn generate_trampolines(info: &ModuleInfo, signatures: &SliceMap, module: &Module, builder: &Builder, intrinsics: &Intrinsics) -> Result<(), String> { + let trampoline_sig = intrinsics.void_ty.fn_type(&[ + intrinsics.ctx_ptr_ty, // vmctx ptr + intrinsics.i64_ptr_ty, // func ptr + intrinsics.i64_ptr_ty, + intrinsics.i64_ptr_ty, + ], false); + + for (sig_index, sig) in info.signatures.iter() { + + } +} + +pub fn generate_trampoline(sig_index: usize, trampoline_sig: FunctionType, sig: &FuncSig, builder: &Builder, intrinsics: &Intrinsics) { + let function = module.add_function( + &format!("tramp{}", sig_index.index()), + signatures[sig_index], + Some(Linkage::External), + ); + + +} \ No newline at end of file From b80252e1654904b4ca61043084ca1b34b95b52c7 Mon Sep 17 00:00:00 2001 From: Brandon Fish Date: Thu, 28 Feb 2019 23:02:03 -0600 Subject: [PATCH 17/75] Setup the spectests lib to use llvm-backend --- Cargo.lock | 1 + lib/runtime-core/src/types.rs | 7 +------ lib/spectests/Cargo.toml | 1 + lib/spectests/build/spectests.rs | 9 +++++---- 4 files changed, 8 insertions(+), 10 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c3cf75ae4..f06c9e940 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1273,6 +1273,7 @@ version = "0.1.2" dependencies = [ "wabt 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)", "wasmer-clif-backend 0.1.2", + "wasmer-llvm-backend 0.1.0", "wasmer-runtime-core 0.1.2", ] diff --git a/lib/runtime-core/src/types.rs b/lib/runtime-core/src/types.rs index 618f24004..9ee5270dd 100644 --- a/lib/runtime-core/src/types.rs +++ b/lib/runtime-core/src/types.rs @@ -1,9 +1,4 @@ -use crate::{ - memory::MemoryType, - module::ModuleInfo, - structures::TypedIndex, - units::Pages, -}; +use crate::{memory::MemoryType, module::ModuleInfo, structures::TypedIndex, units::Pages}; use std::{borrow::Cow, mem}; /// Represents a WebAssembly type. diff --git a/lib/spectests/Cargo.toml b/lib/spectests/Cargo.toml index f69782b40..49f052d77 100644 --- a/lib/spectests/Cargo.toml +++ b/lib/spectests/Cargo.toml @@ -16,6 +16,7 @@ wabt = "0.7.2" [dev-dependencies] wasmer-clif-backend = { path = "../clif-backend", version = "0.1.2" } +wasmer-llvm-backend = { path = "../llvm-backend", version = "0.1.0" } wabt = "0.7.2" [features] diff --git a/lib/spectests/build/spectests.rs b/lib/spectests/build/spectests.rs index 54d9404d6..25b3b63b8 100644 --- a/lib/spectests/build/spectests.rs +++ b/lib/spectests/build/spectests.rs @@ -78,6 +78,7 @@ static COMMON: &'static str = r##" use std::{{f32, f64}}; use wabt::wat2wasm; use wasmer_clif_backend::CraneliftCompiler; +use wasmer_llvm_backend::LLVMCompiler; use wasmer_runtime_core::import::ImportObject; use wasmer_runtime_core::types::Value; use wasmer_runtime_core::{{Instance, module::Module}}; @@ -97,7 +98,7 @@ static IMPORT_MODULE: &str = r#" pub fn generate_imports() -> ImportObject { let wasm_binary = wat2wasm(IMPORT_MODULE.as_bytes()).expect("WAST not valid or malformed"); - let module = wasmer_runtime_core::compile_with(&wasm_binary[..], &CraneliftCompiler::new()) + let module = wasmer_runtime_core::compile_with(&wasm_binary[..], &LLVMCompiler::new()) .expect("WASM can't be compiled"); let instance = module .instantiate(&ImportObject::new()) @@ -358,7 +359,7 @@ fn test_module_{}() {{ let module_str = \"{}\"; println!(\"{{}}\", module_str); let wasm_binary = wat2wasm(module_str.as_bytes()).expect(\"WAST not valid or malformed\"); - let module = wasmer_runtime_core::compile_with(&wasm_binary[..], &CraneliftCompiler::new()).expect(\"WASM can't be compiled\"); + let module = wasmer_runtime_core::compile_with(&wasm_binary[..], &LLVMCompiler::new()).expect(\"WASM can't be compiled\"); module.instantiate(&generate_imports()).expect(\"WASM can't be instantiated\") }}\n", self.last_module, @@ -381,7 +382,7 @@ fn test_module_{}() {{ "#[test] fn {}_assert_invalid() {{ let wasm_binary = {:?}; - let module = wasmer_runtime_core::compile_with(&wasm_binary, &CraneliftCompiler::new()); + let module = wasmer_runtime_core::compile_with(&wasm_binary, &LLVMCompiler::new()); assert!(module.is_err(), \"WASM should not compile as is invalid\"); }}\n", command_name, @@ -512,7 +513,7 @@ fn {}_assert_invalid() {{ "#[test] fn {}_assert_malformed() {{ let wasm_binary = {:?}; - let compilation = wasmer_runtime_core::compile_with(&wasm_binary, &CraneliftCompiler::new()); + let compilation = wasmer_runtime_core::compile_with(&wasm_binary, &LLVMCompiler::new()); assert!(compilation.is_err(), \"WASM should not compile as is malformed\"); }}\n", command_name, From 3717c5720d9a5357498b8b7a6c356bb9cbfe03ab Mon Sep 17 00:00:00 2001 From: Lachlan Sneff Date: Fri, 1 Mar 2019 15:48:43 -0800 Subject: [PATCH 18/75] Get control flow (at least according to the llvm verifier) working. Next up: - Importing vm intrinsics. --- lib/llvm-backend/src/backend.rs | 153 ++++++++++++++++++++++++-- lib/llvm-backend/src/code.rs | 164 ++++++++++++++++++++++------ lib/llvm-backend/src/intrinsics.rs | 1 - lib/llvm-backend/src/lib.rs | 47 ++++---- lib/llvm-backend/src/trampolines.rs | 118 +++++++++++++++++--- lib/runtime-core/src/instance.rs | 2 +- lib/runtime/examples/call.rs | 28 ++--- 7 files changed, 408 insertions(+), 105 deletions(-) diff --git a/lib/llvm-backend/src/backend.rs b/lib/llvm-backend/src/backend.rs index 6e55d55fe..98b0bc6e0 100644 --- a/lib/llvm-backend/src/backend.rs +++ b/lib/llvm-backend/src/backend.rs @@ -11,14 +11,17 @@ use libc::{ }; use std::{ ffi::CString, + mem, ptr::{self, NonNull}, }; use wasmer_runtime_core::{ - backend::FuncResolver, + backend::{FuncResolver, ProtectedCaller, Token, UserTrapper}, + error::RuntimeResult, + export::Context, module::{ModuleInfo, ModuleInner}, structures::TypedIndex, - types::LocalFuncIndex, - vm, + types::{FuncIndex, FuncSig, LocalFuncIndex, LocalOrImport, SigIndex, Type, Value}, + vm::{self, ImportBacking}, }; #[repr(C)] @@ -155,7 +158,7 @@ pub struct LLVMBackend { } impl LLVMBackend { - pub fn new(module: Module, intrinsics: Intrinsics) -> Self { + pub fn new(module: Module, intrinsics: Intrinsics) -> (Self, LLVMProtectedCaller) { Target::initialize_x86(&InitializationConfig { asm_parser: true, asm_printer: true, @@ -198,10 +201,13 @@ impl LLVMBackend { panic!("failed to load object") } - Self { - module, - memory_buffer, - } + ( + Self { + module, + memory_buffer, + }, + LLVMProtectedCaller { module }, + ) } pub fn get_func( @@ -239,6 +245,137 @@ impl FuncResolver for LLVMBackend { } } +struct Placeholder; + +unsafe impl Send for LLVMProtectedCaller {} +unsafe impl Sync for LLVMProtectedCaller {} + +pub struct LLVMProtectedCaller { + module: *mut LLVMModule, +} + +impl ProtectedCaller for LLVMProtectedCaller { + fn call( + &self, + module: &ModuleInner, + func_index: FuncIndex, + params: &[Value], + import_backing: &ImportBacking, + vmctx: *mut vm::Ctx, + _: Token, + ) -> RuntimeResult> { + let (func_ptr, ctx, signature, sig_index) = + get_func_from_index(&module, import_backing, func_index); + + let vmctx_ptr = match ctx { + Context::External(external_vmctx) => external_vmctx, + Context::Internal => vmctx, + }; + + assert!( + signature.returns().len() <= 1, + "multi-value returns not yet supported" + ); + + assert!( + signature.check_param_value_types(params), + "incorrect signature" + ); + + let param_vec: Vec = params + .iter() + .map(|val| match val { + Value::I32(x) => *x as u64, + Value::I64(x) => *x as u64, + Value::F32(x) => x.to_bits() as u64, + Value::F64(x) => x.to_bits(), + }) + .collect(); + + let mut return_vec = vec![0; signature.returns().len()]; + + let trampoline: unsafe extern "C" fn(*mut vm::Ctx, *const vm::Func, *const u64, *mut u64) = unsafe { + let name = if cfg!(target_os = "macos") { + format!("_trmp{}", sig_index.index()) + } else { + format!("trmp{}", sig_index.index()) + }; + + let c_str = CString::new(name).unwrap(); + let symbol = get_func_symbol(self.module, c_str.as_ptr()); + assert!(!symbol.is_null()); + + mem::transmute(symbol) + }; + + // Here we go. + unsafe { + trampoline( + vmctx_ptr, + func_ptr, + param_vec.as_ptr(), + return_vec.as_mut_ptr(), + ); + } + + Ok(return_vec + .iter() + .zip(signature.returns().iter()) + .map(|(&x, ty)| match ty { + Type::I32 => Value::I32(x as i32), + Type::I64 => Value::I64(x as i64), + Type::F32 => Value::F32(f32::from_bits(x as u32)), + Type::F64 => Value::F64(f64::from_bits(x as u64)), + }) + .collect()) + } + + fn get_early_trapper(&self) -> Box { + Box::new(Placeholder) + } +} + +impl UserTrapper for Placeholder { + unsafe fn do_early_trap(&self, msg: String) -> ! { + unimplemented!("do early trap: {}", msg) + } +} + +fn get_func_from_index<'a>( + module: &'a ModuleInner, + import_backing: &ImportBacking, + func_index: FuncIndex, +) -> (*const vm::Func, Context, &'a FuncSig, SigIndex) { + let sig_index = *module + .info + .func_assoc + .get(func_index) + .expect("broken invariant, incorrect func index"); + + let (func_ptr, ctx) = match func_index.local_or_import(&module.info) { + LocalOrImport::Local(local_func_index) => ( + module + .func_resolver + .get(&module, local_func_index) + .expect("broken invariant, func resolver not synced with module.exports") + .cast() + .as_ptr() as *const _, + Context::Internal, + ), + LocalOrImport::Import(imported_func_index) => { + let imported_func = import_backing.imported_func(imported_func_index); + ( + imported_func.func as *const _, + Context::External(imported_func.vmctx), + ) + } + }; + + let signature = &module.info.signatures[sig_index]; + + (func_ptr, ctx, signature, sig_index) +} + unsafe fn disass_ptr(ptr: *const u8, size: usize, inst_count: usize) { use capstone::arch::BuildsCapstone; let mut cs = capstone::Capstone::new() // Call builder-pattern diff --git a/lib/llvm-backend/src/code.rs b/lib/llvm-backend/src/code.rs index 3b72dd309..dd7ec30c7 100644 --- a/lib/llvm-backend/src/code.rs +++ b/lib/llvm-backend/src/code.rs @@ -24,6 +24,7 @@ use wasmparser::{ use crate::intrinsics::{CtxType, GlobalCache, Intrinsics}; use crate::read_info::type_to_type; use crate::state::{ControlFrame, IfElseState, State}; +use crate::trampolines::generate_trampolines; fn func_sig_to_llvm(context: &Context, intrinsics: &Intrinsics, sig: &FuncSig) -> FunctionType { let user_param_types = sig.params().iter().map(|&ty| type_to_llvm(intrinsics, ty)); @@ -102,10 +103,19 @@ pub fn parse_function_bodies( LocalFuncIndex::new(local_func_index), locals_reader, op_reader, - )?; + ) + .map_err(|e| BinaryReaderError { + message: e.message, + offset: local_func_index, + })?; } + // module.print_to_stderr(); + + generate_trampolines(info, &signatures, &module, &context, &builder, &intrinsics); + let pass_manager = PassManager::create_for_module(); + pass_manager.add_verifier_pass(); pass_manager.add_function_inlining_pass(); pass_manager.add_promote_memory_to_register_pass(); pass_manager.add_cfg_simplification_pass(); @@ -116,7 +126,6 @@ pub fn parse_function_bodies( pass_manager.add_gvn_pass(); // pass_manager.add_new_gvn_pass(); pass_manager.add_aggressive_dce_pass(); - // pass_manager.add_verifier_pass(); pass_manager.run_on_module(&module); Ok((module, intrinsics)) @@ -209,8 +218,34 @@ fn parse_function( locals.push(alloca); } + let mut unreachable_depth = 0; + for op in op_reader { - match op? { + let op = op?; + if !state.reachable { + match op { + Operator::Block { ty: _ } | Operator::Loop { ty: _ } | Operator::If { ty: _ } => { + unreachable_depth += 1; + continue; + } + Operator::Else => { + if unreachable_depth != 0 { + continue; + } + } + Operator::End => { + if unreachable_depth != 0 { + unreachable_depth -= 1; + continue; + } + } + _ => { + continue; + } + } + } + + match op { /*************************** * Control Flow instructions. * https://github.com/sunfishcode/wasm-reference-manual/blob/master/WebAssembly.md#control-flow-instructions @@ -356,7 +391,7 @@ fn parse_function( builder.build_switch(index.into_int_value(), default_frame.br_dest(), &cases[..]); state.popn(res_len)?; - builder.build_unreachable(); + state.reachable = false; } Operator::If { ty } => { let current_block = builder.get_insert_block().ok_or(BinaryReaderError { @@ -440,8 +475,22 @@ fn parse_function( builder.build_unconditional_branch(frame.code_after()); for phi in frame.phis().iter().rev() { - let value = state.pop1()?; - phi.add_incoming(&[(&value, ¤t_block)]) + if phi.count_incoming() != 0 { + let value = state.pop1()?; + phi.add_incoming(&[(&value, ¤t_block)]) + } 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() + } + _ => unimplemented!(), + }; + phi.add_incoming(&[(&placeholder_value, ¤t_block)]); + } } } @@ -466,13 +515,40 @@ fn parse_function( // Push each phi value to the value stack. for phi in frame.phis() { - state.push1(phi.as_basic_value()); + if phi.count_incoming() != 0 { + 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() + } + _ => unimplemented!(), + }; + state.push1(placeholder_value); + phi.as_instruction().erase_from_basic_block(); + } } } Operator::Return => { let frame = state.outermost_frame()?; + let current_block = builder.get_insert_block().ok_or(BinaryReaderError { + message: "not currently in a block", + offset: -1isize as usize, + })?; builder.build_unconditional_branch(frame.br_dest()); + + let phis = frame.phis().to_vec(); + + for phi in phis.iter() { + let arg = state.pop1()?; + phi.add_incoming(&[(&arg, ¤t_block)]); + } + state.reachable = false; } @@ -508,7 +584,7 @@ fn parse_function( Operator::F32Const { value } => { let f = intrinsics .f32_ty - .const_float(f64::from_bits(value.bits() as u64)); + .const_float(f32::from_bits(value.bits()) as f64); state.push1(f); } Operator::F64Const { value } => { @@ -562,15 +638,20 @@ fn parse_function( Operator::Select => { let (v1, v2, cond) = state.pop3()?; - let cond = cond.into_int_value(); - let res = builder.build_select(cond, v1, v2, &state.var_name()); + let cond_value = builder.build_int_compare( + IntPredicate::NE, + cond.into_int_value(), + intrinsics.i32_zero, + &state.var_name(), + ); + let res = builder.build_select(cond_value, v1, v2, &state.var_name()); state.push1(res); } Operator::Call { function_index } => { let func_index = FuncIndex::new(function_index as usize); let sigindex = info.func_assoc[func_index]; let llvm_sig = signatures[sigindex]; - let func_sig = &info.signatures[sig_index]; + let func_sig = &info.signatures[sigindex]; let call_site = match func_index.local_or_import(info) { LocalOrImport::Local(local_func_index) => { @@ -710,7 +791,6 @@ fn parse_function( let args: Vec<_> = std::iter::once(ctx_ptr) .chain(pushed_args.into_iter()) .collect(); - println!("args: {:?}", args); let typed_func_ptr = builder.build_pointer_cast( func_ptr, @@ -948,22 +1028,24 @@ fn parse_function( } Operator::I32Eqz => { let input = state.pop1()?.into_int_value(); - let res = builder.build_int_compare( + let cond = builder.build_int_compare( IntPredicate::EQ, input, intrinsics.i32_zero, &state.var_name(), ); + let res = builder.build_int_z_extend(cond, intrinsics.i32_ty, &state.var_name()); state.push1(res); } Operator::I64Eqz => { let input = state.pop1()?.into_int_value(); - let res = builder.build_int_compare( + let cond = builder.build_int_compare( IntPredicate::EQ, input, intrinsics.i64_zero, &state.var_name(), ); + let res = builder.build_int_z_extend(cond, intrinsics.i32_ty, &state.var_name()); state.push1(res); } @@ -1170,61 +1252,71 @@ fn parse_function( Operator::I32Eq | Operator::I64Eq => { let (v1, v2) = state.pop2()?; let (v1, v2) = (v1.into_int_value(), v2.into_int_value()); - let res = builder.build_int_compare(IntPredicate::EQ, v1, v2, &state.var_name()); + let cond = builder.build_int_compare(IntPredicate::EQ, v1, v2, &state.var_name()); + let res = builder.build_int_z_extend(cond, intrinsics.i32_ty, &state.var_name()); state.push1(res); } Operator::I32Ne | Operator::I64Ne => { let (v1, v2) = state.pop2()?; let (v1, v2) = (v1.into_int_value(), v2.into_int_value()); - let res = builder.build_int_compare(IntPredicate::NE, v1, v2, &state.var_name()); + let cond = builder.build_int_compare(IntPredicate::NE, v1, v2, &state.var_name()); + let res = builder.build_int_z_extend(cond, intrinsics.i32_ty, &state.var_name()); state.push1(res); } Operator::I32LtS | Operator::I64LtS => { let (v1, v2) = state.pop2()?; let (v1, v2) = (v1.into_int_value(), v2.into_int_value()); - let res = builder.build_int_compare(IntPredicate::SLT, v1, v2, &state.var_name()); + let cond = builder.build_int_compare(IntPredicate::SLT, v1, v2, &state.var_name()); + let res = builder.build_int_z_extend(cond, intrinsics.i32_ty, &state.var_name()); state.push1(res); } Operator::I32LtU | Operator::I64LtU => { let (v1, v2) = state.pop2()?; let (v1, v2) = (v1.into_int_value(), v2.into_int_value()); - let res = builder.build_int_compare(IntPredicate::ULT, v1, v2, &state.var_name()); + let cond = builder.build_int_compare(IntPredicate::ULT, v1, v2, &state.var_name()); + let res = builder.build_int_z_extend(cond, intrinsics.i32_ty, &state.var_name()); state.push1(res); } Operator::I32LeS | Operator::I64LeS => { let (v1, v2) = state.pop2()?; let (v1, v2) = (v1.into_int_value(), v2.into_int_value()); - let res = builder.build_int_compare(IntPredicate::SLE, v1, v2, &state.var_name()); + let cond = builder.build_int_compare(IntPredicate::SLE, v1, v2, &state.var_name()); + let res = builder.build_int_z_extend(cond, intrinsics.i32_ty, &state.var_name()); state.push1(res); } Operator::I32LeU | Operator::I64LeU => { let (v1, v2) = state.pop2()?; let (v1, v2) = (v1.into_int_value(), v2.into_int_value()); - let res = builder.build_int_compare(IntPredicate::ULE, v1, v2, &state.var_name()); + let cond = builder.build_int_compare(IntPredicate::ULE, v1, v2, &state.var_name()); + let res = builder.build_int_z_extend(cond, intrinsics.i32_ty, &state.var_name()); state.push1(res); } Operator::I32GtS | Operator::I64GtS => { let (v1, v2) = state.pop2()?; let (v1, v2) = (v1.into_int_value(), v2.into_int_value()); - let res = builder.build_int_compare(IntPredicate::SGT, v1, v2, &state.var_name()); + let cond = builder.build_int_compare(IntPredicate::SGT, v1, v2, &state.var_name()); + let res = builder.build_int_z_extend(cond, intrinsics.i32_ty, &state.var_name()); state.push1(res); } Operator::I32GtU | Operator::I64GtU => { let (v1, v2) = state.pop2()?; let (v1, v2) = (v1.into_int_value(), v2.into_int_value()); - let res = builder.build_int_compare(IntPredicate::UGT, v1, v2, &state.var_name()); + let cond = builder.build_int_compare(IntPredicate::UGT, v1, v2, &state.var_name()); + let res = builder.build_int_z_extend(cond, intrinsics.i32_ty, &state.var_name()); state.push1(res); } Operator::I32GeS | Operator::I64GeS => { let (v1, v2) = state.pop2()?; let (v1, v2) = (v1.into_int_value(), v2.into_int_value()); - let res = builder.build_int_compare(IntPredicate::SGE, v1, v2, &state.var_name()); + let cond = builder.build_int_compare(IntPredicate::SGE, v1, v2, &state.var_name()); + let res = builder.build_int_z_extend(cond, intrinsics.i32_ty, &state.var_name()); state.push1(res); } Operator::I32GeU | Operator::I64GeU => { let (v1, v2) = state.pop2()?; let (v1, v2) = (v1.into_int_value(), v2.into_int_value()); - let res = builder.build_int_compare(IntPredicate::UGE, v1, v2, &state.var_name()); + let cond = builder.build_int_compare(IntPredicate::UGE, v1, v2, &state.var_name()); + let res = builder.build_int_z_extend(cond, intrinsics.i32_ty, &state.var_name()); state.push1(res); } @@ -1235,43 +1327,49 @@ fn parse_function( Operator::F32Eq | Operator::F64Eq => { let (v1, v2) = state.pop2()?; let (v1, v2) = (v1.into_float_value(), v2.into_float_value()); - let res = + let cond = builder.build_float_compare(FloatPredicate::OEQ, v1, v2, &state.var_name()); + let res = builder.build_int_z_extend(cond, intrinsics.i32_ty, &state.var_name()); state.push1(res); } Operator::F32Ne | Operator::F64Ne => { let (v1, v2) = state.pop2()?; let (v1, v2) = (v1.into_float_value(), v2.into_float_value()); - let res = + let cond = builder.build_float_compare(FloatPredicate::UNE, v1, v2, &state.var_name()); + let res = builder.build_int_z_extend(cond, intrinsics.i32_ty, &state.var_name()); state.push1(res); } Operator::F32Lt | Operator::F64Lt => { let (v1, v2) = state.pop2()?; let (v1, v2) = (v1.into_float_value(), v2.into_float_value()); - let res = + let cond = builder.build_float_compare(FloatPredicate::OLT, v1, v2, &state.var_name()); + let res = builder.build_int_z_extend(cond, intrinsics.i32_ty, &state.var_name()); state.push1(res); } Operator::F32Le | Operator::F64Le => { let (v1, v2) = state.pop2()?; let (v1, v2) = (v1.into_float_value(), v2.into_float_value()); - let res = + let cond = builder.build_float_compare(FloatPredicate::OLE, v1, v2, &state.var_name()); + let res = builder.build_int_z_extend(cond, intrinsics.i32_ty, &state.var_name()); state.push1(res); } Operator::F32Gt | Operator::F64Gt => { let (v1, v2) = state.pop2()?; let (v1, v2) = (v1.into_float_value(), v2.into_float_value()); - let res = + let cond = builder.build_float_compare(FloatPredicate::OGT, v1, v2, &state.var_name()); + let res = builder.build_int_z_extend(cond, intrinsics.i32_ty, &state.var_name()); state.push1(res); } Operator::F32Ge | Operator::F64Ge => { let (v1, v2) = state.pop2()?; let (v1, v2) = (v1.into_float_value(), v2.into_float_value()); - let res = + let cond = builder.build_float_compare(FloatPredicate::OGE, v1, v2, &state.var_name()); + let res = builder.build_int_z_extend(cond, intrinsics.i32_ty, &state.var_name()); state.push1(res); } @@ -1816,9 +1914,5 @@ fn resolve_memory_ptr( let mem_base_int = builder.build_ptr_to_int(mem_base, intrinsics.i64_ty, &state.var_name()); let effective_address_int = builder.build_int_add(mem_base_int, effective_offset, &state.var_name()); - Ok(builder.build_int_to_ptr( - effective_address_int, - intrinsics.i32_ptr_ty, - &state.var_name(), - )) + Ok(builder.build_int_to_ptr(effective_address_int, ptr_ty, &state.var_name())) } diff --git a/lib/llvm-backend/src/intrinsics.rs b/lib/llvm-backend/src/intrinsics.rs index f2ec8fd05..97af89a5b 100644 --- a/lib/llvm-backend/src/intrinsics.rs +++ b/lib/llvm-backend/src/intrinsics.rs @@ -639,7 +639,6 @@ impl<'a> CtxType<'a> { let int = builder.build_ptr_to_int(global_ptr, intrinsics.i64_ty, "global_ptr_int"); builder.build_int_to_ptr(int, llvm_ptr_ty, "global_ptr_typed") }; - println!("global_ptr: {:?}", global_ptr_typed); if mutable { GlobalCache::Mut { diff --git a/lib/llvm-backend/src/lib.rs b/lib/llvm-backend/src/lib.rs index 66d8e5753..f46520383 100644 --- a/lib/llvm-backend/src/lib.rs +++ b/lib/llvm-backend/src/lib.rs @@ -9,12 +9,14 @@ use wasmer_runtime_core::{ error::CompileError, module::ModuleInner, }; +use wasmparser::{self, WasmDecoder}; mod backend; mod code; mod intrinsics; mod read_info; mod state; +mod trampolines; pub struct LLVMCompiler { _private: (), @@ -28,13 +30,15 @@ impl LLVMCompiler { impl Compiler for LLVMCompiler { fn compile(&self, wasm: &[u8], _: Token) -> Result { + validate(wasm)?; + let (info, code_reader) = read_info::read_module(wasm).unwrap(); let (module, intrinsics) = code::parse_function_bodies(&info, code_reader).unwrap(); - let backend = backend::LLVMBackend::new(module, intrinsics); + let (backend, protected_caller) = backend::LLVMBackend::new(module, intrinsics); // Create placeholder values here. - let (protected_caller, cache_gen) = { + let cache_gen = { use wasmer_runtime_core::backend::{ sys::Memory, CacheGen, ProtectedCaller, UserTrapper, }; @@ -44,22 +48,6 @@ impl Compiler for LLVMCompiler { use wasmer_runtime_core::types::{FuncIndex, Value}; use wasmer_runtime_core::vm; struct Placeholder; - impl ProtectedCaller for Placeholder { - fn call( - &self, - _module: &ModuleInner, - _func_index: FuncIndex, - _params: &[Value], - _import_backing: &vm::ImportBacking, - _vmctx: *mut vm::Ctx, - _: Token, - ) -> RuntimeResult> { - unimplemented!("the llvm-based backend does not yet implement ProtectedCaller") - } - fn get_early_trapper(&self) -> Box { - Box::new(Placeholder) - } - } impl CacheGen for Placeholder { fn generate_cache( &self, @@ -68,18 +56,13 @@ impl Compiler for LLVMCompiler { unimplemented!() } } - impl UserTrapper for Placeholder { - unsafe fn do_early_trap(&self, msg: String) -> ! { - unimplemented!("do early trap: {}", msg) - } - } - (Box::new(Placeholder), Box::new(Placeholder)) + Box::new(Placeholder) }; Ok(ModuleInner { func_resolver: Box::new(backend), - protected_caller, + protected_caller: Box::new(protected_caller), cache_gen, info, @@ -91,6 +74,20 @@ impl Compiler for LLVMCompiler { } } +fn validate(bytes: &[u8]) -> Result<(), CompileError> { + let mut parser = wasmparser::ValidatingParser::new(bytes, None); + loop { + let state = parser.read(); + match *state { + wasmparser::ParserState::EndWasm => break Ok(()), + wasmparser::ParserState::Error(err) => Err(CompileError::ValidationError { + msg: err.message.to_string(), + })?, + _ => {} + } + } +} + #[test] fn test_read_module() { use std::mem::transmute; diff --git a/lib/llvm-backend/src/trampolines.rs b/lib/llvm-backend/src/trampolines.rs index 34ce9eb15..4619cb990 100644 --- a/lib/llvm-backend/src/trampolines.rs +++ b/lib/llvm-backend/src/trampolines.rs @@ -1,3 +1,4 @@ +use crate::intrinsics::Intrinsics; use inkwell::{ builder::Builder, context::Context, @@ -9,30 +10,111 @@ use inkwell::{ }; use wasmer_runtime_core::{ module::ModuleInfo, - types::{SigIndex, FuncSig}, - structures::{TypedIndex, SliceMap}, + structures::{SliceMap, TypedIndex}, + types::{FuncSig, SigIndex, Type}, }; -use crate::intrinsics::Intrinsics; - -pub fn generate_trampolines(info: &ModuleInfo, signatures: &SliceMap, module: &Module, builder: &Builder, intrinsics: &Intrinsics) -> Result<(), String> { - let trampoline_sig = intrinsics.void_ty.fn_type(&[ - intrinsics.ctx_ptr_ty, // vmctx ptr - intrinsics.i64_ptr_ty, // func ptr - intrinsics.i64_ptr_ty, - intrinsics.i64_ptr_ty, - ], false); +pub fn generate_trampolines( + info: &ModuleInfo, + signatures: &SliceMap, + module: &Module, + context: &Context, + builder: &Builder, + intrinsics: &Intrinsics, +) { for (sig_index, sig) in info.signatures.iter() { + let func_type = signatures[sig_index]; + let trampoline_sig = intrinsics.void_ty.fn_type( + &[ + intrinsics.ctx_ptr_ty.as_basic_type_enum(), // vmctx ptr + func_type + .ptr_type(AddressSpace::Generic) + .as_basic_type_enum(), // func ptr + intrinsics.i64_ptr_ty.as_basic_type_enum(), // args ptr + intrinsics.i64_ptr_ty.as_basic_type_enum(), // returns ptr + ], + false, + ); + + let trampoline_func = module.add_function( + &format!("trmp{}", sig_index.index()), + trampoline_sig, + Some(Linkage::External), + ); + + generate_trampoline( + trampoline_func, + func_type, + sig, + context, + builder, + intrinsics, + ); } } -pub fn generate_trampoline(sig_index: usize, trampoline_sig: FunctionType, sig: &FuncSig, builder: &Builder, intrinsics: &Intrinsics) { - let function = module.add_function( - &format!("tramp{}", sig_index.index()), - signatures[sig_index], - Some(Linkage::External), - ); +fn generate_trampoline( + trampoline_func: FunctionValue, + sig_type: FunctionType, + func_sig: &FuncSig, + context: &Context, + builder: &Builder, + intrinsics: &Intrinsics, +) { + let entry_block = context.append_basic_block(&trampoline_func, "entry"); + builder.position_at_end(&entry_block); + let (vmctx_ptr, func_ptr, args_ptr, returns_ptr) = match trampoline_func.get_params().as_slice() + { + &[vmctx_ptr, func_ptr, args_ptr, returns_ptr] => ( + vmctx_ptr, + func_ptr.into_pointer_value(), + args_ptr.into_pointer_value(), + returns_ptr.into_pointer_value(), + ), + _ => unimplemented!(), + }; -} \ No newline at end of file + let cast_ptr_ty = |wasmer_ty| match wasmer_ty { + Type::I32 => intrinsics.i32_ptr_ty, + Type::I64 => intrinsics.i64_ptr_ty, + Type::F32 => intrinsics.f32_ptr_ty, + Type::F64 => intrinsics.f64_ptr_ty, + }; + + let mut args_vec = Vec::with_capacity(func_sig.params().len() + 1); + args_vec.push(vmctx_ptr); + + for (i, param_ty) in func_sig.params().iter().enumerate() { + let index = intrinsics.i32_ty.const_int(i as _, false); + let item_pointer = unsafe { builder.build_in_bounds_gep(args_ptr, &[index], "arg_ptr") }; + + let casted_pointer_type = cast_ptr_ty(*param_ty); + + let typed_item_pointer = + builder.build_pointer_cast(item_pointer, casted_pointer_type, "typed_arg_pointer"); + + let arg = builder.build_load(typed_item_pointer, "arg"); + args_vec.push(arg); + } + + let call_site = builder.build_call(func_ptr, &args_vec, "call"); + + match func_sig.returns() { + &[] => {} + &[one_ret] => { + let ret_ptr_type = cast_ptr_ty(one_ret); + + let typed_ret_ptr = + builder.build_pointer_cast(returns_ptr, ret_ptr_type, "typed_ret_ptr"); + builder.build_store( + typed_ret_ptr, + call_site.try_as_basic_value().left().unwrap(), + ); + } + _ => unimplemented!("multi-value returns"), + } + + builder.build_return(None); +} diff --git a/lib/runtime-core/src/instance.rs b/lib/runtime-core/src/instance.rs index 6a4d5d438..61e8f556d 100644 --- a/lib/runtime-core/src/instance.rs +++ b/lib/runtime-core/src/instance.rs @@ -454,7 +454,7 @@ impl<'a> DynFunc<'a> { /// # Ok(()) /// # } /// ``` - pub fn call(&mut self, params: &[Value]) -> CallResult> { + pub fn call(&self, params: &[Value]) -> CallResult> { if !self.signature.check_param_value_types(params) { Err(ResolveError::Signature { expected: (*self.signature).clone(), diff --git a/lib/runtime/examples/call.rs b/lib/runtime/examples/call.rs index 6015a4bb1..d583f8a2f 100644 --- a/lib/runtime/examples/call.rs +++ b/lib/runtime/examples/call.rs @@ -1,23 +1,16 @@ -use wasmer_runtime::{compile, error, imports, Func}; +use wasmer_runtime::{compile, error, imports, Func, Value}; use wabt::wat2wasm; static WAT: &'static str = r#" (module - (type $t0 (func (param i32) (result i32))) - (type $t1 (func (result i32))) - (memory 1) - (global $g0 (mut i32) (i32.const 0)) - (export "foo" (func $foo)) - (func $foo (type $t0) (param i32) (result i32) - get_local 0 - call $bar - ) - (func $bar (type $t0) (param i32) (result i32) - get_local 0 - i32.const 10 - i32.add - ) + (type (;0;) (func (result i32))) + (func (;0;) (type 0) (result i32) + block (result i32) ;; label = @1 + i32.const 1 + end + return) + (export "as-return-value" (func 0)) ) "#; @@ -32,11 +25,12 @@ fn main() -> Result<(), error::Error> { let imports = imports! {}; + println!("instantiating"); let instance = module.instantiate(&imports)?; - let foo: Func = instance.func("foo")?; + let foo = instance.dyn_func("as-call-value")?; - let result = foo.call(42); + let result = foo.call(&[]); println!("result: {:?}", result); From f0ac76517a9a39c5b016db3315eb5a4f98707f34 Mon Sep 17 00:00:00 2001 From: Lachlan Sneff Date: Fri, 1 Mar 2019 17:11:20 -0800 Subject: [PATCH 19/75] Start running spectests Additional info: - Execution is turned off, this is just to make sure the backend can compile the entire specsuite. - That being said, trampolines are implemented and protected call works (just doesn't protect). --- lib/llvm-backend/cpp/object_loader.cpp | 8 +++-- lib/llvm-backend/cpp/object_loader.hh | 2 +- lib/llvm-backend/src/backend.rs | 33 +++++++++++++++++-- lib/llvm-backend/src/code.rs | 44 ++++++++++---------------- lib/llvm-backend/src/intrinsics.rs | 8 ++--- 5 files changed, 57 insertions(+), 38 deletions(-) diff --git a/lib/llvm-backend/cpp/object_loader.cpp b/lib/llvm-backend/cpp/object_loader.cpp index 9d1d8c731..3c36707c5 100644 --- a/lib/llvm-backend/cpp/object_loader.cpp +++ b/lib/llvm-backend/cpp/object_loader.cpp @@ -117,6 +117,8 @@ private: struct SymbolLookup : llvm::JITSymbolResolver { public: + SymbolLookup(callbacks_t callbacks) : callbacks(callbacks) {} + virtual llvm::Expected lookup(const LookupSet& symbols) override { LookupResult result; @@ -140,10 +142,12 @@ public: private: llvm::JITEvaluatedSymbol symbol_lookup(llvm::StringRef name) { std::cout << "symbol name: " << (std::string)name << std::endl; - uint64_t addr = 0; + uint64_t addr = callbacks.lookup_vm_symbol(name.data(), name.size()); return llvm::JITEvaluatedSymbol(addr, llvm::JITSymbolFlags::None); } + + callbacks_t callbacks; }; WasmModule::WasmModule( @@ -156,7 +160,7 @@ WasmModule::WasmModule( llvm::StringRef((const char *)object_start, object_size), "object" ))); - SymbolLookup symbol_resolver; + SymbolLookup symbol_resolver(callbacks); runtime_dyld = std::unique_ptr(new llvm::RuntimeDyld(*memory_manager, symbol_resolver)); runtime_dyld->setProcessAllSections(true); diff --git a/lib/llvm-backend/cpp/object_loader.hh b/lib/llvm-backend/cpp/object_loader.hh index 969f16150..8134385fd 100644 --- a/lib/llvm-backend/cpp/object_loader.hh +++ b/lib/llvm-backend/cpp/object_loader.hh @@ -20,7 +20,7 @@ typedef enum { typedef result_t (*alloc_memory_t)(size_t size, mem_protect_t protect, uint8_t** ptr_out, size_t* size_out); typedef result_t (*protect_memory_t)(uint8_t* ptr, size_t size, mem_protect_t protect); typedef result_t (*dealloc_memory_t)(uint8_t* ptr, size_t size); -typedef uintptr_t (*lookup_vm_symbol_t)(char* name_ptr); +typedef uintptr_t (*lookup_vm_symbol_t)(const char* name_ptr, size_t length); typedef struct { /* Memory management. */ diff --git a/lib/llvm-backend/src/backend.rs b/lib/llvm-backend/src/backend.rs index 98b0bc6e0..5b9299ce9 100644 --- a/lib/llvm-backend/src/backend.rs +++ b/lib/llvm-backend/src/backend.rs @@ -13,6 +13,7 @@ use std::{ ffi::CString, mem, ptr::{self, NonNull}, + slice, str, }; use wasmer_runtime_core::{ backend::{FuncResolver, ProtectedCaller, Token, UserTrapper}, @@ -22,6 +23,7 @@ use wasmer_runtime_core::{ structures::TypedIndex, types::{FuncIndex, FuncSig, LocalFuncIndex, LocalOrImport, SigIndex, Type, Value}, vm::{self, ImportBacking}, + vmcalls, }; #[repr(C)] @@ -56,7 +58,7 @@ struct Callbacks { protect_memory: extern "C" fn(*mut u8, usize, MemProtect) -> LLVMResult, dealloc_memory: extern "C" fn(*mut u8, usize) -> LLVMResult, - lookup_vm_symbol: extern "C" fn(*const c_char) -> *const vm::Func, + lookup_vm_symbol: extern "C" fn(*const c_char, usize) -> *const vm::Func, } extern "C" { @@ -136,8 +138,31 @@ fn get_callbacks() -> Callbacks { } } - extern "C" fn lookup_vm_symbol(_name_ptr: *const c_char) -> *const vm::Func { - ptr::null() + extern "C" fn lookup_vm_symbol(name_ptr: *const c_char, length: usize) -> *const vm::Func { + #[cfg(target_os = "macos")] + macro_rules! fn_name { + ($s:literal) => { + concat!("_", $s) + }; + } + + #[cfg(not(target_os = "macos"))] + macro_rules! fn_name { + ($s:literal) => { + $s + }; + } + + let name_slice = unsafe { slice::from_raw_parts(name_ptr as *const u8, length) }; + let name = str::from_utf8(name_slice).unwrap(); + + match name { + fn_name!("vm.memory.grow.dynamic.local") => vmcalls::local_dynamic_memory_grow as _, + fn_name!("vm.memory.size.dynamic.local") => vmcalls::local_dynamic_memory_size as _, + fn_name!("vm.memory.grow.static.local") => vmcalls::local_static_memory_grow as _, + fn_name!("vm.memory.size.static.local") => vmcalls::local_static_memory_size as _, + _ => ptr::null(), + } } Callbacks { @@ -241,6 +266,7 @@ impl FuncResolver for LLVMBackend { module: &ModuleInner, local_func_index: LocalFuncIndex, ) -> Option> { + unimplemented!(); self.get_func(&module.info, local_func_index) } } @@ -264,6 +290,7 @@ impl ProtectedCaller for LLVMProtectedCaller { vmctx: *mut vm::Ctx, _: Token, ) -> RuntimeResult> { + unimplemented!(); let (func_ptr, ctx, signature, sig_index) = get_func_from_index(&module, import_backing, func_index); diff --git a/lib/llvm-backend/src/code.rs b/lib/llvm-backend/src/code.rs index dd7ec30c7..aeb050cd5 100644 --- a/lib/llvm-backend/src/code.rs +++ b/lib/llvm-backend/src/code.rs @@ -110,7 +110,7 @@ pub fn parse_function_bodies( })?; } - // module.print_to_stderr(); + module.print_to_stderr(); generate_trampolines(info, &signatures, &module, &context, &builder, &intrinsics); @@ -475,22 +475,8 @@ fn parse_function( builder.build_unconditional_branch(frame.code_after()); for phi in frame.phis().iter().rev() { - if phi.count_incoming() != 0 { - let value = state.pop1()?; - phi.add_incoming(&[(&value, ¤t_block)]) - } 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() - } - _ => unimplemented!(), - }; - phi.add_incoming(&[(&placeholder_value, ¤t_block)]); - } + let value = state.pop1()?; + phi.add_incoming(&[(&value, ¤t_block)]); } } @@ -558,6 +544,7 @@ fn parse_function( // it will emit a `ud2` instruction on x86_64 arches. ctx.build_trap(); builder.build_unreachable(); + state.reachable = false; } @@ -747,12 +734,13 @@ fn parse_function( ) }; - let sigindices_equal = builder.build_int_compare( - IntPredicate::EQ, - expected_dynamic_sigindex, - found_dynamic_sigindex, - "sigindices_equal", - ); + // let sigindices_equal = builder.build_int_compare( + // IntPredicate::EQ, + // expected_dynamic_sigindex, + // found_dynamic_sigindex, + // "sigindices_equal", + // ); + let sigindices_equal = intrinsics.i1_ty.const_int(1, false); // Tell llvm that `expected_dynamic_sigindex` should equal `found_dynamic_sigindex`. let sigindices_equal = builder @@ -1227,18 +1215,18 @@ fn parse_function( state.push1(res); } Operator::F32Copysign => { - let input = state.pop1()?; + let (mag, sgn) = state.pop2()?; let res = builder - .build_call(intrinsics.copysign_f32, &[input], &state.var_name()) + .build_call(intrinsics.copysign_f32, &[mag, sgn], &state.var_name()) .try_as_basic_value() .left() .unwrap(); state.push1(res); } Operator::F64Copysign => { - let input = state.pop1()?; + let (msg, sgn) = state.pop2()?; let res = builder - .build_call(intrinsics.copysign_f64, &[input], &state.var_name()) + .build_call(intrinsics.copysign_f64, &[msg, sgn], &state.var_name()) .try_as_basic_value() .left() .unwrap(); @@ -1549,7 +1537,7 @@ fn parse_function( &mut state, &mut ctx, memarg, - intrinsics.i32_ptr_ty, + intrinsics.f32_ptr_ty, )?; let result = builder.build_load(effective_address, &state.var_name()); state.push1(result); diff --git a/lib/llvm-backend/src/intrinsics.rs b/lib/llvm-backend/src/intrinsics.rs index 97af89a5b..c3f2191f3 100644 --- a/lib/llvm-backend/src/intrinsics.rs +++ b/lib/llvm-backend/src/intrinsics.rs @@ -231,11 +231,11 @@ impl Intrinsics { sqrt_f32: module.add_function("llvm.sqrt.f32", ret_f32_take_f32, None), sqrt_f64: module.add_function("llvm.sqrt.f64", ret_f64_take_f64, None), - minimum_f32: module.add_function("llvm.minimum.f32", ret_f32_take_f32_f32, None), - minimum_f64: module.add_function("llvm.minimum.f64", ret_f64_take_f64_f64, None), + minimum_f32: module.add_function("llvm.minnum.f32", ret_f32_take_f32_f32, None), + minimum_f64: module.add_function("llvm.minnum.f64", ret_f64_take_f64_f64, None), - maximum_f32: module.add_function("llvm.maximum.f32", ret_f32_take_f32_f32, None), - maximum_f64: module.add_function("llvm.maximum.f64", ret_f64_take_f64_f64, None), + maximum_f32: module.add_function("llvm.maxnum.f32", ret_f32_take_f32_f32, None), + maximum_f64: module.add_function("llvm.maxnum.f64", ret_f64_take_f64_f64, None), ceil_f32: module.add_function("llvm.ceil.f32", ret_f32_take_f32, None), ceil_f64: module.add_function("llvm.ceil.f64", ret_f64_take_f64, None), From 362e5aa160137c0e9226dab111521aef7dd9a480 Mon Sep 17 00:00:00 2001 From: Lachlan Sneff Date: Fri, 1 Mar 2019 20:23:21 -0800 Subject: [PATCH 20/75] Fix issue caused by dangling instruction. - Come on inkwell, I thought you were better than this. --- lib/llvm-backend/src/code.rs | 35 +++++++++++++++++------------------ lib/runtime/examples/call.rs | 15 ++++++--------- 2 files changed, 23 insertions(+), 27 deletions(-) diff --git a/lib/llvm-backend/src/code.rs b/lib/llvm-backend/src/code.rs index aeb050cd5..7a0587a15 100644 --- a/lib/llvm-backend/src/code.rs +++ b/lib/llvm-backend/src/code.rs @@ -110,8 +110,6 @@ pub fn parse_function_bodies( })?; } - module.print_to_stderr(); - generate_trampolines(info, &signatures, &module, &context, &builder, &intrinsics); let pass_manager = PassManager::create_for_module(); @@ -161,22 +159,6 @@ fn parse_function( .map(|ty| builder.build_phi(ty, &state.var_name())) .collect(); - match phis.as_slice() { - // No returns. - &[] => { - builder.build_return(None); - } - &[one_value] => { - let value = one_value.as_basic_value(); - builder.build_return(Some(&value)); - } - returns @ _ => { - // let struct_ty = llvm_sig.get_return_type().as_struct_type(); - // let ret_struct = struct_ty.const_zero(); - unimplemented!("multi-value returns not yet implemented") - } - } - state.push_block(return_block, phis); builder.position_at_end(&entry_block); @@ -504,6 +486,7 @@ fn parse_function( if phi.count_incoming() != 0 { state.push1(phi.as_basic_value()); } else { + println!("replacing"); let basic_ty = phi.as_basic_value().get_type(); let placeholder_value = match basic_ty { BasicTypeEnum::IntType(int_ty) => { @@ -1881,6 +1864,22 @@ fn parse_function( } } + let results = state.popn_save(func_sig.returns().len())?; + + match results.as_slice() { + [] => { + builder.build_return(None); + } + [one_value] => { + builder.build_return(Some(one_value)); + } + returns @ _ => { + // let struct_ty = llvm_sig.get_return_type().as_struct_type(); + // let ret_struct = struct_ty.const_zero(); + unimplemented!("multi-value returns not yet implemented") + } + } + Ok(()) } diff --git a/lib/runtime/examples/call.rs b/lib/runtime/examples/call.rs index d583f8a2f..0684c1bb7 100644 --- a/lib/runtime/examples/call.rs +++ b/lib/runtime/examples/call.rs @@ -4,13 +4,10 @@ use wabt::wat2wasm; static WAT: &'static str = r#" (module - (type (;0;) (func (result i32))) - (func (;0;) (type 0) (result i32) - block (result i32) ;; label = @1 - i32.const 1 - end - return) - (export "as-return-value" (func 0)) + (type (;0;) (func (param i32) (result i32))) + (func (;0;) (type 0) (param i32) (result i32) + unreachable) + (export "select_trap_l" (func 0)) ) "#; @@ -28,9 +25,9 @@ fn main() -> Result<(), error::Error> { println!("instantiating"); let instance = module.instantiate(&imports)?; - let foo = instance.dyn_func("as-call-value")?; + let foo = instance.dyn_func("select_trap_l")?; - let result = foo.call(&[]); + let result = foo.call(&[Value::I32(0)]); println!("result: {:?}", result); From a6fc06c9081f69ee8d7f78e59fdd978a46fa52a4 Mon Sep 17 00:00:00 2001 From: Lachlan Sneff Date: Sat, 2 Mar 2019 10:04:44 -0800 Subject: [PATCH 21/75] Fix more compiling issues Specifically: - Don't truncate the list of local parameters. - If the default destination in a br_table instruction is a loop, don't pop any results. --- lib/llvm-backend/src/backend.rs | 2 -- lib/llvm-backend/src/code.rs | 18 +++++++++++------- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/lib/llvm-backend/src/backend.rs b/lib/llvm-backend/src/backend.rs index 5b9299ce9..a7d700e90 100644 --- a/lib/llvm-backend/src/backend.rs +++ b/lib/llvm-backend/src/backend.rs @@ -266,7 +266,6 @@ impl FuncResolver for LLVMBackend { module: &ModuleInner, local_func_index: LocalFuncIndex, ) -> Option> { - unimplemented!(); self.get_func(&module.info, local_func_index) } } @@ -290,7 +289,6 @@ impl ProtectedCaller for LLVMProtectedCaller { vmctx: *mut vm::Ctx, _: Token, ) -> RuntimeResult> { - unimplemented!(); let (func_ptr, ctx, signature, sig_index) = get_func_from_index(&module, import_backing, func_index); diff --git a/lib/llvm-backend/src/code.rs b/lib/llvm-backend/src/code.rs index 7a0587a15..2504d3977 100644 --- a/lib/llvm-backend/src/code.rs +++ b/lib/llvm-backend/src/code.rs @@ -179,14 +179,16 @@ fn parse_function( }), ); - for (index, local) in locals_reader.into_iter().enumerate().skip(locals.len()) { + let param_len = locals.len(); + + for (index, local) in locals_reader.into_iter().enumerate() { let (_, ty) = local?; let wasmer_ty = type_to_type(ty)?; let ty = type_to_llvm(intrinsics, wasmer_ty); - let alloca = builder.build_alloca(ty, &format!("local{}", index)); + let alloca = builder.build_alloca(ty, &format!("local{}", param_len + index)); let default_value = match wasmer_ty { Type::I32 => intrinsics.i32_zero.as_basic_value_enum(), @@ -346,9 +348,12 @@ fn parse_function( let default_frame = state.frame_at_depth(default_depth)?; - let res_len = default_frame.phis().len(); - - let args = state.peekn(res_len)?; + let args = if default_frame.is_loop() { + &[] + } else { + let res_len = default_frame.phis().len(); + state.peekn(res_len)? + }; for (phi, value) in default_frame.phis().iter().zip(args.iter()) { phi.add_incoming(&[(value, ¤t_block)]); @@ -372,7 +377,7 @@ fn parse_function( builder.build_switch(index.into_int_value(), default_frame.br_dest(), &cases[..]); - state.popn(res_len)?; + state.popn(args.len())?; state.reachable = false; } Operator::If { ty } => { @@ -486,7 +491,6 @@ fn parse_function( if phi.count_incoming() != 0 { state.push1(phi.as_basic_value()); } else { - println!("replacing"); let basic_ty = phi.as_basic_value().get_type(); let placeholder_value = match basic_ty { BasicTypeEnum::IntType(int_ty) => { From 87ddf4f8550225a68a04dc20b7ada85cc7d82baf Mon Sep 17 00:00:00 2001 From: Lachlan Sneff Date: Sat, 2 Mar 2019 10:20:18 -0800 Subject: [PATCH 22/75] Add personality function. - This is part of supporting exceptions in the future. --- lib/llvm-backend/src/code.rs | 14 ++++++++++++-- lib/runtime/examples/call.rs | 2 +- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/lib/llvm-backend/src/code.rs b/lib/llvm-backend/src/code.rs index 2504d3977..a9170082b 100644 --- a/lib/llvm-backend/src/code.rs +++ b/lib/llvm-backend/src/code.rs @@ -68,6 +68,12 @@ pub fn parse_function_bodies( let intrinsics = Intrinsics::declare(&module, &context); + let personality_func = module.add_function( + "__gxx_personality_v0", + intrinsics.i32_ty.fn_type(&[], false), + Some(Linkage::External), + ); + let signatures: Map = info .signatures .iter() @@ -78,11 +84,13 @@ pub fn parse_function_bodies( .iter() .skip(info.imported_functions.len()) .map(|(func_index, &sig_index)| { - module.add_function( + let func = module.add_function( &format!("fn{}", func_index.index()), signatures[sig_index], Some(Linkage::External), - ) + ); + func.set_personality_function(personality_func); + func }) .collect(); @@ -110,6 +118,8 @@ pub fn parse_function_bodies( })?; } + module.print_to_stderr(); + generate_trampolines(info, &signatures, &module, &context, &builder, &intrinsics); let pass_manager = PassManager::create_for_module(); diff --git a/lib/runtime/examples/call.rs b/lib/runtime/examples/call.rs index 0684c1bb7..ac38b8d46 100644 --- a/lib/runtime/examples/call.rs +++ b/lib/runtime/examples/call.rs @@ -6,7 +6,7 @@ static WAT: &'static str = r#" (module (type (;0;) (func (param i32) (result i32))) (func (;0;) (type 0) (param i32) (result i32) - unreachable) + i32.const 42) (export "select_trap_l" (func 0)) ) "#; From 5760f6006ab38b3f0c7426e9e72b5e5a3b529f43 Mon Sep 17 00:00:00 2001 From: Lachlan Sneff Date: Sat, 2 Mar 2019 10:56:02 -0800 Subject: [PATCH 23/75] Start implementing exception handling by adding frame descriptor entry processing. - Soon, we should be able basic exceptions. --- lib/llvm-backend/cpp/object_loader.cpp | 20 +++++++++--- lib/llvm-backend/cpp/object_loader.hh | 6 +++- lib/llvm-backend/src/backend.rs | 8 +++++ lib/llvm-backend/src/lib.rs | 1 + lib/llvm-backend/src/platform/mod.rs | 7 ++-- lib/llvm-backend/src/platform/unix.rs | 35 ++++++++++++++++++++ lib/llvm-backend/src/platform/unix/mod.rs | 40 ----------------------- 7 files changed, 68 insertions(+), 49 deletions(-) create mode 100644 lib/llvm-backend/src/platform/unix.rs delete mode 100644 lib/llvm-backend/src/platform/unix/mod.rs diff --git a/lib/llvm-backend/cpp/object_loader.cpp b/lib/llvm-backend/cpp/object_loader.cpp index 3c36707c5..ff6dbe2d1 100644 --- a/lib/llvm-backend/cpp/object_loader.cpp +++ b/lib/llvm-backend/cpp/object_loader.cpp @@ -2,11 +2,15 @@ #include #include +extern "C" void __register_frame(uint8_t *); +extern "C" void __deregister_frame(uint8_t *); + struct MemoryManager : llvm::RuntimeDyld::MemoryManager { public: MemoryManager(callbacks_t callbacks) : callbacks(callbacks) {} virtual ~MemoryManager() override { + deregisterEHFrames(); // Deallocate all of the allocated memory. callbacks.dealloc_memory(code_section.base, code_section.size); callbacks.dealloc_memory(read_section.base, read_section.size); @@ -62,12 +66,17 @@ public: return true; } - virtual void registerEHFrames(uint8_t* Addr, uint64_t LoadAddr, size_t Size) override { - std::cout << "should register eh frames" << std::endl; + virtual void registerEHFrames(uint8_t* addr, uint64_t LoadAddr, size_t size) override { + eh_frame_ptr = addr; + eh_frame_size = size; + eh_frames_registered = true; + callbacks.visit_fde(addr, size, __register_frame); } virtual void deregisterEHFrames() override { - std::cout << "should deregister eh frames" << std::endl; + if (eh_frames_registered) { + callbacks.visit_fde(eh_frame_ptr, eh_frame_size, __deregister_frame); + } } virtual bool finalizeMemory(std::string *ErrMsg = nullptr) override { @@ -111,6 +120,9 @@ private: Section code_section, read_section, readwrite_section; uintptr_t code_bump_ptr, read_bump_ptr, readwrite_bump_ptr; + uint8_t* eh_frame_ptr; + size_t eh_frame_size; + bool eh_frames_registered = false; callbacks_t callbacks; }; @@ -154,7 +166,7 @@ WasmModule::WasmModule( const uint8_t *object_start, size_t object_size, callbacks_t callbacks -) : memory_manager(new MemoryManager(callbacks)) +) : memory_manager(std::unique_ptr(new MemoryManager(callbacks))) { object_file = llvm::cantFail(llvm::object::ObjectFile::createObjectFile(llvm::MemoryBufferRef( llvm::StringRef((const char *)object_start, object_size), "object" diff --git a/lib/llvm-backend/cpp/object_loader.hh b/lib/llvm-backend/cpp/object_loader.hh index 8134385fd..d31d33266 100644 --- a/lib/llvm-backend/cpp/object_loader.hh +++ b/lib/llvm-backend/cpp/object_loader.hh @@ -21,6 +21,8 @@ typedef result_t (*alloc_memory_t)(size_t size, mem_protect_t protect, uint8_t** typedef result_t (*protect_memory_t)(uint8_t* ptr, size_t size, mem_protect_t protect); typedef result_t (*dealloc_memory_t)(uint8_t* ptr, size_t size); typedef uintptr_t (*lookup_vm_symbol_t)(const char* name_ptr, size_t length); +typedef void (*fde_visitor_t)(uint8_t *fde); +typedef result_t (*visit_fde_t)(uint8_t *fde, size_t size, fde_visitor_t visitor); typedef struct { /* Memory management. */ @@ -29,6 +31,8 @@ typedef struct { dealloc_memory_t dealloc_memory; lookup_vm_symbol_t lookup_vm_symbol; + + visit_fde_t visit_fde; } callbacks_t; class WasmModule { @@ -41,7 +45,7 @@ public: void *get_func(llvm::StringRef name) const; private: - llvm::RuntimeDyld::MemoryManager* memory_manager; + std::unique_ptr memory_manager; std::unique_ptr object_file; std::unique_ptr runtime_dyld; }; diff --git a/lib/llvm-backend/src/backend.rs b/lib/llvm-backend/src/backend.rs index a7d700e90..66f29cbbb 100644 --- a/lib/llvm-backend/src/backend.rs +++ b/lib/llvm-backend/src/backend.rs @@ -59,6 +59,7 @@ struct Callbacks { dealloc_memory: extern "C" fn(*mut u8, usize) -> LLVMResult, lookup_vm_symbol: extern "C" fn(*const c_char, usize) -> *const vm::Func, + visit_fde: extern "C" fn(*mut u8, usize, extern "C" fn(*mut u8)), } extern "C" { @@ -165,11 +166,18 @@ fn get_callbacks() -> Callbacks { } } + extern "C" fn visit_fde(fde: *mut u8, size: usize, visitor: extern "C" fn(*mut u8)) { + unsafe { + crate::platform::visit_fde(fde, size, visitor); + } + } + Callbacks { alloc_memory, protect_memory, dealloc_memory, lookup_vm_symbol, + visit_fde, } } diff --git a/lib/llvm-backend/src/lib.rs b/lib/llvm-backend/src/lib.rs index f46520383..3a18d7d48 100644 --- a/lib/llvm-backend/src/lib.rs +++ b/lib/llvm-backend/src/lib.rs @@ -14,6 +14,7 @@ use wasmparser::{self, WasmDecoder}; mod backend; mod code; mod intrinsics; +mod platform; mod read_info; mod state; mod trampolines; diff --git a/lib/llvm-backend/src/platform/mod.rs b/lib/llvm-backend/src/platform/mod.rs index bcc0378c2..01b81b022 100644 --- a/lib/llvm-backend/src/platform/mod.rs +++ b/lib/llvm-backend/src/platform/mod.rs @@ -1,8 +1,7 @@ - -#[cfg(target_family = "unix")] +#[cfg(unix)] mod unix; -#[cfg(target_family = "unix")] +#[cfg(unix)] pub use self::unix::*; #[cfg(target_family = "windows")] -compile_error!("windows not yet supported for the llvm-based compiler backend"); \ No newline at end of file +compile_error!("windows not yet supported for the llvm-based compiler backend"); diff --git a/lib/llvm-backend/src/platform/unix.rs b/lib/llvm-backend/src/platform/unix.rs new file mode 100644 index 000000000..ee03ea08f --- /dev/null +++ b/lib/llvm-backend/src/platform/unix.rs @@ -0,0 +1,35 @@ +/// `__register_frame` and `__deregister_frame` on macos take a single fde as an +/// argument, so we need to parse the fde table here. +/// +/// This is a pretty direct port of llvm's fde handling code: +/// https://llvm.org/doxygen/RTDyldMemoryManager_8cpp_source.html. +#[cfg(target_os = "macos")] +pub unsafe fn visit_fde(addr: *mut u8, size: usize, visitor: extern "C" fn(*mut u8)) { + unsafe fn process_fde(entry: *mut u8, visitor: extern "C" fn(*mut u8)) -> *mut u8 { + let mut p = entry; + let length = (p as *const u32).read_unaligned(); + p = p.add(4); + let offset = (p as *const u32).read_unaligned(); + + if offset != 0 { + visitor(entry); + } + p.add(length as usize) + } + + let mut p = addr; + let end = p.add(size); + + loop { + if p >= end { + break; + } + + p = process_fde(p, visitor); + } +} + +#[cfg(not(target_os = "macos"))] +pub unsafe fn visit_fde(addr: *mut u8, size: usize, visitor: extern "C" fn(*mut u8)) { + visitor(addr); +} diff --git a/lib/llvm-backend/src/platform/unix/mod.rs b/lib/llvm-backend/src/platform/unix/mod.rs deleted file mode 100644 index c0e86f7ef..000000000 --- a/lib/llvm-backend/src/platform/unix/mod.rs +++ /dev/null @@ -1,40 +0,0 @@ - -extern "C" { - fn __register_frame(frame: *const u8); - fn __deregister_frame(frame: *const u8); -} - -pub unsafe fn register_eh_frames(eh_frames: *const u8, num_bytes: usize) { - visit_frame_desc_entries(eh_frames, num_bytes, |frame| __register_frame(frame)); -} - -unsafe fn visit_frame_desc_entries(eh_frames: *const u8, num_bytes: usize, visitor: F) -where - F: Fn(*const u8), -{ - let mut next = eh_frames; - let mut end = eh_frames.add(num_bytes); - - loop { - if next >= end { - break; - } - - let cfi = next; - let mut cfi_num_bytes = (next as *const u32).read_unaligned() as u64; - assert!(cfi_num_bytes != 0); - - next = next.add(4); - if num_bytes == 0xffffffff { - let cfi_num_bytes64 = (next as *const u64).read_unaligned(); - cfi_num_bytes = cfi_num_bytes64; - next = next.add(8); - } - - let cie_offset = (next as *const u32).read_unaligned(); - if cie_offset != 0 { - visitor(cfi); - } - next = next.add(cfi_num_bytes as usize); - } -} From 9a90689b931db780cb7d57eae90ed92c1050eae2 Mon Sep 17 00:00:00 2001 From: Lachlan Sneff Date: Sat, 2 Mar 2019 12:57:35 -0800 Subject: [PATCH 24/75] Add preliminary support for throwing and catching uncatchable exceptions. Additional info: - WebAssembly "traps" are uncatchable, but are still caught by the trampoline caller. --- lib/llvm-backend/cpp/object_loader.hh | 75 +++++++++++++++++++++++++++ lib/llvm-backend/src/backend.rs | 18 ++++++- lib/llvm-backend/src/code.rs | 22 +++++--- lib/llvm-backend/src/intrinsics.rs | 14 ++++- lib/runtime/examples/call.rs | 2 +- 5 files changed, 120 insertions(+), 11 deletions(-) diff --git a/lib/llvm-backend/cpp/object_loader.hh b/lib/llvm-backend/cpp/object_loader.hh index d31d33266..9a6fe5681 100644 --- a/lib/llvm-backend/cpp/object_loader.hh +++ b/lib/llvm-backend/cpp/object_loader.hh @@ -1,6 +1,9 @@ #include #include #include +#include +#include +#include typedef enum { PROTECT_NONE, @@ -24,6 +27,8 @@ typedef uintptr_t (*lookup_vm_symbol_t)(const char* name_ptr, size_t length); typedef void (*fde_visitor_t)(uint8_t *fde); typedef result_t (*visit_fde_t)(uint8_t *fde, size_t size, fde_visitor_t visitor); +typedef void (*trampoline_t)(void*, void*, void*, void*); + typedef struct { /* Memory management. */ alloc_memory_t alloc_memory; @@ -35,6 +40,59 @@ typedef struct { visit_fde_t visit_fde; } callbacks_t; +class WasmException { +public: + virtual std::string description() const noexcept = 0; +}; + +struct UncatchableException : WasmException { +public: + enum class Type { + Unreachable, + IncorrectCallIndirectSignature, + Unknown, + } type; + + UncatchableException(Type type) : type(type) {} + + virtual std::string description() const noexcept override { + std::ostringstream ss; + ss + << "Uncatchable exception:" << '\n' + << " - type: " << type << '\n'; + + return ss.str(); + } + +private: + friend std::ostream& operator<<(std::ostream& out, const Type& ty) { + switch (ty) { + case Type::Unreachable: + out << "unreachable"; + break; + case Type::IncorrectCallIndirectSignature: + out << "incorrect call_indirect signature"; + break; + case Type::Unknown: + out << "unknown"; + break; + } + return out; + } +}; + +struct CatchableException : WasmException { +public: + CatchableException(uint32_t type_id, uint32_t value_num) : type_id(type_id), value_num(value_num) {} + + virtual std::string description() const noexcept override { + return "catchable exception"; + } + + uint32_t type_id, value_num; + uint64_t values[]; +}; + class WasmModule { public: WasmModule( @@ -57,10 +115,27 @@ extern "C" { return RESULT_OK; } + void throw_unreachable_exception() { + throw UncatchableException(UncatchableException::Type::Unreachable); + } + void throw_incorrect_call_indirect_signature() { + throw UncatchableException(UncatchableException::Type::IncorrectCallIndirectSignature); + } + void module_delete(WasmModule* module) { delete module; } + void invoke_trampoline(trampoline_t trampoline, void* ctx, void* func, void* params, void* results) { + try { + trampoline(ctx, func, params, results); + } catch(const WasmException& e) { + std::cout << e.description() << std::endl; + } catch (...) { + std::cout << "unknown exception" << std::endl; + } + } + void* get_func_symbol(WasmModule* module, const char* name) { return module->get_func(llvm::StringRef(name)); } diff --git a/lib/llvm-backend/src/backend.rs b/lib/llvm-backend/src/backend.rs index 66f29cbbb..ebffd914e 100644 --- a/lib/llvm-backend/src/backend.rs +++ b/lib/llvm-backend/src/backend.rs @@ -71,6 +71,16 @@ extern "C" { ) -> LLVMResult; fn module_delete(module: *mut LLVMModule); fn get_func_symbol(module: *mut LLVMModule, name: *const c_char) -> *const vm::Func; + fn throw_unreachable_exception(); + fn throw_incorrect_call_indirect_signature(); + // invoke_trampoline(trampoline_t trampoline, void* ctx, void* func, void* params, void* results) + fn invoke_trampoline( + trampoline: unsafe extern "C" fn(*mut vm::Ctx, *const vm::Func, *const u64, *mut u64), + vmctx_ptr: *mut vm::Ctx, + func_ptr: *const vm::Func, + params: *const u64, + results: *mut u64, + ); } fn get_callbacks() -> Callbacks { @@ -162,6 +172,11 @@ fn get_callbacks() -> Callbacks { fn_name!("vm.memory.size.dynamic.local") => vmcalls::local_dynamic_memory_size as _, fn_name!("vm.memory.grow.static.local") => vmcalls::local_static_memory_grow as _, fn_name!("vm.memory.size.static.local") => vmcalls::local_static_memory_size as _, + + fn_name!("vm.exception.throw.unreachable") => throw_unreachable_exception as _, + fn_name!("vm.exception.throw.incorrect-call_indirect_signature") => { + throw_incorrect_call_indirect_signature as _ + } _ => ptr::null(), } } @@ -343,7 +358,8 @@ impl ProtectedCaller for LLVMProtectedCaller { // Here we go. unsafe { - trampoline( + invoke_trampoline( + trampoline, vmctx_ptr, func_ptr, param_vec.as_ptr(), diff --git a/lib/llvm-backend/src/code.rs b/lib/llvm-backend/src/code.rs index a9170082b..00ad353c3 100644 --- a/lib/llvm-backend/src/code.rs +++ b/lib/llvm-backend/src/code.rs @@ -539,6 +539,9 @@ fn parse_function( // Emit an unreachable instruction. // If llvm cannot prove that this is never touched, // it will emit a `ud2` instruction on x86_64 arches. + + builder.build_call(intrinsics.throw_unreachable, &[], "throw"); + ctx.build_trap(); builder.build_unreachable(); @@ -731,13 +734,12 @@ fn parse_function( ) }; - // let sigindices_equal = builder.build_int_compare( - // IntPredicate::EQ, - // expected_dynamic_sigindex, - // found_dynamic_sigindex, - // "sigindices_equal", - // ); - let sigindices_equal = intrinsics.i1_ty.const_int(1, false); + let sigindices_equal = builder.build_int_compare( + IntPredicate::EQ, + expected_dynamic_sigindex, + found_dynamic_sigindex, + "sigindices_equal", + ); // Tell llvm that `expected_dynamic_sigindex` should equal `found_dynamic_sigindex`. let sigindices_equal = builder @@ -764,7 +766,11 @@ fn parse_function( ); builder.position_at_end(&sigindices_notequal_block); - ctx.build_trap(); + builder.build_call( + intrinsics.throw_incorrect_call_indirect_signature, + &[], + "throw", + ); builder.build_unreachable(); builder.position_at_end(&continue_block); diff --git a/lib/llvm-backend/src/intrinsics.rs b/lib/llvm-backend/src/intrinsics.rs index c3f2191f3..a6f7cb02e 100644 --- a/lib/llvm-backend/src/intrinsics.rs +++ b/lib/llvm-backend/src/intrinsics.rs @@ -105,6 +105,9 @@ pub struct Intrinsics { pub memory_size_static_import: FunctionValue, pub memory_size_shared_import: FunctionValue, + pub throw_unreachable: FunctionValue, + pub throw_incorrect_call_indirect_signature: FunctionValue, + ctx_ty: StructType, pub ctx_ptr_ty: PointerType, } @@ -344,7 +347,16 @@ impl Intrinsics { ret_i32_take_ctx_i32, None, ), - + throw_unreachable: module.add_function( + "vm.exception.throw.unreachable", + void_ty.fn_type(&[], false), + None, + ), + throw_incorrect_call_indirect_signature: module.add_function( + "vm.exception.throw.incorrect-call_indirect_signature", + void_ty.fn_type(&[], false), + None, + ), ctx_ty, ctx_ptr_ty, } diff --git a/lib/runtime/examples/call.rs b/lib/runtime/examples/call.rs index ac38b8d46..0684c1bb7 100644 --- a/lib/runtime/examples/call.rs +++ b/lib/runtime/examples/call.rs @@ -6,7 +6,7 @@ static WAT: &'static str = r#" (module (type (;0;) (func (param i32) (result i32))) (func (;0;) (type 0) (param i32) (result i32) - i32.const 42) + unreachable) (export "select_trap_l" (func 0)) ) "#; From 57bfa9b0a4c4b680a7c87e5632f7f640ea5c3e14 Mon Sep 17 00:00:00 2001 From: Lachlan Sneff Date: Sat, 2 Mar 2019 14:16:02 -0800 Subject: [PATCH 25/75] Remove multiple throwing functions, just use one. --- lib/llvm-backend/cpp/object_loader.hh | 50 +++++++++++++++++++-------- lib/llvm-backend/src/backend.rs | 12 +++---- lib/llvm-backend/src/code.rs | 12 ++++--- lib/llvm-backend/src/intrinsics.rs | 22 ++++++------ 4 files changed, 60 insertions(+), 36 deletions(-) diff --git a/lib/llvm-backend/cpp/object_loader.hh b/lib/llvm-backend/cpp/object_loader.hh index 9a6fe5681..33724a868 100644 --- a/lib/llvm-backend/cpp/object_loader.hh +++ b/lib/llvm-backend/cpp/object_loader.hh @@ -40,30 +40,51 @@ typedef struct { visit_fde_t visit_fde; } callbacks_t; -class WasmException { +struct WasmException { public: virtual std::string description() const noexcept = 0; }; struct UncatchableException : WasmException { public: - enum class Type { - Unreachable, - IncorrectCallIndirectSignature, - Unknown, - } type; + virtual std::string description() const noexcept override { + return "Uncatchable exception"; + } +}; - UncatchableException(Type type) : type(type) {} +struct UserException : UncatchableException { +public: + UserException(std::string msg) : msg(msg) {} + + virtual std::string description() const noexcept override { + return std::string("user exception: ") + msg; + } +private: + std::string msg; +}; + +struct WasmTrap : UncatchableException { +public: + enum Type { + Unreachable = 0, + IncorrectCallIndirectSignature = 1, + MemoryOutOfBounds = 2, + Unknown, + }; + + WasmTrap(Type type) : type(type) {} virtual std::string description() const noexcept override { std::ostringstream ss; ss - << "Uncatchable exception:" << '\n' + << "WebAssembly trap:" << '\n' << " - type: " << type << '\n'; return ss.str(); } + Type type; + private: friend std::ostream& operator<<(std::ostream& out, const Type& ty) { switch (ty) { @@ -73,7 +94,11 @@ private: case Type::IncorrectCallIndirectSignature: out << "incorrect call_indirect signature"; break; + case Type::MemoryOutOfBounds: + out << "memory access out-of-bounds"; + break; case Type::Unknown: + default: out << "unknown"; break; } @@ -93,7 +118,7 @@ public: uint64_t values[]; }; -class WasmModule { +struct WasmModule { public: WasmModule( const uint8_t *object_start, @@ -115,11 +140,8 @@ extern "C" { return RESULT_OK; } - void throw_unreachable_exception() { - throw UncatchableException(UncatchableException::Type::Unreachable); - } - void throw_incorrect_call_indirect_signature() { - throw UncatchableException(UncatchableException::Type::IncorrectCallIndirectSignature); + void throw_trap(WasmTrap::Type ty) { + throw WasmTrap(ty); } void module_delete(WasmModule* module) { diff --git a/lib/llvm-backend/src/backend.rs b/lib/llvm-backend/src/backend.rs index ebffd914e..e7e641aa9 100644 --- a/lib/llvm-backend/src/backend.rs +++ b/lib/llvm-backend/src/backend.rs @@ -71,9 +71,9 @@ extern "C" { ) -> LLVMResult; fn module_delete(module: *mut LLVMModule); fn get_func_symbol(module: *mut LLVMModule, name: *const c_char) -> *const vm::Func; - fn throw_unreachable_exception(); - fn throw_incorrect_call_indirect_signature(); - // invoke_trampoline(trampoline_t trampoline, void* ctx, void* func, void* params, void* results) + + fn throw_trap(ty: i32); + fn invoke_trampoline( trampoline: unsafe extern "C" fn(*mut vm::Ctx, *const vm::Func, *const u64, *mut u64), vmctx_ptr: *mut vm::Ctx, @@ -173,10 +173,8 @@ fn get_callbacks() -> Callbacks { fn_name!("vm.memory.grow.static.local") => vmcalls::local_static_memory_grow as _, fn_name!("vm.memory.size.static.local") => vmcalls::local_static_memory_size as _, - fn_name!("vm.exception.throw.unreachable") => throw_unreachable_exception as _, - fn_name!("vm.exception.throw.incorrect-call_indirect_signature") => { - throw_incorrect_call_indirect_signature as _ - } + fn_name!("vm.exception.trap") => throw_trap as _, + _ => ptr::null(), } } diff --git a/lib/llvm-backend/src/code.rs b/lib/llvm-backend/src/code.rs index 00ad353c3..eba8fdd7d 100644 --- a/lib/llvm-backend/src/code.rs +++ b/lib/llvm-backend/src/code.rs @@ -540,9 +540,11 @@ fn parse_function( // If llvm cannot prove that this is never touched, // it will emit a `ud2` instruction on x86_64 arches. - builder.build_call(intrinsics.throw_unreachable, &[], "throw"); - - ctx.build_trap(); + builder.build_call( + intrinsics.throw_trap, + &[intrinsics.trap_unreachable], + "throw", + ); builder.build_unreachable(); state.reachable = false; @@ -767,8 +769,8 @@ fn parse_function( builder.position_at_end(&sigindices_notequal_block); builder.build_call( - intrinsics.throw_incorrect_call_indirect_signature, - &[], + intrinsics.throw_trap, + &[intrinsics.trap_call_indirect_sig], "throw", ); builder.build_unreachable(); diff --git a/lib/llvm-backend/src/intrinsics.rs b/lib/llvm-backend/src/intrinsics.rs index a6f7cb02e..152047b84 100644 --- a/lib/llvm-backend/src/intrinsics.rs +++ b/lib/llvm-backend/src/intrinsics.rs @@ -90,6 +90,10 @@ pub struct Intrinsics { pub f32_zero: FloatValue, pub f64_zero: FloatValue, + pub trap_unreachable: BasicValueEnum, + pub trap_call_indirect_sig: BasicValueEnum, + pub trap_memory_oob: BasicValueEnum, + // VM intrinsics. pub memory_grow_dynamic_local: FunctionValue, pub memory_grow_static_local: FunctionValue, @@ -105,8 +109,7 @@ pub struct Intrinsics { pub memory_size_static_import: FunctionValue, pub memory_size_shared_import: FunctionValue, - pub throw_unreachable: FunctionValue, - pub throw_incorrect_call_indirect_signature: FunctionValue, + pub throw_trap: FunctionValue, ctx_ty: StructType, pub ctx_ptr_ty: PointerType, @@ -285,6 +288,10 @@ impl Intrinsics { f32_zero, f64_zero, + trap_unreachable: i32_zero.as_basic_value_enum(), + trap_call_indirect_sig: i32_ty.const_int(1, false).as_basic_value_enum(), + trap_memory_oob: i32_ty.const_int(2, false).as_basic_value_enum(), + // VM intrinsics. memory_grow_dynamic_local: module.add_function( "vm.memory.grow.dynamic.local", @@ -347,14 +354,9 @@ impl Intrinsics { ret_i32_take_ctx_i32, None, ), - throw_unreachable: module.add_function( - "vm.exception.throw.unreachable", - void_ty.fn_type(&[], false), - None, - ), - throw_incorrect_call_indirect_signature: module.add_function( - "vm.exception.throw.incorrect-call_indirect_signature", - void_ty.fn_type(&[], false), + throw_trap: module.add_function( + "vm.exception.trap", + void_ty.fn_type(&[i32_ty_basic], false), None, ), ctx_ty, From caf2205936f677bca62be83fcf62ed069fecc2c0 Mon Sep 17 00:00:00 2001 From: Lachlan Sneff Date: Sat, 2 Mar 2019 17:00:05 -0800 Subject: [PATCH 26/75] Add a signal handler for macos and linux. Implementation Notes: - To avoid setjmp, longjmp, and the mess that those create, we instead set the interrupting context of the signal handler to return into the `throw_trap` routine. To my surprise, this actually works. The stack ends up getting unwound normally and the memory-oob error is caught by the trampoline. --- Cargo.lock | 1 + lib/llvm-backend/Cargo.toml | 1 + lib/llvm-backend/cpp/object_loader.hh | 4 +- lib/llvm-backend/src/backend.rs | 4 + lib/llvm-backend/src/platform/unix.rs | 106 ++++++++++++++++++++++++++ lib/runtime/examples/call.rs | 5 +- 6 files changed, 118 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f06c9e940..a31fa0a7d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1213,6 +1213,7 @@ dependencies = [ "inkwell 0.1.0 (git+https://github.com/TheDan64/inkwell?branch=llvm7-0)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "nix 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/lib/llvm-backend/Cargo.toml b/lib/llvm-backend/Cargo.toml index 81301872b..f350b263e 100644 --- a/lib/llvm-backend/Cargo.toml +++ b/lib/llvm-backend/Cargo.toml @@ -12,6 +12,7 @@ hashbrown = "0.1.8" smallvec = "0.6.8" goblin = "0.0.20" libc = "0.2.49" +nix = "0.13.0" capstone = "0.5.0" [build-dependencies] diff --git a/lib/llvm-backend/cpp/object_loader.hh b/lib/llvm-backend/cpp/object_loader.hh index 33724a868..9d51d686c 100644 --- a/lib/llvm-backend/cpp/object_loader.hh +++ b/lib/llvm-backend/cpp/object_loader.hh @@ -115,7 +115,7 @@ public: } uint32_t type_id, value_num; - uint64_t values[]; + uint64_t values[1]; }; struct WasmModule { @@ -140,7 +140,7 @@ extern "C" { return RESULT_OK; } - void throw_trap(WasmTrap::Type ty) { + [[noreturn]] void throw_trap(WasmTrap::Type ty) { throw WasmTrap(ty); } diff --git a/lib/llvm-backend/src/backend.rs b/lib/llvm-backend/src/backend.rs index e7e641aa9..792a10422 100644 --- a/lib/llvm-backend/src/backend.rs +++ b/lib/llvm-backend/src/backend.rs @@ -243,6 +243,10 @@ impl LLVMBackend { ) }; + unsafe { + crate::platform::install_signal_handler(); + } + if res != LLVMResult::OK { panic!("failed to load object") } diff --git a/lib/llvm-backend/src/platform/unix.rs b/lib/llvm-backend/src/platform/unix.rs index ee03ea08f..7db0d0110 100644 --- a/lib/llvm-backend/src/platform/unix.rs +++ b/lib/llvm-backend/src/platform/unix.rs @@ -1,3 +1,8 @@ +use libc::{c_void, siginfo_t}; +use nix::sys::signal::{ + sigaction, SaFlags, SigAction, SigHandler, SigSet, Signal, SIGBUS, SIGFPE, SIGILL, SIGSEGV, +}; + /// `__register_frame` and `__deregister_frame` on macos take a single fde as an /// argument, so we need to parse the fde table here. /// @@ -33,3 +38,104 @@ pub unsafe fn visit_fde(addr: *mut u8, size: usize, visitor: extern "C" fn(*mut pub unsafe fn visit_fde(addr: *mut u8, size: usize, visitor: extern "C" fn(*mut u8)) { visitor(addr); } + +extern "C" { + fn throw_trap(ty: i32) -> !; +} + +pub unsafe fn install_signal_handler() { + let sa = SigAction::new( + SigHandler::SigAction(signal_trap_handler), + SaFlags::SA_ONSTACK, + SigSet::empty(), + ); + sigaction(SIGFPE, &sa).unwrap(); + sigaction(SIGILL, &sa).unwrap(); + sigaction(SIGSEGV, &sa).unwrap(); + sigaction(SIGBUS, &sa).unwrap(); +} + +extern "C" fn signal_trap_handler( + signum: ::nix::libc::c_int, + siginfo: *mut siginfo_t, + ucontext: *mut c_void, +) { + unsafe { + /// By setting the instruction pointer of the interrupted context + /// to `throw_trap` and the register of the first argument + /// to the trap ID, we can approximate throwing an exception + /// from a signal handler. + set_context_to_throw(ucontext); + } +} + +#[cfg(all(target_os = "linux", target_arch = "x86_64"))] +unsafe fn set_context_to_throw(ucontext: *mut c_void) { + use libc::{ucontext_t, RDI, RIP}; + + let ucontext = ucontext as *mut ucontext_t; + (*ucontext).uc_mcontext.gregs[RIP as usize] = throw_trap as u64; + (*ucontext).uc_mcontext.gregs[RDI as usize] = 2; // `MemoryOutOfBounds` variant. +} + +#[cfg(all(target_os = "macos", target_arch = "x86_64"))] +unsafe fn set_context_to_throw(ucontext: *mut c_void) { + #[allow(dead_code)] + #[repr(C)] + struct ucontext_t { + uc_onstack: u32, + uc_sigmask: u32, + uc_stack: libc::stack_t, + uc_link: *const ucontext_t, + uc_mcsize: u64, + uc_mcontext: *mut mcontext_t, + } + #[repr(C)] + struct exception_state { + trapno: u16, + cpu: u16, + err: u32, + faultvaddr: u64, + } + #[repr(C)] + struct regs { + rax: u64, + rbx: u64, + rcx: u64, + rdx: u64, + rdi: u64, + rsi: u64, + rbp: u64, + rsp: u64, + r8: u64, + r9: u64, + r10: u64, + r11: u64, + r12: u64, + r13: u64, + r14: u64, + r15: u64, + rip: u64, + rflags: u64, + cs: u64, + fs: u64, + gs: u64, + } + #[allow(dead_code)] + #[repr(C)] + struct mcontext_t { + es: exception_state, + ss: regs, + // ... + } + + let ucontext = ucontext as *mut ucontext_t; + (*(*ucontext).uc_mcontext).ss.rip = throw_trap as u64; + (*(*ucontext).uc_mcontext).ss.rdi = 2; // `MemoryOutOfBounds` variant. +} + +#[cfg(not(any( + all(target_os = "macos", target_arch = "x86_64"), + all(target_os = "linux", target_arch = "x86_64"), +)))] +compile_error!("This crate doesn't yet support compiling on operating systems other than linux and macos and architectures other than x86_64"); diff --git a/lib/runtime/examples/call.rs b/lib/runtime/examples/call.rs index 0684c1bb7..2a11db9e8 100644 --- a/lib/runtime/examples/call.rs +++ b/lib/runtime/examples/call.rs @@ -4,9 +4,12 @@ use wabt::wat2wasm; static WAT: &'static str = r#" (module + (memory 1) (type (;0;) (func (param i32) (result i32))) (func (;0;) (type 0) (param i32) (result i32) - unreachable) + i32.const 0x20000 + i32.load + ) (export "select_trap_l" (func 0)) ) "#; From 9cfda6800ff3493bd267e4a822fb949915b83325 Mon Sep 17 00:00:00 2001 From: Lachlan Sneff Date: Sat, 2 Mar 2019 19:08:15 -0800 Subject: [PATCH 27/75] Try to return an error from call_protected when an exception occurs. Something breaks pretty drastically sometimes, not sure why. --- lib/llvm-backend/cpp/object_loader.hh | 22 ++++++++- lib/llvm-backend/src/backend.rs | 65 ++++++++++++++++++++------- lib/llvm-backend/src/code.rs | 2 - lib/llvm-backend/src/platform/unix.rs | 2 +- lib/runtime/examples/call.rs | 37 ++++++++++----- 5 files changed, 98 insertions(+), 30 deletions(-) diff --git a/lib/llvm-backend/cpp/object_loader.hh b/lib/llvm-backend/cpp/object_loader.hh index 9d51d686c..cb1b48554 100644 --- a/lib/llvm-backend/cpp/object_loader.hh +++ b/lib/llvm-backend/cpp/object_loader.hh @@ -141,6 +141,7 @@ extern "C" { } [[noreturn]] void throw_trap(WasmTrap::Type ty) { + std::cout << "throwing trap: " << ty << std::endl; throw WasmTrap(ty); } @@ -148,13 +149,30 @@ extern "C" { delete module; } - void invoke_trampoline(trampoline_t trampoline, void* ctx, void* func, void* params, void* results) { + bool invoke_trampoline( + trampoline_t trampoline, + void* ctx, + void* func, + void* params, + void* results, + WasmTrap::Type* trap_out + ) throw() { try { trampoline(ctx, func, params, results); + std::cout << "Success" << std::endl; + return true; + } catch(const WasmTrap& e) { + std::cout << e.description() << std::endl; + *trap_out = e.type; + return false; } catch(const WasmException& e) { std::cout << e.description() << std::endl; + *trap_out = WasmTrap::Type::Unknown; + return false; } catch (...) { - std::cout << "unknown exception" << std::endl; + std::cout << "unknown" << std::endl; + *trap_out = WasmTrap::Type::Unknown; + return false; } } diff --git a/lib/llvm-backend/src/backend.rs b/lib/llvm-backend/src/backend.rs index 792a10422..2d67d7a9b 100644 --- a/lib/llvm-backend/src/backend.rs +++ b/lib/llvm-backend/src/backend.rs @@ -17,11 +17,14 @@ use std::{ }; use wasmer_runtime_core::{ backend::{FuncResolver, ProtectedCaller, Token, UserTrapper}, - error::RuntimeResult, + error::{RuntimeError, RuntimeResult}, export::Context, module::{ModuleInfo, ModuleInner}, structures::TypedIndex, - types::{FuncIndex, FuncSig, LocalFuncIndex, LocalOrImport, SigIndex, Type, Value}, + types::{ + FuncIndex, FuncSig, LocalFuncIndex, LocalOrImport, MemoryIndex, SigIndex, TableIndex, Type, + Value, + }, vm::{self, ImportBacking}, vmcalls, }; @@ -52,6 +55,14 @@ enum LLVMResult { OBJECT_LOAD_FAILURE, } +#[repr(C)] +enum WasmTrapType { + Unreachable = 0, + IncorrectCallIndirectSignature = 1, + MemoryOutOfBounds = 2, + Unknown, +} + #[repr(C)] struct Callbacks { alloc_memory: extern "C" fn(usize, MemProtect, &mut *mut u8, &mut usize) -> LLVMResult, @@ -80,7 +91,8 @@ extern "C" { func_ptr: *const vm::Func, params: *const u64, results: *mut u64, - ); + trap_out: *mut WasmTrapType, + ) -> bool; } fn get_callbacks() -> Callbacks { @@ -358,27 +370,50 @@ impl ProtectedCaller for LLVMProtectedCaller { mem::transmute(symbol) }; + let mut trap_out = WasmTrapType::Unknown; + // Here we go. - unsafe { + let success = unsafe { invoke_trampoline( trampoline, vmctx_ptr, func_ptr, param_vec.as_ptr(), return_vec.as_mut_ptr(), - ); - } + &mut trap_out, + ) + }; - Ok(return_vec - .iter() - .zip(signature.returns().iter()) - .map(|(&x, ty)| match ty { - Type::I32 => Value::I32(x as i32), - Type::I64 => Value::I64(x as i64), - Type::F32 => Value::F32(f32::from_bits(x as u32)), - Type::F64 => Value::F64(f64::from_bits(x as u64)), + if success { + Ok(return_vec + .iter() + .zip(signature.returns().iter()) + .map(|(&x, ty)| match ty { + Type::I32 => Value::I32(x as i32), + Type::I64 => Value::I64(x as i64), + Type::F32 => Value::F32(f32::from_bits(x as u32)), + Type::F64 => Value::F64(f64::from_bits(x as u64)), + }) + .collect()) + } else { + Err(match trap_out { + WasmTrapType::Unreachable => RuntimeError::User { + msg: "unreachable".into(), + }, + WasmTrapType::IncorrectCallIndirectSignature => { + RuntimeError::IndirectCallSignature { + table: TableIndex::new(0), + } + } + WasmTrapType::MemoryOutOfBounds => RuntimeError::OutOfBoundsAccess { + memory: MemoryIndex::new(0), + addr: None, + }, + WasmTrapType::Unknown => RuntimeError::Unknown { + msg: "unknown error".into(), + }, }) - .collect()) + } } fn get_early_trapper(&self) -> Box { diff --git a/lib/llvm-backend/src/code.rs b/lib/llvm-backend/src/code.rs index eba8fdd7d..01fb09a20 100644 --- a/lib/llvm-backend/src/code.rs +++ b/lib/llvm-backend/src/code.rs @@ -118,8 +118,6 @@ pub fn parse_function_bodies( })?; } - module.print_to_stderr(); - generate_trampolines(info, &signatures, &module, &context, &builder, &intrinsics); let pass_manager = PassManager::create_for_module(); diff --git a/lib/llvm-backend/src/platform/unix.rs b/lib/llvm-backend/src/platform/unix.rs index 7db0d0110..6b6f8356e 100644 --- a/lib/llvm-backend/src/platform/unix.rs +++ b/lib/llvm-backend/src/platform/unix.rs @@ -46,7 +46,7 @@ extern "C" { pub unsafe fn install_signal_handler() { let sa = SigAction::new( SigHandler::SigAction(signal_trap_handler), - SaFlags::SA_ONSTACK, + SaFlags::SA_ONSTACK | SaFlags::SA_SIGINFO, SigSet::empty(), ); sigaction(SIGFPE, &sa).unwrap(); diff --git a/lib/runtime/examples/call.rs b/lib/runtime/examples/call.rs index 2a11db9e8..e9ac58acc 100644 --- a/lib/runtime/examples/call.rs +++ b/lib/runtime/examples/call.rs @@ -4,14 +4,31 @@ use wabt::wat2wasm; static WAT: &'static str = r#" (module - (memory 1) - (type (;0;) (func (param i32) (result i32))) - (func (;0;) (type 0) (param i32) (result i32) - i32.const 0x20000 - i32.load - ) - (export "select_trap_l" (func 0)) - ) + (type (;0;) (func (result i32))) + (type (;1;) (func (param i32 i32))) + (type (;2;) (func (param i32) (result i32))) + (func (;0;) (type 0) (result i32) + memory.size + i32.const 65536 + i32.mul) + (func (;1;) (type 1) (param i32 i32) + call 0 + local.get 0 + i32.sub + local.get 1 + i32.store) + (func (;2;) (type 2) (param i32) (result i32) + call 0 + local.get 0 + i32.add + i32.load) + (func (;3;) (type 2) (param i32) (result i32) + local.get 0 + memory.grow) + (memory (;0;) 1 2) + (export "store" (func 1)) + (export "load" (func 2)) + (export "memory.grow" (func 3))) "#; fn get_wasm() -> Vec { @@ -28,9 +45,9 @@ fn main() -> Result<(), error::Error> { println!("instantiating"); let instance = module.instantiate(&imports)?; - let foo = instance.dyn_func("select_trap_l")?; + let foo = instance.dyn_func("store")?; - let result = foo.call(&[Value::I32(0)]); + let result = foo.call(&[Value::I32(0), Value::I32(1)]); println!("result: {:?}", result); From e362b56b07a336bc726d17da5d87f61341cc1bb2 Mon Sep 17 00:00:00 2001 From: Lachlan Sneff Date: Sun, 3 Mar 2019 02:15:53 -0800 Subject: [PATCH 28/75] Turns out we can just throw an exception from the signal handler without any fancy tricks. This has been tested on macos, hopefully it works on linux too. --- lib/llvm-backend/src/platform/unix.rs | 82 ++------------------------- 1 file changed, 6 insertions(+), 76 deletions(-) diff --git a/lib/llvm-backend/src/platform/unix.rs b/lib/llvm-backend/src/platform/unix.rs index 6b6f8356e..585797b0a 100644 --- a/lib/llvm-backend/src/platform/unix.rs +++ b/lib/llvm-backend/src/platform/unix.rs @@ -61,81 +61,11 @@ extern "C" fn signal_trap_handler( ucontext: *mut c_void, ) { unsafe { - /// By setting the instruction pointer of the interrupted context - /// to `throw_trap` and the register of the first argument - /// to the trap ID, we can approximate throwing an exception - /// from a signal handler. - set_context_to_throw(ucontext); + /// Apparently, we can unwind from arbitary instructions, as long + /// as we don't need to catch the exception inside the function that + /// was interrupted. + /// + /// This works on macos, not sure about linux. + throw_trap(2); } } - -#[cfg(all(target_os = "linux", target_arch = "x86_64"))] -unsafe fn set_context_to_throw(ucontext: *mut c_void) { - use libc::{ucontext_t, RDI, RIP}; - - let ucontext = ucontext as *mut ucontext_t; - (*ucontext).uc_mcontext.gregs[RIP as usize] = throw_trap as u64; - (*ucontext).uc_mcontext.gregs[RDI as usize] = 2; // `MemoryOutOfBounds` variant. -} - -#[cfg(all(target_os = "macos", target_arch = "x86_64"))] -unsafe fn set_context_to_throw(ucontext: *mut c_void) { - #[allow(dead_code)] - #[repr(C)] - struct ucontext_t { - uc_onstack: u32, - uc_sigmask: u32, - uc_stack: libc::stack_t, - uc_link: *const ucontext_t, - uc_mcsize: u64, - uc_mcontext: *mut mcontext_t, - } - #[repr(C)] - struct exception_state { - trapno: u16, - cpu: u16, - err: u32, - faultvaddr: u64, - } - #[repr(C)] - struct regs { - rax: u64, - rbx: u64, - rcx: u64, - rdx: u64, - rdi: u64, - rsi: u64, - rbp: u64, - rsp: u64, - r8: u64, - r9: u64, - r10: u64, - r11: u64, - r12: u64, - r13: u64, - r14: u64, - r15: u64, - rip: u64, - rflags: u64, - cs: u64, - fs: u64, - gs: u64, - } - #[allow(dead_code)] - #[repr(C)] - struct mcontext_t { - es: exception_state, - ss: regs, - // ... - } - - let ucontext = ucontext as *mut ucontext_t; - (*(*ucontext).uc_mcontext).ss.rip = throw_trap as u64; - (*(*ucontext).uc_mcontext).ss.rdi = 2; // `MemoryOutOfBounds` variant. -} - -#[cfg(not(any( - all(target_os = "macos", target_arch = "x86_64"), - all(target_os = "linux", target_arch = "x86_64"), -)))] -compile_error!("This crate doesn't yet support compiling on operating systems other than linux and macos and architectures other than x86_64"); From 2c765c87c5b62fba3d28c842515a0b7b54b15aef Mon Sep 17 00:00:00 2001 From: Brandon Fish Date: Sun, 3 Mar 2019 12:55:29 -0600 Subject: [PATCH 29/75] Update locals reading to use count --- lib/llvm-backend/src/code.rs | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/lib/llvm-backend/src/code.rs b/lib/llvm-backend/src/code.rs index 01fb09a20..355a6d830 100644 --- a/lib/llvm-backend/src/code.rs +++ b/lib/llvm-backend/src/code.rs @@ -172,7 +172,8 @@ fn parse_function( let mut ctx = intrinsics.ctx(info, builder, &function); - let mut locals = Vec::with_capacity(locals_reader.get_count() as usize); + let mut locals = Vec::with_capacity(locals_reader.get_count() as usize); // TODO fix capacity + locals.extend( function .get_param_iter() @@ -189,15 +190,12 @@ fn parse_function( let param_len = locals.len(); + let mut local_idx = 0; for (index, local) in locals_reader.into_iter().enumerate() { - let (_, ty) = local?; - + let (count, ty) = local?; let wasmer_ty = type_to_type(ty)?; - let ty = type_to_llvm(intrinsics, wasmer_ty); - let alloca = builder.build_alloca(ty, &format!("local{}", param_len + index)); - let default_value = match wasmer_ty { Type::I32 => intrinsics.i32_zero.as_basic_value_enum(), Type::I64 => intrinsics.i64_zero.as_basic_value_enum(), @@ -205,9 +203,14 @@ fn parse_function( Type::F64 => intrinsics.f64_zero.as_basic_value_enum(), }; - builder.build_store(alloca, default_value); + for _ in 0..count { + let alloca = builder.build_alloca(ty, &format!("local{}", param_len + local_idx)); - locals.push(alloca); + builder.build_store(alloca, default_value); + + locals.push(alloca); + local_idx += 1; + } } let mut unreachable_depth = 0; From 97a70327d063f171034e3aa99c58aae9612ffb45 Mon Sep 17 00:00:00 2001 From: Brandon Fish Date: Sun, 3 Mar 2019 15:13:20 -0600 Subject: [PATCH 30/75] Fix compilation of test example --- lib/llvm-backend/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/llvm-backend/src/lib.rs b/lib/llvm-backend/src/lib.rs index 3a18d7d48..b1ddc1f18 100644 --- a/lib/llvm-backend/src/lib.rs +++ b/lib/llvm-backend/src/lib.rs @@ -111,7 +111,7 @@ fn test_read_module() { let (module, intrinsics) = code::parse_function_bodies(&info, code_reader).unwrap(); - let backend = backend::LLVMBackend::new(module, intrinsics); + let (backend, _caller) = backend::LLVMBackend::new(module, intrinsics); let func_ptr = backend.get_func(&info, LocalFuncIndex::new(0)).unwrap(); From 3f345b41c2c29825f7055b304d3ac41f89a78df4 Mon Sep 17 00:00:00 2001 From: Brandon Fish Date: Sun, 3 Mar 2019 15:18:16 -0600 Subject: [PATCH 31/75] Fix emscripten lib compilation --- lib/emscripten/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/emscripten/src/lib.rs b/lib/emscripten/src/lib.rs index 5a7f008f1..4f3fa0d3d 100644 --- a/lib/emscripten/src/lib.rs +++ b/lib/emscripten/src/lib.rs @@ -341,7 +341,7 @@ impl EmscriptenGlobals { if name == "abortOnCannotGrowMemory" && namespace == "env" { let sig_index = module.info().func_assoc[index.convert_up(module.info())]; let expected_sig = &module.info().signatures[sig_index]; - if **expected_sig == *OLD_ABORT_ON_CANNOT_GROW_MEMORY_SIG { + if *expected_sig == *OLD_ABORT_ON_CANNOT_GROW_MEMORY_SIG { use_old_abort_on_cannot_grow_memory = true; } break; From aae256b4074cc147b8559653612acf0ce2f96b0c Mon Sep 17 00:00:00 2001 From: Brandon Fish Date: Sun, 3 Mar 2019 15:34:20 -0600 Subject: [PATCH 32/75] Add tag to fix cast ptr lint error --- lib/llvm-backend/src/platform/unix.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/llvm-backend/src/platform/unix.rs b/lib/llvm-backend/src/platform/unix.rs index 585797b0a..c17f56359 100644 --- a/lib/llvm-backend/src/platform/unix.rs +++ b/lib/llvm-backend/src/platform/unix.rs @@ -8,6 +8,7 @@ use nix::sys::signal::{ /// /// This is a pretty direct port of llvm's fde handling code: /// https://llvm.org/doxygen/RTDyldMemoryManager_8cpp_source.html. +#[allow(clippy::cast_ptr_alignment)] #[cfg(target_os = "macos")] pub unsafe fn visit_fde(addr: *mut u8, size: usize, visitor: extern "C" fn(*mut u8)) { unsafe fn process_fde(entry: *mut u8, visitor: extern "C" fn(*mut u8)) -> *mut u8 { From c07298e58eb8804bfe7b412a6dfd7ea732a54e9a Mon Sep 17 00:00:00 2001 From: Brandon Fish Date: Sun, 3 Mar 2019 16:02:20 -0600 Subject: [PATCH 33/75] Make capstone optional with a feature --- lib/llvm-backend/Cargo.toml | 5 +++-- lib/llvm-backend/src/backend.rs | 1 + 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/llvm-backend/Cargo.toml b/lib/llvm-backend/Cargo.toml index f350b263e..cdbfe63bf 100644 --- a/lib/llvm-backend/Cargo.toml +++ b/lib/llvm-backend/Cargo.toml @@ -13,7 +13,7 @@ smallvec = "0.6.8" goblin = "0.0.20" libc = "0.2.49" nix = "0.13.0" -capstone = "0.5.0" +capstone = { version = "0.5.0", optional = true } [build-dependencies] cc = "1.0" @@ -25,4 +25,5 @@ semver = "0.9" wabt = "0.7.4" [features] -debug = ["wasmer-runtime-core/debug"] \ No newline at end of file +debug = ["wasmer-runtime-core/debug"] +disasm = ["capstone"] \ No newline at end of file diff --git a/lib/llvm-backend/src/backend.rs b/lib/llvm-backend/src/backend.rs index 2d67d7a9b..f08f0fd84 100644 --- a/lib/llvm-backend/src/backend.rs +++ b/lib/llvm-backend/src/backend.rs @@ -462,6 +462,7 @@ fn get_func_from_index<'a>( (func_ptr, ctx, signature, sig_index) } +#[cfg(feature = "disasm")] unsafe fn disass_ptr(ptr: *const u8, size: usize, inst_count: usize) { use capstone::arch::BuildsCapstone; let mut cs = capstone::Capstone::new() // Call builder-pattern From 51cf9dde058778fa748f2d966f91f2f8261a6b63 Mon Sep 17 00:00:00 2001 From: Lachlan Sneff Date: Sun, 3 Mar 2019 21:13:37 -0800 Subject: [PATCH 34/75] Move SSA value caches to the entry block. The supporting framework around LLVM will make sure to only compute values once if they are known to never change. Previously, these values were attempted to be reused from places where the users may not dominate the creation of the value. To avoid that, they are always created in the entry block now. --- lib/llvm-backend/cpp/object_loader.hh | 4 - lib/llvm-backend/src/code.rs | 11 ++- lib/llvm-backend/src/intrinsics.rs | 133 +++++++++++++++++--------- 3 files changed, 99 insertions(+), 49 deletions(-) diff --git a/lib/llvm-backend/cpp/object_loader.hh b/lib/llvm-backend/cpp/object_loader.hh index cb1b48554..67a2f5740 100644 --- a/lib/llvm-backend/cpp/object_loader.hh +++ b/lib/llvm-backend/cpp/object_loader.hh @@ -159,18 +159,14 @@ extern "C" { ) throw() { try { trampoline(ctx, func, params, results); - std::cout << "Success" << std::endl; return true; } catch(const WasmTrap& e) { - std::cout << e.description() << std::endl; *trap_out = e.type; return false; } catch(const WasmException& e) { - std::cout << e.description() << std::endl; *trap_out = WasmTrap::Type::Unknown; return false; } catch (...) { - std::cout << "unknown" << std::endl; *trap_out = WasmTrap::Type::Unknown; return false; } diff --git a/lib/llvm-backend/src/code.rs b/lib/llvm-backend/src/code.rs index 355a6d830..46ddffa41 100644 --- a/lib/llvm-backend/src/code.rs +++ b/lib/llvm-backend/src/code.rs @@ -118,6 +118,8 @@ pub fn parse_function_bodies( })?; } + // module.print_to_stderr(); + generate_trampolines(info, &signatures, &module, &context, &builder, &intrinsics); let pass_manager = PassManager::create_for_module(); @@ -170,8 +172,6 @@ fn parse_function( state.push_block(return_block, phis); builder.position_at_end(&entry_block); - let mut ctx = intrinsics.ctx(info, builder, &function); - let mut locals = Vec::with_capacity(locals_reader.get_count() as usize); // TODO fix capacity locals.extend( @@ -213,6 +213,13 @@ fn parse_function( } } + let start_of_code_block = context.append_basic_block(&function, "start_of_code"); + let entry_end_inst = builder.build_unconditional_branch(&start_of_code_block); + builder.position_at_end(&start_of_code_block); + + let cache_builder = context.create_builder(); + cache_builder.position_before(&entry_end_inst); + let mut ctx = intrinsics.ctx(info, builder, &function, cache_builder); let mut unreachable_depth = 0; for op in op_reader { diff --git a/lib/llvm-backend/src/intrinsics.rs b/lib/llvm-backend/src/intrinsics.rs index 152047b84..908448a51 100644 --- a/lib/llvm-backend/src/intrinsics.rs +++ b/lib/llvm-backend/src/intrinsics.rs @@ -4,7 +4,10 @@ use inkwell::{ context::Context, module::Module, types::{BasicType, FloatType, IntType, PointerType, StructType, VoidType}, - values::{BasicValue, BasicValueEnum, FloatValue, FunctionValue, IntValue, PointerValue}, + values::{ + BasicValue, BasicValueEnum, FloatValue, FunctionValue, InstructionValue, IntValue, + PointerValue, + }, AddressSpace, }; use std::marker::PhantomData; @@ -369,6 +372,7 @@ impl Intrinsics { info: &'a ModuleInfo, builder: &'a Builder, func_value: &'a FunctionValue, + cache_builder: Builder, ) -> CtxType<'a> { CtxType { ctx_ty: self.ctx_ty, @@ -379,6 +383,7 @@ impl Intrinsics { builder, intrinsics: self, info, + cache_builder, cached_memories: HashMap::new(), cached_tables: HashMap::new(), @@ -429,6 +434,7 @@ pub struct CtxType<'a> { builder: &'a Builder, intrinsics: &'a Intrinsics, info: &'a ModuleInfo, + cache_builder: Builder, cached_memories: HashMap, cached_tables: HashMap, @@ -445,43 +451,52 @@ impl<'a> CtxType<'a> { } pub fn memory(&mut self, index: MemoryIndex) -> (PointerValue, IntValue) { - let (cached_memories, builder, info, ctx_ptr_value, intrinsics) = ( + let (cached_memories, builder, info, ctx_ptr_value, intrinsics, cache_builder) = ( &mut self.cached_memories, self.builder, self.info, self.ctx_ptr_value, self.intrinsics, + &self.cache_builder, ); let memory_cache = cached_memories.entry(index).or_insert_with(|| { let (memory_array_ptr_ptr, index, memory_type) = match index.local_or_import(info) { LocalOrImport::Local(local_mem_index) => ( - unsafe { builder.build_struct_gep(ctx_ptr_value, 0, "memory_array_ptr_ptr") }, + unsafe { + cache_builder.build_struct_gep(ctx_ptr_value, 0, "memory_array_ptr_ptr") + }, local_mem_index.index() as u64, info.memories[local_mem_index].memory_type(), ), LocalOrImport::Import(import_mem_index) => ( - unsafe { builder.build_struct_gep(ctx_ptr_value, 3, "memory_array_ptr_ptr") }, + unsafe { + cache_builder.build_struct_gep(ctx_ptr_value, 3, "memory_array_ptr_ptr") + }, import_mem_index.index() as u64, info.imported_memories[import_mem_index].1.memory_type(), ), }; - let memory_array_ptr = builder + let memory_array_ptr = cache_builder .build_load(memory_array_ptr_ptr, "memory_array_ptr") .into_pointer_value(); let const_index = intrinsics.i32_ty.const_int(index, false); let memory_ptr_ptr = unsafe { - builder.build_in_bounds_gep(memory_array_ptr, &[const_index], "memory_ptr_ptr") + cache_builder.build_in_bounds_gep( + memory_array_ptr, + &[const_index], + "memory_ptr_ptr", + ) }; - let memory_ptr = builder + let memory_ptr = cache_builder .build_load(memory_ptr_ptr, "memory_ptr") .into_pointer_value(); let (ptr_to_base_ptr, ptr_to_bounds) = unsafe { ( - builder.build_struct_gep(memory_ptr, 0, "base_ptr"), - builder.build_struct_gep(memory_ptr, 1, "bounds_ptr"), + cache_builder.build_struct_gep(memory_ptr, 0, "base_ptr"), + cache_builder.build_struct_gep(memory_ptr, 1, "bounds_ptr"), ) }; @@ -491,10 +506,12 @@ impl<'a> CtxType<'a> { ptr_to_bounds, }, MemoryType::Static | MemoryType::SharedStatic => MemoryCache::Static { - base_ptr: builder + base_ptr: cache_builder .build_load(ptr_to_base_ptr, "base") .into_pointer_value(), - bounds: builder.build_load(ptr_to_bounds, "bounds").into_int_value(), + bounds: cache_builder + .build_load(ptr_to_bounds, "bounds") + .into_int_value(), }, } }); @@ -518,12 +535,13 @@ impl<'a> CtxType<'a> { } pub fn table(&mut self, index: TableIndex) -> (PointerValue, IntValue) { - let (cached_tables, builder, info, ctx_ptr_value, intrinsics) = ( + let (cached_tables, builder, info, ctx_ptr_value, intrinsics, cache_builder) = ( &mut self.cached_tables, self.builder, self.info, self.ctx_ptr_value, self.intrinsics, + &self.cache_builder, ); let TableCache { @@ -532,30 +550,34 @@ impl<'a> CtxType<'a> { } = *cached_tables.entry(index).or_insert_with(|| { let (table_array_ptr_ptr, index) = match index.local_or_import(info) { LocalOrImport::Local(local_table_index) => ( - unsafe { builder.build_struct_gep(ctx_ptr_value, 1, "table_array_ptr_ptr") }, + unsafe { + cache_builder.build_struct_gep(ctx_ptr_value, 1, "table_array_ptr_ptr") + }, local_table_index.index() as u64, ), LocalOrImport::Import(import_table_index) => ( - unsafe { builder.build_struct_gep(ctx_ptr_value, 4, "table_array_ptr_ptr") }, + unsafe { + cache_builder.build_struct_gep(ctx_ptr_value, 4, "table_array_ptr_ptr") + }, import_table_index.index() as u64, ), }; - let table_array_ptr = builder + let table_array_ptr = cache_builder .build_load(table_array_ptr_ptr, "table_array_ptr") .into_pointer_value(); let const_index = intrinsics.i32_ty.const_int(index, false); let table_ptr_ptr = unsafe { - builder.build_in_bounds_gep(table_array_ptr, &[const_index], "table_ptr_ptr") + cache_builder.build_in_bounds_gep(table_array_ptr, &[const_index], "table_ptr_ptr") }; - let table_ptr = builder + let table_ptr = cache_builder .build_load(table_ptr_ptr, "table_ptr") .into_pointer_value(); let (ptr_to_base_ptr, ptr_to_bounds) = unsafe { ( - builder.build_struct_gep(table_ptr, 0, "base_ptr"), - builder.build_struct_gep(table_ptr, 1, "bounds_ptr"), + cache_builder.build_struct_gep(table_ptr, 0, "base_ptr"), + cache_builder.build_struct_gep(table_ptr, 1, "bounds_ptr"), ) }; @@ -574,39 +596,46 @@ impl<'a> CtxType<'a> { } pub fn dynamic_sigindex(&mut self, index: SigIndex) -> IntValue { - let (cached_sigindices, builder, info, ctx_ptr_value, intrinsics) = ( + let (cached_sigindices, builder, info, ctx_ptr_value, intrinsics, cache_builder) = ( &mut self.cached_sigindices, self.builder, self.info, self.ctx_ptr_value, self.intrinsics, + &self.cache_builder, ); *cached_sigindices.entry(index).or_insert_with(|| { - let sigindex_array_ptr_ptr = - unsafe { builder.build_struct_gep(ctx_ptr_value, 7, "sigindex_array_ptr_ptr") }; - let sigindex_array_ptr = builder + let sigindex_array_ptr_ptr = unsafe { + cache_builder.build_struct_gep(ctx_ptr_value, 7, "sigindex_array_ptr_ptr") + }; + let sigindex_array_ptr = cache_builder .build_load(sigindex_array_ptr_ptr, "sigindex_array_ptr") .into_pointer_value(); let const_index = intrinsics.i32_ty.const_int(index.index() as u64, false); let sigindex_ptr = unsafe { - builder.build_in_bounds_gep(sigindex_array_ptr, &[const_index], "sigindex_ptr") + cache_builder.build_in_bounds_gep( + sigindex_array_ptr, + &[const_index], + "sigindex_ptr", + ) }; - builder + cache_builder .build_load(sigindex_ptr, "sigindex") .into_int_value() }) } pub fn global_cache(&mut self, index: GlobalIndex) -> GlobalCache { - let (cached_globals, builder, ctx_ptr_value, info, intrinsics) = ( + let (cached_globals, builder, ctx_ptr_value, info, intrinsics, cache_builder) = ( &mut self.cached_globals, self.builder, self.ctx_ptr_value, self.info, self.intrinsics, + &self.cache_builder, ); *cached_globals.entry(index).or_insert_with(|| { @@ -616,7 +645,11 @@ impl<'a> CtxType<'a> { let desc = info.globals[local_global_index].desc; ( unsafe { - builder.build_struct_gep(ctx_ptr_value, 2, "globals_array_ptr_ptr") + cache_builder.build_struct_gep( + ctx_ptr_value, + 2, + "globals_array_ptr_ptr", + ) }, local_global_index.index() as u64, desc.mutable, @@ -627,7 +660,11 @@ impl<'a> CtxType<'a> { let desc = info.imported_globals[import_global_index].1; ( unsafe { - builder.build_struct_gep(ctx_ptr_value, 5, "globals_array_ptr_ptr") + cache_builder.build_struct_gep( + ctx_ptr_value, + 5, + "globals_array_ptr_ptr", + ) }, import_global_index.index() as u64, desc.mutable, @@ -638,20 +675,25 @@ impl<'a> CtxType<'a> { let llvm_ptr_ty = type_to_llvm_ptr(intrinsics, wasmer_ty); - let global_array_ptr = builder + let global_array_ptr = cache_builder .build_load(globals_array_ptr_ptr, "global_array_ptr") .into_pointer_value(); let const_index = intrinsics.i32_ty.const_int(index, false); let global_ptr_ptr = unsafe { - builder.build_in_bounds_gep(global_array_ptr, &[const_index], "global_ptr_ptr") + cache_builder.build_in_bounds_gep( + global_array_ptr, + &[const_index], + "global_ptr_ptr", + ) }; - let global_ptr = builder + let global_ptr = cache_builder .build_load(global_ptr_ptr, "global_ptr") .into_pointer_value(); let global_ptr_typed = { - let int = builder.build_ptr_to_int(global_ptr, intrinsics.i64_ty, "global_ptr_int"); - builder.build_int_to_ptr(int, llvm_ptr_ty, "global_ptr_typed") + let int = + cache_builder.build_ptr_to_int(global_ptr, intrinsics.i64_ty, "global_ptr_int"); + cache_builder.build_int_to_ptr(int, llvm_ptr_ty, "global_ptr_typed") }; if mutable { @@ -660,7 +702,7 @@ impl<'a> CtxType<'a> { } } else { GlobalCache::Const { - value: builder + value: cache_builder .build_load(global_ptr_typed, "global_value") .into_int_value(), } @@ -669,38 +711,43 @@ impl<'a> CtxType<'a> { } pub fn imported_func(&mut self, index: ImportedFuncIndex) -> (PointerValue, PointerValue) { - let (cached_imported_functions, builder, ctx_ptr_value, intrinsics) = ( + let (cached_imported_functions, builder, ctx_ptr_value, intrinsics, cache_builder) = ( &mut self.cached_imported_functions, self.builder, self.ctx_ptr_value, self.intrinsics, + &self.cache_builder, ); let imported_func_cache = cached_imported_functions.entry(index).or_insert_with(|| { let func_array_ptr_ptr = unsafe { - builder.build_struct_gep(ctx_ptr_value, 6, "imported_func_array_ptr_ptr") + cache_builder.build_struct_gep(ctx_ptr_value, 6, "imported_func_array_ptr_ptr") }; - let func_array_ptr = builder + let func_array_ptr = cache_builder .build_load(func_array_ptr_ptr, "func_array_ptr") .into_pointer_value(); let const_index = intrinsics.i32_ty.const_int(index.index() as u64, false); let imported_func_ptr_ptr = unsafe { - builder.build_in_bounds_gep(func_array_ptr, &[const_index], "imported_func_ptr_ptr") + cache_builder.build_in_bounds_gep( + func_array_ptr, + &[const_index], + "imported_func_ptr_ptr", + ) }; - let imported_func_ptr = builder + let imported_func_ptr = cache_builder .build_load(imported_func_ptr_ptr, "imported_func_ptr") .into_pointer_value(); let (func_ptr_ptr, ctx_ptr_ptr) = unsafe { ( - builder.build_struct_gep(imported_func_ptr, 0, "func_ptr_ptr"), - builder.build_struct_gep(imported_func_ptr, 1, "ctx_ptr_ptr"), + cache_builder.build_struct_gep(imported_func_ptr, 0, "func_ptr_ptr"), + cache_builder.build_struct_gep(imported_func_ptr, 1, "ctx_ptr_ptr"), ) }; - let func_ptr = builder + let func_ptr = cache_builder .build_load(func_ptr_ptr, "func_ptr") .into_pointer_value(); - let ctx_ptr = builder + let ctx_ptr = cache_builder .build_load(ctx_ptr_ptr, "ctx_ptr") .into_pointer_value(); From 801979c40d36c70869e06b35667e94f41356fde4 Mon Sep 17 00:00:00 2001 From: Lachlan Sneff Date: Sun, 3 Mar 2019 21:26:34 -0800 Subject: [PATCH 35/75] Add dynamic sigindices to the vm context. --- lib/runtime-core/src/backing.rs | 23 +++++++++++++++++++++-- lib/runtime-core/src/vm.rs | 12 ++++++++++++ 2 files changed, 33 insertions(+), 2 deletions(-) diff --git a/lib/runtime-core/src/backing.rs b/lib/runtime-core/src/backing.rs index 9734f0c02..33cd80182 100644 --- a/lib/runtime-core/src/backing.rs +++ b/lib/runtime-core/src/backing.rs @@ -4,13 +4,14 @@ use crate::{ global::Global, import::ImportObject, memory::Memory, - module::{ImportName, ModuleInner}, + module::{ImportName, ModuleInfo, ModuleInner}, sig_registry::SigRegistry, structures::{BoxedMap, Map, SliceMap, TypedIndex}, table::Table, types::{ ImportedFuncIndex, ImportedGlobalIndex, ImportedMemoryIndex, ImportedTableIndex, - Initializer, LocalGlobalIndex, LocalMemoryIndex, LocalOrImport, LocalTableIndex, Value, + Initializer, LocalGlobalIndex, LocalMemoryIndex, LocalOrImport, LocalTableIndex, SigIndex, + Value, }, vm, }; @@ -25,6 +26,8 @@ pub struct LocalBacking { pub(crate) vm_memories: BoxedMap, pub(crate) vm_tables: BoxedMap, pub(crate) vm_globals: BoxedMap, + + pub(crate) dynamic_sigindices: BoxedMap, } // impl LocalBacking { @@ -47,6 +50,8 @@ impl LocalBacking { let vm_tables = Self::finalize_tables(module, imports, &mut tables, vmctx); let vm_globals = Self::finalize_globals(&mut globals); + let dynamic_sigindices = Self::generate_sigindices(&module.info); + Self { memories, tables, @@ -55,9 +60,23 @@ impl LocalBacking { vm_memories, vm_tables, vm_globals, + + dynamic_sigindices, } } + fn generate_sigindices(info: &ModuleInfo) -> BoxedMap { + info.signatures + .iter() + .map(|(_, signature)| { + let signature = SigRegistry.lookup_signature_ref(signature); + let sig_index = SigRegistry.lookup_sig_index(signature); + vm::SigId(sig_index.index() as u32) + }) + .collect::>() + .into_boxed_map() + } + fn generate_memories(module: &ModuleInner) -> BoxedMap { let mut memories = Map::with_capacity(module.info.memories.len()); for (_, &desc) in &module.info.memories { diff --git a/lib/runtime-core/src/vm.rs b/lib/runtime-core/src/vm.rs index 71400af70..c016c76e7 100644 --- a/lib/runtime-core/src/vm.rs +++ b/lib/runtime-core/src/vm.rs @@ -34,6 +34,12 @@ pub struct Ctx { /// A pointer to an array of imported functions, indexed by `FuncIndex`. pub(crate) imported_funcs: *mut ImportedFunc, + /// A pointer to an array of signature ids. Conceptually, this maps + /// from a static, module-local signature id to a runtime-global + /// signature id. This is used to allow call-indirect to other + /// modules safely. + pub(crate) dynamic_sigindices: *const SigId, + local_backing: *mut LocalBacking, import_backing: *mut ImportBacking, module: *const ModuleInner, @@ -59,6 +65,8 @@ impl Ctx { imported_globals: import_backing.vm_globals.as_mut_ptr(), imported_funcs: import_backing.vm_functions.as_mut_ptr(), + dynamic_sigindices: local_backing.dynamic_sigindices.as_ptr(), + local_backing, import_backing, module, @@ -86,6 +94,8 @@ impl Ctx { imported_globals: import_backing.vm_globals.as_mut_ptr(), imported_funcs: import_backing.vm_functions.as_mut_ptr(), + dynamic_sigindices: local_backing.dynamic_sigindices.as_ptr(), + local_backing, import_backing, module, @@ -468,6 +478,8 @@ mod vm_ctx_tests { vm_memories: Map::new().into_boxed_map(), vm_tables: Map::new().into_boxed_map(), vm_globals: Map::new().into_boxed_map(), + + dynamic_sigindices: Map::new().into_boxed_map(), }; let module = generate_module(); let data = &mut data as *mut _ as *mut c_void; From 87c453a0ec77bd024529aa05fa4f437c6891c13e Mon Sep 17 00:00:00 2001 From: Lachlan Sneff Date: Sun, 3 Mar 2019 21:38:35 -0800 Subject: [PATCH 36/75] Add check for table bounds on call_indirect. --- lib/llvm-backend/cpp/object_loader.hh | 1 + lib/llvm-backend/src/code.rs | 48 +++++++++++++++++++++++++++ lib/llvm-backend/src/intrinsics.rs | 2 ++ 3 files changed, 51 insertions(+) diff --git a/lib/llvm-backend/cpp/object_loader.hh b/lib/llvm-backend/cpp/object_loader.hh index 67a2f5740..880d97b3f 100644 --- a/lib/llvm-backend/cpp/object_loader.hh +++ b/lib/llvm-backend/cpp/object_loader.hh @@ -69,6 +69,7 @@ public: Unreachable = 0, IncorrectCallIndirectSignature = 1, MemoryOutOfBounds = 2, + CallIndirectOOB = 3, Unknown, }; diff --git a/lib/llvm-backend/src/code.rs b/lib/llvm-backend/src/code.rs index 46ddffa41..341848d27 100644 --- a/lib/llvm-backend/src/code.rs +++ b/lib/llvm-backend/src/code.rs @@ -744,6 +744,54 @@ fn parse_function( ) }; + let truncated_table_bounds = builder.build_int_truncate( + table_bound, + intrinsics.i32_ty, + "truncated_table_bounds", + ); + + // First, check if the index is outside of the table bounds. + let index_in_bounds = builder.build_int_compare( + IntPredicate::ULT, + func_index, + truncated_table_bounds, + "index_in_bounds", + ); + + let index_in_bounds = builder + .build_call( + intrinsics.expect_i1, + &[ + index_in_bounds.as_basic_value_enum(), + intrinsics.i1_ty.const_int(1, false).as_basic_value_enum(), + ], + "index_in_bounds_expect", + ) + .try_as_basic_value() + .left() + .unwrap() + .into_int_value(); + + let in_bounds_continue_block = + context.append_basic_block(&function, "in_bounds_continue_block"); + let not_in_bounds_block = + context.append_basic_block(&function, "not_in_bounds_block"); + builder.build_conditional_branch( + index_in_bounds, + &in_bounds_continue_block, + ¬_in_bounds_block, + ); + builder.position_at_end(¬_in_bounds_block); + builder.build_call( + intrinsics.throw_trap, + &[intrinsics.trap_call_indirect_oob], + "throw", + ); + builder.build_unreachable(); + builder.position_at_end(&in_bounds_continue_block); + + // Next, check if the signature id is correct. + let sigindices_equal = builder.build_int_compare( IntPredicate::EQ, expected_dynamic_sigindex, diff --git a/lib/llvm-backend/src/intrinsics.rs b/lib/llvm-backend/src/intrinsics.rs index 908448a51..f19561417 100644 --- a/lib/llvm-backend/src/intrinsics.rs +++ b/lib/llvm-backend/src/intrinsics.rs @@ -95,6 +95,7 @@ pub struct Intrinsics { pub trap_unreachable: BasicValueEnum, pub trap_call_indirect_sig: BasicValueEnum, + pub trap_call_indirect_oob: BasicValueEnum, pub trap_memory_oob: BasicValueEnum, // VM intrinsics. @@ -293,6 +294,7 @@ impl Intrinsics { trap_unreachable: i32_zero.as_basic_value_enum(), trap_call_indirect_sig: i32_ty.const_int(1, false).as_basic_value_enum(), + trap_call_indirect_oob: i32_ty.const_int(3, false).as_basic_value_enum(), trap_memory_oob: i32_ty.const_int(2, false).as_basic_value_enum(), // VM intrinsics. From ae3b2b2a42f9008ad4002bce6d37b2f79da6b991 Mon Sep 17 00:00:00 2001 From: Lachlan Sneff Date: Sun, 3 Mar 2019 21:56:30 -0800 Subject: [PATCH 37/75] Add bounds checking for memory accesses on dynamic memories --- lib/llvm-backend/src/code.rs | 104 ++++++++++++++++++++++++++++- lib/llvm-backend/src/intrinsics.rs | 26 ++------ 2 files changed, 106 insertions(+), 24 deletions(-) diff --git a/lib/llvm-backend/src/code.rs b/lib/llvm-backend/src/code.rs index 341848d27..471cb78db 100644 --- a/lib/llvm-backend/src/code.rs +++ b/lib/llvm-backend/src/code.rs @@ -21,7 +21,7 @@ use wasmparser::{ BinaryReaderError, CodeSectionReader, LocalsReader, MemoryImmediate, Operator, OperatorsReader, }; -use crate::intrinsics::{CtxType, GlobalCache, Intrinsics}; +use crate::intrinsics::{CtxType, GlobalCache, Intrinsics, MemoryCache}; use crate::read_info::type_to_type; use crate::state::{ControlFrame, IfElseState, State}; use crate::trampolines::generate_trampolines; @@ -1571,6 +1571,8 @@ fn parse_function( let effective_address = resolve_memory_ptr( builder, intrinsics, + context, + &function, &mut state, &mut ctx, memarg, @@ -1583,6 +1585,8 @@ fn parse_function( let effective_address = resolve_memory_ptr( builder, intrinsics, + context, + &function, &mut state, &mut ctx, memarg, @@ -1595,6 +1599,8 @@ fn parse_function( let effective_address = resolve_memory_ptr( builder, intrinsics, + context, + &function, &mut state, &mut ctx, memarg, @@ -1607,6 +1613,8 @@ fn parse_function( let effective_address = resolve_memory_ptr( builder, intrinsics, + context, + &function, &mut state, &mut ctx, memarg, @@ -1621,6 +1629,8 @@ fn parse_function( let effective_address = resolve_memory_ptr( builder, intrinsics, + context, + &function, &mut state, &mut ctx, memarg, @@ -1633,6 +1643,8 @@ fn parse_function( let effective_address = resolve_memory_ptr( builder, intrinsics, + context, + &function, &mut state, &mut ctx, memarg, @@ -1645,6 +1657,8 @@ fn parse_function( let effective_address = resolve_memory_ptr( builder, intrinsics, + context, + &function, &mut state, &mut ctx, memarg, @@ -1657,6 +1671,8 @@ fn parse_function( let effective_address = resolve_memory_ptr( builder, intrinsics, + context, + &function, &mut state, &mut ctx, memarg, @@ -1669,6 +1685,8 @@ fn parse_function( let effective_address = resolve_memory_ptr( builder, intrinsics, + context, + &function, &mut state, &mut ctx, memarg, @@ -1685,6 +1703,8 @@ fn parse_function( let effective_address = resolve_memory_ptr( builder, intrinsics, + context, + &function, &mut state, &mut ctx, memarg, @@ -1701,6 +1721,8 @@ fn parse_function( let effective_address = resolve_memory_ptr( builder, intrinsics, + context, + &function, &mut state, &mut ctx, memarg, @@ -1717,6 +1739,8 @@ fn parse_function( let effective_address = resolve_memory_ptr( builder, intrinsics, + context, + &function, &mut state, &mut ctx, memarg, @@ -1733,6 +1757,8 @@ fn parse_function( let effective_address = resolve_memory_ptr( builder, intrinsics, + context, + &function, &mut state, &mut ctx, memarg, @@ -1750,6 +1776,8 @@ fn parse_function( let effective_address = resolve_memory_ptr( builder, intrinsics, + context, + &function, &mut state, &mut ctx, memarg, @@ -1766,6 +1794,8 @@ fn parse_function( let effective_address = resolve_memory_ptr( builder, intrinsics, + context, + &function, &mut state, &mut ctx, memarg, @@ -1782,6 +1812,8 @@ fn parse_function( let effective_address = resolve_memory_ptr( builder, intrinsics, + context, + &function, &mut state, &mut ctx, memarg, @@ -1798,6 +1830,8 @@ fn parse_function( let effective_address = resolve_memory_ptr( builder, intrinsics, + context, + &function, &mut state, &mut ctx, memarg, @@ -1814,6 +1848,8 @@ fn parse_function( let effective_address = resolve_memory_ptr( builder, intrinsics, + context, + &function, &mut state, &mut ctx, memarg, @@ -1832,6 +1868,8 @@ fn parse_function( let effective_address = resolve_memory_ptr( builder, intrinsics, + context, + &function, &mut state, &mut ctx, memarg, @@ -1846,6 +1884,8 @@ fn parse_function( let effective_address = resolve_memory_ptr( builder, intrinsics, + context, + &function, &mut state, &mut ctx, memarg, @@ -1860,6 +1900,8 @@ fn parse_function( let effective_address = resolve_memory_ptr( builder, intrinsics, + context, + &function, &mut state, &mut ctx, memarg, @@ -1964,6 +2006,8 @@ fn parse_function( fn resolve_memory_ptr( builder: &Builder, intrinsics: &Intrinsics, + context: &Context, + function: &FunctionValue, state: &mut State, ctx: &mut CtxType, memarg: MemoryImmediate, @@ -1975,8 +2019,62 @@ fn resolve_memory_ptr( let var_offset = builder.build_int_z_extend(var_offset_i32, intrinsics.i64_ty, &state.var_name()); let effective_offset = builder.build_int_add(var_offset, imm_offset, &state.var_name()); - let (mem_base, mem_bound) = ctx.memory(MemoryIndex::new(0)); - let mem_base_int = builder.build_ptr_to_int(mem_base, intrinsics.i64_ty, &state.var_name()); + let memory_cache = ctx.memory(MemoryIndex::new(0)); + + let mem_base_int = match memory_cache { + MemoryCache::Dynamic { + ptr_to_base_ptr, + ptr_to_bounds, + } => { + let base = builder + .build_load(ptr_to_base_ptr, "base") + .into_pointer_value(); + let bounds = builder.build_load(ptr_to_bounds, "bounds").into_int_value(); + + let base_as_int = builder.build_ptr_to_int(base, intrinsics.i64_ty, "base_as_int"); + + let base_in_bounds = + builder.build_int_compare(IntPredicate::ULT, base_as_int, bounds, "base_in_bounds"); + + let base_in_bounds = builder + .build_call( + intrinsics.expect_i1, + &[ + base_in_bounds.as_basic_value_enum(), + intrinsics.i1_ty.const_int(1, false).as_basic_value_enum(), + ], + "base_in_bounds_expect", + ) + .try_as_basic_value() + .left() + .unwrap() + .into_int_value(); + + let in_bounds_continue_block = + context.append_basic_block(function, "in_bounds_continue_block"); + let not_in_bounds_block = context.append_basic_block(function, "not_in_bounds_block"); + builder.build_conditional_branch( + base_in_bounds, + &in_bounds_continue_block, + ¬_in_bounds_block, + ); + builder.position_at_end(¬_in_bounds_block); + builder.build_call( + intrinsics.throw_trap, + &[intrinsics.trap_memory_oob], + "throw", + ); + builder.build_unreachable(); + builder.position_at_end(&in_bounds_continue_block); + + base_as_int + } + MemoryCache::Static { + base_ptr, + bounds: _, + } => builder.build_ptr_to_int(base_ptr, intrinsics.i64_ty, "base_as_int"), + }; + let effective_address_int = builder.build_int_add(mem_base_int, effective_offset, &state.var_name()); Ok(builder.build_int_to_ptr(effective_address_int, ptr_ty, &state.var_name())) diff --git a/lib/llvm-backend/src/intrinsics.rs b/lib/llvm-backend/src/intrinsics.rs index f19561417..9e91c5911 100644 --- a/lib/llvm-backend/src/intrinsics.rs +++ b/lib/llvm-backend/src/intrinsics.rs @@ -398,7 +398,8 @@ impl Intrinsics { } } -enum MemoryCache { +#[derive(Clone, Copy)] +pub enum MemoryCache { /// The memory moves around. Dynamic { ptr_to_base_ptr: PointerValue, @@ -452,7 +453,7 @@ impl<'a> CtxType<'a> { self.ctx_ptr_value.as_basic_value_enum() } - pub fn memory(&mut self, index: MemoryIndex) -> (PointerValue, IntValue) { + pub fn memory(&mut self, index: MemoryIndex) -> MemoryCache { let (cached_memories, builder, info, ctx_ptr_value, intrinsics, cache_builder) = ( &mut self.cached_memories, self.builder, @@ -462,7 +463,7 @@ impl<'a> CtxType<'a> { &self.cache_builder, ); - let memory_cache = cached_memories.entry(index).or_insert_with(|| { + *cached_memories.entry(index).or_insert_with(|| { let (memory_array_ptr_ptr, index, memory_type) = match index.local_or_import(info) { LocalOrImport::Local(local_mem_index) => ( unsafe { @@ -516,24 +517,7 @@ impl<'a> CtxType<'a> { .into_int_value(), }, } - }); - - match memory_cache { - MemoryCache::Dynamic { - ptr_to_base_ptr, - ptr_to_bounds, - } => { - let base = builder - .build_load(*ptr_to_base_ptr, "base") - .into_pointer_value(); - let bounds = builder - .build_load(*ptr_to_bounds, "bounds") - .into_int_value(); - - (base, bounds) - } - MemoryCache::Static { base_ptr, bounds } => (*base_ptr, *bounds), - } + }) } pub fn table(&mut self, index: TableIndex) -> (PointerValue, IntValue) { From ab550f46fcb6763eb088aa6b7416426a565be56c Mon Sep 17 00:00:00 2001 From: Lachlan Sneff Date: Sun, 3 Mar 2019 22:11:40 -0800 Subject: [PATCH 38/75] Fix bug resulting from comparing the memory base instead of the memory offset to the memory bounds. --- lib/llvm-backend/src/code.rs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/lib/llvm-backend/src/code.rs b/lib/llvm-backend/src/code.rs index 471cb78db..51815f3f6 100644 --- a/lib/llvm-backend/src/code.rs +++ b/lib/llvm-backend/src/code.rs @@ -2033,8 +2033,12 @@ fn resolve_memory_ptr( let base_as_int = builder.build_ptr_to_int(base, intrinsics.i64_ty, "base_as_int"); - let base_in_bounds = - builder.build_int_compare(IntPredicate::ULT, base_as_int, bounds, "base_in_bounds"); + let base_in_bounds = builder.build_int_compare( + IntPredicate::ULT, + effective_offset, + bounds, + "base_in_bounds", + ); let base_in_bounds = builder .build_call( From 3f9dbca17f987a411be00e52b753505ad66804fd Mon Sep 17 00:00:00 2001 From: Lachlan Sneff Date: Sun, 3 Mar 2019 22:47:34 -0800 Subject: [PATCH 39/75] List specific supported features for validator. --- lib/llvm-backend/src/lib.rs | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/lib/llvm-backend/src/lib.rs b/lib/llvm-backend/src/lib.rs index b1ddc1f18..d70f0f363 100644 --- a/lib/llvm-backend/src/lib.rs +++ b/lib/llvm-backend/src/lib.rs @@ -76,7 +76,19 @@ impl Compiler for LLVMCompiler { } fn validate(bytes: &[u8]) -> Result<(), CompileError> { - let mut parser = wasmparser::ValidatingParser::new(bytes, None); + let mut parser = wasmparser::ValidatingParser::new( + bytes, + Some(wasmparser::ValidatingParserConfig { + operator_config: wasmparser::OperatorValidatorConfig { + enable_threads: false, + enable_reference_types: false, + enable_simd: false, + enable_bulk_memory: false, + }, + mutable_global_imports: false, + }), + ); + loop { let state = parser.read(); match *state { From deea9e98a4a449f9236151752a7819d598dbbf08 Mon Sep 17 00:00:00 2001 From: Lachlan Sneff Date: Mon, 4 Mar 2019 10:19:38 -0800 Subject: [PATCH 40/75] Add import names, whoops. --- lib/llvm-backend/src/read_info.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/llvm-backend/src/read_info.rs b/lib/llvm-backend/src/read_info.rs index bed91aa90..a974beb59 100644 --- a/lib/llvm-backend/src/read_info.rs +++ b/lib/llvm-backend/src/read_info.rs @@ -111,6 +111,9 @@ pub fn read_module(wasm: &[u8]) -> Result<(ModuleInfo, CodeSectionReader), Binar } } } + + info.namespace_table = namespace_builder.finish(); + info.name_table = name_builder.finish(); } SectionCode::Function => { let func_decl_reader = section.get_function_section_reader()?; From 039ebdcf7591e1ff0aea16c9ecc8a2e061fbf1c0 Mon Sep 17 00:00:00 2001 From: Lachlan Sneff Date: Mon, 4 Mar 2019 13:10:28 -0800 Subject: [PATCH 41/75] Fix merge errors and update llvm to use the new runtime error type. --- Cargo.lock | 1682 +++++++++++++++++++++++++++++++ lib/llvm-backend/Cargo.toml | 2 +- lib/llvm-backend/src/backend.rs | 24 +- 3 files changed, 1694 insertions(+), 14 deletions(-) create mode 100644 Cargo.lock diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 000000000..2845dc155 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,1682 @@ +[[package]] +name = "aho-corasick" +version = "0.6.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "ansi_term" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "arrayref" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "arrayvec" +version = "0.4.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "atty" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "autocfg" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "backtrace" +version = "0.3.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "backtrace-sys 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-demangle 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "backtrace-sys" +version = "0.1.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cc 1.0.30 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "bindgen" +version = "0.46.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "cexpr 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "clang-sys 0.26.4 (registry+https://github.com/rust-lang/crates.io-index)", + "clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)", + "env_logger 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "hashbrown 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "peeking_take_while 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "which 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "bitflags" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "blake2b_simd" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "arrayref 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "constant_time_eq 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "byteorder" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "capstone" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "capstone-sys 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "capstone-sys" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cc 1.0.30 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "cast" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "cbindgen" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.58 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.27 (registry+https://github.com/rust-lang/crates.io-index)", + "tempfile 3.0.7 (registry+https://github.com/rust-lang/crates.io-index)", + "toml 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "cc" +version = "1.0.30" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "cexpr" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "nom 4.2.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "cfg-if" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "clang-sys" +version = "0.26.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "libloading 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "clap" +version = "2.32.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "textwrap 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "cloudabi" +version = "0.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "cmake" +version = "0.1.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cc 1.0.30 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "constant_time_eq" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "cranelift-bforest" +version = "0.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cranelift-entity 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "cranelift-codegen" +version = "0.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cranelift-bforest 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cranelift-codegen-meta 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cranelift-entity 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)", + "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "target-lexicon 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "cranelift-codegen-meta" +version = "0.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cranelift-entity 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "cranelift-entity" +version = "0.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "cranelift-frontend" +version = "0.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cranelift-codegen 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "target-lexicon 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "cranelift-native" +version = "0.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cranelift-codegen 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)", + "raw-cpuid 6.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "target-lexicon 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "cranelift-wasm" +version = "0.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cast 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "cranelift-codegen 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cranelift-entity 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cranelift-frontend 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)", + "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "wasmparser 0.22.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "criterion" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "cast 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)", + "criterion-plot 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "csv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_os 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_xoshiro 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rayon 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.58 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", + "tinytemplate 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "walkdir 2.2.7 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "criterion-plot" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "cast 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "crossbeam-deque" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "crossbeam-epoch 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", + "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "crossbeam-utils" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "csv" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "csv-core 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "csv-core" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "digest" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "generic-array 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "either" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "enum-methods" +version = "0.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "env_logger" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "humantime 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "termcolor 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "errno" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "errno-dragonfly 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "errno-dragonfly" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "gcc 0.3.55 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "failure" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "backtrace 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", + "failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "failure_derive" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.27 (registry+https://github.com/rust-lang/crates.io-index)", + "synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "field-offset" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "fuchsia-cprng" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "gcc" +version = "0.3.55" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "generic-array" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "glob" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "goblin" +version = "0.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "plain 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "scroll 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "hashbrown" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "heck" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "unicode-segmentation 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "hex" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "humantime" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "indexmap" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "inkwell" +version = "0.1.0" +source = "git+https://github.com/TheDan64/inkwell?branch=llvm7-0#b8699b0ee594e4162ce850fbedb37892e9cdb7e4" +dependencies = [ + "either 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "enum-methods 0.0.8 (registry+https://github.com/rust-lang/crates.io-index)", + "inkwell_internal_macros 0.1.0 (git+https://github.com/TheDan64/inkwell?branch=llvm7-0)", + "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "llvm-sys 70.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "inkwell_internal_macros" +version = "0.1.0" +source = "git+https://github.com/TheDan64/inkwell?branch=llvm7-0#b8699b0ee594e4162ce850fbedb37892e9cdb7e4" +dependencies = [ + "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.27 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "itertools" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "either 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "itoa" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "kernel32-sys" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "lazy_static" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "libc" +version = "0.2.49" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "libloading" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cc 1.0.30 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "llvm-sys" +version = "70.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cc 1.0.30 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "lock_api" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "owning_ref 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "log" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "memchr" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "memmap" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "memoffset" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "nix" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.30 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "nix" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.30 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "nodrop" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "nom" +version = "4.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "num-traits" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "num_cpus" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "owning_ref" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "page_size" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "parking_lot" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "lock_api 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "parking_lot_core" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "peeking_take_while" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "plain" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "proc-macro2" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "proc-macro2" +version = "0.4.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "quick-error" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "quote" +version = "0.3.15" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "quote" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "quote" +version = "0.6.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_jitter 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_os 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_pcg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand_chacha" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand_core" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand_core" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "rand_hc" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand_isaac" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand_jitter" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand_os" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand_pcg" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand_xorshift" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand_xoshiro" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "raw-cpuid" +version = "6.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.30 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rayon" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "either 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rayon-core 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rayon-core" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rdrand" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "redox_syscall" +version = "0.1.51" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "redox_termios" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "regex" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "aho-corasick 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "regex-syntax 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "utf8-ranges 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "regex-syntax" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "ucd-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "remove_dir_all" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rustc-demangle" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "rustc_version" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "ryu" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "same-file" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "scopeguard" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "scroll" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "scroll_derive 0.9.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "scroll_derive" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.27 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "semver" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "semver-parser" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "serde" +version = "1.0.89" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "serde_derive 1.0.58 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "serde-bench" +version = "0.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "serde_bytes" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "serde_derive" +version = "1.0.58" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.13.11 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "serde_json" +version = "1.0.39" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", + "ryu 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "smallvec" +version = "0.6.9" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "stable_deref_trait" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "strsim" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "structopt" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)", + "structopt-derive 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "structopt-derive" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.27 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "syn" +version = "0.11.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", + "synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "syn" +version = "0.13.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "syn" +version = "0.15.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "synom" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "synstructure" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.27 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "target-lexicon" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "tempfile" +version = "3.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)", + "remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "termcolor" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "wincolor 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "termion" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "textwrap" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "thread_local" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "time" +version = "0.1.42" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "tinytemplate" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "toml" +version = "0.4.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "typenum" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "ucd-util" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "unicode-segmentation" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "unicode-width" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "unicode-xid" +version = "0.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "unicode-xid" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "utf8-ranges" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "vec_map" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "version_check" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "void" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "wabt" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.58 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", + "wabt-sys 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "wabt-sys" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cc 1.0.30 (registry+https://github.com/rust-lang/crates.io-index)", + "cmake 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)", + "glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "walkdir" +version = "2.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "same-file 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "wasmer" +version = "0.2.1" +dependencies = [ + "glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "structopt 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", + "wabt 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)", + "wasmer-clif-backend 0.2.0", + "wasmer-emscripten 0.2.1", + "wasmer-runtime 0.2.1", + "wasmer-runtime-core 0.2.1", +] + +[[package]] +name = "wasmer-clif-backend" +version = "0.2.0" +dependencies = [ + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "cranelift-codegen 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cranelift-entity 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cranelift-native 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cranelift-wasm 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)", + "hashbrown 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "nix 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rayon 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", + "serde-bench 0.0.7 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_bytes 0.10.5 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.58 (registry+https://github.com/rust-lang/crates.io-index)", + "target-lexicon 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "wasmer-runtime-core 0.2.1", + "wasmer-win-exception-handler 0.2.0", + "wasmparser 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "wasmer-emscripten" +version = "0.2.1" +dependencies = [ + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", + "wabt 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)", + "wasmer-clif-backend 0.2.0", + "wasmer-runtime-core 0.2.1", +] + +[[package]] +name = "wasmer-llvm-backend" +version = "0.1.0" +dependencies = [ + "capstone 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.30 (registry+https://github.com/rust-lang/crates.io-index)", + "goblin 0.0.20 (registry+https://github.com/rust-lang/crates.io-index)", + "hashbrown 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "inkwell 0.1.0 (git+https://github.com/TheDan64/inkwell?branch=llvm7-0)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "nix 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", + "wabt 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)", + "wasmer-runtime-core 0.2.1", + "wasmparser 0.28.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "wasmer-runtime" +version = "0.2.1" +dependencies = [ + "criterion 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "memmap 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "tempfile 3.0.7 (registry+https://github.com/rust-lang/crates.io-index)", + "wabt 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)", + "wasmer-clif-backend 0.2.0", + "wasmer-llvm-backend 0.1.0", + "wasmer-runtime-core 0.2.1", +] + +[[package]] +name = "wasmer-runtime-c-api" +version = "0.2.1" +dependencies = [ + "cbindgen 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "wasmer-runtime 0.2.1", + "wasmer-runtime-core 0.2.1", +] + +[[package]] +name = "wasmer-runtime-core" +version = "0.2.1" +dependencies = [ + "blake2b_simd 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "digest 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "errno 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", + "field-offset 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "hashbrown 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "nix 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", + "page_size 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", + "serde-bench 0.0.7 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_bytes 0.10.5 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.58 (registry+https://github.com/rust-lang/crates.io-index)", + "wasmparser 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "wasmer-spectests" +version = "0.2.0" +dependencies = [ + "wabt 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)", + "wasmer-clif-backend 0.2.0", + "wasmer-llvm-backend 0.1.0", + "wasmer-runtime-core 0.2.1", +] + +[[package]] +name = "wasmer-win-exception-handler" +version = "0.2.0" +dependencies = [ + "bindgen 0.46.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cmake 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "wasmer-runtime-core 0.2.1", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "wasmparser" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "wasmparser" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "wasmparser" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "which" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "winapi" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "winapi" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "winapi-build" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "winapi-util" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "wincolor" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[metadata] +"checksum aho-corasick 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "81ce3d38065e618af2d7b77e10c5ad9a069859b4be3c2250f674af3840d9c8a5" +"checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" +"checksum arrayref 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "0d382e583f07208808f6b1249e60848879ba3543f57c32277bf52d69c2f0f0ee" +"checksum arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)" = "92c7fb76bc8826a8b33b4ee5bb07a247a81e76764ab4d55e8f73e3a4d8808c71" +"checksum atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "9a7d5b8723950951411ee34d271d99dddcc2035a16ab25310ea2c8cfd4369652" +"checksum autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a6d640bee2da49f60a4068a7fae53acde8982514ab7bae8b8cea9e88cbcfd799" +"checksum backtrace 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)" = "cd5a90e2b463010cd0e0ce9a11d4a9d5d58d9f41d4a6ba3dcaf9e68b466e88b4" +"checksum backtrace-sys 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)" = "797c830ac25ccc92a7f8a7b9862bde440715531514594a6154e3d4a54dd769b6" +"checksum bindgen 0.46.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8f7f7f0701772b17de73e4f5cbcb1dd6926f4706cba4c1ab62c5367f8bdc94e1" +"checksum bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12" +"checksum blake2b_simd 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ce2571a6cd634670daa2977cc894c1cc2ba57c563c498e5a82c35446f34d056e" +"checksum byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a019b10a2a7cdeb292db131fc8113e57ea2a908f6e7894b0c3c671893b65dbeb" +"checksum capstone 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "00be9d203fa0e078b93b24603633fb081851dfe0c1086364431f52587a47157e" +"checksum capstone-sys 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2dc8d32bc5c1e6d0fcde10af411c98b07d93498d51654f678757f08fa2acd6a6" +"checksum cast 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "926013f2860c46252efceabb19f4a6b308197505082c609025aa6706c011d427" +"checksum cbindgen 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "32e01024aaf5390d6a8145047371a4f5b0063a14c1e411bc731353bd2278ca44" +"checksum cc 1.0.30 (registry+https://github.com/rust-lang/crates.io-index)" = "d01c69d08ff207f231f07196e30f84c70f1c815b04f980f8b7b01ff01f05eb92" +"checksum cexpr 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "644d693ecfa91955ed32dcc7eda4914e1be97a641fb6f0645a37348e20b230da" +"checksum cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "082bb9b28e00d3c9d39cc03e64ce4cea0f1bb9b3fde493f0cbc008472d22bdf4" +"checksum clang-sys 0.26.4 (registry+https://github.com/rust-lang/crates.io-index)" = "6ef0c1bcf2e99c649104bd7a7012d8f8802684400e03db0ec0af48583c6fa0e4" +"checksum clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b957d88f4b6a63b9d70d5f454ac8011819c6efa7727858f458ab71c756ce2d3e" +"checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" +"checksum cmake 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)" = "6ec65ee4f9c9d16f335091d23693457ed4928657ba4982289d7fafee03bc614a" +"checksum constant_time_eq 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8ff012e225ce166d4422e0e78419d901719760f62ae2b7969ca6b564d1b54a9e" +"checksum cranelift-bforest 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)" = "40f8ff24e9a6c89b8a846b14df9a34d2cac17cea7bdb5c81ed6b4744ee0e38bf" +"checksum cranelift-codegen 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)" = "42f5b809bd885c368e01aeec8fe04f21dcb07569834b907d75b4a7bed8d067eb" +"checksum cranelift-codegen-meta 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)" = "014c23ed3ebdc8377d41540af638245207dd169f421df042dfccc867465734ed" +"checksum cranelift-entity 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d4df40e26c0cf7b4d86919cb995bb412ee3001cc18e4f3c83a903f30b7007d8b" +"checksum cranelift-frontend 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)" = "789907218eeebebcea8122c2053d71affac91c96ce72cea35ebfdbbf547e82af" +"checksum cranelift-native 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)" = "474bee81d620a473bf43411a3d6f10ffbf7965141dc5e5b76d8d2151dde3285d" +"checksum cranelift-wasm 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)" = "49723365dab9a48b354bdc24cb6d9d5719bc1d3b858ffd2ea179d0d7d885804a" +"checksum criterion 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "1c6e5ee5b9652d4f851418c448af105642e1f99e9a2741a8ff45c0d2c911b1e0" +"checksum criterion-plot 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4107e4a5abb94267e0149922b8ff49dc70a87cc202820fdbfc0d3e1edbdc4b16" +"checksum crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f739f8c5363aca78cfb059edf753d8f0d36908c348f3d8d1503f03d8b75d9cf3" +"checksum crossbeam-epoch 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "927121f5407de9956180ff5e936fe3cf4324279280001cd56b669d28ee7e9150" +"checksum crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2760899e32a1d58d5abb31129f8fae5de75220bc2176e77ff7c627ae45c918d9" +"checksum csv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "9fd1c44c58078cfbeaf11fbb3eac9ae5534c23004ed770cc4bfb48e658ae4f04" +"checksum csv-core 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "fa5cdef62f37e6ffe7d1f07a381bc0db32b7a3ff1cac0de56cb0d81e71f53d65" +"checksum digest 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "05f47366984d3ad862010e22c7ce81a7dbcaebbdfb37241a620f8b6596ee135c" +"checksum either 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c67353c641dc847124ea1902d69bd753dee9bb3beff9aa3662ecf86c971d1fac" +"checksum enum-methods 0.0.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7798e7da2d4cb0d6d6fc467e8d6b5bf247e9e989f786dde1732d79899c32bb10" +"checksum env_logger 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "afb070faf94c85d17d50ca44f6ad076bce18ae92f0037d350947240a36e9d42e" +"checksum errno 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "c2a071601ed01b988f896ab14b95e67335d1eeb50190932a1320f7fe3cadc84e" +"checksum errno-dragonfly 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "14ca354e36190500e1e1fb267c647932382b54053c50b14970856c0b00a35067" +"checksum failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "795bd83d3abeb9220f257e597aa0080a508b27533824adf336529648f6abf7e2" +"checksum failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "ea1063915fd7ef4309e222a5a07cf9c319fb9c7836b1f89b85458672dbb127e1" +"checksum field-offset 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "64e9bc339e426139e02601fa69d101e96a92aee71b58bc01697ec2a63a5c9e68" +"checksum fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" +"checksum gcc 0.3.55 (registry+https://github.com/rust-lang/crates.io-index)" = "8f5f3913fa0bfe7ee1fd8248b6b9f42a5af4b9d65ec2dd2c3c26132b950ecfc2" +"checksum generic-array 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3c0f28c2f5bfb5960175af447a2da7c18900693738343dc896ffbcabd9839592" +"checksum glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "8be18de09a56b60ed0edf84bc9df007e30040691af7acd1c41874faac5895bfb" +"checksum goblin 0.0.20 (registry+https://github.com/rust-lang/crates.io-index)" = "84473a5302fa5094d3d9911c2f312f522f9a37462a777f195f63fae1bf7faf4d" +"checksum hashbrown 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "3bae29b6653b3412c2e71e9d486db9f9df5d701941d86683005efb9f2d28e3da" +"checksum heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205" +"checksum hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "805026a5d0141ffc30abb3be3173848ad46a1b1664fe632428479619a3644d77" +"checksum humantime 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3ca7e5f2e110db35f93b837c81797f3714500b81d517bf20c431b16d3ca4f114" +"checksum indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7e81a7c05f79578dbc15793d8b619db9ba32b4577003ef3af1a91c416798c58d" +"checksum inkwell 0.1.0 (git+https://github.com/TheDan64/inkwell?branch=llvm7-0)" = "" +"checksum inkwell_internal_macros 0.1.0 (git+https://github.com/TheDan64/inkwell?branch=llvm7-0)" = "" +"checksum itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5b8467d9c1cebe26feb08c640139247fac215782d35371ade9a2136ed6085358" +"checksum itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1306f3464951f30e30d12373d31c79fbd52d236e5e896fd92f96ec7babbbe60b" +"checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" +"checksum lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bc5729f27f159ddd61f4df6228e827e86643d4d3e7c32183cb30a1c08f604a14" +"checksum libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)" = "413f3dfc802c5dc91dc570b05125b6cda9855edfaa9825c9849807876376e70e" +"checksum libloading 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9c3ad660d7cb8c5822cd83d10897b0f1f1526792737a179e73896152f85b88c2" +"checksum llvm-sys 70.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "60a9ee82fe0fa72ae6ef6d018b407296085863836451c7a97384f84ed7e26b9f" +"checksum lock_api 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "62ebf1391f6acad60e5c8b43706dde4582df75c06698ab44511d15016bc2442c" +"checksum log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c84ec4b527950aa83a329754b01dbe3f58361d1c5efacd1f6d68c494d08a17c6" +"checksum memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2efc7bc57c883d4a4d6e3246905283d8dae951bb3bd32f49d6ef297f546e1c39" +"checksum memmap 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6585fd95e7bb50d6cc31e20d4cf9afb4e2ba16c5846fc76793f11218da9c475b" +"checksum memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0f9dc261e2b62d7a622bf416ea3c5245cdd5d9a7fcc428c0d06804dfce1775b3" +"checksum nix 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "921f61dc817b379d0834e45d5ec45beaacfae97082090a49c2cf30dcbc30206f" +"checksum nix 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "46f0f3210768d796e8fa79ec70ee6af172dacbe7147f5e69be5240a47778302b" +"checksum nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "2f9667ddcc6cc8a43afc9b7917599d7216aa09c463919ea32c59ed6cac8bc945" +"checksum nom 4.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "22293d25d3f33a8567cc8a1dc20f40c7eeb761ce83d0fcca059858580790cac3" +"checksum num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0b3a5d7cc97d6d30d8b9bc8fa19bf45349ffe46241e8816f50f62f6d6aaabee1" +"checksum num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1a23f0ed30a54abaa0c7e83b1d2d87ada7c3c23078d1d87815af3e3b6385fbba" +"checksum owning_ref 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "49a4b8ea2179e6a2e27411d3bca09ca6dd630821cf6894c6c7c8467a8ee7ef13" +"checksum page_size 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f89ef58b3d32420dbd1a43d2f38ae92f6239ef12bb556ab09ca55445f5a67242" +"checksum parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ab41b4aed082705d1056416ae4468b6ea99d52599ecf3169b00088d43113e337" +"checksum parking_lot_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "94c8c7923936b28d546dfd14d4472eaf34c99b14e1c973a32b3e6d4eb04298c9" +"checksum peeking_take_while 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099" +"checksum plain 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "b4596b6d070b27117e987119b4dac604f3c58cfb0b191112e24771b2faeac1a6" +"checksum proc-macro2 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "1b06e2f335f48d24442b35a19df506a835fb3547bc3c06ef27340da9acf5cae7" +"checksum proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)" = "4d317f9caece796be1980837fd5cb3dfec5613ebdb04ad0956deea83ce168915" +"checksum quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9274b940887ce9addde99c4eee6b5c44cc494b182b97e73dc8ffdcb3397fd3f0" +"checksum quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a" +"checksum quote 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9949cfe66888ffe1d53e6ec9d9f3b70714083854be20fd5e271b232a017401e8" +"checksum quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)" = "cdd8e04bd9c52e0342b406469d494fcb033be4bdbe5c606016defbb1681411e1" +"checksum rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca" +"checksum rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef" +"checksum rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b" +"checksum rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d0e7a549d590831370895ab7ba4ea0c1b6b011d106b5ff2da6eee112615e6dc0" +"checksum rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b40677c7be09ae76218dc623efbf7b18e34bced3f38883af07bb75630a21bc4" +"checksum rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ded997c9d5f13925be2a6fd7e66bf1872597f759fd9dd93513dd7e92e5a5ee08" +"checksum rand_jitter 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7b9ea758282efe12823e0d952ddb269d2e1897227e464919a554f2a03ef1b832" +"checksum rand_os 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b7c690732391ae0abafced5015ffb53656abfaec61b342290e5eb56b286a679d" +"checksum rand_pcg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "abf9b09b01790cfe0364f52bf32995ea3c39f4d2dd011eac241d2914146d0b44" +"checksum rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c" +"checksum rand_xoshiro 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "03b418169fb9c46533f326efd6eed2576699c44ca92d3052a066214a8d828929" +"checksum raw-cpuid 6.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "30a9d219c32c9132f7be513c18be77c9881c7107d2ab5569d205a6a0f0e6dc7d" +"checksum rayon 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "373814f27745b2686b350dd261bfd24576a6fb0e2c5919b3a2b6005f820b0473" +"checksum rayon-core 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b055d1e92aba6877574d8fe604a63c8b5df60f60e5982bf7ccbb1338ea527356" +"checksum rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" +"checksum redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)" = "423e376fffca3dfa06c9e9790a9ccd282fafb3cc6e6397d01dbf64f9bacc6b85" +"checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76" +"checksum regex 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "53ee8cfdddb2e0291adfb9f13d31d3bbe0a03c9a402c01b1e24188d86c35b24f" +"checksum regex-syntax 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "8c2f35eedad5295fdf00a63d7d4b238135723f92b434ec06774dad15c7ab0861" +"checksum remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3488ba1b9a2084d38645c4c08276a1752dcbf2c7130d74f1569681ad5d2799c5" +"checksum rustc-demangle 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "adacaae16d02b6ec37fdc7acfcddf365978de76d1983d3ee22afc260e1ca9619" +"checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" +"checksum ryu 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "eb9e9b8cde282a9fe6a42dd4681319bfb63f121b8a8ee9439c6f4107e58a46f7" +"checksum same-file 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8f20c4be53a8a1ff4c1f1b2bd14570d2f634628709752f0702ecdd2b3f9a5267" +"checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27" +"checksum scroll 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2f84d114ef17fd144153d608fba7c446b0145d038985e7a8cc5d08bb0ce20383" +"checksum scroll_derive 0.9.5 (registry+https://github.com/rust-lang/crates.io-index)" = "8f1aa96c45e7f5a91cb7fabe7b279f02fea7126239fc40b732316e8b6a2d0fcb" +"checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" +"checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" +"checksum serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)" = "92514fb95f900c9b5126e32d020f5c6d40564c27a5ea6d1d7d9f157a96623560" +"checksum serde-bench 0.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "d733da87e79faaac25616e33d26299a41143fd4cd42746cbb0e91d8feea243fd" +"checksum serde_bytes 0.10.5 (registry+https://github.com/rust-lang/crates.io-index)" = "defbb8a83d7f34cc8380751eeb892b825944222888aff18996ea7901f24aec88" +"checksum serde_derive 1.0.58 (registry+https://github.com/rust-lang/crates.io-index)" = "ac38f51a52a556cd17545798e29536885fb1a3fa63d6399f5ef650f4a7d35901" +"checksum serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)" = "5a23aa71d4a4d43fdbfaac00eff68ba8a06a51759a89ac3304323e800c4dd40d" +"checksum smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)" = "c4488ae950c49d403731982257768f48fada354a5203fe81f9bb6f43ca9002be" +"checksum stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dba1a27d3efae4351c8051072d619e3ade2820635c3958d826bfea39d59b54c8" +"checksum strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4f380125926a99e52bc279241539c018323fab05ad6368b56f93d9369ff550" +"checksum structopt 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "670ad348dc73012fcf78c71f06f9d942232cdd4c859d4b6975e27836c3efc0c3" +"checksum structopt-derive 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "ef98172b1a00b0bec738508d3726540edcbd186d50dfd326f2b1febbb3559f04" +"checksum syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d3b891b9015c88c576343b9b3e41c2c11a51c219ef067b264bd9c8aa9b441dad" +"checksum syn 0.13.11 (registry+https://github.com/rust-lang/crates.io-index)" = "14f9bf6292f3a61d2c716723fdb789a41bbe104168e6f496dc6497e531ea1b9b" +"checksum syn 0.15.27 (registry+https://github.com/rust-lang/crates.io-index)" = "525bd55255f03c816e5d7f615587bd13030c7103354fadb104993dcee6a788ec" +"checksum synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a393066ed9010ebaed60b9eafa373d4b1baac186dd7e008555b0f702b51945b6" +"checksum synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "73687139bf99285483c96ac0add482c3776528beac1d97d444f6e91f203a2015" +"checksum target-lexicon 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4af5e2227f0b887d591d3724b796a96eff04226104d872f5b3883fcd427d64b9" +"checksum tempfile 3.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "b86c784c88d98c801132806dadd3819ed29d8600836c4088e855cdf3e178ed8a" +"checksum termcolor 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "4096add70612622289f2fdcdbd5086dc81c1e2675e6ae58d6c4f62a16c6d7f2f" +"checksum termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "689a3bdfaab439fd92bc87df5c4c78417d3cbe537487274e9b0b2dce76e92096" +"checksum textwrap 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "307686869c93e71f94da64286f9a9524c0f308a9e1c87a583de8e9c9039ad3f6" +"checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b" +"checksum time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "db8dcfca086c1143c9270ac42a2bbd8a7ee477b78ac8e45b19abfb0cbede4b6f" +"checksum tinytemplate 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7655088894274afb52b807bd3c87072daa1fedd155068b8705cabfd628956115" +"checksum toml 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)" = "758664fc71a3a69038656bee8b6be6477d2a6c315a6b81f7081f591bffa4111f" +"checksum typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "612d636f949607bdf9b123b4a6f6d966dedf3ff669f7f045890d3a4a73948169" +"checksum ucd-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "535c204ee4d8434478593480b8f86ab45ec9aae0e83c568ca81abf0fd0e88f86" +"checksum unicode-segmentation 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "aa6024fc12ddfd1c6dbc14a80fa2324d4568849869b779f6bd37e5e4c03344d1" +"checksum unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "882386231c45df4700b275c7ff55b6f3698780a650026380e72dabe76fa46526" +"checksum unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f860d7d29cf02cb2f3f359fd35991af3d30bac52c57d265a3c461074cb4dc" +"checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" +"checksum utf8-ranges 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "796f7e48bef87609f7ade7e06495a87d5cd06c7866e6a5cbfceffc558a243737" +"checksum vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a" +"checksum version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd" +"checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" +"checksum wabt 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)" = "74e463a508e390cc7447e70f640fbf44ad52e1bd095314ace1fdf99516d32add" +"checksum wabt-sys 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)" = "a6265b25719e82598d104b3717375e37661d41753e2c84cde3f51050c7ed7e3c" +"checksum walkdir 2.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "9d9d7ed3431229a144296213105a390676cc49c9b6a72bd19f3176c98e129fa1" +"checksum wasmparser 0.22.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f46e666ecb4a406483a59a49f9d0c17f327e70da53a128eccddae2eadb95865c" +"checksum wasmparser 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b5e01c420bc7d36e778bd242e1167b079562ba8b34087122cc9057187026d060" +"checksum wasmparser 0.28.0 (registry+https://github.com/rust-lang/crates.io-index)" = "40f426b1929bd26517fb10702e2a8e520d1845c49567aa4d244f426f10b206c1" +"checksum which 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b57acb10231b9493c8472b20cb57317d0679a49e0bdbee44b3b803a6473af164" +"checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" +"checksum winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "92c1eb33641e276cfa214a0522acad57be5c56b10cb348b3c5117db75f3ac4b0" +"checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" +"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" +"checksum winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7168bab6e1daee33b4557efd0e95d5ca70a03706d39fa5f3fe7a236f584b03c9" +"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +"checksum wincolor 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "561ed901ae465d6185fa7864d63fbd5720d0ef718366c9a4dc83cf6170d7e9ba" diff --git a/lib/llvm-backend/Cargo.toml b/lib/llvm-backend/Cargo.toml index cdbfe63bf..a3290f3fd 100644 --- a/lib/llvm-backend/Cargo.toml +++ b/lib/llvm-backend/Cargo.toml @@ -5,7 +5,7 @@ authors = ["Lachlan Sneff "] edition = "2018" [dependencies] -wasmer-runtime-core = { path = "../runtime-core", version = "0.1.2" } +wasmer-runtime-core = { path = "../runtime-core", version = "0.2.1" } wasmparser = "0.28.0" inkwell = { git = "https://github.com/TheDan64/inkwell", branch = "llvm7-0" } hashbrown = "0.1.8" diff --git a/lib/llvm-backend/src/backend.rs b/lib/llvm-backend/src/backend.rs index f08f0fd84..60cbef939 100644 --- a/lib/llvm-backend/src/backend.rs +++ b/lib/llvm-backend/src/backend.rs @@ -10,6 +10,7 @@ use libc::{ PROT_WRITE, }; use std::{ + any::Any, ffi::CString, mem, ptr::{self, NonNull}, @@ -397,20 +398,17 @@ impl ProtectedCaller for LLVMProtectedCaller { .collect()) } else { Err(match trap_out { - WasmTrapType::Unreachable => RuntimeError::User { + WasmTrapType::Unreachable => RuntimeError::Trap { msg: "unreachable".into(), }, - WasmTrapType::IncorrectCallIndirectSignature => { - RuntimeError::IndirectCallSignature { - table: TableIndex::new(0), - } - } - WasmTrapType::MemoryOutOfBounds => RuntimeError::OutOfBoundsAccess { - memory: MemoryIndex::new(0), - addr: None, + WasmTrapType::IncorrectCallIndirectSignature => RuntimeError::Trap { + msg: "uncorrect call_indirect signature".into(), }, - WasmTrapType::Unknown => RuntimeError::Unknown { - msg: "unknown error".into(), + WasmTrapType::MemoryOutOfBounds => RuntimeError::Trap { + msg: "memory out-of-bounds access".into(), + }, + WasmTrapType::Unknown => RuntimeError::Trap { + msg: "unknown trap".into(), }, }) } @@ -422,8 +420,8 @@ impl ProtectedCaller for LLVMProtectedCaller { } impl UserTrapper for Placeholder { - unsafe fn do_early_trap(&self, msg: String) -> ! { - unimplemented!("do early trap: {}", msg) + unsafe fn do_early_trap(&self, _data: Box) -> ! { + unimplemented!("do early trap") } } From 7ef2c0dece933830ba6aa4640e1933afdf13f5af Mon Sep 17 00:00:00 2001 From: Lachlan Sneff Date: Mon, 4 Mar 2019 14:41:56 -0800 Subject: [PATCH 42/75] Fix execute after free issue with llvm (and presumably cranelift?) --- lib/llvm-backend/src/backend.rs | 2 +- lib/llvm-backend/src/code.rs | 16 +++---- lib/llvm-backend/src/intrinsics.rs | 8 +--- lib/runtime-core/src/import.rs | 28 +++++++++-- lib/runtime-core/src/instance.rs | 8 +++- lib/runtime/examples/call.rs | 74 +++++++++++++++++++----------- 6 files changed, 88 insertions(+), 48 deletions(-) diff --git a/lib/llvm-backend/src/backend.rs b/lib/llvm-backend/src/backend.rs index 60cbef939..d951c7fa0 100644 --- a/lib/llvm-backend/src/backend.rs +++ b/lib/llvm-backend/src/backend.rs @@ -278,7 +278,7 @@ impl LLVMBackend { info: &ModuleInfo, local_func_index: LocalFuncIndex, ) -> Option> { - let index = local_func_index.index(); + let index = info.imported_functions.len() + local_func_index.index(); let name = if cfg!(target_os = "macos") { format!("_fn{}", index) } else { diff --git a/lib/llvm-backend/src/code.rs b/lib/llvm-backend/src/code.rs index 51815f3f6..e58a5d06a 100644 --- a/lib/llvm-backend/src/code.rs +++ b/lib/llvm-backend/src/code.rs @@ -136,6 +136,8 @@ pub fn parse_function_bodies( pass_manager.add_aggressive_dce_pass(); pass_manager.run_on_module(&module); + // module.print_to_stderr(); + Ok((module, intrinsics)) } @@ -671,15 +673,11 @@ fn parse_function( let func_ptr_ty = llvm_sig.ptr_type(AddressSpace::Generic); - // Once we can just bitcast between pointer types, remove this. - let func_ptr = { - let ptr_int = builder.build_ptr_to_int( - func_ptr_untyped, - intrinsics.i64_ty, - "func_ptr_int", - ); - builder.build_int_to_ptr(ptr_int, func_ptr_ty, "typed_func_ptr") - }; + let func_ptr = builder.build_pointer_cast( + func_ptr_untyped, + func_ptr_ty, + "typed_func_ptr", + ); builder.build_call(func_ptr, ¶ms, &state.var_name()) } diff --git a/lib/llvm-backend/src/intrinsics.rs b/lib/llvm-backend/src/intrinsics.rs index 9e91c5911..78ce0ae12 100644 --- a/lib/llvm-backend/src/intrinsics.rs +++ b/lib/llvm-backend/src/intrinsics.rs @@ -197,7 +197,6 @@ impl Intrinsics { .ptr_type(AddressSpace::Generic) .as_basic_type_enum(), imported_func_ty - .ptr_type(AddressSpace::Generic) .ptr_type(AddressSpace::Generic) .as_basic_type_enum(), sigindex_ty @@ -713,16 +712,13 @@ impl<'a> CtxType<'a> { .build_load(func_array_ptr_ptr, "func_array_ptr") .into_pointer_value(); let const_index = intrinsics.i32_ty.const_int(index.index() as u64, false); - let imported_func_ptr_ptr = unsafe { + let imported_func_ptr = unsafe { cache_builder.build_in_bounds_gep( func_array_ptr, &[const_index], - "imported_func_ptr_ptr", + "imported_func_ptr", ) }; - let imported_func_ptr = cache_builder - .build_load(imported_func_ptr_ptr, "imported_func_ptr") - .into_pointer_value(); let (func_ptr_ptr, ctx_ptr_ptr) = unsafe { ( cache_builder.build_struct_gep(imported_func_ptr, 0, "func_ptr_ptr"), diff --git a/lib/runtime-core/src/import.rs b/lib/runtime-core/src/import.rs index 7073a5ac1..59d9da555 100644 --- a/lib/runtime-core/src/import.rs +++ b/lib/runtime-core/src/import.rs @@ -1,5 +1,9 @@ use crate::export::Export; use hashbrown::{hash_map::Entry, HashMap}; +use std::{ + cell::{Ref, RefCell}, + rc::Rc, +}; pub trait LikeNamespace { fn get_export(&self, name: &str) -> Option; @@ -37,14 +41,14 @@ impl IsExport for Export { /// } /// ``` pub struct ImportObject { - map: HashMap>, + map: Rc>>>, } impl ImportObject { /// Create a new `ImportObject`. pub fn new() -> Self { Self { - map: HashMap::new(), + map: Rc::new(RefCell::new(HashMap::new())), } } @@ -67,7 +71,9 @@ impl ImportObject { S: Into, N: LikeNamespace + 'static, { - match self.map.entry(name.into()) { + let mut map = self.map.borrow_mut(); + + match map.entry(name.into()) { Entry::Vacant(empty) => { empty.insert(Box::new(namespace)); None @@ -76,8 +82,20 @@ impl ImportObject { } } - pub fn get_namespace(&self, namespace: &str) -> Option<&(dyn LikeNamespace + 'static)> { - self.map.get(namespace).map(|namespace| &**namespace) + pub fn get_namespace(&self, namespace: &str) -> Option> { + let map_ref = self.map.borrow(); + + if map_ref.contains_key(namespace) { + Some(Ref::map(map_ref, |map| &*map[namespace])) + } else { + None + } + } + + pub fn clone_ref(&self) -> Self { + Self { + map: Rc::clone(&self.map), + } } } diff --git a/lib/runtime-core/src/instance.rs b/lib/runtime-core/src/instance.rs index 61e8f556d..3dee6ee50 100644 --- a/lib/runtime-core/src/instance.rs +++ b/lib/runtime-core/src/instance.rs @@ -39,6 +39,8 @@ impl Drop for InstanceInner { pub struct Instance { module: Arc, inner: Box, + #[allow(dead_code)] + import_object: ImportObject, } impl Instance { @@ -64,7 +66,11 @@ impl Instance { *inner.vmctx = vm::Ctx::new(&mut inner.backing, &mut inner.import_backing, &module) }; - let instance = Instance { module, inner }; + let instance = Instance { + module, + inner, + import_object: imports.clone_ref(), + }; if let Some(start_index) = instance.module.info.start_func { instance.call_with_index(start_index, &[])?; diff --git a/lib/runtime/examples/call.rs b/lib/runtime/examples/call.rs index e9ac58acc..679f01d27 100644 --- a/lib/runtime/examples/call.rs +++ b/lib/runtime/examples/call.rs @@ -1,53 +1,75 @@ -use wasmer_runtime::{compile, error, imports, Func, Value}; +use wasmer_runtime::{compile, error, imports, Ctx, Func, Value}; use wabt::wat2wasm; static WAT: &'static str = r#" (module - (type (;0;) (func (result i32))) - (type (;1;) (func (param i32 i32))) - (type (;2;) (func (param i32) (result i32))) - (func (;0;) (type 0) (result i32) - memory.size - i32.const 65536 - i32.mul) - (func (;1;) (type 1) (param i32 i32) - call 0 + (type (;0;) (func)) + (type (;1;) (func)) + (type (;2;) (func)) + (type (;3;) (func (result i32))) + (type (;4;) (func (result i32))) + (type (;5;) (func (param i32) (result i32))) + (type (;6;) (func (param i32))) + (import "spectest" "print_i32" (func (;0;) (type 6))) + (func (;1;) (type 0)) + (func (;2;) (type 1)) + (func (;3;) (type 4) (result i32) + i32.const 13) + (func (;4;) (type 5) (param i32) (result i32) local.get 0 - i32.sub - local.get 1 - i32.store) - (func (;2;) (type 2) (param i32) (result i32) - call 0 + i32.const 1 + i32.add) + (func (;5;) (type 5) (param i32) (result i32) local.get 0 - i32.add - i32.load) - (func (;3;) (type 2) (param i32) (result i32) + i32.const 2 + i32.sub) + (func (;6;) (type 6) (param i32) local.get 0 - memory.grow) - (memory (;0;) 1 2) - (export "store" (func 1)) - (export "load" (func 2)) - (export "memory.grow" (func 3))) + call 0) + (export "one" (func 3)) + (export "two" (func 4)) + (export "three" (func 5)) + (export "four" (func 6))) +"#; + +static WAT2: &'static str = r#" + (module + (type $t0 (func (param i32))) + (type $t1 (func)) + (func $print_i32 (export "print_i32") (type $t0) (param $lhs i32)) + (func $print (export "print") (type $t1)) + (table $table (export "table") 10 20 anyfunc) + (memory $memory (export "memory") 1 2) + (global $global_i32 (export "global_i32") i32 (i32.const 666))) "#; fn get_wasm() -> Vec { wat2wasm(WAT).unwrap() } +fn foobar(ctx: &mut Ctx) -> i32 { + 42 +} + fn main() -> Result<(), error::Error> { let wasm = get_wasm(); let module = compile(&wasm)?; - let imports = imports! {}; + let import_module = compile(&wat2wasm(WAT2).unwrap())?; + let import_instance = import_module.instantiate(&imports! {})?; + + let imports = imports! { + "spectest" => import_instance, + }; println!("instantiating"); let instance = module.instantiate(&imports)?; - let foo = instance.dyn_func("store")?; + let foo = instance.dyn_func("four")?; - let result = foo.call(&[Value::I32(0), Value::I32(1)]); + let result = foo.call(&[Value::I32(10)]); println!("result: {:?}", result); From 25c0cef5f7a40bc5aa6fef74cb84f70047457854 Mon Sep 17 00:00:00 2001 From: Lachlan Sneff Date: Mon, 4 Mar 2019 15:51:45 -0800 Subject: [PATCH 43/75] Up to 1242 passing spectests --- lib/llvm-backend/src/code.rs | 124 ++++++++++++++++++++++++++++- lib/llvm-backend/src/intrinsics.rs | 13 +-- 2 files changed, 125 insertions(+), 12 deletions(-) diff --git a/lib/llvm-backend/src/code.rs b/lib/llvm-backend/src/code.rs index e58a5d06a..7566d53dc 100644 --- a/lib/llvm-backend/src/code.rs +++ b/lib/llvm-backend/src/code.rs @@ -3,8 +3,8 @@ use inkwell::{ context::Context, module::{Linkage, Module}, passes::PassManager, - types::{BasicType, BasicTypeEnum, FunctionType, PointerType}, - values::{BasicValue, FunctionValue, PhiValue, PointerValue}, + types::{BasicType, BasicTypeEnum, FunctionType, IntType, PointerType}, + values::{BasicValue, FunctionValue, IntValue, PhiValue, PointerValue}, AddressSpace, FloatPredicate, IntPredicate, }; use smallvec::SmallVec; @@ -613,7 +613,7 @@ fn parse_function( let global_cache = ctx.global_cache(index); match global_cache { GlobalCache::Const { value } => { - state.push1(value.as_basic_value_enum()); + state.push1(value); } GlobalCache::Mut { ptr_to_value } => { let value = builder.build_load(ptr_to_value, "global_value"); @@ -882,24 +882,36 @@ fn parse_function( Operator::I32DivS | Operator::I64DivS => { let (v1, v2) = state.pop2()?; let (v1, v2) = (v1.into_int_value(), v2.into_int_value()); + + trap_if_zero_or_overflow(builder, intrinsics, context, &function, v1, v2); + let res = builder.build_int_signed_div(v1, v2, &state.var_name()); state.push1(res); } Operator::I32DivU | Operator::I64DivU => { let (v1, v2) = state.pop2()?; let (v1, v2) = (v1.into_int_value(), v2.into_int_value()); + + trap_if_zero(builder, intrinsics, context, &function, v2); + let res = builder.build_int_unsigned_div(v1, v2, &state.var_name()); state.push1(res); } Operator::I32RemS | Operator::I64RemS => { let (v1, v2) = state.pop2()?; let (v1, v2) = (v1.into_int_value(), v2.into_int_value()); + + trap_if_zero(builder, intrinsics, context, &function, v2); + let res = builder.build_int_signed_rem(v1, v2, &state.var_name()); state.push1(res); } Operator::I32RemU | Operator::I64RemU => { let (v1, v2) = state.pop2()?; let (v1, v2) = (v1.into_int_value(), v2.into_int_value()); + + trap_if_zero(builder, intrinsics, context, &function, v2); + let res = builder.build_int_unsigned_rem(v1, v2, &state.var_name()); state.push1(res); } @@ -2001,6 +2013,112 @@ fn parse_function( Ok(()) } +fn trap_if_zero_or_overflow( + builder: &Builder, + intrinsics: &Intrinsics, + context: &Context, + function: &FunctionValue, + left: IntValue, + right: IntValue, +) { + let int_type = left.get_type(); + + let (min_value, neg_one_value) = if int_type == intrinsics.i32_ty { + let min_value = int_type.const_int(i32::min_value() as u64, false); + let neg_one_value = int_type.const_int(-1i32 as u32 as u64, false); + (min_value, neg_one_value) + } else if int_type == intrinsics.i64_ty { + let min_value = int_type.const_int(i64::min_value() as u64, false); + let neg_one_value = int_type.const_int(-1i64 as u64, false); + (min_value, neg_one_value) + } else { + unreachable!() + }; + + let should_trap = builder.build_or( + builder.build_int_compare( + IntPredicate::EQ, + right, + int_type.const_int(0, false), + "divisor_is_zero", + ), + builder.build_and( + builder.build_int_compare(IntPredicate::EQ, left, min_value, "left_is_min"), + builder.build_int_compare(IntPredicate::EQ, right, neg_one_value, "right_is_neg_one"), + "div_will_overflow", + ), + "div_should_trap", + ); + + let should_trap = builder + .build_call( + intrinsics.expect_i1, + &[ + should_trap.as_basic_value_enum(), + intrinsics.i1_ty.const_int(0, false).as_basic_value_enum(), + ], + "should_trap_expect", + ) + .try_as_basic_value() + .left() + .unwrap() + .into_int_value(); + + let shouldnt_trap_block = context.append_basic_block(function, "shouldnt_trap_block"); + let should_trap_block = context.append_basic_block(function, "should_trap_block"); + builder.build_conditional_branch(should_trap, &should_trap_block, &shouldnt_trap_block); + builder.position_at_end(&should_trap_block); + builder.build_call( + intrinsics.throw_trap, + &[intrinsics.trap_memory_oob], + "throw", + ); + builder.build_unreachable(); + builder.position_at_end(&shouldnt_trap_block); +} + +fn trap_if_zero( + builder: &Builder, + intrinsics: &Intrinsics, + context: &Context, + function: &FunctionValue, + value: IntValue, +) { + let int_type = value.get_type(); + let should_trap = builder.build_int_compare( + IntPredicate::EQ, + value, + int_type.const_int(0, false), + "divisor_is_zero", + ); + + let should_trap = builder + .build_call( + intrinsics.expect_i1, + &[ + should_trap.as_basic_value_enum(), + intrinsics.i1_ty.const_int(0, false).as_basic_value_enum(), + ], + "should_trap_expect", + ) + .try_as_basic_value() + .left() + .unwrap() + .into_int_value(); + + let shouldnt_trap_block = context.append_basic_block(function, "shouldnt_trap_block"); + let should_trap_block = context.append_basic_block(function, "should_trap_block"); + builder.build_conditional_branch(should_trap, &should_trap_block, &shouldnt_trap_block); + builder.position_at_end(&should_trap_block); + builder.build_call( + intrinsics.throw_trap, + &[intrinsics.trap_memory_oob], + "throw", + ); + builder.build_unreachable(); + builder.position_at_end(&shouldnt_trap_block); +} + fn resolve_memory_ptr( builder: &Builder, intrinsics: &Intrinsics, diff --git a/lib/llvm-backend/src/intrinsics.rs b/lib/llvm-backend/src/intrinsics.rs index 78ce0ae12..f0764742b 100644 --- a/lib/llvm-backend/src/intrinsics.rs +++ b/lib/llvm-backend/src/intrinsics.rs @@ -419,7 +419,7 @@ struct TableCache { #[derive(Clone, Copy)] pub enum GlobalCache { Mut { ptr_to_value: PointerValue }, - Const { value: IntValue }, + Const { value: BasicValueEnum }, } struct ImportedFuncCache { @@ -675,11 +675,8 @@ impl<'a> CtxType<'a> { .build_load(global_ptr_ptr, "global_ptr") .into_pointer_value(); - let global_ptr_typed = { - let int = - cache_builder.build_ptr_to_int(global_ptr, intrinsics.i64_ty, "global_ptr_int"); - cache_builder.build_int_to_ptr(int, llvm_ptr_ty, "global_ptr_typed") - }; + let global_ptr_typed = + cache_builder.build_pointer_cast(global_ptr, llvm_ptr_ty, "global_ptr_typed"); if mutable { GlobalCache::Mut { @@ -687,9 +684,7 @@ impl<'a> CtxType<'a> { } } else { GlobalCache::Const { - value: cache_builder - .build_load(global_ptr_typed, "global_value") - .into_int_value(), + value: cache_builder.build_load(global_ptr_typed, "global_value"), } } }) From 2969409ca74ccd0b3ece01d9ad9a11968bbc0c09 Mon Sep 17 00:00:00 2001 From: Lachlan Sneff Date: Mon, 4 Mar 2019 16:44:46 -0800 Subject: [PATCH 44/75] Add hacky reinterpret instructions and pop used arguments off the value stack --- lib/llvm-backend/src/code.rs | 64 ++++++++++++++++--- lib/runtime/examples/call.rs | 119 ++++++++++++++++++++++++----------- 2 files changed, 136 insertions(+), 47 deletions(-) diff --git a/lib/llvm-backend/src/code.rs b/lib/llvm-backend/src/code.rs index 7566d53dc..5cff36abd 100644 --- a/lib/llvm-backend/src/code.rs +++ b/lib/llvm-backend/src/code.rs @@ -581,13 +581,23 @@ fn parse_function( state.push1(i); } Operator::F32Const { value } => { - let f = intrinsics - .f32_ty - .const_float(f32::from_bits(value.bits()) as f64); + let bits = intrinsics.i32_ty.const_int(value.bits() as u64, false); + let space = + builder.build_alloca(intrinsics.f32_ty.as_basic_type_enum(), "const_space"); + let i32_space = + builder.build_pointer_cast(space, intrinsics.i32_ptr_ty, "i32_space"); + builder.build_store(i32_space, bits); + let f = builder.build_load(space, "f"); state.push1(f); } Operator::F64Const { value } => { - let f = intrinsics.f64_ty.const_float(f64::from_bits(value.bits())); + let bits = intrinsics.i64_ty.const_int(value.bits(), false); + let space = + builder.build_alloca(intrinsics.f64_ty.as_basic_type_enum(), "const_space"); + let i64_space = + builder.build_pointer_cast(space, intrinsics.i64_ptr_ty, "i32_space"); + builder.build_store(i64_space, bits); + let f = builder.build_load(space, "f"); state.push1(f); } @@ -683,6 +693,8 @@ fn parse_function( } }; + state.popn(func_sig.params().len())?; + if let Some(basic_value) = call_site.try_as_basic_value().left() { match func_sig.returns().len() { 1 => state.push1(basic_value), @@ -1521,11 +1533,45 @@ fn parse_function( builder.build_unsigned_int_to_float(v1, intrinsics.f64_ty, &state.var_name()); state.push1(res); } - Operator::I32ReinterpretF32 - | Operator::F32ReinterpretI32 - | Operator::I64ReinterpretF64 - | Operator::F64ReinterpretI64 => { - unimplemented!("waiting on better bitcasting support in inkwell") + Operator::I32ReinterpretF32 => { + let v = state.pop1()?; + let space = + builder.build_alloca(intrinsics.i32_ty.as_basic_type_enum(), &state.var_name()); + let f32_space = + builder.build_pointer_cast(space, intrinsics.f32_ptr_ty, &state.var_name()); + builder.build_store(f32_space, v); + let int = builder.build_load(space, &state.var_name()); + state.push1(int); + } + Operator::I64ReinterpretF64 => { + let v = state.pop1()?; + let space = + builder.build_alloca(intrinsics.i64_ty.as_basic_type_enum(), &state.var_name()); + let f64_space = + builder.build_pointer_cast(space, intrinsics.f64_ptr_ty, &state.var_name()); + builder.build_store(f64_space, v); + let int = builder.build_load(space, &state.var_name()); + state.push1(int); + } + Operator::F32ReinterpretI32 => { + let v = state.pop1()?; + let space = + builder.build_alloca(intrinsics.f32_ty.as_basic_type_enum(), &state.var_name()); + let i32_space = + builder.build_pointer_cast(space, intrinsics.i32_ptr_ty, &state.var_name()); + builder.build_store(i32_space, v); + let f = builder.build_load(space, &state.var_name()); + state.push1(f); + } + Operator::F64ReinterpretI64 => { + let v = state.pop1()?; + let space = + builder.build_alloca(intrinsics.f64_ty.as_basic_type_enum(), &state.var_name()); + let i64_space = + builder.build_pointer_cast(space, intrinsics.i64_ptr_ty, &state.var_name()); + builder.build_store(i64_space, v); + let f = builder.build_load(space, &state.var_name()); + state.push1(f); } /*************************** diff --git a/lib/runtime/examples/call.rs b/lib/runtime/examples/call.rs index 679f01d27..c2716bb6c 100644 --- a/lib/runtime/examples/call.rs +++ b/lib/runtime/examples/call.rs @@ -4,45 +4,88 @@ use wabt::wat2wasm; static WAT: &'static str = r#" (module - (type (;0;) (func)) - (type (;1;) (func)) - (type (;2;) (func)) - (type (;3;) (func (result i32))) - (type (;4;) (func (result i32))) - (type (;5;) (func (param i32) (result i32))) - (type (;6;) (func (param i32))) - (import "spectest" "print_i32" (func (;0;) (type 6))) - (func (;1;) (type 0)) - (func (;2;) (type 1)) - (func (;3;) (type 4) (result i32) - i32.const 13) - (func (;4;) (type 5) (param i32) (result i32) + (type (;0;) (func (param i32 i32))) + (type (;1;) (func (param i32 i64))) + (type (;2;) (func (param i32) (result i32))) + (type (;3;) (func (param i32) (result i64))) + (type (;4;) (func (param i64) (result i64))) + (type (;5;) (func (param f32) (result f32))) + (type (;6;) (func (param f64) (result f64))) + (func (;0;) (type 0) (param i32 i32) + local.get 0 + local.get 1 + i32.store8 local.get 0 i32.const 1 - i32.add) - (func (;5;) (type 5) (param i32) (result i32) + i32.add + local.get 1 + i32.const 8 + i32.shr_u + i32.store8) + (func (;1;) (type 0) (param i32 i32) + local.get 0 + local.get 1 + call 0 local.get 0 i32.const 2 - i32.sub) - (func (;6;) (type 6) (param i32) - local.get 0 + i32.add + local.get 1 + i32.const 16 + i32.shr_u call 0) - (export "one" (func 3)) - (export "two" (func 4)) - (export "three" (func 5)) - (export "four" (func 6))) + (func (;2;) (type 1) (param i32 i64) + local.get 0 + local.get 1 + i32.wrap_i64 + call 1 + local.get 0 + i32.const 4 + i32.add + local.get 1 + i64.const 32 + i64.shr_u + i32.wrap_i64 + call 1) + (func (;3;) (type 2) (param i32) (result i32) + local.get 0 + i32.load8_u + local.get 0 + i32.const 1 + i32.add + i32.load8_u + i32.const 8 + i32.shl + i32.or) + (func (;4;) (type 2) (param i32) (result i32) + local.get 0 + call 3 + local.get 0 + i32.const 2 + i32.add + call 3 + i32.const 16 + i32.shl + i32.or) + (func (;5;) (type 3) (param i32) (result i64) + local.get 0 + i64.extend_i32_u + local.get 0 + call 4 + i64.extend_i32_u + i64.or) + (memory (;0;) 1)) "#; -static WAT2: &'static str = r#" - (module - (type $t0 (func (param i32))) - (type $t1 (func)) - (func $print_i32 (export "print_i32") (type $t0) (param $lhs i32)) - (func $print (export "print") (type $t1)) - (table $table (export "table") 10 20 anyfunc) - (memory $memory (export "memory") 1 2) - (global $global_i32 (export "global_i32") i32 (i32.const 666))) -"#; +// static WAT2: &'static str = r#" +// (module +// (type $t0 (func (param i32))) +// (type $t1 (func)) +// (func $print_i32 (export "print_i32") (type $t0) (param $lhs i32)) +// (func $print (export "print") (type $t1)) +// (table $table (export "table") 10 20 anyfunc) +// (memory $memory (export "memory") 1 2) +// (global $global_i32 (export "global_i32") i32 (i32.const 666))) +// "#; fn get_wasm() -> Vec { wat2wasm(WAT).unwrap() @@ -57,15 +100,15 @@ fn main() -> Result<(), error::Error> { let module = compile(&wasm)?; - let import_module = compile(&wat2wasm(WAT2).unwrap())?; - let import_instance = import_module.instantiate(&imports! {})?; + // let import_module = compile(&wat2wasm(WAT2).unwrap())?; + // let import_instance = import_module.instantiate(&imports! {})?; - let imports = imports! { - "spectest" => import_instance, - }; + // let imports = imports! { + // "spectest" => import_instance, + // }; println!("instantiating"); - let instance = module.instantiate(&imports)?; + let instance = module.instantiate(&imports! {})?; let foo = instance.dyn_func("four")?; From 3be714489287f975335614949ae8927bf5e05209 Mon Sep 17 00:00:00 2001 From: Lachlan Sneff Date: Mon, 4 Mar 2019 17:37:05 -0800 Subject: [PATCH 45/75] Some cleanup --- lib/llvm-backend/cpp/object_loader.cpp | 1 - lib/llvm-backend/src/backend.rs | 2 +- lib/llvm-backend/src/code.rs | 8 ++++---- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/lib/llvm-backend/cpp/object_loader.cpp b/lib/llvm-backend/cpp/object_loader.cpp index ff6dbe2d1..968618068 100644 --- a/lib/llvm-backend/cpp/object_loader.cpp +++ b/lib/llvm-backend/cpp/object_loader.cpp @@ -153,7 +153,6 @@ public: private: llvm::JITEvaluatedSymbol symbol_lookup(llvm::StringRef name) { - std::cout << "symbol name: " << (std::string)name << std::endl; uint64_t addr = callbacks.lookup_vm_symbol(name.data(), name.size()); return llvm::JITEvaluatedSymbol(addr, llvm::JITSymbolFlags::None); diff --git a/lib/llvm-backend/src/backend.rs b/lib/llvm-backend/src/backend.rs index d951c7fa0..749f47af1 100644 --- a/lib/llvm-backend/src/backend.rs +++ b/lib/llvm-backend/src/backend.rs @@ -233,7 +233,7 @@ impl LLVMBackend { &triple, &TargetMachine::get_host_cpu_name().to_string(), &TargetMachine::get_host_cpu_features().to_string(), - OptimizationLevel::Default, + OptimizationLevel::Aggressive, RelocMode::PIC, CodeModel::Default, ) diff --git a/lib/llvm-backend/src/code.rs b/lib/llvm-backend/src/code.rs index 5cff36abd..ef9ca15af 100644 --- a/lib/llvm-backend/src/code.rs +++ b/lib/llvm-backend/src/code.rs @@ -123,13 +123,13 @@ pub fn parse_function_bodies( generate_trampolines(info, &signatures, &module, &context, &builder, &intrinsics); let pass_manager = PassManager::create_for_module(); - pass_manager.add_verifier_pass(); + // pass_manager.add_verifier_pass(); pass_manager.add_function_inlining_pass(); pass_manager.add_promote_memory_to_register_pass(); pass_manager.add_cfg_simplification_pass(); - pass_manager.add_instruction_combining_pass(); - // pass_manager.add_aggressive_inst_combiner_pass(); - // pass_manager.add_merged_load_store_motion_pass(); + // pass_manager.add_instruction_combining_pass(); + pass_manager.add_aggressive_inst_combiner_pass(); + pass_manager.add_merged_load_store_motion_pass(); // pass_manager.add_sccp_pass(); pass_manager.add_gvn_pass(); // pass_manager.add_new_gvn_pass(); From fe8f8a013284b2f3631c54edd8329fbe974b0028 Mon Sep 17 00:00:00 2001 From: Lachlan Sneff Date: Mon, 4 Mar 2019 19:56:02 -0800 Subject: [PATCH 46/75] Add illegal arithmetic runtime error --- lib/llvm-backend/cpp/object_loader.hh | 8 ++- lib/llvm-backend/src/backend.rs | 8 +++ lib/llvm-backend/src/code.rs | 12 ++-- lib/llvm-backend/src/intrinsics.rs | 2 + lib/runtime/examples/call.rs | 82 ++++----------------------- 5 files changed, 35 insertions(+), 77 deletions(-) diff --git a/lib/llvm-backend/cpp/object_loader.hh b/lib/llvm-backend/cpp/object_loader.hh index 880d97b3f..d22acb919 100644 --- a/lib/llvm-backend/cpp/object_loader.hh +++ b/lib/llvm-backend/cpp/object_loader.hh @@ -70,6 +70,7 @@ public: IncorrectCallIndirectSignature = 1, MemoryOutOfBounds = 2, CallIndirectOOB = 3, + IllegalArithmetic = 4, Unknown, }; @@ -98,6 +99,12 @@ private: case Type::MemoryOutOfBounds: out << "memory access out-of-bounds"; break; + case Type::CallIndirectOOB: + out << "call_indirect out-of-bounds"; + break; + case Type::IllegalArithmetic: + out << "illegal arithmetic operation"; + break; case Type::Unknown: default: out << "unknown"; @@ -142,7 +149,6 @@ extern "C" { } [[noreturn]] void throw_trap(WasmTrap::Type ty) { - std::cout << "throwing trap: " << ty << std::endl; throw WasmTrap(ty); } diff --git a/lib/llvm-backend/src/backend.rs b/lib/llvm-backend/src/backend.rs index 749f47af1..bd8f25bb3 100644 --- a/lib/llvm-backend/src/backend.rs +++ b/lib/llvm-backend/src/backend.rs @@ -61,6 +61,8 @@ enum WasmTrapType { Unreachable = 0, IncorrectCallIndirectSignature = 1, MemoryOutOfBounds = 2, + CallIndirectOOB = 3, + IllegalArithmetic = 4, Unknown, } @@ -407,6 +409,12 @@ impl ProtectedCaller for LLVMProtectedCaller { WasmTrapType::MemoryOutOfBounds => RuntimeError::Trap { msg: "memory out-of-bounds access".into(), }, + WasmTrapType::CallIndirectOOB => RuntimeError::Trap { + msg: "call_indirect out-of-bounds".into(), + }, + WasmTrapType::IllegalArithmetic => RuntimeError::Trap { + msg: "illegal arithmetic operation".into(), + }, WasmTrapType::Unknown => RuntimeError::Trap { msg: "unknown trap".into(), }, diff --git a/lib/llvm-backend/src/code.rs b/lib/llvm-backend/src/code.rs index ef9ca15af..c223900f5 100644 --- a/lib/llvm-backend/src/code.rs +++ b/lib/llvm-backend/src/code.rs @@ -122,6 +122,8 @@ pub fn parse_function_bodies( generate_trampolines(info, &signatures, &module, &context, &builder, &intrinsics); + println!("done generating ir"); + let pass_manager = PassManager::create_for_module(); // pass_manager.add_verifier_pass(); pass_manager.add_function_inlining_pass(); @@ -131,11 +133,13 @@ pub fn parse_function_bodies( pass_manager.add_aggressive_inst_combiner_pass(); pass_manager.add_merged_load_store_motion_pass(); // pass_manager.add_sccp_pass(); - pass_manager.add_gvn_pass(); - // pass_manager.add_new_gvn_pass(); + // pass_manager.add_gvn_pass(); + pass_manager.add_new_gvn_pass(); pass_manager.add_aggressive_dce_pass(); pass_manager.run_on_module(&module); + println!("done optimizing ir"); + // module.print_to_stderr(); Ok((module, intrinsics)) @@ -2116,7 +2120,7 @@ fn trap_if_zero_or_overflow( builder.position_at_end(&should_trap_block); builder.build_call( intrinsics.throw_trap, - &[intrinsics.trap_memory_oob], + &[intrinsics.trap_illegal_arithmetic], "throw", ); builder.build_unreachable(); @@ -2158,7 +2162,7 @@ fn trap_if_zero( builder.position_at_end(&should_trap_block); builder.build_call( intrinsics.throw_trap, - &[intrinsics.trap_memory_oob], + &[intrinsics.trap_illegal_arithmetic], "throw", ); builder.build_unreachable(); diff --git a/lib/llvm-backend/src/intrinsics.rs b/lib/llvm-backend/src/intrinsics.rs index f0764742b..98c41326e 100644 --- a/lib/llvm-backend/src/intrinsics.rs +++ b/lib/llvm-backend/src/intrinsics.rs @@ -97,6 +97,7 @@ pub struct Intrinsics { pub trap_call_indirect_sig: BasicValueEnum, pub trap_call_indirect_oob: BasicValueEnum, pub trap_memory_oob: BasicValueEnum, + pub trap_illegal_arithmetic: BasicValueEnum, // VM intrinsics. pub memory_grow_dynamic_local: FunctionValue, @@ -295,6 +296,7 @@ impl Intrinsics { trap_call_indirect_sig: i32_ty.const_int(1, false).as_basic_value_enum(), trap_call_indirect_oob: i32_ty.const_int(3, false).as_basic_value_enum(), trap_memory_oob: i32_ty.const_int(2, false).as_basic_value_enum(), + trap_illegal_arithmetic: i32_ty.const_int(4, false).as_basic_value_enum(), // VM intrinsics. memory_grow_dynamic_local: module.add_function( diff --git a/lib/runtime/examples/call.rs b/lib/runtime/examples/call.rs index c2716bb6c..dbd29c7e8 100644 --- a/lib/runtime/examples/call.rs +++ b/lib/runtime/examples/call.rs @@ -4,76 +4,14 @@ use wabt::wat2wasm; static WAT: &'static str = r#" (module - (type (;0;) (func (param i32 i32))) - (type (;1;) (func (param i32 i64))) - (type (;2;) (func (param i32) (result i32))) - (type (;3;) (func (param i32) (result i64))) - (type (;4;) (func (param i64) (result i64))) - (type (;5;) (func (param f32) (result f32))) - (type (;6;) (func (param f64) (result f64))) - (func (;0;) (type 0) (param i32 i32) - local.get 0 - local.get 1 - i32.store8 - local.get 0 - i32.const 1 - i32.add - local.get 1 - i32.const 8 - i32.shr_u - i32.store8) - (func (;1;) (type 0) (param i32 i32) - local.get 0 - local.get 1 - call 0 - local.get 0 - i32.const 2 - i32.add - local.get 1 - i32.const 16 - i32.shr_u - call 0) - (func (;2;) (type 1) (param i32 i64) - local.get 0 - local.get 1 - i32.wrap_i64 - call 1 - local.get 0 - i32.const 4 - i32.add - local.get 1 - i64.const 32 - i64.shr_u - i32.wrap_i64 - call 1) - (func (;3;) (type 2) (param i32) (result i32) - local.get 0 - i32.load8_u - local.get 0 - i32.const 1 - i32.add - i32.load8_u - i32.const 8 - i32.shl - i32.or) - (func (;4;) (type 2) (param i32) (result i32) - local.get 0 - call 3 - local.get 0 - i32.const 2 - i32.add - call 3 - i32.const 16 - i32.shl - i32.or) - (func (;5;) (type 3) (param i32) (result i64) - local.get 0 - i64.extend_i32_u - local.get 0 - call 4 - i64.extend_i32_u - i64.or) - (memory (;0;) 1)) + (type (;0;) (func (result i32))) + (func $dbz (result i32) + i32.const 42 + i32.const 0 + i32.div_u + ) + (export "dbz" (func $dbz)) + ) "#; // static WAT2: &'static str = r#" @@ -110,9 +48,9 @@ fn main() -> Result<(), error::Error> { println!("instantiating"); let instance = module.instantiate(&imports! {})?; - let foo = instance.dyn_func("four")?; + let foo = instance.dyn_func("dbz")?; - let result = foo.call(&[Value::I32(10)]); + let result = foo.call(&[]); println!("result: {:?}", result); From f2b927bcd86891c3c644ee3f85f3cfe8977e6d32 Mon Sep 17 00:00:00 2001 From: Lachlan Sneff Date: Mon, 4 Mar 2019 20:00:56 -0800 Subject: [PATCH 47/75] Remove debug print --- lib/llvm-backend/src/code.rs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/lib/llvm-backend/src/code.rs b/lib/llvm-backend/src/code.rs index c223900f5..38d5ac7b6 100644 --- a/lib/llvm-backend/src/code.rs +++ b/lib/llvm-backend/src/code.rs @@ -122,8 +122,6 @@ pub fn parse_function_bodies( generate_trampolines(info, &signatures, &module, &context, &builder, &intrinsics); - println!("done generating ir"); - let pass_manager = PassManager::create_for_module(); // pass_manager.add_verifier_pass(); pass_manager.add_function_inlining_pass(); @@ -138,8 +136,6 @@ pub fn parse_function_bodies( pass_manager.add_aggressive_dce_pass(); pass_manager.run_on_module(&module); - println!("done optimizing ir"); - // module.print_to_stderr(); Ok((module, intrinsics)) From c86c910054610368688b63c90a8b8143b8a4d654 Mon Sep 17 00:00:00 2001 From: Lachlan Sneff Date: Tue, 5 Mar 2019 11:50:56 -0800 Subject: [PATCH 48/75] Add partiality to float truncation --- lib/llvm-backend/src/code.rs | 252 ++++++++++++++++++++++++++++++++--- 1 file changed, 235 insertions(+), 17 deletions(-) diff --git a/lib/llvm-backend/src/code.rs b/lib/llvm-backend/src/code.rs index 38d5ac7b6..3d9f82153 100644 --- a/lib/llvm-backend/src/code.rs +++ b/lib/llvm-backend/src/code.rs @@ -4,7 +4,7 @@ use inkwell::{ module::{Linkage, Module}, passes::PassManager, types::{BasicType, BasicTypeEnum, FunctionType, IntType, PointerType}, - values::{BasicValue, FunctionValue, IntValue, PhiValue, PointerValue}, + values::{BasicValue, FloatValue, FunctionValue, IntValue, PhiValue, PointerValue}, AddressSpace, FloatPredicate, IntPredicate, }; use smallvec::SmallVec; @@ -1463,37 +1463,145 @@ fn parse_function( let res = builder.build_int_z_extend(v1, intrinsics.i64_ty, &state.var_name()); state.push1(res); } - Operator::I32TruncSF32 - | Operator::I32TruncSF64 - | Operator::I32TruncSSatF32 - | Operator::I32TruncSSatF64 => { + Operator::I32TruncSF32 => { + let v1 = state.pop1()?.into_float_value(); + trap_if_not_representatable_as_int( + builder, + intrinsics, + context, + &function, + -2147483904.0, + 2147483648.0, + v1, + ); + let res = + builder.build_float_to_signed_int(v1, intrinsics.i32_ty, &state.var_name()); + state.push1(res); + } + Operator::I32TruncSF64 => { + let v1 = state.pop1()?.into_float_value(); + trap_if_not_representatable_as_int( + builder, + intrinsics, + context, + &function, + -2147483649.0, + 2147483648.0, + v1, + ); + let res = + builder.build_float_to_signed_int(v1, intrinsics.i32_ty, &state.var_name()); + state.push1(res); + } + Operator::I32TruncSSatF32 | Operator::I32TruncSSatF64 => { let v1 = state.pop1()?.into_float_value(); let res = builder.build_float_to_signed_int(v1, intrinsics.i32_ty, &state.var_name()); state.push1(res); } - Operator::I64TruncSF32 - | Operator::I64TruncSF64 - | Operator::I64TruncSSatF32 - | Operator::I64TruncSSatF64 => { + Operator::I64TruncSF32 => { + let v1 = state.pop1()?.into_float_value(); + trap_if_not_representatable_as_int( + builder, + intrinsics, + context, + &function, + -9223373136366403584.0, + 9223372036854775808.0, + v1, + ); + let res = + builder.build_float_to_signed_int(v1, intrinsics.i64_ty, &state.var_name()); + state.push1(res); + } + Operator::I64TruncSF64 => { + let v1 = state.pop1()?.into_float_value(); + trap_if_not_representatable_as_int( + builder, + intrinsics, + context, + &function, + -9223372036854777856.0, + 9223372036854775808.0, + v1, + ); + let res = + builder.build_float_to_signed_int(v1, intrinsics.i64_ty, &state.var_name()); + state.push1(res); + } + Operator::I64TruncSSatF32 | Operator::I64TruncSSatF64 => { let v1 = state.pop1()?.into_float_value(); let res = builder.build_float_to_signed_int(v1, intrinsics.i64_ty, &state.var_name()); state.push1(res); } - Operator::I32TruncUF32 - | Operator::I32TruncUF64 - | Operator::I32TruncUSatF32 - | Operator::I32TruncUSatF64 => { + Operator::I32TruncUF32 => { + let v1 = state.pop1()?.into_float_value(); + trap_if_not_representatable_as_int( + builder, + intrinsics, + context, + &function, + -1.0, + 4294967296.0, + v1, + ); + let res = + builder.build_float_to_unsigned_int(v1, intrinsics.i32_ty, &state.var_name()); + state.push1(res); + } + Operator::I32TruncUF64 => { + let v1 = state.pop1()?.into_float_value(); + trap_if_not_representatable_as_int( + builder, + intrinsics, + context, + &function, + -1.0, + 4294967296.0, + v1, + ); + let res = + builder.build_float_to_unsigned_int(v1, intrinsics.i32_ty, &state.var_name()); + state.push1(res); + } + Operator::I32TruncUSatF32 | Operator::I32TruncUSatF64 => { let v1 = state.pop1()?.into_float_value(); let res = builder.build_float_to_unsigned_int(v1, intrinsics.i32_ty, &state.var_name()); state.push1(res); } - Operator::I64TruncUF32 - | Operator::I64TruncUF64 - | Operator::I64TruncUSatF32 - | Operator::I64TruncUSatF64 => { + Operator::I64TruncUF32 => { + let v1 = state.pop1()?.into_float_value(); + trap_if_not_representatable_as_int( + builder, + intrinsics, + context, + &function, + -1.0, + 18446744073709551616.0, + v1, + ); + let res = + builder.build_float_to_unsigned_int(v1, intrinsics.i64_ty, &state.var_name()); + state.push1(res); + } + Operator::I64TruncUF64 => { + let v1 = state.pop1()?.into_float_value(); + trap_if_not_representatable_as_int( + builder, + intrinsics, + context, + &function, + -1.0, + 18446744073709551616.0, + v1, + ); + let res = + builder.build_float_to_unsigned_int(v1, intrinsics.i64_ty, &state.var_name()); + state.push1(res); + } + Operator::I64TruncUSatF32 | Operator::I64TruncUSatF64 => { let v1 = state.pop1()?.into_float_value(); let res = builder.build_float_to_unsigned_int(v1, intrinsics.i64_ty, &state.var_name()); @@ -2059,6 +2167,116 @@ fn parse_function( Ok(()) } +fn trap_if_not_representatable_as_int( + builder: &Builder, + intrinsics: &Intrinsics, + context: &Context, + function: &FunctionValue, + lower_bounds: f64, + upper_bound: f64, + value: FloatValue, +) { + enum FloatSize { + Bits32, + Bits64, + } + + let failure_block = context.append_basic_block(function, "conversion_failure_block"); + let continue_block = context.append_basic_block(function, "conversion_success_block"); + + let float_ty = value.get_type(); + let (int_ty, float_ptr_ty, float_size) = if float_ty == intrinsics.f32_ty { + (intrinsics.i32_ty, intrinsics.f32_ptr_ty, FloatSize::Bits32) + } else if float_ty == intrinsics.f64_ty { + (intrinsics.i64_ty, intrinsics.f64_ptr_ty, FloatSize::Bits64) + } else { + unreachable!() + }; + + let (exponent, invalid_exponent) = { + let float_bits = { + let space = builder.build_alloca(int_ty, "space"); + let float_ptr = builder.build_pointer_cast(space, float_ptr_ty, "float_ptr"); + builder.build_store(float_ptr, value); + builder.build_load(space, "float_bits").into_int_value() + }; + + let (shift_amount, exponent_mask, invalid_exponent) = match float_size { + FloatSize::Bits32 => (23, 0b01111111100000000000000000000000, 0b11111111), + FloatSize::Bits64 => ( + 52, + 0b0111111111110000000000000000000000000000000000000000000000000000, + 0b11111111111, + ), + }; + + let masked = builder.build_and( + float_bits, + int_ty.const_int(exponent_mask, false), + "masked_bits", + ); + + ( + builder.build_right_shift( + float_bits, + int_ty.const_int(shift_amount, false), + false, + "exponent", + ), + invalid_exponent, + ) + }; + + let is_invalid_float = builder.build_or( + builder.build_int_compare( + IntPredicate::EQ, + exponent, + int_ty.const_int(invalid_exponent, false), + "is_not_normal", + ), + builder.build_or( + builder.build_float_compare( + FloatPredicate::ULT, + value, + float_ty.const_float(lower_bounds), + "less_than_lower_bounds", + ), + builder.build_float_compare( + FloatPredicate::UGT, + value, + float_ty.const_float(upper_bound), + "greater_than_upper_bounds", + ), + "float_not_in_bounds", + ), + "is_invalid_float", + ); + + let is_invalid_float = builder + .build_call( + intrinsics.expect_i1, + &[ + is_invalid_float.as_basic_value_enum(), + intrinsics.i1_ty.const_int(0, false).as_basic_value_enum(), + ], + "is_invalid_float_expect", + ) + .try_as_basic_value() + .left() + .unwrap() + .into_int_value(); + + builder.build_conditional_branch(is_invalid_float, &failure_block, &continue_block); + builder.position_at_end(&failure_block); + builder.build_call( + intrinsics.throw_trap, + &[intrinsics.trap_illegal_arithmetic], + "throw", + ); + builder.build_unreachable(); + builder.position_at_end(&continue_block); +} + fn trap_if_zero_or_overflow( builder: &Builder, intrinsics: &Intrinsics, From 276e5125b512d4a680c43145bf1be429353bf605 Mon Sep 17 00:00:00 2001 From: Lachlan Sneff Date: Tue, 5 Mar 2019 13:23:26 -0800 Subject: [PATCH 49/75] Filter out -fno-exceptions from `llvm-config --cxxflags` --- lib/llvm-backend/build.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/llvm-backend/build.rs b/lib/llvm-backend/build.rs index 33ce4525d..062a5a5fe 100644 --- a/lib/llvm-backend/build.rs +++ b/lib/llvm-backend/build.rs @@ -199,6 +199,7 @@ fn get_llvm_cxxflags() -> String { output .split(&[' ', '\n'][..]) .filter(|word| !word.starts_with("-W")) + .filter(|word| word != &"-fno-exceptions") .collect::>() .join(" ") } From ae8676df443edd0c3f619da16ef86f7abe647527 Mon Sep 17 00:00:00 2001 From: Lachlan Sneff Date: Tue, 5 Mar 2019 13:32:02 -0800 Subject: [PATCH 50/75] Attempt to update circleci config to install llvm --- .circleci/config.yml | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/.circleci/config.yml b/.circleci/config.yml index 52160f216..260717e0b 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -13,6 +13,9 @@ jobs: name: Install dependencies command: | sudo apt-get install -y cmake + curl -O https://releases.llvm.org/7.0.0/clang+llvm-7.0.0-x86_64-linux-gnu-ubuntu-16.04.tar.xz + tar xf clang+llvm-7.0.0-x86_64-linux-gnu-ubuntu-16.04.tar.xz + export LLVM_SYS_70_PREFIX="`pwd`/clang+llvm-7.0.0-x86_64-linux-gnu-ubuntu-16.04/" - run: name: Install lint deps command: | @@ -41,6 +44,9 @@ jobs: name: Install dependencies command: | sudo apt-get install -y cmake + curl -O https://releases.llvm.org/7.0.0/clang+llvm-7.0.0-x86_64-linux-gnu-ubuntu-16.04.tar.xz + tar xf clang+llvm-7.0.0-x86_64-linux-gnu-ubuntu-16.04.tar.xz + export LLVM_SYS_70_PREFIX="`pwd`/clang+llvm-7.0.0-x86_64-linux-gnu-ubuntu-16.04/" - run: make test - run: make integration-tests - save_cache: @@ -66,6 +72,10 @@ jobs: curl -O https://cmake.org/files/v3.4/cmake-3.4.1-Darwin-x86_64.tar.gz tar xf cmake-3.4.1-Darwin-x86_64.tar.gz export PATH="`pwd`/cmake-3.4.1-Darwin-x86_64/CMake.app/Contents/bin:$PATH" + # Installing LLVM outside of brew + curl -O https://releases.llvm.org/7.0.0/clang+llvm-7.0.0-x86_64-apple-darwin.tar.xz + tar xf clang+llvm-7.0.0-x86_64-apple-darwin.tar.xz + export LLVM_SYS_70_PREFIX="`pwd`/clang+llvm-7.0.0-x86_64-apple-darwin/" - run: name: Install Rust command: | @@ -110,6 +120,9 @@ jobs: name: Install dependencies command: | sudo apt-get install -y cmake + curl -O https://releases.llvm.org/7.0.0/clang+llvm-7.0.0-x86_64-linux-gnu-ubuntu-16.04.tar.xz + tar xf clang+llvm-7.0.0-x86_64-linux-gnu-ubuntu-16.04.tar.xz + export LLVM_SYS_70_PREFIX="`pwd`/clang+llvm-7.0.0-x86_64-linux-gnu-ubuntu-16.04/" - run: name: Execute tests command: make test @@ -153,6 +166,10 @@ jobs: curl -O https://cmake.org/files/v3.4/cmake-3.4.1-Darwin-x86_64.tar.gz tar xf cmake-3.4.1-Darwin-x86_64.tar.gz export PATH="`pwd`/cmake-3.4.1-Darwin-x86_64/CMake.app/Contents/bin:$PATH" + # Installing LLVM outside of brew + curl -O https://releases.llvm.org/7.0.0/clang+llvm-7.0.0-x86_64-apple-darwin.tar.xz + tar xf clang+llvm-7.0.0-x86_64-apple-darwin.tar.xz + export LLVM_SYS_70_PREFIX="`pwd`/clang+llvm-7.0.0-x86_64-apple-darwin/" - run: name: Install Rust command: | @@ -205,6 +222,9 @@ jobs: name: Install dependencies command: | sudo apt-get install -y cmake + curl -O https://releases.llvm.org/7.0.0/clang+llvm-7.0.0-x86_64-linux-gnu-ubuntu-16.04.tar.xz + tar xf clang+llvm-7.0.0-x86_64-linux-gnu-ubuntu-16.04.tar.xz + export LLVM_SYS_70_PREFIX="`pwd`/clang+llvm-7.0.0-x86_64-linux-gnu-ubuntu-16.04/" - run: rustup default nightly - run: make test - save_cache: From fa3ef2e88dd316056cefdfa8305fbc601976bc58 Mon Sep 17 00:00:00 2001 From: Lachlan Sneff Date: Tue, 5 Mar 2019 13:34:22 -0800 Subject: [PATCH 51/75] Remove .llvmenv --- lib/llvm-backend/.llvmenv | 1 - 1 file changed, 1 deletion(-) delete mode 100644 lib/llvm-backend/.llvmenv diff --git a/lib/llvm-backend/.llvmenv b/lib/llvm-backend/.llvmenv deleted file mode 100644 index 6d1e3080f..000000000 --- a/lib/llvm-backend/.llvmenv +++ /dev/null @@ -1 +0,0 @@ -/usr/local/opt/llvm/bin \ No newline at end of file From 13850929d7bd43384bf1057bb8f07f1aa20aed80 Mon Sep 17 00:00:00 2001 From: Lachlan Sneff Date: Tue, 5 Mar 2019 13:45:19 -0800 Subject: [PATCH 52/75] Try again with path instead of environment var --- .circleci/config.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 260717e0b..66ac286da 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -15,7 +15,7 @@ jobs: sudo apt-get install -y cmake curl -O https://releases.llvm.org/7.0.0/clang+llvm-7.0.0-x86_64-linux-gnu-ubuntu-16.04.tar.xz tar xf clang+llvm-7.0.0-x86_64-linux-gnu-ubuntu-16.04.tar.xz - export LLVM_SYS_70_PREFIX="`pwd`/clang+llvm-7.0.0-x86_64-linux-gnu-ubuntu-16.04/" + export PATH=$PATH:`pwd`/clang+llvm-7.0.0-x86_64-linux-gnu-ubuntu-16.04/bin/ - run: name: Install lint deps command: | @@ -46,7 +46,7 @@ jobs: sudo apt-get install -y cmake curl -O https://releases.llvm.org/7.0.0/clang+llvm-7.0.0-x86_64-linux-gnu-ubuntu-16.04.tar.xz tar xf clang+llvm-7.0.0-x86_64-linux-gnu-ubuntu-16.04.tar.xz - export LLVM_SYS_70_PREFIX="`pwd`/clang+llvm-7.0.0-x86_64-linux-gnu-ubuntu-16.04/" + export PATH=$PATH:`pwd`/clang+llvm-7.0.0-x86_64-linux-gnu-ubuntu-16.04/bin/ - run: make test - run: make integration-tests - save_cache: @@ -122,7 +122,7 @@ jobs: sudo apt-get install -y cmake curl -O https://releases.llvm.org/7.0.0/clang+llvm-7.0.0-x86_64-linux-gnu-ubuntu-16.04.tar.xz tar xf clang+llvm-7.0.0-x86_64-linux-gnu-ubuntu-16.04.tar.xz - export LLVM_SYS_70_PREFIX="`pwd`/clang+llvm-7.0.0-x86_64-linux-gnu-ubuntu-16.04/" + export PATH=$PATH:`pwd`/clang+llvm-7.0.0-x86_64-linux-gnu-ubuntu-16.04/bin/ - run: name: Execute tests command: make test @@ -224,7 +224,7 @@ jobs: sudo apt-get install -y cmake curl -O https://releases.llvm.org/7.0.0/clang+llvm-7.0.0-x86_64-linux-gnu-ubuntu-16.04.tar.xz tar xf clang+llvm-7.0.0-x86_64-linux-gnu-ubuntu-16.04.tar.xz - export LLVM_SYS_70_PREFIX="`pwd`/clang+llvm-7.0.0-x86_64-linux-gnu-ubuntu-16.04/" + export PATH=$PATH:`pwd`/clang+llvm-7.0.0-x86_64-linux-gnu-ubuntu-16.04/bin/ - run: rustup default nightly - run: make test - save_cache: From 48b36a3b013a2e57f8644b1b10c0419e79a9e8df Mon Sep 17 00:00:00 2001 From: Lachlan Sneff Date: Tue, 5 Mar 2019 14:54:44 -0800 Subject: [PATCH 53/75] Runs on linux and also hopefully ci --- .circleci/config.yml | 31 +++++++++++++++++--------- lib/llvm-backend/cpp/object_loader.cpp | 14 +++++++++--- 2 files changed, 31 insertions(+), 14 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 66ac286da..0aa57b5bb 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -15,7 +15,6 @@ jobs: sudo apt-get install -y cmake curl -O https://releases.llvm.org/7.0.0/clang+llvm-7.0.0-x86_64-linux-gnu-ubuntu-16.04.tar.xz tar xf clang+llvm-7.0.0-x86_64-linux-gnu-ubuntu-16.04.tar.xz - export PATH=$PATH:`pwd`/clang+llvm-7.0.0-x86_64-linux-gnu-ubuntu-16.04/bin/ - run: name: Install lint deps command: | @@ -23,7 +22,9 @@ jobs: rustup component add clippy - run: name: Execute lints - command: make lint + command: | + export LLVM_SYS_70_PREFIX="`pwd`/clang+llvm-7.0.0-x86_64-linux-gnu-ubuntu-16.04/" + make lint - save_cache: paths: - /usr/local/cargo/registry @@ -46,9 +47,12 @@ jobs: sudo apt-get install -y cmake curl -O https://releases.llvm.org/7.0.0/clang+llvm-7.0.0-x86_64-linux-gnu-ubuntu-16.04.tar.xz tar xf clang+llvm-7.0.0-x86_64-linux-gnu-ubuntu-16.04.tar.xz - export PATH=$PATH:`pwd`/clang+llvm-7.0.0-x86_64-linux-gnu-ubuntu-16.04/bin/ - - run: make test - - run: make integration-tests + - run: | + export LLVM_SYS_70_PREFIX="`pwd`/clang+llvm-7.0.0-x86_64-linux-gnu-ubuntu-16.04/" + make test + - run: | + export LLVM_SYS_70_PREFIX="`pwd`/clang+llvm-7.0.0-x86_64-linux-gnu-ubuntu-16.04/" + make integration-tests - save_cache: paths: - /usr/local/cargo/registry @@ -75,7 +79,6 @@ jobs: # Installing LLVM outside of brew curl -O https://releases.llvm.org/7.0.0/clang+llvm-7.0.0-x86_64-apple-darwin.tar.xz tar xf clang+llvm-7.0.0-x86_64-apple-darwin.tar.xz - export LLVM_SYS_70_PREFIX="`pwd`/clang+llvm-7.0.0-x86_64-apple-darwin/" - run: name: Install Rust command: | @@ -87,6 +90,7 @@ jobs: command: | export PATH="$HOME/.cargo/bin:$PATH" export PATH="`pwd`/cmake-3.4.1-Darwin-x86_64/CMake.app/Contents/bin:$PATH" + export LLVM_SYS_70_PREFIX="`pwd`/clang+llvm-7.0.0-x86_64-apple-darwin/" # We increase the ulimit for fixing cargo unclosed files in mac ulimit -n 8000 sudo sysctl -w kern.maxfiles=655360 kern.maxfilesperproc=327680 @@ -96,6 +100,7 @@ jobs: command: | export PATH="$HOME/.cargo/bin:$PATH" export PATH="`pwd`/cmake-3.4.1-Darwin-x86_64/CMake.app/Contents/bin:$PATH" + export LLVM_SYS_70_PREFIX="`pwd`/clang+llvm-7.0.0-x86_64-apple-darwin/" make integration-tests - save_cache: paths: @@ -122,13 +127,15 @@ jobs: sudo apt-get install -y cmake curl -O https://releases.llvm.org/7.0.0/clang+llvm-7.0.0-x86_64-linux-gnu-ubuntu-16.04.tar.xz tar xf clang+llvm-7.0.0-x86_64-linux-gnu-ubuntu-16.04.tar.xz - export PATH=$PATH:`pwd`/clang+llvm-7.0.0-x86_64-linux-gnu-ubuntu-16.04/bin/ - run: name: Execute tests - command: make test + command: | + export LLVM_SYS_70_PREFIX="`pwd`/clang+llvm-7.0.0-x86_64-linux-gnu-ubuntu-16.04/" + make test - run: name: Make release build command: | + export LLVM_SYS_70_PREFIX="`pwd`/clang+llvm-7.0.0-x86_64-linux-gnu-ubuntu-16.04/" make release mkdir -p artifacts VERSION=$(cargo pkgid | cut -d# -f2 | cut -d: -f2) @@ -169,7 +176,6 @@ jobs: # Installing LLVM outside of brew curl -O https://releases.llvm.org/7.0.0/clang+llvm-7.0.0-x86_64-apple-darwin.tar.xz tar xf clang+llvm-7.0.0-x86_64-apple-darwin.tar.xz - export LLVM_SYS_70_PREFIX="`pwd`/clang+llvm-7.0.0-x86_64-apple-darwin/" - run: name: Install Rust command: | @@ -181,6 +187,7 @@ jobs: command: | export PATH="`pwd`/cmake-3.4.1-Darwin-x86_64/CMake.app/Contents/bin:$PATH" export PATH="$HOME/.cargo/bin:$PATH" + export LLVM_SYS_70_PREFIX="`pwd`/clang+llvm-7.0.0-x86_64-apple-darwin/" # We increase the ulimit for fixing cargo unclosed files in mac ulimit -n 8000 sudo sysctl -w kern.maxfiles=655360 kern.maxfilesperproc=327680 @@ -190,6 +197,7 @@ jobs: command: | export PATH="`pwd`/cmake-3.4.1-Darwin-x86_64/CMake.app/Contents/bin:$PATH" export PATH="$HOME/.cargo/bin:$PATH" + export LLVM_SYS_70_PREFIX="`pwd`/clang+llvm-7.0.0-x86_64-apple-darwin/" make release mkdir -p artifacts # VERSION=$(cargo pkgid | cut -d# -f2 | cut -d: -f2) @@ -224,9 +232,10 @@ jobs: sudo apt-get install -y cmake curl -O https://releases.llvm.org/7.0.0/clang+llvm-7.0.0-x86_64-linux-gnu-ubuntu-16.04.tar.xz tar xf clang+llvm-7.0.0-x86_64-linux-gnu-ubuntu-16.04.tar.xz - export PATH=$PATH:`pwd`/clang+llvm-7.0.0-x86_64-linux-gnu-ubuntu-16.04/bin/ - run: rustup default nightly - - run: make test + - run: | + export LLVM_SYS_70_PREFIX="`pwd`/clang+llvm-7.0.0-x86_64-linux-gnu-ubuntu-16.04/" + make test - save_cache: paths: - /usr/local/cargo/registry diff --git a/lib/llvm-backend/cpp/object_loader.cpp b/lib/llvm-backend/cpp/object_loader.cpp index 968618068..cef7c7214 100644 --- a/lib/llvm-backend/cpp/object_loader.cpp +++ b/lib/llvm-backend/cpp/object_loader.cpp @@ -39,23 +39,31 @@ public: uintptr_t read_write_data_size, uint32_t read_write_data_align ) override { + auto aligner = [](uintptr_t ptr, size_t align) { + if (ptr == 0) { + return align; + } + return (ptr + align - 1) & ~(align - 1); + }; + + uint8_t *code_ptr_out = nullptr; size_t code_size_out = 0; - auto code_result = callbacks.alloc_memory(code_size, PROTECT_READ_WRITE, &code_ptr_out, &code_size_out); + auto code_result = callbacks.alloc_memory(aligner(code_size, 4096), PROTECT_READ_WRITE, &code_ptr_out, &code_size_out); assert(code_result == RESULT_OK); code_section = Section { code_ptr_out, code_size_out }; code_bump_ptr = (uintptr_t)code_ptr_out; uint8_t *read_ptr_out = nullptr; size_t read_size_out = 0; - auto read_result = callbacks.alloc_memory(read_data_size, PROTECT_READ_WRITE, &read_ptr_out, &read_size_out); + auto read_result = callbacks.alloc_memory(aligner(read_data_size, 4096), PROTECT_READ_WRITE, &read_ptr_out, &read_size_out); assert(read_result == RESULT_OK); read_section = Section { read_ptr_out, read_size_out }; read_bump_ptr = (uintptr_t)read_ptr_out; uint8_t *readwrite_ptr_out = nullptr; size_t readwrite_size_out = 0; - auto readwrite_result = callbacks.alloc_memory(read_write_data_size, PROTECT_READ_WRITE, &readwrite_ptr_out, &readwrite_size_out); + auto readwrite_result = callbacks.alloc_memory(aligner(read_write_data_size, 4096), PROTECT_READ_WRITE, &readwrite_ptr_out, &readwrite_size_out); assert(readwrite_result == RESULT_OK); readwrite_section = Section { readwrite_ptr_out, readwrite_size_out }; readwrite_bump_ptr = (uintptr_t)readwrite_ptr_out; From f36aade2e5aad0399977e37f77797f05edccb5f3 Mon Sep 17 00:00:00 2001 From: Lachlan Sneff Date: Tue, 5 Mar 2019 14:57:37 -0800 Subject: [PATCH 54/75] Fix broken test --- lib/runtime-core/src/vm.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/runtime-core/src/vm.rs b/lib/runtime-core/src/vm.rs index c016c76e7..bc0aa71e8 100644 --- a/lib/runtime-core/src/vm.rs +++ b/lib/runtime-core/src/vm.rs @@ -468,6 +468,8 @@ mod vm_ctx_tests { vm_memories: Map::new().into_boxed_map(), vm_tables: Map::new().into_boxed_map(), vm_globals: Map::new().into_boxed_map(), + + dynamic_sigindices: Map::new().into_boxed_map(), }; let mut import_backing = ImportBacking { memories: Map::new().into_boxed_map(), @@ -478,8 +480,6 @@ mod vm_ctx_tests { vm_memories: Map::new().into_boxed_map(), vm_tables: Map::new().into_boxed_map(), vm_globals: Map::new().into_boxed_map(), - - dynamic_sigindices: Map::new().into_boxed_map(), }; let module = generate_module(); let data = &mut data as *mut _ as *mut c_void; From 0e5d1172d636d94501bedb89638fe05eaa2e9d5a Mon Sep 17 00:00:00 2001 From: Lachlan Sneff Date: Tue, 5 Mar 2019 16:50:49 -0800 Subject: [PATCH 55/75] Just install the signal handler once --- lib/llvm-backend/src/backend.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/lib/llvm-backend/src/backend.rs b/lib/llvm-backend/src/backend.rs index bd8f25bb3..742069d48 100644 --- a/lib/llvm-backend/src/backend.rs +++ b/lib/llvm-backend/src/backend.rs @@ -15,6 +15,7 @@ use std::{ mem, ptr::{self, NonNull}, slice, str, + sync::Once, }; use wasmer_runtime_core::{ backend::{FuncResolver, ProtectedCaller, Token, UserTrapper}, @@ -258,9 +259,11 @@ impl LLVMBackend { ) }; - unsafe { + static SIGNAL_HANDLER_INSTALLED: Once = Once::new(); + + SIGNAL_HANDLER_INSTALLED.call_once(|| unsafe { crate::platform::install_signal_handler(); - } + }); if res != LLVMResult::OK { panic!("failed to load object") From 03909fe3c245e4075fa960a65e85d0ba6a6a2687 Mon Sep 17 00:00:00 2001 From: Brandon Fish Date: Wed, 6 Mar 2019 00:15:07 -0600 Subject: [PATCH 56/75] Run spectests with both compilers, activate using features --- Makefile | 2 ++ lib/spectests/Cargo.toml | 4 +++- lib/spectests/build/spectests.rs | 30 +++++++++++++++++++++------ lib/spectests/examples/simple/main.rs | 25 +++++++++++++++++++--- 4 files changed, 51 insertions(+), 10 deletions(-) diff --git a/Makefile b/Makefile index 74e3428fc..8270778f2 100644 --- a/Makefile +++ b/Makefile @@ -39,6 +39,8 @@ test: # We use one thread so the emscripten stdouts doesn't collide cargo test --all --exclude wasmer-runtime-c-api -- --test-threads=1 $(runargs) # cargo test --all --exclude wasmer-emscripten -- --test-threads=1 $(runargs) + cargo test --manifest-path lib/spectests/Cargo.toml --features clif + cargo test --manifest-path lib/spectests/Cargo.toml --features llvm cargo build -p wasmer-runtime-c-api cargo test -p wasmer-runtime-c-api -- --nocapture diff --git a/lib/spectests/Cargo.toml b/lib/spectests/Cargo.toml index 32b14e421..e9ce75132 100644 --- a/lib/spectests/Cargo.toml +++ b/lib/spectests/Cargo.toml @@ -21,4 +21,6 @@ wabt = "0.7.2" [features] default = ["fast-tests"] -fast-tests = [] \ No newline at end of file +fast-tests = [] +clif = [] +llvm = [] \ No newline at end of file diff --git a/lib/spectests/build/spectests.rs b/lib/spectests/build/spectests.rs index c533a2951..c1d28ca29 100644 --- a/lib/spectests/build/spectests.rs +++ b/lib/spectests/build/spectests.rs @@ -77,13 +77,12 @@ const TESTS: &[&str] = &[ static COMMON: &'static str = r##" use std::{{f32, f64}}; use wabt::wat2wasm; -use wasmer_clif_backend::CraneliftCompiler; -use wasmer_llvm_backend::LLVMCompiler; use wasmer_runtime_core::import::ImportObject; use wasmer_runtime_core::types::Value; use wasmer_runtime_core::{{Instance, module::Module}}; use wasmer_runtime_core::error::Result; use wasmer_runtime_core::vm::Ctx; +use wasmer_runtime_core::backend::Compiler; static IMPORT_MODULE: &str = r#" (module @@ -96,9 +95,28 @@ static IMPORT_MODULE: &str = r#" (global $global_i32 (export "global_i32") i32 (i32.const 666))) "#; +#[cfg(feature = "clif")] +fn get_compiler() -> impl Compiler { + use wasmer_clif_backend::CraneliftCompiler; + CraneliftCompiler::new() +} + +#[cfg(feature = "llvm")] +fn get_compiler() -> impl Compiler { + use wasmer_llvm_backend::LLVMCompiler; + LLVMCompiler::new() +} + +#[cfg(not(any(feature = "llvm", feature = "clif")))] +fn get_compiler() -> impl Compiler { + panic!("compiler not specified, activate a compiler via features"); + use wasmer_clif_backend::CraneliftCompiler; + CraneliftCompiler::new() +} + pub fn generate_imports() -> ImportObject { let wasm_binary = wat2wasm(IMPORT_MODULE.as_bytes()).expect("WAST not valid or malformed"); - let module = wasmer_runtime_core::compile_with(&wasm_binary[..], &LLVMCompiler::new()) + let module = wasmer_runtime_core::compile_with(&wasm_binary[..], &get_compiler()) .expect("WASM can't be compiled"); let instance = module .instantiate(&ImportObject::new()) @@ -359,7 +377,7 @@ fn test_module_{}() {{ let module_str = \"{}\"; println!(\"{{}}\", module_str); let wasm_binary = wat2wasm(module_str.as_bytes()).expect(\"WAST not valid or malformed\"); - let module = wasmer_runtime_core::compile_with(&wasm_binary[..], &LLVMCompiler::new()).expect(\"WASM can't be compiled\"); + let module = wasmer_runtime_core::compile_with(&wasm_binary[..], &get_compiler()).expect(\"WASM can't be compiled\"); module.instantiate(&generate_imports()).expect(\"WASM can't be instantiated\") }}\n", self.last_module, @@ -382,7 +400,7 @@ fn test_module_{}() {{ "#[test] fn {}_assert_invalid() {{ let wasm_binary = {:?}; - let module = wasmer_runtime_core::compile_with(&wasm_binary, &LLVMCompiler::new()); + let module = wasmer_runtime_core::compile_with(&wasm_binary, &get_compiler()); assert!(module.is_err(), \"WASM should not compile as is invalid\"); }}\n", command_name, @@ -513,7 +531,7 @@ fn {}_assert_invalid() {{ "#[test] fn {}_assert_malformed() {{ let wasm_binary = {:?}; - let compilation = wasmer_runtime_core::compile_with(&wasm_binary, &LLVMCompiler::new()); + let compilation = wasmer_runtime_core::compile_with(&wasm_binary, &get_compiler()); assert!(compilation.is_err(), \"WASM should not compile as is malformed\"); }}\n", command_name, diff --git a/lib/spectests/examples/simple/main.rs b/lib/spectests/examples/simple/main.rs index 029cec1ac..595bb3680 100644 --- a/lib/spectests/examples/simple/main.rs +++ b/lib/spectests/examples/simple/main.rs @@ -1,6 +1,6 @@ use wabt::wat2wasm; -use wasmer_clif_backend::CraneliftCompiler; use wasmer_runtime_core::{ + backend::Compiler, error, global::Global, memory::Memory, @@ -10,12 +10,31 @@ use wasmer_runtime_core::{ units::Pages, }; +#[cfg(feature = "clif")] +fn get_compiler() -> impl Compiler { + use wasmer_clif_backend::CraneliftCompiler; + CraneliftCompiler::new() +} + +#[cfg(feature = "llvm")] +fn get_compiler() -> impl Compiler { + use wasmer_llvm_backend::LLVMCompiler; + LLVMCompiler::new() +} + +#[cfg(not(any(feature = "llvm", feature = "clif")))] +fn get_compiler() -> impl Compiler { + panic!("compiler not specified, activate a compiler via features"); + use wasmer_clif_backend::CraneliftCompiler; + CraneliftCompiler::new() +} + static EXAMPLE_WASM: &'static [u8] = include_bytes!("simple.wasm"); fn main() -> error::Result<()> { let wasm_binary = wat2wasm(IMPORT_MODULE.as_bytes()).expect("WAST not valid or malformed"); - let inner_module = wasmer_runtime_core::compile_with(&wasm_binary, &CraneliftCompiler::new())?; + let inner_module = wasmer_runtime_core::compile_with(&wasm_binary, &get_compiler())?; let memory = Memory::new(MemoryDescriptor { minimum: Pages(1), @@ -50,7 +69,7 @@ fn main() -> error::Result<()> { "env" => inner_instance, }; - let outer_module = wasmer_runtime_core::compile_with(EXAMPLE_WASM, &CraneliftCompiler::new())?; + let outer_module = wasmer_runtime_core::compile_with(EXAMPLE_WASM, &get_compiler())?; let outer_instance = outer_module.instantiate(&outer_imports)?; let ret = outer_instance.call("main", &[Value::I32(42)])?; println!("ret: {:?}", ret); From fd99ed60bf12de4cc60c97b4937c512354a337c2 Mon Sep 17 00:00:00 2001 From: Lachlan Sneff Date: Wed, 6 Mar 2019 12:44:19 -0800 Subject: [PATCH 57/75] Split tests into spectests/code-tests and emscripten tests --- .circleci/config.yml | 50 +++++++++++++++++++++++++++++++++++++------- Makefile | 5 ++++- 2 files changed, 46 insertions(+), 9 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 0aa57b5bb..0c7073764 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -47,10 +47,19 @@ jobs: sudo apt-get install -y cmake curl -O https://releases.llvm.org/7.0.0/clang+llvm-7.0.0-x86_64-linux-gnu-ubuntu-16.04.tar.xz tar xf clang+llvm-7.0.0-x86_64-linux-gnu-ubuntu-16.04.tar.xz - - run: | + - run: + name: Tests + command: | export LLVM_SYS_70_PREFIX="`pwd`/clang+llvm-7.0.0-x86_64-linux-gnu-ubuntu-16.04/" make test - - run: | + - run: + name: Emscripten Tests + command: | + export LLVM_SYS_70_PREFIX="`pwd`/clang+llvm-7.0.0-x86_64-linux-gnu-ubuntu-16.04/" + make test-emscripten + - run: + name: Integration Tests + command: | export LLVM_SYS_70_PREFIX="`pwd`/clang+llvm-7.0.0-x86_64-linux-gnu-ubuntu-16.04/" make integration-tests - save_cache: @@ -86,7 +95,7 @@ jobs: export PATH="$HOME/.cargo/bin:$PATH" cargo --version - run: - name: Execute tests + name: Tests command: | export PATH="$HOME/.cargo/bin:$PATH" export PATH="`pwd`/cmake-3.4.1-Darwin-x86_64/CMake.app/Contents/bin:$PATH" @@ -96,7 +105,17 @@ jobs: sudo sysctl -w kern.maxfiles=655360 kern.maxfilesperproc=327680 make test - run: - name: Execute integration tests + name: Emscripten Tests + command: | + export PATH="$HOME/.cargo/bin:$PATH" + export PATH="`pwd`/cmake-3.4.1-Darwin-x86_64/CMake.app/Contents/bin:$PATH" + export LLVM_SYS_70_PREFIX="`pwd`/clang+llvm-7.0.0-x86_64-apple-darwin/" + # We increase the ulimit for fixing cargo unclosed files in mac + ulimit -n 8000 + sudo sysctl -w kern.maxfiles=655360 kern.maxfilesperproc=327680 + make test-emscripten + - run: + name: Integration Tests command: | export PATH="$HOME/.cargo/bin:$PATH" export PATH="`pwd`/cmake-3.4.1-Darwin-x86_64/CMake.app/Contents/bin:$PATH" @@ -128,12 +147,17 @@ jobs: curl -O https://releases.llvm.org/7.0.0/clang+llvm-7.0.0-x86_64-linux-gnu-ubuntu-16.04.tar.xz tar xf clang+llvm-7.0.0-x86_64-linux-gnu-ubuntu-16.04.tar.xz - run: - name: Execute tests + name: Tests command: | export LLVM_SYS_70_PREFIX="`pwd`/clang+llvm-7.0.0-x86_64-linux-gnu-ubuntu-16.04/" make test - run: - name: Make release build + name: Emscripten Tests + command: | + export LLVM_SYS_70_PREFIX="`pwd`/clang+llvm-7.0.0-x86_64-linux-gnu-ubuntu-16.04/" + make test-emscripten + - run: + name: Release Build command: | export LLVM_SYS_70_PREFIX="`pwd`/clang+llvm-7.0.0-x86_64-linux-gnu-ubuntu-16.04/" make release @@ -183,7 +207,7 @@ jobs: export PATH="$HOME/.cargo/bin:$PATH" cargo --version - run: - name: Execute tests + name: Tests command: | export PATH="`pwd`/cmake-3.4.1-Darwin-x86_64/CMake.app/Contents/bin:$PATH" export PATH="$HOME/.cargo/bin:$PATH" @@ -193,7 +217,17 @@ jobs: sudo sysctl -w kern.maxfiles=655360 kern.maxfilesperproc=327680 make test - run: - name: Make release build + name: Emscripten Tests + command: | + export PATH="`pwd`/cmake-3.4.1-Darwin-x86_64/CMake.app/Contents/bin:$PATH" + export PATH="$HOME/.cargo/bin:$PATH" + export LLVM_SYS_70_PREFIX="`pwd`/clang+llvm-7.0.0-x86_64-apple-darwin/" + # We increase the ulimit for fixing cargo unclosed files in mac + ulimit -n 8000 + sudo sysctl -w kern.maxfiles=655360 kern.maxfilesperproc=327680 + make test-emscripten + - run: + name: Release Build command: | export PATH="`pwd`/cmake-3.4.1-Darwin-x86_64/CMake.app/Contents/bin:$PATH" export PATH="$HOME/.cargo/bin:$PATH" diff --git a/Makefile b/Makefile index 8270778f2..487a0e4cb 100644 --- a/Makefile +++ b/Makefile @@ -37,13 +37,16 @@ precommit: lint test test: # We use one thread so the emscripten stdouts doesn't collide - cargo test --all --exclude wasmer-runtime-c-api -- --test-threads=1 $(runargs) + cargo test --all --exclude wasmer-runtime-c-api --exclude wasmer-emscripten --exclude wasmer-spectests -- $(runargs) # cargo test --all --exclude wasmer-emscripten -- --test-threads=1 $(runargs) cargo test --manifest-path lib/spectests/Cargo.toml --features clif cargo test --manifest-path lib/spectests/Cargo.toml --features llvm cargo build -p wasmer-runtime-c-api cargo test -p wasmer-runtime-c-api -- --nocapture +test-emscripten: + cargo test -p wasmer-emscripten -- --test-threads=1 $(runargs) + release: # If you are in OS-X, you will need mingw-w64 for cross compiling to windows # brew install mingw-w64 From 8f2d90186dabf6bc0a35fd20961f510703b32fb8 Mon Sep 17 00:00:00 2001 From: Lachlan Sneff Date: Wed, 6 Mar 2019 12:45:42 -0800 Subject: [PATCH 58/75] Fix circleci config --- .circleci/config.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 0c7073764..c5ea7e219 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -50,18 +50,18 @@ jobs: - run: name: Tests command: | - export LLVM_SYS_70_PREFIX="`pwd`/clang+llvm-7.0.0-x86_64-linux-gnu-ubuntu-16.04/" - make test + export LLVM_SYS_70_PREFIX="`pwd`/clang+llvm-7.0.0-x86_64-linux-gnu-ubuntu-16.04/" + make test - run: name: Emscripten Tests command: | - export LLVM_SYS_70_PREFIX="`pwd`/clang+llvm-7.0.0-x86_64-linux-gnu-ubuntu-16.04/" - make test-emscripten + export LLVM_SYS_70_PREFIX="`pwd`/clang+llvm-7.0.0-x86_64-linux-gnu-ubuntu-16.04/" + make test-emscripten - run: name: Integration Tests command: | - export LLVM_SYS_70_PREFIX="`pwd`/clang+llvm-7.0.0-x86_64-linux-gnu-ubuntu-16.04/" - make integration-tests + export LLVM_SYS_70_PREFIX="`pwd`/clang+llvm-7.0.0-x86_64-linux-gnu-ubuntu-16.04/" + make integration-tests - save_cache: paths: - /usr/local/cargo/registry From 9f93ac2fe5a70b1d234eecca97310e78816b2759 Mon Sep 17 00:00:00 2001 From: Lachlan Sneff Date: Wed, 6 Mar 2019 13:18:30 -0800 Subject: [PATCH 59/75] Fix integration tests --- integration_tests/lua/test.sh | 3 +-- integration_tests/nginx/test.sh | 4 ++-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/integration_tests/lua/test.sh b/integration_tests/lua/test.sh index b45752f0b..7c3cc9b6c 100755 --- a/integration_tests/lua/test.sh +++ b/integration_tests/lua/test.sh @@ -1,7 +1,6 @@ #! /bin/bash -nohup ./target/release/wasmer run examples/lua.wasm & -sleep 3s +nohup ./target/release/wasmer run examples/lua.wasm --disable-cache -- -v if grep "Lua 5.4.0 Copyright (C) 1994-2018 Lua.org, PUC-Rio" ./nohup.out then diff --git a/integration_tests/nginx/test.sh b/integration_tests/nginx/test.sh index aeb790e28..496b6ae6d 100755 --- a/integration_tests/nginx/test.sh +++ b/integration_tests/nginx/test.sh @@ -1,7 +1,7 @@ #! /bin/bash -nohup ./target/release/wasmer run examples/nginx/nginx.wasm -- -p integration_tests/nginx/ -c nginx.conf & -sleep 3s +nohup ./target/release/wasmer run examples/nginx/nginx.wasm --disable-cache -- -p integration_tests/nginx/ -c nginx.conf & +sleep 10s curl localhost:8080 > ./nginx.out From 334a1310df1cf6836e09ffccfa0c644638c1f4ce Mon Sep 17 00:00:00 2001 From: Lachlan Sneff Date: Wed, 6 Mar 2019 13:28:07 -0800 Subject: [PATCH 60/75] Change nginx integration just to test it it starts --- integration_tests/nginx/test.sh | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/integration_tests/nginx/test.sh b/integration_tests/nginx/test.sh index 496b6ae6d..a2cfb7159 100755 --- a/integration_tests/nginx/test.sh +++ b/integration_tests/nginx/test.sh @@ -1,22 +1,14 @@ #! /bin/bash -nohup ./target/release/wasmer run examples/nginx/nginx.wasm --disable-cache -- -p integration_tests/nginx/ -c nginx.conf & -sleep 10s +nohup ./target/release/wasmer run examples/nginx/nginx.wasm --disable-cache -- -v -curl localhost:8080 > ./nginx.out - - -if grep "wasmer" ./nginx.out +if grep "nginx version: nginx/1.15.3" ./nohup.out then echo "nginx integration test succeeded" rm ./nohup.out - rm ./nginx.out - rm -rf ./integration_tests/nginx/*_temp exit 0 else echo "nginx integration test failed" rm ./nohup.out - rm ./nginx.out - rm -rf ./integration_tests/nginx/*_temp exit -1 fi From 9f589de0310df49b29acab9b9650f76895129dc4 Mon Sep 17 00:00:00 2001 From: Lachlan Sneff Date: Wed, 6 Mar 2019 13:53:06 -0800 Subject: [PATCH 61/75] Reset Cargo.lock --- Cargo.lock | 149 +++++++++++++++++++++-------------------------------- 1 file changed, 60 insertions(+), 89 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b9a0622bc..f93daf2a7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -32,7 +32,7 @@ name = "atty" version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", "termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -49,8 +49,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "backtrace-sys 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-demangle 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -61,7 +61,7 @@ version = "0.1.28" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cc 1.0.30 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -71,7 +71,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "cexpr 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "clang-sys 0.26.4 (registry+https://github.com/rust-lang/crates.io-index)", "clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -129,15 +129,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "cbindgen" -version = "0.8.1" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro2 0.4.26 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.58 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", "syn 0.15.27 (registry+https://github.com/rust-lang/crates.io-index)", "tempfile 3.0.7 (registry+https://github.com/rust-lang/crates.io-index)", @@ -159,7 +159,7 @@ dependencies = [ [[package]] name = "cfg-if" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -168,7 +168,7 @@ version = "0.26.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", "libloading 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -291,11 +291,11 @@ dependencies = [ "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_os 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "rand_xoshiro 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "rayon 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.58 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", "tinytemplate 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "walkdir 2.2.7 (registry+https://github.com/rust-lang/crates.io-index)", @@ -326,7 +326,7 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -339,7 +339,7 @@ name = "crossbeam-utils" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -399,7 +399,7 @@ version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "errno-dragonfly 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -409,7 +409,7 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "gcc 0.3.55 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -514,7 +514,7 @@ dependencies = [ "either 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "enum-methods 0.0.8 (registry+https://github.com/rust-lang/crates.io-index)", "inkwell_internal_macros 0.1.0 (git+https://github.com/TheDan64/inkwell?branch=llvm7-0)", - "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", "llvm-sys 70.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -556,7 +556,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "libc" -version = "0.2.49" +version = "0.2.50" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -575,7 +575,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cc 1.0.30 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -594,7 +594,7 @@ name = "log" version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -602,7 +602,7 @@ name = "memchr" version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -610,7 +610,7 @@ name = "memmap" version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -626,8 +626,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "cc 1.0.30 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -638,8 +638,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "cc 1.0.30 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -667,7 +667,7 @@ name = "num_cpus" version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -684,7 +684,7 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -702,7 +702,7 @@ name = "parking_lot_core" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", @@ -719,14 +719,6 @@ name = "plain" version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "proc-macro2" -version = "0.3.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "proc-macro2" version = "0.4.27" @@ -745,14 +737,6 @@ name = "quote" version = "0.3.15" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "quote" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "proc-macro2 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "quote" version = "0.6.11" @@ -767,13 +751,13 @@ version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", "rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "rand_jitter 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_os 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "rand_pcg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -822,19 +806,19 @@ name = "rand_jitter" version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rand_os" -version = "0.1.2" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -893,7 +877,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1014,7 +998,7 @@ name = "serde" version = "1.0.89" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "serde_derive 1.0.58 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1036,12 +1020,12 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.58" +version = "1.0.89" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.13.11 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.27 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1099,16 +1083,6 @@ dependencies = [ "unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "syn" -version = "0.13.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "proc-macro2 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "syn" version = "0.15.27" @@ -1153,8 +1127,8 @@ name = "tempfile" version = "3.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)", "remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1174,7 +1148,7 @@ name = "termion" version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)", "redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1200,7 +1174,7 @@ name = "time" version = "0.1.42" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1278,7 +1252,7 @@ version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.58 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", "wabt-sys 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1326,13 +1300,13 @@ dependencies = [ "cranelift-native 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)", "cranelift-wasm 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)", "hashbrown 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", "nix 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)", "rayon 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", "serde-bench 0.0.7 (registry+https://github.com/rust-lang/crates.io-index)", "serde_bytes 0.10.5 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.58 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", "target-lexicon 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "wasmer-runtime-core 0.2.1", "wasmer-win-exception-handler 0.2.0", @@ -1347,7 +1321,7 @@ dependencies = [ "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", "wabt 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1365,7 +1339,7 @@ dependencies = [ "hashbrown 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "inkwell 0.1.0 (git+https://github.com/TheDan64/inkwell?branch=llvm7-0)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", "nix 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1393,8 +1367,8 @@ dependencies = [ name = "wasmer-runtime-c-api" version = "0.2.1" dependencies = [ - "cbindgen 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "cbindgen 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", "wasmer-runtime 0.2.1", "wasmer-runtime-core 0.2.1", ] @@ -1411,14 +1385,14 @@ dependencies = [ "hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", "nix 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "page_size 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", "serde-bench 0.0.7 (registry+https://github.com/rust-lang/crates.io-index)", "serde_bytes 0.10.5 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.58 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", "wasmparser 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1439,7 +1413,7 @@ version = "0.2.0" dependencies = [ "bindgen 0.46.0 (registry+https://github.com/rust-lang/crates.io-index)", "cmake 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "wasmer-runtime-core 0.2.1", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1466,7 +1440,7 @@ version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1531,10 +1505,10 @@ dependencies = [ "checksum capstone 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "00be9d203fa0e078b93b24603633fb081851dfe0c1086364431f52587a47157e" "checksum capstone-sys 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2dc8d32bc5c1e6d0fcde10af411c98b07d93498d51654f678757f08fa2acd6a6" "checksum cast 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "926013f2860c46252efceabb19f4a6b308197505082c609025aa6706c011d427" -"checksum cbindgen 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "32e01024aaf5390d6a8145047371a4f5b0063a14c1e411bc731353bd2278ca44" +"checksum cbindgen 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f61c5411fe3ac196fae7ea397dd13959b1323edda046eec50d648a8e92015a53" "checksum cc 1.0.30 (registry+https://github.com/rust-lang/crates.io-index)" = "d01c69d08ff207f231f07196e30f84c70f1c815b04f980f8b7b01ff01f05eb92" "checksum cexpr 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "644d693ecfa91955ed32dcc7eda4914e1be97a641fb6f0645a37348e20b230da" -"checksum cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "082bb9b28e00d3c9d39cc03e64ce4cea0f1bb9b3fde493f0cbc008472d22bdf4" +"checksum cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "11d43355396e872eefb45ce6342e4374ed7bc2b3a502d1b28e36d6e23c05d1f4" "checksum clang-sys 0.26.4 (registry+https://github.com/rust-lang/crates.io-index)" = "6ef0c1bcf2e99c649104bd7a7012d8f8802684400e03db0ec0af48583c6fa0e4" "checksum clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b957d88f4b6a63b9d70d5f454ac8011819c6efa7727858f458ab71c756ce2d3e" "checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" @@ -1579,7 +1553,7 @@ dependencies = [ "checksum itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1306f3464951f30e30d12373d31c79fbd52d236e5e896fd92f96ec7babbbe60b" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" "checksum lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bc5729f27f159ddd61f4df6228e827e86643d4d3e7c32183cb30a1c08f604a14" -"checksum libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)" = "413f3dfc802c5dc91dc570b05125b6cda9855edfaa9825c9849807876376e70e" +"checksum libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)" = "aab692d7759f5cd8c859e169db98ae5b52c924add2af5fbbca11d12fefb567c1" "checksum libloading 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9c3ad660d7cb8c5822cd83d10897b0f1f1526792737a179e73896152f85b88c2" "checksum llvm-sys 70.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "60a9ee82fe0fa72ae6ef6d018b407296085863836451c7a97384f84ed7e26b9f" "checksum lock_api 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "62ebf1391f6acad60e5c8b43706dde4582df75c06698ab44511d15016bc2442c" @@ -1599,11 +1573,9 @@ dependencies = [ "checksum parking_lot_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "94c8c7923936b28d546dfd14d4472eaf34c99b14e1c973a32b3e6d4eb04298c9" "checksum peeking_take_while 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099" "checksum plain 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "b4596b6d070b27117e987119b4dac604f3c58cfb0b191112e24771b2faeac1a6" -"checksum proc-macro2 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "1b06e2f335f48d24442b35a19df506a835fb3547bc3c06ef27340da9acf5cae7" "checksum proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)" = "4d317f9caece796be1980837fd5cb3dfec5613ebdb04ad0956deea83ce168915" "checksum quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9274b940887ce9addde99c4eee6b5c44cc494b182b97e73dc8ffdcb3397fd3f0" "checksum quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a" -"checksum quote 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9949cfe66888ffe1d53e6ec9d9f3b70714083854be20fd5e271b232a017401e8" "checksum quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)" = "cdd8e04bd9c52e0342b406469d494fcb033be4bdbe5c606016defbb1681411e1" "checksum rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca" "checksum rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef" @@ -1612,7 +1584,7 @@ dependencies = [ "checksum rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b40677c7be09ae76218dc623efbf7b18e34bced3f38883af07bb75630a21bc4" "checksum rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ded997c9d5f13925be2a6fd7e66bf1872597f759fd9dd93513dd7e92e5a5ee08" "checksum rand_jitter 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7b9ea758282efe12823e0d952ddb269d2e1897227e464919a554f2a03ef1b832" -"checksum rand_os 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b7c690732391ae0abafced5015ffb53656abfaec61b342290e5eb56b286a679d" +"checksum rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7b75f676a1e053fc562eafbb47838d67c84801e38fc1ba459e8f180deabd5071" "checksum rand_pcg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "abf9b09b01790cfe0364f52bf32995ea3c39f4d2dd011eac241d2914146d0b44" "checksum rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c" "checksum rand_xoshiro 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "03b418169fb9c46533f326efd6eed2576699c44ca92d3052a066214a8d828929" @@ -1637,7 +1609,7 @@ dependencies = [ "checksum serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)" = "92514fb95f900c9b5126e32d020f5c6d40564c27a5ea6d1d7d9f157a96623560" "checksum serde-bench 0.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "d733da87e79faaac25616e33d26299a41143fd4cd42746cbb0e91d8feea243fd" "checksum serde_bytes 0.10.5 (registry+https://github.com/rust-lang/crates.io-index)" = "defbb8a83d7f34cc8380751eeb892b825944222888aff18996ea7901f24aec88" -"checksum serde_derive 1.0.58 (registry+https://github.com/rust-lang/crates.io-index)" = "ac38f51a52a556cd17545798e29536885fb1a3fa63d6399f5ef650f4a7d35901" +"checksum serde_derive 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)" = "bb6eabf4b5914e88e24eea240bb7c9f9a2cbc1bbbe8d961d381975ec3c6b806c" "checksum serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)" = "5a23aa71d4a4d43fdbfaac00eff68ba8a06a51759a89ac3304323e800c4dd40d" "checksum smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)" = "c4488ae950c49d403731982257768f48fada354a5203fe81f9bb6f43ca9002be" "checksum stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dba1a27d3efae4351c8051072d619e3ade2820635c3958d826bfea39d59b54c8" @@ -1645,7 +1617,6 @@ dependencies = [ "checksum structopt 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "670ad348dc73012fcf78c71f06f9d942232cdd4c859d4b6975e27836c3efc0c3" "checksum structopt-derive 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "ef98172b1a00b0bec738508d3726540edcbd186d50dfd326f2b1febbb3559f04" "checksum syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d3b891b9015c88c576343b9b3e41c2c11a51c219ef067b264bd9c8aa9b441dad" -"checksum syn 0.13.11 (registry+https://github.com/rust-lang/crates.io-index)" = "14f9bf6292f3a61d2c716723fdb789a41bbe104168e6f496dc6497e531ea1b9b" "checksum syn 0.15.27 (registry+https://github.com/rust-lang/crates.io-index)" = "525bd55255f03c816e5d7f615587bd13030c7103354fadb104993dcee6a788ec" "checksum synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a393066ed9010ebaed60b9eafa373d4b1baac186dd7e008555b0f702b51945b6" "checksum synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "73687139bf99285483c96ac0add482c3776528beac1d97d444f6e91f203a2015" From 95c90f84b7471adc46f97e32bc3bf816647e64e3 Mon Sep 17 00:00:00 2001 From: Syrus Date: Wed, 6 Mar 2019 15:13:38 -0800 Subject: [PATCH 62/75] Added LLVM to the PATH in windows appveyor --- .appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.appveyor.yml b/.appveyor.yml index 2a67567e4..57a6f5fd3 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -20,7 +20,7 @@ install: # uncomment these lines if the cache is cleared, or if we must re-install rust for some reason # - appveyor DownloadFile https://win.rustup.rs/ -FileName rustup-init.exe # - rustup-init.exe -yv --default-host %target% - - set PATH=%PATH%;%USERPROFILE%\.cargo\bin + - set PATH=%PATH%;"C:\Program Files\LLVM\bin";%USERPROFILE%\.cargo\bin - rustup default stable-%target% - rustup update - rustc -vV From 0540c50b871d67d20d60344c1fa872315809515f Mon Sep 17 00:00:00 2001 From: Syrus Date: Wed, 6 Mar 2019 15:27:41 -0800 Subject: [PATCH 63/75] Use LLVM 5.0 instead of the default one --- .appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.appveyor.yml b/.appveyor.yml index 57a6f5fd3..ec30e348f 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -20,7 +20,7 @@ install: # uncomment these lines if the cache is cleared, or if we must re-install rust for some reason # - appveyor DownloadFile https://win.rustup.rs/ -FileName rustup-init.exe # - rustup-init.exe -yv --default-host %target% - - set PATH=%PATH%;"C:\Program Files\LLVM\bin";%USERPROFILE%\.cargo\bin + - set PATH=%PATH%;C:\\Libraries\\llvm-5.0.0\\bin;%USERPROFILE%\.cargo\bin - rustup default stable-%target% - rustup update - rustc -vV From 9812fa09c729f15223735cc0880e16a87f568272 Mon Sep 17 00:00:00 2001 From: Syrus Date: Wed, 6 Mar 2019 15:49:35 -0800 Subject: [PATCH 64/75] Trying custom LLVM install in windows appveyor --- .appveyor.yml | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/.appveyor.yml b/.appveyor.yml index ec30e348f..1eaca6c23 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -17,14 +17,24 @@ cache: - target install: + # Install LLVM + - mkdir C:\projects\deps + - cd C:\projects\deps + - appveyor DownloadFile http://prereleases.llvm.org/win-snapshots/LLVM-7.0.0-r336178-win64.exe -FileName llvm.exe + - 7z x llvm.exe -oC:\projects\deps\llvm + - set "PATH=C:\projects\deps\llvm\bin;%PATH%" + - set "LLD_LINK=C:\projects\deps\llvm\bin\lld-link.exe" + + # Install Rust # uncomment these lines if the cache is cleared, or if we must re-install rust for some reason # - appveyor DownloadFile https://win.rustup.rs/ -FileName rustup-init.exe # - rustup-init.exe -yv --default-host %target% - - set PATH=%PATH%;C:\\Libraries\\llvm-5.0.0\\bin;%USERPROFILE%\.cargo\bin + - set PATH=%PATH%;%USERPROFILE%\.cargo\bin - rustup default stable-%target% - rustup update - rustc -vV - cargo -vV + # Install InnoSetup - appveyor-retry appveyor DownloadFile https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror/2017-08-22-is.exe - 2017-08-22-is.exe /VERYSILENT /SUPPRESSMSGBOXES /NORESTART /SP- From bd76a276fcf7a7b22ced7538d3b342f3eb61d5ae Mon Sep 17 00:00:00 2001 From: Syrus Date: Wed, 6 Mar 2019 15:57:38 -0800 Subject: [PATCH 65/75] Fixed path --- .appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.appveyor.yml b/.appveyor.yml index 1eaca6c23..f513d1aa1 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -22,7 +22,7 @@ install: - cd C:\projects\deps - appveyor DownloadFile http://prereleases.llvm.org/win-snapshots/LLVM-7.0.0-r336178-win64.exe -FileName llvm.exe - 7z x llvm.exe -oC:\projects\deps\llvm - - set "PATH=C:\projects\deps\llvm\bin;%PATH%" + - set "PATH=%PATH%;C:\projects\deps\llvm\bin" - set "LLD_LINK=C:\projects\deps\llvm\bin\lld-link.exe" # Install Rust From a0ff2733cee315a9725ceda4c49d5845001901bf Mon Sep 17 00:00:00 2001 From: Syrus Date: Wed, 6 Mar 2019 16:03:25 -0800 Subject: [PATCH 66/75] Go back to the appveyor build folder --- .appveyor.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.appveyor.yml b/.appveyor.yml index f513d1aa1..0d309666f 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -24,6 +24,7 @@ install: - 7z x llvm.exe -oC:\projects\deps\llvm - set "PATH=%PATH%;C:\projects\deps\llvm\bin" - set "LLD_LINK=C:\projects\deps\llvm\bin\lld-link.exe" + - cd "%APPVEYOR_BUILD_FOLDER%" # Install Rust # uncomment these lines if the cache is cleared, or if we must re-install rust for some reason From 58897aba5a8e74f182d80ce5112911f535c3ccc3 Mon Sep 17 00:00:00 2001 From: Syrus Date: Wed, 6 Mar 2019 16:18:35 -0800 Subject: [PATCH 67/75] Try to use LLVM path uniformily for appveyor --- .appveyor.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.appveyor.yml b/.appveyor.yml index 0d309666f..b50fb31d4 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -22,7 +22,7 @@ install: - cd C:\projects\deps - appveyor DownloadFile http://prereleases.llvm.org/win-snapshots/LLVM-7.0.0-r336178-win64.exe -FileName llvm.exe - 7z x llvm.exe -oC:\projects\deps\llvm - - set "PATH=%PATH%;C:\projects\deps\llvm\bin" + # - set "PATH=%PATH%;C:\projects\deps\llvm\bin" - set "LLD_LINK=C:\projects\deps\llvm\bin\lld-link.exe" - cd "%APPVEYOR_BUILD_FOLDER%" @@ -30,7 +30,7 @@ install: # uncomment these lines if the cache is cleared, or if we must re-install rust for some reason # - appveyor DownloadFile https://win.rustup.rs/ -FileName rustup-init.exe # - rustup-init.exe -yv --default-host %target% - - set PATH=%PATH%;%USERPROFILE%\.cargo\bin + - set PATH=%PATH%;C:\\projects\\deps\\llvm\\bin;%USERPROFILE%\.cargo\bin - rustup default stable-%target% - rustup update - rustc -vV From e63515279f2c0167b256dbcaf86ae824cecf0fb6 Mon Sep 17 00:00:00 2001 From: Syrus Date: Wed, 6 Mar 2019 16:35:23 -0800 Subject: [PATCH 68/75] Try to use LLVM_SYS_70_PREFIX for appveyor --- .appveyor.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.appveyor.yml b/.appveyor.yml index b50fb31d4..46c989086 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -24,6 +24,7 @@ install: - 7z x llvm.exe -oC:\projects\deps\llvm # - set "PATH=%PATH%;C:\projects\deps\llvm\bin" - set "LLD_LINK=C:\projects\deps\llvm\bin\lld-link.exe" + - set "LLVM_SYS_70_PREFIX=C:\projects\deps\llvm" - cd "%APPVEYOR_BUILD_FOLDER%" # Install Rust From 1957ddef5332b58a34061fe0e572df1a226b0737 Mon Sep 17 00:00:00 2001 From: Brandon Fish Date: Wed, 6 Mar 2019 21:36:46 -0600 Subject: [PATCH 69/75] Run emscripten tests with both compilers --- Cargo.lock | 1 + Makefile | 3 ++- lib/emscripten/Cargo.toml | 5 +++++ lib/emscripten/src/utils.rs | 29 ++++++++++++++++++++----- lib/emscripten/tests/emtests/_common.rs | 23 ++++++++++++++++++-- 5 files changed, 53 insertions(+), 8 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f93daf2a7..a903bc9dc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1326,6 +1326,7 @@ dependencies = [ "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", "wabt 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)", "wasmer-clif-backend 0.2.0", + "wasmer-llvm-backend 0.1.0", "wasmer-runtime-core 0.2.1", ] diff --git a/Makefile b/Makefile index 6963cfc7f..77af8ae8f 100644 --- a/Makefile +++ b/Makefile @@ -45,7 +45,8 @@ test: cargo test -p wasmer-runtime-c-api -- --nocapture test-emscripten: - cargo test -p wasmer-emscripten -- --test-threads=1 $(runargs) + cargo test --manifest-path lib/spectests/Cargo.toml --features clif -- --test-threads=1 $(runargs) + cargo test --manifest-path lib/spectests/Cargo.toml --features llvm -- --test-threads=1 $(runargs) release: # If you are in OS-X, you will need mingw-w64 for cross compiling to windows diff --git a/lib/emscripten/Cargo.toml b/lib/emscripten/Cargo.toml index 62fb40c5a..3106d905c 100644 --- a/lib/emscripten/Cargo.toml +++ b/lib/emscripten/Cargo.toml @@ -20,7 +20,12 @@ rand = "0.6" [dev-dependencies] wasmer-clif-backend = { path = "../clif-backend", version = "0.2.0" } +wasmer-llvm-backend = { path = "../llvm-backend", version = "0.1.0" } wabt = "0.7.2" [build-dependencies] glob = "0.2.11" + +[features] +clif = [] +llvm = [] \ No newline at end of file diff --git a/lib/emscripten/src/utils.rs b/lib/emscripten/src/utils.rs index 678032374..56b080207 100644 --- a/lib/emscripten/src/utils.rs +++ b/lib/emscripten/src/utils.rs @@ -169,15 +169,34 @@ mod tests { use super::is_emscripten_module; use std::sync::Arc; use wabt::wat2wasm; - use wasmer_clif_backend::CraneliftCompiler; + use wasmer_runtime_core::backend::Compiler; use wasmer_runtime_core::compile_with; + #[cfg(feature = "clif")] + fn get_compiler() -> impl Compiler { + use wasmer_clif_backend::CraneliftCompiler; + CraneliftCompiler::new() + } + + #[cfg(feature = "llvm")] + fn get_compiler() -> impl Compiler { + use wasmer_llvm_backend::LLVMCompiler; + LLVMCompiler::new() + } + + #[cfg(not(any(feature = "llvm", feature = "clif")))] + fn get_compiler() -> impl Compiler { + panic!("compiler not specified, activate a compiler via features"); + use wasmer_clif_backend::CraneliftCompiler; + CraneliftCompiler::new() + } + #[test] fn should_detect_emscripten_files() { const WAST_BYTES: &[u8] = include_bytes!("tests/is_emscripten_true.wast"); let wasm_binary = wat2wasm(WAST_BYTES.to_vec()).expect("Can't convert to wasm"); - let module = compile_with(&wasm_binary[..], &CraneliftCompiler::new()) - .expect("WASM can't be compiled"); + let module = + compile_with(&wasm_binary[..], &get_compiler()).expect("WASM can't be compiled"); let module = Arc::new(module); assert!(is_emscripten_module(&module)); } @@ -186,8 +205,8 @@ mod tests { fn should_detect_non_emscripten_files() { const WAST_BYTES: &[u8] = include_bytes!("tests/is_emscripten_false.wast"); let wasm_binary = wat2wasm(WAST_BYTES.to_vec()).expect("Can't convert to wasm"); - let module = compile_with(&wasm_binary[..], &CraneliftCompiler::new()) - .expect("WASM can't be compiled"); + let module = + compile_with(&wasm_binary[..], &get_compiler()).expect("WASM can't be compiled"); let module = Arc::new(module); assert!(!is_emscripten_module(&module)); } diff --git a/lib/emscripten/tests/emtests/_common.rs b/lib/emscripten/tests/emtests/_common.rs index 8d3e00296..c252c9e98 100644 --- a/lib/emscripten/tests/emtests/_common.rs +++ b/lib/emscripten/tests/emtests/_common.rs @@ -1,16 +1,35 @@ macro_rules! assert_emscripten_output { ($file:expr, $name:expr, $args:expr, $expected:expr) => {{ - use wasmer_clif_backend::CraneliftCompiler; use wasmer_emscripten::{ EmscriptenGlobals, generate_emscripten_env, stdio::StdioCapturer }; + use wasmer_runtime_core::backend::Compiler; + + #[cfg(feature = "clif")] + fn get_compiler() -> impl Compiler { + use wasmer_clif_backend::CraneliftCompiler; + CraneliftCompiler::new() + } + + #[cfg(feature = "llvm")] + fn get_compiler() -> impl Compiler { + use wasmer_llvm_backend::LLVMCompiler; + LLVMCompiler::new() + } + + #[cfg(not(any(feature = "llvm", feature = "clif")))] + fn get_compiler() -> impl Compiler { + panic!("compiler not specified, activate a compiler via features"); + use wasmer_clif_backend::CraneliftCompiler; + CraneliftCompiler::new() + } let wasm_bytes = include_bytes!($file); - let module = wasmer_runtime_core::compile_with(&wasm_bytes[..], &CraneliftCompiler::new()) + let module = wasmer_runtime_core::compile_with(&wasm_bytes[..], &get_compiler()) .expect("WASM can't be compiled"); // let module = compile(&wasm_bytes[..]) From cad4110e10ff74d80810eb0e0030237dc7529e5c Mon Sep 17 00:00:00 2001 From: Brandon Fish Date: Wed, 6 Mar 2019 23:58:07 -0600 Subject: [PATCH 70/75] Fix typo in Makefile test-emscripten --- Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 77af8ae8f..a8e7c53de 100644 --- a/Makefile +++ b/Makefile @@ -45,8 +45,8 @@ test: cargo test -p wasmer-runtime-c-api -- --nocapture test-emscripten: - cargo test --manifest-path lib/spectests/Cargo.toml --features clif -- --test-threads=1 $(runargs) - cargo test --manifest-path lib/spectests/Cargo.toml --features llvm -- --test-threads=1 $(runargs) + cargo test --manifest-path lib/emscripten/Cargo.toml --features clif -- --test-threads=1 $(runargs) + cargo test --manifest-path lib/emscripten/Cargo.toml --features llvm -- --test-threads=1 $(runargs) release: # If you are in OS-X, you will need mingw-w64 for cross compiling to windows From 671ff09e6a80529a086f438a5a1a1e88bf83cfc2 Mon Sep 17 00:00:00 2001 From: Syrus Date: Thu, 7 Mar 2019 18:06:47 -0800 Subject: [PATCH 71/75] Use LLVM 5 for Windows --- .appveyor.yml | 20 ++++++++++---------- lib/llvm-backend/Cargo.toml | 7 ++++++- 2 files changed, 16 insertions(+), 11 deletions(-) diff --git a/.appveyor.yml b/.appveyor.yml index 46c989086..dec078c91 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -17,21 +17,21 @@ cache: - target install: - # Install LLVM - - mkdir C:\projects\deps - - cd C:\projects\deps - - appveyor DownloadFile http://prereleases.llvm.org/win-snapshots/LLVM-7.0.0-r336178-win64.exe -FileName llvm.exe - - 7z x llvm.exe -oC:\projects\deps\llvm - # - set "PATH=%PATH%;C:\projects\deps\llvm\bin" - - set "LLD_LINK=C:\projects\deps\llvm\bin\lld-link.exe" - - set "LLVM_SYS_70_PREFIX=C:\projects\deps\llvm" - - cd "%APPVEYOR_BUILD_FOLDER%" + # # Install LLVM + # - mkdir C:\projects\deps + # - cd C:\projects\deps + # - appveyor DownloadFile http://prereleases.llvm.org/win-snapshots/LLVM-7.0.0-r336178-win64.exe -FileName llvm.exe + # - 7z x llvm.exe -oC:\projects\deps\llvm + # # - set "PATH=%PATH%;C:\projects\deps\llvm\bin" + # - set "LLD_LINK=C:\projects\deps\llvm\bin\lld-link.exe" + # - set "LLVM_SYS_70_PREFIX=C:\projects\deps\llvm" + # - cd "%APPVEYOR_BUILD_FOLDER%" # Install Rust # uncomment these lines if the cache is cleared, or if we must re-install rust for some reason # - appveyor DownloadFile https://win.rustup.rs/ -FileName rustup-init.exe # - rustup-init.exe -yv --default-host %target% - - set PATH=%PATH%;C:\\projects\\deps\\llvm\\bin;%USERPROFILE%\.cargo\bin + - set PATH=%PATH%;C:\\Libraries\\llvm-5.0.0\\bin;%USERPROFILE%\.cargo\bin - rustup default stable-%target% - rustup update - rustc -vV diff --git a/lib/llvm-backend/Cargo.toml b/lib/llvm-backend/Cargo.toml index a3290f3fd..1dbb63a96 100644 --- a/lib/llvm-backend/Cargo.toml +++ b/lib/llvm-backend/Cargo.toml @@ -7,7 +7,6 @@ edition = "2018" [dependencies] wasmer-runtime-core = { path = "../runtime-core", version = "0.2.1" } wasmparser = "0.28.0" -inkwell = { git = "https://github.com/TheDan64/inkwell", branch = "llvm7-0" } hashbrown = "0.1.8" smallvec = "0.6.8" goblin = "0.0.20" @@ -15,6 +14,12 @@ libc = "0.2.49" nix = "0.13.0" capstone = { version = "0.5.0", optional = true } +[target.'cfg(windows)'.dependencies] +inkwell = { git = "https://github.com/TheDan64/inkwell", branch = "llvm5-0" } + +[target.'cfg(not(windows))'.dependencies] +inkwell = { git = "https://github.com/TheDan64/inkwell", branch = "llvm7-0" } + [build-dependencies] cc = "1.0" lazy_static = "1.2.0" From 7c2667ab0bd6a8fc488e7dae3fc62612a8321800 Mon Sep 17 00:00:00 2001 From: Syrus Date: Thu, 7 Mar 2019 18:06:53 -0800 Subject: [PATCH 72/75] Updated README --- README.md | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 74e9ef575..53677bca9 100644 --- a/README.md +++ b/README.md @@ -97,13 +97,19 @@ sudo apt install cmake Windows support is _highly experimental_. Only simple Wasm programs may be run, and no syscalls are allowed. This means nginx and Lua do not work on Windows. See [this issue](https://github.com/wasmerio/wasmer/issues/176) regarding Emscripten syscall polyfills for Windows. -1. Install [Python for Windows](https://www.python.org/downloads/release/python-2714/). The Windows x86-64 MSI installer is fine. +1. Install [Visual Studio](https://visualstudio.microsoft.com/thank-you-downloading-visual-studio/?sku=Community&rel=15) + +2. Install [Rust for Windows](https://win.rustup.rs) + +3. Install [Python for Windows](https://www.python.org/downloads/release/python-2714/). The Windows x86-64 MSI installer is fine. Make sure to enable "Add python.exe to Path" during installation. -2. Install [Git for Windows](https://git-scm.com/download/win). Allow it to add `git.exe` to your PATH (default +4. Install [Git for Windows](https://git-scm.com/download/win). Allow it to add `git.exe` to your PATH (default settings for the installer are fine). -3. Install [CMake](https://cmake.org/download/). Ensure CMake is in your PATH. +5. Install [CMake](https://cmake.org/download/). Ensure CMake is in your PATH. + +6. Install [LLVM 7.0](https://prereleases.llvm.org/win-snapshots/LLVM-7.0.0-r336178-win64.exe) ## Building From 3a4325c5a3c6df990797f1d40c54609bcd832a25 Mon Sep 17 00:00:00 2001 From: Syrus Date: Thu, 7 Mar 2019 18:26:29 -0800 Subject: [PATCH 73/75] Only use llvm in non windows envs --- Cargo.lock | 1 + Cargo.toml | 6 ++++++ lib/emscripten/Cargo.toml | 4 +++- lib/llvm-backend/Cargo.toml | 7 +------ lib/runtime/Cargo.toml | 2 +- lib/spectests/Cargo.toml | 4 +++- 6 files changed, 15 insertions(+), 9 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a903bc9dc..2ee89b128 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1286,6 +1286,7 @@ dependencies = [ "wabt 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)", "wasmer-clif-backend 0.2.0", "wasmer-emscripten 0.2.1", + "wasmer-llvm-backend 0.1.0", "wasmer-runtime 0.2.1", "wasmer-runtime-core 0.2.1", ] diff --git a/Cargo.toml b/Cargo.toml index d987498cf..67672e097 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -26,7 +26,13 @@ wasmer-runtime = { path = "lib/runtime" } wasmer-runtime-core = { path = "lib/runtime-core" } wasmer-emscripten = { path = "lib/emscripten" } +[target.'cfg(not(windows))'.dependencies] +wasmer-llvm-backend = { path = "lib/llvm-backend" } + [workspace] +members = ["lib/clif-backend", "lib/runtime", "lib/runtime-core", "lib/emscripten", "lib/spectests", "lib/win-exception-handler", "lib/runtime-c-api"] + +[target.'cfg(not(windows))'.workspace] members = ["lib/clif-backend", "lib/runtime", "lib/runtime-core", "lib/emscripten", "lib/spectests", "lib/win-exception-handler", "lib/runtime-c-api", "lib/llvm-backend"] [build-dependencies] diff --git a/lib/emscripten/Cargo.toml b/lib/emscripten/Cargo.toml index 3106d905c..cd691e566 100644 --- a/lib/emscripten/Cargo.toml +++ b/lib/emscripten/Cargo.toml @@ -20,9 +20,11 @@ rand = "0.6" [dev-dependencies] wasmer-clif-backend = { path = "../clif-backend", version = "0.2.0" } -wasmer-llvm-backend = { path = "../llvm-backend", version = "0.1.0" } wabt = "0.7.2" +[target.'cfg(not(windows))'.dev-dependencies] +wasmer-llvm-backend = { path = "../llvm-backend", version = "0.1.0" } + [build-dependencies] glob = "0.2.11" diff --git a/lib/llvm-backend/Cargo.toml b/lib/llvm-backend/Cargo.toml index 1dbb63a96..e6f58e6e7 100644 --- a/lib/llvm-backend/Cargo.toml +++ b/lib/llvm-backend/Cargo.toml @@ -6,6 +6,7 @@ edition = "2018" [dependencies] wasmer-runtime-core = { path = "../runtime-core", version = "0.2.1" } +inkwell = { git = "https://github.com/TheDan64/inkwell", branch = "llvm7-0" } wasmparser = "0.28.0" hashbrown = "0.1.8" smallvec = "0.6.8" @@ -14,12 +15,6 @@ libc = "0.2.49" nix = "0.13.0" capstone = { version = "0.5.0", optional = true } -[target.'cfg(windows)'.dependencies] -inkwell = { git = "https://github.com/TheDan64/inkwell", branch = "llvm5-0" } - -[target.'cfg(not(windows))'.dependencies] -inkwell = { git = "https://github.com/TheDan64/inkwell", branch = "llvm7-0" } - [build-dependencies] cc = "1.0" lazy_static = "1.2.0" diff --git a/lib/runtime/Cargo.toml b/lib/runtime/Cargo.toml index 12b719248..895423ead 100644 --- a/lib/runtime/Cargo.toml +++ b/lib/runtime/Cargo.toml @@ -25,7 +25,7 @@ tempfile = "3.0.7" criterion = "0.2" wabt = "0.7.4" -[dependencies.wasmer-llvm-backend] +[target.'cfg(not(windows))'.dependencies.wasmer-llvm-backend] path = "../llvm-backend" [features] diff --git a/lib/spectests/Cargo.toml b/lib/spectests/Cargo.toml index e9ce75132..fea4560c5 100644 --- a/lib/spectests/Cargo.toml +++ b/lib/spectests/Cargo.toml @@ -16,9 +16,11 @@ wabt = "0.7.2" [dev-dependencies] wasmer-clif-backend = { path = "../clif-backend", version = "0.2.0" } -wasmer-llvm-backend = { path = "../llvm-backend", version = "0.1.0" } wabt = "0.7.2" +[target.'cfg(not(windows))'.dev-dependencies] +wasmer-llvm-backend = { path = "../llvm-backend", version = "0.1.0" } + [features] default = ["fast-tests"] fast-tests = [] From 4acb826bf23723693c08147261223549d3d32f73 Mon Sep 17 00:00:00 2001 From: Syrus Date: Thu, 7 Mar 2019 19:11:15 -0800 Subject: [PATCH 74/75] Fixed default compiler on windows --- lib/runtime/src/lib.rs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/lib/runtime/src/lib.rs b/lib/runtime/src/lib.rs index 4c5ce88cd..4ad74c345 100644 --- a/lib/runtime/src/lib.rs +++ b/lib/runtime/src/lib.rs @@ -154,11 +154,15 @@ pub fn instantiate(wasm: &[u8], import_object: &ImportObject) -> error::Result &'static dyn Compiler { use lazy_static::lazy_static; - // use wasmer_clif_backend::CraneliftCompiler; - use wasmer_llvm_backend::LLVMCompiler; + + #[cfg(feature = "llvm")] + use wasmer_llvm_backend::LLVMCompiler as DefaultCompiler; + + #[cfg(not(feature = "llvm"))] + use wasmer_clif_backend::CraneliftCompiler as DefaultCompiler; lazy_static! { - static ref DEFAULT_COMPILER: LLVMCompiler = { LLVMCompiler::new() }; + static ref DEFAULT_COMPILER: DefaultCompiler = { DefaultCompiler::new() }; } &*DEFAULT_COMPILER as &dyn Compiler From 3866f8fd73c307099ec580de01a0537d9b1081b2 Mon Sep 17 00:00:00 2001 From: Syrus Date: Thu, 7 Mar 2019 19:32:04 -0800 Subject: [PATCH 75/75] Updated test script --- .appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.appveyor.yml b/.appveyor.yml index dec078c91..eca2e24ae 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -48,7 +48,7 @@ build_script: - cargo build --release --verbose test_script: - - cargo test --package wasmer-spectests + - cargo test --manifest-path lib/spectests/Cargo.toml --features clif after_build: - cd ./src/installer