From d8edcd516ad07b2f3c10522ce244aca397ff5235 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Thu, 5 Dec 2024 15:41:05 +0000 Subject: [PATCH] Handle abi adjusting in lib_call correctly for s390x --- src/abi/mod.rs | 44 +++++++++++++++++++++++++++++--------------- 1 file changed, 29 insertions(+), 15 deletions(-) diff --git a/src/abi/mod.rs b/src/abi/mod.rs index 92229bfaf..1c706694d 100644 --- a/src/abi/mod.rs +++ b/src/abi/mod.rs @@ -125,8 +125,9 @@ impl<'tcx> FunctionCx<'_, '_, 'tcx> { returns: Vec, 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,20 +141,33 @@ 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)) + } } fn lib_call_unadjusted( @@ -162,7 +176,7 @@ impl<'tcx> FunctionCx<'_, '_, 'tcx> { params: Vec, returns: Vec, 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 } }