Skip to content

Commit e60c7ed

Browse files
committed
rustc_codegen_ssa: try to make codegen_get_discr more readable.
1 parent 4bb6b4a commit e60c7ed

File tree

1 file changed

+32
-18
lines changed

1 file changed

+32
-18
lines changed

src/librustc_codegen_ssa/mir/place.rs

+32-18
Original file line numberDiff line numberDiff line change
@@ -228,8 +228,11 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> {
228228
}
229229
};
230230

231-
let discr = self.project_field(bx, discr_index);
232-
let lldiscr = bx.load_operand(discr).immediate();
231+
// Read the tag/niche-encoded discriminant from memory.
232+
let encoded_discr = self.project_field(bx, discr_index);
233+
let encoded_discr = bx.load_operand(encoded_discr);
234+
235+
// Decode the discriminant (specifically if it's niche-encoded).
233236
match *discr_kind {
234237
layout::DiscriminantKind::Tag => {
235238
let signed = match discr_scalar.value {
@@ -240,38 +243,49 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> {
240243
layout::Int(_, signed) => !discr_scalar.is_bool() && signed,
241244
_ => false
242245
};
243-
bx.intcast(lldiscr, cast_to, signed)
246+
bx.intcast(encoded_discr.immediate(), cast_to, signed)
244247
}
245248
layout::DiscriminantKind::Niche {
246249
dataful_variant,
247250
ref niche_variants,
248251
niche_start,
249252
} => {
250-
let niche_llty = bx.cx().immediate_backend_type(discr.layout);
251-
if niche_variants.start() == niche_variants.end() {
253+
let niche_llty = bx.cx().immediate_backend_type(encoded_discr.layout);
254+
let encoded_discr = encoded_discr.immediate();
255+
let (is_niche, niche_discr) = if niche_variants.start() == niche_variants.end() {
256+
// Special case for when we can use a simple equality check,
257+
// which covers null pointers, and needs simpler codegen.
252258
// FIXME(eddyb): check the actual primitive type here.
253-
let niche_llval = if niche_start == 0 {
259+
let encoded_niche = if niche_start == 0 {
254260
// HACK(eddyb): using `c_null` as it works on all types.
255261
bx.cx().const_null(niche_llty)
256262
} else {
257263
bx.cx().const_uint_big(niche_llty, niche_start)
258264
};
259-
let select_arg = bx.icmp(IntPredicate::IntEQ, lldiscr, niche_llval);
260-
bx.select(select_arg,
265+
(
266+
bx.icmp(IntPredicate::IntEQ, encoded_discr, encoded_niche),
261267
bx.cx().const_uint(cast_to, niche_variants.start().as_u32() as u64),
262-
bx.cx().const_uint(cast_to, dataful_variant.as_u32() as u64))
268+
)
263269
} else {
264-
// Rebase from niche values to discriminant values.
270+
// Rebase from niche values to discriminants, and check
271+
// whether the result is in range for the niche variants.
272+
// FIXME(#61696) the range check is sometimes incorrect.
265273
let delta = niche_start.wrapping_sub(niche_variants.start().as_u32() as u128);
266-
let lldiscr = bx.sub(lldiscr, bx.cx().const_uint_big(niche_llty, delta));
267-
let lldiscr_max =
274+
let niche_discr =
275+
bx.sub(encoded_discr, bx.cx().const_uint_big(niche_llty, delta));
276+
let niche_discr_max =
268277
bx.cx().const_uint(niche_llty, niche_variants.end().as_u32() as u64);
269-
let select_arg = bx.icmp(IntPredicate::IntULE, lldiscr, lldiscr_max);
270-
let cast = bx.intcast(lldiscr, cast_to, false);
271-
bx.select(select_arg,
272-
cast,
273-
bx.cx().const_uint(cast_to, dataful_variant.as_u32() as u64))
274-
}
278+
(
279+
bx.icmp(IntPredicate::IntULE, niche_discr, niche_discr_max),
280+
niche_discr,
281+
)
282+
};
283+
let niche_discr = bx.intcast(niche_discr, cast_to, false);
284+
bx.select(
285+
is_niche,
286+
niche_discr,
287+
bx.cx().const_uint(cast_to, dataful_variant.as_u32() as u64),
288+
)
275289
}
276290
}
277291
}

0 commit comments

Comments
 (0)