@@ -17,8 +17,11 @@ use trans::base;
17
17
use trans:: build;
18
18
use trans:: common:: { self , Block } ;
19
19
use trans:: debuginfo:: DebugLoc ;
20
+ use trans:: foreign;
20
21
use trans:: type_of;
21
22
23
+ use syntax:: abi as synabi;
24
+
22
25
use super :: MirContext ;
23
26
use super :: operand:: OperandValue :: { FatPtr , Immediate , Ref } ;
24
27
@@ -112,19 +115,24 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
112
115
// Create the callee. This will always be a fn
113
116
// ptr and hence a kind of scalar.
114
117
let callee = self . trans_operand ( bcx, & data. func ) ;
115
- let ret_ty = if let ty:: TyBareFn ( _, ref f) = callee. ty . sty {
118
+ let ( abi , ret_ty) = if let ty:: TyBareFn ( _, ref f) = callee. ty . sty {
116
119
let sig = bcx. tcx ( ) . erase_late_bound_regions ( & f. sig ) ;
117
120
let sig = infer:: normalize_associated_type ( bcx. tcx ( ) , & sig) ;
118
- sig. output
121
+ ( f . abi , sig. output )
119
122
} else {
120
123
panic ! ( "trans_block: expected TyBareFn as callee" ) ;
121
124
} ;
122
125
126
+ // Have we got a 'Rust' function?
127
+ let is_rust_fn = abi == synabi:: Rust || abi == synabi:: RustCall ;
128
+
123
129
// The arguments we'll be passing
124
- let mut llargs = vec ! [ ] ;
130
+ let mut llargs = Vec :: with_capacity ( data. args . len ( ) + 1 ) ;
131
+ // and their Rust types (formal args only so not outptr)
132
+ let mut arg_tys = Vec :: with_capacity ( data. args . len ( ) ) ;
125
133
126
134
// Does the fn use an outptr? If so, that's the first arg.
127
- if let ty:: FnConverging ( ret_ty) = ret_ty {
135
+ if let ( true , ty:: FnConverging ( ret_ty) ) = ( is_rust_fn , ret_ty) {
128
136
if type_of:: return_uses_outptr ( bcx. ccx ( ) , ret_ty) {
129
137
llargs. push ( call_dest. llval ) ;
130
138
}
@@ -133,6 +141,7 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
133
141
// Process the rest of the args.
134
142
for arg in & data. args {
135
143
let arg_op = self . trans_operand ( bcx, arg) ;
144
+ arg_tys. push ( arg_op. ty ) ;
136
145
match arg_op. val {
137
146
Ref ( llval) | Immediate ( llval) => llargs. push ( llval) ,
138
147
FatPtr ( base, extra) => {
@@ -148,19 +157,29 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
148
157
//self.make_landing_pad(panic_bb);
149
158
150
159
// Do the actual call.
151
- let ( llret, b) = base:: invoke ( bcx,
152
- callee. immediate ( ) ,
153
- & llargs[ ..] ,
154
- callee. ty ,
155
- DebugLoc :: None ) ;
156
- bcx = b;
157
-
158
- // Copy the return value into the destination.
159
- if let ty:: FnConverging ( ret_ty) = ret_ty {
160
- if !type_of:: return_uses_outptr ( bcx. ccx ( ) , ret_ty) &&
161
- !common:: type_is_zero_size ( bcx. ccx ( ) , ret_ty) {
162
- base:: store_ty ( bcx, llret, call_dest. llval , ret_ty) ;
160
+ if is_rust_fn {
161
+ let ( llret, b) = base:: invoke ( bcx,
162
+ callee. immediate ( ) ,
163
+ & llargs,
164
+ callee. ty ,
165
+ DebugLoc :: None ) ;
166
+ bcx = b;
167
+
168
+ // Copy the return value into the destination.
169
+ if let ty:: FnConverging ( ret_ty) = ret_ty {
170
+ if !type_of:: return_uses_outptr ( bcx. ccx ( ) , ret_ty) &&
171
+ !common:: type_is_zero_size ( bcx. ccx ( ) , ret_ty) {
172
+ base:: store_ty ( bcx, llret, call_dest. llval , ret_ty) ;
173
+ }
163
174
}
175
+ } else {
176
+ bcx = foreign:: trans_native_call ( bcx,
177
+ callee. ty ,
178
+ callee. immediate ( ) ,
179
+ call_dest. llval ,
180
+ & llargs,
181
+ arg_tys,
182
+ DebugLoc :: None ) ;
164
183
}
165
184
166
185
build:: Br ( bcx, self . llblock ( targets. 0 ) , DebugLoc :: None )
0 commit comments