@@ -407,7 +407,8 @@ impl<'tcx> LayoutExt<'tcx> for TyLayout<'tcx> {
407407#[ derive( Clone , Copy , PartialEq , Eq , Debug ) ]
408408pub enum CastTarget {
409409 Uniform ( Uniform ) ,
410- Pair ( Reg , Reg )
410+ Pair ( Reg , Reg ) ,
411+ ChunkedPrefix { prefix : [ RegKind ; 8 ] , chunk : Size , total : Size }
411412}
412413
413414impl From < Reg > for CastTarget {
@@ -429,7 +430,8 @@ impl CastTarget {
429430 CastTarget :: Pair ( a, b) => {
430431 ( a. size . abi_align ( a. align ( cx) ) + b. size )
431432 . abi_align ( self . align ( cx) )
432- }
433+ } ,
434+ CastTarget :: ChunkedPrefix { total, .. } => total
433435 }
434436 }
435437
@@ -440,6 +442,12 @@ impl CastTarget {
440442 cx. data_layout ( ) . aggregate_align
441443 . max ( a. align ( cx) )
442444 . 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) )
443451 }
444452 }
445453 }
@@ -452,6 +460,34 @@ impl CastTarget {
452460 a. llvm_type ( cx) ,
453461 b. llvm_type ( cx)
454462 ] , 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 )
455491 }
456492 }
457493 }
0 commit comments