@@ -420,7 +420,7 @@ impl CastTarget {
420
420
/// should be passed to or returned from a function
421
421
///
422
422
/// This is borrowed from clang's ABIInfo.h
423
- #[ derive( Clone , Copy , Debug ) ]
423
+ #[ derive( Debug ) ]
424
424
pub struct ArgType < ' tcx > {
425
425
kind : ArgKind ,
426
426
pub layout : FullLayout < ' tcx > ,
@@ -429,7 +429,8 @@ pub struct ArgType<'tcx> {
429
429
/// Dummy argument, which is emitted before the real argument.
430
430
pub pad : Option < Reg > ,
431
431
/// Attributes of argument.
432
- pub attrs : ArgAttributes
432
+ pub attrs : ArgAttributes ,
433
+ pub nested : Vec < ArgType < ' tcx > >
433
434
}
434
435
435
436
impl < ' a , ' tcx > ArgType < ' tcx > {
@@ -439,11 +440,13 @@ impl<'a, 'tcx> ArgType<'tcx> {
439
440
layout,
440
441
cast : None ,
441
442
pad : None ,
442
- attrs : ArgAttributes :: default ( )
443
+ attrs : ArgAttributes :: default ( ) ,
444
+ nested : vec ! [ ]
443
445
}
444
446
}
445
447
446
448
pub fn make_indirect ( & mut self , ccx : & CrateContext < ' a , ' tcx > ) {
449
+ assert ! ( self . nested. is_empty( ) ) ;
447
450
assert_eq ! ( self . kind, ArgKind :: Direct ) ;
448
451
449
452
// Wipe old attributes, likely not valid through indirection.
@@ -460,6 +463,7 @@ impl<'a, 'tcx> ArgType<'tcx> {
460
463
}
461
464
462
465
pub fn ignore ( & mut self ) {
466
+ assert ! ( self . nested. is_empty( ) ) ;
463
467
assert_eq ! ( self . kind, ArgKind :: Direct ) ;
464
468
self . kind = ArgKind :: Ignore ;
465
469
}
@@ -482,10 +486,12 @@ impl<'a, 'tcx> ArgType<'tcx> {
482
486
}
483
487
484
488
pub fn cast_to < T : Into < CastTarget > > ( & mut self , target : T ) {
489
+ assert ! ( self . nested. is_empty( ) ) ;
485
490
self . cast = Some ( target. into ( ) ) ;
486
491
}
487
492
488
493
pub fn pad_with ( & mut self , reg : Reg ) {
494
+ assert ! ( self . nested. is_empty( ) ) ;
489
495
self . pad = Some ( reg) ;
490
496
}
491
497
@@ -561,6 +567,12 @@ impl<'a, 'tcx> ArgType<'tcx> {
561
567
}
562
568
563
569
pub fn store_fn_arg ( & self , bcx : & Builder < ' a , ' tcx > , idx : & mut usize , dst : LvalueRef < ' tcx > ) {
570
+ if !self . nested . is_empty ( ) {
571
+ for ( i, arg) in self . nested . iter ( ) . enumerate ( ) {
572
+ arg. store_fn_arg ( bcx, idx, dst. project_field ( bcx, i) ) ;
573
+ }
574
+ return ;
575
+ }
564
576
if self . pad . is_some ( ) {
565
577
* idx += 1 ;
566
578
}
@@ -578,7 +590,7 @@ impl<'a, 'tcx> ArgType<'tcx> {
578
590
///
579
591
/// I will do my best to describe this structure, but these
580
592
/// comments are reverse-engineered and may be inaccurate. -NDM
581
- #[ derive( Clone , Debug ) ]
593
+ #[ derive( Debug ) ]
582
594
pub struct FnType < ' tcx > {
583
595
/// The LLVM types of each argument.
584
596
pub args : Vec < ArgType < ' tcx > > ,
@@ -613,7 +625,8 @@ impl<'a, 'tcx> FnType<'tcx> {
613
625
extra_args : & [ Ty < ' tcx > ] ) -> FnType < ' tcx > {
614
626
let mut fn_ty = FnType :: unadjusted ( ccx, sig, extra_args) ;
615
627
// Don't pass the vtable, it's not an argument of the virtual fn.
616
- fn_ty. args [ 1 ] . ignore ( ) ;
628
+ assert_eq ! ( fn_ty. args[ 0 ] . nested. len( ) , 2 ) ;
629
+ fn_ty. args [ 0 ] . nested [ 1 ] . ignore ( ) ;
617
630
fn_ty. adjust_for_abi ( ccx, sig) ;
618
631
fn_ty
619
632
}
@@ -766,7 +779,7 @@ impl<'a, 'tcx> FnType<'tcx> {
766
779
for ty in inputs. iter ( ) . chain ( extra_args. iter ( ) ) {
767
780
let mut arg = arg_of ( ty, false ) ;
768
781
769
- if let ty:: layout :: Layout :: FatPointer { .. } = * arg . layout . layout {
782
+ if type_is_fat_ptr ( ccx , ty) {
770
783
let mut data = ArgType :: new ( arg. layout . field ( ccx, 0 ) ) ;
771
784
let mut info = ArgType :: new ( arg. layout . field ( ccx, 1 ) ) ;
772
785
@@ -780,14 +793,16 @@ impl<'a, 'tcx> FnType<'tcx> {
780
793
info. attrs . set ( ArgAttribute :: NoAlias ) ;
781
794
}
782
795
}
783
- args. push ( data) ;
784
- args. push ( info) ;
796
+ // FIXME(eddyb) other ABIs don't have logic for nested.
797
+ if rust_abi {
798
+ arg. nested = vec ! [ data, info] ;
799
+ }
785
800
} else {
786
801
if let Some ( inner) = rust_ptr_attrs ( ty, & mut arg) {
787
802
arg. attrs . set_dereferenceable ( ccx. size_of ( inner) ) ;
788
803
}
789
- args. push ( arg) ;
790
804
}
805
+ args. push ( arg) ;
791
806
}
792
807
793
808
FnType {
@@ -854,6 +869,13 @@ impl<'a, 'tcx> FnType<'tcx> {
854
869
}
855
870
for arg in & mut self . args {
856
871
if arg. is_ignore ( ) { continue ; }
872
+ if !arg. nested . is_empty ( ) {
873
+ for arg in & mut arg. nested {
874
+ assert ! ( arg. nested. is_empty( ) ) ;
875
+ fixup ( arg) ;
876
+ }
877
+ continue ;
878
+ }
857
879
fixup ( arg) ;
858
880
}
859
881
if self . ret . is_indirect ( ) {
@@ -915,24 +937,36 @@ impl<'a, 'tcx> FnType<'tcx> {
915
937
ccx. immediate_llvm_type_of ( self . ret . layout . ty )
916
938
} ;
917
939
918
- for arg in & self . args {
919
- if arg. is_ignore ( ) {
920
- continue ;
921
- }
922
- // add padding
923
- if let Some ( ty) = arg. pad {
924
- llargument_tys. push ( ty. llvm_type ( ccx) ) ;
925
- }
940
+ {
941
+ let mut push = |arg : & ArgType < ' tcx > | {
942
+ if arg. is_ignore ( ) {
943
+ return ;
944
+ }
945
+ // add padding
946
+ if let Some ( ty) = arg. pad {
947
+ llargument_tys. push ( ty. llvm_type ( ccx) ) ;
948
+ }
926
949
927
- let llarg_ty = if arg. is_indirect ( ) {
928
- arg. memory_ty ( ccx) . ptr_to ( )
929
- } else if let Some ( cast) = arg. cast {
930
- cast. llvm_type ( ccx)
931
- } else {
932
- ccx. immediate_llvm_type_of ( arg. layout . ty )
933
- } ;
950
+ let llarg_ty = if arg. is_indirect ( ) {
951
+ arg. memory_ty ( ccx) . ptr_to ( )
952
+ } else if let Some ( cast) = arg. cast {
953
+ cast. llvm_type ( ccx)
954
+ } else {
955
+ ccx. immediate_llvm_type_of ( arg. layout . ty )
956
+ } ;
934
957
935
- llargument_tys. push ( llarg_ty) ;
958
+ llargument_tys. push ( llarg_ty) ;
959
+ } ;
960
+ for arg in & self . args {
961
+ if !arg. nested . is_empty ( ) {
962
+ for arg in & arg. nested {
963
+ assert ! ( arg. nested. is_empty( ) ) ;
964
+ push ( arg) ;
965
+ }
966
+ continue ;
967
+ }
968
+ push ( arg) ;
969
+ }
936
970
}
937
971
938
972
if self . variadic {
@@ -948,12 +982,22 @@ impl<'a, 'tcx> FnType<'tcx> {
948
982
self . ret . attrs . apply_llfn ( llvm:: AttributePlace :: Argument ( i) , llfn) ;
949
983
}
950
984
i += 1 ;
951
- for arg in & self . args {
985
+ let mut apply = | arg : & ArgType | {
952
986
if !arg. is_ignore ( ) {
953
987
if arg. pad . is_some ( ) { i += 1 ; }
954
988
arg. attrs . apply_llfn ( llvm:: AttributePlace :: Argument ( i) , llfn) ;
955
989
i += 1 ;
956
990
}
991
+ } ;
992
+ for arg in & self . args {
993
+ if !arg. nested . is_empty ( ) {
994
+ for arg in & arg. nested {
995
+ assert ! ( arg. nested. is_empty( ) ) ;
996
+ apply ( arg) ;
997
+ }
998
+ continue ;
999
+ }
1000
+ apply ( arg) ;
957
1001
}
958
1002
}
959
1003
@@ -963,12 +1007,22 @@ impl<'a, 'tcx> FnType<'tcx> {
963
1007
self . ret . attrs . apply_callsite ( llvm:: AttributePlace :: Argument ( i) , callsite) ;
964
1008
}
965
1009
i += 1 ;
966
- for arg in & self . args {
1010
+ let mut apply = | arg : & ArgType | {
967
1011
if !arg. is_ignore ( ) {
968
1012
if arg. pad . is_some ( ) { i += 1 ; }
969
1013
arg. attrs . apply_callsite ( llvm:: AttributePlace :: Argument ( i) , callsite) ;
970
1014
i += 1 ;
971
1015
}
1016
+ } ;
1017
+ for arg in & self . args {
1018
+ if !arg. nested . is_empty ( ) {
1019
+ for arg in & arg. nested {
1020
+ assert ! ( arg. nested. is_empty( ) ) ;
1021
+ apply ( arg) ;
1022
+ }
1023
+ continue ;
1024
+ }
1025
+ apply ( arg) ;
972
1026
}
973
1027
974
1028
if self . cconv != llvm:: CCallConv {
0 commit comments