From a1981a64a22024bbda98cf1b76b7c751fb1dcddb Mon Sep 17 00:00:00 2001 From: Thomas Lively Date: Fri, 16 Jun 2017 15:43:43 -0700 Subject: [PATCH] Add target to use LLVM wasm backend The new target is wasm32-experimental-emscripten. Adds a new configuration option to opt in to building experimental LLVM backends such as the WebAssembly backend. The target name was chosen to be similar to the existing wasm32-unknown-emscripten target so that the build and tests would work with minimal other code changes. When/if the new target replaces the old target, simply renaming it should just work. --- src/bootstrap/config.rs | 3 ++ src/bootstrap/config.toml.example | 8 +++ src/bootstrap/native.rs | 6 +++ src/librustc_back/target/mod.rs | 1 + .../target/wasm32_experimental_emscripten.rs | 53 +++++++++++++++++++ src/librustc_llvm/build.rs | 2 +- src/librustc_llvm/lib.rs | 5 ++ 7 files changed, 77 insertions(+), 1 deletion(-) create mode 100644 src/librustc_back/target/wasm32_experimental_emscripten.rs diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs index 64b2a665e25..fd8aa320fb3 100644 --- a/src/bootstrap/config.rs +++ b/src/bootstrap/config.rs @@ -60,6 +60,7 @@ pub struct Config { pub llvm_static_stdcpp: bool, pub llvm_link_shared: bool, pub llvm_targets: Option, + pub llvm_experimental_targets: Option, pub llvm_link_jobs: Option, pub llvm_clean_rebuild: bool, @@ -189,6 +190,7 @@ struct Llvm { version_check: Option, static_libstdcpp: Option, targets: Option, + experimental_targets: Option, link_jobs: Option, clean_rebuild: Option, } @@ -350,6 +352,7 @@ impl Config { set(&mut config.llvm_static_stdcpp, llvm.static_libstdcpp); set(&mut config.llvm_clean_rebuild, llvm.clean_rebuild); config.llvm_targets = llvm.targets.clone(); + config.llvm_experimental_targets = llvm.experimental_targets.clone(); config.llvm_link_jobs = llvm.link_jobs; } diff --git a/src/bootstrap/config.toml.example b/src/bootstrap/config.toml.example index 3a467dafbfb..7a52222e46e 100644 --- a/src/bootstrap/config.toml.example +++ b/src/bootstrap/config.toml.example @@ -53,6 +53,14 @@ # Rust team and file an issue if you need assistance in porting! #targets = "X86;ARM;AArch64;Mips;PowerPC;SystemZ;JSBackend;MSP430;Sparc;NVPTX;Hexagon" +# LLVM experimental targets to build support for. These targets are specified in +# the same format as above, but since these targets are experimental, they are +# not built by default and the experimental Rust compilation targets that depend +# on them will not work unless the user opts in to building them. Possible +# experimental LLVM targets include WebAssembly for the +# wasm32-experimental-emscripten Rust target. +#experimental-targets = "" + # Cap the number of parallel linker invocations when compiling LLVM. # This can be useful when building LLVM with debug info, which significantly # increases the size of binaries and consequently the memory required by diff --git a/src/bootstrap/native.rs b/src/bootstrap/native.rs index 6b9a6347d22..a23be37b15e 100644 --- a/src/bootstrap/native.rs +++ b/src/bootstrap/native.rs @@ -86,6 +86,11 @@ pub fn llvm(build: &Build, target: &str) { None => "X86;ARM;AArch64;Mips;PowerPC;SystemZ;JSBackend;MSP430;Sparc;NVPTX;Hexagon", }; + let llvm_exp_targets = match build.config.llvm_experimental_targets { + Some(ref s) => s, + None => "", + }; + let assertions = if build.config.llvm_assertions {"ON"} else {"OFF"}; cfg.target(target) @@ -94,6 +99,7 @@ pub fn llvm(build: &Build, target: &str) { .profile(profile) .define("LLVM_ENABLE_ASSERTIONS", assertions) .define("LLVM_TARGETS_TO_BUILD", llvm_targets) + .define("LLVM_EXPERIMENTAL_TARGETS_TO_BUILD", llvm_exp_targets) .define("LLVM_INCLUDE_EXAMPLES", "OFF") .define("LLVM_INCLUDE_TESTS", "OFF") .define("LLVM_INCLUDE_DOCS", "OFF") diff --git a/src/librustc_back/target/mod.rs b/src/librustc_back/target/mod.rs index e60fdc386ce..37d6a6b95d9 100644 --- a/src/librustc_back/target/mod.rs +++ b/src/librustc_back/target/mod.rs @@ -214,6 +214,7 @@ supported_targets! { ("le32-unknown-nacl", le32_unknown_nacl), ("asmjs-unknown-emscripten", asmjs_unknown_emscripten), ("wasm32-unknown-emscripten", wasm32_unknown_emscripten), + ("wasm32-experimental-emscripten", wasm32_experimental_emscripten), ("thumbv6m-none-eabi", thumbv6m_none_eabi), ("thumbv7m-none-eabi", thumbv7m_none_eabi), diff --git a/src/librustc_back/target/wasm32_experimental_emscripten.rs b/src/librustc_back/target/wasm32_experimental_emscripten.rs new file mode 100644 index 00000000000..1a95c93363a --- /dev/null +++ b/src/librustc_back/target/wasm32_experimental_emscripten.rs @@ -0,0 +1,53 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use LinkerFlavor; +use super::{LinkArgs, Target, TargetOptions}; +use super::emscripten_base::{cmd}; + +pub fn target() -> Result { + let mut post_link_args = LinkArgs::new(); + post_link_args.insert(LinkerFlavor::Em, + vec!["-s".to_string(), + "WASM=1".to_string(), + "-s".to_string(), + "ERROR_ON_UNDEFINED_SYMBOLS=1".to_string()]); + + let opts = TargetOptions { + linker: cmd("emcc"), + ar: cmd("emar"), + + dynamic_linking: false, + executables: true, + // Today emcc emits two files - a .js file to bootstrap and + // possibly interpret the wasm, and a .wasm file + exe_suffix: ".js".to_string(), + linker_is_gnu: true, + allow_asm: false, + obj_is_bitcode: true, + is_like_emscripten: true, + max_atomic_width: Some(32), + post_link_args: post_link_args, + target_family: Some("unix".to_string()), + .. Default::default() + }; + Ok(Target { + llvm_target: "wasm32-unknown-unknown".to_string(), + target_endian: "little".to_string(), + target_pointer_width: "32".to_string(), + target_os: "emscripten".to_string(), + target_env: "".to_string(), + target_vendor: "unknown".to_string(), + data_layout: "e-m:e-p:32:32-i64:64-n32:64-S128".to_string(), + arch: "wasm32".to_string(), + linker_flavor: LinkerFlavor::Em, + options: opts, + }) +} diff --git a/src/librustc_llvm/build.rs b/src/librustc_llvm/build.rs index bdfc0a2fe85..01b37a55f4f 100644 --- a/src/librustc_llvm/build.rs +++ b/src/librustc_llvm/build.rs @@ -93,7 +93,7 @@ fn main() { let mut optional_components = vec!["x86", "arm", "aarch64", "mips", "powerpc", "pnacl", - "systemz", "jsbackend", "msp430", "sparc", "nvptx"]; + "systemz", "jsbackend", "webassembly", "msp430", "sparc", "nvptx"]; let mut version_cmd = Command::new(&llvm_config); version_cmd.arg("--version"); diff --git a/src/librustc_llvm/lib.rs b/src/librustc_llvm/lib.rs index 790d493f191..e2d0b204837 100644 --- a/src/librustc_llvm/lib.rs +++ b/src/librustc_llvm/lib.rs @@ -389,6 +389,11 @@ pub fn initialize_available_targets() { LLVMInitializeHexagonTargetMC, LLVMInitializeHexagonAsmPrinter, LLVMInitializeHexagonAsmParser); + init_target!(llvm_component = "webassembly", + LLVMInitializeWebAssemblyTargetInfo, + LLVMInitializeWebAssemblyTarget, + LLVMInitializeWebAssemblyTargetMC, + LLVMInitializeWebAssemblyAsmPrinter); } pub fn last_error() -> Option {