@@ -3897,6 +3897,11 @@ fn trans_call(in_cx: @block_ctxt, f: @ast::expr,
3897
3897
// with trans_call.
3898
3898
let tcx = bcx_tcx ( in_cx) ;
3899
3899
let fn_expr_ty = ty:: expr_ty ( tcx, f) ;
3900
+
3901
+ if check type_is_native_fn_on_c_stack ( tcx, fn_expr_ty) {
3902
+ ret trans_c_stack_native_call ( in_cx, f, args) ;
3903
+ }
3904
+
3900
3905
let by_ref = ast_util:: ret_by_ref ( ty:: ty_fn_ret_style ( tcx, fn_expr_ty) ) ;
3901
3906
let cx = new_scope_block_ctxt ( in_cx, "call" ) ;
3902
3907
let f_res = trans_callee ( cx, f) ;
@@ -3977,6 +3982,63 @@ fn trans_call(in_cx: @block_ctxt, f: @ast::expr,
3977
3982
ret { res : rslt ( bcx, retval) , by_ref : by_ref} ;
3978
3983
}
3979
3984
3985
+ // Translates a native call on the C stack. Calls into the runtime to perform
3986
+ // the stack switching operation.
3987
+ fn trans_c_stack_native_call ( bcx : @block_ctxt , f : @ast:: expr ,
3988
+ args : [ @ast:: expr ] )
3989
+ -> { res : result , by_ref : bool } {
3990
+ let ccx = bcx_ccx ( bcx) ;
3991
+ let f_res = trans_callee ( bcx, f) ;
3992
+ let llfn = f_res. val ; bcx = f_res. bcx ;
3993
+
3994
+ // Translate the callee.
3995
+ let fn_ty = ty:: expr_ty ( bcx_tcx ( bcx) , f) ;
3996
+ let fn_arg_tys = ty:: ty_fn_args ( bcx_tcx ( bcx) , fn_ty) ;
3997
+
3998
+ // Translate arguments.
3999
+ let ( to_zero, to_revoke) = ( [ ] , [ ] ) ;
4000
+ let llargs = vec:: map2 ( { |ty_arg, arg|
4001
+ let arg_ty = ty_arg. ty ;
4002
+ check type_has_static_size ( ccx, arg_ty) ;
4003
+ let llargty = type_of ( ccx, f. span , arg_ty) ;
4004
+ let r = trans_arg_expr ( bcx, ty_arg, llargty, to_zero, to_revoke, arg) ;
4005
+ let llargval = r. val ; bcx = r. bcx ;
4006
+ { llval: llargval, llty: llargty }
4007
+ } , fn_arg_tys, args) ;
4008
+
4009
+ // Allocate the argument bundle.
4010
+ let llargbundlety = T_struct ( vec:: map ( { |r| r. llty } , llargs) ) ;
4011
+ let llargbundlesz = llsize_of ( llargbundlety) ;
4012
+ let llrawargbundle = Call ( bcx, ccx. upcalls . alloc_c_stack ,
4013
+ [ llargbundlesz] ) ;
4014
+ let llargbundle = PointerCast ( bcx, llrawargbundle, T_ptr ( llargbundlety) ) ;
4015
+
4016
+ // Copy in arguments.
4017
+ log_err ( "bundle type" , val_str ( ccx. tn , llargbundle) ) ;
4018
+ vec:: eachi ( { |llarg, i|
4019
+ // FIXME: This load is unfortunate.
4020
+ let llargval = Load ( bcx, llarg. llval ) ;
4021
+ log_err ( "llarg type" , val_str ( ccx. tn , llargval) , i) ;
4022
+ store_inbounds ( bcx, llargval, llargbundle, [ C_int ( 0 ) , C_uint ( i) ] ) ;
4023
+ } , llargs) ;
4024
+
4025
+ // Call.
4026
+ // TODO: Invoke instead.
4027
+ let llrawretval = Call ( bcx, ccx. upcalls . call_c_stack ,
4028
+ [ llfn, llrawargbundle] ) ;
4029
+
4030
+ // Cast return type.
4031
+ let ret_ty = ty:: ty_fn_ret ( bcx_tcx ( bcx) , fn_ty) ;
4032
+ check type_has_static_size ( ccx, ret_ty) ;
4033
+ let llretty = type_of ( ccx, f. span , ret_ty) ;
4034
+ let llretval = TruncOrBitCast ( bcx, llrawretval, llretty) ;
4035
+
4036
+ // Forget about anything we moved out.
4037
+ bcx = zero_and_revoke ( bcx, to_zero, to_revoke) ;
4038
+
4039
+ ret { res : rslt ( bcx, llretval) , by_ref : false } ;
4040
+ }
4041
+
3980
4042
fn zero_and_revoke ( bcx : @block_ctxt ,
3981
4043
to_zero : [ { v : ValueRef , t : ty:: t } ] ,
3982
4044
to_revoke : [ { v : ValueRef , t : ty:: t } ] ) -> @block_ctxt {
@@ -5662,7 +5724,7 @@ fn native_fn_ty_param_count(cx: @crate_ctxt, id: ast::node_id) -> uint {
5662
5724
ret count;
5663
5725
}
5664
5726
5665
- fn native_abi_requires_pair ( abi : ast:: native_abi ) -> bool {
5727
+ pure fn native_abi_requires_pair ( abi: ast:: native_abi) -> bool {
5666
5728
alt abi {
5667
5729
ast : : native_abi_rust. | ast:: native_abi_cdecl. |
5668
5730
ast:: native_abi_llvm. | ast:: native_abi_rust_intrinsic. |
@@ -5671,6 +5733,13 @@ fn native_abi_requires_pair(abi: ast::native_abi) -> bool {
5671
5733
}
5672
5734
}
5673
5735
5736
+ pure fn type_is_native_fn_on_c_stack ( tcx: ty:: ctxt, t: ty:: t) -> bool {
5737
+ alt ty:: struct ( tcx, t) {
5738
+ ty:: ty_native_fn ( abi, _, _) { ret ! native_abi_requires_pair( abi) ; }
5739
+ _ { ret false; }
5740
+ }
5741
+ }
5742
+
5674
5743
fn native_fn_wrapper_type ( cx : @crate_ctxt , sp : span , ty_param_count : uint ,
5675
5744
x : ty:: t ) -> TypeRef {
5676
5745
alt ty:: struct ( cx. tcx , x) {
@@ -5690,32 +5759,8 @@ fn raw_native_fn_type(ccx: @crate_ctxt, sp: span, args: [ty::arg],
5690
5759
5691
5760
fn register_native_fn( ccx : @crate_ctxt , sp : span , path : [ str ] , name : str ,
5692
5761
id : ast:: node_id ) {
5693
- let path = path;
5694
- let num_ty_param = native_fn_ty_param_count ( ccx, id) ;
5695
- // Declare the wrapper.
5696
-
5697
- let t = node_id_type ( ccx, id) ;
5698
- let wrapper_type = native_fn_wrapper_type ( ccx, sp, num_ty_param, t) ;
5699
- let ps: str = mangle_exported_name ( ccx, path, node_id_type ( ccx, id) ) ;
5700
- let wrapper_fn = decl_cdecl_fn ( ccx. llmod , ps, wrapper_type) ;
5701
- ccx. item_ids . insert ( id, wrapper_fn) ;
5702
- ccx. item_symbols . insert ( id, ps) ;
5703
-
5704
- // Build the wrapper.
5705
- let fcx = new_fn_ctxt ( new_local_ctxt ( ccx) , sp, wrapper_fn) ;
5706
- let bcx = new_top_block_ctxt ( fcx) ;
5707
- let lltop = bcx. llbb ;
5708
-
5709
- // Declare the function itself.
5710
5762
let fn_type = node_id_type ( ccx, id) ; // NB: has no type params
5711
-
5712
5763
let abi = ty:: ty_fn_abi ( ccx. tcx , fn_type) ;
5713
- // FIXME: If the returned type is not nil, then we assume it's 32 bits
5714
- // wide. This is obviously wildly unsafe. We should have a better FFI
5715
- // that allows types of different sizes to be returned.
5716
-
5717
- let rty = ty:: ty_fn_ret ( ccx. tcx , fn_type) ;
5718
- let rty_is_nil = ty:: type_is_nil ( ccx. tcx , rty) ;
5719
5764
5720
5765
let pass_task;
5721
5766
let uses_retptr;
@@ -5747,10 +5792,37 @@ fn register_native_fn(ccx: @crate_ctxt, sp: span, path: [str], name: str,
5747
5792
cast_to_i32 = true ;
5748
5793
}
5749
5794
ast:: native_abi_c_stack_cdecl. {
5750
- fail "C stack cdecl ABI shouldn't have a wrapper" ;
5795
+ let llfn = decl_cdecl_fn ( ccx. llmod , name, T_fn ( [ ] , T_void ( ) ) ) ;
5796
+ ccx. item_ids . insert ( id, llfn) ;
5797
+ ccx. item_symbols . insert ( id, name) ;
5798
+ ret;
5751
5799
}
5752
5800
}
5753
5801
5802
+ let path = path;
5803
+ let num_ty_param = native_fn_ty_param_count ( ccx, id) ;
5804
+ // Declare the wrapper.
5805
+
5806
+ let t = node_id_type ( ccx, id) ;
5807
+ let wrapper_type = native_fn_wrapper_type ( ccx, sp, num_ty_param, t) ;
5808
+ let ps: str = mangle_exported_name ( ccx, path, node_id_type ( ccx, id) ) ;
5809
+ let wrapper_fn = decl_cdecl_fn ( ccx. llmod , ps, wrapper_type) ;
5810
+ ccx. item_ids . insert ( id, wrapper_fn) ;
5811
+ ccx. item_symbols . insert ( id, ps) ;
5812
+
5813
+ // Build the wrapper.
5814
+ let fcx = new_fn_ctxt ( new_local_ctxt ( ccx) , sp, wrapper_fn) ;
5815
+ let bcx = new_top_block_ctxt ( fcx) ;
5816
+ let lltop = bcx. llbb ;
5817
+
5818
+ // Declare the function itself.
5819
+ // FIXME: If the returned type is not nil, then we assume it's 32 bits
5820
+ // wide. This is obviously wildly unsafe. We should have a better FFI
5821
+ // that allows types of different sizes to be returned.
5822
+
5823
+ let rty = ty:: ty_fn_ret ( ccx. tcx , fn_type) ;
5824
+ let rty_is_nil = ty:: type_is_nil ( ccx. tcx , rty) ;
5825
+
5754
5826
let lltaskptr;
5755
5827
if cast_to_i32 {
5756
5828
lltaskptr = vp2i ( bcx, fcx. lltaskptr ) ;
0 commit comments