@@ -228,6 +228,33 @@ impl CastTarget {
228
228
}
229
229
}
230
230
231
+ /// Return value from the `homogeneous_aggregate` test function.
232
+ #[ derive( Copy , Clone , Debug ) ]
233
+ pub enum HomogeneousAggregate {
234
+ /// Yes, all the "leaf fields" of this struct are passed in the
235
+ /// same way (specified in the `Reg` value).
236
+ Homogeneous ( Reg ) ,
237
+
238
+ /// There are distinct leaf fields passed in different ways,
239
+ /// or this is uninhabited.
240
+ Heterogeneous ,
241
+
242
+ /// There are no leaf fields at all.
243
+ NoData ,
244
+ }
245
+
246
+ impl HomogeneousAggregate {
247
+ /// If this is a homogeneous aggregate, returns the homogeneous
248
+ /// unit, else `None`.
249
+ pub fn unit ( self ) -> Option < Reg > {
250
+ if let HomogeneousAggregate :: Homogeneous ( r) = self {
251
+ Some ( r)
252
+ } else {
253
+ None
254
+ }
255
+ }
256
+ }
257
+
231
258
impl < ' a , Ty > TyLayout < ' a , Ty > {
232
259
fn is_aggregate ( & self ) -> bool {
233
260
match self . abi {
@@ -239,11 +266,21 @@ impl<'a, Ty> TyLayout<'a, Ty> {
239
266
}
240
267
}
241
268
242
- fn homogeneous_aggregate < C > ( & self , cx : & C ) -> Option < Reg >
269
+ /// True if this layout is an aggregate containing fields of only
270
+ /// a single type (e.g., `(u32, u32)`). Such aggregates are often
271
+ /// special-cased in ABIs.
272
+ ///
273
+ /// Note: We generally ignore fields of zero-sized type when computing
274
+ /// this value (cc #56877).
275
+ ///
276
+ /// This is public so that it can be used in unit tests, but
277
+ /// should generally only be relevant to the ABI details of
278
+ /// specific targets.
279
+ pub fn homogeneous_aggregate < C > ( & self , cx : & C ) -> HomogeneousAggregate
243
280
where Ty : TyLayoutMethods < ' a , C > + Copy , C : LayoutOf < Ty = Ty , TyLayout = Self >
244
281
{
245
282
match self . abi {
246
- Abi :: Uninhabited => None ,
283
+ Abi :: Uninhabited => HomogeneousAggregate :: Heterogeneous ,
247
284
248
285
// The primitive for this algorithm.
249
286
Abi :: Scalar ( ref scalar) => {
@@ -252,14 +289,15 @@ impl<'a, Ty> TyLayout<'a, Ty> {
252
289
abi:: Pointer => RegKind :: Integer ,
253
290
abi:: Float ( _) => RegKind :: Float ,
254
291
} ;
255
- Some ( Reg {
292
+ HomogeneousAggregate :: Homogeneous ( Reg {
256
293
kind,
257
294
size : self . size
258
295
} )
259
296
}
260
297
261
298
Abi :: Vector { .. } => {
262
- Some ( Reg {
299
+ assert ! ( !self . is_zst( ) ) ;
300
+ HomogeneousAggregate :: Homogeneous ( Reg {
263
301
kind : RegKind :: Vector ,
264
302
size : self . size
265
303
} )
@@ -275,7 +313,7 @@ impl<'a, Ty> TyLayout<'a, Ty> {
275
313
if count > 0 {
276
314
return self . field ( cx, 0 ) . homogeneous_aggregate ( cx) ;
277
315
} else {
278
- return None ;
316
+ return HomogeneousAggregate :: NoData ;
279
317
}
280
318
}
281
319
FieldPlacement :: Union ( _) => true ,
@@ -284,21 +322,27 @@ impl<'a, Ty> TyLayout<'a, Ty> {
284
322
285
323
for i in 0 ..self . fields . count ( ) {
286
324
if !is_union && total != self . fields . offset ( i) {
287
- return None ;
325
+ return HomogeneousAggregate :: Heterogeneous ;
288
326
}
289
327
290
328
let field = self . field ( cx, i) ;
329
+
291
330
match ( result, field. homogeneous_aggregate ( cx) ) {
292
- // The field itself must be a homogeneous aggregate.
293
- ( _, None ) => return None ,
331
+ ( _, HomogeneousAggregate :: NoData ) => {
332
+ // Ignore fields that have no data
333
+ }
334
+ ( _, HomogeneousAggregate :: Heterogeneous ) => {
335
+ // The field itself must be a homogeneous aggregate.
336
+ return HomogeneousAggregate :: Heterogeneous ;
337
+ }
294
338
// If this is the first field, record the unit.
295
- ( None , Some ( unit) ) => {
339
+ ( None , HomogeneousAggregate :: Homogeneous ( unit) ) => {
296
340
result = Some ( unit) ;
297
341
}
298
342
// For all following fields, the unit must be the same.
299
- ( Some ( prev_unit) , Some ( unit) ) => {
343
+ ( Some ( prev_unit) , HomogeneousAggregate :: Homogeneous ( unit) ) => {
300
344
if prev_unit != unit {
301
- return None ;
345
+ return HomogeneousAggregate :: Heterogeneous ;
302
346
}
303
347
}
304
348
}
@@ -314,9 +358,18 @@ impl<'a, Ty> TyLayout<'a, Ty> {
314
358
315
359
// There needs to be no padding.
316
360
if total != self . size {
317
- None
361
+ HomogeneousAggregate :: Heterogeneous
318
362
} else {
319
- result
363
+ match result {
364
+ Some ( reg) => {
365
+ assert_ne ! ( total, Size :: ZERO ) ;
366
+ HomogeneousAggregate :: Homogeneous ( reg)
367
+ }
368
+ None => {
369
+ assert_eq ! ( total, Size :: ZERO ) ;
370
+ HomogeneousAggregate :: NoData
371
+ }
372
+ }
320
373
}
321
374
}
322
375
}
0 commit comments