@@ -370,6 +370,40 @@ impl<'tcx> ConvSpirvType<'tcx> for TyAndLayout<'tcx> {
370
370
. def_with_name ( cx, span, TyLayoutNameKey :: from ( * self ) ) ,
371
371
Abi :: Scalar ( ref scalar) => trans_scalar ( cx, span, * self , scalar, Size :: ZERO ) ,
372
372
Abi :: ScalarPair ( ref a, ref b) => {
373
+ // NOTE(eddyb) unlike `Abi::Scalar`'s simpler newtype-unpacking
374
+ // behavior, `Abi::ScalarPair` can be composed in two ways:
375
+ // * two `Abi::Scalar` fields (and any number of ZST fields),
376
+ // gets handled the same as a `struct { a, b }`, further below
377
+ // * an `Abi::ScalarPair` field (and any number of ZST fields),
378
+ // which requires more work to allow taking a reference to
379
+ // that field, and there are two potential approaches:
380
+ // 1. wrapping that field's SPIR-V type in a single-field
381
+ // `OpTypeStruct` - this has the disadvantage that GEPs
382
+ // would have to inject an extra `0` field index, and other
383
+ // field-related operations would also need additional work
384
+ // 2. reusing that field's SPIR-V type, instead of defining
385
+ // a new one, offering the `(a, b)` shape `rustc_codegen_ssa`
386
+ // expects, while letting noop pointercasts access the sole
387
+ // `Abi::ScalarPair` field - this is the approach taken here
388
+ let mut non_zst_fields = ( 0 ..self . fields . count ( ) )
389
+ . map ( |i| ( i, self . field ( cx, i) ) )
390
+ . filter ( |( _, field) | !field. is_zst ( ) ) ;
391
+ let sole_non_zst_field = match ( non_zst_fields. next ( ) , non_zst_fields. next ( ) ) {
392
+ ( Some ( field) , None ) => Some ( field) ,
393
+ _ => None ,
394
+ } ;
395
+ if let Some ( ( i, field) ) = sole_non_zst_field {
396
+ // Only unpack a newtype if the field and the newtype line up
397
+ // perfectly, in every way that could potentially affect ABI.
398
+ if self . fields . offset ( i) == Size :: ZERO
399
+ && field. size == self . size
400
+ && field. align == self . align
401
+ && field. abi == self . abi
402
+ {
403
+ return field. spirv_type ( span, cx) ;
404
+ }
405
+ }
406
+
373
407
// Note: We can't use auto_struct_layout here because the spirv types here might be undefined due to
374
408
// recursive pointer types.
375
409
let a_offset = Size :: ZERO ;
0 commit comments