@@ -204,10 +204,14 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> {
204204 }
205205
206206 /// Obtain the actual discriminant of a value.
207+ ///
208+ /// If `relative` is true, instead calculate the *relative* discriminant (see
209+ /// `RValue::Discriminant`).
207210 pub fn codegen_get_discr < Bx : BuilderMethods < ' a , ' tcx , Value = V > > (
208211 self ,
209212 bx : & mut Bx ,
210213 cast_to : Ty < ' tcx > ,
214+ relative : bool ,
211215 ) -> V {
212216 let cast_to = bx. cx ( ) . immediate_backend_type ( bx. cx ( ) . layout_of ( cast_to) ) ;
213217 if self . layout . abi . is_uninhabited ( ) {
@@ -266,44 +270,49 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> {
266270 } else {
267271 bx. sub ( tag, bx. cx ( ) . const_uint_big ( niche_llty, niche_start) )
268272 } ;
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 )
275277 } 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+ } ;
279299
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) )
293305 } 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)
295308 } ;
296- bx. add (
297- relative_discr,
298- bx. cx ( ) . const_uint ( cast_to, niche_variants. start ( ) . as_u32 ( ) as u64 ) ,
299- )
300- } ;
301309
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+ }
307316 }
308317 }
309318 }
0 commit comments