diff options
Diffstat (limited to 'src/comp')
| -rw-r--r-- | src/comp/back/abi.rs | 7 | ||||
| -rw-r--r-- | src/comp/back/x86.rs | 26 | ||||
| -rw-r--r-- | src/comp/middle/trans.rs | 79 |
3 files changed, 66 insertions, 46 deletions
diff --git a/src/comp/back/abi.rs b/src/comp/back/abi.rs index dd058590..cae1dc90 100644 --- a/src/comp/back/abi.rs +++ b/src/comp/back/abi.rs @@ -75,8 +75,11 @@ fn vec_append_glue_name() -> str { ret "rust_vec_append_glue"; } -fn upcall_glue_name(int n) -> str { - ret "rust_upcall_" + util.common.istr(n); +fn upcall_glue_name(int n, bool pass_task) -> str { + if (pass_task) { + ret "rust_upcall_rust_" + util.common.istr(n); + } + ret "rust_upcall_cdecl_" + util.common.istr(n); } fn activate_glue_name() -> str { diff --git a/src/comp/back/x86.rs b/src/comp/back/x86.rs index 345603bb..1ac03d1f 100644 --- a/src/comp/back/x86.rs +++ b/src/comp/back/x86.rs @@ -179,7 +179,7 @@ fn rust_yield_glue() -> vec[str] { + vec("ret"); } -fn upcall_glue(int n_args) -> vec[str] { +fn upcall_glue(int n_args, bool pass_task) -> vec[str] { /* * 0, 4, 8, 12 are callee-saves @@ -191,18 +191,23 @@ fn upcall_glue(int n_args) -> vec[str] { * */ - fn copy_arg(uint i) -> str { - if (i == 0u) { + fn copy_arg(bool pass_task, uint i) -> str { + if (i == 0u && pass_task) { ret "movl %edx, (%esp)"; } - auto src_off = wstr(4 + (i as int)); auto dst_off = wstr(0 + (i as int)); + auto src_off; + if (pass_task) { + src_off = wstr(4 + (i as int)); + } else { + src_off = wstr(5 + (i as int)); + } auto m = vec("movl " + src_off + "(%ebp),%eax", "movl %eax," + dst_off + "(%esp)"); ret _str.connect(m, "\n\t"); } - auto carg = copy_arg; + auto carg = bind copy_arg(pass_task, _); ret save_callee_saves() @@ -237,11 +242,11 @@ fn decl_glue(int align, str prefix, str name, vec[str] insns) -> str { } -fn decl_upcall_glue(int align, str prefix, uint n) -> str { +fn decl_upcall_glue(int align, str prefix, bool pass_task, uint n) -> str { let int i = n as int; ret decl_glue(align, prefix, - abi.upcall_glue_name(i), - upcall_glue(i)); + abi.upcall_glue_name(i, pass_task), + upcall_glue(i, pass_task)); } fn get_symbol_prefix() -> str { @@ -267,9 +272,12 @@ fn get_module_asm() -> str { abi.yield_glue_name(), rust_yield_glue())) - + _vec.init_fn[str](bind decl_upcall_glue(align, prefix, _), + + _vec.init_fn[str](bind decl_upcall_glue(align, prefix, true, _), + (abi.n_upcall_glues + 1) as uint) + + _vec.init_fn[str](bind decl_upcall_glue(align, prefix, false, _), (abi.n_upcall_glues + 1) as uint); + ret _str.connect(glues, "\n\n"); } diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index c6cd1ab4..e7102413 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -53,7 +53,8 @@ state obj namegen(mutable int i) { type glue_fns = rec(ValueRef activate_glue, ValueRef yield_glue, ValueRef exit_task_glue, - vec[ValueRef] upcall_glues, + vec[ValueRef] upcall_glues_rust, + vec[ValueRef] upcall_glues_cdecl, ValueRef no_op_type_glue, ValueRef memcpy_glue, ValueRef bzero_glue, @@ -71,7 +72,6 @@ state type crate_ctxt = rec(session.session sess, hashmap[str, ValueRef] upcalls, hashmap[str, ValueRef] intrinsics, hashmap[str, ValueRef] item_names, - hashmap[str, ValueRef] native_fns, hashmap[ast.def_id, ValueRef] item_ids, hashmap[ast.def_id, @ast.item] items, hashmap[ast.def_id, @@ -826,16 +826,19 @@ fn decl_glue(ModuleRef llmod, type_names tn, str s) -> ValueRef { ret decl_cdecl_fn(llmod, s, T_fn(vec(T_taskptr(tn)), T_void())); } -fn decl_upcall_glue(ModuleRef llmod, type_names tn, uint _n) -> ValueRef { +fn decl_upcall_glue(ModuleRef llmod, type_names tn, + bool pass_task, uint _n) -> ValueRef { // It doesn't actually matter what type we come up with here, at the // moment, as we cast the upcall function pointers to int before passing // them to the indirect upcall-invocation glue. But eventually we'd like // to call them directly, once we have a calling convention worked out. let int n = _n as int; - let str s = abi.upcall_glue_name(n); - let vec[TypeRef] args = - vec(T_int()) // callee - + _vec.init_elt[TypeRef](T_int(), n as uint); + let str s = abi.upcall_glue_name(n, pass_task); + let vec[TypeRef] args = vec(T_int()); // callee + if (!pass_task) { + args += vec(T_int()); // taskptr, will not be passed + } + args += _vec.init_elt[TypeRef](T_int(), n as uint); ret decl_fastcall_fn(llmod, s, T_fn(args, T_int())); } @@ -856,21 +859,29 @@ fn trans_upcall(@block_ctxt cx, str name, vec[ValueRef] args) -> result { auto cxx = cx.fcx.ccx; auto lltaskptr = cx.build.PtrToInt(cx.fcx.lltaskptr, T_int()); auto args2 = vec(lltaskptr) + args; - auto t = trans_upcall2(cx.build, cxx.glues, - cxx.upcalls, cxx.tn, cxx.llmod, name, args2); + auto t = trans_upcall2(cx.build, cxx.glues, lltaskptr, + cxx.upcalls, cxx.tn, cxx.llmod, name, true, args2); ret res(cx, t); } -fn trans_upcall2(builder b, @glue_fns glues, +fn trans_upcall2(builder b, @glue_fns glues, ValueRef lltaskptr, &hashmap[str, ValueRef] upcalls, type_names tn, ModuleRef llmod, str name, - vec[ValueRef] args) -> ValueRef { + bool pass_task, vec[ValueRef] args) -> ValueRef { let int n = (_vec.len[ValueRef](args) as int); let ValueRef llupcall = get_upcall(upcalls, llmod, name, n); llupcall = llvm.LLVMConstPointerCast(llupcall, T_int()); - let ValueRef llglue = glues.upcall_glues.(n); + let ValueRef llglue; + if (pass_task) { + llglue = glues.upcall_glues_rust.(n); + } else { + llglue = glues.upcall_glues_cdecl.(n); + } let vec[ValueRef] call_args = vec(llupcall); + if (!pass_task) { + call_args += vec(lltaskptr); + } for (ValueRef a in args) { call_args += vec(b.ZExtOrBitCast(a, T_int())); @@ -5457,44 +5468,38 @@ fn decl_native_fn_and_pair(@crate_ctxt cx, auto llfnty = type_of_native_fn(cx, abi, ty.ty_fn_args(fn_type), ty.ty_fn_ret(fn_type), num_ty_param); - // We can only declare a native function with a given name once; LLVM - // unhelpfully mangles the names if we try to multiply declare one. - auto function; - if (!cx.native_fns.contains_key(name)) { - function = decl_cdecl_fn(cx.llmod, name, llfnty); - cx.native_fns.insert(name, function); - } else { - // We support type-punning a native function by giving it different - // Rust types. - auto llorigfn = cx.native_fns.get(name); - function = bcx.build.PointerCast(llorigfn, T_ptr(llfnty)); - } - let vec[ValueRef] call_args = vec(); auto arg_n = 3u; + auto pass_task; + + auto lltaskptr = bcx.build.PtrToInt(fcx.lltaskptr, T_int()); alt (abi) { case (ast.native_abi_rust) { - call_args += vec(fcx.lltaskptr); + pass_task = true; + call_args += vec(lltaskptr); for each (uint i in _uint.range(0u, num_ty_param)) { auto llarg = llvm.LLVMGetParam(fcx.llfn, arg_n); check (llarg as int != 0); - call_args += vec(llarg); + call_args += vec(bcx.build.PointerCast(llarg, T_i32())); arg_n += 1u; } } case (ast.native_abi_cdecl) { + pass_task = false; } } auto args = ty.ty_fn_args(fn_type); for (ty.arg arg in args) { auto llarg = llvm.LLVMGetParam(fcx.llfn, arg_n); check (llarg as int != 0); - call_args += vec(llarg); + call_args += vec(bcx.build.PointerCast(llarg, T_i32())); arg_n += 1u; } - auto r = bcx.build.Call(function, call_args); - bcx.build.Store(r, fcx.llretptr); + auto r = trans_upcall2(bcx.build, cx.glues, lltaskptr, cx.upcalls, cx.tn, + cx.llmod, name, pass_task, call_args); + auto rptr = bcx.build.BitCast(fcx.llretptr, T_ptr(T_i32())); + bcx.build.Store(r, rptr); bcx.build.RetVoid(); } @@ -5695,8 +5700,8 @@ fn trans_exit_task_glue(@glue_fns glues, auto build = new_builder(entrybb); auto tptr = build.PtrToInt(lltaskptr, T_int()); auto V_args2 = vec(tptr) + V_args; - trans_upcall2(build, glues, - upcalls, tn, llmod, "upcall_exit", V_args2); + trans_upcall2(build, glues, lltaskptr, + upcalls, tn, llmod, "upcall_exit", true, V_args2); build.RetVoid(); } @@ -6146,8 +6151,13 @@ fn make_glues(ModuleRef llmod, type_names tn) -> @glue_fns { T_taskptr(tn)), T_void())), - upcall_glues = - _vec.init_fn[ValueRef](bind decl_upcall_glue(llmod, tn, _), + upcall_glues_rust = + _vec.init_fn[ValueRef](bind decl_upcall_glue(llmod, tn, true, + _), + abi.n_upcall_glues + 1 as uint), + upcall_glues_cdecl = + _vec.init_fn[ValueRef](bind decl_upcall_glue(llmod, tn, false, + _), abi.n_upcall_glues + 1 as uint), no_op_type_glue = decl_no_op_type_glue(llmod, tn), memcpy_glue = decl_memcpy_glue(llmod), @@ -6217,7 +6227,6 @@ fn trans_crate(session.session sess, @ast.crate crate, str output, upcalls = new_str_hash[ValueRef](), intrinsics = intrinsics, item_names = new_str_hash[ValueRef](), - native_fns = new_str_hash[ValueRef](), item_ids = new_def_hash[ValueRef](), items = new_def_hash[@ast.item](), native_items = new_def_hash[@ast.native_item](), |