about summary refs log tree commit diff
diff options
context:
space:
mode:
authorBrian Anderson <banderson@mozilla.com>2011-08-17 20:31:55 -0700
committerBrian Anderson <banderson@mozilla.com>2011-08-18 13:09:49 -0700
commit0a8bffceb3ba25b12926bbd42ed3d282f573c9a0 (patch)
tree049632f6bf5475751688f571ee3c7d79eda9769a
parentc2d8a4df35a0a22d64d7d15ccd5fe25a495a2bc1 (diff)
Simplify the _rust_main/rust_start interface
rust_start will always call _rust_main with the command line args, and it is
_rust_main's responsibility to free the args ivec heap. _rust_main will be
generated slightly differently depending on whether main takes an ivec or not:
if so then it's just passed through to main, otherwise it frees the ivec
directly.
-rw-r--r--src/comp/middle/trans.rs29
-rw-r--r--src/rt/main.ll.in9
-rw-r--r--src/rt/rust.cpp25
3 files changed, 28 insertions, 35 deletions
diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs
index 6cfdf80a0f9..ebaa225a00d 100644
--- a/src/comp/middle/trans.rs
+++ b/src/comp/middle/trans.rs
@@ -6378,6 +6378,8 @@ fn decl_fn_and_pair_full(ccx: &@crate_ctxt, sp: &span, path: &[str],
     }
 }
 
+// Create a _rust_main(args: [str]) function which will be called from the
+// runtime rust_start function
 fn create_main_wrapper(ccx: &@crate_ctxt, sp: &span,
                        main_llfn: ValueRef, main_node_type: ty::t) {
 
@@ -6392,14 +6394,13 @@ fn create_main_wrapper(ccx: &@crate_ctxt, sp: &span,
     };
 
     let llfn = create_main(ccx, sp, main_llfn, main_takes_ivec);
-    create_main_type_indicator(ccx, main_takes_ivec);
     ccx.main_fn = some(llfn);
 
     fn create_main(ccx: &@crate_ctxt,
                    sp: &span,
                    main_llfn: ValueRef,
                    takes_ivec: bool) -> ValueRef {
-        let ivecarg = {
+        let ivecarg_ty: ty::arg = {
             mode: ty::mo_val,
             ty: ty::mk_ivec(ccx.tcx, {
                 ty: ty::mk_str(ccx.tcx),
@@ -6408,13 +6409,15 @@ fn create_main_wrapper(ccx: &@crate_ctxt, sp: &span,
         };
         let llfty = type_of_fn(ccx, sp,
                                ast::proto_fn,
-                               ~[ivecarg],
+                               ~[ivecarg_ty],
                                ty::mk_nil(ccx.tcx),
                                0u);
         let llfdecl = decl_fastcall_fn(ccx.llmod, "_rust_main", llfty);
 
         let fcx = new_fn_ctxt(new_local_ctxt(ccx), sp, llfdecl);
+
         let bcx = new_top_block_ctxt(fcx);
+        let lltop = bcx.llbb;
 
         if takes_ivec {
             let lloutputarg = llvm::LLVMGetParam(llfdecl, 0u);
@@ -6430,6 +6433,15 @@ fn create_main_wrapper(ccx: &@crate_ctxt, sp: &span,
             let lloutputarg = llvm::LLVMGetParam(llfdecl, 0u);
             let lltaskarg = llvm::LLVMGetParam(llfdecl, 1u);
             let llenvarg = llvm::LLVMGetParam(llfdecl, 2u);
+            let llargvarg = llvm::LLVMGetParam(llfdecl, 3u);
+
+            // If the crate's main function doesn't take the args vector then
+            // we're responsible for freeing it
+            let llivecptr = alloca(bcx, val_ty(llargvarg));
+            bcx.build.Store(llargvarg, llivecptr);
+            bcx = maybe_free_ivec_heap_part(bcx, llivecptr,
+                                            ty::mk_str(ccx.tcx)).bcx;
+
             let args = ~[lloutputarg,
                          lltaskarg,
                          llenvarg];
@@ -6437,21 +6449,10 @@ fn create_main_wrapper(ccx: &@crate_ctxt, sp: &span,
         }
         build_return(bcx);
 
-        let lltop = bcx.llbb;
         finish_fn(fcx, lltop);
 
         ret llfdecl;
     }
-
-    // FIXME: Remove after main takes only ivec
-    // Sets a global value hinting to the runtime whether main takes
-    // a vec or an ivec
-    fn create_main_type_indicator(ccx: &@crate_ctxt, takes_ivec: bool) {
-        let i = llvm::LLVMAddGlobal(ccx.llmod, T_int(),
-                                    str::buf("_rust_main_is_ivec"));
-        llvm::LLVMSetInitializer(i, C_int(takes_ivec as int));
-        llvm::LLVMSetGlobalConstant(i, True);
-    }
 }
 
 
diff --git a/src/rt/main.ll.in b/src/rt/main.ll.in
index c13e167d3c6..5f33f89da4c 100644
--- a/src/rt/main.ll.in
+++ b/src/rt/main.ll.in
@@ -14,10 +14,7 @@
 
 @_rust_crate_map_toplevel = external global %0
 
-; FIXME: Remove after main takes only ivec
-@_rust_main_is_ivec = external global i32
-
-declare i32 @rust_start(i32, i32, i32, i32, i32)
+declare i32 @rust_start(i32, i32, i32, i32)
 
 declare external fastcc void @_rust_main(i1* nocapture, %task*, %2* nocapture, %ivec)
 
@@ -29,8 +26,6 @@ define void @_rust_main_wrap(i1* nocapture, %task *, %2* nocapture, %ivec *)
 }
 
 define i32 @"MAIN"(i32, i32) {
-  %is_ivec = load i32 *@_rust_main_is_ivec
-
-  %3 = tail call i32 @rust_start(i32 ptrtoint (void (i1*, %task*, %2*, %ivec*)* @_rust_main_wrap to i32), i32 %0, i32 %1, i32 ptrtoint (%0* @_rust_crate_map_toplevel to i32), i32 %is_ivec)
+  %3 = tail call i32 @rust_start(i32 ptrtoint (void (i1*, %task*, %2*, %ivec*)* @_rust_main_wrap to i32), i32 %0, i32 %1, i32 ptrtoint (%0* @_rust_crate_map_toplevel to i32))
   ret i32 %3
 }
diff --git a/src/rt/rust.cpp b/src/rt/rust.cpp
index 908d3dca80b..a34738b8411 100644
--- a/src/rt/rust.cpp
+++ b/src/rt/rust.cpp
@@ -14,8 +14,7 @@ command_line_args : public kernel_owned<command_line_args>
 
     command_line_args(rust_task *task,
                       int sys_argc,
-                      char **sys_argv,
-                      bool main_is_ivec)
+                      char **sys_argv)
         : kernel(task->kernel),
           task(task),
           argc(sys_argc),
@@ -67,15 +66,13 @@ command_line_args : public kernel_owned<command_line_args>
         args_ivec->fill = 0;
         size_t ivec_exterior_sz = sizeof(rust_str *) * argc;
         args_ivec->alloc = ivec_exterior_sz;
-        if (main_is_ivec) {
-            // NB: This is freed by some ivec machinery, probably the drop
-            // glue in main, so we don't free it ourselves
-            args_ivec->payload.ptr = (rust_ivec_heap *)
-                kernel->malloc(ivec_exterior_sz + sizeof(size_t),
-                               "command line arg exterior");
-            args_ivec->payload.ptr->fill = ivec_exterior_sz;
-            memcpy(&args_ivec->payload.ptr->data, strs, ivec_exterior_sz);
-        }
+        // NB: This is freed by some ivec machinery, probably the drop
+        // glue in main, so we don't free it ourselves
+        args_ivec->payload.ptr = (rust_ivec_heap *)
+            kernel->malloc(ivec_exterior_sz + sizeof(size_t),
+                           "command line arg exterior");
+        args_ivec->payload.ptr->fill = ivec_exterior_sz;
+        memcpy(&args_ivec->payload.ptr->data, strs, ivec_exterior_sz);
     }
 
     ~command_line_args() {
@@ -107,7 +104,7 @@ int check_claims = 0;
 
 extern "C" CDECL int
 rust_start(uintptr_t main_fn, int argc, char **argv,
-           void* crate_map, int main_takes_ivec) {
+           void* crate_map) {
 
     rust_env *env = load_env();
 
@@ -122,7 +119,7 @@ rust_start(uintptr_t main_fn, int argc, char **argv,
     rust_scheduler *sched = root_task->sched;
     command_line_args *args
         = new (kernel, "main command line args")
-        command_line_args(root_task, argc, argv, main_takes_ivec);
+        command_line_args(root_task, argc, argv);
 
     DLOG(sched, dom, "startup: %d args in 0x%" PRIxPTR,
              args->argc, (uintptr_t)args->args);
@@ -154,7 +151,7 @@ rust_start(uintptr_t main_fn, int argc, char **argv,
 extern "C" CDECL int
 rust_start_ivec(uintptr_t main_fn, int argc, char **argv,
                 void* crate_map, int main_takes_ivec) {
-    return rust_start(main_fn, argc, argv, crate_map, main_takes_ivec);
+    return rust_start(main_fn, argc, argv, crate_map);
 }