about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_target/src/abi/call/mod.rs1
-rw-r--r--compiler/rustc_ty_utils/src/abi.rs35
2 files changed, 30 insertions, 6 deletions
diff --git a/compiler/rustc_target/src/abi/call/mod.rs b/compiler/rustc_target/src/abi/call/mod.rs
index f7c860cf56b..e9730947389 100644
--- a/compiler/rustc_target/src/abi/call/mod.rs
+++ b/compiler/rustc_target/src/abi/call/mod.rs
@@ -382,6 +382,7 @@ impl HomogeneousAggregate {
 }
 
 impl<'a, Ty> TyAndLayout<'a, Ty> {
+    /// Returns `true` if this is an aggregate type (including a ScalarPair!)
     fn is_aggregate(&self) -> bool {
         match self.abi {
             Abi::Uninhabited | Abi::Scalar(_) | Abi::Vector { .. } => false,
diff --git a/compiler/rustc_ty_utils/src/abi.rs b/compiler/rustc_ty_utils/src/abi.rs
index ec2fb4888ea..9ad7a1f588e 100644
--- a/compiler/rustc_ty_utils/src/abi.rs
+++ b/compiler/rustc_ty_utils/src/abi.rs
@@ -327,10 +327,15 @@ fn adjust_for_rust_scalar<'tcx>(
 }
 
 /// Ensure that the ABI makes basic sense.
-fn fn_abi_sanity_check<'tcx>(cx: &LayoutCx<'tcx, TyCtxt<'tcx>>, fn_abi: &FnAbi<'tcx, Ty<'tcx>>) {
+fn fn_abi_sanity_check<'tcx>(
+    cx: &LayoutCx<'tcx, TyCtxt<'tcx>>,
+    fn_abi: &FnAbi<'tcx, Ty<'tcx>>,
+    spec_abi: SpecAbi,
+) {
     fn fn_arg_sanity_check<'tcx>(
         cx: &LayoutCx<'tcx, TyCtxt<'tcx>>,
         fn_abi: &FnAbi<'tcx, Ty<'tcx>>,
+        spec_abi: SpecAbi,
         arg: &ArgAbi<'tcx, Ty<'tcx>>,
     ) {
         match &arg.mode {
@@ -360,8 +365,8 @@ fn fn_abi_sanity_check<'tcx>(cx: &LayoutCx<'tcx, TyCtxt<'tcx>>, fn_abi: &FnAbi<'
                     // (See issue: https://github.com/rust-lang/rust/issues/117271)
                     assert!(
                         matches!(&*cx.tcx.sess.target.arch, "wasm32" | "wasm64")
-                            || fn_abi.conv == Conv::PtxKernel,
-                        "`PassMode::Direct` for aggregates only allowed on wasm and `extern \"ptx-kernel\"` fns\nProblematic type: {:#?}",
+                            || matches!(spec_abi, SpecAbi::PtxKernel | SpecAbi::Unadjusted),
+                        r#"`PassMode::Direct` for aggregates only allowed for "unadjusted" and "ptx-kernel" functions and on wasm\nProblematic type: {:#?}"#,
                         arg.layout,
                     );
                 }
@@ -391,9 +396,9 @@ fn fn_abi_sanity_check<'tcx>(cx: &LayoutCx<'tcx, TyCtxt<'tcx>>, fn_abi: &FnAbi<'
     }
 
     for arg in fn_abi.args.iter() {
-        fn_arg_sanity_check(cx, fn_abi, arg);
+        fn_arg_sanity_check(cx, fn_abi, spec_abi, arg);
     }
-    fn_arg_sanity_check(cx, fn_abi, &fn_abi.ret);
+    fn_arg_sanity_check(cx, fn_abi, spec_abi, &fn_abi.ret);
 }
 
 // FIXME(eddyb) perhaps group the signature/type-containing (or all of them?)
@@ -522,7 +527,7 @@ fn fn_abi_new_uncached<'tcx>(
     };
     fn_abi_adjust_for_abi(cx, &mut fn_abi, sig.abi, fn_def_id)?;
     debug!("fn_abi_new_uncached = {:?}", fn_abi);
-    fn_abi_sanity_check(cx, &fn_abi);
+    fn_abi_sanity_check(cx, &fn_abi, sig.abi);
     Ok(cx.tcx.arena.alloc(fn_abi))
 }
 
@@ -534,6 +539,24 @@ fn fn_abi_adjust_for_abi<'tcx>(
     fn_def_id: Option<DefId>,
 ) -> Result<(), &'tcx FnAbiError<'tcx>> {
     if abi == SpecAbi::Unadjusted {
+        // The "unadjusted" ABI passes aggregates in "direct" mode. That's fragile but needed for
+        // some LLVM intrinsics.
+        fn unadjust<'tcx>(arg: &mut ArgAbi<'tcx, Ty<'tcx>>) {
+            // This still uses `PassMode::Pair` for ScalarPair types. That's unlikely to be intended,
+            // but who knows what breaks if we change this now.
+            if matches!(arg.layout.abi, Abi::Aggregate { .. }) {
+                assert!(
+                    arg.layout.abi.is_sized(),
+                    "'unadjusted' ABI does not support unsized arguments"
+                );
+            }
+            arg.make_direct_deprecated();
+        }
+
+        unadjust(&mut fn_abi.ret);
+        for arg in fn_abi.args.iter_mut() {
+            unadjust(arg);
+        }
         return Ok(());
     }