about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorbjorn3 <bjorn3@users.noreply.github.com>2021-01-25 10:57:59 +0100
committerbjorn3 <bjorn3@users.noreply.github.com>2021-01-25 10:57:59 +0100
commit6170fc617ef61698705e3c3d8847ce72d92991ca (patch)
tree7d03d347e23b401dcb362185d104ec691ec61732 /src
parentd39b4411296585895b1111d14c1459ea3e9bf9be (diff)
downloadrust-6170fc617ef61698705e3c3d8847ce72d92991ca.tar.gz
rust-6170fc617ef61698705e3c3d8847ce72d92991ca.zip
Split abi adjustments out
Diffstat (limited to 'src')
-rw-r--r--src/abi/pass_mode.rs131
1 files changed, 74 insertions, 57 deletions
diff --git a/src/abi/pass_mode.rs b/src/abi/pass_mode.rs
index 957beab745b..2d2410f2d6c 100644
--- a/src/abi/pass_mode.rs
+++ b/src/abi/pass_mode.rs
@@ -80,69 +80,86 @@ impl PassMode {
 }
 
 pub(super) fn get_pass_mode<'tcx>(tcx: TyCtxt<'tcx>, layout: TyAndLayout<'tcx>) -> PassMode {
+    let mut arg_abi = ArgAbi::new(&tcx, layout, |_, _, _| ArgAttributes::new());
     if layout.is_zst() {
         // WARNING zst arguments must never be passed, as that will break CastKind::ClosureFnPointer
-        PassMode::NoPass
-    } else {
-        let arg_abi = ArgAbi::new(&tcx, layout, |_, _, _| ArgAttributes::new());
-        match arg_abi.mode {
-            RustcPassMode::Ignore => PassMode::NoPass,
-            RustcPassMode::Direct(_) => match &arg_abi.layout.abi {
-                Abi::Scalar(scalar) => PassMode::ByVal(scalar_to_clif_type(tcx, scalar.clone())),
-                // FIXME implement Vector Abi in a cg_llvm compatible way
-                Abi::Vector { .. } => {
-                    if let Some(vector_ty) = crate::intrinsics::clif_vector_type(tcx, arg_abi.layout) {
-                        PassMode::ByVal(vector_ty)
-                    } else {
-                        PassMode::ByRef {
-                            size: Some(arg_abi.layout.size),
-                        }
-                    }
-                }
-                _ => unreachable!("{:?}", arg_abi.layout.abi)
-            },
-            RustcPassMode::Pair(_, _) => match &arg_abi.layout.abi {
-                Abi::ScalarPair(a, b) => {
-                    let a = scalar_to_clif_type(tcx, a.clone());
-                    let b = scalar_to_clif_type(tcx, b.clone());
-                    if a == types::I128 && b == types::I128 {
-                        // Returning (i128, i128) by-val-pair would take 4 regs, while only 3 are
-                        // available on x86_64. Cranelift gets confused when too many return params
-                        // are used.
-                        PassMode::ByRef {
-                            size: Some(arg_abi.layout.size),
-                        }
-                    } else {
-                        PassMode::ByValPair(a, b)
-                    }
+        arg_abi.mode = RustcPassMode::Ignore;
+    }
+    match arg_abi.mode {
+        RustcPassMode::Ignore => {}
+        RustcPassMode::Direct(_) => match &arg_abi.layout.abi {
+            Abi::Scalar(_) => {},
+            // FIXME implement Vector Abi in a cg_llvm compatible way
+            Abi::Vector { .. } => {
+                if crate::intrinsics::clif_vector_type(tcx, arg_abi.layout).is_none() {
+                    arg_abi.mode = RustcPassMode::Indirect {
+                        attrs: ArgAttributes::new(),
+                        extra_attrs: None,
+                        on_stack: false,
+                    };
                 }
-                _ => unreachable!("{:?}", arg_abi.layout.abi)
-            },
-            RustcPassMode::Cast(_) | RustcPassMode::Indirect {
-                attrs: _,
-                extra_attrs: None,
-                on_stack: false,
-            } => PassMode::ByRef {
-                size: Some(arg_abi.layout.size),
-            },
-            RustcPassMode::Indirect {
-                attrs: _,
-                extra_attrs,
-                on_stack: true,
-            } => {
-                assert!(extra_attrs.is_none());
-                PassMode::ByRef {
-                    size: Some(arg_abi.layout.size)
+            }
+            _ => unreachable!("{:?}", arg_abi.layout.abi)
+        },
+        RustcPassMode::Pair(_, _) => match &arg_abi.layout.abi {
+            Abi::ScalarPair(a, b) => {
+                let a = scalar_to_clif_type(tcx, a.clone());
+                let b = scalar_to_clif_type(tcx, b.clone());
+                if a == types::I128 && b == types::I128 {
+                    arg_abi.mode = RustcPassMode::Indirect {
+                        attrs: ArgAttributes::new(),
+                        extra_attrs: None,
+                        on_stack: false,
+                    };
                 }
             }
-            RustcPassMode::Indirect {
-                attrs: _,
-                extra_attrs: Some(_),
-                on_stack: false,
-            } => PassMode::ByRef {
-                size: None,
-            },
+            _ => unreachable!("{:?}", arg_abi.layout.abi)
+        },
+        _ => {}
+    }
+    match arg_abi.mode {
+        RustcPassMode::Ignore => PassMode::NoPass,
+        RustcPassMode::Direct(_) => match &arg_abi.layout.abi {
+            Abi::Scalar(scalar) => PassMode::ByVal(scalar_to_clif_type(tcx, scalar.clone())),
+            // FIXME implement Vector Abi in a cg_llvm compatible way
+            Abi::Vector { .. } => {
+                let vector_ty = crate::intrinsics::clif_vector_type(tcx, arg_abi.layout).unwrap();
+                PassMode::ByVal(vector_ty)
+            }
+            _ => unreachable!("{:?}", arg_abi.layout.abi)
+        },
+        RustcPassMode::Pair(_, _) => match &arg_abi.layout.abi {
+            Abi::ScalarPair(a, b) => {
+                let a = scalar_to_clif_type(tcx, a.clone());
+                let b = scalar_to_clif_type(tcx, b.clone());
+                PassMode::ByValPair(a, b)
+            }
+            _ => unreachable!("{:?}", arg_abi.layout.abi)
+        },
+        RustcPassMode::Cast(_) | RustcPassMode::Indirect {
+            attrs: _,
+            extra_attrs: None,
+            on_stack: false,
+        } => PassMode::ByRef {
+            size: Some(arg_abi.layout.size),
+        },
+        RustcPassMode::Indirect {
+            attrs: _,
+            extra_attrs,
+            on_stack: true,
+        } => {
+            assert!(extra_attrs.is_none());
+            PassMode::ByRef {
+                size: Some(arg_abi.layout.size)
+            }
         }
+        RustcPassMode::Indirect {
+            attrs: _,
+            extra_attrs: Some(_),
+            on_stack: false,
+        } => PassMode::ByRef {
+            size: None,
+        },
     }
 }