From 01ea27b205817ee952f7132b2663701622aa6c69 Mon Sep 17 00:00:00 2001
From: Eric Holk <eholk@mozilla.com>
Date: Tue, 14 Jun 2011 17:41:45 -0700
Subject: [PATCH] Step 1 of moving task startup to always be cdecl.

---
 src/comp/middle/trans.rs |  3 ++-
 src/rt/main.ll.in        | 11 +++++++++--
 src/rt/rust.cpp          | 22 +++++++++++++++-------
 src/rt/rust_task.cpp     |  2 +-
 4 files changed, 27 insertions(+), 11 deletions(-)

diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs
index 24bef67d758..a01650dc1ac 100644
--- a/src/comp/middle/trans.rs
+++ b/src/comp/middle/trans.rs
@@ -5842,7 +5842,8 @@ fn mk_spawn_wrapper(&@block_ctxt cx, &@ast::expr func, &ty::t args_ty) ->
     let str wrap_name =
         mangle_internal_name_by_path_and_seq(cx.fcx.lcx.ccx, cx.fcx.lcx.path,
                                              "spawn_wrapper");
-    auto llfndecl = decl_fastcall_fn(llmod, wrap_name, wrapper_fn_type);
+    auto llfndecl = decl_cdecl_fn(llmod, wrap_name, wrapper_fn_type);
+
     auto fcx = new_fn_ctxt(cx.fcx.lcx, cx.sp, llfndecl);
     auto fbcx = new_top_block_ctxt(fcx);
     // 3u to skip the three implicit args
diff --git a/src/rt/main.ll.in b/src/rt/main.ll.in
index 4fc22afdaa6..c25b324f956 100644
--- a/src/rt/main.ll.in
+++ b/src/rt/main.ll.in
@@ -10,13 +10,20 @@
 @_rust_crate_map_toplevel = external global %0
 
 declare fastcc void @_rust_main(i1* nocapture, %task*, %2* nocapture, %5*);
-declare i32 @rust_start(i32, i32, i32, i32)
+declare i32 @rust_start(i32, i32, i32, i32, i32)
 
 %tydesc = type { %tydesc**, i32, i32, void (i1*, %task*, i1*, %tydesc**, i8*)*, void (i1*, %task*, i1*, %tydesc**, i8*)*, void (i1*, %task*, i1*, %tydesc**, i8*)*, void (i1*, %task*, i1*, %tydesc**, i8*)*, void (i1*, %task*, i1*, %tydesc**, i8*)*, void (i1*, %task*, i1*, %tydesc**, i8*)*, void (i1*, %task*, i1*, %tydesc**, i8*)*, void (i1*, %task*, i1*, %tydesc**, i8*, i8*, i8)* }
 
 %task = type { i32, i32, i32, i32, i32, i32, i32, i32 }
 
+define void @_rust_main_wrap(i1* nocapture, %task *, %2* nocapture, %5 *)
+{
+  tail call fastcc void @_rust_main(i1* %0, %task *%1, %2* nocapture %2, %5 *%3)
+  ret void
+}
+
 define i32 @"MAIN"(i32, i32) {
-  %3 = tail call i32 @rust_start(i32 ptrtoint (void (i1*, %task*, %2*, %5*)* @_rust_main to i32), i32 %0, i32 %1, i32 ptrtoint (%0* @_rust_crate_map_toplevel to i32))
+;  %3 = tail call i32 @rust_start(i32 ptrtoint (void (i1*, %task*, %2*, %5*)* @_rust_main_wrap to i32), i32 %0, i32 %1, i32 ptrtoint (%0* @_rust_crate_map_toplevel to i32))
+  %3 = tail call i32 @rust_start(i32 0, i32 %0, i32 %1, i32 ptrtoint (%0* @_rust_crate_map_toplevel to i32), i32 ptrtoint (void (i1*, %task*, %2*, %5*)* @_rust_main_wrap to i32))
   ret i32 %3
 }
diff --git a/src/rt/rust.cpp b/src/rt/rust.cpp
index ae150acab17..a8ac7c7ef9c 100644
--- a/src/rt/rust.cpp
+++ b/src/rt/rust.cpp
@@ -71,13 +71,24 @@ command_line_args : public dom_owned<command_line_args>
     }
 };
 
+// THIS IS AN UGLY HACK TO MAKE rust_start STILL WORK WITH STAGE0 WHILE WE
+// TRANSITION TO ALL-CDECL TASK STARTUP FUNCTIONS.
+void FASTCALL
+(*real_main)(uintptr_t a, uintptr_t b, uintptr_t c, uintptr_t d) = NULL;
+
+void CDECL fake_main(uintptr_t a, uintptr_t b, uintptr_t c, uintptr_t d)
+{
+    real_main(a, b, c, d);
+}
+
 /**
  * Main entry point into the Rust runtime. Here we create a Rust service,
  * initialize the kernel, create the root domain and run it.
  */
 
 extern "C" CDECL int
-rust_start(uintptr_t main_fn, int argc, char **argv, void* crate_map) {
+rust_start(uintptr_t main_fn, int argc, char **argv, void* crate_map,
+           uintptr_t main_fn_cdecl) {
 
     update_log_settings(crate_map, getenv("RUST_LOG"));
     rust_srv *srv = new rust_srv();
@@ -93,12 +104,9 @@ rust_start(uintptr_t main_fn, int argc, char **argv, void* crate_map) {
         DLOG(dom, dom, "startup: arg[%d] = '%s'", i, args->argv[i]);
     }
 
-    /*
-    uintptr_t main_args[4] = {0, 0, 0, (uintptr_t)args->args};
-    dom->root_task->start(main_fn,
-                          (uintptr_t)&main_args, sizeof(main_args));
-    */
-    dom->root_task->start(main_fn,
+    real_main = (typeof(real_main))main_fn;
+    if(main_fn) { printf("using fastcall main\n"); }
+    dom->root_task->start(main_fn ? (uintptr_t)fake_main : main_fn_cdecl,
                           (uintptr_t)args->args, sizeof(args->args));
 
     int ret = dom->start_main_loop();
diff --git a/src/rt/rust_task.cpp b/src/rt/rust_task.cpp
index 6caaf25db82..bae6f221a95 100644
--- a/src/rt/rust_task.cpp
+++ b/src/rt/rust_task.cpp
@@ -118,7 +118,7 @@ struct spawn_args {
     rust_task *task;
     uintptr_t a3;
     uintptr_t a4;
-    void (*FASTCALL f)(int *, rust_task *, 
+    void (*CDECL f)(int *, rust_task *, 
                        uintptr_t, uintptr_t);
 };