@@ -2225,24 +2225,50 @@ where
2225
2225
struct Niche {
2226
2226
offset : Size ,
2227
2227
scalar : Scalar ,
2228
- available : u128 ,
2229
2228
}
2230
2229
2231
2230
impl 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
+
2240
2245
let Scalar { value, valid_range : ref v } = self . scalar ;
2241
2246
let bits = value. size ( cx) . bits ( ) ;
2242
2247
assert ! ( bits <= 128 ) ;
2243
2248
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.
2244
2255
let start = v. end ( ) . wrapping_add ( 1 ) & max_value;
2245
2256
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
+
2246
2272
Some ( ( start, Scalar { value, valid_range : * v. start ( ) ..=end } ) )
2247
2273
}
2248
2274
}
@@ -2253,25 +2279,12 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
2253
2279
// FIXME(eddyb) traverse already optimized enums.
2254
2280
fn find_niche ( & self , layout : TyLayout < ' tcx > ) -> Result < Option < Niche > , LayoutError < ' tcx > > {
2255
2281
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)
2265
2285
} 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
2272
2287
}
2273
-
2274
- Some ( Niche { offset, scalar : scalar. clone ( ) , available } )
2275
2288
} ;
2276
2289
2277
2290
// Locals variables which live across yields are stored
@@ -2293,7 +2306,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
2293
2306
)
2294
2307
. chain ( iter:: once ( ( a, Size :: ZERO ) ) )
2295
2308
. filter_map ( |( scalar, offset) | scalar_niche ( scalar, offset) )
2296
- . max_by_key ( |niche| niche. available ) ;
2309
+ . max_by_key ( |niche| niche. available ( self ) ) ;
2297
2310
return Ok ( niche) ;
2298
2311
}
2299
2312
Abi :: Vector { ref element, .. } => {
@@ -2325,8 +2338,9 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
2325
2338
let mut available = 0 ;
2326
2339
for i in 0 ..layout. fields . count ( ) {
2327
2340
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;
2330
2344
c. offset += layout. fields . offset ( i) ;
2331
2345
niche = Some ( c) ;
2332
2346
}
0 commit comments