@@ -32,18 +32,56 @@ pub(crate) fn maybe_codegen<'tcx>(
32
32
BinOp :: Add | BinOp :: Sub if !checked => None ,
33
33
BinOp :: Mul if !checked => {
34
34
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
+ }
36
57
}
37
58
BinOp :: Add | BinOp :: Sub | BinOp :: Mul => {
38
59
assert ! ( checked) ;
39
60
let out_ty = fx. tcx . mk_tup ( [ lhs. layout ( ) . ty , fx. tcx . types . bool ] . iter ( ) ) ;
40
61
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
+ } ;
47
85
let name = match ( bin_op, is_signed) {
48
86
( BinOp :: Add , false ) => "__rust_u128_addo" ,
49
87
( BinOp :: Add , true ) => "__rust_i128_addo" ,
@@ -57,20 +95,33 @@ pub(crate) fn maybe_codegen<'tcx>(
57
95
Some ( out_place. to_cvalue ( fx) )
58
96
}
59
97
BinOp :: Offset => unreachable ! ( "offset should only be used on pointers, not 128bit ints" ) ,
60
- BinOp :: Div => {
98
+ BinOp :: Div | BinOp :: Rem => {
61
99
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) )
72
123
} else {
73
- Some ( fx. easy_call ( "__umodti3" , & [ lhs, rhs] , fx . tcx . types . u128 ) )
124
+ Some ( fx. easy_call ( name , & [ lhs, rhs] , lhs . layout ( ) . ty ) )
74
125
}
75
126
}
76
127
BinOp :: Lt | BinOp :: Le | BinOp :: Eq | BinOp :: Ge | BinOp :: Gt | BinOp :: Ne => {
0 commit comments