Skip to content

Commit e564790

Browse files
committed
Split codegen_i128::maybe_codegen into two functions
1 parent 9b40efa commit e564790

File tree

2 files changed

+82
-67
lines changed

2 files changed

+82
-67
lines changed

src/codegen_i128.rs

Lines changed: 80 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ use crate::prelude::*;
77
pub(crate) fn maybe_codegen<'tcx>(
88
fx: &mut FunctionCx<'_, '_, 'tcx>,
99
bin_op: BinOp,
10-
checked: bool,
1110
lhs: CValue<'tcx>,
1211
rhs: CValue<'tcx>,
1312
) -> Option<CValue<'tcx>> {
@@ -22,69 +21,23 @@ pub(crate) fn maybe_codegen<'tcx>(
2221
let is_signed = type_sign(lhs.layout().ty);
2322

2423
match bin_op {
25-
BinOp::BitAnd | BinOp::BitOr | BinOp::BitXor => {
26-
assert!(!checked);
27-
None
28-
}
29-
BinOp::Add | BinOp::Sub if !checked => None,
30-
BinOp::Mul if !checked || is_signed => {
31-
if !checked {
32-
let args = [lhs.load_scalar(fx), rhs.load_scalar(fx)];
33-
let ret_val = fx.lib_call(
34-
"__multi3",
35-
vec![AbiParam::new(types::I128), AbiParam::new(types::I128)],
36-
vec![AbiParam::new(types::I128)],
37-
&args,
38-
)[0];
39-
Some(CValue::by_val(
40-
ret_val,
41-
fx.layout_of(if is_signed { fx.tcx.types.i128 } else { fx.tcx.types.u128 }),
42-
))
43-
} else {
44-
let out_ty = fx.tcx.mk_tup(&[lhs.layout().ty, fx.tcx.types.bool]);
45-
let oflow = CPlace::new_stack_slot(fx, fx.layout_of(fx.tcx.types.i32));
46-
let lhs = lhs.load_scalar(fx);
47-
let rhs = rhs.load_scalar(fx);
48-
let oflow_ptr = oflow.to_ptr().get_addr(fx);
49-
let res = fx.lib_call_unadjusted(
50-
"__muloti4",
51-
vec![
52-
AbiParam::new(types::I128),
53-
AbiParam::new(types::I128),
54-
AbiParam::new(fx.pointer_type),
55-
],
56-
vec![AbiParam::new(types::I128)],
57-
&[lhs, rhs, oflow_ptr],
58-
)[0];
59-
let oflow = oflow.to_cvalue(fx).load_scalar(fx);
60-
let oflow = fx.bcx.ins().ireduce(types::I8, oflow);
61-
Some(CValue::by_val_pair(res, oflow, fx.layout_of(out_ty)))
62-
}
63-
}
64-
BinOp::Add | BinOp::Sub | BinOp::Mul => {
65-
assert!(checked);
66-
let out_ty = fx.tcx.mk_tup(&[lhs.layout().ty, fx.tcx.types.bool]);
67-
let out_place = CPlace::new_stack_slot(fx, fx.layout_of(out_ty));
68-
let param_types = vec![
69-
AbiParam::special(fx.pointer_type, ArgumentPurpose::StructReturn),
70-
AbiParam::new(types::I128),
71-
AbiParam::new(types::I128),
72-
];
73-
let args = [out_place.to_ptr().get_addr(fx), lhs.load_scalar(fx), rhs.load_scalar(fx)];
74-
let name = match (bin_op, is_signed) {
75-
(BinOp::Add, false) => "__rust_u128_addo",
76-
(BinOp::Add, true) => "__rust_i128_addo",
77-
(BinOp::Sub, false) => "__rust_u128_subo",
78-
(BinOp::Sub, true) => "__rust_i128_subo",
79-
(BinOp::Mul, false) => "__rust_u128_mulo",
80-
_ => unreachable!(),
81-
};
82-
fx.lib_call(name, param_types, vec![], &args);
83-
Some(out_place.to_cvalue(fx))
24+
BinOp::BitAnd | BinOp::BitOr | BinOp::BitXor => None,
25+
BinOp::Add | BinOp::Sub => None,
26+
BinOp::Mul => {
27+
let args = [lhs.load_scalar(fx), rhs.load_scalar(fx)];
28+
let ret_val = fx.lib_call(
29+
"__multi3",
30+
vec![AbiParam::new(types::I128), AbiParam::new(types::I128)],
31+
vec![AbiParam::new(types::I128)],
32+
&args,
33+
)[0];
34+
Some(CValue::by_val(
35+
ret_val,
36+
fx.layout_of(if is_signed { fx.tcx.types.i128 } else { fx.tcx.types.u128 }),
37+
))
8438
}
8539
BinOp::Offset => unreachable!("offset should only be used on pointers, not 128bit ints"),
8640
BinOp::Div | BinOp::Rem => {
87-
assert!(!checked);
8841
let name = match (bin_op, is_signed) {
8942
(BinOp::Div, false) => "__udivti3",
9043
(BinOp::Div, true) => "__divti3",
@@ -115,10 +68,72 @@ pub(crate) fn maybe_codegen<'tcx>(
11568
Some(CValue::by_val(ret_val, lhs.layout()))
11669
}
11770
}
118-
BinOp::Lt | BinOp::Le | BinOp::Eq | BinOp::Ge | BinOp::Gt | BinOp::Ne => {
119-
assert!(!checked);
120-
None
121-
}
71+
BinOp::Lt | BinOp::Le | BinOp::Eq | BinOp::Ge | BinOp::Gt | BinOp::Ne => None,
12272
BinOp::Shl | BinOp::Shr => None,
12373
}
12474
}
75+
76+
pub(crate) fn maybe_codegen_checked<'tcx>(
77+
fx: &mut FunctionCx<'_, '_, 'tcx>,
78+
bin_op: BinOp,
79+
lhs: CValue<'tcx>,
80+
rhs: CValue<'tcx>,
81+
) -> Option<CValue<'tcx>> {
82+
if lhs.layout().ty != fx.tcx.types.u128
83+
&& lhs.layout().ty != fx.tcx.types.i128
84+
&& rhs.layout().ty != fx.tcx.types.u128
85+
&& rhs.layout().ty != fx.tcx.types.i128
86+
{
87+
return None;
88+
}
89+
90+
let is_signed = type_sign(lhs.layout().ty);
91+
92+
match bin_op {
93+
BinOp::BitAnd | BinOp::BitOr | BinOp::BitXor => unreachable!(),
94+
BinOp::Mul if is_signed => {
95+
let out_ty = fx.tcx.mk_tup(&[lhs.layout().ty, fx.tcx.types.bool]);
96+
let oflow = CPlace::new_stack_slot(fx, fx.layout_of(fx.tcx.types.i32));
97+
let lhs = lhs.load_scalar(fx);
98+
let rhs = rhs.load_scalar(fx);
99+
let oflow_ptr = oflow.to_ptr().get_addr(fx);
100+
let res = fx.lib_call_unadjusted(
101+
"__muloti4",
102+
vec![
103+
AbiParam::new(types::I128),
104+
AbiParam::new(types::I128),
105+
AbiParam::new(fx.pointer_type),
106+
],
107+
vec![AbiParam::new(types::I128)],
108+
&[lhs, rhs, oflow_ptr],
109+
)[0];
110+
let oflow = oflow.to_cvalue(fx).load_scalar(fx);
111+
let oflow = fx.bcx.ins().ireduce(types::I8, oflow);
112+
Some(CValue::by_val_pair(res, oflow, fx.layout_of(out_ty)))
113+
}
114+
BinOp::Add | BinOp::Sub | BinOp::Mul => {
115+
let out_ty = fx.tcx.mk_tup(&[lhs.layout().ty, fx.tcx.types.bool]);
116+
let out_place = CPlace::new_stack_slot(fx, fx.layout_of(out_ty));
117+
let param_types = vec![
118+
AbiParam::special(fx.pointer_type, ArgumentPurpose::StructReturn),
119+
AbiParam::new(types::I128),
120+
AbiParam::new(types::I128),
121+
];
122+
let args = [out_place.to_ptr().get_addr(fx), lhs.load_scalar(fx), rhs.load_scalar(fx)];
123+
let name = match (bin_op, is_signed) {
124+
(BinOp::Add, false) => "__rust_u128_addo",
125+
(BinOp::Add, true) => "__rust_i128_addo",
126+
(BinOp::Sub, false) => "__rust_u128_subo",
127+
(BinOp::Sub, true) => "__rust_i128_subo",
128+
(BinOp::Mul, false) => "__rust_u128_mulo",
129+
_ => unreachable!(),
130+
};
131+
fx.lib_call(name, param_types, vec![], &args);
132+
Some(out_place.to_cvalue(fx))
133+
}
134+
BinOp::Offset => unreachable!("offset should only be used on pointers, not 128bit ints"),
135+
BinOp::Div | BinOp::Rem => unreachable!(),
136+
BinOp::Lt | BinOp::Le | BinOp::Eq | BinOp::Ge | BinOp::Gt | BinOp::Ne => unreachable!(),
137+
BinOp::Shl | BinOp::Shr => unreachable!(),
138+
}
139+
}

src/num.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ pub(crate) fn codegen_int_binop<'tcx>(
118118
);
119119
}
120120

121-
if let Some(res) = crate::codegen_i128::maybe_codegen(fx, bin_op, false, in_lhs, in_rhs) {
121+
if let Some(res) = crate::codegen_i128::maybe_codegen(fx, bin_op, in_lhs, in_rhs) {
122122
return res;
123123
}
124124

@@ -173,7 +173,7 @@ pub(crate) fn codegen_checked_int_binop<'tcx>(
173173
let lhs = in_lhs.load_scalar(fx);
174174
let rhs = in_rhs.load_scalar(fx);
175175

176-
if let Some(res) = crate::codegen_i128::maybe_codegen(fx, bin_op, true, in_lhs, in_rhs) {
176+
if let Some(res) = crate::codegen_i128::maybe_codegen_checked(fx, bin_op, in_lhs, in_rhs) {
177177
return res;
178178
}
179179

0 commit comments

Comments
 (0)