When casting enum to integer sign extend the discriminant if necessary
This commit is contained in:
parent
cc0268fa1a
commit
bf2ba15972
43
src/base.rs
43
src/base.rs
@ -515,12 +515,43 @@ fn is_fat_ptr<'tcx>(
|
||||
_ => unreachable!("cast adt {} -> {}", from_ty, to_ty),
|
||||
}
|
||||
|
||||
let discr = crate::discriminant::codegen_get_discriminant(
|
||||
fx,
|
||||
operand,
|
||||
fx.layout_of(to_ty),
|
||||
);
|
||||
lval.write_cvalue(fx, discr);
|
||||
use rustc_target::abi::{TagEncoding, Int, Variants};
|
||||
|
||||
match &operand.layout().variants {
|
||||
Variants::Single { index } => {
|
||||
let discr = operand.layout().ty.discriminant_for_variant(fx.tcx, *index).unwrap();
|
||||
let discr = if discr.ty.is_signed() {
|
||||
rustc_middle::mir::interpret::sign_extend(discr.val, fx.layout_of(discr.ty).size)
|
||||
} else {
|
||||
discr.val
|
||||
};
|
||||
|
||||
let discr = CValue::const_val(fx, fx.layout_of(to_ty), discr);
|
||||
lval.write_cvalue(fx, discr);
|
||||
}
|
||||
Variants::Multiple {
|
||||
tag,
|
||||
tag_field,
|
||||
tag_encoding: TagEncoding::Direct,
|
||||
variants: _,
|
||||
} => {
|
||||
let cast_to = fx.clif_type(dest_layout.ty).unwrap();
|
||||
|
||||
// Read the tag/niche-encoded discriminant from memory.
|
||||
let encoded_discr = operand.value_field(fx, mir::Field::new(*tag_field));
|
||||
let encoded_discr = encoded_discr.load_scalar(fx);
|
||||
|
||||
// Decode the discriminant (specifically if it's niche-encoded).
|
||||
let signed = match tag.value {
|
||||
Int(_, signed) => signed,
|
||||
_ => false,
|
||||
};
|
||||
let val = clif_intcast(fx, encoded_discr, cast_to, signed);
|
||||
let val = CValue::by_val(val, dest_layout);
|
||||
lval.write_cvalue(fx, val);
|
||||
}
|
||||
Variants::Multiple { ..} => unreachable!(),
|
||||
}
|
||||
} else {
|
||||
let to_clif_ty = fx.clif_type(to_ty).unwrap();
|
||||
let from = operand.load_scalar(fx);
|
||||
|
Loading…
Reference in New Issue
Block a user