From 0a8bffceb3ba25b12926bbd42ed3d282f573c9a0 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Wed, 17 Aug 2011 20:31:55 -0700 Subject: [PATCH] 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. --- src/comp/middle/trans.rs | 29 +++++++++++++++-------------- src/rt/main.ll.in | 9 ++------- src/rt/rust.cpp | 25 +++++++++++-------------- 3 files changed, 28 insertions(+), 35 deletions(-) diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 6cfdf80a0f94..ebaa225a00d4 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 c13e167d3c6e..5f33f89da4c6 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 908d3dca80b9..a34738b84114 100644 --- a/src/rt/rust.cpp +++ b/src/rt/rust.cpp @@ -14,8 +14,7 @@ command_line_args : public kernel_owned 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 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); }