diff --git a/src/compiler/c_codegen.c b/src/compiler/c_codegen.c index 487752014..0f381b297 100644 --- a/src/compiler/c_codegen.c +++ b/src/compiler/c_codegen.c @@ -396,6 +396,8 @@ static void c_emit_expr(GenContext *c, CValue *value, Expr *expr) switch (expr->expr_kind) { case EXPR_PTR_ACCESS: + case EXPR_INT_TO_FLOAT: + case EXPR_FLOAT_TO_INT: case EXPR_SLICE_LEN: case EXPR_DISCARD: case EXPR_RVALUE: diff --git a/src/compiler/compiler_internal.h b/src/compiler/compiler_internal.h index abe5e269d..7d8a1623a 100644 --- a/src/compiler/compiler_internal.h +++ b/src/compiler/compiler_internal.h @@ -3371,6 +3371,8 @@ static inline void expr_set_span(Expr *expr, SourceSpan loc) return; case EXPR_SPLAT: case EXPR_PTR_ACCESS: + case EXPR_INT_TO_FLOAT: + case EXPR_FLOAT_TO_INT: case EXPR_SLICE_LEN: case EXPR_DISCARD: case EXPR_VECTOR_FROM_ARRAY: @@ -3819,6 +3821,22 @@ INLINE void expr_rewrite_const_int(Expr *expr, Type *type, uint64_t v) (&expr->const_expr)->const_kind = CONST_INTEGER; } +INLINE void expr_rewrite_to_int_to_float(Expr *expr, Type *type) +{ + Expr *inner = expr_copy(expr); + expr->expr_kind = EXPR_INT_TO_FLOAT; + expr->inner_expr = inner; + expr->type = type; +} + +INLINE void expr_rewrite_to_float_to_int(Expr *expr, Type *type) +{ + Expr *inner = expr_copy(expr); + expr->expr_kind = EXPR_FLOAT_TO_INT; + expr->inner_expr = inner; + expr->type = type; +} + INLINE void expr_rewrite_const_float(Expr *expr, Type *type, Real d) { expr->expr_kind = EXPR_CONST; diff --git a/src/compiler/copying.c b/src/compiler/copying.c index b8f8d162f..984e8717f 100644 --- a/src/compiler/copying.c +++ b/src/compiler/copying.c @@ -476,6 +476,8 @@ Expr *copy_expr(CopyStruct *c, Expr *source_expr) case EXPR_SPLAT: case EXPR_STRINGIFY: case EXPR_PTR_ACCESS: + case EXPR_INT_TO_FLOAT: + case EXPR_FLOAT_TO_INT: case EXPR_SLICE_LEN: case EXPR_DISCARD: case EXPR_VECTOR_FROM_ARRAY: diff --git a/src/compiler/enums.h b/src/compiler/enums.h index b24e33c03..9d84f8385 100644 --- a/src/compiler/enums.h +++ b/src/compiler/enums.h @@ -543,15 +543,12 @@ typedef enum typedef enum { CAST_APTSA, - CAST_BOOLFP, CAST_BSBOOL, CAST_ERPTR, CAST_ERROR, CAST_EUER, CAST_FPFP, - CAST_FPINT, CAST_INTENUM, - CAST_INTFP, CAST_IDPTR, CAST_PTRBOOL, CAST_PTRINT, @@ -771,10 +768,12 @@ typedef enum EXPR_EXPRESSION_LIST, EXPR_EXPR_BLOCK, EXPR_FORCE_UNWRAP, + EXPR_FLOAT_TO_INT, EXPR_GENERIC_IDENT, EXPR_HASH_IDENT, EXPR_IDENTIFIER, EXPR_INITIALIZER_LIST, + EXPR_INT_TO_FLOAT, EXPR_LAMBDA, EXPR_LAST_FAULT, EXPR_MACRO_BLOCK, diff --git a/src/compiler/expr.c b/src/compiler/expr.c index bc5d74220..9cb43e61b 100644 --- a/src/compiler/expr.c +++ b/src/compiler/expr.c @@ -84,6 +84,8 @@ bool expr_may_addr(Expr *expr) case EXPR_TEST_HOOK: case EXPR_VECTOR_FROM_ARRAY: case EXPR_PTR_ACCESS: + case EXPR_FLOAT_TO_INT: + case EXPR_INT_TO_FLOAT: case EXPR_SLICE_LEN: case EXPR_RVALUE: case EXPR_RECAST: @@ -195,6 +197,8 @@ bool expr_is_runtime_const(Expr *expr) case EXPR_BITACCESS: case EXPR_COND: case EXPR_PTR_ACCESS: + case EXPR_INT_TO_FLOAT: + case EXPR_FLOAT_TO_INT: case EXPR_SLICE_LEN: return false; case EXPR_VECTOR_FROM_ARRAY: @@ -358,10 +362,7 @@ static inline bool expr_cast_is_runtime_const(Expr *expr) case CAST_INTENUM: case CAST_EUER: case CAST_PTRBOOL: - case CAST_BOOLFP: case CAST_FPFP: - case CAST_FPINT: - case CAST_INTFP: case CAST_SLBOOL: case CAST_VECARR: return exprid_is_runtime_const(expr->cast_expr.expr); @@ -608,6 +609,8 @@ bool expr_is_pure(Expr *expr) case EXPR_MAKE_ANY: return expr_is_pure(expr->make_any_expr.inner) && expr_is_pure(expr->make_any_expr.typeid); case EXPR_PTR_ACCESS: + case EXPR_INT_TO_FLOAT: + case EXPR_FLOAT_TO_INT: case EXPR_SLICE_LEN: case EXPR_DISCARD: case EXPR_VECTOR_FROM_ARRAY: diff --git a/src/compiler/json_output.c b/src/compiler/json_output.c index 88aa5a4b0..be53e9171 100644 --- a/src/compiler/json_output.c +++ b/src/compiler/json_output.c @@ -272,6 +272,10 @@ void print_var_expr(FILE *file, Expr *expr) print_var_expr(file, expr->access_expr.parent); fputs(".len", file); break; + case EXPR_FLOAT_TO_INT: + case EXPR_INT_TO_FLOAT: + TODO + break; case EXPR_PTR_ACCESS: print_var_expr(file, expr->access_expr.parent); fputs(".ptr", file); diff --git a/src/compiler/llvm_codegen_expr.c b/src/compiler/llvm_codegen_expr.c index b89d97960..56082ee9b 100644 --- a/src/compiler/llvm_codegen_expr.c +++ b/src/compiler/llvm_codegen_expr.c @@ -1475,35 +1475,12 @@ void llvm_emit_cast(GenContext *c, CastKind cast_kind, Expr *expr, BEValue *valu value->value = LLVMBuildIsNotNull(c->builder, value->value, "ptrbool"); value->kind = BE_BOOLEAN; break; - case CAST_BOOLFP: - llvm_value_rvalue(c, value); - value->value = LLVMBuildUIToFP(c->builder, value->value, llvm_get_type(c, to_type), "boolfp"); - value->kind = BE_VALUE; - break; case CAST_FPFP: llvm_value_rvalue(c, value); value->value = type_convert_will_trunc(to_type, from_type) ? LLVMBuildFPTrunc(c->builder, value->value, llvm_get_type(c, to_type), "fpfptrunc") : LLVMBuildFPExt(c->builder, value->value, llvm_get_type(c, to_type), "fpfpext"); break; - case CAST_FPINT: - llvm_value_rvalue(c, value); - if (type_is_signed(to_type)) - { - value->value = LLVMBuildFPToSI(c->builder, value->value, llvm_get_type(c, to_type), "fpsi"); - break; - } - value->value = LLVMBuildFPToUI(c->builder, value->value, llvm_get_type(c, to_type), "fpui"); - break; - case CAST_INTFP: - llvm_value_rvalue(c, value); - if (type_is_signed(value->type)) - { - value->value = LLVMBuildSIToFP(c->builder, value->value, llvm_get_type(c, to_type), "sifp"); - break; - } - value->value = LLVMBuildUIToFP(c->builder, value->value, llvm_get_type(c, to_type), "uifp"); - break; case CAST_IDPTR: case CAST_ERPTR: case CAST_INTPTR: @@ -7291,6 +7268,28 @@ void llvm_emit_expr(GenContext *c, BEValue *value, Expr *expr) case EXPR_MAKE_ANY: llvm_emit_make_any(c, value, expr); return; + case EXPR_FLOAT_TO_INT: + llvm_emit_expr(c, value, expr->inner_expr); + llvm_value_rvalue(c, value); + if (type_is_signed(type_lowering(expr->type))) + { + llvm_value_set(value, LLVMBuildFPToSI(c->builder, value->value, llvm_get_type(c, expr->type), "fpsi"), expr->type); + return; + } + llvm_value_set(value, LLVMBuildFPToUI(c->builder, value->value, llvm_get_type(c, expr->type), "fpui"), expr->type); + return; + case EXPR_INT_TO_FLOAT: + llvm_emit_expr(c, value, expr->inner_expr); + llvm_value_rvalue(c, value); + if (type_is_signed(value->type)) + { + llvm_value_set(value, LLVMBuildSIToFP(c->builder, value->value, llvm_get_type(c, expr->type), "sifp"), expr->type); + } + else + { + llvm_value_set(value, LLVMBuildUIToFP(c->builder, value->value, llvm_get_type(c, expr->type), "uifp"), expr->type); + } + return; case EXPR_DISCARD: llvm_value_set(value, NULL, type_void); llvm_emit_ignored_expr(c, expr->inner_expr); diff --git a/src/compiler/sema_casts.c b/src/compiler/sema_casts.c index 71baebbb3..d07440a01 100644 --- a/src/compiler/sema_casts.c +++ b/src/compiler/sema_casts.c @@ -1548,7 +1548,11 @@ static void cast_float_to_float(SemaContext *context, Expr *expr, Type *type) */ static void cast_float_to_int(SemaContext *context, Expr *expr, Type *type) { - if (insert_runtime_cast_unless_const(expr, CAST_FPINT, type)) return; + if (!sema_cast_const(expr)) + { + expr_rewrite_to_float_to_int(expr, type); + return; + } // Run the int->real to and rewrite. Real d = expr->const_expr.fxx.f; @@ -1668,7 +1672,11 @@ static void cast_bitstruct_to_bool(SemaContext *context, Expr *expr, Type *type) */ static void cast_int_to_float(SemaContext *context, Expr *expr, Type *type) { - if (insert_runtime_cast_unless_const(expr, CAST_INTFP, type)) return; + if (!sema_cast_const(expr)) + { + expr_rewrite_to_int_to_float(expr, type); + return; + } Real f = int_to_real(expr->const_expr.ixx); expr_rewrite_const_float(expr, type, f); @@ -1727,7 +1735,7 @@ static void cast_vec_to_vec(SemaContext *context, Expr *expr, Type *to_type) return; } case ALL_INTS: - insert_runtime_cast(expr, CAST_FPINT, to_type); + expr_rewrite_to_float_to_int(expr, to_type); return; default: UNREACHABLE; @@ -1745,7 +1753,7 @@ static void cast_vec_to_vec(SemaContext *context, Expr *expr, Type *to_type) } if (type_is_float(to_element)) { - insert_runtime_cast(expr, CAST_BOOLFP, to_type); + expr_rewrite_to_int_to_float(expr, to_type); return; } UNREACHABLE; @@ -1756,7 +1764,7 @@ static void cast_vec_to_vec(SemaContext *context, Expr *expr, Type *to_type) switch (to_element->type_kind) { case ALL_FLOATS: - insert_runtime_cast(expr, CAST_INTFP, to_type); + expr_rewrite_to_int_to_float(expr, to_type); return; case TYPE_BOOL: { @@ -1887,7 +1895,11 @@ static void cast_bool_to_int(SemaContext *context, Expr *expr, Type *type) */ static void cast_bool_to_float(SemaContext *context, Expr *expr, Type *type) { - if (insert_runtime_cast_unless_const(expr, CAST_BOOLFP, type)) return; + if (!sema_cast_const(expr)) + { + expr_rewrite_to_int_to_float(expr, type); + return; + } ASSERT0(expr->const_expr.const_kind == CONST_BOOL); expr_rewrite_const_float(expr, type, expr->const_expr.b ? 1.0 : 0.0); diff --git a/src/compiler/sema_expr.c b/src/compiler/sema_expr.c index 1cb92e1ed..df70e3da5 100644 --- a/src/compiler/sema_expr.c +++ b/src/compiler/sema_expr.c @@ -560,6 +560,8 @@ static bool sema_binary_is_expr_lvalue(SemaContext *context, Expr *top_expr, Exp case EXPR_POST_UNARY: case EXPR_PTR_ACCESS: case EXPR_SLICE_LEN: + case EXPR_FLOAT_TO_INT: + case EXPR_INT_TO_FLOAT: case EXPR_RECAST: case EXPR_RETHROW: case EXPR_RETVAL: @@ -606,6 +608,8 @@ static bool expr_may_ref(Expr *expr) case EXPR_MEMBER_GET: case EXPR_EXT_TRUNC: case EXPR_PTR_ACCESS: + case EXPR_FLOAT_TO_INT: + case EXPR_INT_TO_FLOAT: case EXPR_SLICE_LEN: case EXPR_VECTOR_FROM_ARRAY: case EXPR_INT_TO_BOOL: @@ -8995,6 +8999,8 @@ static inline bool sema_expr_analyse_ct_defined(SemaContext *context, Expr *expr case EXPR_MAKE_ANY: case EXPR_DISCARD: case EXPR_ADDR_CONVERSION: + case EXPR_FLOAT_TO_INT: + case EXPR_INT_TO_FLOAT: if (!sema_analyse_expr(active_context, main_expr)) goto FAIL; break; } @@ -9376,6 +9382,8 @@ static inline bool sema_analyse_expr_dispatch(SemaContext *context, Expr *expr, case EXPR_TRY_UNWRAP: case EXPR_TRY_UNWRAP_CHAIN: case EXPR_TYPEID_INFO: + case EXPR_FLOAT_TO_INT: + case EXPR_INT_TO_FLOAT: UNREACHABLE case EXPR_MAKE_ANY: if (!sema_analyse_expr(context, expr->make_any_expr.typeid)) return false; diff --git a/src/compiler/sema_liveness.c b/src/compiler/sema_liveness.c index 0d22eb44b..6b8a5824d 100644 --- a/src/compiler/sema_liveness.c +++ b/src/compiler/sema_liveness.c @@ -330,6 +330,8 @@ RETRY: case EXPR_RETHROW: case EXPR_OPTIONAL: case EXPR_PTR_ACCESS: + case EXPR_FLOAT_TO_INT: + case EXPR_INT_TO_FLOAT: case EXPR_SLICE_LEN: case EXPR_VECTOR_FROM_ARRAY: case EXPR_RVALUE: diff --git a/src/compiler/sema_stmts.c b/src/compiler/sema_stmts.c index d98c76db1..dca3d320f 100644 --- a/src/compiler/sema_stmts.c +++ b/src/compiler/sema_stmts.c @@ -765,6 +765,8 @@ static inline bool sema_expr_valid_try_expression(Expr *expr) case EXPR_EXT_TRUNC: case EXPR_INT_TO_BOOL: case EXPR_PTR_ACCESS: + case EXPR_FLOAT_TO_INT: + case EXPR_INT_TO_FLOAT: case EXPR_SLICE_LEN: case EXPR_VECTOR_FROM_ARRAY: case EXPR_RVALUE: