use stores of the correct size to set discriminants

This commit is contained in:
The 8472 2024-10-13 18:01:52 +02:00
parent 97b84e40cb
commit 26d7b5da99

View File

@ -1,5 +1,6 @@
use rustc_abi::Primitive::{Int, Pointer};
use rustc_abi::{Align, FieldsShape, Size, TagEncoding, VariantIdx, Variants};
use rustc_abi::{Align, BackendRepr, FieldsShape, Size, TagEncoding, VariantIdx, Variants};
use rustc_middle::mir::interpret::Scalar;
use rustc_middle::mir::tcx::PlaceTy;
use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf, TyAndLayout};
use rustc_middle::ty::{self, Ty};
@ -385,15 +386,22 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> {
if variant_index != untagged_variant {
let niche = self.project_field(bx, tag_field);
let niche_llty = bx.cx().immediate_backend_type(niche.layout);
let BackendRepr::Scalar(scalar) = niche.layout.backend_repr else {
bug!("expected a scalar placeref for the niche");
};
// We are supposed to compute `niche_value.wrapping_add(niche_start)` wrapping
// around the `niche`'s type.
// The easiest way to do that is to do wrapping arithmetic on `u128` and then
// masking off any extra bits that occur because we did the arithmetic with too many bits.
let niche_value = variant_index.as_u32() - niche_variants.start().as_u32();
let niche_value = (niche_value as u128).wrapping_add(niche_start);
// FIXME(eddyb): check the actual primitive type here.
let niche_llval = if niche_value == 0 {
// HACK(eddyb): using `c_null` as it works on all types.
bx.cx().const_null(niche_llty)
} else {
bx.cx().const_uint_big(niche_llty, niche_value)
};
let niche_value = niche_value & niche.layout.size.unsigned_int_max();
let niche_llval = bx.cx().scalar_to_backend(
Scalar::from_uint(niche_value, niche.layout.size),
scalar,
niche_llty,
);
OperandValue::Immediate(niche_llval).store(bx, niche);
}
}