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:
Brian Anderson 2011-08-17 20:31:55 -07:00
parent c2d8a4df35
commit 0a8bffceb3
3 changed files with 28 additions and 35 deletions

View file

@ -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);
}
}