Skip to content

Commit c0e5bc8

Browse files
committed
---
yaml --- r: 1411 b: refs/heads/master c: af4d6ae h: refs/heads/master i: 1409: 70105b2 1407: bb08404 v: v3
1 parent 8d5e6aa commit c0e5bc8

File tree

13 files changed

+98
-43
lines changed

13 files changed

+98
-43
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: 01c2761769ab93682afec9101b4896a7253b5251
2+
refs/heads/master: af4d6ae76b05d4edb9d7074b971600a447c9c9a4

trunk/src/boot/be/abi.ml

Lines changed: 22 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -110,23 +110,33 @@ let indirect_args_elt_closure = 0;;
110110
(* Current worst case is by vec grow glue *)
111111
let worst_case_glue_call_args = 8;;
112112

113+
(*
114+
* ABI tags used to inform the runtime which sort of frame to set up for new
115+
* spawned functions. FIXME: There is almost certainly a better abstraction to
116+
* use.
117+
*)
118+
let abi_x86_rustboot_cdecl = 1;;
119+
let abi_x86_rustc_fastcall = 2;;
120+
113121
type abi =
114-
{
115-
abi_word_sz: int64;
116-
abi_word_bits: Il.bits;
117-
abi_word_ty: Common.ty_mach;
122+
{
123+
abi_word_sz: int64;
124+
abi_word_bits: Il.bits;
125+
abi_word_ty: Common.ty_mach;
126+
127+
abi_tag: int;
118128

119-
abi_has_pcrel_data: bool;
120-
abi_has_pcrel_code: bool;
129+
abi_has_pcrel_data: bool;
130+
abi_has_pcrel_code: bool;
121131

122-
abi_n_hardregs: int;
123-
abi_str_of_hardreg: (int -> string);
132+
abi_n_hardregs: int;
133+
abi_str_of_hardreg: (int -> string);
124134

125-
abi_emit_target_specific: (Il.emitter -> Il.quad -> unit);
126-
abi_constrain_vregs: (Il.quad -> (Il.vreg,Bits.t) Hashtbl.t -> unit);
135+
abi_emit_target_specific: (Il.emitter -> Il.quad -> unit);
136+
abi_constrain_vregs: (Il.quad -> (Il.vreg,Bits.t) Hashtbl.t -> unit);
127137

128-
abi_emit_fn_prologue: (Il.emitter
129-
-> Common.size (* framesz *)
138+
abi_emit_fn_prologue: (Il.emitter
139+
-> Common.size (* framesz *)
130140
-> Common.size (* callsz *)
131141
-> Common.nabi
132142
-> Common.fixup (* grow_task *)

trunk/src/boot/be/x86.ml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1851,6 +1851,8 @@ let (abi:Abi.abi) =
18511851
Abi.abi_word_bits = word_bits;
18521852
Abi.abi_word_ty = word_ty;
18531853

1854+
Abi.abi_tag = Abi.abi_x86_rustboot_cdecl;
1855+
18541856
Abi.abi_has_pcrel_data = false;
18551857
Abi.abi_has_pcrel_code = true;
18561858

trunk/src/boot/me/trans.ml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2727,6 +2727,7 @@ let trans_visitor
27272727
[|
27282728
Il.Cell new_task;
27292729
exit_task_glue_fptr;
2730+
(imm (Int64.of_int abi.Abi.abi_tag));
27302731
fptr_operand;
27312732
callsz
27322733
|];
@@ -2739,6 +2740,7 @@ let trans_visitor
27392740
[|
27402741
Il.Cell new_task;
27412742
exit_task_glue_fptr;
2743+
(imm (Int64.of_int abi.Abi.abi_tag));
27422744
fptr_operand;
27432745
callsz
27442746
|];
@@ -6183,6 +6185,8 @@ let trans_visitor
61836185
tab_sz cx.ctxt_required_rust_sym_num;
61846186
tab_sz cx.ctxt_required_c_sym_num;
61856187
tab_sz cx.ctxt_required_lib_num;
6188+
6189+
Asm.WORD (word_ty_mach, Asm.IMM (Int64.of_int abi.Abi.abi_tag));
61866190
|]))
61876191
in
61886192

trunk/src/comp/back/abi.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,9 @@ const int worst_case_glue_call_args = 7;
6060

6161
const int n_upcall_glues = 7;
6262

63+
const int abi_x86_rustboot_cdecl = 1;
64+
const int abi_x86_rustc_fastcall = 2;
65+
6366
fn memcpy_glue_name() -> str {
6467
ret "rust_memcpy_glue";
6568
}

trunk/src/comp/back/x86.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -98,12 +98,12 @@ fn rust_activate_glue() -> vec[str] {
9898
* | esi |
9999
* | ebx | <-- current task->rust_sp == current esp
100100
*
101-
*
101+
*
102102
* This is a problem. If we return to "esp <- task->rust_sp" it
103103
* will push esp back down by 5 words. This manifests as a rust
104104
* stack that grows by 5 words on each yield/reactivate. Not
105105
* good.
106-
*
106+
*
107107
* So what we do here is just adjust task->rust_sp up 5 words as
108108
* well, to mirror the movement in esp we're about to
109109
* perform. That way the "esp <- task->rust_sp" we 'ret' to below

trunk/src/comp/middle/trans.rs

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -345,7 +345,8 @@ fn T_crate(type_names tn) -> TypeRef {
345345
T_int(), // size_t main_exit_task_glue_off
346346
T_int(), // int n_rust_syms
347347
T_int(), // int n_c_syms
348-
T_int() // int n_libs
348+
T_int(), // int n_libs
349+
T_int() // uintptr_t abi_tag
349350
));
350351
tn.associate(s, t);
351352
ret t;
@@ -4545,7 +4546,7 @@ fn trans_exit_task_glue(@crate_ctxt cx) {
45454546
let vec[ValueRef] V_args = vec();
45464547

45474548
auto llfn = cx.glues.exit_task_glue;
4548-
let ValueRef lltaskptr = llvm.LLVMGetParam(llfn, 0u);
4549+
let ValueRef lltaskptr = llvm.LLVMGetParam(llfn, 3u);
45494550
auto fcx = @rec(llfn=llfn,
45504551
lltaskptr=lltaskptr,
45514552
llenv=C_null(T_opaque_closure_ptr(cx.tn)),
@@ -4596,7 +4597,8 @@ fn create_crate_constant(@crate_ctxt cx) {
45964597
exit_task_glue_off, // size_t main_exit_task_glue_off
45974598
C_null(T_int()), // int n_rust_syms
45984599
C_null(T_int()), // int n_c_syms
4599-
C_null(T_int()) // int n_libs
4600+
C_null(T_int()), // int n_libs
4601+
C_int(abi.abi_x86_rustc_fastcall) // uintptr_t abi_tag
46004602
));
46014603

46024604
llvm.LLVMSetInitializer(cx.crate_ptr, crate_val);
@@ -4810,7 +4812,10 @@ fn make_glues(ModuleRef llmod, type_names tn) -> @glue_fns {
48104812
* this is the signature required to retrieve it.
48114813
*/
48124814
exit_task_glue = decl_cdecl_fn(llmod, abi.exit_task_glue_name(),
4813-
T_fn(vec(T_taskptr(tn)),
4815+
T_fn(vec(T_int(),
4816+
T_int(),
4817+
T_int(),
4818+
T_taskptr(tn)),
48144819
T_void())),
48154820

48164821
upcall_glues =

trunk/src/rt/rust.cpp

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ command_line_args : public dom_owned<command_line_args>
7878

7979
extern "C" CDECL int
8080
rust_start(uintptr_t main_fn, rust_crate const *crate, int argc,
81-
char **argv) {
81+
char **argv) {
8282

8383
rust_srv *srv = new rust_srv();
8484
rust_kernel *kernel = new rust_kernel(srv);
@@ -87,7 +87,8 @@ rust_start(uintptr_t main_fn, rust_crate const *crate, int argc,
8787
rust_dom *dom = handle->referent();
8888
command_line_args *args = new (dom) command_line_args(dom, argc, argv);
8989

90-
dom->log(rust_log::DOM, "startup: %d args", args->argc);
90+
dom->log(rust_log::DOM, "startup: %d args in 0x%" PRIxPTR,
91+
args->argc, (uintptr_t)args->args);
9192
for (int i = 0; i < args->argc; i++) {
9293
dom->log(rust_log::DOM,
9394
"startup: arg[%d] = '%s'", i, args->argv[i]);
@@ -99,7 +100,8 @@ rust_start(uintptr_t main_fn, rust_crate const *crate, int argc,
99100

100101
uintptr_t main_args[4] = {0, 0, 0, (uintptr_t)args->args};
101102
dom->root_task->start(crate->get_exit_task_glue(),
102-
main_fn, (uintptr_t)&main_args, sizeof(main_args));
103+
crate->abi_tag, main_fn,
104+
(uintptr_t)&main_args, sizeof(main_args));
103105
int ret = dom->start_main_loop();
104106
delete args;
105107
kernel->destroy_domain(dom);

trunk/src/rt/rust_internal.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,10 @@ static size_t const TIME_SLICE_IN_MS = 10;
8888

8989
static intptr_t const CONST_REFCOUNT = 0x7badface;
9090

91+
// ABI tags for rust_start, rust_task::start and friends.
92+
static uintptr_t const ABI_X86_RUSTBOOT_CDECL = 1;
93+
static uintptr_t const ABI_X86_RUSTC_FASTCALL = 2;
94+
9195
// This accounts for logging buffers.
9296

9397
static size_t const BUF_BYTES = 2048;
@@ -241,6 +245,8 @@ class rust_crate {
241245
size_t n_c_syms;
242246
size_t n_libs;
243247

248+
uintptr_t abi_tag;
249+
244250
// Crates are immutable, constructed by the compiler.
245251

246252
uintptr_t get_image_base() const;

trunk/src/rt/rust_task.cpp

Lines changed: 34 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,7 @@ rust_task::~rust_task()
123123

124124
void
125125
rust_task::start(uintptr_t exit_task_glue,
126+
uintptr_t spawnee_abi,
126127
uintptr_t spawnee_fn,
127128
uintptr_t args,
128129
size_t callsz)
@@ -147,39 +148,46 @@ rust_task::start(uintptr_t exit_task_glue,
147148
// The exit_task_glue frame we synthesize above the frame we activate:
148149
*spp-- = (uintptr_t) 0; // closure-or-obj
149150
*spp-- = (uintptr_t) this; // task
150-
*spp-- = (uintptr_t) 0; // output
151-
*spp-- = (uintptr_t) 0; // retpc
151+
*spp-- = (uintptr_t) 0x0; // output
152+
*spp-- = (uintptr_t) 0x0; // retpc
152153

153154
uintptr_t exit_task_frame_base;
154155

155-
for (size_t j = 0; j < n_callee_saves; ++j) {
156+
if (spawnee_abi == ABI_X86_RUSTBOOT_CDECL) {
157+
for (size_t j = 0; j < n_callee_saves; ++j) {
156158

157-
// We want 'frame_base' to point to the old fp in this (exit-task)
158-
// frame, because we're going to inject this frame-pointer into the
159-
// callee-save frame pointer value in the *next* (spawnee) frame. A
160-
// cheap trick, but this means the spawnee frame will restore the
161-
// proper frame pointer of the glue frame as it runs its epilogue.
162-
if (j == callee_save_fp)
163-
exit_task_frame_base = (uintptr_t)spp;
159+
// We want 'frame_base' to point to the old fp in this (exit-task)
160+
// frame, because we're going to inject this frame-pointer into
161+
// the callee-save frame pointer value in the *next* (spawnee)
162+
// frame. A cheap trick, but this means the spawnee frame will
163+
// restore the proper frame pointer of the glue frame as it runs
164+
// its epilogue.
165+
if (j == callee_save_fp)
166+
exit_task_frame_base = (uintptr_t)spp;
164167

165-
*spp-- = 0;
166-
}
168+
*spp-- = 0;
169+
}
167170

168-
*spp-- = (uintptr_t) dom->root_crate; // crate ptr
169-
*spp-- = (uintptr_t) 0; // frame_glue_fns
171+
*spp-- = (uintptr_t) dom->root_crate; // crate ptr
172+
*spp-- = (uintptr_t) 0; // frame_glue_fns
173+
}
170174

171175
// Copy args from spawner to spawnee.
172176
if (args) {
173177
uintptr_t *src = (uintptr_t *)args;
174178
src += 1; // spawn-call output slot
175179
src += 1; // spawn-call task slot
176180
src += 1; // spawn-call closure-or-obj slot
181+
182+
// Undo previous sp-- so we're pointing at the last word pushed.
183+
++spp;
184+
177185
// Memcpy all but the task, output and env pointers
178186
callsz -= (3 * sizeof(uintptr_t));
179187
spp = (uintptr_t*) (((uintptr_t)spp) - callsz);
180188
memcpy(spp, src, callsz);
181189

182-
// Move sp down to point to task cell.
190+
// Move sp down to point to last implicit-arg cell (env).
183191
spp--;
184192
} else {
185193
// We're at root, starting up.
@@ -188,10 +196,18 @@ rust_task::start(uintptr_t exit_task_glue,
188196

189197
// The *implicit* incoming args to the spawnee frame we're
190198
// activating:
199+
*spp-- = (uintptr_t) 0x0; // closure-or-obj
200+
201+
if (spawnee_abi == ABI_X86_RUSTBOOT_CDECL) {
202+
// in CDECL mode we write the task + outptr to the spawnee stack.
203+
*spp-- = (uintptr_t) this; // task
204+
*spp-- = (uintptr_t) 0; // output addr
205+
} else {
206+
// in FASTCALL mode we don't, the outptr will be in ecx and the task
207+
// in edx, and the activate_glue will make sure to set that up.
208+
I(dom, spawnee_abi == ABI_X86_RUSTC_FASTCALL);
209+
}
191210

192-
*spp-- = (uintptr_t) 0; // closure-or-obj
193-
*spp-- = (uintptr_t) this; // task
194-
*spp-- = (uintptr_t) 0; // output addr
195211
*spp-- = (uintptr_t) exit_task_glue; // retpc
196212

197213
// The context the activate_glue needs to switch stack.

trunk/src/rt/rust_task.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ rust_task : public maybe_proxy<rust_task>,
5656
~rust_task();
5757

5858
void start(uintptr_t exit_task_glue,
59+
uintptr_t spawnee_abi,
5960
uintptr_t spawnee_fn,
6061
uintptr_t args,
6162
size_t callsz);

trunk/src/rt/rust_upcall.cpp

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -559,6 +559,7 @@ extern "C" CDECL rust_task *
559559
upcall_start_task(rust_task *spawner,
560560
rust_task *task,
561561
uintptr_t exit_task_glue,
562+
uintptr_t spawnee_abi,
562563
uintptr_t spawnee_fn,
563564
size_t callsz) {
564565
LOG_UPCALL_ENTRY(spawner);
@@ -570,7 +571,8 @@ upcall_start_task(rust_task *spawner,
570571
", spawnee 0x%" PRIxPTR
571572
", callsz %" PRIdPTR ")", task->name, task, exit_task_glue,
572573
spawnee_fn, callsz);
573-
task->start(exit_task_glue, spawnee_fn, spawner->rust_sp, callsz);
574+
task->start(exit_task_glue, spawnee_abi, spawnee_fn,
575+
spawner->rust_sp, callsz);
574576
return task;
575577
}
576578

@@ -623,16 +625,19 @@ extern "C" CDECL maybe_proxy<rust_task> *
623625
upcall_start_thread(rust_task *task,
624626
rust_proxy<rust_task> *child_task_proxy,
625627
uintptr_t exit_task_glue,
628+
uintptr_t spawnee_abi,
626629
uintptr_t spawnee_fn,
627630
size_t callsz) {
628631
LOG_UPCALL_ENTRY(task);
629632
rust_dom *parenet_dom = task->dom;
630633
rust_handle<rust_task> *child_task_handle = child_task_proxy->handle();
631634
task->log(rust_log::UPCALL | rust_log::MEM | rust_log::TASK,
632635
"exit_task_glue: " PTR ", spawnee_fn " PTR
633-
", callsz %" PRIdPTR ")", exit_task_glue, spawnee_fn, callsz);
636+
", callsz %" PRIdPTR ")",
637+
exit_task_glue, spawnee_fn, callsz);
634638
rust_task *child_task = child_task_handle->referent();
635-
child_task->start(exit_task_glue, spawnee_fn, task->rust_sp, callsz);
639+
child_task->start(exit_task_glue, spawnee_abi, spawnee_fn,
640+
task->rust_sp, callsz);
636641
#if defined(__WIN32__)
637642
HANDLE thread;
638643
thread = CreateThread(NULL, 0, rust_thread_start, child_task->dom, 0,

trunk/src/rt/test/rust_test_runtime.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ rust_task_test::worker::run() {
5454
kernel->create_domain(crate, "test");
5555
rust_dom *domain = handle->referent();
5656
domain->root_task->start(crate->get_exit_task_glue(),
57+
ABI_X86_RUSTBOOT_CDECL,
5758
(uintptr_t)&task_entry, (uintptr_t)NULL, 0);
5859
domain->start_main_loop();
5960
kernel->destroy_domain(domain);

0 commit comments

Comments
 (0)