about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbjorn3 <17426603+bjorn3@users.noreply.github.com>2023-02-17 10:41:31 +0000
committerbjorn3 <17426603+bjorn3@users.noreply.github.com>2023-02-17 18:20:34 +0000
commitc6a0d3716b3ffa5be96c161bb4d82ea007463021 (patch)
tree5717c64c34fd3c3069bfe47f1d63a5336ede9ac6
parentede7cde065d94fa53127c70c7db7f86c58eb749f (diff)
downloadrust-c6a0d3716b3ffa5be96c161bb4d82ea007463021.tar.gz
rust-c6a0d3716b3ffa5be96c161bb4d82ea007463021.zip
Move windows i128 indirect return handling to lib_call
-rw-r--r--src/abi/mod.rs25
-rw-r--r--src/codegen_i128.rs39
2 files changed, 33 insertions, 31 deletions
diff --git a/src/abi/mod.rs b/src/abi/mod.rs
index 4f8ede9cfbc..f1c3ea61636 100644
--- a/src/abi/mod.rs
+++ b/src/abi/mod.rs
@@ -4,6 +4,8 @@ mod comments;
 mod pass_mode;
 mod returning;
 
+use std::borrow::Cow;
+
 use cranelift_module::ModuleError;
 use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
 use rustc_middle::ty::layout::FnAbiOf;
@@ -116,11 +118,11 @@ impl<'tcx> FunctionCx<'_, '_, 'tcx> {
         params: Vec<AbiParam>,
         returns: Vec<AbiParam>,
         args: &[Value],
-    ) -> &[Value] {
+    ) -> Cow<'_, [Value]> {
         if self.tcx.sess.target.is_like_windows
             && params.iter().any(|param| param.value_type == types::I128)
         {
-            let (params, args): (Vec<_>, Vec<_>) =
+            let (mut params, mut args): (Vec<_>, Vec<_>) =
                 params
                     .into_iter()
                     .zip(args)
@@ -136,7 +138,22 @@ impl<'tcx> FunctionCx<'_, '_, 'tcx> {
                         }
                     })
                     .unzip();
-            return self.lib_call(name, params, returns, &args);
+
+            let indirect_ret_val = returns.len() == 1 && returns[0].value_type == types::I128;
+
+            if indirect_ret_val {
+                params.insert(0, AbiParam::new(types::I128));
+                let ret_ptr =
+                    Pointer::stack_slot(self.bcx.create_sized_stack_slot(StackSlotData {
+                        kind: StackSlotKind::ExplicitSlot,
+                        size: 16,
+                    }));
+                args.insert(0, ret_ptr.get_addr(self));
+                self.lib_call(name, params, vec![], &args);
+                return Cow::Owned(vec![ret_ptr.load(self, types::I128, MemFlags::trusted())]);
+            } else {
+                return self.lib_call(name, params, returns, &args);
+            }
         }
 
         let sig = Signature { params, returns, call_conv: self.target_config.default_call_conv };
@@ -151,7 +168,7 @@ impl<'tcx> FunctionCx<'_, '_, 'tcx> {
         }
         let results = self.bcx.inst_results(call_inst);
         assert!(results.len() <= 2, "{}", results.len());
-        results
+        Cow::Borrowed(results)
     }
 }
 
diff --git a/src/codegen_i128.rs b/src/codegen_i128.rs
index c2a2ce8ad6a..6640f0f3587 100644
--- a/src/codegen_i128.rs
+++ b/src/codegen_i128.rs
@@ -29,32 +29,17 @@ pub(crate) fn maybe_codegen<'tcx>(
         BinOp::Add | BinOp::Sub if !checked => None,
         BinOp::Mul if !checked || is_signed => {
             if !checked {
-                let val_ty = if is_signed { fx.tcx.types.i128 } else { fx.tcx.types.u128 };
-                if fx.tcx.sess.target.is_like_windows {
-                    let ret_place = CPlace::new_stack_slot(fx, lhs.layout());
-                    let args =
-                        [ret_place.to_ptr().get_addr(fx), lhs.load_scalar(fx), rhs.load_scalar(fx)];
-                    fx.lib_call(
-                        "__multi3",
-                        vec![
-                            AbiParam::special(fx.pointer_type, ArgumentPurpose::StructReturn),
-                            AbiParam::new(types::I128),
-                            AbiParam::new(types::I128),
-                        ],
-                        vec![],
-                        &args,
-                    );
-                    Some(ret_place.to_cvalue(fx))
-                } else {
-                    let args: Vec<_> = vec![lhs.load_scalar(fx), rhs.load_scalar(fx)];
-                    let ret_val = fx.lib_call(
-                        "__multi3",
-                        vec![AbiParam::new(types::I128), AbiParam::new(types::I128)],
-                        vec![AbiParam::new(types::I128)],
-                        &args,
-                    )[0];
-                    Some(CValue::by_val(ret_val, fx.layout_of(val_ty)))
-                }
+                let args = [lhs.load_scalar(fx), rhs.load_scalar(fx)];
+                let ret_val = fx.lib_call(
+                    "__multi3",
+                    vec![AbiParam::new(types::I128), AbiParam::new(types::I128)],
+                    vec![AbiParam::new(types::I128)],
+                    &args,
+                )[0];
+                Some(CValue::by_val(
+                    ret_val,
+                    fx.layout_of(if is_signed { fx.tcx.types.i128 } else { fx.tcx.types.u128 }),
+                ))
             } else {
                 let out_ty = fx.tcx.mk_tup([lhs.layout().ty, fx.tcx.types.bool].iter());
                 let oflow = CPlace::new_stack_slot(fx, fx.layout_of(fx.tcx.types.i32));
@@ -120,7 +105,7 @@ pub(crate) fn maybe_codegen<'tcx>(
                 ret_place.to_ptr().store(fx, ret, MemFlags::trusted());
                 Some(ret_place.to_cvalue(fx))
             } else {
-                let args: Vec<_> = vec![lhs.load_scalar(fx), rhs.load_scalar(fx)];
+                let args = [lhs.load_scalar(fx), rhs.load_scalar(fx)];
                 let ret_val = fx.lib_call(
                     name,
                     vec![AbiParam::new(types::I128), AbiParam::new(types::I128)],