@@ -40,7 +40,7 @@ use rustc::ty::layout::{self, Align, Size, TyLayout};
40
40
use rustc:: ty:: layout:: { HasDataLayout , LayoutOf } ;
41
41
42
42
use libc:: c_uint;
43
- use std:: { cmp, iter } ;
43
+ use std:: cmp;
44
44
45
45
pub use syntax:: abi:: Abi ;
46
46
pub use rustc:: ty:: layout:: { FAT_PTR_ADDR , FAT_PTR_EXTRA } ;
@@ -279,30 +279,6 @@ impl Uniform {
279
279
pub fn align ( & self , cx : & CodegenCx ) -> Align {
280
280
self . unit . align ( cx)
281
281
}
282
-
283
- pub fn llvm_type ( & self , cx : & CodegenCx ) -> Type {
284
- let llunit = self . unit . llvm_type ( cx) ;
285
-
286
- if self . total <= self . unit . size {
287
- return llunit;
288
- }
289
-
290
- let count = self . total . bytes ( ) / self . unit . size . bytes ( ) ;
291
- let rem_bytes = self . total . bytes ( ) % self . unit . size . bytes ( ) ;
292
-
293
- if rem_bytes == 0 {
294
- return Type :: array ( & llunit, count) ;
295
- }
296
-
297
- // Only integers can be really split further.
298
- assert_eq ! ( self . unit. kind, RegKind :: Integer ) ;
299
-
300
- let args: Vec < _ > = ( 0 ..count) . map ( |_| llunit)
301
- . chain ( iter:: once ( Type :: ix ( cx, rem_bytes * 8 ) ) )
302
- . collect ( ) ;
303
-
304
- Type :: struct_ ( cx, & args, false )
305
- }
306
282
}
307
283
308
284
pub trait LayoutExt < ' tcx > {
@@ -405,91 +381,81 @@ impl<'tcx> LayoutExt<'tcx> for TyLayout<'tcx> {
405
381
}
406
382
407
383
#[ derive( Clone , Copy , PartialEq , Eq , Debug ) ]
408
- pub enum CastTarget {
409
- Uniform ( Uniform ) ,
410
- Pair ( Reg , Reg ) ,
411
- ChunkedPrefix { prefix : [ RegKind ; 8 ] , chunk : Size , total : Size }
384
+ pub struct CastTarget {
385
+ pub prefix : [ Option < RegKind > ; 8 ] ,
386
+ pub prefix_chunk : Size ,
387
+ pub rest : Uniform ,
412
388
}
413
389
414
390
impl From < Reg > for CastTarget {
415
391
fn from ( unit : Reg ) -> CastTarget {
416
- CastTarget :: Uniform ( Uniform :: from ( unit) )
392
+ CastTarget :: from ( Uniform :: from ( unit) )
417
393
}
418
394
}
419
395
420
396
impl From < Uniform > for CastTarget {
421
397
fn from ( uniform : Uniform ) -> CastTarget {
422
- CastTarget :: Uniform ( uniform)
398
+ CastTarget {
399
+ prefix : [ None ; 8 ] ,
400
+ prefix_chunk : Size :: from_bytes ( 0 ) ,
401
+ rest : uniform
402
+ }
423
403
}
424
404
}
425
405
426
406
impl CastTarget {
427
- pub fn size ( & self , cx : & CodegenCx ) -> Size {
428
- match * self {
429
- CastTarget :: Uniform ( u) => u. total ,
430
- CastTarget :: Pair ( a, b) => {
431
- ( a. size . abi_align ( a. align ( cx) ) + b. size )
432
- . abi_align ( self . align ( cx) )
433
- } ,
434
- CastTarget :: ChunkedPrefix { total, .. } => total
407
+ pub fn pair ( a : Reg , b : Reg ) -> CastTarget {
408
+ CastTarget {
409
+ prefix : [ Some ( a. kind ) , None , None , None , None , None , None , None ] ,
410
+ prefix_chunk : a. size ,
411
+ rest : Uniform :: from ( b)
435
412
}
436
413
}
437
414
415
+ pub fn size ( & self , cx : & CodegenCx ) -> Size {
416
+ ( self . prefix_chunk * self . prefix . iter ( ) . filter ( |x| x. is_some ( ) ) . count ( ) as u64 )
417
+ . abi_align ( self . rest . align ( cx) ) + self . rest . total
418
+ }
419
+
438
420
pub fn align ( & self , cx : & CodegenCx ) -> Align {
439
- match * self {
440
- CastTarget :: Uniform ( u) => u. align ( cx) ,
441
- CastTarget :: Pair ( a, b) => {
442
- cx. data_layout ( ) . aggregate_align
443
- . max ( a. align ( cx) )
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) )
451
- }
452
- }
421
+ self . prefix . iter ( )
422
+ . filter_map ( |x| x. map ( |kind| Reg { kind : kind, size : self . prefix_chunk } . align ( cx) ) )
423
+ . fold ( cx. data_layout ( ) . aggregate_align . max ( self . rest . align ( cx) ) ,
424
+ |acc, align| acc. max ( align) )
453
425
}
454
426
455
427
pub fn llvm_type ( & self , cx : & CodegenCx ) -> Type {
456
- match * self {
457
- CastTarget :: Uniform ( u) => u. llvm_type ( cx) ,
458
- CastTarget :: Pair ( a, b) => {
459
- Type :: struct_ ( cx, & [
460
- a. llvm_type ( cx) ,
461
- b. llvm_type ( cx)
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) ;
428
+ let rest_ll_unit = self . rest . unit . llvm_type ( cx) ;
429
+ let rest_count = self . rest . total . bytes ( ) / self . rest . unit . size . bytes ( ) ;
430
+ let rem_bytes = self . rest . total . bytes ( ) % self . rest . unit . size . bytes ( ) ;
431
+
432
+ if self . prefix . iter ( ) . all ( |x| x. is_none ( ) ) {
433
+ // Simplify to a single unit when there is no prefix and size <= unit size
434
+ if self . rest . total <= self . rest . unit . size {
435
+ return rest_ll_unit;
436
+ }
470
437
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
- }
438
+ // Simplify to array when all chunks are the same size and type
439
+ if rem_bytes == 0 {
440
+ return Type :: array ( & rest_ll_unit, rest_count) ;
441
+ }
442
+ }
475
443
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
- }
444
+ // Create list of fields in the main structure
445
+ let mut args: Vec < _ > =
446
+ self . prefix . iter ( ) . flat_map ( |option_kind| option_kind. map (
447
+ |kind| Reg { kind : kind, size : self . prefix_chunk } . llvm_type ( cx) ) )
448
+ . chain ( ( 0 ..rest_count) . map ( |_| rest_ll_unit) )
449
+ . collect ( ) ;
489
450
490
- Type :: struct_ ( cx, & args, false )
491
- }
451
+ // Append final integer
452
+ if rem_bytes != 0 {
453
+ // Only integers can be really split further.
454
+ assert_eq ! ( self . rest. unit. kind, RegKind :: Integer ) ;
455
+ args. push ( Type :: ix ( cx, rem_bytes * 8 ) ) ;
492
456
}
457
+
458
+ Type :: struct_ ( cx, & args, false )
493
459
}
494
460
}
495
461
0 commit comments