about summary refs log tree commit diff
path: root/compiler/rustc_codegen_ssa/src
diff options
context:
space:
mode:
authorRalf Jung <post@ralfj.de>2024-11-30 19:24:40 +0100
committerGitHub <noreply@github.com>2024-11-30 19:24:40 +0100
commit3029e09e2f751ecf37f3840e45281e66cdea8477 (patch)
tree90fb63fb4fcc12858a2791923a8041d68edc0ec9 /compiler/rustc_codegen_ssa/src
parente93e096cc88728337fb41ff74431ebe71a1b4663 (diff)
parent26d7b5da996ec8935c33638f1d7c29f58c96f8f0 (diff)
downloadrust-3029e09e2f751ecf37f3840e45281e66cdea8477.tar.gz
rust-3029e09e2f751ecf37f3840e45281e66cdea8477.zip
Rollup merge of #131698 - the8472:remove-set-discriminant-hack, r=RalfJung
use stores of the correct size to set discriminants

Resolves an old HACK /FIXME.

Note that I haven't worked much with codegen so I'm not sure if I'm using the functions correctly and I was surprised seeing out-of-range values being fed into `const_uint_big` but apparently they're wrapped implicitly? By making it explicit we can pass in-range values instead.
Diffstat (limited to 'compiler/rustc_codegen_ssa/src')
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/place.rs24
1 files changed, 16 insertions, 8 deletions
diff --git a/compiler/rustc_codegen_ssa/src/mir/place.rs b/compiler/rustc_codegen_ssa/src/mir/place.rs
index b8fa8c0351b..c38484109d2 100644
--- a/compiler/rustc_codegen_ssa/src/mir/place.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/place.rs
@@ -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);
                 }
             }