diff --git a/example/std_example.rs b/example/std_example.rs index a09e050ce3b..2a9df999559 100644 --- a/example/std_example.rs +++ b/example/std_example.rs @@ -30,6 +30,7 @@ fn main() { println!("{}", 2.3f32.ceil()); println!("{}", 2.3f32.min(1.0)); println!("{}", 2.3f32.max(1.0)); + println!("{}", 2.3f32.powi(2)); assert_eq!(0b0000000000000000000000000010000010000000000000000000000000000000_0000000000100000000000000000000000001000000000000100000000000000u128.leading_zeros(), 26); assert_eq!(0b0000000000000000000000000010000000000000000000000000000000000000_0000000000000000000000000000000000001000000000000000000010000000u128.trailing_zeros(), 7); diff --git a/src/intrinsics.rs b/src/intrinsics.rs index ee00924ad82..1f86b096e63 100644 --- a/src/intrinsics.rs +++ b/src/intrinsics.rs @@ -59,6 +59,35 @@ macro_rules! intrinsic_match { }; } +macro_rules! call_intrinsic_match { + ($fx:expr, $intrinsic:expr, $substs:expr, $ret:expr, $destination:expr, $args:expr, $( + $name:ident($($arg:ident),*) -> $ty:ident => $func:ident, + )*) => { + match $intrinsic { + $( + stringify!($name) => { + assert!($substs.is_noop()); + if let [$($arg),*] = *$args { + let res = $fx.easy_call(stringify!($func), &[$($arg),*], $fx.tcx.types.$ty); + $ret.write_cvalue($fx, res); + + if let Some((_, dest)) = $destination { + let ret_ebb = $fx.get_ebb(dest); + $fx.bcx.ins().jump(ret_ebb, &[]); + return; + } else { + unreachable!(); + } + } else { + bug!("wrong number of args for intrinsic {:?}", $intrinsic); + } + } + )* + _ => {} + } + } +} + macro_rules! atomic_binop_return_old { ($fx:expr, $op:ident<$T:ident>($ptr:ident, $src:ident) -> $ret:ident) => { let clif_ty = $fx.clif_type($T).unwrap(); @@ -117,6 +146,48 @@ pub fn codegen_intrinsic_call<'a, 'tcx: 'a>( let u64_layout = fx.layout_of(fx.tcx.types.u64); let usize_layout = fx.layout_of(fx.tcx.types.usize); + call_intrinsic_match! { + fx, intrinsic, substs, ret, destination, args, + expf32(flt) -> f32 => expf, + expf64(flt) -> f64 => exp, + exp2f32(flt) -> f32 => exp2f, + exp2f64(flt) -> f64 => exp2, + sqrtf32(flt) -> f32 => sqrtf, + sqrtf64(flt) -> f64 => sqrt, + powif32(a, x) -> f32 => __powisf2, // compiler-builtins + powif64(a, x) -> f64 => __powidf2, // compiler-builtins + logf32(flt) -> f32 => logf, + logf64(flt) -> f64 => log, + fabsf32(flt) -> f32 => fabsf, + fabsf64(flt) -> f64 => fabs, + fmaf32(x, y, z) -> f32 => fmaf, + fmaf64(x, y, z) -> f64 => fma, + + // rounding variants + floorf32(flt) -> f32 => floorf, + floorf64(flt) -> f64 => floor, + ceilf32(flt) -> f32 => ceilf, + ceilf64(flt) -> f64 => ceil, + truncf32(flt) -> f32 => truncf, + truncf64(flt) -> f64 => trunc, + roundf32(flt) -> f32 => roundf, + roundf64(flt) -> f64 => round, + + // trigonometry + sinf32(flt) -> f32 => sinf, + sinf64(flt) -> f64 => sin, + cosf32(flt) -> f32 => cosf, + cosf64(flt) -> f64 => cos, + tanf32(flt) -> f32 => tanf, + tanf64(flt) -> f64 => tan, + + // minmax + minnumf32(a, b) -> f32 => fminf, + minnumf64(a, b) -> f64 => fmin, + maxnumf32(a, b) -> f32 => fmaxf, + maxnumf64(a, b) -> f64 => fmax, + } + intrinsic_match! { fx, intrinsic, substs, args, @@ -604,73 +675,6 @@ pub fn codegen_intrinsic_call<'a, 'tcx: 'a>( _ if intrinsic.starts_with("atomic_umin"), (v ptr, v src) { atomic_minmax!(fx, IntCC::UnsignedLessThan, (ptr, src) -> ret); }; - - expf32, (c flt) { - let res = fx.easy_call("expf", &[flt], fx.tcx.types.f32); - ret.write_cvalue(fx, res); - }; - expf64, (c flt) { - let res = fx.easy_call("exp", &[flt], fx.tcx.types.f64); - ret.write_cvalue(fx, res); - }; - exp2f32, (c flt) { - let res = fx.easy_call("exp2f", &[flt], fx.tcx.types.f32); - ret.write_cvalue(fx, res); - }; - exp2f64, (c flt) { - let res = fx.easy_call("exp2", &[flt], fx.tcx.types.f64); - ret.write_cvalue(fx, res); - }; - fabsf32, (c flt) { - let res = fx.easy_call("fabsf", &[flt], fx.tcx.types.f32); - ret.write_cvalue(fx, res); - }; - fabsf64, (c flt) { - let res = fx.easy_call("fabs", &[flt], fx.tcx.types.f64); - ret.write_cvalue(fx, res); - }; - sqrtf32, (c flt) { - let res = fx.easy_call("sqrtf", &[flt], fx.tcx.types.f32); - ret.write_cvalue(fx, res); - }; - sqrtf64, (c flt) { - let res = fx.easy_call("sqrt", &[flt], fx.tcx.types.f64); - ret.write_cvalue(fx, res); - }; - floorf32, (c flt) { - let res = fx.easy_call("floorf", &[flt], fx.tcx.types.f32); - ret.write_cvalue(fx, res); - }; - floorf64, (c flt) { - let res = fx.easy_call("floor", &[flt], fx.tcx.types.f64); - ret.write_cvalue(fx, res); - }; - ceilf32, (c flt) { - let res = fx.easy_call("ceilf", &[flt], fx.tcx.types.f32); - ret.write_cvalue(fx, res); - }; - ceilf64, (c flt) { - let res = fx.easy_call("ceil", &[flt], fx.tcx.types.f64); - ret.write_cvalue(fx, res); - }; - - minnumf32, (c a, c b) { - let res = fx.easy_call("fminf", &[a, b], fx.tcx.types.f32); - ret.write_cvalue(fx, res); - }; - minnumf64, (c a, c b) { - let res = fx.easy_call("fmin", &[a, b], fx.tcx.types.f64); - ret.write_cvalue(fx, res); - }; - maxnumf32, (c a, c b) { - let res = fx.easy_call("fmaxf", &[a, b], fx.tcx.types.f32); - ret.write_cvalue(fx, res); - }; - maxnumf64, (c a, c b) { - let res = fx.easy_call("fmax", &[a, b], fx.tcx.types.f64); - ret.write_cvalue(fx, res); - }; - } if let Some((_, dest)) = destination {