Skip to content

Commit d601d78

Browse files
committed
---
yaml --- r: 6297 b: refs/heads/master c: 85083ec h: refs/heads/master i: 6295: 9320aa3 v: v3
1 parent 684ec0f commit d601d78

File tree

5 files changed

+167
-78
lines changed

5 files changed

+167
-78
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: bfbaa3d1e1b43eda2016a936dd4095bd79e64a1b
2+
refs/heads/master: 85083ec51b57ed5a44ce34c8b3610ca66dff7a68

trunk/src/comp/back/upcall.rs

Lines changed: 6 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,7 @@ type upcalls =
2626
dynastack_alloc: ValueRef,
2727
dynastack_free: ValueRef,
2828
alloc_c_stack: ValueRef,
29-
call_c_stack: ValueRef,
30-
call_c_stack_i64: ValueRef,
31-
call_c_stack_float: ValueRef,
29+
call_c_stack_shim: ValueRef,
3230
rust_personality: ValueRef};
3331

3432
fn declare_upcalls(targ_cfg: @session::config,
@@ -46,7 +44,6 @@ fn declare_upcalls(targ_cfg: @session::config,
4644
let dv = bind decl(llmod, _, _, T_void());
4745

4846
let int_t = T_int(targ_cfg);
49-
let float_t = T_float(targ_cfg);
5047
let size_t = T_size_t(targ_cfg);
5148
let opaque_vec_t = T_opaque_vec(targ_cfg);
5249

@@ -88,15 +85,11 @@ fn declare_upcalls(targ_cfg: @session::config,
8885
T_ptr(T_i8())),
8986
dynastack_free: dv("dynastack_free", [T_ptr(T_i8())]),
9087
alloc_c_stack: d("alloc_c_stack", [size_t], T_ptr(T_i8())),
91-
call_c_stack: d("call_c_stack",
92-
[T_ptr(T_fn([], int_t)), T_ptr(T_i8())],
93-
int_t),
94-
call_c_stack_i64: d("call_c_stack_i64",
95-
[T_ptr(T_fn([], int_t)), T_ptr(T_i8())],
96-
T_i64()),
97-
call_c_stack_float: d("call_c_stack_float",
98-
[T_ptr(T_fn([], int_t)), T_ptr(T_i8())],
99-
float_t),
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),
10093
rust_personality: d("rust_personality", [], T_i32())
10194
};
10295
}

trunk/src/comp/middle/trans.rs

Lines changed: 142 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -1607,8 +1607,8 @@ fn compare_scalar_values(cx: @block_ctxt, lhs: ValueRef, rhs: ValueRef,
16071607
type val_pair_fn = fn(@block_ctxt, ValueRef, ValueRef) -> @block_ctxt;
16081608
type val_and_ty_fn = fn(@block_ctxt, ValueRef, ty::t) -> @block_ctxt;
16091609

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));
16121612
}
16131613

16141614
fn store_inbounds(cx: @block_ctxt, v: ValueRef, p: ValueRef,
@@ -3833,7 +3833,7 @@ fn trans_call(in_cx: @block_ctxt, f: @ast::expr,
38333833
}
38343834

38353835
// 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().
38373837
fn trans_c_stack_native_call(bcx: @block_ctxt, f: @ast::expr,
38383838
args: [@ast::expr], dest: dest) -> @block_ctxt {
38393839
let ccx = bcx_ccx(bcx);
@@ -3846,74 +3846,37 @@ fn trans_c_stack_native_call(bcx: @block_ctxt, f: @ast::expr,
38463846
let fn_arg_tys = ty::ty_fn_args(bcx_tcx(bcx), fn_ty);
38473847
let llargtys = type_of_explicit_args(ccx, f.span, fn_arg_tys);
38483848

3849-
// Translate arguments.
3850-
let (to_zero, to_revoke) = ([], []);
3851-
let i = 0u, 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 += 1u;
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);
38643853

38653854
// Allocate the argument bundle.
3866-
let llargbundlety = T_struct(vec::map({ |r| r.llty }, llargs));
3855+
let llargbundlety = T_struct(llargtys + [llretty]);
38673856
let llargbundlesz = llsize_of(ccx, llargbundlety);
38683857
let llrawargbundle = Call(bcx, ccx.upcalls.alloc_c_stack,
38693858
[llargbundlesz]);
38703859
let llargbundle = PointerCast(bcx, llrawargbundle, T_ptr(llargbundlety));
38713860

3872-
// Copy in arguments.
3873-
let i = 0u, n = vec::len(llargs);
3861+
// Translate arguments and store into bundle.
3862+
let (to_zero, to_revoke) = ([], []);
3863+
let i = 0u, n = vec::len(args);
38743864
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]);
38773871
i += 1u;
38783872
}
38793873

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 == 64u { 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);
39173880
}
39183881

39193882
fn zero_and_revoke(bcx: @block_ctxt,
@@ -5373,6 +5336,116 @@ fn trans_const(cx: @crate_ctxt, e: @ast::expr, id: ast::node_id) {
53735336
}
53745337
}
53755338

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, 0u);
5401+
let i = 0u, 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 += 1u;
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+
53765449
fn trans_item(cx: @local_ctxt, item: ast::item) {
53775450
alt item.node {
53785451
ast::item_fn(f, tps) {
@@ -5422,6 +5495,9 @@ fn trans_item(cx: @local_ctxt, item: ast::item) {
54225495
}
54235496
}
54245497
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+
}
54255501
_ {/* fall through */ }
54265502
}
54275503
}
@@ -5641,9 +5717,12 @@ fn register_native_fn(ccx: @crate_ctxt, sp: span, path: [str], name: str,
56415717
cast_to_i32 = false;
56425718
}
56435719
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);
56475726
ret;
56485727
}
56495728
ast::native_abi_stdcall. {

trunk/src/rt/arch/i386/ccall.S

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
.text
22

3-
// upcall_call_c_stack(void (*fn)(), void *new_esp)
3+
// upcall_call_c_stack(void (*fn)(), void *arg_struct)
44
//
55
// Note that we could use |enter| and |leave| but the manuals tell me they're
66
// slower.
@@ -28,3 +28,19 @@ upcall_call_c_stack_float:
2828
popl %ebp
2929
ret
3030

31+
#if defined(__APPLE__) || defined(_WIN32)
32+
.globl _upcall_call_c_stack_shim
33+
_upcall_call_c_stack_shim:
34+
#else
35+
.globl upcall_call_c_stack_shim
36+
upcall_call_c_stack_shim:
37+
#endif
38+
pushl %ebp
39+
movl %esp,%ebp // save esp
40+
movl 8(%esp),%eax // eax = callee
41+
movl 12(%esp),%esp // switch stack
42+
pushl %esp // push ptr to new arguments
43+
calll *%eax
44+
movl %ebp,%esp // would like to use "leave" but it's slower
45+
popl %ebp
46+
ret

trunk/src/rt/rustrt.def.in

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ upcall_alloc_c_stack
5353
upcall_call_c_stack
5454
upcall_call_c_stack_i64
5555
upcall_call_c_stack_float
56+
upcall_call_c_stack_shim
5657
upcall_cmp_type
5758
upcall_dynastack_alloc
5859
upcall_dynastack_alloc_2

0 commit comments

Comments
 (0)