From 3b2d751c5595126fe90aabab8d1cdf8dd871f41f Mon Sep 17 00:00:00 2001 From: anb Date: Wed, 13 Nov 2019 12:31:50 -0800 Subject: [PATCH 1/3] Enable compilation for specific target By exposing the target information through `CompilerConfig`, compiler(only LLVM at the moment) could create a machine with different CPU feature flags other than current host, which makes it capable to "cross compile" to some degree. Update #959 --- lib/clif-backend/src/code.rs | 4 +++ lib/llvm-backend/src/code.rs | 35 ++++++++++++++++------- lib/runtime-core/src/backend.rs | 5 ++++ lib/runtime-core/src/codegen.rs | 16 ++++++++++- lib/singlepass-backend/src/codegen_x64.rs | 4 +++ src/bin/kwasmd.rs | 1 + src/bin/wasmer.rs | 1 + 7 files changed, 54 insertions(+), 12 deletions(-) diff --git a/lib/clif-backend/src/code.rs b/lib/clif-backend/src/code.rs index 1bd1958e3..d86d19b4f 100644 --- a/lib/clif-backend/src/code.rs +++ b/lib/clif-backend/src/code.rs @@ -54,6 +54,10 @@ impl ModuleCodeGenerator } } + fn new_with_target(_: Option, _: Option, _: Option) -> Self { + unimplemented!("cross compilation is not available for clif backend") + } + fn backend_id() -> Backend { Backend::Cranelift } diff --git a/lib/llvm-backend/src/code.rs b/lib/llvm-backend/src/code.rs index ac7ac92bb..0aca84650 100644 --- a/lib/llvm-backend/src/code.rs +++ b/lib/llvm-backend/src/code.rs @@ -8075,24 +8075,37 @@ impl ModuleCodeGenerator for LLVMModuleCodeGenerator { fn new() -> LLVMModuleCodeGenerator { + Self::new_with_target(None, None, None) + } + + fn new_with_target( + triple: Option, + cpu_name: Option, + cpu_features: Option, + ) -> LLVMModuleCodeGenerator { let context = Context::create(); let module = context.create_module("module"); - 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 triple = triple.unwrap_or(TargetMachine::get_default_triple().to_string()); + + match triple { + _ if triple.starts_with("x86") => Target::initialize_x86(&InitializationConfig { + asm_parser: true, + asm_printer: true, + base: true, + disassembler: true, + info: true, + machine_code: true, + }), + _ => unimplemented!("compile to target other than x86-64 is not supported"), + } + 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(), + &cpu_name.unwrap_or(TargetMachine::get_host_cpu_name().to_string()), + &cpu_features.unwrap_or(TargetMachine::get_host_cpu_features().to_string()), OptimizationLevel::Aggressive, RelocMode::Static, CodeModel::Large, diff --git a/lib/runtime-core/src/backend.rs b/lib/runtime-core/src/backend.rs index f1086de0d..893874ed9 100644 --- a/lib/runtime-core/src/backend.rs +++ b/lib/runtime-core/src/backend.rs @@ -129,6 +129,11 @@ pub struct CompilerConfig { pub enforce_stack_check: bool, pub track_state: bool, pub features: Features, + + // target info used by LLVM + pub triple: Option, + pub cpu_name: Option, + pub cpu_features: Option, } pub trait Compiler { diff --git a/lib/runtime-core/src/codegen.rs b/lib/runtime-core/src/codegen.rs index e96f419e6..9e42d8049 100644 --- a/lib/runtime-core/src/codegen.rs +++ b/lib/runtime-core/src/codegen.rs @@ -74,6 +74,13 @@ pub trait ModuleCodeGenerator, RM: RunnableModule, /// Creates a new module code generator. fn new() -> Self; + /// Creates a new module code generator for specified target. + fn new_with_target( + triple: Option, + cpu_name: Option, + cpu_features: Option, + ) -> Self; + /// Returns the backend id associated with this MCG. fn backend_id() -> Backend; @@ -206,7 +213,14 @@ impl< validate_with_features(wasm, &compiler_config.features)?; } - let mut mcg = MCG::new(); + let mut mcg = match MCG::backend_id() { + Backend::LLVM => MCG::new_with_target( + compiler_config.triple.clone(), + compiler_config.cpu_name.clone(), + compiler_config.cpu_features.clone(), + ), + _ => MCG::new(), + }; let mut chain = (self.middleware_chain_generator)(); let info = crate::parse::read_module( wasm, diff --git a/lib/singlepass-backend/src/codegen_x64.rs b/lib/singlepass-backend/src/codegen_x64.rs index 7a71a289f..e4934e3c2 100644 --- a/lib/singlepass-backend/src/codegen_x64.rs +++ b/lib/singlepass-backend/src/codegen_x64.rs @@ -370,6 +370,10 @@ impl ModuleCodeGenerator } } + fn new_with_target(_: Option, _: Option, _: Option) -> Self { + unimplemented!("cross compilation is not available for singlepass backend") + } + fn backend_id() -> Backend { Backend::Singlepass } diff --git a/src/bin/kwasmd.rs b/src/bin/kwasmd.rs index 62e22b731..79949417b 100644 --- a/src/bin/kwasmd.rs +++ b/src/bin/kwasmd.rs @@ -63,6 +63,7 @@ fn handle_client(mut stream: UnixStream) { enforce_stack_check: true, track_state: false, features: Default::default(), + ..Default::default() }, &SinglePassCompiler::new(), ) diff --git a/src/bin/wasmer.rs b/src/bin/wasmer.rs index 7af5df3e2..ad9afa972 100644 --- a/src/bin/wasmer.rs +++ b/src/bin/wasmer.rs @@ -447,6 +447,7 @@ fn execute_wasm(options: &Run) -> Result<(), String> { simd: options.features.simd || options.features.all, threads: options.features.threads || options.features.all, }, + ..Default::default() }, &*compiler, ) From b36bf011884f664ed12f33e4563d28329d743783 Mon Sep 17 00:00:00 2001 From: losfair Date: Sun, 17 Nov 2019 04:38:40 +0800 Subject: [PATCH 2/3] Update Rust version to 1.39.0. --- Dockerfile | 2 +- README.md | 2 +- azure-pipelines.yml | 8 ++++---- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Dockerfile b/Dockerfile index 6affe470f..c118f0f57 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM circleci/rust:1.38.0-stretch as wasmer-build-env +FROM circleci/rust:1.39.0-stretch as wasmer-build-env RUN sudo apt-get update && \ sudo apt-get install -y --no-install-recommends \ cmake \ diff --git a/README.md b/README.md index 98533edf9..77fd34357 100644 --- a/README.md +++ b/README.md @@ -181,7 +181,7 @@ nginx and Lua do not work on Windows - you can track the progress on [this issue ## Building -[![Rustc Version 1.38+](https://img.shields.io/badge/rustc-1.37+-red.svg?style=flat-square)](https://blog.rust-lang.org/2019/09/26/Rust-1.38.0.html) +[![Rustc Version 1.39+](https://img.shields.io/badge/rustc-1.39+-red.svg?style=flat-square)](https://blog.rust-lang.org/2019/09/26/Rust-1.39.0.html) Wasmer is built with [Cargo](https://crates.io/), the Rust package manager. diff --git a/azure-pipelines.yml b/azure-pipelines.yml index a8b571e28..d99561a21 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -22,7 +22,7 @@ jobs: - script: cargo fmt --all -- --check displayName: Lint variables: - rust_toolchain: '1.38.0' + rust_toolchain: '1.39.0' - job: Test strategy: @@ -39,7 +39,7 @@ jobs: CARGO_HTTP_CHECK_REVOKE: false windows: imageName: "vs2017-win2016" - rust_toolchain: '1.38.0' + rust_toolchain: '1.39.0' pool: vmImage: $(imageName) condition: in(variables['Build.SourceBranch'], 'refs/heads/master', 'refs/heads/staging', 'refs/heads/trying') @@ -100,7 +100,7 @@ jobs: MACOSX_DEPLOYMENT_TARGET: 10.10 windows: imageName: "vs2017-win2016" - rust_toolchain: '1.38.0' + rust_toolchain: '1.39.0' # RUSTFLAGS: -Ctarget-feature=+crt-static pool: vmImage: $(imageName) @@ -163,7 +163,7 @@ jobs: MACOSX_DEPLOYMENT_TARGET: 10.10 windows: imageName: "vs2017-win2016" - rust_toolchain: '1.38.0' + rust_toolchain: '1.39.0' # RUSTFLAGS: -Ctarget-feature=+crt-static pool: vmImage: $(imageName) From 021a75244e52ec420bd6db65849b163e1673990c Mon Sep 17 00:00:00 2001 From: losfair Date: Sun, 17 Nov 2019 04:39:39 +0800 Subject: [PATCH 3/3] Reformat code for rust 1.39. --- lib/singlepass-backend/src/emitter_x64.rs | 88 +++++++++++++++++------ 1 file changed, 66 insertions(+), 22 deletions(-) diff --git a/lib/singlepass-backend/src/emitter_x64.rs b/lib/singlepass-backend/src/emitter_x64.rs index a40d5b5e5..251868231 100644 --- a/lib/singlepass-backend/src/emitter_x64.rs +++ b/lib/singlepass-backend/src/emitter_x64.rs @@ -709,14 +709,18 @@ impl Emitter for Assembler { match (sz, src) { (Size::S64, Location::Imm32(src)) => dynasm!(self ; push src as i32), (Size::S64, Location::GPR(src)) => dynasm!(self ; push Rq(src as u8)), - (Size::S64, Location::Memory(src, disp)) => dynasm!(self ; push QWORD [Rq(src as u8) + disp]), + (Size::S64, Location::Memory(src, disp)) => { + dynasm!(self ; push QWORD [Rq(src as u8) + disp]) + } _ => panic!("singlepass can't emit PUSH {:?} {:?}", sz, src), } } fn emit_pop(&mut self, sz: Size, dst: Location) { match (sz, dst) { (Size::S64, Location::GPR(dst)) => dynasm!(self ; pop Rq(dst as u8)), - (Size::S64, Location::Memory(dst, disp)) => dynasm!(self ; pop QWORD [Rq(dst as u8) + disp]), + (Size::S64, Location::Memory(dst, disp)) => { + dynasm!(self ; pop QWORD [Rq(dst as u8) + disp]) + } _ => panic!("singlepass can't emit POP {:?} {:?}", sz, dst), } } @@ -738,13 +742,21 @@ impl Emitter for Assembler { fn emit_neg(&mut self, sz: Size, value: Location) { match (sz, value) { (Size::S8, Location::GPR(value)) => dynasm!(self ; neg Rb(value as u8)), - (Size::S8, Location::Memory(value, disp)) => dynasm!(self ; neg [Rq(value as u8) + disp]), + (Size::S8, Location::Memory(value, disp)) => { + dynasm!(self ; neg [Rq(value as u8) + disp]) + } (Size::S16, Location::GPR(value)) => dynasm!(self ; neg Rw(value as u8)), - (Size::S16, Location::Memory(value, disp)) => dynasm!(self ; neg [Rq(value as u8) + disp]), + (Size::S16, Location::Memory(value, disp)) => { + dynasm!(self ; neg [Rq(value as u8) + disp]) + } (Size::S32, Location::GPR(value)) => dynasm!(self ; neg Rd(value as u8)), - (Size::S32, Location::Memory(value, disp)) => dynasm!(self ; neg [Rq(value as u8) + disp]), + (Size::S32, Location::Memory(value, disp)) => { + dynasm!(self ; neg [Rq(value as u8) + disp]) + } (Size::S64, Location::GPR(value)) => dynasm!(self ; neg Rq(value as u8)), - (Size::S64, Location::Memory(value, disp)) => dynasm!(self ; neg [Rq(value as u8) + disp]), + (Size::S64, Location::Memory(value, disp)) => { + dynasm!(self ; neg [Rq(value as u8) + disp]) + } _ => panic!("singlepass can't emit NEG {:?} {:?}", sz, value), } } @@ -997,18 +1009,30 @@ impl Emitter for Assembler { fn emit_vmovaps(&mut self, src: XMMOrMemory, dst: XMMOrMemory) { match (src, dst) { - (XMMOrMemory::XMM(src), XMMOrMemory::XMM(dst)) => dynasm!(self ; movaps Rx(dst as u8), Rx(src as u8)), - (XMMOrMemory::Memory(base, disp), XMMOrMemory::XMM(dst)) => dynasm!(self ; movaps Rx(dst as u8), [Rq(base as u8) + disp]), - (XMMOrMemory::XMM(src), XMMOrMemory::Memory(base, disp)) => dynasm!(self ; movaps [Rq(base as u8) + disp], Rx(src as u8)), + (XMMOrMemory::XMM(src), XMMOrMemory::XMM(dst)) => { + dynasm!(self ; movaps Rx(dst as u8), Rx(src as u8)) + } + (XMMOrMemory::Memory(base, disp), XMMOrMemory::XMM(dst)) => { + dynasm!(self ; movaps Rx(dst as u8), [Rq(base as u8) + disp]) + } + (XMMOrMemory::XMM(src), XMMOrMemory::Memory(base, disp)) => { + dynasm!(self ; movaps [Rq(base as u8) + disp], Rx(src as u8)) + } _ => panic!("singlepass can't emit VMOVAPS {:?} {:?}", src, dst), }; } fn emit_vmovapd(&mut self, src: XMMOrMemory, dst: XMMOrMemory) { match (src, dst) { - (XMMOrMemory::XMM(src), XMMOrMemory::XMM(dst)) => dynasm!(self ; movapd Rx(dst as u8), Rx(src as u8)), - (XMMOrMemory::Memory(base, disp), XMMOrMemory::XMM(dst)) => dynasm!(self ; movapd Rx(dst as u8), [Rq(base as u8) + disp]), - (XMMOrMemory::XMM(src), XMMOrMemory::Memory(base, disp)) => dynasm!(self ; movapd [Rq(base as u8) + disp], Rx(src as u8)), + (XMMOrMemory::XMM(src), XMMOrMemory::XMM(dst)) => { + dynasm!(self ; movapd Rx(dst as u8), Rx(src as u8)) + } + (XMMOrMemory::Memory(base, disp), XMMOrMemory::XMM(dst)) => { + dynasm!(self ; movapd Rx(dst as u8), [Rq(base as u8) + disp]) + } + (XMMOrMemory::XMM(src), XMMOrMemory::Memory(base, disp)) => { + dynasm!(self ; movapd [Rq(base as u8) + disp], Rx(src as u8)) + } _ => panic!("singlepass can't emit VMOVAPD {:?} {:?}", src, dst), }; } @@ -1080,57 +1104,77 @@ impl Emitter for Assembler { fn emit_vblendvps(&mut self, src1: XMM, src2: XMMOrMemory, mask: XMM, dst: XMM) { match src2 { - XMMOrMemory::XMM(src2) => dynasm!(self ; vblendvps Rx(dst as u8), Rx(mask as u8), Rx(src2 as u8), Rx(src1 as u8)), - XMMOrMemory::Memory(base, disp) => dynasm!(self ; vblendvps Rx(dst as u8), Rx(mask as u8), [Rq(base as u8) + disp], Rx(src1 as u8)), + XMMOrMemory::XMM(src2) => { + dynasm!(self ; vblendvps Rx(dst as u8), Rx(mask as u8), Rx(src2 as u8), Rx(src1 as u8)) + } + XMMOrMemory::Memory(base, disp) => { + dynasm!(self ; vblendvps Rx(dst as u8), Rx(mask as u8), [Rq(base as u8) + disp], Rx(src1 as u8)) + } } } fn emit_vblendvpd(&mut self, src1: XMM, src2: XMMOrMemory, mask: XMM, dst: XMM) { match src2 { - XMMOrMemory::XMM(src2) => dynasm!(self ; vblendvpd Rx(dst as u8), Rx(mask as u8), Rx(src2 as u8), Rx(src1 as u8)), - XMMOrMemory::Memory(base, disp) => dynasm!(self ; vblendvpd Rx(dst as u8), Rx(mask as u8), [Rq(base as u8) + disp], Rx(src1 as u8)), + XMMOrMemory::XMM(src2) => { + dynasm!(self ; vblendvpd Rx(dst as u8), Rx(mask as u8), Rx(src2 as u8), Rx(src1 as u8)) + } + XMMOrMemory::Memory(base, disp) => { + dynasm!(self ; vblendvpd Rx(dst as u8), Rx(mask as u8), [Rq(base as u8) + disp], Rx(src1 as u8)) + } } } fn emit_ucomiss(&mut self, src: XMMOrMemory, dst: XMM) { match src { XMMOrMemory::XMM(x) => dynasm!(self ; ucomiss Rx(dst as u8), Rx(x as u8)), - XMMOrMemory::Memory(base, disp) => dynasm!(self ; ucomiss Rx(dst as u8), [Rq(base as u8) + disp]), + XMMOrMemory::Memory(base, disp) => { + dynasm!(self ; ucomiss Rx(dst as u8), [Rq(base as u8) + disp]) + } } } fn emit_ucomisd(&mut self, src: XMMOrMemory, dst: XMM) { match src { XMMOrMemory::XMM(x) => dynasm!(self ; ucomisd Rx(dst as u8), Rx(x as u8)), - XMMOrMemory::Memory(base, disp) => dynasm!(self ; ucomisd Rx(dst as u8), [Rq(base as u8) + disp]), + XMMOrMemory::Memory(base, disp) => { + dynasm!(self ; ucomisd Rx(dst as u8), [Rq(base as u8) + disp]) + } } } fn emit_cvttss2si_32(&mut self, src: XMMOrMemory, dst: GPR) { match src { XMMOrMemory::XMM(x) => dynasm!(self ; cvttss2si Rd(dst as u8), Rx(x as u8)), - XMMOrMemory::Memory(base, disp) => dynasm!(self ; cvttss2si Rd(dst as u8), [Rq(base as u8) + disp]), + XMMOrMemory::Memory(base, disp) => { + dynasm!(self ; cvttss2si Rd(dst as u8), [Rq(base as u8) + disp]) + } } } fn emit_cvttss2si_64(&mut self, src: XMMOrMemory, dst: GPR) { match src { XMMOrMemory::XMM(x) => dynasm!(self ; cvttss2si Rq(dst as u8), Rx(x as u8)), - XMMOrMemory::Memory(base, disp) => dynasm!(self ; cvttss2si Rq(dst as u8), [Rq(base as u8) + disp]), + XMMOrMemory::Memory(base, disp) => { + dynasm!(self ; cvttss2si Rq(dst as u8), [Rq(base as u8) + disp]) + } } } fn emit_cvttsd2si_32(&mut self, src: XMMOrMemory, dst: GPR) { match src { XMMOrMemory::XMM(x) => dynasm!(self ; cvttsd2si Rd(dst as u8), Rx(x as u8)), - XMMOrMemory::Memory(base, disp) => dynasm!(self ; cvttsd2si Rd(dst as u8), [Rq(base as u8) + disp]), + XMMOrMemory::Memory(base, disp) => { + dynasm!(self ; cvttsd2si Rd(dst as u8), [Rq(base as u8) + disp]) + } } } fn emit_cvttsd2si_64(&mut self, src: XMMOrMemory, dst: GPR) { match src { XMMOrMemory::XMM(x) => dynasm!(self ; cvttsd2si Rq(dst as u8), Rx(x as u8)), - XMMOrMemory::Memory(base, disp) => dynasm!(self ; cvttsd2si Rq(dst as u8), [Rq(base as u8) + disp]), + XMMOrMemory::Memory(base, disp) => { + dynasm!(self ; cvttsd2si Rq(dst as u8), [Rq(base as u8) + disp]) + } } }