Skip to content

Commit b2d6705

Browse files
committed
Implement u/i128 <-> float casts
Fixes rust-lang#668
1 parent 3fcd540 commit b2d6705

File tree

2 files changed

+52
-2
lines changed

2 files changed

+52
-2
lines changed

example/std_example.rs

+11
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,17 @@ fn main() {
5555
assert_eq!(0xFEDCBA987654321123456789ABCDEFu128 as i128 >> 64, 0xFEDCBA98765432i128);
5656
assert_eq!(353985398u128 * 932490u128, 330087843781020u128);
5757

58+
// Check that all u/i128 <-> float casts work correctly.
59+
assert_eq!(100u128 as f32, 100.0);
60+
assert_eq!(100u128 as f64, 100.0);
61+
assert_eq!(100.0f32 as u128, 100);
62+
assert_eq!(100.0f64 as u128, 100);
63+
assert_eq!(100i128 as f32, 100.0);
64+
assert_eq!(100i128 as f64, 100.0);
65+
assert_eq!(100.0f32 as i128, 100);
66+
assert_eq!(100.0f64 as i128, 100);
67+
68+
5869
let _a = 1u32 << 2u8;
5970

6071
unsafe {

src/cast.rs

+41-2
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,17 @@ pub fn clif_int_or_float_cast(
5555
) -> Value {
5656
let from_ty = fx.bcx.func.dfg.value_type(from);
5757

58+
macro call_float_cvt_intrinsic($fmt:literal, $sign_name:literal, $from_ty:expr, $to_ty:expr) {
59+
let intrinsic_sign_name = if from_signed { "" } else { $sign_name };
60+
let intrinsic_float_name = match to_ty {
61+
types::F32 => "s",
62+
types::F64 => "d",
63+
_ => unreachable!("{:?}", to_ty),
64+
};
65+
let intrinsic_name = format!($fmt, sign=intrinsic_sign_name, flt=intrinsic_float_name);
66+
return fx.easy_call(&intrinsic_name, &[CValue::by_val(from, fx.layout_of($from_ty))], $to_ty).load_scalar(fx);
67+
}
68+
5869
if from_ty.is_int() && to_ty.is_int() {
5970
// int-like -> int-like
6071
clif_intcast(
@@ -65,7 +76,21 @@ pub fn clif_int_or_float_cast(
6576
)
6677
} else if from_ty.is_int() && to_ty.is_float() {
6778
if from_ty == types::I128 {
68-
unimpl!("u/i128 -> float");
79+
// _______ss__f_
80+
// __float tisf: i128 -> f32
81+
// __float tidf: i128 -> f64
82+
// __floatuntisf: u128 -> f32
83+
// __floatuntidf: u128 -> f64
84+
call_float_cvt_intrinsic!("__float{sign}ti{flt}f", "un", if from_signed {
85+
fx.tcx.types.i128
86+
} else {
87+
fx.tcx.types.u128
88+
},
89+
match to_ty {
90+
types::F32 => fx.tcx.types.f32,
91+
types::F64 => fx.tcx.types.f64,
92+
_ => unreachable!(),
93+
});
6994
}
7095

7196
// int-like -> float
@@ -76,7 +101,21 @@ pub fn clif_int_or_float_cast(
76101
}
77102
} else if from_ty.is_float() && to_ty.is_int() {
78103
if to_ty == types::I128 {
79-
unimpl!("float -> u/i128");
104+
// _____sssf___
105+
// __fix sfti: f32 -> i128
106+
// __fix dfti: f64 -> i128
107+
// __fixunssfti: f32 -> u128
108+
// __fixunsdfti: f64 -> u128
109+
call_float_cvt_intrinsic!("__fix{sign}{flt}fti", "uns", match from_ty {
110+
types::F32 => fx.tcx.types.f32,
111+
types::F64 => fx.tcx.types.f64,
112+
_ => unreachable!(),
113+
},
114+
if to_signed {
115+
fx.tcx.types.i128
116+
} else {
117+
fx.tcx.types.u128
118+
});
80119
}
81120

82121
// float -> int-like

0 commit comments

Comments
 (0)