Skip to content

Commit 933c01b

Browse files
committed
Every upcall needs a task pointer to find the C stack. It is just that when
handling cdecl call they should skip it when calling the final function. There is some cleanup to be done on the generated IL, but this gets us running Hello World for real.
1 parent 0eb6be1 commit 933c01b

File tree

3 files changed

+66
-46
lines changed

3 files changed

+66
-46
lines changed

src/comp/back/abi.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,8 +75,11 @@ fn vec_append_glue_name() -> str {
7575
ret "rust_vec_append_glue";
7676
}
7777

78-
fn upcall_glue_name(int n) -> str {
79-
ret "rust_upcall_" + util.common.istr(n);
78+
fn upcall_glue_name(int n, bool pass_task) -> str {
79+
if (pass_task) {
80+
ret "rust_upcall_rust_" + util.common.istr(n);
81+
}
82+
ret "rust_upcall_cdecl_" + util.common.istr(n);
8083
}
8184

8285
fn activate_glue_name() -> str {

src/comp/back/x86.rs

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -179,7 +179,7 @@ fn rust_yield_glue() -> vec[str] {
179179
+ vec("ret");
180180
}
181181

182-
fn upcall_glue(int n_args) -> vec[str] {
182+
fn upcall_glue(int n_args, bool pass_task) -> vec[str] {
183183

184184
/*
185185
* 0, 4, 8, 12 are callee-saves
@@ -191,18 +191,23 @@ fn upcall_glue(int n_args) -> vec[str] {
191191
*
192192
*/
193193

194-
fn copy_arg(uint i) -> str {
195-
if (i == 0u) {
194+
fn copy_arg(bool pass_task, uint i) -> str {
195+
if (i == 0u && pass_task) {
196196
ret "movl %edx, (%esp)";
197197
}
198-
auto src_off = wstr(4 + (i as int));
199198
auto dst_off = wstr(0 + (i as int));
199+
auto src_off;
200+
if (pass_task) {
201+
src_off = wstr(4 + (i as int));
202+
} else {
203+
src_off = wstr(5 + (i as int));
204+
}
200205
auto m = vec("movl " + src_off + "(%ebp),%eax",
201206
"movl %eax," + dst_off + "(%esp)");
202207
ret _str.connect(m, "\n\t");
203208
}
204209

205-
auto carg = copy_arg;
210+
auto carg = bind copy_arg(pass_task, _);
206211

207212
ret
208213
save_callee_saves()
@@ -237,11 +242,11 @@ fn decl_glue(int align, str prefix, str name, vec[str] insns) -> str {
237242
}
238243

239244

240-
fn decl_upcall_glue(int align, str prefix, uint n) -> str {
245+
fn decl_upcall_glue(int align, str prefix, bool pass_task, uint n) -> str {
241246
let int i = n as int;
242247
ret decl_glue(align, prefix,
243-
abi.upcall_glue_name(i),
244-
upcall_glue(i));
248+
abi.upcall_glue_name(i, pass_task),
249+
upcall_glue(i, pass_task));
245250
}
246251

247252
fn get_symbol_prefix() -> str {
@@ -267,9 +272,12 @@ fn get_module_asm() -> str {
267272
abi.yield_glue_name(),
268273
rust_yield_glue()))
269274

270-
+ _vec.init_fn[str](bind decl_upcall_glue(align, prefix, _),
275+
+ _vec.init_fn[str](bind decl_upcall_glue(align, prefix, true, _),
276+
(abi.n_upcall_glues + 1) as uint)
277+
+ _vec.init_fn[str](bind decl_upcall_glue(align, prefix, false, _),
271278
(abi.n_upcall_glues + 1) as uint);
272279

280+
273281
ret _str.connect(glues, "\n\n");
274282
}
275283

src/comp/middle/trans.rs

Lines changed: 44 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,8 @@ state obj namegen(mutable int i) {
5353
type glue_fns = rec(ValueRef activate_glue,
5454
ValueRef yield_glue,
5555
ValueRef exit_task_glue,
56-
vec[ValueRef] upcall_glues,
56+
vec[ValueRef] upcall_glues_rust,
57+
vec[ValueRef] upcall_glues_cdecl,
5758
ValueRef no_op_type_glue,
5859
ValueRef memcpy_glue,
5960
ValueRef bzero_glue,
@@ -71,7 +72,6 @@ state type crate_ctxt = rec(session.session sess,
7172
hashmap[str, ValueRef] upcalls,
7273
hashmap[str, ValueRef] intrinsics,
7374
hashmap[str, ValueRef] item_names,
74-
hashmap[str, ValueRef] native_fns,
7575
hashmap[ast.def_id, ValueRef] item_ids,
7676
hashmap[ast.def_id, @ast.item] items,
7777
hashmap[ast.def_id,
@@ -826,16 +826,19 @@ fn decl_glue(ModuleRef llmod, type_names tn, str s) -> ValueRef {
826826
ret decl_cdecl_fn(llmod, s, T_fn(vec(T_taskptr(tn)), T_void()));
827827
}
828828

829-
fn decl_upcall_glue(ModuleRef llmod, type_names tn, uint _n) -> ValueRef {
829+
fn decl_upcall_glue(ModuleRef llmod, type_names tn,
830+
bool pass_task, uint _n) -> ValueRef {
830831
// It doesn't actually matter what type we come up with here, at the
831832
// moment, as we cast the upcall function pointers to int before passing
832833
// them to the indirect upcall-invocation glue. But eventually we'd like
833834
// to call them directly, once we have a calling convention worked out.
834835
let int n = _n as int;
835-
let str s = abi.upcall_glue_name(n);
836-
let vec[TypeRef] args =
837-
vec(T_int()) // callee
838-
+ _vec.init_elt[TypeRef](T_int(), n as uint);
836+
let str s = abi.upcall_glue_name(n, pass_task);
837+
let vec[TypeRef] args = vec(T_int()); // callee
838+
if (!pass_task) {
839+
args += vec(T_int()); // taskptr, will not be passed
840+
}
841+
args += _vec.init_elt[TypeRef](T_int(), n as uint);
839842

840843
ret decl_fastcall_fn(llmod, s, T_fn(args, T_int()));
841844
}
@@ -856,21 +859,29 @@ fn trans_upcall(@block_ctxt cx, str name, vec[ValueRef] args) -> result {
856859
auto cxx = cx.fcx.ccx;
857860
auto lltaskptr = cx.build.PtrToInt(cx.fcx.lltaskptr, T_int());
858861
auto args2 = vec(lltaskptr) + args;
859-
auto t = trans_upcall2(cx.build, cxx.glues,
860-
cxx.upcalls, cxx.tn, cxx.llmod, name, args2);
862+
auto t = trans_upcall2(cx.build, cxx.glues, lltaskptr,
863+
cxx.upcalls, cxx.tn, cxx.llmod, name, true, args2);
861864
ret res(cx, t);
862865
}
863866

864-
fn trans_upcall2(builder b, @glue_fns glues,
867+
fn trans_upcall2(builder b, @glue_fns glues, ValueRef lltaskptr,
865868
&hashmap[str, ValueRef] upcalls,
866869
type_names tn, ModuleRef llmod, str name,
867-
vec[ValueRef] args) -> ValueRef {
870+
bool pass_task, vec[ValueRef] args) -> ValueRef {
868871
let int n = (_vec.len[ValueRef](args) as int);
869872
let ValueRef llupcall = get_upcall(upcalls, llmod, name, n);
870873
llupcall = llvm.LLVMConstPointerCast(llupcall, T_int());
871874

872-
let ValueRef llglue = glues.upcall_glues.(n);
875+
let ValueRef llglue;
876+
if (pass_task) {
877+
llglue = glues.upcall_glues_rust.(n);
878+
} else {
879+
llglue = glues.upcall_glues_cdecl.(n);
880+
}
873881
let vec[ValueRef] call_args = vec(llupcall);
882+
if (!pass_task) {
883+
call_args += vec(lltaskptr);
884+
}
874885

875886
for (ValueRef a in args) {
876887
call_args += vec(b.ZExtOrBitCast(a, T_int()));
@@ -5457,44 +5468,38 @@ fn decl_native_fn_and_pair(@crate_ctxt cx,
54575468
auto llfnty = type_of_native_fn(cx, abi, ty.ty_fn_args(fn_type),
54585469
ty.ty_fn_ret(fn_type), num_ty_param);
54595470

5460-
// We can only declare a native function with a given name once; LLVM
5461-
// unhelpfully mangles the names if we try to multiply declare one.
5462-
auto function;
5463-
if (!cx.native_fns.contains_key(name)) {
5464-
function = decl_cdecl_fn(cx.llmod, name, llfnty);
5465-
cx.native_fns.insert(name, function);
5466-
} else {
5467-
// We support type-punning a native function by giving it different
5468-
// Rust types.
5469-
auto llorigfn = cx.native_fns.get(name);
5470-
function = bcx.build.PointerCast(llorigfn, T_ptr(llfnty));
5471-
}
5472-
54735471
let vec[ValueRef] call_args = vec();
54745472
auto arg_n = 3u;
5473+
auto pass_task;
5474+
5475+
auto lltaskptr = bcx.build.PtrToInt(fcx.lltaskptr, T_int());
54755476
alt (abi) {
54765477
case (ast.native_abi_rust) {
5477-
call_args += vec(fcx.lltaskptr);
5478+
pass_task = true;
5479+
call_args += vec(lltaskptr);
54785480
for each (uint i in _uint.range(0u, num_ty_param)) {
54795481
auto llarg = llvm.LLVMGetParam(fcx.llfn, arg_n);
54805482
check (llarg as int != 0);
5481-
call_args += vec(llarg);
5483+
call_args += vec(bcx.build.PointerCast(llarg, T_i32()));
54825484
arg_n += 1u;
54835485
}
54845486
}
54855487
case (ast.native_abi_cdecl) {
5488+
pass_task = false;
54865489
}
54875490
}
54885491
auto args = ty.ty_fn_args(fn_type);
54895492
for (ty.arg arg in args) {
54905493
auto llarg = llvm.LLVMGetParam(fcx.llfn, arg_n);
54915494
check (llarg as int != 0);
5492-
call_args += vec(llarg);
5495+
call_args += vec(bcx.build.PointerCast(llarg, T_i32()));
54935496
arg_n += 1u;
54945497
}
54955498

5496-
auto r = bcx.build.Call(function, call_args);
5497-
bcx.build.Store(r, fcx.llretptr);
5499+
auto r = trans_upcall2(bcx.build, cx.glues, lltaskptr, cx.upcalls, cx.tn,
5500+
cx.llmod, name, pass_task, call_args);
5501+
auto rptr = bcx.build.BitCast(fcx.llretptr, T_ptr(T_i32()));
5502+
bcx.build.Store(r, rptr);
54985503
bcx.build.RetVoid();
54995504
}
55005505

@@ -5695,8 +5700,8 @@ fn trans_exit_task_glue(@glue_fns glues,
56955700
auto build = new_builder(entrybb);
56965701
auto tptr = build.PtrToInt(lltaskptr, T_int());
56975702
auto V_args2 = vec(tptr) + V_args;
5698-
trans_upcall2(build, glues,
5699-
upcalls, tn, llmod, "upcall_exit", V_args2);
5703+
trans_upcall2(build, glues, lltaskptr,
5704+
upcalls, tn, llmod, "upcall_exit", true, V_args2);
57005705
build.RetVoid();
57015706
}
57025707

@@ -6146,8 +6151,13 @@ fn make_glues(ModuleRef llmod, type_names tn) -> @glue_fns {
61466151
T_taskptr(tn)),
61476152
T_void())),
61486153

6149-
upcall_glues =
6150-
_vec.init_fn[ValueRef](bind decl_upcall_glue(llmod, tn, _),
6154+
upcall_glues_rust =
6155+
_vec.init_fn[ValueRef](bind decl_upcall_glue(llmod, tn, true,
6156+
_),
6157+
abi.n_upcall_glues + 1 as uint),
6158+
upcall_glues_cdecl =
6159+
_vec.init_fn[ValueRef](bind decl_upcall_glue(llmod, tn, false,
6160+
_),
61516161
abi.n_upcall_glues + 1 as uint),
61526162
no_op_type_glue = decl_no_op_type_glue(llmod, tn),
61536163
memcpy_glue = decl_memcpy_glue(llmod),
@@ -6217,7 +6227,6 @@ fn trans_crate(session.session sess, @ast.crate crate, str output,
62176227
upcalls = new_str_hash[ValueRef](),
62186228
intrinsics = intrinsics,
62196229
item_names = new_str_hash[ValueRef](),
6220-
native_fns = new_str_hash[ValueRef](),
62216230
item_ids = new_def_hash[ValueRef](),
62226231
items = new_def_hash[@ast.item](),
62236232
native_items = new_def_hash[@ast.native_item](),

0 commit comments

Comments
 (0)