Skip to content

Commit b45d973

Browse files
committed
Rewrite trans_cast, float->float and float->int casts
1 parent 5864d4e commit b45d973

File tree

4 files changed

+73
-50
lines changed

4 files changed

+73
-50
lines changed

src/comp/lib/llvm.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1543,6 +1543,16 @@ fn type_to_str_inner(type_names names, &TypeRef[] outer0, TypeRef ty) -> str {
15431543
}
15441544
}
15451545

1546+
fn float_width(TypeRef llt) -> uint {
1547+
ret alt llvm::LLVMGetTypeKind(llt) {
1548+
1 { 32u }
1549+
2 { 64u }
1550+
3 { 80u }
1551+
4 | 5 { 128u }
1552+
_ { fail "llvm_float_width called on a non-float type"; 0u }
1553+
};
1554+
}
1555+
15461556
fn fn_ty_param_tys(TypeRef fn_ty) -> TypeRef[] {
15471557
auto args = ivec::init_elt(0 as TypeRef,
15481558
llvm::LLVMCountParamTypes(fn_ty));

src/comp/middle/trans.rs

Lines changed: 62 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -4403,60 +4403,73 @@ fn trans_lval(&@block_ctxt cx, &@ast::expr e) -> lval_result {
44034403

44044404
fn int_cast(&@block_ctxt bcx, TypeRef lldsttype, TypeRef llsrctype,
44054405
ValueRef llsrc, bool signed) -> ValueRef {
4406-
if (llvm::LLVMGetIntTypeWidth(lldsttype) >
4407-
llvm::LLVMGetIntTypeWidth(llsrctype)) {
4408-
if (signed) {
4409-
// Widening signed cast.
4410-
4411-
ret bcx.build.SExtOrBitCast(llsrc, lldsttype);
4412-
}
4413-
// Widening unsigned cast.
4406+
auto srcsz = llvm::LLVMGetIntTypeWidth(llsrctype);
4407+
auto dstsz = llvm::LLVMGetIntTypeWidth(lldsttype);
4408+
ret if dstsz == srcsz { bcx.build.BitCast(llsrc, lldsttype) }
4409+
else if srcsz > dstsz { bcx.build.TruncOrBitCast(llsrc, lldsttype) }
4410+
else if signed { bcx.build.SExtOrBitCast(llsrc, lldsttype) }
4411+
else { bcx.build.ZExtOrBitCast(llsrc, lldsttype) };
4412+
}
44144413

4415-
ret bcx.build.ZExtOrBitCast(llsrc, lldsttype);
4416-
}
4417-
ret bcx.build.TruncOrBitCast(llsrc, lldsttype);
4414+
fn float_cast(&@block_ctxt bcx, TypeRef lldsttype, TypeRef llsrctype,
4415+
ValueRef llsrc) -> ValueRef {
4416+
auto srcsz = lib::llvm::float_width(llsrctype);
4417+
auto dstsz = lib::llvm::float_width(lldsttype);
4418+
ret if dstsz > srcsz { bcx.build.FPExt(llsrc, lldsttype) }
4419+
else if srcsz > dstsz { bcx.build.FPTrunc(llsrc, lldsttype) }
4420+
else { llsrc };
44184421
}
44194422

44204423
fn trans_cast(&@block_ctxt cx, &@ast::expr e, ast::node_id id) -> result {
4424+
auto ccx = cx.fcx.lcx.ccx;
44214425
auto e_res = trans_expr(cx, e);
4422-
auto llsrctype = val_ty(e_res.val);
4423-
auto t = node_id_type(cx.fcx.lcx.ccx, id);
4424-
auto lldsttype = type_of(cx.fcx.lcx.ccx, e.span, t);
4425-
if (!ty::type_is_fp(cx.fcx.lcx.ccx.tcx, t)) {
4426-
4427-
// TODO: native-to-native casts
4428-
if (ty::type_is_native(cx.fcx.lcx.ccx.tcx,
4429-
ty::expr_ty(cx.fcx.lcx.ccx.tcx, e))) {
4430-
e_res =
4431-
rslt(e_res.bcx,
4432-
e_res.bcx.build.PtrToInt(e_res.val, lldsttype));
4433-
} else if (ty::type_is_native(cx.fcx.lcx.ccx.tcx, t)) {
4434-
e_res =
4435-
rslt(e_res.bcx,
4436-
e_res.bcx.build.IntToPtr(e_res.val, lldsttype));
4437-
} else {
4438-
e_res =
4439-
rslt(e_res.bcx,
4440-
int_cast(e_res.bcx, lldsttype, llsrctype, e_res.val,
4441-
ty::type_is_signed(cx.fcx.lcx.ccx.tcx, t)));
4442-
}
4443-
}
4444-
else {
4445-
if (ty::type_is_integral(cx.fcx.lcx.ccx.tcx,
4446-
ty::expr_ty(cx.fcx.lcx.ccx.tcx, e))) {
4447-
if (ty::type_is_signed(cx.fcx.lcx.ccx.tcx,
4448-
ty::expr_ty(cx.fcx.lcx.ccx.tcx, e))) {
4449-
e_res = rslt(e_res.bcx,
4450-
e_res.bcx.build.SIToFP(e_res.val, lldsttype));
4451-
}
4452-
else {
4453-
e_res = rslt(e_res.bcx,
4454-
e_res.bcx.build.UIToFP(e_res.val, lldsttype));
4455-
}
4456-
}
4457-
else { cx.fcx.lcx.ccx.sess.unimpl("fp cast"); }
4458-
}
4459-
ret e_res;
4426+
auto ll_t_in = val_ty(e_res.val);
4427+
auto t_in = ty::expr_ty(ccx.tcx, e);
4428+
auto t_out = node_id_type(ccx, id);
4429+
auto ll_t_out = type_of(ccx, e.span, t_out);
4430+
4431+
tag kind { native_; integral; float; other; }
4432+
fn t_kind(&ty::ctxt tcx, ty::t t) -> kind {
4433+
ret if ty::type_is_fp(tcx, t) { float }
4434+
else if ty::type_is_native(tcx, t) { native_ }
4435+
else if ty::type_is_integral(tcx, t) { integral }
4436+
else { other };
4437+
}
4438+
auto k_in = t_kind(ccx.tcx, t_in);
4439+
auto k_out = t_kind(ccx.tcx, t_out);
4440+
auto s_in = k_in == integral && ty::type_is_signed(ccx.tcx, t_in);
4441+
4442+
auto newval = alt rec(in=k_in, out=k_out) {
4443+
{in: integral, out: integral} {
4444+
int_cast(e_res.bcx, ll_t_out, ll_t_in, e_res.val, s_in)
4445+
}
4446+
{in: float, out: float} {
4447+
float_cast(e_res.bcx, ll_t_out, ll_t_in, e_res.val)
4448+
}
4449+
{in: integral, out: float} {
4450+
if s_in { e_res.bcx.build.SIToFP(e_res.val, ll_t_out) }
4451+
else { e_res.bcx.build.UIToFP(e_res.val, ll_t_out) }
4452+
}
4453+
{in: float, out: integral} {
4454+
if ty::type_is_signed(ccx.tcx, t_out) {
4455+
e_res.bcx.build.FPToSI(e_res.val, ll_t_out)
4456+
} else { e_res.bcx.build.FPToUI(e_res.val, ll_t_out) }
4457+
}
4458+
{in: integral, out: native_} {
4459+
e_res.bcx.build.IntToPtr(e_res.val, ll_t_out)
4460+
}
4461+
{in: native_, out: integral} {
4462+
e_res.bcx.build.PtrToInt(e_res.val, ll_t_out)
4463+
}
4464+
{in: native_, out: native_} {
4465+
e_res.bcx.build.PointerCast(e_res.val, ll_t_out)
4466+
}
4467+
_ {
4468+
ccx.sess.bug("Translating unsupported cast.");
4469+
C_nil() // FIXME the typechecker doesn't seem to understand _|_ here
4470+
}
4471+
};
4472+
ret rslt(e_res.bcx, newval);
44604473
}
44614474

44624475
fn trans_bind_thunk(&@local_ctxt cx, &span sp, &ty::t incoming_fty,

src/comp/middle/trans_common.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -456,7 +456,6 @@ fn T_int() -> TypeRef {
456456

457457
fn T_float() -> TypeRef {
458458
// FIXME: switch on target type.
459-
460459
ret T_f64();
461460
}
462461

src/comp/middle/ty.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1158,6 +1158,7 @@ fn type_is_integral(&ctxt cx, &t ty) -> bool {
11581158
}
11591159
}
11601160
case (ty_char) { ret true; }
1161+
case (ty_bool) { ret true; }
11611162
case (_) { ret false; }
11621163
}
11631164
}

0 commit comments

Comments
 (0)