From fc497d00263be103ca9d009206963d4a5763392d Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Fri, 31 Aug 2018 22:41:17 -0700 Subject: [PATCH] rustc: Prepare the `atomics` feature for wasm This commit adds a few changes for atomic instructions on the `wasm32-unknown-unknown` target. Atomic instructions are not yet stable in WebAssembly itself but there are multiple implementations and LLVM has support for the proposed instruction set, so let's work on exposing it! Here there are a few inclusions: * The `atomics` feature was whitelisted for LLVM, allowing code in Rust to enable/disable/gate on this. * The `singlethread` option is turned off for wasm when the `atomics` feature is enabled. This means that by default wasm won't be lowering with atomics, but when atomics are enabled globally we'll turn off single-threaded mode to actually codegen atomics. This probably isn't what we'll want in the long term but for now it should work. * Finally the maximum atomic width is increased to 64 to reflect the current wasm spec. --- src/librustc_codegen_llvm/back/write.rs | 17 +++++++++++++---- src/librustc_codegen_llvm/llvm_util.rs | 1 + .../spec/wasm32_unknown_unknown.rs | 3 +-- 3 files changed, 15 insertions(+), 6 deletions(-) diff --git a/src/librustc_codegen_llvm/back/write.rs b/src/librustc_codegen_llvm/back/write.rs index 2373428d68c0d..c88a1809cabc7 100644 --- a/src/librustc_codegen_llvm/back/write.rs +++ b/src/librustc_codegen_llvm/back/write.rs @@ -171,13 +171,22 @@ pub fn target_machine_factory(sess: &Session, find_features: bool) None => llvm::CodeModel::None, }; - let singlethread = sess.target.target.options.singlethread; + let features = attributes::llvm_target_features(sess).collect::>(); + let mut singlethread = sess.target.target.options.singlethread; + + // On the wasm target once the `atomics` feature is enabled that means that + // we're no longer single-threaded, or otherwise we don't want LLVM to + // lower atomic operations to single-threaded operations. + if singlethread && + sess.target.target.llvm_target.contains("wasm32") && + features.iter().any(|s| *s == "+atomics") + { + singlethread = false; + } let triple = SmallCStr::new(&sess.target.target.llvm_target); let cpu = SmallCStr::new(llvm_util::target_cpu(sess)); - let features = attributes::llvm_target_features(sess) - .collect::>() - .join(","); + let features = features.join(","); let features = CString::new(features).unwrap(); let is_pie_binary = !find_features && is_pie_binary(sess); let trap_unreachable = sess.target.target.options.trap_unreachable; diff --git a/src/librustc_codegen_llvm/llvm_util.rs b/src/librustc_codegen_llvm/llvm_util.rs index 9fcc33d82cfa4..4f172c9f292fa 100644 --- a/src/librustc_codegen_llvm/llvm_util.rs +++ b/src/librustc_codegen_llvm/llvm_util.rs @@ -173,6 +173,7 @@ const MIPS_WHITELIST: &[(&str, Option<&str>)] = &[ const WASM_WHITELIST: &[(&str, Option<&str>)] = &[ ("simd128", Some("wasm_target_feature")), + ("atomics", Some("wasm_target_feature")), ]; /// When rustdoc is running, provide a list of all known features so that all their respective diff --git a/src/librustc_target/spec/wasm32_unknown_unknown.rs b/src/librustc_target/spec/wasm32_unknown_unknown.rs index 6c368e09003a3..c0455ceb8390c 100644 --- a/src/librustc_target/spec/wasm32_unknown_unknown.rs +++ b/src/librustc_target/spec/wasm32_unknown_unknown.rs @@ -36,8 +36,7 @@ pub fn target() -> Result { dll_suffix: ".wasm".to_string(), linker_is_gnu: false, - // A bit of a lie, but "eh" - max_atomic_width: Some(32), + max_atomic_width: Some(64), // Unwinding doesn't work right now, so the whole target unconditionally // defaults to panic=abort. Note that this is guaranteed to change in