From 8ad09748d0cd10f8e6356aeeb68d2d144eabeb33 Mon Sep 17 00:00:00 2001 From: David Mak Date: Fri, 3 Nov 2023 15:34:07 +0800 Subject: [PATCH] core: Fix conversion from float to unsigned types These conversions also need to wraparound. --- nac3core/src/toplevel/builtins.rs | 83 ++++++++++++++++++++++++------- 1 file changed, 64 insertions(+), 19 deletions(-) diff --git a/nac3core/src/toplevel/builtins.rs b/nac3core/src/toplevel/builtins.rs index 2bd0f9a4..8f6e32df 100644 --- a/nac3core/src/toplevel/builtins.rs +++ b/nac3core/src/toplevel/builtins.rs @@ -650,13 +650,34 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo { .build_int_truncate(arg.into_int_value(), ctx.ctx.i32_type(), "trunc") .into() } else if ctx.unifier.unioned(arg_ty, float) { - ctx.builder + let llvm_i32 = ctx.ctx.i32_type(); + let llvm_i64 = ctx.ctx.i64_type(); + + let arg = arg.into_float_value(); + let arg_gez = ctx.builder + .build_float_compare(FloatPredicate::OGE, arg, arg.get_type().const_zero(), ""); + + let to_int32 = ctx.builder + .build_float_to_signed_int( + arg, + llvm_i32, + "" + ); + let to_uint64 = ctx.builder .build_float_to_unsigned_int( - arg.into_float_value(), - ctx.ctx.i32_type(), - "ftoi", - ) - .into() + arg, + llvm_i64, + "" + ); + + let val = ctx.builder.build_select( + arg_gez, + ctx.builder.build_int_truncate(to_uint64, llvm_i32, ""), + to_int32, + "conv" + ); + + val.into() } else { unreachable!(); }; @@ -703,13 +724,33 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo { { arg } else if ctx.unifier.unioned(arg_ty, float) { - ctx.builder + let llvm_i64 = ctx.ctx.i64_type(); + + let arg = arg.into_float_value(); + let arg_gez = ctx.builder + .build_float_compare(FloatPredicate::OGE, arg, arg.get_type().const_zero(), ""); + + let to_int64 = ctx.builder + .build_float_to_signed_int( + arg, + llvm_i64, + "" + ); + let to_uint64 = ctx.builder .build_float_to_unsigned_int( - arg.into_float_value(), - ctx.ctx.i64_type(), - "ftoi", - ) - .into() + arg, + llvm_i64, + "" + ); + + let val = ctx.builder.build_select( + arg_gez, + to_uint64, + to_int64, + "conv" + ); + + val.into() } else { unreachable!(); }; @@ -732,16 +773,20 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo { resolver: None, codegen_callback: Some(Arc::new(GenCall::new(Box::new( |ctx, _, fun, args, generator| { - let int32 = ctx.primitives.int32; - let int64 = ctx.primitives.int64; - let boolean = ctx.primitives.bool; - let float = ctx.primitives.float; + let PrimitiveStore { + int32, + int64, + uint32, + uint64, + float, + bool: boolean, + .. + } = ctx.primitives; + let arg_ty = fun.0.args[0].ty; let arg = args[0].1.clone().to_basic_value_enum(ctx, generator, arg_ty)?; Ok( - if ctx.unifier.unioned(arg_ty, boolean) - || ctx.unifier.unioned(arg_ty, int32) - || ctx.unifier.unioned(arg_ty, int64) + if [boolean, int32, int64].iter().any(|ty| ctx.unifier.unioned(arg_ty, *ty)) { let arg = arg.into_int_value(); let val = ctx