diff options
| author | bjorn3 <17426603+bjorn3@users.noreply.github.com> | 2024-12-05 15:41:05 +0000 |
|---|---|---|
| committer | bjorn3 <17426603+bjorn3@users.noreply.github.com> | 2024-12-05 15:41:05 +0000 |
| commit | d8edcd516ad07b2f3c10522ce244aca397ff5235 (patch) | |
| tree | 347ea0cb72e836f9a583d3f7f68140c9e53c1977 | |
| parent | 9fd3b18b0bb4c8635509113a875ad574fbd48a96 (diff) | |
| download | rust-d8edcd516ad07b2f3c10522ce244aca397ff5235.tar.gz rust-d8edcd516ad07b2f3c10522ce244aca397ff5235.zip | |
Handle abi adjusting in lib_call correctly for s390x
| -rw-r--r-- | src/abi/mod.rs | 44 |
1 files changed, 29 insertions, 15 deletions
diff --git a/src/abi/mod.rs b/src/abi/mod.rs index 92229bfaf94..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,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<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 } } |
