Skip to content

Commit

Permalink
Implement u/i128 <-> float casts
Browse files Browse the repository at this point in the history
  • Loading branch information
bjorn3 committed Aug 21, 2019
1 parent 3fcd540 commit b2d6705
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 2 deletions.
11 changes: 11 additions & 0 deletions example/std_example.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,17 @@ fn main() {
assert_eq!(0xFEDCBA987654321123456789ABCDEFu128 as i128 >> 64, 0xFEDCBA98765432i128);
assert_eq!(353985398u128 * 932490u128, 330087843781020u128);

// Check that all u/i128 <-> float casts work correctly.
assert_eq!(100u128 as f32, 100.0);
assert_eq!(100u128 as f64, 100.0);
assert_eq!(100.0f32 as u128, 100);
assert_eq!(100.0f64 as u128, 100);
assert_eq!(100i128 as f32, 100.0);
assert_eq!(100i128 as f64, 100.0);
assert_eq!(100.0f32 as i128, 100);
assert_eq!(100.0f64 as i128, 100);


let _a = 1u32 << 2u8;

unsafe {
Expand Down
43 changes: 41 additions & 2 deletions src/cast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,17 @@ pub fn clif_int_or_float_cast(
) -> Value {
let from_ty = fx.bcx.func.dfg.value_type(from);

macro call_float_cvt_intrinsic($fmt:literal, $sign_name:literal, $from_ty:expr, $to_ty:expr) {
let intrinsic_sign_name = if from_signed { "" } else { $sign_name };
let intrinsic_float_name = match to_ty {
types::F32 => "s",
types::F64 => "d",
_ => unreachable!("{:?}", to_ty),
};
let intrinsic_name = format!($fmt, sign=intrinsic_sign_name, flt=intrinsic_float_name);
return fx.easy_call(&intrinsic_name, &[CValue::by_val(from, fx.layout_of($from_ty))], $to_ty).load_scalar(fx);
}

if from_ty.is_int() && to_ty.is_int() {
// int-like -> int-like
clif_intcast(
Expand All @@ -65,7 +76,21 @@ pub fn clif_int_or_float_cast(
)
} else if from_ty.is_int() && to_ty.is_float() {
if from_ty == types::I128 {
unimpl!("u/i128 -> float");
// _______ss__f_
// __float tisf: i128 -> f32
// __float tidf: i128 -> f64
// __floatuntisf: u128 -> f32
// __floatuntidf: u128 -> f64
call_float_cvt_intrinsic!("__float{sign}ti{flt}f", "un", if from_signed {
fx.tcx.types.i128
} else {
fx.tcx.types.u128
},
match to_ty {
types::F32 => fx.tcx.types.f32,
types::F64 => fx.tcx.types.f64,
_ => unreachable!(),
});
}

// int-like -> float
Expand All @@ -76,7 +101,21 @@ pub fn clif_int_or_float_cast(
}
} else if from_ty.is_float() && to_ty.is_int() {
if to_ty == types::I128 {
unimpl!("float -> u/i128");
// _____sssf___
// __fix sfti: f32 -> i128
// __fix dfti: f64 -> i128
// __fixunssfti: f32 -> u128
// __fixunsdfti: f64 -> u128
call_float_cvt_intrinsic!("__fix{sign}{flt}fti", "uns", match from_ty {
types::F32 => fx.tcx.types.f32,
types::F64 => fx.tcx.types.f64,
_ => unreachable!(),
},
if to_signed {
fx.tcx.types.i128
} else {
fx.tcx.types.u128
});
}

// float -> int-like
Expand Down

0 comments on commit b2d6705

Please sign in to comment.