support casting between int and float types
This commit is contained in:
parent
954afe5d9a
commit
e74a7264ad
@ -347,6 +347,8 @@ enum CastOp {
|
||||
CastOpPureErrorWrap,
|
||||
CastOpPointerReinterpret,
|
||||
CastOpErrToInt,
|
||||
CastOpIntToFloat,
|
||||
CastOpFloatToInt,
|
||||
};
|
||||
|
||||
struct AstNodeFnCallExpr {
|
||||
|
@ -3417,6 +3417,14 @@ static void eval_const_expr_implicit_cast(CodeGen *g, AstNode *node, AstNode *ex
|
||||
const_val->ok = true;
|
||||
break;
|
||||
}
|
||||
case CastOpIntToFloat:
|
||||
bignum_cast_to_float(&const_val->data.x_bignum, &other_val->data.x_bignum);
|
||||
const_val->ok = true;
|
||||
break;
|
||||
case CastOpFloatToInt:
|
||||
bignum_cast_to_int(&const_val->data.x_bignum, &other_val->data.x_bignum);
|
||||
const_val->ok = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -3478,6 +3486,24 @@ static TypeTableEntry *analyze_cast_expr(CodeGen *g, ImportTableEntry *import, B
|
||||
return wanted_type;
|
||||
}
|
||||
|
||||
// explicit cast from int to float
|
||||
if (wanted_type->id == TypeTableEntryIdFloat &&
|
||||
actual_type->id == TypeTableEntryIdInt)
|
||||
{
|
||||
node->data.fn_call_expr.cast_op = CastOpIntToFloat;
|
||||
eval_const_expr_implicit_cast(g, node, expr_node);
|
||||
return wanted_type;
|
||||
}
|
||||
|
||||
// explicit cast from float to int
|
||||
if (wanted_type->id == TypeTableEntryIdInt &&
|
||||
actual_type->id == TypeTableEntryIdFloat)
|
||||
{
|
||||
node->data.fn_call_expr.cast_op = CastOpFloatToInt;
|
||||
eval_const_expr_implicit_cast(g, node, expr_node);
|
||||
return wanted_type;
|
||||
}
|
||||
|
||||
// explicit cast from fixed size array to unknown size array
|
||||
if (wanted_type->id == TypeTableEntryIdStruct &&
|
||||
wanted_type->data.structure.is_unknown_size_array &&
|
||||
|
@ -120,6 +120,30 @@ void bignum_negate(BigNum *dest, BigNum *op) {
|
||||
}
|
||||
}
|
||||
|
||||
void bignum_cast_to_float(BigNum *dest, BigNum *op) {
|
||||
assert(op->kind == BigNumKindInt);
|
||||
dest->kind = BigNumKindFloat;
|
||||
|
||||
dest->data.x_float = op->data.x_uint;
|
||||
|
||||
if (op->is_negative) {
|
||||
dest->data.x_float = -dest->data.x_float;
|
||||
}
|
||||
}
|
||||
|
||||
void bignum_cast_to_int(BigNum *dest, BigNum *op) {
|
||||
assert(op->kind == BigNumKindFloat);
|
||||
dest->kind = BigNumKindInt;
|
||||
|
||||
if (op->data.x_float >= 0) {
|
||||
dest->data.x_uint = op->data.x_float;
|
||||
dest->is_negative = false;
|
||||
} else {
|
||||
dest->data.x_uint = -op->data.x_float;
|
||||
dest->is_negative = true;
|
||||
}
|
||||
}
|
||||
|
||||
bool bignum_sub(BigNum *dest, BigNum *op1, BigNum *op2) {
|
||||
BigNum op2_negated;
|
||||
bignum_negate(&op2_negated, op2);
|
||||
|
@ -44,6 +44,8 @@ bool bignum_shl(BigNum *dest, BigNum *op1, BigNum *op2);
|
||||
bool bignum_shr(BigNum *dest, BigNum *op1, BigNum *op2);
|
||||
|
||||
void bignum_negate(BigNum *dest, BigNum *op);
|
||||
void bignum_cast_to_float(BigNum *dest, BigNum *op);
|
||||
void bignum_cast_to_int(BigNum *dest, BigNum *op);
|
||||
|
||||
// returns the result of the comparison
|
||||
bool bignum_cmp_eq(BigNum *op1, BigNum *op2);
|
||||
|
@ -478,6 +478,25 @@ static LLVMValueRef gen_cast_expr(CodeGen *g, AstNode *node) {
|
||||
|
||||
return cast_expr->tmp_ptr;
|
||||
}
|
||||
case CastOpIntToFloat:
|
||||
assert(actual_type->id == TypeTableEntryIdInt);
|
||||
if (actual_type->data.integral.is_signed) {
|
||||
add_debug_source_node(g, node);
|
||||
return LLVMBuildSIToFP(g->builder, expr_val, wanted_type->type_ref, "");
|
||||
} else {
|
||||
add_debug_source_node(g, node);
|
||||
return LLVMBuildUIToFP(g->builder, expr_val, wanted_type->type_ref, "");
|
||||
}
|
||||
case CastOpFloatToInt:
|
||||
assert(wanted_type->id == TypeTableEntryIdInt);
|
||||
if (wanted_type->data.integral.is_signed) {
|
||||
add_debug_source_node(g, node);
|
||||
return LLVMBuildFPToSI(g->builder, expr_val, wanted_type->type_ref, "");
|
||||
} else {
|
||||
add_debug_source_node(g, node);
|
||||
return LLVMBuildFPToUI(g->builder, expr_val, wanted_type->type_ref, "");
|
||||
}
|
||||
|
||||
}
|
||||
zig_unreachable();
|
||||
}
|
||||
|
@ -1483,6 +1483,23 @@ export fn main(args: c_int, argv: &&u8) -> c_int {
|
||||
return 0;
|
||||
}
|
||||
)SOURCE", "");
|
||||
|
||||
|
||||
|
||||
add_simple_case("casting between float and integer types", R"SOURCE(
|
||||
#link("c")
|
||||
export executable "test";
|
||||
c_import {
|
||||
@c_include("stdio.h");
|
||||
}
|
||||
export fn main(argc: c_int, argv: &&u8) -> c_int {
|
||||
const x : f64 = 3.25;
|
||||
const y = i32(x);
|
||||
const z = f64(y);
|
||||
printf(c"%.2f\n%d\n%.2f\n", x, y, z);
|
||||
return 0;
|
||||
}
|
||||
)SOURCE", "3.25\n3\n3.00\n");
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user