authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-01-31 21:22:05-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-01-31 21:22:05-07:00
loga4e19f94f10445273b977e21e721d236a37c5cf4
tree842e06c40599c418b67553dfa6859c3dfcf220bc
parente74a7264ad3b221dfef0c959c1fdd6275f7c70ef

support casting between floats


4 files changed, 47 insertions(+), 14 deletions(-)

src/all_types.hpp+1-1
...@@ -340,7 +340,7 @@ enum CastOp {...@@ -340,7 +340,7 @@ enum CastOp {
340 CastOpNoop, // fn call expr is a cast, but does nothing340 CastOpNoop, // fn call expr is a cast, but does nothing
341 CastOpPtrToInt,341 CastOpPtrToInt,
342 CastOpIntToPtr,342 CastOpIntToPtr,
343 CastOpIntWidenOrShorten,343 CastOpWidenOrShorten,
344 CastOpToUnknownSizeArray,344 CastOpToUnknownSizeArray,
345 CastOpMaybeWrap,345 CastOpMaybeWrap,
346 CastOpErrorWrap,346 CastOpErrorWrap,
src/analyze.cpp+15-5
...@@ -1681,6 +1681,14 @@ static bool types_match_with_implicit_cast(CodeGen *g, TypeTableEntry *expected_...@@ -1681,6 +1681,14 @@ static bool types_match_with_implicit_cast(CodeGen *g, TypeTableEntry *expected_
1681 return true;1681 return true;
1682 }1682 }
16831683
1684 // implicit float widening conversion
1685 if (expected_type->id == TypeTableEntryIdFloat &&
1686 actual_type->id == TypeTableEntryIdFloat &&
1687 expected_type->size_in_bits >= actual_type->size_in_bits)
1688 {
1689 return true;
1690 }
1691
1684 // implicit constant sized array to unknown size array conversion1692 // implicit constant sized array to unknown size array conversion
1685 if (expected_type->id == TypeTableEntryIdStruct &&1693 if (expected_type->id == TypeTableEntryIdStruct &&
1686 expected_type->data.structure.is_unknown_size_array &&1694 expected_type->data.structure.is_unknown_size_array &&
...@@ -3366,7 +3374,7 @@ static void eval_const_expr_implicit_cast(CodeGen *g, AstNode *node, AstNode *ex...@@ -3366,7 +3374,7 @@ static void eval_const_expr_implicit_cast(CodeGen *g, AstNode *node, AstNode *ex
3366 case CastOpNoCast:3374 case CastOpNoCast:
3367 zig_unreachable();3375 zig_unreachable();
3368 case CastOpNoop:3376 case CastOpNoop:
3369 case CastOpIntWidenOrShorten:3377 case CastOpWidenOrShorten:
3370 case CastOpPointerReinterpret:3378 case CastOpPointerReinterpret:
3371 *const_val = *other_val;3379 *const_val = *other_val;
3372 break;3380 break;
...@@ -3477,11 +3485,13 @@ static TypeTableEntry *analyze_cast_expr(CodeGen *g, ImportTableEntry *import, B...@@ -3477,11 +3485,13 @@ static TypeTableEntry *analyze_cast_expr(CodeGen *g, ImportTableEntry *import, B
3477 return wanted_type;3485 return wanted_type;
3478 }3486 }
34793487
3480 // explicit cast from any int to any other int3488 // explicit widening or shortening cast
3481 if (wanted_type->id == TypeTableEntryIdInt &&3489 if ((wanted_type->id == TypeTableEntryIdInt &&
3482 actual_type->id == TypeTableEntryIdInt)3490 actual_type->id == TypeTableEntryIdInt) ||
3491 (wanted_type->id == TypeTableEntryIdFloat &&
3492 actual_type->id == TypeTableEntryIdFloat))
3483 {3493 {
3484 node->data.fn_call_expr.cast_op = CastOpIntWidenOrShorten;3494 node->data.fn_call_expr.cast_op = CastOpWidenOrShorten;
3485 eval_const_expr_implicit_cast(g, node, expr_node);3495 eval_const_expr_implicit_cast(g, node, expr_node);
3486 return wanted_type;3496 return wanted_type;
3487 }3497 }
src/codegen.cpp+23-7
...@@ -349,20 +349,36 @@ static LLVMValueRef gen_enum_value_expr(CodeGen *g, AstNode *node, TypeTableEntr...@@ -349,20 +349,36 @@ static LLVMValueRef gen_enum_value_expr(CodeGen *g, AstNode *node, TypeTableEntr
349static LLVMValueRef gen_widen_or_shorten(CodeGen *g, AstNode *source_node, TypeTableEntry *actual_type,349static LLVMValueRef gen_widen_or_shorten(CodeGen *g, AstNode *source_node, TypeTableEntry *actual_type,
350 TypeTableEntry *wanted_type, LLVMValueRef expr_val)350 TypeTableEntry *wanted_type, LLVMValueRef expr_val)
351{351{
352 assert(actual_type->id == wanted_type->id);
352 if (actual_type->size_in_bits == wanted_type->size_in_bits) {353 if (actual_type->size_in_bits == wanted_type->size_in_bits) {
353 return expr_val;354 return expr_val;
354 } else if (actual_type->size_in_bits < wanted_type->size_in_bits) {355 } else if (actual_type->size_in_bits < wanted_type->size_in_bits) {
355 if (actual_type->data.integral.is_signed) {356 if (actual_type->id == TypeTableEntryIdFloat) {
356 add_debug_source_node(g, source_node);357 add_debug_source_node(g, source_node);
357 return LLVMBuildSExt(g->builder, expr_val, wanted_type->type_ref, "");358 return LLVMBuildFPExt(g->builder, expr_val, wanted_type->type_ref, "");
359 } else if (actual_type->id == TypeTableEntryIdInt) {
360 if (actual_type->data.integral.is_signed) {
361 add_debug_source_node(g, source_node);
362 return LLVMBuildSExt(g->builder, expr_val, wanted_type->type_ref, "");
363 } else {
364 add_debug_source_node(g, source_node);
365 return LLVMBuildZExt(g->builder, expr_val, wanted_type->type_ref, "");
366 }
358 } else {367 } else {
368 zig_unreachable();
369 }
370 } else if (actual_type->size_in_bits > wanted_type->size_in_bits) {
371 if (actual_type->id == TypeTableEntryIdFloat) {
359 add_debug_source_node(g, source_node);372 add_debug_source_node(g, source_node);
360 return LLVMBuildZExt(g->builder, expr_val, wanted_type->type_ref, "");373 return LLVMBuildFPTrunc(g->builder, expr_val, wanted_type->type_ref, "");
374 } else if (actual_type->id == TypeTableEntryIdInt) {
375 add_debug_source_node(g, source_node);
376 return LLVMBuildTrunc(g->builder, expr_val, wanted_type->type_ref, "");
377 } else {
378 zig_unreachable();
361 }379 }
362 } else {380 } else {
363 assert(actual_type->size_in_bits > wanted_type->size_in_bits);381 zig_unreachable();
364 add_debug_source_node(g, source_node);
365 return LLVMBuildTrunc(g->builder, expr_val, wanted_type->type_ref, "");
366 }382 }
367}383}
368384
...@@ -455,7 +471,7 @@ static LLVMValueRef gen_cast_expr(CodeGen *g, AstNode *node) {...@@ -455,7 +471,7 @@ static LLVMValueRef gen_cast_expr(CodeGen *g, AstNode *node) {
455 case CastOpPointerReinterpret:471 case CastOpPointerReinterpret:
456 add_debug_source_node(g, node);472 add_debug_source_node(g, node);
457 return LLVMBuildBitCast(g->builder, expr_val, wanted_type->type_ref, "");473 return LLVMBuildBitCast(g->builder, expr_val, wanted_type->type_ref, "");
458 case CastOpIntWidenOrShorten:474 case CastOpWidenOrShorten:
459 return gen_widen_or_shorten(g, node, actual_type, wanted_type, expr_val);475 return gen_widen_or_shorten(g, node, actual_type, wanted_type, expr_val);
460 case CastOpToUnknownSizeArray:476 case CastOpToUnknownSizeArray:
461 {477 {
test/run_tests.cpp+8-1
...@@ -1493,7 +1493,8 @@ c_import {...@@ -1493,7 +1493,8 @@ c_import {
1493 @c_include("stdio.h");1493 @c_include("stdio.h");
1494}1494}
1495export fn main(argc: c_int, argv: &&u8) -> c_int {1495export fn main(argc: c_int, argv: &&u8) -> c_int {
1496 const x : f64 = 3.25;1496 const small: f32 = 3.25;
1497 const x: f64 = small;
1497 const y = i32(x);1498 const y = i32(x);
1498 const z = f64(y);1499 const z = f64(y);
1499 printf(c"%.2f\n%d\n%.2f\n", x, y, z);1500 printf(c"%.2f\n%d\n%.2f\n", x, y, z);
...@@ -1945,6 +1946,12 @@ pub fn a(x: i32) -> i32 {x + 0}...@@ -1945,6 +1946,12 @@ pub fn a(x: i32) -> i32 {x + 0}
1945pub fn b(x: i32) -> i32 {x + 1}1946pub fn b(x: i32) -> i32 {x + 1}
1946export fn c(x: i32) -> i32 {x + 2}1947export fn c(x: i32) -> i32 {x + 2}
1947 )SOURCE", 1, ".tmp_source.zig:2:37: error: expected type 'fn(i32) -> i32', got 'extern fn(i32) -> i32'");1948 )SOURCE", 1, ".tmp_source.zig:2:37: error: expected type 'fn(i32) -> i32', got 'extern fn(i32) -> i32'");
1949
1950
1951 add_compile_fail_case("implicit cast from f64 to f32", R"SOURCE(
1952const x : f64 = 1.0;
1953const y : f32 = x;
1954 )SOURCE", 1, ".tmp_source.zig:3:17: error: expected type 'f32', got 'f64'");
1948}1955}
19491956
1950//////////////////////////////////////////////////////////////////////////////1957//////////////////////////////////////////////////////////////////////////////