@@ -13,19 +13,17 @@ use back::link;
13
13
use llvm:: { ValueRef , get_param} ;
14
14
use llvm;
15
15
use middle:: weak_lang_items;
16
- use trans:: abi:: { self , Abi , FnType } ;
16
+ use trans:: abi:: { Abi , FnType } ;
17
17
use trans:: attributes;
18
18
use trans:: base:: { llvm_linkage_by_name, push_ctxt} ;
19
19
use trans:: base;
20
20
use trans:: build:: * ;
21
21
use trans:: common:: * ;
22
22
use trans:: debuginfo:: DebugLoc ;
23
23
use trans:: declare;
24
- use trans:: expr;
25
24
use trans:: machine;
26
25
use trans:: monomorphize;
27
26
use trans:: type_:: Type ;
28
- use trans:: type_of:: * ;
29
27
use trans:: type_of;
30
28
use trans:: value:: Value ;
31
29
use middle:: infer;
@@ -167,17 +165,40 @@ pub fn trans_native_call<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
167
165
}
168
166
}
169
167
170
- let mut offset = 0 ;
171
- for ( i , arg_ty ) in fn_type . args . iter ( ) . enumerate ( ) {
172
- let mut llarg_rust = llargs_rust [ i + offset ] ;
168
+ let mut i = 0 ;
169
+ for & passed_arg_ty in & passed_arg_tys {
170
+ let arg_ty = fn_type . args [ i ] ;
173
171
174
172
if arg_ty. is_ignore ( ) {
173
+ i += 1 ;
174
+ continue ;
175
+ }
176
+
177
+ if type_is_fat_ptr ( ccx. tcx ( ) , passed_arg_ty) {
178
+ // Fat pointers are one pointer and one integer or pointer.
179
+ let ( a, b) = ( fn_type. args [ i] , fn_type. args [ i + 1 ] ) ;
180
+ assert_eq ! ( ( a. cast, b. cast) , ( None , None ) ) ;
181
+ assert ! ( !a. is_indirect( ) && !b. is_indirect( ) ) ;
182
+
183
+ if let Some ( ty) = a. pad {
184
+ llargs_foreign. push ( C_undef ( ty) ) ;
185
+ }
186
+ llargs_foreign. push ( llargs_rust[ i] ) ;
187
+ i += 1 ;
188
+
189
+ if let Some ( ty) = b. pad {
190
+ llargs_foreign. push ( C_undef ( ty) ) ;
191
+ }
192
+ llargs_foreign. push ( llargs_rust[ i] ) ;
193
+ i += 1 ;
175
194
continue ;
176
195
}
177
196
178
197
// Does Rust pass this argument by pointer?
179
- let rust_indirect = type_of:: arg_is_indirect ( ccx, passed_arg_tys [ i ] ) ;
198
+ let rust_indirect = type_of:: arg_is_indirect ( ccx, passed_arg_ty ) ;
180
199
200
+ let mut llarg_rust = llargs_rust[ i] ;
201
+ i += 1 ;
181
202
debug ! ( "argument {}, llarg_rust={:?}, rust_indirect={}, arg_ty={:?}" ,
182
203
i,
183
204
Value ( llarg_rust) ,
@@ -187,24 +208,17 @@ pub fn trans_native_call<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
187
208
// Ensure that we always have the Rust value indirectly,
188
209
// because it makes bitcasting easier.
189
210
if !rust_indirect {
190
- let scratch = base:: alloc_ty ( bcx, passed_arg_tys[ i] , "__arg" ) ;
191
- if type_is_fat_ptr ( ccx. tcx ( ) , passed_arg_tys[ i] ) {
192
- Store ( bcx, llargs_rust[ i + offset] , expr:: get_dataptr ( bcx, scratch) ) ;
193
- Store ( bcx, llargs_rust[ i + offset + 1 ] , expr:: get_meta ( bcx, scratch) ) ;
194
- offset += 1 ;
195
- } else {
196
- base:: store_ty ( bcx, llarg_rust, scratch, passed_arg_tys[ i] ) ;
197
- }
211
+ let scratch = base:: alloc_ty ( bcx, passed_arg_ty, "__arg" ) ;
212
+ base:: store_ty ( bcx, llarg_rust, scratch, passed_arg_ty) ;
198
213
llarg_rust = scratch;
199
214
}
200
215
201
216
debug ! ( "llarg_rust={:?} (after indirection)" ,
202
217
Value ( llarg_rust) ) ;
203
218
204
219
// Check whether we need to do any casting
205
- match arg_ty. cast {
206
- Some ( ty) => llarg_rust = BitCast ( bcx, llarg_rust, ty. ptr_to ( ) ) ,
207
- None => ( )
220
+ if let Some ( ty) = arg_ty. cast {
221
+ llarg_rust = BitCast ( bcx, llarg_rust, ty. ptr_to ( ) ) ;
208
222
}
209
223
210
224
debug ! ( "llarg_rust={:?} (after casting)" ,
@@ -214,22 +228,19 @@ pub fn trans_native_call<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
214
228
let foreign_indirect = arg_ty. is_indirect ( ) ;
215
229
let llarg_foreign = if foreign_indirect {
216
230
llarg_rust
231
+ } else if passed_arg_ty. is_bool ( ) {
232
+ let val = LoadRangeAssert ( bcx, llarg_rust, 0 , 2 , llvm:: False ) ;
233
+ Trunc ( bcx, val, Type :: i1 ( bcx. ccx ( ) ) )
217
234
} else {
218
- if passed_arg_tys[ i] . is_bool ( ) {
219
- let val = LoadRangeAssert ( bcx, llarg_rust, 0 , 2 , llvm:: False ) ;
220
- Trunc ( bcx, val, Type :: i1 ( bcx. ccx ( ) ) )
221
- } else {
222
- Load ( bcx, llarg_rust)
223
- }
235
+ Load ( bcx, llarg_rust)
224
236
} ;
225
237
226
238
debug ! ( "argument {}, llarg_foreign={:?}" ,
227
239
i, Value ( llarg_foreign) ) ;
228
240
229
241
// fill padding with undef value
230
- match arg_ty. pad {
231
- Some ( ty) => llargs_foreign. push ( C_undef ( ty) ) ,
232
- None => ( )
242
+ if let Some ( ty) = arg_ty. pad {
243
+ llargs_foreign. push ( C_undef ( ty) ) ;
233
244
}
234
245
llargs_foreign. push ( llarg_foreign) ;
235
246
}
@@ -552,16 +563,16 @@ pub fn trans_rust_fn_with_foreign_abi<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
552
563
// Build up the arguments to the call to the rust function.
553
564
// Careful to adapt for cases where the native convention uses
554
565
// a pointer and Rust does not or vice versa.
566
+ let mut tys = fn_ty. args . iter ( ) . zip ( rust_param_tys) ;
555
567
for i in 0 ..fn_sig. inputs . len ( ) {
556
568
let rust_ty = fn_sig. inputs [ i] ;
557
569
let rust_indirect = type_of:: arg_is_indirect ( ccx, rust_ty) ;
558
- let llty = rust_param_tys . next ( ) . expect ( "Not enough parameter types!" ) ;
570
+ let ( llforeign_arg_ty , llty) = tys . next ( ) . expect ( "Not enough parameter types!" ) ;
559
571
let llrust_ty = if rust_indirect {
560
572
llty. element_type ( )
561
573
} else {
562
574
llty
563
575
} ;
564
- let llforeign_arg_ty = fn_ty. args [ i] ;
565
576
let foreign_indirect = llforeign_arg_ty. is_indirect ( ) ;
566
577
567
578
if llforeign_arg_ty. is_ignore ( ) {
@@ -574,6 +585,19 @@ pub fn trans_rust_fn_with_foreign_abi<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
574
585
let foreign_index = next_foreign_arg ( llforeign_arg_ty. pad . is_some ( ) ) ;
575
586
let mut llforeign_arg = get_param ( llwrapfn, foreign_index) ;
576
587
588
+ if type_is_fat_ptr ( ccx. tcx ( ) , rust_ty) {
589
+ // Fat pointers are one pointer and one integer or pointer.
590
+ let a = llforeign_arg_ty;
591
+ let ( b, _) = tys. next ( ) . expect ( "Not enough parameter types!" ) ;
592
+ assert_eq ! ( ( a. cast, b. cast) , ( None , None ) ) ;
593
+ assert ! ( !a. is_indirect( ) && !b. is_indirect( ) ) ;
594
+
595
+ llrust_args. push ( llforeign_arg) ;
596
+ let foreign_index = next_foreign_arg ( llforeign_arg_ty. pad . is_some ( ) ) ;
597
+ llrust_args. push ( get_param ( llwrapfn, foreign_index) ) ;
598
+ continue ;
599
+ }
600
+
577
601
debug ! ( "llforeign_arg {}{}: {:?}" , "#" ,
578
602
i, Value ( llforeign_arg) ) ;
579
603
debug ! ( "rust_indirect = {}, foreign_indirect = {}" ,
@@ -624,15 +648,7 @@ pub fn trans_rust_fn_with_foreign_abi<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
624
648
625
649
debug ! ( "llrust_arg {}{}: {:?}" , "#" ,
626
650
i, Value ( llrust_arg) ) ;
627
- if type_is_fat_ptr ( ccx. tcx ( ) , rust_ty) {
628
- let next_llrust_ty = rust_param_tys. next ( ) . expect ( "Not enough parameter types!" ) ;
629
- llrust_args. push ( builder. load ( builder. bitcast ( builder. struct_gep (
630
- llrust_arg, abi:: FAT_PTR_ADDR ) , llrust_ty. ptr_to ( ) ) ) ) ;
631
- llrust_args. push ( builder. load ( builder. bitcast ( builder. struct_gep (
632
- llrust_arg, abi:: FAT_PTR_EXTRA ) , next_llrust_ty. ptr_to ( ) ) ) ) ;
633
- } else {
634
- llrust_args. push ( llrust_arg) ;
635
- }
651
+ llrust_args. push ( llrust_arg) ;
636
652
}
637
653
638
654
// Perform the call itself
0 commit comments