@@ -171,9 +171,10 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
171
171
172
172
let _icx = push_ctxt ( "trans_intrinsic_call" ) ;
173
173
174
- let ret_ty = match callee_ty. sty {
174
+ let ( arg_tys , ret_ty) = match callee_ty. sty {
175
175
ty:: TyBareFn ( _, ref f) => {
176
- bcx. tcx ( ) . erase_late_bound_regions ( & f. sig . output ( ) )
176
+ ( bcx. tcx ( ) . erase_late_bound_regions ( & f. sig . inputs ( ) ) ,
177
+ bcx. tcx ( ) . erase_late_bound_regions ( & f. sig . output ( ) ) )
177
178
}
178
179
_ => panic ! ( "expected bare_fn in trans_intrinsic_call" )
179
180
} ;
@@ -924,25 +925,94 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
924
925
Some ( intr) => intr,
925
926
None => ccx. sess ( ) . span_bug ( foreign_item. span , "unknown intrinsic" ) ,
926
927
} ;
927
- fn ty_to_type ( ccx : & CrateContext , t : & intrinsics:: Type ) -> Type {
928
+ fn one < T > ( x : Vec < T > ) -> T {
929
+ assert_eq ! ( x. len( ) , 1 ) ;
930
+ x. into_iter ( ) . next ( ) . unwrap ( )
931
+ }
932
+ fn ty_to_type ( ccx : & CrateContext , t : & intrinsics:: Type ,
933
+ any_flattened_aggregate : & mut bool ) -> Vec < Type > {
928
934
use intrinsics:: Type :: * ;
929
935
match * t {
930
- Integer ( _signed, x) => Type :: ix ( ccx, x as u64 ) ,
936
+ Integer ( _signed, x) => vec ! [ Type :: ix( ccx, x as u64 ) ] ,
931
937
Float ( x) => {
932
938
match x {
933
- 32 => Type :: f32 ( ccx) ,
934
- 64 => Type :: f64 ( ccx) ,
939
+ 32 => vec ! [ Type :: f32 ( ccx) ] ,
940
+ 64 => vec ! [ Type :: f64 ( ccx) ] ,
935
941
_ => unreachable ! ( )
936
942
}
937
943
}
938
944
Pointer ( _) => unimplemented ! ( ) ,
939
- Vector ( ref t, length) => Type :: vector ( & ty_to_type ( ccx, t) ,
940
- length as u64 )
945
+ Vector ( ref t, length) => {
946
+ let elem = one ( ty_to_type ( ccx, t,
947
+ any_flattened_aggregate) ) ;
948
+ vec ! [ Type :: vector( & elem,
949
+ length as u64 ) ]
950
+ }
951
+ Aggregate ( false , _) => unimplemented ! ( ) ,
952
+ Aggregate ( true , ref contents) => {
953
+ * any_flattened_aggregate = true ;
954
+ contents. iter ( )
955
+ . flat_map ( |t| ty_to_type ( ccx, t, any_flattened_aggregate) )
956
+ . collect ( )
957
+ }
958
+ }
959
+ }
960
+
961
+ // This allows an argument list like `foo, (bar, baz),
962
+ // qux` to be converted into `foo, bar, baz, qux`.
963
+ fn flatten_aggregate < ' blk , ' tcx > ( bcx : Block < ' blk , ' tcx > ,
964
+ t : & intrinsics:: Type ,
965
+ arg_type : Ty < ' tcx > ,
966
+ llarg : ValueRef )
967
+ -> Vec < ValueRef >
968
+ {
969
+ match * t {
970
+ intrinsics:: Type :: Aggregate ( true , ref contents) => {
971
+ // We found a tuple that needs squishing! So
972
+ // run over the tuple and load each field.
973
+ //
974
+ // This assumes the type is "simple", i.e. no
975
+ // destructors, and the contents are SIMD
976
+ // etc.
977
+ assert ! ( !bcx. fcx. type_needs_drop( arg_type) ) ;
978
+
979
+ let repr = adt:: represent_type ( bcx. ccx ( ) , arg_type) ;
980
+ let repr_ptr = & * repr;
981
+ ( 0 ..contents. len ( ) )
982
+ . map ( |i| {
983
+ Load ( bcx, adt:: trans_field_ptr ( bcx, repr_ptr, llarg, 0 , i) )
984
+ } )
985
+ . collect ( )
986
+ }
987
+ _ => vec ! [ llarg] ,
941
988
}
942
989
}
943
990
944
- let inputs = intr. inputs . iter ( ) . map ( |t| ty_to_type ( ccx, t) ) . collect :: < Vec < _ > > ( ) ;
945
- let outputs = ty_to_type ( ccx, & intr. output ) ;
991
+
992
+ let mut any_flattened_aggregate = false ;
993
+ let inputs = intr. inputs . iter ( )
994
+ . flat_map ( |t| ty_to_type ( ccx, t, & mut any_flattened_aggregate) )
995
+ . collect :: < Vec < _ > > ( ) ;
996
+
997
+ let mut out_flattening = false ;
998
+ let outputs = one ( ty_to_type ( ccx, & intr. output , & mut out_flattening) ) ;
999
+ // outputting a flattened aggregate is nonsense
1000
+ assert ! ( !out_flattening) ;
1001
+
1002
+ let llargs = if !any_flattened_aggregate {
1003
+ // no aggregates to flatten, so no change needed
1004
+ llargs
1005
+ } else {
1006
+ // there are some aggregates that need to be flattened
1007
+ // in the LLVM call, so we need to run over the types
1008
+ // again to find them and extract the arguments
1009
+ intr. inputs . iter ( )
1010
+ . zip ( & llargs)
1011
+ . zip ( & arg_tys)
1012
+ . flat_map ( |( ( t, llarg) , ty) | flatten_aggregate ( bcx, t, ty, * llarg) )
1013
+ . collect ( )
1014
+ } ;
1015
+
946
1016
match intr. definition {
947
1017
intrinsics:: IntrinsicDef :: Named ( name) => {
948
1018
let f = declare:: declare_cfn ( ccx,
0 commit comments