@@ -204,10 +204,14 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> {
204
204
}
205
205
206
206
/// Obtain the actual discriminant of a value.
207
+ ///
208
+ /// If `relative` is true, instead calculate the *relative* discriminant (see
209
+ /// `RValue::Discriminant`).
207
210
pub fn codegen_get_discr < Bx : BuilderMethods < ' a , ' tcx , Value = V > > (
208
211
self ,
209
212
bx : & mut Bx ,
210
213
cast_to : Ty < ' tcx > ,
214
+ relative : bool ,
211
215
) -> V {
212
216
let cast_to = bx. cx ( ) . immediate_backend_type ( bx. cx ( ) . layout_of ( cast_to) ) ;
213
217
if self . layout . abi . is_uninhabited ( ) {
@@ -266,44 +270,49 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> {
266
270
} else {
267
271
bx. sub ( tag, bx. cx ( ) . const_uint_big ( niche_llty, niche_start) )
268
272
} ;
269
- let relative_max = niche_variants. end ( ) . as_u32 ( ) - niche_variants. start ( ) . as_u32 ( ) ;
270
- let is_niche = if relative_max == 0 {
271
- // Avoid calling `const_uint`, which wouldn't work for pointers.
272
- // Also use canonical == 0 instead of non-canonical u<= 0.
273
- // FIXME(eddyb) check the actual primitive type here.
274
- bx. icmp ( IntPredicate :: IntEQ , relative_discr, bx. cx ( ) . const_null ( niche_llty) )
273
+ let relative_max = niche_variants. size_hint ( ) . 1 . unwrap ( ) - 1 ;
274
+
275
+ if relative {
276
+ bx. intcast ( relative_discr, cast_to, false )
275
277
} else {
276
- let relative_max = bx. cx ( ) . const_uint ( niche_llty, relative_max as u64 ) ;
277
- bx. icmp ( IntPredicate :: IntULE , relative_discr, relative_max)
278
- } ;
278
+ // NOTE(eddyb) this addition needs to be performed on the final
279
+ // type, in case the niche itself can't represent all variant
280
+ // indices (e.g. `u8` niche with more than `256` variants,
281
+ // but enough uninhabited variants so that the remaining variants
282
+ // fit in the niche).
283
+ // In other words, `niche_variants.end - niche_variants.start`
284
+ // is representable in the niche, but `niche_variants.end`
285
+ // might not be, in extreme cases.
286
+ let niche_discr = {
287
+ let relative_discr = if relative_max == 0 {
288
+ // HACK(eddyb) since we have only one niche, we know which
289
+ // one it is, and we can avoid having a dynamic value here.
290
+ bx. cx ( ) . const_uint ( cast_to, 0 )
291
+ } else {
292
+ bx. intcast ( relative_discr, cast_to, false )
293
+ } ;
294
+ bx. add (
295
+ relative_discr,
296
+ bx. cx ( ) . const_uint ( cast_to, niche_variants. start ( ) . as_u32 ( ) as u64 ) ,
297
+ )
298
+ } ;
279
299
280
- // NOTE(eddyb) this addition needs to be performed on the final
281
- // type, in case the niche itself can't represent all variant
282
- // indices (e.g. `u8` niche with more than `256` variants,
283
- // but enough uninhabited variants so that the remaining variants
284
- // fit in the niche).
285
- // In other words, `niche_variants.end - niche_variants.start`
286
- // is representable in the niche, but `niche_variants.end`
287
- // might not be, in extreme cases.
288
- let niche_discr = {
289
- let relative_discr = if relative_max == 0 {
290
- // HACK(eddyb) since we have only one niche, we know which
291
- // one it is, and we can avoid having a dynamic value here.
292
- bx. cx ( ) . const_uint ( cast_to, 0 )
300
+ let is_niche = if relative_max == 0 {
301
+ // Avoid calling `const_uint`, which wouldn't work for pointers.
302
+ // Also use canonical == 0 instead of non-canonical u<= 0.
303
+ // FIXME(eddyb) check the actual primitive type here.
304
+ bx. icmp ( IntPredicate :: IntEQ , relative_discr, bx. cx ( ) . const_null ( niche_llty) )
293
305
} else {
294
- bx. intcast ( relative_discr, cast_to, false )
306
+ let relative_max = bx. cx ( ) . const_uint ( niche_llty, relative_max as u64 ) ;
307
+ bx. icmp ( IntPredicate :: IntULE , relative_discr, relative_max)
295
308
} ;
296
- bx. add (
297
- relative_discr,
298
- bx. cx ( ) . const_uint ( cast_to, niche_variants. start ( ) . as_u32 ( ) as u64 ) ,
299
- )
300
- } ;
301
309
302
- bx. select (
303
- is_niche,
304
- niche_discr,
305
- bx. cx ( ) . const_uint ( cast_to, dataful_variant. as_u32 ( ) as u64 ) ,
306
- )
310
+ bx. select (
311
+ is_niche,
312
+ niche_discr,
313
+ bx. cx ( ) . const_uint ( cast_to, dataful_variant. as_u32 ( ) as u64 ) ,
314
+ )
315
+ }
307
316
}
308
317
}
309
318
}
0 commit comments