@@ -141,16 +141,19 @@ impl<'tcx> FunctionCx<'_, '_, 'tcx> {
141141 ) -> Cow < ' _ , [ Value ] > {
142142 // FIXME any way to reuse the abi adjustment code in rustc_target?
143143
144- // Pass i128 arguments by-ref on Windows.
144+ // Pass and return f128 indirectly on s390x and x86_64 Windows.
145+ let indirect_f128 = self . tcx . sess . target . arch == Arch :: S390x
146+ || ( self . tcx . sess . target . is_like_windows && self . tcx . sess . target . arch == Arch :: X86_64 ) ;
147+
148+ // Pass i128 arguments by-ref on s390x and Windows.
145149 let ( params, args) : ( Vec < _ > , Cow < ' _ , [ _ ] > ) =
146150 if self . tcx . sess . target . is_like_windows || self . tcx . sess . target . arch == Arch :: S390x {
147151 let ( params, args) : ( Vec < _ > , Vec < _ > ) = params
148152 . into_iter ( )
149153 . zip ( args)
150154 . map ( |( param, & arg) | {
151155 if param. value_type == types:: I128
152- || ( self . tcx . sess . target . arch == Arch :: S390x
153- && param. value_type == types:: F128 )
156+ || ( indirect_f128 && param. value_type == types:: F128 )
154157 {
155158 let arg_ptr = self . create_stack_slot ( 16 , 16 ) ;
156159 arg_ptr. store ( self , arg, MemFlagsData :: trusted ( ) ) ;
@@ -166,19 +169,20 @@ impl<'tcx> FunctionCx<'_, '_, 'tcx> {
166169 ( params, args. into ( ) )
167170 } ;
168171
169- if self . tcx . sess . target . is_like_windows
170- && matches ! ( * returns, [ AbiParam { value_type: types:: I128 , .. } ] )
171- {
172+ let ret_single_i128 = matches ! ( * returns , [ AbiParam { value_type : types :: I128 , .. } ] ) ;
173+ let ret_single_f128 = matches ! ( * returns, [ AbiParam { value_type: types:: F128 , .. } ] ) ;
174+ if ret_single_i128 && self . tcx . sess . target . is_like_windows {
172175 // Return i128 using the vector ABI on Windows
173176 returns[ 0 ] . value_type = types:: I64X2 ;
174177
175178 let ret = self . lib_call_unadjusted ( name, params, returns, & args) [ 0 ] ;
176179
177180 Cow :: Owned ( vec ! [ codegen_bitcast( self , types:: I128 , ret) ] )
178- } else if self . tcx . sess . target . arch == Arch :: S390x
179- && matches ! ( * returns , [ AbiParam { value_type : types :: I128 | types :: F128 , .. } ] )
181+ } else if ( ret_single_i128 && self . tcx . sess . target . arch == Arch :: S390x )
182+ || ( ret_single_f128 && indirect_f128 )
180183 {
181- // Return i128 and f128 using a return area pointer on s390x.
184+ // Return x86_64 Windows f128 and s390x i128 indirectly (sret in LLVM terminology).
185+ let ret_ty = returns[ 0 ] . value_type ;
182186 let mut params = params;
183187 let mut args = args. to_vec ( ) ;
184188
@@ -188,7 +192,7 @@ impl<'tcx> FunctionCx<'_, '_, 'tcx> {
188192
189193 self . lib_call_unadjusted ( name, params, vec ! [ ] , & args) ;
190194
191- Cow :: Owned ( vec ! [ ret_ptr. load( self , types :: I128 , MemFlagsData :: trusted( ) ) ] )
195+ Cow :: Owned ( vec ! [ ret_ptr. load( self , ret_ty , MemFlagsData :: trusted( ) ) ] )
192196 } else {
193197 Cow :: Borrowed ( self . lib_call_unadjusted ( name, params, returns, & args) )
194198 }
0 commit comments