authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-01-31 21:05:17-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-01-31 21:05:17-07:00
loge74a7264ad3b221dfef0c959c1fdd6275f7c70ef
tree915b1d379b4dbe803f89d26242ba1d876229a9fa
parent954afe5d9a5ae634f7db22641ebac6e755cdaba7

support casting between int and float types


6 files changed, 90 insertions(+), 0 deletions(-)

src/all_types.hpp+2
...@@ -347,6 +347,8 @@ enum CastOp {...@@ -347,6 +347,8 @@ enum CastOp {
347 CastOpPureErrorWrap,347 CastOpPureErrorWrap,
348 CastOpPointerReinterpret,348 CastOpPointerReinterpret,
349 CastOpErrToInt,349 CastOpErrToInt,
350 CastOpIntToFloat,
351 CastOpFloatToInt,
350};352};
351353
352struct AstNodeFnCallExpr {354struct AstNodeFnCallExpr {
src/analyze.cpp+26
...@@ -3417,6 +3417,14 @@ static void eval_const_expr_implicit_cast(CodeGen *g, AstNode *node, AstNode *ex...@@ -3417,6 +3417,14 @@ static void eval_const_expr_implicit_cast(CodeGen *g, AstNode *node, AstNode *ex
3417 const_val->ok = true;3417 const_val->ok = true;
3418 break;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}
34223430
...@@ -3478,6 +3486,24 @@ static TypeTableEntry *analyze_cast_expr(CodeGen *g, ImportTableEntry *import, B...@@ -3478,6 +3486,24 @@ static TypeTableEntry *analyze_cast_expr(CodeGen *g, ImportTableEntry *import, B
3478 return wanted_type;3486 return wanted_type;
3479 }3487 }
34803488
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 // explicit cast from fixed size array to unknown size array3507 // explicit cast from fixed size array to unknown size array
3482 if (wanted_type->id == TypeTableEntryIdStruct &&3508 if (wanted_type->id == TypeTableEntryIdStruct &&
3483 wanted_type->data.structure.is_unknown_size_array &&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,6 +120,30 @@ void bignum_negate(BigNum *dest, BigNum *op) {
120 }120 }
121}121}
122122
123void 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
134void 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
123bool bignum_sub(BigNum *dest, BigNum *op1, BigNum *op2) {147bool bignum_sub(BigNum *dest, BigNum *op1, BigNum *op2) {
124 BigNum op2_negated;148 BigNum op2_negated;
125 bignum_negate(&op2_negated, op2);149 bignum_negate(&op2_negated, op2);
src/bignum.hpp+2
...@@ -44,6 +44,8 @@ bool bignum_shl(BigNum *dest, BigNum *op1, BigNum *op2);...@@ -44,6 +44,8 @@ bool bignum_shl(BigNum *dest, BigNum *op1, BigNum *op2);
44bool bignum_shr(BigNum *dest, BigNum *op1, BigNum *op2);44bool bignum_shr(BigNum *dest, BigNum *op1, BigNum *op2);
4545
46void bignum_negate(BigNum *dest, BigNum *op);46void bignum_negate(BigNum *dest, BigNum *op);
47void bignum_cast_to_float(BigNum *dest, BigNum *op);
48void bignum_cast_to_int(BigNum *dest, BigNum *op);
4749
48// returns the result of the comparison50// returns the result of the comparison
49bool bignum_cmp_eq(BigNum *op1, BigNum *op2);51bool 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,6 +478,25 @@ static LLVMValueRef gen_cast_expr(CodeGen *g, AstNode *node) {
478478
479 return cast_expr->tmp_ptr;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 zig_unreachable();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,6 +1483,23 @@ export fn main(args: c_int, argv: &&u8) -> c_int {
1483 return 0;1483 return 0;
1484}1484}
1485 )SOURCE", "");1485 )SOURCE", "");
1486
1487
1488
1489 add_simple_case("casting between float and integer types", R"SOURCE(
1490#link("c")
1491export executable "test";
1492c_import {
1493 @c_include("stdio.h");
1494}
1495export 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}
14871504
14881505