Skip to content

Commit ea95aa3

Browse files
committed
---
yaml --- r: 5617 b: refs/heads/master c: a5b422f h: refs/heads/master i: 5615: 2940bae v: v3
1 parent 0c46e8e commit ea95aa3

File tree

2 files changed

+99
-27
lines changed

2 files changed

+99
-27
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
---
2-
refs/heads/master: f22601321f3844ea009ece6d410353644aaf8ec2
2+
refs/heads/master: a5b422fe6ba916b8761a70f3043982ce0af77956

trunk/src/comp/middle/trans.rs

Lines changed: 98 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -3897,6 +3897,11 @@ fn trans_call(in_cx: @block_ctxt, f: @ast::expr,
38973897
// with trans_call.
38983898
let tcx = bcx_tcx(in_cx);
38993899
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+
39003905
let by_ref = ast_util::ret_by_ref(ty::ty_fn_ret_style(tcx, fn_expr_ty));
39013906
let cx = new_scope_block_ctxt(in_cx, "call");
39023907
let f_res = trans_callee(cx, f);
@@ -3977,6 +3982,63 @@ fn trans_call(in_cx: @block_ctxt, f: @ast::expr,
39773982
ret {res: rslt(bcx, retval), by_ref: by_ref};
39783983
}
39793984

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+
39804042
fn zero_and_revoke(bcx: @block_ctxt,
39814043
to_zero: [{v: ValueRef, t: ty::t}],
39824044
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 {
56625724
ret count;
56635725
}
56645726

5665-
fn native_abi_requires_pair(abi: ast::native_abi) -> bool {
5727+
pure fn native_abi_requires_pair(abi: ast::native_abi) -> bool {
56665728
alt abi {
56675729
ast::native_abi_rust. | ast::native_abi_cdecl. |
56685730
ast::native_abi_llvm. | ast::native_abi_rust_intrinsic. |
@@ -5671,6 +5733,13 @@ fn native_abi_requires_pair(abi: ast::native_abi) -> bool {
56715733
}
56725734
}
56735735

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+
56745743
fn native_fn_wrapper_type(cx: @crate_ctxt, sp: span, ty_param_count: uint,
56755744
x: ty::t) -> TypeRef {
56765745
alt ty::struct(cx.tcx, x) {
@@ -5690,32 +5759,8 @@ fn raw_native_fn_type(ccx: @crate_ctxt, sp: span, args: [ty::arg],
56905759

56915760
fn register_native_fn(ccx: @crate_ctxt, sp: span, path: [str], name: str,
56925761
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.
57105762
let fn_type = node_id_type(ccx, id); // NB: has no type params
5711-
57125763
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);
57195764

57205765
let pass_task;
57215766
let uses_retptr;
@@ -5747,10 +5792,37 @@ fn register_native_fn(ccx: @crate_ctxt, sp: span, path: [str], name: str,
57475792
cast_to_i32 = true;
57485793
}
57495794
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;
57515799
}
57525800
}
57535801

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+
57545826
let lltaskptr;
57555827
if cast_to_i32 {
57565828
lltaskptr = vp2i(bcx, fcx.lltaskptr);

0 commit comments

Comments
 (0)