Skip to content

Commit 23a9dcd

Browse files
committed
Make CastKind::Misc handling more clean and general
1 parent be377f9 commit 23a9dcd

File tree

1 file changed

+74
-106
lines changed

1 file changed

+74
-106
lines changed

src/base.rs

Lines changed: 74 additions & 106 deletions
Original file line numberDiff line numberDiff line change
@@ -466,124 +466,92 @@ fn trans_stmt<'a, 'tcx: 'a>(
466466
Rvalue::Cast(CastKind::Misc, operand, to_ty) => {
467467
let operand = trans_operand(fx, operand);
468468
let from_ty = operand.layout().ty;
469-
match (&from_ty.sty, &to_ty.sty) {
470-
(ty::Ref(..), ty::Ref(..))
471-
| (ty::Ref(..), ty::RawPtr(..))
472-
| (ty::RawPtr(..), ty::Ref(..))
473-
| (ty::RawPtr(..), ty::RawPtr(..))
474-
| (ty::FnPtr(..), ty::RawPtr(..)) => {
475-
lval.write_cvalue(fx, operand.unchecked_cast_to(dest_layout));
476-
}
477-
(ty::RawPtr(..), ty::Uint(_))
478-
| (ty::RawPtr(..), ty::Int(_))
479-
| (ty::FnPtr(..), ty::Uint(_))
480-
if to_ty.sty == fx.tcx.types.usize.sty
481-
|| to_ty.sty == fx.tcx.types.isize.sty
482-
|| fx.clif_type(to_ty).unwrap() == pointer_ty(fx.tcx) =>
483-
{
484-
lval.write_cvalue(fx, operand.unchecked_cast_to(dest_layout));
485-
}
486-
(ty::Uint(_), ty::RawPtr(..)) if from_ty.sty == fx.tcx.types.usize.sty => {
487-
lval.write_cvalue(fx, operand.unchecked_cast_to(dest_layout));
488-
}
489-
(ty::Int(_), ty::RawPtr(..)) if from_ty.sty == fx.tcx.types.isize.sty => {
469+
470+
fn is_fat_ptr<'a, 'tcx: 'a>(fx: &FunctionCx<'a, 'tcx, impl Backend>, ty: Ty<'tcx>) -> bool {
471+
ty
472+
.builtin_deref(true)
473+
.map(|ty::TypeAndMut {ty: pointee_ty, mutbl: _ }| fx.layout_of(pointee_ty).is_unsized())
474+
.unwrap_or(false)
475+
}
476+
477+
if is_fat_ptr(fx, from_ty) {
478+
if is_fat_ptr(fx, to_ty) {
479+
// fat-ptr -> fat-ptr
490480
lval.write_cvalue(fx, operand.unchecked_cast_to(dest_layout));
481+
} else {
482+
// fat-ptr -> thin-ptr
483+
let (ptr, _extra) = operand.load_value_pair(fx);
484+
lval.write_cvalue(fx, CValue::ByVal(ptr, dest_layout))
491485
}
492-
(ty::Char, ty::Uint(_))
493-
| (ty::Uint(_), ty::Char)
494-
| (ty::Uint(_), ty::Int(_))
495-
| (ty::Uint(_), ty::Uint(_)) => {
496-
let from = operand.load_scalar(fx);
497-
let res = crate::common::clif_intcast(
498-
fx,
499-
from,
500-
fx.clif_type(to_ty).unwrap(),
501-
false,
502-
);
503-
lval.write_cvalue(fx, CValue::ByVal(res, dest_layout));
486+
} else if let ty::Adt(adt_def, _substs) = from_ty.sty {
487+
// enum -> discriminant value
488+
assert!(adt_def.is_enum());
489+
match to_ty.sty {
490+
ty::Uint(_) | ty::Int(_) => {},
491+
_ => unreachable!("cast adt {} -> {}", from_ty, to_ty),
504492
}
505-
(ty::Int(_), ty::Int(_)) | (ty::Int(_), ty::Uint(_)) => {
506-
let from = operand.load_scalar(fx);
507-
let res = crate::common::clif_intcast(
493+
494+
// FIXME avoid forcing to stack
495+
let place =
496+
CPlace::Addr(operand.force_stack(fx), None, operand.layout());
497+
let discr = trans_get_discriminant(fx, place, fx.layout_of(to_ty));
498+
lval.write_cvalue(fx, discr);
499+
} else {
500+
let from_clif_ty = fx.clif_type(from_ty).unwrap();
501+
let to_clif_ty = fx.clif_type(to_ty).unwrap();
502+
let from = operand.load_scalar(fx);
503+
504+
let signed = match from_ty.sty {
505+
ty::Ref(..) | ty::RawPtr(..) | ty::FnPtr(..) | ty::Char | ty::Uint(..) | ty::Bool => false,
506+
ty::Int(..) => true,
507+
ty::Float(..) => false, // `signed` is unused for floats
508+
_ => panic!("{}", from_ty),
509+
};
510+
511+
let res = if from_clif_ty.is_int() && to_clif_ty.is_int() {
512+
// int-like -> int-like
513+
crate::common::clif_intcast(
508514
fx,
509515
from,
510-
fx.clif_type(to_ty).unwrap(),
511-
true,
512-
);
513-
lval.write_cvalue(fx, CValue::ByVal(res, dest_layout));
514-
}
515-
(ty::Float(from_flt), ty::Float(to_flt)) => {
516-
let from = operand.load_scalar(fx);
517-
let res = match (from_flt, to_flt) {
518-
(FloatTy::F32, FloatTy::F64) => {
519-
fx.bcx.ins().fpromote(types::F64, from)
520-
}
521-
(FloatTy::F64, FloatTy::F32) => {
522-
fx.bcx.ins().fdemote(types::F32, from)
523-
}
524-
_ => from,
525-
};
526-
lval.write_cvalue(fx, CValue::ByVal(res, dest_layout));
527-
}
528-
(ty::Float(_), ty::Int(_)) => {
529-
let from = operand.load_scalar(fx);
530-
let i_type = fx.clif_type(to_ty).unwrap();
531-
let res = fx.bcx.ins().fcvt_to_sint_sat(i_type, from);
532-
lval.write_cvalue(fx, CValue::ByVal(res, dest_layout));
533-
}
534-
(ty::Float(_), ty::Uint(_)) => {
535-
let from = operand.load_scalar(fx);
536-
let i_type = fx.clif_type(to_ty).unwrap();
537-
let res = fx.bcx.ins().fcvt_to_uint_sat(i_type, from);
538-
lval.write_cvalue(fx, CValue::ByVal(res, dest_layout));
539-
}
540-
(ty::Int(_), ty::Float(_)) => {
541-
let from_ty = fx.clif_type(from_ty).unwrap();
542-
let from = operand.load_scalar(fx);
516+
to_clif_ty,
517+
signed,
518+
)
519+
} else if from_clif_ty.is_int() && to_clif_ty.is_float() {
520+
// int-like -> float
543521
// FIXME missing encoding for fcvt_from_sint.f32.i8
544-
let from = if from_ty == types::I8 || from_ty == types::I16 {
545-
fx.bcx.ins().sextend(types::I32, from)
546-
} else {
547-
from
548-
};
549-
let f_type = fx.clif_type(to_ty).unwrap();
550-
let res = fx.bcx.ins().fcvt_from_sint(f_type, from);
551-
lval.write_cvalue(fx, CValue::ByVal(res, dest_layout));
552-
}
553-
(ty::Uint(_), ty::Float(_)) => {
554-
let from_ty = fx.clif_type(from_ty).unwrap();
555-
let from = operand.load_scalar(fx);
556-
// FIXME missing encoding for fcvt_from_uint.f32.i8
557-
let from = if from_ty == types::I8 || from_ty == types::I16 {
522+
let from = if from_clif_ty == types::I8 || from_clif_ty == types::I16 {
558523
fx.bcx.ins().uextend(types::I32, from)
559524
} else {
560525
from
561526
};
562-
let f_type = fx.clif_type(to_ty).unwrap();
563-
let res = fx.bcx.ins().fcvt_from_uint(f_type, from);
564-
lval.write_cvalue(fx, CValue::ByVal(res, dest_layout));
565-
}
566-
(ty::Bool, ty::Uint(_)) | (ty::Bool, ty::Int(_)) => {
567-
let to_ty = fx.clif_type(to_ty).unwrap();
527+
if signed {
528+
fx.bcx.ins().fcvt_from_sint(to_clif_ty, from)
529+
} else {
530+
fx.bcx.ins().fcvt_from_uint(to_clif_ty, from)
531+
}
532+
} else if from_clif_ty.is_float() && to_clif_ty.is_int() {
533+
// float -> int-like
568534
let from = operand.load_scalar(fx);
569-
let res = if to_ty != types::I8 {
570-
fx.bcx.ins().uextend(to_ty, from)
535+
if signed {
536+
fx.bcx.ins().fcvt_to_sint_sat(to_clif_ty, from)
571537
} else {
572-
from
573-
};
574-
lval.write_cvalue(fx, CValue::ByVal(res, dest_layout));
575-
}
576-
(ty::Adt(adt_def, _substs), ty::Uint(_))
577-
| (ty::Adt(adt_def, _substs), ty::Int(_))
578-
if adt_def.is_enum() =>
579-
{
580-
// FIXME avoid forcing to stack
581-
let place =
582-
CPlace::Addr(operand.force_stack(fx), None, operand.layout());
583-
let discr = trans_get_discriminant(fx, place, fx.layout_of(to_ty));
584-
lval.write_cvalue(fx, discr);
585-
}
586-
_ => unimpl!("rval misc {:?} {:?}", from_ty, to_ty),
538+
fx.bcx.ins().fcvt_to_uint_sat(to_clif_ty, from)
539+
}
540+
} else if from_clif_ty.is_float() && to_clif_ty.is_float() {
541+
// float -> float
542+
match (from_clif_ty, to_clif_ty) {
543+
(types::F32, types::F64) => {
544+
fx.bcx.ins().fpromote(types::F64, from)
545+
}
546+
(types::F64, types::F32) => {
547+
fx.bcx.ins().fdemote(types::F32, from)
548+
}
549+
_ => from,
550+
}
551+
} else {
552+
unimpl!("rval misc {:?} {:?}", from_ty, to_ty)
553+
};
554+
lval.write_cvalue(fx, CValue::ByVal(res, dest_layout));
587555
}
588556
}
589557
Rvalue::Cast(CastKind::ClosureFnPointer, operand, _ty) => {

0 commit comments

Comments
 (0)