| author | |
| committer | |
| log | e74a7264ad3b221dfef0c959c1fdd6275f7c70ef |
| tree | 915b1d379b4dbe803f89d26242ba1d876229a9fa |
| parent | 954afe5d9a5ae634f7db22641ebac6e755cdaba7 |
6 files changed, 90 insertions(+), 0 deletions(-)
src/all_types.hpp+2| ... | ... | @@ -347,6 +347,8 @@ enum CastOp { |
| 347 | 347 | CastOpPureErrorWrap, |
| 348 | 348 | CastOpPointerReinterpret, |
| 349 | 349 | CastOpErrToInt, |
| 350 | CastOpIntToFloat, | |
| 351 | CastOpFloatToInt, | |
| 350 | 352 | }; |
| 351 | 353 | |
| 352 | 354 | struct AstNodeFnCallExpr { |
src/analyze.cpp+26| ... | ... | @@ -3417,6 +3417,14 @@ static void eval_const_expr_implicit_cast(CodeGen *g, AstNode *node, AstNode *ex |
| 3417 | 3417 | const_val->ok = true; |
| 3418 | 3418 | break; |
| 3419 | 3419 | } |
| 3420 | case CastOpIntToFloat: | |
| 3421 | bignum_cast_to_float(&const_val->data.x_bignum, &other_val->data.x_bignum); | |
| 3422 | const_val->ok = true; | |
| 3423 | break; | |
| 3424 | case CastOpFloatToInt: | |
| 3425 | bignum_cast_to_int(&const_val->data.x_bignum, &other_val->data.x_bignum); | |
| 3426 | const_val->ok = true; | |
| 3427 | break; | |
| 3420 | 3428 | } |
| 3421 | 3429 | } |
| 3422 | 3430 | |
| ... | ... | @@ -3478,6 +3486,24 @@ static TypeTableEntry *analyze_cast_expr(CodeGen *g, ImportTableEntry *import, B |
| 3478 | 3486 | return wanted_type; |
| 3479 | 3487 | } |
| 3480 | 3488 | |
| 3489 | // explicit cast from int to float | |
| 3490 | if (wanted_type->id == TypeTableEntryIdFloat && | |
| 3491 | actual_type->id == TypeTableEntryIdInt) | |
| 3492 | { | |
| 3493 | node->data.fn_call_expr.cast_op = CastOpIntToFloat; | |
| 3494 | eval_const_expr_implicit_cast(g, node, expr_node); | |
| 3495 | return wanted_type; | |
| 3496 | } | |
| 3497 | ||
| 3498 | // explicit cast from float to int | |
| 3499 | if (wanted_type->id == TypeTableEntryIdInt && | |
| 3500 | actual_type->id == TypeTableEntryIdFloat) | |
| 3501 | { | |
| 3502 | node->data.fn_call_expr.cast_op = CastOpFloatToInt; | |
| 3503 | eval_const_expr_implicit_cast(g, node, expr_node); | |
| 3504 | return wanted_type; | |
| 3505 | } | |
| 3506 | ||
| 3481 | 3507 | // explicit cast from fixed size array to unknown size array |
| 3482 | 3508 | if (wanted_type->id == TypeTableEntryIdStruct && |
| 3483 | 3509 | wanted_type->data.structure.is_unknown_size_array && |
src/bignum.cpp+24| ... | ... | @@ -120,6 +120,30 @@ void bignum_negate(BigNum *dest, BigNum *op) { |
| 120 | 120 | } |
| 121 | 121 | } |
| 122 | 122 | |
| 123 | void bignum_cast_to_float(BigNum *dest, BigNum *op) { | |
| 124 | assert(op->kind == BigNumKindInt); | |
| 125 | dest->kind = BigNumKindFloat; | |
| 126 | ||
| 127 | dest->data.x_float = op->data.x_uint; | |
| 128 | ||
| 129 | if (op->is_negative) { | |
| 130 | dest->data.x_float = -dest->data.x_float; | |
| 131 | } | |
| 132 | } | |
| 133 | ||
| 134 | void bignum_cast_to_int(BigNum *dest, BigNum *op) { | |
| 135 | assert(op->kind == BigNumKindFloat); | |
| 136 | dest->kind = BigNumKindInt; | |
| 137 | ||
| 138 | if (op->data.x_float >= 0) { | |
| 139 | dest->data.x_uint = op->data.x_float; | |
| 140 | dest->is_negative = false; | |
| 141 | } else { | |
| 142 | dest->data.x_uint = -op->data.x_float; | |
| 143 | dest->is_negative = true; | |
| 144 | } | |
| 145 | } | |
| 146 | ||
| 123 | 147 | bool bignum_sub(BigNum *dest, BigNum *op1, BigNum *op2) { |
| 124 | 148 | BigNum op2_negated; |
| 125 | 149 | bignum_negate(&op2_negated, op2); |
src/bignum.hpp+2| ... | ... | @@ -44,6 +44,8 @@ bool bignum_shl(BigNum *dest, BigNum *op1, BigNum *op2); |
| 44 | 44 | bool bignum_shr(BigNum *dest, BigNum *op1, BigNum *op2); |
| 45 | 45 | |
| 46 | 46 | void bignum_negate(BigNum *dest, BigNum *op); |
| 47 | void bignum_cast_to_float(BigNum *dest, BigNum *op); | |
| 48 | void bignum_cast_to_int(BigNum *dest, BigNum *op); | |
| 47 | 49 | |
| 48 | 50 | // returns the result of the comparison |
| 49 | 51 | bool bignum_cmp_eq(BigNum *op1, BigNum *op2); |
src/codegen.cpp+19| ... | ... | @@ -478,6 +478,25 @@ static LLVMValueRef gen_cast_expr(CodeGen *g, AstNode *node) { |
| 478 | 478 | |
| 479 | 479 | return cast_expr->tmp_ptr; |
| 480 | 480 | } |
| 481 | case CastOpIntToFloat: | |
| 482 | assert(actual_type->id == TypeTableEntryIdInt); | |
| 483 | if (actual_type->data.integral.is_signed) { | |
| 484 | add_debug_source_node(g, node); | |
| 485 | return LLVMBuildSIToFP(g->builder, expr_val, wanted_type->type_ref, ""); | |
| 486 | } else { | |
| 487 | add_debug_source_node(g, node); | |
| 488 | return LLVMBuildUIToFP(g->builder, expr_val, wanted_type->type_ref, ""); | |
| 489 | } | |
| 490 | case CastOpFloatToInt: | |
| 491 | assert(wanted_type->id == TypeTableEntryIdInt); | |
| 492 | if (wanted_type->data.integral.is_signed) { | |
| 493 | add_debug_source_node(g, node); | |
| 494 | return LLVMBuildFPToSI(g->builder, expr_val, wanted_type->type_ref, ""); | |
| 495 | } else { | |
| 496 | add_debug_source_node(g, node); | |
| 497 | return LLVMBuildFPToUI(g->builder, expr_val, wanted_type->type_ref, ""); | |
| 498 | } | |
| 499 | ||
| 481 | 500 | } |
| 482 | 501 | zig_unreachable(); |
| 483 | 502 | } |
test/run_tests.cpp+17| ... | ... | @@ -1483,6 +1483,23 @@ export fn main(args: c_int, argv: &&u8) -> c_int { |
| 1483 | 1483 | return 0; |
| 1484 | 1484 | } |
| 1485 | 1485 | )SOURCE", ""); |
| 1486 | ||
| 1487 | ||
| 1488 | ||
| 1489 | add_simple_case("casting between float and integer types", R"SOURCE( | |
| 1490 | #link("c") | |
| 1491 | export executable "test"; | |
| 1492 | c_import { | |
| 1493 | @c_include("stdio.h"); | |
| 1494 | } | |
| 1495 | export fn main(argc: c_int, argv: &&u8) -> c_int { | |
| 1496 | const x : f64 = 3.25; | |
| 1497 | const y = i32(x); | |
| 1498 | const z = f64(y); | |
| 1499 | printf(c"%.2f\n%d\n%.2f\n", x, y, z); | |
| 1500 | return 0; | |
| 1501 | } | |
| 1502 | )SOURCE", "3.25\n3\n3.00\n"); | |
| 1486 | 1503 | } |
| 1487 | 1504 | |
| 1488 | 1505 |