about summary refs log tree commit diff
path: root/compiler
diff options
context:
space:
mode:
authorbjorn3 <bjorn3@users.noreply.github.com>2021-01-26 11:31:37 +0100
committerbjorn3 <bjorn3@users.noreply.github.com>2021-01-26 11:31:37 +0100
commit903c553f4a2fc8344edac0da565e6c1a7fad4b39 (patch)
treeae9370ba8e0b96e9697a8f5aa202122e5e488e45 /compiler
parentecbc6610302c4269f3e3e903022d8a84d5537e59 (diff)
downloadrust-903c553f4a2fc8344edac0da565e6c1a7fad4b39.tar.gz
rust-903c553f4a2fc8344edac0da565e6c1a7fad4b39.zip
Wasm-bindgen abi compat using cast_to
Diffstat (limited to 'compiler')
-rw-r--r--compiler/rustc_middle/src/ty/layout.rs2
-rw-r--r--compiler/rustc_target/src/abi/call/mod.rs11
-rw-r--r--compiler/rustc_target/src/abi/call/wasm32_bindgen_compat.rs45
3 files changed, 49 insertions, 9 deletions
diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs
index ef467ed6514..041c8c9281a 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 2cbd52bf3e9..fa6da9f85b9 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<C>(&mut self, cx: &C, abi: spec::abi::Abi) -> Result<(), String>
+    pub fn adjust_for_cabi<C>(
+        &mut self,
+        cx: &C,
+        target_features: &FxHashSet<Symbol>,
+        abi: spec::abi::Abi,
+    ) -> Result<(), String>
     where
         Ty: TyAndLayoutMethods<'a, C> + Copy,
         C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>> + 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 59571fd9d48..d73240a614e 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<Ty>(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<Symbol>, ret: &mut ArgAbi<'a, Ty>)
+where
+    Ty: TyAndLayoutMethods<'a, C> + Copy,
+    C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>> + 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<Ty>(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<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>> + 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<Ty>(fn_abi: &mut FnAbi<'_, Ty>) {
+pub fn compute_abi_info<'a, Ty, C>(
+    cx: &C,
+    target_features: &FxHashSet<Symbol>,
+    fn_abi: &mut FnAbi<'a, Ty>,
+) where
+    Ty: TyAndLayoutMethods<'a, C> + Copy,
+    C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>> + 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);
     }
 }