11//! Replaces 128-bit operators with lang item calls where necessary
22
3+ use cranelift_codegen:: ir:: ArgumentPurpose ;
4+
35use crate :: prelude:: * ;
46
57pub ( crate ) fn maybe_codegen < ' tcx > (
@@ -24,41 +26,41 @@ pub(crate) fn maybe_codegen<'tcx>(
2426 None
2527 }
2628 BinOp :: Add | BinOp :: Sub if !checked => None ,
27- BinOp :: Add => {
28- let out_ty = fx. tcx . mk_tup ( [ lhs. layout ( ) . ty , fx. tcx . types . bool ] . iter ( ) ) ;
29- return Some ( if is_signed {
30- fx. easy_call ( "__rust_i128_addo" , & [ lhs, rhs] , out_ty)
29+ BinOp :: Mul if !checked => {
30+ let val_ty = if is_signed {
31+ fx. tcx . types . i128
3132 } else {
32- fx. easy_call ( "__rust_u128_addo" , & [ lhs, rhs] , out_ty)
33- } ) ;
33+ fx. tcx . types . u128
34+ } ;
35+ Some ( fx. easy_call ( "__multi3" , & [ lhs, rhs] , val_ty) )
3436 }
35- BinOp :: Sub => {
37+ BinOp :: Add | BinOp :: Sub | BinOp :: Mul => {
38+ assert ! ( checked) ;
3639 let out_ty = fx. tcx . mk_tup ( [ lhs. layout ( ) . ty , fx. tcx . types . bool ] . iter ( ) ) ;
37- return Some ( if is_signed {
38- fx. easy_call ( "__rust_i128_subo" , & [ lhs, rhs] , out_ty)
39- } else {
40- fx. easy_call ( "__rust_u128_subo" , & [ lhs, rhs] , out_ty)
41- } ) ;
42- }
43- BinOp :: Offset => unreachable ! ( "offset should only be used on pointers, not 128bit ints" ) ,
44- BinOp :: Mul => {
45- let res = if checked {
46- let out_ty = fx. tcx . mk_tup ( [ lhs. layout ( ) . ty , fx. tcx . types . bool ] . iter ( ) ) ;
47- if is_signed {
48- fx. easy_call ( "__rust_i128_mulo" , & [ lhs, rhs] , out_ty)
49- } else {
50- fx. easy_call ( "__rust_u128_mulo" , & [ lhs, rhs] , out_ty)
51- }
52- } else {
53- let val_ty = if is_signed {
54- fx. tcx . types . i128
55- } else {
56- fx. tcx . types . u128
57- } ;
58- fx. easy_call ( "__multi3" , & [ lhs, rhs] , val_ty)
40+ 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 = [
47+ out_place. to_ptr ( ) . get_addr ( fx) ,
48+ lhs. load_scalar ( fx) ,
49+ rhs. load_scalar ( fx) ,
50+ ] ;
51+ let name = match ( bin_op, is_signed) {
52+ ( BinOp :: Add , false ) => "__rust_u128_addo" ,
53+ ( BinOp :: Add , true ) => "__rust_i128_addo" ,
54+ ( BinOp :: Sub , false ) => "__rust_u128_subo" ,
55+ ( BinOp :: Sub , true ) => "__rust_i128_subo" ,
56+ ( BinOp :: Mul , false ) => "__rust_u128_mulo" ,
57+ ( BinOp :: Mul , true ) => "__rust_i128_mulo" ,
58+ _ => unreachable ! ( ) ,
5959 } ;
60- Some ( res)
60+ fx. lib_call ( name, param_types, vec ! [ ] , & args) ;
61+ Some ( out_place. to_cvalue ( fx) )
6162 }
63+ BinOp :: Offset => unreachable ! ( "offset should only be used on pointers, not 128bit ints" ) ,
6264 BinOp :: Div => {
6365 assert ! ( !checked) ;
6466 if is_signed {
0 commit comments