@@ -407,7 +407,8 @@ impl<'tcx> LayoutExt<'tcx> for TyLayout<'tcx> {
407
407
#[ derive( Clone , Copy , PartialEq , Eq , Debug ) ]
408
408
pub enum CastTarget {
409
409
Uniform ( Uniform ) ,
410
- Pair ( Reg , Reg )
410
+ Pair ( Reg , Reg ) ,
411
+ ChunkedPrefix { prefix : [ RegKind ; 8 ] , chunk : Size , total : Size }
411
412
}
412
413
413
414
impl From < Reg > for CastTarget {
@@ -429,7 +430,8 @@ impl CastTarget {
429
430
CastTarget :: Pair ( a, b) => {
430
431
( a. size . abi_align ( a. align ( cx) ) + b. size )
431
432
. abi_align ( self . align ( cx) )
432
- }
433
+ } ,
434
+ CastTarget :: ChunkedPrefix { total, .. } => total
433
435
}
434
436
}
435
437
@@ -440,6 +442,12 @@ impl CastTarget {
440
442
cx. data_layout ( ) . aggregate_align
441
443
. max ( a. align ( cx) )
442
444
. max ( b. align ( cx) )
445
+ } ,
446
+ CastTarget :: ChunkedPrefix { chunk, .. } => {
447
+ cx. data_layout ( ) . aggregate_align
448
+ . max ( Reg { kind : RegKind :: Integer , size : chunk } . align ( cx) )
449
+ . max ( Reg { kind : RegKind :: Float , size : chunk } . align ( cx) )
450
+ . max ( Reg { kind : RegKind :: Vector , size : chunk } . align ( cx) )
443
451
}
444
452
}
445
453
}
@@ -452,6 +460,34 @@ impl CastTarget {
452
460
a. llvm_type ( cx) ,
453
461
b. llvm_type ( cx)
454
462
] , false )
463
+ } ,
464
+ CastTarget :: ChunkedPrefix { prefix, chunk, total } => {
465
+ let total_chunks = total. bytes ( ) / chunk. bytes ( ) ;
466
+ let rem_bytes = total. bytes ( ) % chunk. bytes ( ) ;
467
+ let prefix_chunks = total_chunks. min ( prefix. len ( ) as u64 ) ;
468
+
469
+ let int_ll_type = Reg { kind : RegKind :: Integer , size : chunk } . llvm_type ( cx) ;
470
+
471
+ // Simple cases simplify to an array
472
+ if rem_bytes == 0 && prefix. into_iter ( ) . all ( |& kind| kind == RegKind :: Integer ) {
473
+ return Type :: array ( & int_ll_type, total_chunks) ;
474
+ }
475
+
476
+ // The final structure is made up of:
477
+ // Up to 8 chunks of the type specified in the prefix
478
+ // Any other complete chunks as integers
479
+ // One final integer needed to make up the total structure size
480
+ let mut args: Vec < _ > =
481
+ prefix. into_iter ( ) . take ( prefix_chunks as usize )
482
+ . map ( |& kind| Reg { kind : kind, size : chunk } . llvm_type ( cx) )
483
+ . chain ( ( 0 ..total_chunks - prefix_chunks) . map ( |_| int_ll_type) )
484
+ . collect ( ) ;
485
+
486
+ if rem_bytes > 0 {
487
+ args. push ( Type :: ix ( cx, rem_bytes * 8 ) ) ;
488
+ }
489
+
490
+ Type :: struct_ ( cx, & args, false )
455
491
}
456
492
}
457
493
}
0 commit comments