diff --git a/src/librustc_codegen_llvm/abi.rs b/src/librustc_codegen_llvm/abi.rs index c8e8d0dc84ef0..7b93d3e795ed8 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 9c0f945326d14..9ee4582fabf7b 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 c0455ceb8390c..46353068bd045 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 {