Skip to content

Commit 9fa44a4

Browse files
committed
get pure wrappers approach running
1 parent 6072dda commit 9fa44a4

File tree

8 files changed

+111
-106
lines changed

8 files changed

+111
-106
lines changed

src/comp/back/upcall.rs

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ type upcalls =
2626
dynastack_alloc: ValueRef,
2727
dynastack_free: ValueRef,
2828
alloc_c_stack: ValueRef,
29-
call_c_stack_shim: ValueRef,
29+
call_shim_on_c_stack: ValueRef,
3030
rust_personality: ValueRef};
3131

3232
fn declare_upcalls(targ_cfg: @session::config,
@@ -85,11 +85,10 @@ fn declare_upcalls(targ_cfg: @session::config,
8585
T_ptr(T_i8())),
8686
dynastack_free: dv("dynastack_free", [T_ptr(T_i8())]),
8787
alloc_c_stack: d("alloc_c_stack", [size_t], T_ptr(T_i8())),
88-
call_c_stack_shim: d("call_c_stack_shim",
89-
// first arg is func ptr, but type of func varies,
90-
// so just call it char* for LLVM
91-
[T_ptr(T_i8()), T_ptr(T_i8())],
92-
int_t),
88+
call_shim_on_c_stack: d("call_shim_on_c_stack",
89+
// arguments: void *args, void *fn_ptr
90+
[T_ptr(T_i8()), T_ptr(T_i8())],
91+
int_t),
9392
rust_personality: d("rust_personality", [], T_i32())
9493
};
9594
}

src/comp/middle/trans.rs

Lines changed: 49 additions & 100 deletions
Original file line numberDiff line numberDiff line change
@@ -183,12 +183,8 @@ fn type_of_inner(cx: @crate_ctxt, sp: span, t: ty::t)
183183
T_fn_pair(cx, type_of_fn_from_ty(cx, sp, t, 0u))
184184
}
185185
ty::ty_native_fn(abi, args, out) {
186-
if native_abi_requires_pair(abi) {
187-
let nft = native_fn_wrapper_type(cx, sp, 0u, t);
188-
T_fn_pair(cx, nft)
189-
} else {
190-
raw_native_fn_type(cx, sp, args, out)
191-
}
186+
let nft = native_fn_wrapper_type(cx, sp, 0u, t);
187+
T_fn_pair(cx, nft)
192188
}
193189
ty::ty_obj(meths) { cx.rust_object_type }
194190
ty::ty_res(_, sub, tps) {
@@ -3766,9 +3762,9 @@ fn trans_call(in_cx: @block_ctxt, f: @ast::expr,
37663762
let tcx = bcx_tcx(in_cx);
37673763
let fn_expr_ty = ty::expr_ty(tcx, f);
37683764

3769-
if check type_is_native_fn_on_c_stack(tcx, fn_expr_ty) {
3770-
ret trans_c_stack_native_call(in_cx, f, args, dest);
3771-
}
3765+
//NDM if check type_is_native_fn_on_c_stack(tcx, fn_expr_ty) {
3766+
//NDM ret trans_c_stack_native_call(in_cx, f, args, dest);
3767+
//NDM }
37723768

37733769
let cx = new_scope_block_ctxt(in_cx, "call");
37743770
let f_res = trans_callee(cx, f);
@@ -3832,63 +3828,6 @@ fn trans_call(in_cx: @block_ctxt, f: @ast::expr,
38323828
ret next_cx;
38333829
}
38343830

3835-
// Translates a native call on the C stack. Calls into the runtime to perform
3836-
// the stack switching operation. Must be kept in sync with
3837-
// trans_native_mod().
3838-
fn trans_c_stack_native_call(bcx: @block_ctxt, f: @ast::expr,
3839-
args: [@ast::expr], dest: dest) -> @block_ctxt {
3840-
let ccx = bcx_ccx(bcx);
3841-
let f_res = trans_callee(bcx, f);
3842-
let llfn = f_res.val, bcx = f_res.bcx;
3843-
let llfn = BitCast(bcx, llfn, T_ptr(T_fn([], bcx_ccx(bcx).int_type)));
3844-
3845-
// Translate the callee.
3846-
let { params: _, ty: fn_ty } = ty::expr_ty_params_and_ty(bcx_tcx(bcx), f);
3847-
let fn_arg_tys = ty::ty_fn_args(bcx_tcx(bcx), fn_ty);
3848-
let llargtys = type_of_explicit_args(ccx, f.span, fn_arg_tys);
3849-
3850-
// Determine return type.
3851-
let ret_ty = ty::ty_fn_ret(bcx_tcx(bcx), fn_ty);
3852-
check type_has_static_size(ccx, ret_ty);
3853-
let llretty = type_of(ccx, f.span, ret_ty);
3854-
3855-
// Translate arguments.
3856-
// n.b.: We must do this before allocating the argument
3857-
// bundle in order to avoid problems with nested function calls.
3858-
let (to_zero, to_revoke) = ([], []);
3859-
let i = 0u, n = vec::len(args);
3860-
let llargs = [];
3861-
while i < n {
3862-
let ty_arg = fn_arg_tys[i];
3863-
let arg = args[i];
3864-
let llargty = llargtys[i];
3865-
let r = trans_arg_expr(bcx, ty_arg, llargty, to_zero, to_revoke, arg);
3866-
bcx = r.bcx;
3867-
llargs += [r.val];
3868-
i += 1u;
3869-
}
3870-
3871-
// Allocate the argument bundle and store arguments.
3872-
let llargbundlety = T_struct(llargtys + [llretty]);
3873-
let llargbundlesz = llsize_of(ccx, llargbundlety);
3874-
let llrawargbundle = Call(bcx, ccx.upcalls.alloc_c_stack,
3875-
[llargbundlesz]);
3876-
let llargbundle = PointerCast(bcx, llrawargbundle, T_ptr(llargbundlety));
3877-
i = 0u;
3878-
while i < n {
3879-
store_inbounds(bcx, llargs[i], llargbundle, [0, i as int]);
3880-
i += 1u;
3881-
}
3882-
3883-
// Call the upcall function then extract return value from the bundle.
3884-
let upcall_fn = ccx.upcalls.call_c_stack_shim;
3885-
let llfnptr = PointerCast(bcx, llfn, T_ptr(T_i8()));
3886-
Call(bcx, upcall_fn, [llfnptr, llrawargbundle]);
3887-
let llres = load_inbounds(bcx, llargbundle, [0, n as int]);
3888-
bcx = zero_and_revoke(bcx, to_zero, to_revoke);
3889-
ret store_in_dest(bcx, llres, dest);
3890-
}
3891-
38923831
fn zero_and_revoke(bcx: @block_ctxt,
38933832
to_zero: [{v: ValueRef, t: ty::t}],
38943833
to_revoke: [{v: ValueRef, t: ty::t}]) -> @block_ctxt {
@@ -5354,6 +5293,7 @@ fn trans_const(cx: @crate_ctxt, e: @ast::expr, id: ast::node_id) {
53545293
type c_stack_tys = {
53555294
arg_tys: [TypeRef],
53565295
ret_ty: TypeRef,
5296+
ret_def: bool,
53575297
base_fn_ty: TypeRef,
53585298
bundle_ty: TypeRef,
53595299
shim_fn_ty: TypeRef
@@ -5364,13 +5304,16 @@ fn c_stack_tys(ccx: @crate_ctxt,
53645304
id: ast::node_id) -> @c_stack_tys {
53655305
alt ty::struct(ccx.tcx, ty::node_id_to_type(ccx.tcx, id)) {
53665306
ty::ty_native_fn(_, arg_tys, ret_ty) {
5307+
let tcx = ccx.tcx;
53675308
let llargtys = type_of_explicit_args(ccx, sp, arg_tys);
53685309
check non_ty_var(ccx, ret_ty); // NDM does this truly hold?
5369-
let llretty = T_ptr(type_of_inner(ccx, sp, ret_ty));
5370-
let bundle_ty = T_struct(llargtys + [llretty]);
5310+
let llretty = type_of_inner(ccx, sp, ret_ty);
5311+
let bundle_ty = T_struct(llargtys + [T_ptr(llretty)]);
53715312
ret @{
53725313
arg_tys: llargtys,
53735314
ret_ty: llretty,
5315+
ret_def: !ty::type_is_bot(tcx, ret_ty) &&
5316+
!ty::type_is_nil(tcx, ret_ty),
53745317
base_fn_ty: T_fn(llargtys, llretty),
53755318
bundle_ty: bundle_ty,
53765319
shim_fn_ty: T_fn([T_ptr(bundle_ty)], T_void())
@@ -5451,8 +5394,15 @@ fn trans_native_mod(lcx: @local_ctxt, native_mod: ast::native_mod) {
54515394
}
54525395

54535396
// Create the call itself and store the return value:
5454-
let llretval = CallWithConv(bcx, llbasefn, llargvals, cc);
5455-
store_inbounds(bcx, llretval, llargbundle, [0, n as int, 0]);
5397+
let llretval = CallWithConv(bcx, llbasefn, llargvals, cc); // r
5398+
if tys.ret_def {
5399+
// R** llretptr = &args->r;
5400+
let llretptr = GEPi(bcx, llargbundle, [0, n as int]);
5401+
// R* llretloc = *llretptr; /* (args->r) */
5402+
let llretloc = Load(bcx, llretptr);
5403+
// *args->r = r;
5404+
Store(bcx, llretval, llretloc);
5405+
}
54565406

54575407
// Finish up:
54585408
build_return(bcx);
@@ -5464,25 +5414,32 @@ fn trans_native_mod(lcx: @local_ctxt, native_mod: ast::native_mod) {
54645414
fn build_wrap_fn(lcx: @local_ctxt,
54655415
native_item: @ast::native_item,
54665416
tys: @c_stack_tys,
5417+
num_tps: uint,
54675418
llshimfn: ValueRef,
54685419
llwrapfn: ValueRef) {
5469-
let fcx = new_fn_ctxt(lcx, span, llshimfn);
5420+
let span = native_item.span;
5421+
let ccx = lcx_ccx(lcx);
5422+
let fcx = new_fn_ctxt(lcx, span, llwrapfn);
54705423
let bcx = new_top_block_ctxt(fcx);
54715424
let lltop = bcx.llbb;
54725425

54735426
// Allocate the struct and write the arguments into it.
54745427
let llargbundle = alloca(bcx, tys.bundle_ty);
5475-
let imp = 2u, i = 0u, n = vec::len(tys.arg_tys);
5428+
let i = 0u, n = vec::len(tys.arg_tys);
5429+
let implicit_args = 2u + num_tps; // ret + env
54765430
while i < n {
5477-
let llargval = llvm::LLVMGetParam(llwrapfn, i + imp);
5431+
let llargval = llvm::LLVMGetParam(llwrapfn, i + implicit_args);
54785432
store_inbounds(bcx, llargval, llargbundle, [0, i as int]);
54795433
i += 1u;
54805434
}
5481-
let llretptr = llvm::LLVMGetParam(llwrapfn, 0);
5435+
let llretptr = llvm::LLVMGetParam(llwrapfn, 0u);
54825436
store_inbounds(bcx, llretptr, llargbundle, [0, n as int]);
54835437

5484-
// Create call itself:
5485-
5438+
// Create call itself.
5439+
let call_shim_on_c_stack = ccx.upcalls.call_shim_on_c_stack;
5440+
let llshimfnptr = PointerCast(bcx, llshimfn, T_ptr(T_i8()));
5441+
let llrawargbundle = PointerCast(bcx, llargbundle, T_ptr(T_i8()));
5442+
Call(bcx, call_shim_on_c_stack, [llrawargbundle, llshimfnptr]);
54865443
build_return(bcx);
54875444
finish_fn(fcx, lltop);
54885445
}
@@ -5498,13 +5455,15 @@ fn trans_native_mod(lcx: @local_ctxt, native_mod: ast::native_mod) {
54985455
for native_item in native_mod.items {
54995456
alt native_item.node {
55005457
ast::native_item_ty. {}
5501-
ast::native_item_fn(fn_decl, _) {
5458+
ast::native_item_fn(fn_decl, tps) {
5459+
let span = native_item.span;
55025460
let id = native_item.id;
55035461
let tys = c_stack_tys(ccx, span, id);
55045462
alt ccx.item_ids.find(id) {
55055463
some(llwrapfn) {
5506-
let llshimfn = build_shim_fn(lcx, native_item, cc, tys);
5507-
build_wrap_fn(lcx, native_item, tys, llshimfn, llwrapfn);
5464+
let llshimfn = build_shim_fn(lcx, native_item, tys, cc);
5465+
build_wrap_fn(lcx, native_item, tys,
5466+
vec::len(tps), llshimfn, llwrapfn);
55085467
}
55095468

55105469
none. {
@@ -5733,21 +5692,6 @@ fn native_fn_ty_param_count(cx: @crate_ctxt, id: ast::node_id) -> uint {
57335692
ret count;
57345693
}
57355694

5736-
pure fn native_abi_requires_pair(abi: ast::native_abi) -> bool {
5737-
alt abi {
5738-
ast::native_abi_rust_intrinsic. { ret true; }
5739-
ast::native_abi_cdecl. |
5740-
ast::native_abi_stdcall. { ret false; }
5741-
}
5742-
}
5743-
5744-
pure fn type_is_native_fn_on_c_stack(tcx: ty::ctxt, t: ty::t) -> bool {
5745-
alt ty::struct(tcx, t) {
5746-
ty::ty_native_fn(abi, _, _) { ret !native_abi_requires_pair(abi); }
5747-
_ { ret false; }
5748-
}
5749-
}
5750-
57515695
fn native_fn_wrapper_type(cx: @crate_ctxt, sp: span, ty_param_count: uint,
57525696
x: ty::t) -> TypeRef {
57535697
alt ty::struct(cx.tcx, x) {
@@ -5778,19 +5722,24 @@ fn collect_native_item(ccx: @crate_ctxt, i: @ast::native_item, &&pt: [str],
57785722
alt i.node {
57795723
ast::native_item_fn(_, tps) {
57805724
if !ccx.obj_methods.contains_key(i.id) {
5725+
let sp = i.span;
5726+
let id = i.id;
5727+
let node_type = node_id_type(ccx, id);
57815728
// FIXME NDM abi should come from attr
5782-
let abi = ty::ty_fn_abi(ccx.tcx, fn_type);
5729+
let abi = ty::ty_fn_abi(ccx.tcx, node_type);
57835730

57845731
alt abi {
57855732
ast::native_abi_rust_intrinsic. {
57865733
// For intrinsics: link the function directly to the intrinsic
57875734
// function itself.
57885735
let num_ty_param = vec::len(tps);
5789-
let node_type = node_id_type(ccx, id);
5790-
let fn_type = type_of_fn_from_ty(ccx, sp, node_type, num_ty_param);
5791-
let ri_name = "rust_intrinsic_" + name;
5792-
let llnativefn = get_extern_fn(ccx.externs, ccx.llmod, ri_name,
5793-
lib::llvm::LLVMCCallConv, fn_type);
5736+
check returns_non_ty_var(ccx, node_type);
5737+
let fn_type = type_of_fn_from_ty(ccx, sp, node_type,
5738+
num_ty_param);
5739+
let ri_name = "rust_intrinsic_" + link_name(i);
5740+
let llnativefn = get_extern_fn(
5741+
ccx.externs, ccx.llmod, ri_name,
5742+
lib::llvm::LLVMCCallConv, fn_type);
57945743
ccx.item_ids.insert(id, llnativefn);
57955744
ccx.item_symbols.insert(id, ri_name);
57965745
}

src/rt/arch/i386/ccall.S

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,3 +45,20 @@ upcall_call_c_stack_shim:
4545
movl %ebp,%esp // would like to use "leave" but it's slower
4646
popl %ebp
4747
ret
48+
49+
#if defined(__APPLE__) || defined(_WIN32)
50+
.globl _asm_call_on_stack
51+
_asm_call_on_stack:
52+
#else
53+
.globl asm_call_on_stack
54+
asm_call_on_stack:
55+
#endif
56+
pushl %ebp
57+
movl %esp,%ebp // save esp
58+
movl 16(%ebp),%esp // load new esp
59+
subl $12,%esp // maintain 16-byte alignment
60+
pushl 8(%ebp) // push ptr to argument block
61+
calll *12(%ebp)
62+
movl %ebp,%esp // would like to use "leave" but it's slower
63+
popl %ebp
64+
ret

src/rt/arch/i386/context.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ struct registers_t {
2929
uint32_t eip;
3030
};
3131

32+
extern "C" void asm_call_on_stack(void *args, void *fn_ptr, uintptr_t stack_ptr);
33+
3234
class context {
3335
public:
3436
registers_t regs;
@@ -55,6 +57,10 @@ class context {
5557

5658
return reinterpret_cast<void *>(top);
5759
}
60+
61+
void call_shim_on_c_stack(void *args, void *fn_ptr) {
62+
asm_call_on_stack(args, fn_ptr, regs.esp);
63+
}
5864
};
5965

6066
#endif

src/rt/arch/x86_64/ccall.S

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
#define ARG0 RUSTRT_ARG0_S
44
#define ARG1 RUSTRT_ARG1_S
5+
#define ARG2 RUSTRT_ARG2_S
56

67
.text
78

@@ -72,3 +73,18 @@ upcall_call_c_stack_shim:
7273
mov %rbp,%rsp
7374
pop %rbp
7475
ret
76+
77+
#if defined(__APPLE__) || defined(_WIN32)
78+
.globl _asm_call_on_stack
79+
_asm_call_on_stack:
80+
#else
81+
.globl asm_call_on_stack
82+
asm_call_on_stack:
83+
#endif
84+
push %rbp
85+
mov %rsp,%rbp // save rsp
86+
mov ARG2,%rsp // switch stack
87+
call *ARG1 // invoke target address
88+
mov %rbp,%rsp
89+
pop %rbp
90+
ret

src/rt/arch/x86_64/context.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ struct registers_t {
2929
uint64_t data[RUSTRT_MAX];
3030
};
3131

32+
extern "C" void asm_call_on_stack(void *args, void *fn_ptr, uintptr_t stack_ptr);
33+
3234
class context {
3335
public:
3436
registers_t regs;
@@ -55,6 +57,10 @@ class context {
5557

5658
return reinterpret_cast<void *>(top);
5759
}
60+
61+
void call_shim_on_c_stack(void *args, void *fn_ptr) {
62+
asm_call_on_stack(args, fn_ptr, regs.data[RUSTRT_RSP]);
63+
}
5864
};
5965

6066
#endif

src/rt/rust_upcall.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,16 @@ upcall_alloc_c_stack(size_t nbytes) {
219219
return sched->c_context.alloc_stack(nbytes);
220220
}
221221

222+
/**
223+
* Allocates |nbytes| bytes in the C stack and returns a pointer to the start
224+
* of the allocated space.
225+
*/
226+
extern "C" CDECL void
227+
upcall_call_shim_on_c_stack(void *args, void *fn_ptr) {
228+
rust_scheduler *sched = rust_scheduler::get_task()->sched;
229+
sched->c_context.call_shim_on_c_stack(args, fn_ptr);
230+
}
231+
222232
extern "C" _Unwind_Reason_Code
223233
__gxx_personality_v0(int version,
224234
_Unwind_Action actions,

src/rt/rustrt.def.in

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,3 +74,5 @@ upcall_shared_malloc
7474
upcall_shared_free
7575
upcall_vec_grow
7676
upcall_vec_push
77+
upcall_call_shim_on_c_stack
78+
asm_call_on_stack

0 commit comments

Comments
 (0)