|
| 1 | +use std::collections::BTreeSet; |
1 | 2 | use std::fmt::{self,Write}; |
2 | 3 | use std::ops::{Bound,Deref}; |
3 | 4 | use std::{cmp, iter}; |
4 | 5 |
|
5 | 6 | use rustc_hashes::Hash64; |
6 | 7 | use rustc_index::Idx; |
7 | 8 | use rustc_index::bit_set::BitMatrix; |
8 | | -use tracing::debug; |
| 9 | +use tracing::{debug, trace}; |
9 | 10 |
|
10 | 11 | usecrate::{ |
11 | 12 | AbiAlign,Align,BackendRepr,FieldsShape,HasDataLayout,IndexSlice,IndexVec,Integer, |
@@ -766,30 +767,63 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> { |
766 | 767 |
|
767 | 768 | let niche_filling_layout = calculate_niche_filling_layout(); |
768 | 769 |
|
769 | | -let(mut min,mut max) = (i128::MAX, i128::MIN); |
770 | 770 | let discr_type = repr.discr_type(); |
771 | | -let bits = Integer::from_attr(dl, discr_type).size().bits(); |
772 | | -for(i,mut val)in discriminants { |
773 | | -if !repr.c() && variants[i].iter().any(|f| f.is_uninhabited()){ |
774 | | -continue; |
775 | | -} |
776 | | -if discr_type.is_signed(){ |
777 | | -// sign extend the raw representation to be an i128 |
778 | | - val = (val << (128 - bits)) >> (128 - bits); |
779 | | -} |
780 | | -if val < min { |
781 | | - min = val; |
782 | | -} |
783 | | -if val > max { |
784 | | - max = val; |
785 | | -} |
786 | | -} |
787 | | -// We might have no inhabited variants, so pretend there's at least one. |
788 | | -if(min, max) == (i128::MAX, i128::MIN){ |
789 | | - min = 0; |
790 | | - max = 0; |
791 | | -} |
792 | | -assert!(min <= max,"discriminant range is {min}...{max}"); |
| 771 | +let discr_int = Integer::from_attr(dl, discr_type); |
| 772 | +// Because we can only represent one range of valid values, we'll look for the |
| 773 | +// largest range of invalid values and pick everything else as the range of valid |
| 774 | +// values. |
| 775 | + |
| 776 | +// First we need to sort the possible discriminant values so that we can look for the largest gap: |
| 777 | +let valid_discriminants:BTreeSet<i128> = discriminants |
| 778 | +.filter(|&(i, _)| repr.c() || variants[i].iter().all(|f| !f.is_uninhabited())) |
| 779 | +.map(|(_, val)| { |
| 780 | +if discr_type.is_signed(){ |
| 781 | +// sign extend the raw representation to be an i128 |
| 782 | +// FIXME: do this at the discriminant iterator creation sites |
| 783 | + discr_int.size().sign_extend(val asu128) |
| 784 | +}else{ |
| 785 | + val |
| 786 | +} |
| 787 | +}) |
| 788 | +.collect(); |
| 789 | +trace!(?valid_discriminants); |
| 790 | +let discriminants = valid_discriminants.iter().copied(); |
| 791 | +//let next_discriminants = discriminants.clone().cycle().skip(1); |
| 792 | +let next_discriminants = |
| 793 | + discriminants.clone().chain(valid_discriminants.first().copied()).skip(1); |
| 794 | +// Iterate over pairs of each discriminant together with the next one. |
| 795 | +// Since they were sorted, we can now compute the niche sizes and pick the largest. |
| 796 | +let discriminants = discriminants.zip(next_discriminants); |
| 797 | +let largest_niche = discriminants.max_by_key(|&(start, end)| { |
| 798 | +trace!(?start, ?end); |
| 799 | +// If this is a wraparound range, the niche size is `MAX - abs(diff)`, as the diff between |
| 800 | +// the two end points is actually the size of the valid discriminants. |
| 801 | +let dist = if start > end { |
| 802 | +// Overflow can happen for 128 bit discriminants if `end` is negative. |
| 803 | +// But in that case casting to `u128` still gets us the right value, |
| 804 | +// as the distance must be positive if the lhs of the subtraction is larger than the rhs. |
| 805 | +let dist = start.wrapping_sub(end); |
| 806 | +if discr_type.is_signed(){ |
| 807 | + discr_int.signed_max().wrapping_sub(dist)asu128 |
| 808 | +}else{ |
| 809 | + discr_int.size().unsigned_int_max() - dist asu128 |
| 810 | +} |
| 811 | +}else{ |
| 812 | +// Overflow can happen for 128 bit discriminants if `start` is negative. |
| 813 | +// But in that case casting to `u128` still gets us the right value, |
| 814 | +// as the distance must be positive if the lhs of the subtraction is larger than the rhs. |
| 815 | + end.wrapping_sub(start)asu128 |
| 816 | +}; |
| 817 | +trace!(?dist); |
| 818 | + dist |
| 819 | +}); |
| 820 | +trace!(?largest_niche); |
| 821 | + |
| 822 | +// `max` is the last valid discriminant before the largest niche |
| 823 | +// `min` is the first valid discriminant after the largest niche |
| 824 | +let(max, min) = largest_niche |
| 825 | +// We might have no inhabited variants, so pretend there's at least one. |
| 826 | +.unwrap_or((0,0)); |
793 | 827 | let(min_ity, signed) = discr_range_of_repr(min, max);//Integer::repr_discr(tcx, ty, &repr, min, max); |
794 | 828 |
|
795 | 829 | letmut align = dl.aggregate_align; |
|
0 commit comments