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.
This commit is contained in:
parent
c2d8a4df35
commit
0a8bffceb3
3 changed files with 28 additions and 35 deletions
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue