Skip to content
This repository was archived by the owner on May 28, 2025. It is now read-only.

Commit 139a6d1

Browse files
committed
Fix 128bit checked math intrinsic calls
1 parent e8f48e4 commit 139a6d1

File tree

3 files changed

+52
-41
lines changed

3 files changed

+52
-41
lines changed

src/abi/mod.rs

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -102,13 +102,13 @@ impl<'tcx, M: Module> FunctionCx<'_, 'tcx, M> {
102102
pub(crate) fn lib_call(
103103
&mut self,
104104
name: &str,
105-
input_tys: Vec<types::Type>,
106-
output_tys: Vec<types::Type>,
105+
params: Vec<AbiParam>,
106+
returns: Vec<AbiParam>,
107107
args: &[Value],
108108
) -> &[Value] {
109109
let sig = Signature {
110-
params: input_tys.iter().cloned().map(AbiParam::new).collect(),
111-
returns: output_tys.iter().cloned().map(AbiParam::new).collect(),
110+
params,
111+
returns,
112112
call_conv: CallConv::triple_default(self.triple()),
113113
};
114114
let func_id = self
@@ -140,16 +140,18 @@ impl<'tcx, M: Module> FunctionCx<'_, 'tcx, M> {
140140
.iter()
141141
.map(|arg| {
142142
(
143-
self.clif_type(arg.layout().ty).unwrap(),
143+
AbiParam::new(self.clif_type(arg.layout().ty).unwrap()),
144144
arg.load_scalar(self),
145145
)
146146
})
147147
.unzip();
148148
let return_layout = self.layout_of(return_ty);
149149
let return_tys = if let ty::Tuple(tup) = return_ty.kind() {
150-
tup.types().map(|ty| self.clif_type(ty).unwrap()).collect()
150+
tup.types()
151+
.map(|ty| AbiParam::new(self.clif_type(ty).unwrap()))
152+
.collect()
151153
} else {
152-
vec![self.clif_type(return_ty).unwrap()]
154+
vec![AbiParam::new(self.clif_type(return_ty).unwrap())]
153155
};
154156
let ret_vals = self.lib_call(name, input_tys, return_tys, &args);
155157
match *ret_vals {
@@ -208,7 +210,8 @@ pub(crate) fn codegen_fn_prelude<'tcx>(
208210
.block_params(start_block)
209211
.to_vec()
210212
.into_iter();
211-
let ret_place = self::returning::codegen_return_param(fx, &ssa_analyzed, &mut block_params_iter);
213+
let ret_place =
214+
self::returning::codegen_return_param(fx, &ssa_analyzed, &mut block_params_iter);
212215
assert_eq!(fx.local_map.push(ret_place), RETURN_PLACE);
213216

214217
// None means pass_mode == NoPass
@@ -241,14 +244,16 @@ pub(crate) fn codegen_fn_prelude<'tcx>(
241244
let mut params = Vec::new();
242245
for (i, _arg_ty) in tupled_arg_tys.types().enumerate() {
243246
let arg_abi = arg_abis_iter.next().unwrap();
244-
let param = cvalue_for_param(fx, Some(local), Some(i), arg_abi, &mut block_params_iter);
247+
let param =
248+
cvalue_for_param(fx, Some(local), Some(i), arg_abi, &mut block_params_iter);
245249
params.push(param);
246250
}
247251

248252
(local, ArgKind::Spread(params), arg_ty)
249253
} else {
250254
let arg_abi = arg_abis_iter.next().unwrap();
251-
let param = cvalue_for_param(fx, Some(local), None, arg_abi, &mut block_params_iter);
255+
let param =
256+
cvalue_for_param(fx, Some(local), None, arg_abi, &mut block_params_iter);
252257
(local, ArgKind::Normal(param), arg_ty)
253258
}
254259
})

src/base.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1060,7 +1060,11 @@ pub(crate) fn codegen_panic_inner<'tcx>(
10601060

10611061
fx.lib_call(
10621062
&*symbol_name,
1063-
vec![fx.pointer_type, fx.pointer_type, fx.pointer_type],
1063+
vec![
1064+
AbiParam::new(fx.pointer_type),
1065+
AbiParam::new(fx.pointer_type),
1066+
AbiParam::new(fx.pointer_type),
1067+
],
10641068
vec![],
10651069
args,
10661070
);

src/codegen_i128.rs

Lines changed: 32 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
//! Replaces 128-bit operators with lang item calls where necessary
22
3+
use cranelift_codegen::ir::ArgumentPurpose;
4+
35
use crate::prelude::*;
46

57
pub(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

Comments
 (0)