From 9562b69b4f270a824b9f54203ed69427f8833fe9 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Fri, 12 Oct 2018 17:04:31 -0700 Subject: [PATCH] rustc: Allow targets to specify SIMD args are by-val The upcoming SIMD support in the wasm target is unique from the other platforms where it's either unconditionally available or not available, there's no halfway where a subsection of the program can use it but no other parts of the program can use it. In this world it's valid for wasm SIMD args to always be passed by value and there's no need to pass them by reference. This commit adds a new custom target specification option `simd_types_indirect` which defaults to `true`, but the wasm backend disables this and sets it to `false`. --- src/librustc_codegen_llvm/abi.rs | 5 ++++- src/librustc_target/spec/mod.rs | 9 +++++++++ src/librustc_target/spec/wasm32_unknown_unknown.rs | 6 ++++++ 3 files changed, 19 insertions(+), 1 deletion(-) diff --git a/src/librustc_codegen_llvm/abi.rs b/src/librustc_codegen_llvm/abi.rs index c8e8d0dc84e..7b93d3e795e 100644 --- a/src/librustc_codegen_llvm/abi.rs +++ b/src/librustc_codegen_llvm/abi.rs @@ -536,7 +536,10 @@ impl<'tcx> FnTypeExt<'tcx> for FnType<'tcx, Ty<'tcx>> { // Note that the platform intrinsic ABI is exempt here as // that's how we connect up to LLVM and it's unstable // anyway, we control all calls to it in libstd. - layout::Abi::Vector { .. } if abi != Abi::PlatformIntrinsic => { + layout::Abi::Vector { .. } + if abi != Abi::PlatformIntrinsic && + cx.sess().target.target.options.simd_types_indirect => + { arg.make_indirect(); return } diff --git a/src/librustc_target/spec/mod.rs b/src/librustc_target/spec/mod.rs index 9c0f945326d..9ee4582fabf 100644 --- a/src/librustc_target/spec/mod.rs +++ b/src/librustc_target/spec/mod.rs @@ -680,6 +680,12 @@ pub struct TargetOptions { /// typically because the platform needs to unwind for things like stack /// unwinders. pub requires_uwtable: bool, + + /// Whether or not SIMD types are passed by reference in the Rust ABI, + /// typically required if a target can be compiled with a mixed set of + /// target features. This is `true` by default, and `false` for targets like + /// wasm32 where the whole program either has simd or not. + pub simd_types_indirect: bool, } impl Default for TargetOptions { @@ -760,6 +766,7 @@ impl Default for TargetOptions { embed_bitcode: false, emit_debug_gdb_scripts: true, requires_uwtable: false, + simd_types_indirect: true, } } } @@ -1041,6 +1048,7 @@ impl Target { key!(embed_bitcode, bool); key!(emit_debug_gdb_scripts, bool); key!(requires_uwtable, bool); + key!(simd_types_indirect, bool); if let Some(array) = obj.find("abi-blacklist").and_then(Json::as_array) { for name in array.iter().filter_map(|abi| abi.as_string()) { @@ -1250,6 +1258,7 @@ impl ToJson for Target { target_option_val!(embed_bitcode); target_option_val!(emit_debug_gdb_scripts); target_option_val!(requires_uwtable); + target_option_val!(simd_types_indirect); if default.abi_blacklist != self.options.abi_blacklist { d.insert("abi-blacklist".to_string(), self.options.abi_blacklist.iter() diff --git a/src/librustc_target/spec/wasm32_unknown_unknown.rs b/src/librustc_target/spec/wasm32_unknown_unknown.rs index c0455ceb839..46353068bd0 100644 --- a/src/librustc_target/spec/wasm32_unknown_unknown.rs +++ b/src/librustc_target/spec/wasm32_unknown_unknown.rs @@ -54,6 +54,12 @@ pub fn target() -> Result { linker: Some("rust-lld".to_owned()), lld_flavor: LldFlavor::Wasm, + // No need for indirection here, simd types can always be passed by + // value as the whole module either has simd or not, which is different + // from x86 (for example) where programs can have functions that don't + // enable simd features. + simd_types_indirect: false, + .. Default::default() }; Ok(Target {