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, returns: Vec, 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)],