Skip to content

Commit cd684e3

Browse files
committed
Fix saturated_* intrinsics for 128bit ints
Fixes #968
1 parent 9a378c3 commit cd684e3

File tree

3 files changed

+36
-7
lines changed

3 files changed

+36
-7
lines changed

src/cast.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,13 @@ pub(crate) fn clif_int_or_float_cast(
159159
} else {
160160
fx.bcx.ins().fcvt_to_uint_sat(types::I32, from)
161161
};
162-
let (min, max) = type_min_max_value(to_ty, to_signed);
162+
let (min, max) = match (to_ty, to_signed) {
163+
(types::I8, false) => (0, u8::MAX as i64),
164+
(types::I16, false) => (0, u16::MAX as i64),
165+
(types::I8, true) => (i8::MIN as i64, i8::MAX as i64),
166+
(types::I16, true) => (i16::MIN as i64, i16::MAX as i64),
167+
_ => unreachable!(),
168+
};
163169
let min_val = fx.bcx.ins().iconst(types::I32, min);
164170
let max_val = fx.bcx.ins().iconst(types::I32, max);
165171

src/common.rs

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -215,8 +215,33 @@ pub(crate) fn resolve_value_imm(func: &Function, val: Value) -> Option<u128> {
215215
}
216216
}
217217

218-
pub(crate) fn type_min_max_value(ty: Type, signed: bool) -> (i64, i64) {
218+
pub(crate) fn type_min_max_value(bcx: &mut FunctionBuilder<'_>, ty: Type, signed: bool) -> (Value, Value) {
219219
assert!(ty.is_int());
220+
221+
if ty == types::I128 {
222+
if signed {
223+
let min = i128::MIN as u128;
224+
let min_lsb = bcx.ins().iconst(types::I64, min as u64 as i64);
225+
let min_msb = bcx.ins().iconst(types::I64, (min >> 64) as u64 as i64);
226+
let min = bcx.ins().iconcat(min_lsb, min_msb);
227+
228+
let max = i128::MIN as u128;
229+
let max_lsb = bcx.ins().iconst(types::I64, max as u64 as i64);
230+
let max_msb = bcx.ins().iconst(types::I64, (max >> 64) as u64 as i64);
231+
let max = bcx.ins().iconcat(max_lsb, max_msb);
232+
233+
return (min, max);
234+
} else {
235+
let min_half = bcx.ins().iconst(types::I64, 0);
236+
let min = bcx.ins().iconcat(min_half, min_half);
237+
238+
let max_half = bcx.ins().iconst(types::I64, u64::MAX as i64);
239+
let max = bcx.ins().iconcat(max_half, max_half);
240+
241+
return (min, max);
242+
}
243+
}
244+
220245
let min = match (ty, signed) {
221246
(types::I8, false) | (types::I16, false) | (types::I32, false) | (types::I64, false) => {
222247
0i64
@@ -225,7 +250,6 @@ pub(crate) fn type_min_max_value(ty: Type, signed: bool) -> (i64, i64) {
225250
(types::I16, true) => i16::MIN as i64,
226251
(types::I32, true) => i32::MIN as i64,
227252
(types::I64, true) => i64::MIN,
228-
(types::I128, _) => unimplemented!(),
229253
_ => unreachable!(),
230254
};
231255

@@ -238,10 +262,11 @@ pub(crate) fn type_min_max_value(ty: Type, signed: bool) -> (i64, i64) {
238262
(types::I16, true) => i16::MAX as i64,
239263
(types::I32, true) => i32::MAX as i64,
240264
(types::I64, true) => i64::MAX,
241-
(types::I128, _) => unimplemented!(),
242265
_ => unreachable!(),
243266
};
244267

268+
let (min, max) = (bcx.ins().iconst(ty, min), bcx.ins().iconst(ty, max));
269+
245270
(min, max)
246271
}
247272

src/intrinsics/mod.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -583,9 +583,7 @@ pub(crate) fn codegen_intrinsic_call<'tcx>(
583583
// `select.i8` is not implemented by Cranelift.
584584
let has_overflow = fx.bcx.ins().uextend(types::I32, has_overflow);
585585

586-
let (min, max) = type_min_max_value(clif_ty, signed);
587-
let min = fx.bcx.ins().iconst(clif_ty, min);
588-
let max = fx.bcx.ins().iconst(clif_ty, max);
586+
let (min, max) = type_min_max_value(&mut fx.bcx, clif_ty, signed);
589587

590588
let val = match (intrinsic, signed) {
591589
("saturating_add", false) => fx.bcx.ins().select(has_overflow, max, val),

0 commit comments

Comments
 (0)