@@ -7,12 +7,22 @@ use prelude::*;
7
7
8
8
pub fn cton_sig_from_fn_ty < ' a , ' tcx : ' a > ( tcx : TyCtxt < ' a , ' tcx , ' tcx > , fn_ty : Ty < ' tcx > ) -> Signature {
9
9
let sig = ty_fn_sig ( tcx, fn_ty) ;
10
- let sig = tcx. normalize_erasing_late_bound_regions ( ParamEnv :: reveal_all ( ) , & sig) ;
11
10
assert ! ( !sig. variadic, "Variadic function are not yet supported" ) ;
12
11
let ( call_conv, inputs, _output) : ( CallConv , Vec < Ty > , Ty ) = match sig. abi {
13
12
Abi :: Rust => ( CallConv :: SystemV , sig. inputs ( ) . to_vec ( ) , sig. output ( ) ) ,
14
13
Abi :: RustCall => {
15
- unimplemented ! ( "rust-call" ) ;
14
+ println ! ( "rust-call sig: {:?} inputs: {:?} output: {:?}" , sig, sig. inputs( ) , sig. output( ) ) ;
15
+ let extra_args = match sig. inputs ( ) . last ( ) . unwrap ( ) . sty {
16
+ ty:: TyTuple ( ref tupled_arguments) => tupled_arguments,
17
+ _ => bug ! ( "argument to function with \" rust-call\" ABI is not a tuple" ) ,
18
+ } ;
19
+ let mut inputs: Vec < Ty > = sig. inputs ( ) [ 0 ..sig. inputs ( ) . len ( ) - 1 ] . to_vec ( ) ;
20
+ inputs. extend ( extra_args. into_iter ( ) ) ;
21
+ (
22
+ CallConv :: SystemV ,
23
+ inputs,
24
+ sig. output ( ) ,
25
+ )
16
26
}
17
27
Abi :: System => bug ! ( "system abi should be selected elsewhere" ) ,
18
28
// TODO: properly implement intrinsics
@@ -32,8 +42,8 @@ pub fn cton_sig_from_fn_ty<'a, 'tcx: 'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>, fn_ty: Ty<
32
42
fn ty_fn_sig < ' a , ' tcx > (
33
43
tcx : TyCtxt < ' a , ' tcx , ' tcx > ,
34
44
ty : Ty < ' tcx >
35
- ) -> ty:: PolyFnSig < ' tcx > {
36
- match ty. sty {
45
+ ) -> ty:: FnSig < ' tcx > {
46
+ let sig = match ty. sty {
37
47
ty:: TyFnDef ( ..) |
38
48
// Shims currently have type TyFnPtr. Not sure this should remain.
39
49
ty:: TyFnPtr ( _) => ty. fn_sig ( tcx) ,
@@ -73,7 +83,8 @@ fn ty_fn_sig<'a, 'tcx>(
73
83
} )
74
84
}
75
85
_ => bug ! ( "unexpected type {:?} to ty_fn_sig" , ty)
76
- }
86
+ } ;
87
+ tcx. normalize_erasing_late_bound_regions ( ParamEnv :: reveal_all ( ) , & sig)
77
88
}
78
89
79
90
impl < ' a , ' tcx : ' a > FunctionCx < ' a , ' tcx > {
@@ -91,8 +102,7 @@ impl<'a, 'tcx: 'a> FunctionCx<'a, 'tcx> {
91
102
}
92
103
93
104
fn self_sig ( & self ) -> FnSig < ' tcx > {
94
- let sig = ty_fn_sig ( self . tcx , self . instance . ty ( self . tcx ) ) ;
95
- self . tcx . normalize_erasing_late_bound_regions ( ParamEnv :: reveal_all ( ) , & sig)
105
+ ty_fn_sig ( self . tcx , self . instance . ty ( self . tcx ) )
96
106
}
97
107
98
108
fn return_type ( & self ) -> Ty < ' tcx > {
@@ -153,36 +163,42 @@ pub fn codegen_call<'a, 'tcx: 'a>(
153
163
destination : & Option < ( Place < ' tcx > , BasicBlock ) > ,
154
164
) {
155
165
let func = :: base:: trans_operand ( fx, func) ;
166
+ let fn_ty = func. layout ( ) . ty ;
167
+ let sig = ty_fn_sig ( fx. tcx , fn_ty) ;
156
168
157
169
let return_place = if let Some ( ( place, _) ) = destination {
158
170
Some ( :: base:: trans_place ( fx, place) )
159
171
} else {
160
172
None
161
173
} ;
162
174
163
- let args = args
164
- . into_iter ( )
165
- . map ( |arg| {
166
- let arg = :: base:: trans_operand ( fx, arg) ;
167
- if let Some ( _) = fx. cton_type ( arg. layout ( ) . ty ) {
168
- arg. load_value ( fx)
169
- } else {
170
- arg. force_stack ( fx)
171
- }
172
- } )
173
- . collect :: < Vec < _ > > ( ) ;
175
+ // Unpack arguments tuple for closures
176
+ let args = if sig. abi == Abi :: RustCall {
177
+ assert_eq ! ( args. len( ) , 2 , "rust-call abi requires two arguments" ) ;
178
+ let self_arg = :: base:: trans_operand ( fx, & args[ 0 ] ) ;
179
+ let pack_arg = :: base:: trans_operand ( fx, & args[ 1 ] ) ;
180
+ let mut args = Vec :: new ( ) ;
181
+ args. push ( self_arg) ;
182
+ match pack_arg. layout ( ) . ty . sty {
183
+ ty:: TyTuple ( ref tupled_arguments) => {
184
+ for ( i, _) in tupled_arguments. iter ( ) . enumerate ( ) {
185
+ args. push ( pack_arg. value_field ( fx, mir:: Field :: new ( i) ) ) ;
186
+ }
187
+ } ,
188
+ _ => bug ! ( "argument to function with \" rust-call\" ABI is not a tuple" ) ,
189
+ }
190
+ args
191
+ } else {
192
+ args
193
+ . into_iter ( )
194
+ . map ( |arg| {
195
+ :: base:: trans_operand ( fx, arg)
196
+ } )
197
+ . collect :: < Vec < _ > > ( )
198
+ } ;
174
199
175
- let fn_ty = func. layout ( ) . ty ;
176
200
if let TypeVariants :: TyFnDef ( def_id, substs) = fn_ty. sty {
177
- let instance = ty:: Instance :: resolve (
178
- fx. tcx ,
179
- ParamEnv :: reveal_all ( ) ,
180
- def_id,
181
- substs
182
- ) . unwrap ( ) ;
183
-
184
- // Handle intrinsics old codegen wants Expr's for, ourselves.
185
- if let InstanceDef :: Intrinsic ( def_id) = instance. def {
201
+ if sig. abi == Abi :: RustIntrinsic {
186
202
let intrinsic = fx. tcx . item_name ( def_id) . as_str ( ) ;
187
203
let intrinsic = & intrinsic[ ..] ;
188
204
@@ -218,17 +234,23 @@ pub fn codegen_call<'a, 'tcx: 'a>(
218
234
None => fx. bcx . ins ( ) . iconst ( types:: I64 , 0 ) ,
219
235
} ;
220
236
221
- let args = Some ( return_ptr) . into_iter ( ) . chain ( args) . collect :: < Vec < _ > > ( ) ;
237
+ let call_args = Some ( return_ptr) . into_iter ( ) . chain ( args. into_iter ( ) . map ( |arg| {
238
+ if fx. cton_type ( arg. layout ( ) . ty ) . is_some ( ) {
239
+ arg. load_value ( fx)
240
+ } else {
241
+ arg. force_stack ( fx)
242
+ }
243
+ } ) ) . collect :: < Vec < _ > > ( ) ;
222
244
223
245
match func {
224
246
CValue :: Func ( func, _) => {
225
- fx. bcx . ins ( ) . call ( func, & args ) ;
247
+ fx. bcx . ins ( ) . call ( func, & call_args ) ;
226
248
}
227
249
func => {
228
250
let func_ty = func. layout ( ) . ty ;
229
251
let func = func. load_value ( fx) ;
230
252
let sig = fx. bcx . import_signature ( cton_sig_from_fn_ty ( fx. tcx , func_ty) ) ;
231
- fx. bcx . ins ( ) . call_indirect ( sig, func, & args ) ;
253
+ fx. bcx . ins ( ) . call_indirect ( sig, func, & call_args ) ;
232
254
}
233
255
}
234
256
if let Some ( ( _, dest) ) = * destination {
0 commit comments