@@ -2225,24 +2225,50 @@ where
22252225struct Niche {
22262226 offset : Size ,
22272227 scalar : Scalar ,
2228- available : u128 ,
22292228}
22302229
22312230impl Niche {
2232- fn reserve < ' tcx > (
2233- & self ,
2234- cx : & LayoutCx < ' tcx , TyCtxt < ' tcx > > ,
2235- count : u128 ,
2236- ) -> Option < ( u128 , Scalar ) > {
2237- if count > self . available {
2238- return None ;
2239- }
2231+ fn available < C : HasDataLayout > ( & self , cx : & C ) -> u128 {
2232+ let Scalar { value, valid_range : ref v } = self . scalar ;
2233+ let bits = value. size ( cx) . bits ( ) ;
2234+ assert ! ( bits <= 128 ) ;
2235+ let max_value = !0u128 >> ( 128 - bits) ;
2236+
2237+ // Find out how many values are outside the valid range.
2238+ let niche = v. end ( ) . wrapping_add ( 1 ) ..* v. start ( ) ;
2239+ niche. end . wrapping_sub ( niche. start ) & max_value
2240+ }
2241+
2242+ fn reserve < C : HasDataLayout > ( & self , cx : & C , count : u128 ) -> Option < ( u128 , Scalar ) > {
2243+ assert ! ( count > 0 ) ;
2244+
22402245 let Scalar { value, valid_range : ref v } = self . scalar ;
22412246 let bits = value. size ( cx) . bits ( ) ;
22422247 assert ! ( bits <= 128 ) ;
22432248 let max_value = !0u128 >> ( 128 - bits) ;
2249+
2250+ if count > max_value {
2251+ return None ;
2252+ }
2253+
2254+ // Compute the range of invalid values being reserved.
22442255 let start = v. end ( ) . wrapping_add ( 1 ) & max_value;
22452256 let end = v. end ( ) . wrapping_add ( count) & max_value;
2257+
2258+ // If the `end` of our range is inside the valid range,
2259+ // then we ran out of invalid values.
2260+ // FIXME(eddyb) abstract this with a wraparound range type.
2261+ let valid_range_contains = |x| {
2262+ if v. start ( ) <= v. end ( ) {
2263+ * v. start ( ) <= x && x <= * v. end ( )
2264+ } else {
2265+ * v. start ( ) <= x || x <= * v. end ( )
2266+ }
2267+ } ;
2268+ if valid_range_contains ( end) {
2269+ return None ;
2270+ }
2271+
22462272 Some ( ( start, Scalar { value, valid_range : * v. start ( ) ..=end } ) )
22472273 }
22482274}
@@ -2253,25 +2279,12 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
22532279 // FIXME(eddyb) traverse already optimized enums.
22542280 fn find_niche ( & self , layout : TyLayout < ' tcx > ) -> Result < Option < Niche > , LayoutError < ' tcx > > {
22552281 let scalar_niche = |scalar : & Scalar , offset| {
2256- let Scalar { value, valid_range : ref v } = * scalar;
2257-
2258- let bits = value. size ( self ) . bits ( ) ;
2259- assert ! ( bits <= 128 ) ;
2260- let max_value = !0u128 >> ( 128 - bits) ;
2261-
2262- // Find out how many values are outside the valid range.
2263- let available = if v. start ( ) <= v. end ( ) {
2264- v. start ( ) + ( max_value - v. end ( ) )
2282+ let niche = Niche { offset, scalar : scalar. clone ( ) } ;
2283+ if niche. available ( self ) > 0 {
2284+ Some ( niche)
22652285 } else {
2266- v. start ( ) - v. end ( ) - 1
2267- } ;
2268-
2269- // Give up if there is no niche value available.
2270- if available == 0 {
2271- return None ;
2286+ None
22722287 }
2273-
2274- Some ( Niche { offset, scalar : scalar. clone ( ) , available } )
22752288 } ;
22762289
22772290 // Locals variables which live across yields are stored
@@ -2293,7 +2306,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
22932306 )
22942307 . chain ( iter:: once ( ( a, Size :: ZERO ) ) )
22952308 . filter_map ( |( scalar, offset) | scalar_niche ( scalar, offset) )
2296- . max_by_key ( |niche| niche. available ) ;
2309+ . max_by_key ( |niche| niche. available ( self ) ) ;
22972310 return Ok ( niche) ;
22982311 }
22992312 Abi :: Vector { ref element, .. } => {
@@ -2325,8 +2338,9 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
23252338 let mut available = 0 ;
23262339 for i in 0 ..layout. fields . count ( ) {
23272340 if let Some ( mut c) = self . find_niche ( layout. field ( self , i) ?) ? {
2328- if c. available > available {
2329- available = c. available ;
2341+ let c_available = c. available ( self ) ;
2342+ if c_available > available {
2343+ available = c_available;
23302344 c. offset += layout. fields . offset ( i) ;
23312345 niche = Some ( c) ;
23322346 }
0 commit comments