1
Fork 0

Change enum->int casts to not go through MIR casts.

Instead we generate a discriminant rvalue and cast the result of that.
This commit is contained in:
Oli Scherer 2022-06-29 14:18:55 +00:00
parent 0e674b3ec5
commit 7839cb963f
15 changed files with 221 additions and 132 deletions

View file

@ -1,6 +1,7 @@
//! See docs in `build/expr/mod.rs`.
use rustc_index::vec::Idx;
use rustc_middle::ty::util::IntTypeExt;
use crate::build::expr::as_place::PlaceBase;
use crate::build::expr::category::{Category, RvalueFunc};
@ -190,7 +191,30 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
}
ExprKind::Cast { source } => {
let source = &this.thir[source];
let from_ty = CastTy::from_ty(source.ty);
// Casting an enum to an integer is equivalent to computing the discriminant and casting the
// discriminant. Previously every backend had to repeat the logic for this operation. Now we
// create all the steps directly in MIR with operations all backends need to support anyway.
let (source, ty) = if let ty::Adt(adt_def, ..) = source.ty.kind() && adt_def.is_enum() {
let discr_ty = adt_def.repr().discr_type().to_ty(this.tcx);
let place = unpack!(block = this.as_place(block, source));
let discr = this.temp(discr_ty, source.span);
this.cfg.push_assign(
block,
source_info,
discr,
Rvalue::Discriminant(place),
);
(Operand::Move(discr), discr_ty)
} else {
let ty = source.ty;
let source = unpack!(
block = this.as_operand(block, scope, source, None, NeedsTemporary::No)
);
(source, ty)
};
let from_ty = CastTy::from_ty(ty);
let cast_ty = CastTy::from_ty(expr.ty);
let cast_kind = match (from_ty, cast_ty) {
(Some(CastTy::Ptr(_) | CastTy::FnPtr), Some(CastTy::Int(_))) => {
@ -201,9 +225,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
}
(_, _) => CastKind::Misc,
};
let source = unpack!(
block = this.as_operand(block, scope, source, None, NeedsTemporary::No)
);
block.and(Rvalue::Cast(cast_kind, source, expr.ty))
}
ExprKind::Pointer { cast, source } => {