about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/abi/mod.rs46
-rw-r--r--src/codegen_i128.rs27
2 files changed, 36 insertions, 37 deletions
diff --git a/src/abi/mod.rs b/src/abi/mod.rs
index cab5b35c18d..1c706694dcd 100644
--- a/src/abi/mod.rs
+++ b/src/abi/mod.rs
@@ -125,8 +125,9 @@ impl<'tcx> FunctionCx<'_, '_, 'tcx> {
         returns: Vec<AbiParam>,
         args: &[Value],
     ) -> Cow<'_, [Value]> {
-        if self.tcx.sess.target.is_like_windows {
-            let (mut params, mut args): (Vec<_>, Vec<_>) = params
+        // Pass i128 arguments by-ref on Windows.
+        let (params, args): (Vec<_>, Cow<'_, [_]>) = if self.tcx.sess.target.is_like_windows {
+            let (params, args): (Vec<_>, Vec<_>) = params
                 .into_iter()
                 .zip(args)
                 .map(|(param, &arg)| {
@@ -140,29 +141,42 @@ impl<'tcx> FunctionCx<'_, '_, 'tcx> {
                 })
                 .unzip();
 
-            let indirect_ret_val = returns.len() == 1 && returns[0].value_type == types::I128;
+            (params, args.into())
+        } else {
+            (params, args.into())
+        };
 
-            if indirect_ret_val {
-                params.insert(0, AbiParam::new(self.pointer_type));
-                let ret_ptr = self.create_stack_slot(16, 16);
-                args.insert(0, ret_ptr.get_addr(self));
-                self.lib_call_unadjusted(name, params, vec![], &args);
-                return Cow::Owned(vec![ret_ptr.load(self, types::I128, MemFlags::trusted())]);
+        // Return i128 using a return area pointer on Windows and s390x.
+        let adjust_ret_param =
+            if self.tcx.sess.target.is_like_windows || self.tcx.sess.target.arch == "s390x" {
+                returns.len() == 1 && returns[0].value_type == types::I128
             } else {
-                return self.lib_call_unadjusted(name, params, returns, &args);
-            }
-        }
+                false
+            };
+
+        if adjust_ret_param {
+            let mut params = params;
+            let mut args = args.to_vec();
 
-        self.lib_call_unadjusted(name, params, returns, args)
+            params.insert(0, AbiParam::new(self.pointer_type));
+            let ret_ptr = self.create_stack_slot(16, 16);
+            args.insert(0, ret_ptr.get_addr(self));
+
+            self.lib_call_unadjusted(name, params, vec![], &args);
+
+            Cow::Owned(vec![ret_ptr.load(self, types::I128, MemFlags::trusted())])
+        } else {
+            Cow::Borrowed(self.lib_call_unadjusted(name, params, returns, &args))
+        }
     }
 
-    pub(crate) fn lib_call_unadjusted(
+    fn lib_call_unadjusted(
         &mut self,
         name: &str,
         params: Vec<AbiParam>,
         returns: Vec<AbiParam>,
         args: &[Value],
-    ) -> Cow<'_, [Value]> {
+    ) -> &[Value] {
         let sig = Signature { params, returns, call_conv: self.target_config.default_call_conv };
         let func_id = self.module.declare_function(name, Linkage::Import, &sig).unwrap();
         let func_ref = self.module.declare_func_in_func(func_id, &mut self.bcx.func);
@@ -175,7 +189,7 @@ impl<'tcx> FunctionCx<'_, '_, 'tcx> {
         }
         let results = self.bcx.inst_results(call_inst);
         assert!(results.len() <= 2, "{}", results.len());
-        Cow::Borrowed(results)
+        results
     }
 }
 
diff --git a/src/codegen_i128.rs b/src/codegen_i128.rs
index b6a4769e031..734574338d0 100644
--- a/src/codegen_i128.rs
+++ b/src/codegen_i128.rs
@@ -81,26 +81,6 @@ pub(crate) fn maybe_codegen_checked<'tcx>(
     match bin_op {
         BinOp::BitAnd | BinOp::BitOr | BinOp::BitXor => unreachable!(),
         BinOp::Add | BinOp::Sub => None,
-        BinOp::Mul if is_signed => {
-            let out_ty = Ty::new_tup(fx.tcx, &[lhs.layout().ty, fx.tcx.types.bool]);
-            let oflow = CPlace::new_stack_slot(fx, fx.layout_of(fx.tcx.types.i32));
-            let lhs = lhs.load_scalar(fx);
-            let rhs = rhs.load_scalar(fx);
-            let oflow_ptr = oflow.to_ptr().get_addr(fx);
-            let res = fx.lib_call_unadjusted(
-                "__muloti4",
-                vec![
-                    AbiParam::new(types::I128),
-                    AbiParam::new(types::I128),
-                    AbiParam::new(fx.pointer_type),
-                ],
-                vec![AbiParam::new(types::I128)],
-                &[lhs, rhs, oflow_ptr],
-            )[0];
-            let oflow = oflow.to_cvalue(fx).load_scalar(fx);
-            let oflow = fx.bcx.ins().ireduce(types::I8, oflow);
-            Some(CValue::by_val_pair(res, oflow, fx.layout_of(out_ty)))
-        }
         BinOp::Mul => {
             let out_ty = Ty::new_tup(fx.tcx, &[lhs.layout().ty, fx.tcx.types.bool]);
             let out_place = CPlace::new_stack_slot(fx, fx.layout_of(out_ty));
@@ -110,7 +90,12 @@ pub(crate) fn maybe_codegen_checked<'tcx>(
                 AbiParam::new(types::I128),
             ];
             let args = [out_place.to_ptr().get_addr(fx), lhs.load_scalar(fx), rhs.load_scalar(fx)];
-            fx.lib_call("__rust_u128_mulo", param_types, vec![], &args);
+            fx.lib_call(
+                if is_signed { "__rust_i128_mulo" } else { "__rust_u128_mulo" },
+                param_types,
+                vec![],
+                &args,
+            );
             Some(out_place.to_cvalue(fx))
         }
         BinOp::AddUnchecked | BinOp::SubUnchecked | BinOp::MulUnchecked => unreachable!(),