@@ -1607,8 +1607,8 @@ fn compare_scalar_values(cx: @block_ctxt, lhs: ValueRef, rhs: ValueRef,
1607
1607
type val_pair_fn = fn ( @block_ctxt , ValueRef , ValueRef ) -> @block_ctxt ;
1608
1608
type val_and_ty_fn = fn ( @block_ctxt , ValueRef , ty:: t ) -> @block_ctxt ;
1609
1609
1610
- fn load_inbounds ( cx : @block_ctxt , p : ValueRef , idxs : [ ValueRef ] ) -> ValueRef {
1611
- ret Load ( cx, InBoundsGEP ( cx, p, idxs) ) ;
1610
+ fn load_inbounds ( cx : @block_ctxt , p : ValueRef , idxs : [ int ] ) -> ValueRef {
1611
+ ret Load ( cx, GEPi ( cx, p, idxs) ) ;
1612
1612
}
1613
1613
1614
1614
fn store_inbounds ( cx : @block_ctxt , v : ValueRef , p : ValueRef ,
@@ -3833,7 +3833,7 @@ fn trans_call(in_cx: @block_ctxt, f: @ast::expr,
3833
3833
}
3834
3834
3835
3835
// Translates a native call on the C stack. Calls into the runtime to perform
3836
- // the stack switching operation.
3836
+ // the stack switching operation. Must be kept in sync with trans_native_mod().
3837
3837
fn trans_c_stack_native_call ( bcx : @block_ctxt , f : @ast:: expr ,
3838
3838
args : [ @ast:: expr ] , dest : dest ) -> @block_ctxt {
3839
3839
let ccx = bcx_ccx ( bcx) ;
@@ -3846,74 +3846,37 @@ fn trans_c_stack_native_call(bcx: @block_ctxt, f: @ast::expr,
3846
3846
let fn_arg_tys = ty:: ty_fn_args ( bcx_tcx ( bcx) , fn_ty) ;
3847
3847
let llargtys = type_of_explicit_args ( ccx, f. span , fn_arg_tys) ;
3848
3848
3849
- // Translate arguments.
3850
- let ( to_zero, to_revoke) = ( [ ] , [ ] ) ;
3851
- let i = 0 u, n = vec:: len ( args) ;
3852
- let llargs = [ ] ;
3853
- while i < n {
3854
- let ty_arg = fn_arg_tys[ i] ;
3855
- let arg = args[ i] ;
3856
- let llargty = llargtys[ i] ;
3857
- let r = trans_arg_expr ( bcx, ty_arg, llargty, to_zero, to_revoke, arg) ;
3858
- let llargval = r. val ; bcx = r. bcx ;
3859
- llargs += [
3860
- { llval: llargval, llty: llargty }
3861
- ] ;
3862
- i += 1 u;
3863
- }
3849
+ // Determine return type.
3850
+ let ret_ty = ty:: ty_fn_ret ( bcx_tcx ( bcx) , fn_ty) ;
3851
+ check type_has_static_size ( ccx, ret_ty) ;
3852
+ let llretty = type_of ( ccx, f. span , ret_ty) ;
3864
3853
3865
3854
// Allocate the argument bundle.
3866
- let llargbundlety = T_struct ( vec :: map ( { |r| r . llty } , llargs ) ) ;
3855
+ let llargbundlety = T_struct ( llargtys + [ llretty ] ) ;
3867
3856
let llargbundlesz = llsize_of ( ccx, llargbundlety) ;
3868
3857
let llrawargbundle = Call ( bcx, ccx. upcalls . alloc_c_stack ,
3869
3858
[ llargbundlesz] ) ;
3870
3859
let llargbundle = PointerCast ( bcx, llrawargbundle, T_ptr ( llargbundlety) ) ;
3871
3860
3872
- // Copy in arguments.
3873
- let i = 0 u, n = vec:: len ( llargs) ;
3861
+ // Translate arguments and store into bundle.
3862
+ let ( to_zero, to_revoke) = ( [ ] , [ ] ) ;
3863
+ let i = 0 u, n = vec:: len ( args) ;
3874
3864
while i < n {
3875
- let llarg = llargs[ i] . llval ;
3876
- store_inbounds ( bcx, llarg, llargbundle, [ 0 , i as int ] ) ;
3865
+ let ty_arg = fn_arg_tys[ i] ;
3866
+ let arg = args[ i] ;
3867
+ let llargty = llargtys[ i] ;
3868
+ let r = trans_arg_expr ( bcx, ty_arg, llargty, to_zero, to_revoke, arg) ;
3869
+ bcx = r. bcx ;
3870
+ store_inbounds ( bcx, r. val , llargbundle, [ 0 , i as int ] ) ;
3877
3871
i += 1 u;
3878
3872
}
3879
3873
3880
- // Determine return type.
3881
- let ret_ty = ty:: ty_fn_ret ( bcx_tcx ( bcx) , fn_ty) ;
3882
- check type_has_static_size ( ccx, ret_ty) ;
3883
- let llretty = type_of ( ccx, f. span , ret_ty) ;
3884
-
3885
- // Determine which upcall fn to use based on the return type.
3886
- let upcall_fn = alt lib:: llvm:: llvm:: LLVMGetTypeKind ( llretty) {
3887
- 1 | 2 | 3 | 4 | 5 {
3888
- // LLVMFloatTypeKind, LLVMDoubleTypeKind,
3889
- // LLVMX86_FP80TypeKind, LLVMFP128TypeKind
3890
- // LLVMPPC_FP128TypeKind
3891
- ccx. upcalls . call_c_stack_float
3892
- }
3893
-
3894
- 7 {
3895
- // LLVMIntegerTypeKind
3896
- let width = lib:: llvm:: llvm:: LLVMGetIntTypeWidth ( llretty) ;
3897
- if width == 64 u { ccx. upcalls . call_c_stack_i64 }
3898
- else { ccx. upcalls . call_c_stack } // on 64-bit target, no diff
3899
- }
3900
-
3901
- _ { ccx. upcalls . call_c_stack }
3902
- } ;
3903
-
3904
- // Call and cast the return type.
3905
- // TODO: Invoke instead.
3906
- let llrawretval = Call ( bcx, upcall_fn, [ llfn, llrawargbundle] ) ;
3907
- let llretval;
3908
- if lib:: llvm:: llvm:: LLVMGetTypeKind ( llretty) as int == 11 { // pointer
3909
- llretval = IntToPtr ( bcx, llrawretval, llretty) ;
3910
- } else {
3911
- llretval = TruncOrBitCast ( bcx, llrawretval, llretty) ;
3912
- }
3913
-
3914
- // Forget about anything we moved out.
3915
- bcx = zero_and_revoke ( bcx, to_zero, to_revoke) ;
3916
- ret store_in_dest ( bcx, llretval, dest) ;
3874
+ // Call the upcall function then extract return value from the bundle.
3875
+ let upcall_fn = ccx. upcalls . call_c_stack_shim ;
3876
+ let llfnptr = PointerCast ( bcx, llfn, T_ptr ( T_i8 ( ) ) ) ;
3877
+ Call ( bcx, upcall_fn, [ llfnptr, llrawargbundle] ) ;
3878
+ let llres = load_inbounds ( bcx, llargbundle, [ 0 , n as int ] ) ;
3879
+ ret store_in_dest ( bcx, llres, dest) ;
3917
3880
}
3918
3881
3919
3882
fn zero_and_revoke ( bcx : @block_ctxt ,
@@ -5373,6 +5336,116 @@ fn trans_const(cx: @crate_ctxt, e: @ast::expr, id: ast::node_id) {
5373
5336
}
5374
5337
}
5375
5338
5339
+ type c_stack_tys = {
5340
+ arg_tys : [ TypeRef ] ,
5341
+ ret_ty : TypeRef ,
5342
+ base_fn_ty : TypeRef ,
5343
+ bundle_ty : TypeRef ,
5344
+ shim_fn_ty : TypeRef
5345
+ } ;
5346
+
5347
+ fn c_stack_tys ( ccx : @crate_ctxt ,
5348
+ sp : span ,
5349
+ id : ast:: node_id ) -> @c_stack_tys {
5350
+ alt ty:: struct ( ccx. tcx , ty:: node_id_to_type ( ccx. tcx , id) ) {
5351
+ ty:: ty_native_fn ( _, arg_tys, ret_ty) {
5352
+ let llargtys = type_of_explicit_args ( ccx, sp, arg_tys) ;
5353
+ check non_ty_var( ccx, ret_ty) ; // NDM does this truly hold?
5354
+ let llretty = type_of_inner ( ccx, sp, ret_ty) ;
5355
+ let bundle_ty = T_struct ( llargtys + [ llretty] ) ;
5356
+ ret @{
5357
+ arg_tys : llargtys,
5358
+ ret_ty : llretty,
5359
+ base_fn_ty : T_fn ( llargtys, llretty) ,
5360
+ bundle_ty : bundle_ty,
5361
+ shim_fn_ty : T_fn ( [ T_ptr ( bundle_ty) ] , T_void ( ) )
5362
+ } ;
5363
+ }
5364
+
5365
+ _ {
5366
+ ccx. sess . span_fatal (
5367
+ sp,
5368
+ "Non-function type for native fn" ) ;
5369
+ }
5370
+ }
5371
+ }
5372
+
5373
+ // For c-stack ABIs, we must generate shim functions for making
5374
+ // the call. These shim functions will unpack arguments out of
5375
+ // a struct and then invoke the base function.
5376
+ //
5377
+ // Example: Given a native c-stack function F(x: X, y: Y) -> Z,
5378
+ // we generate a shim function S that is something like:
5379
+ //
5380
+ // void S(struct F_Args { X x; Y y; Z *z; } *args) {
5381
+ // *args->z = F(args->x, args->y);
5382
+ // }
5383
+ //
5384
+ fn trans_native_mod ( lcx : @local_ctxt , native_mod : ast:: native_mod ) {
5385
+ fn build_shim_fn ( lcx : @local_ctxt , native_item : @ast:: native_item ,
5386
+ llshimfn : ValueRef ) {
5387
+ let ccx = lcx_ccx ( lcx) ;
5388
+ let span = native_item. span ;
5389
+ let id = native_item. id ;
5390
+ let tys = c_stack_tys ( ccx, span, id) ;
5391
+
5392
+ // Declare the "prototype" for the base function F:
5393
+ let name = native_item. ident ;
5394
+ let llbasefn = decl_cdecl_fn ( ccx. llmod , name, tys. base_fn_ty ) ;
5395
+
5396
+ // Declare the body of the shim function:
5397
+ let fcx = new_fn_ctxt ( lcx, span, llshimfn) ;
5398
+ let bcx = new_top_block_ctxt ( fcx) ;
5399
+ let lltop = bcx. llbb ;
5400
+ let llargbundle = llvm:: LLVMGetParam ( llshimfn, 0 u) ;
5401
+ let i = 0 u, n = vec:: len ( tys. arg_tys ) ;
5402
+ let llargvals = [ ] ;
5403
+ while i < n {
5404
+ let llargval = load_inbounds ( bcx, llargbundle, [ 0 , i as int ] ) ;
5405
+ llargvals += [ llargval] ;
5406
+ i += 1 u;
5407
+ }
5408
+
5409
+ // Create the call itself:
5410
+ let llretval = Call ( bcx, llbasefn, llargvals) ;
5411
+ //log_err("llretval", val_str(ccx.tn, llretval),
5412
+ // "llargbundle", val_str(ccx.tn, llargbundle),
5413
+ // "tys.ret_ty", ty_str(ccx.tn, tys.ret_ty),
5414
+ // "n", n);
5415
+ store_inbounds ( bcx, llretval, llargbundle, [ 0 , n as int ] ) ;
5416
+
5417
+ // Finish up.
5418
+ build_return ( bcx) ;
5419
+ finish_fn ( fcx, lltop) ;
5420
+ }
5421
+
5422
+ let ccx = lcx_ccx ( lcx) ;
5423
+ alt native_mod. abi {
5424
+ ast:: native_abi_cdecl. {
5425
+ for native_item in native_mod. items {
5426
+ alt native_item. node {
5427
+ ast:: native_item_ty. { }
5428
+ ast:: native_item_fn ( _, fn_decl, _) {
5429
+ let id = native_item. id ;
5430
+ alt ccx. item_ids . find ( id) {
5431
+ some ( llshimfn) {
5432
+ build_shim_fn ( lcx, native_item, llshimfn) ;
5433
+ }
5434
+
5435
+ none. {
5436
+ ccx . sess . span_fatal (
5437
+ native_item. span ,
5438
+ "unbound function item in trans_native_mod" ) ;
5439
+ }
5440
+ }
5441
+ }
5442
+ }
5443
+ }
5444
+ }
5445
+ _ { /* nothing to do for other ABIs */ }
5446
+ }
5447
+ }
5448
+
5376
5449
fn trans_item ( cx : @local_ctxt , item : ast:: item ) {
5377
5450
alt item. node {
5378
5451
ast:: item_fn ( f, tps) {
@@ -5422,6 +5495,9 @@ fn trans_item(cx: @local_ctxt, item: ast::item) {
5422
5495
}
5423
5496
}
5424
5497
ast:: item_const ( _, expr) { trans_const ( cx. ccx , expr, item. id ) ; }
5498
+ ast:: item_native_mod ( native_mod) {
5499
+ trans_native_mod ( cx, native_mod) ;
5500
+ }
5425
5501
_ { /* fall through */ }
5426
5502
}
5427
5503
}
@@ -5641,9 +5717,12 @@ fn register_native_fn(ccx: @crate_ctxt, sp: span, path: [str], name: str,
5641
5717
cast_to_i32 = false ;
5642
5718
}
5643
5719
ast:: native_abi_cdecl. {
5644
- let llfn = decl_cdecl_fn ( ccx. llmod , name, T_fn ( [ ] , ccx. int_type ) ) ;
5645
- ccx. item_ids . insert ( id, llfn) ;
5646
- ccx. item_symbols . insert ( id, name) ;
5720
+ let tys = c_stack_tys ( ccx, sp, id) ;
5721
+ let shim_name = name + "__c_stack_shim" ;
5722
+ let llshimfn = decl_internal_cdecl_fn (
5723
+ ccx. llmod , shim_name, tys. shim_fn_ty ) ;
5724
+ ccx. item_ids . insert ( id, llshimfn) ;
5725
+ ccx. item_symbols . insert ( id, shim_name) ;
5647
5726
ret;
5648
5727
}
5649
5728
ast:: native_abi_stdcall. {
0 commit comments