diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index ef467ed651454..041c8c9281a97 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -2860,7 +2860,7 @@ where return; } - if let Err(msg) = self.adjust_for_cabi(cx, abi) { + if let Err(msg) = self.adjust_for_cabi(cx, &cx.tcx().sess.target_features, abi) { cx.tcx().sess.fatal(&msg); } } diff --git a/compiler/rustc_target/src/abi/call/mod.rs b/compiler/rustc_target/src/abi/call/mod.rs index 2cbd52bf3e9a7..fa6da9f85b9bf 100644 --- a/compiler/rustc_target/src/abi/call/mod.rs +++ b/compiler/rustc_target/src/abi/call/mod.rs @@ -53,6 +53,8 @@ pub enum PassMode { // Hack to disable non_upper_case_globals only for the bitflags! and not for the rest // of this module pub use attr_impl::ArgAttribute; +use rustc_data_structures::stable_set::FxHashSet; +use rustc_span::Symbol; #[allow(non_upper_case_globals)] #[allow(unused)] @@ -592,7 +594,12 @@ pub struct FnAbi<'a, Ty> { } impl<'a, Ty> FnAbi<'a, Ty> { - pub fn adjust_for_cabi(&mut self, cx: &C, abi: spec::abi::Abi) -> Result<(), String> + pub fn adjust_for_cabi( + &mut self, + cx: &C, + target_features: &FxHashSet, + abi: spec::abi::Abi, + ) -> Result<(), String> where Ty: TyAndLayoutMethods<'a, C> + Copy, C: LayoutOf> + HasDataLayout + HasTargetSpec, @@ -633,7 +640,7 @@ impl<'a, Ty> FnAbi<'a, Ty> { "riscv32" | "riscv64" => riscv::compute_abi_info(cx, self), "wasm32" => match cx.target_spec().os.as_str() { "emscripten" | "wasi" => wasm32::compute_abi_info(cx, self), - _ => wasm32_bindgen_compat::compute_abi_info(self), + _ => wasm32_bindgen_compat::compute_abi_info(cx, target_features, self), }, "asmjs" => wasm32::compute_abi_info(cx, self), a => return Err(format!("unrecognized arch \"{}\" in target specification", a)), diff --git a/compiler/rustc_target/src/abi/call/wasm32_bindgen_compat.rs b/compiler/rustc_target/src/abi/call/wasm32_bindgen_compat.rs index 59571fd9d4821..d73240a614e91 100644 --- a/compiler/rustc_target/src/abi/call/wasm32_bindgen_compat.rs +++ b/compiler/rustc_target/src/abi/call/wasm32_bindgen_compat.rs @@ -5,25 +5,58 @@ // can be fixed to work with the correct ABI. See #63649 for further // discussion. -use crate::abi::call::{ArgAbi, FnAbi}; +use rustc_data_structures::stable_set::FxHashSet; +use rustc_span::Symbol; -fn classify_ret(ret: &mut ArgAbi<'_, Ty>) { +use crate::abi::call::{ArgAbi, FnAbi, Uniform}; +use crate::abi::{HasDataLayout, LayoutOf, TyAndLayout, TyAndLayoutMethods}; + +fn classify_ret<'a, Ty, C>(cx: &C, target_features: &FxHashSet, ret: &mut ArgAbi<'a, Ty>) +where + Ty: TyAndLayoutMethods<'a, C> + Copy, + C: LayoutOf> + HasDataLayout, +{ + if ret.layout.is_aggregate() { + if let Some(unit) = ret.layout.homogeneous_aggregate(cx).ok().and_then(|ha| ha.unit()) { + let size = ret.layout.size; + if unit.size == size || target_features.contains(&Symbol::intern("multivalue")) { + ret.cast_to(Uniform { unit, total: size }); + } + } + } ret.extend_integer_width_to(32); } -fn classify_arg(arg: &mut ArgAbi<'_, Ty>) { +fn classify_arg<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'a, Ty>) +where + Ty: TyAndLayoutMethods<'a, C> + Copy, + C: LayoutOf> + HasDataLayout, +{ + if arg.layout.is_aggregate() { + if let Some(unit) = arg.layout.homogeneous_aggregate(cx).ok().and_then(|ha| ha.unit()) { + let size = arg.layout.size; + arg.cast_to(Uniform { unit, total: size }); + } + } arg.extend_integer_width_to(32); } -pub fn compute_abi_info(fn_abi: &mut FnAbi<'_, Ty>) { +pub fn compute_abi_info<'a, Ty, C>( + cx: &C, + target_features: &FxHashSet, + fn_abi: &mut FnAbi<'a, Ty>, +) where + Ty: TyAndLayoutMethods<'a, C> + Copy, + C: LayoutOf> + HasDataLayout, +{ if !fn_abi.ret.is_ignore() { - classify_ret(&mut fn_abi.ret); + classify_ret(cx, target_features, &mut fn_abi.ret); } for arg in &mut fn_abi.args { if arg.is_ignore() { continue; } - classify_arg(arg); + classify_arg(cx, arg); } }