@@ -32,18 +32,56 @@ pub(crate) fn maybe_codegen<'tcx>(
3232 BinOp :: Add | BinOp :: Sub if !checked => None ,
3333 BinOp :: Mul if !checked => {
3434 let val_ty = if is_signed { fx. tcx . types . i128 } else { fx. tcx . types . u128 } ;
35- Some ( fx. easy_call ( "__multi3" , & [ lhs, rhs] , val_ty) )
35+ if fx. tcx . sess . target . is_like_windows {
36+ let ret_place = CPlace :: new_stack_slot ( fx, lhs. layout ( ) ) ;
37+ let ( lhs_ptr, lhs_extra) = lhs. force_stack ( fx) ;
38+ let ( rhs_ptr, rhs_extra) = rhs. force_stack ( fx) ;
39+ assert ! ( lhs_extra. is_none( ) ) ;
40+ assert ! ( rhs_extra. is_none( ) ) ;
41+ let args =
42+ [ ret_place. to_ptr ( ) . get_addr ( fx) , lhs_ptr. get_addr ( fx) , rhs_ptr. get_addr ( fx) ] ;
43+ fx. lib_call (
44+ "__multi3" ,
45+ vec ! [
46+ AbiParam :: special( pointer_ty( fx. tcx) , ArgumentPurpose :: StructReturn ) ,
47+ AbiParam :: new( pointer_ty( fx. tcx) ) ,
48+ AbiParam :: new( pointer_ty( fx. tcx) ) ,
49+ ] ,
50+ vec ! [ ] ,
51+ & args,
52+ ) ;
53+ Some ( ret_place. to_cvalue ( fx) )
54+ } else {
55+ Some ( fx. easy_call ( "__multi3" , & [ lhs, rhs] , val_ty) )
56+ }
3657 }
3758 BinOp :: Add | BinOp :: Sub | BinOp :: Mul => {
3859 assert ! ( checked) ;
3960 let out_ty = fx. tcx . mk_tup ( [ lhs. layout ( ) . ty , fx. tcx . types . bool ] . iter ( ) ) ;
4061 let out_place = CPlace :: new_stack_slot ( fx, fx. layout_of ( out_ty) ) ;
41- let param_types = vec ! [
42- AbiParam :: special( pointer_ty( fx. tcx) , ArgumentPurpose :: StructReturn ) ,
43- AbiParam :: new( types:: I128 ) ,
44- AbiParam :: new( types:: I128 ) ,
45- ] ;
46- let args = [ out_place. to_ptr ( ) . get_addr ( fx) , lhs. load_scalar ( fx) , rhs. load_scalar ( fx) ] ;
62+ let ( param_types, args) = if fx. tcx . sess . target . is_like_windows {
63+ let ( lhs_ptr, lhs_extra) = lhs. force_stack ( fx) ;
64+ let ( rhs_ptr, rhs_extra) = rhs. force_stack ( fx) ;
65+ assert ! ( lhs_extra. is_none( ) ) ;
66+ assert ! ( rhs_extra. is_none( ) ) ;
67+ (
68+ vec ! [
69+ AbiParam :: special( pointer_ty( fx. tcx) , ArgumentPurpose :: StructReturn ) ,
70+ AbiParam :: new( pointer_ty( fx. tcx) ) ,
71+ AbiParam :: new( pointer_ty( fx. tcx) ) ,
72+ ] ,
73+ [ out_place. to_ptr ( ) . get_addr ( fx) , lhs_ptr. get_addr ( fx) , rhs_ptr. get_addr ( fx) ] ,
74+ )
75+ } else {
76+ (
77+ vec ! [
78+ AbiParam :: special( pointer_ty( fx. tcx) , ArgumentPurpose :: StructReturn ) ,
79+ AbiParam :: new( types:: I128 ) ,
80+ AbiParam :: new( types:: I128 ) ,
81+ ] ,
82+ [ out_place. to_ptr ( ) . get_addr ( fx) , lhs. load_scalar ( fx) , rhs. load_scalar ( fx) ] ,
83+ )
84+ } ;
4785 let name = match ( bin_op, is_signed) {
4886 ( BinOp :: Add , false ) => "__rust_u128_addo" ,
4987 ( BinOp :: Add , true ) => "__rust_i128_addo" ,
@@ -57,20 +95,33 @@ pub(crate) fn maybe_codegen<'tcx>(
5795 Some ( out_place. to_cvalue ( fx) )
5896 }
5997 BinOp :: Offset => unreachable ! ( "offset should only be used on pointers, not 128bit ints" ) ,
60- BinOp :: Div => {
98+ BinOp :: Div | BinOp :: Rem => {
6199 assert ! ( !checked) ;
62- if is_signed {
63- Some ( fx. easy_call ( "__divti3" , & [ lhs, rhs] , fx. tcx . types . i128 ) )
64- } else {
65- Some ( fx. easy_call ( "__udivti3" , & [ lhs, rhs] , fx. tcx . types . u128 ) )
66- }
67- }
68- BinOp :: Rem => {
69- assert ! ( !checked) ;
70- if is_signed {
71- Some ( fx. easy_call ( "__modti3" , & [ lhs, rhs] , fx. tcx . types . i128 ) )
100+ let name = match ( bin_op, is_signed) {
101+ ( BinOp :: Div , false ) => "__udivti3" ,
102+ ( BinOp :: Div , true ) => "__divti3" ,
103+ ( BinOp :: Rem , false ) => "__umodti3" ,
104+ ( BinOp :: Rem , true ) => "__modti3" ,
105+ _ => unreachable ! ( ) ,
106+ } ;
107+ if fx. tcx . sess . target . is_like_windows {
108+ let ( lhs_ptr, lhs_extra) = lhs. force_stack ( fx) ;
109+ let ( rhs_ptr, rhs_extra) = rhs. force_stack ( fx) ;
110+ assert ! ( lhs_extra. is_none( ) ) ;
111+ assert ! ( rhs_extra. is_none( ) ) ;
112+ let args = [ lhs_ptr. get_addr ( fx) , rhs_ptr. get_addr ( fx) ] ;
113+ let ret = fx. lib_call (
114+ name,
115+ vec ! [ AbiParam :: new( pointer_ty( fx. tcx) ) , AbiParam :: new( pointer_ty( fx. tcx) ) ] ,
116+ vec ! [ AbiParam :: new( types:: I64X2 ) ] ,
117+ & args,
118+ ) [ 0 ] ;
119+ // FIXME use bitcast instead of store to get from i64x2 to i128
120+ let ret_place = CPlace :: new_stack_slot ( fx, lhs. layout ( ) ) ;
121+ ret_place. to_ptr ( ) . store ( fx, ret, MemFlags :: trusted ( ) ) ;
122+ Some ( ret_place. to_cvalue ( fx) )
72123 } else {
73- Some ( fx. easy_call ( "__umodti3" , & [ lhs, rhs] , fx . tcx . types . u128 ) )
124+ Some ( fx. easy_call ( name , & [ lhs, rhs] , lhs . layout ( ) . ty ) )
74125 }
75126 }
76127 BinOp :: Lt | BinOp :: Le | BinOp :: Eq | BinOp :: Ge | BinOp :: Gt | BinOp :: Ne => {
0 commit comments