diff --git a/src/libcore/rt.rs b/src/libcore/rt.rs index 60e6118057d..c3e4f925c40 100644 --- a/src/libcore/rt.rs +++ b/src/libcore/rt.rs @@ -11,7 +11,7 @@ //! Runtime calls emitted by the compiler. use cast::transmute; -use libc::{c_char, c_uchar, c_void, size_t, uintptr_t}; +use libc::{c_char, c_uchar, c_void, size_t, uintptr_t, c_int}; use managed::raw::BoxRepr; use str; use sys; @@ -121,6 +121,21 @@ pub unsafe fn strdup_uniq(ptr: *c_uchar, len: uint) -> ~str { str::raw::from_buf_len(ptr, len) } +#[lang="start"] +pub fn start(main: *u8, argc: int, argv: *c_char, + crate_map: *u8) -> int { + + extern { + fn rust_start(main: *c_void, argc: c_int, argv: *c_char, + crate_map: *c_void) -> c_int; + } + + unsafe { + return rust_start(main as *c_void, argc as c_int, argv, + crate_map as *c_void) as int; + } +} + // Local Variables: // mode: rust; // fill-column: 78; diff --git a/src/librustc/back/link.rs b/src/librustc/back/link.rs index b30f9fcb9dd..8db27bd675d 100644 --- a/src/librustc/back/link.rs +++ b/src/librustc/back/link.rs @@ -838,9 +838,6 @@ pub fn link_binary(sess: Session, } } - // Always want the runtime linked in - cc_args.push(~"-lrustrt"); - // On linux librt and libdl are an indirect dependencies via rustrt, // and binutils 2.22+ won't add them automatically if sess.targ_cfg.os == session::os_linux { @@ -880,6 +877,9 @@ pub fn link_binary(sess: Session, cc_args.push(~"-lmorestack"); } + // Always want the runtime linked in + cc_args.push(~"-lrustrt"); + // FIXME (#2397): At some point we want to rpath our guesses as to where // extern libraries might live, based on the addl_lib_search_paths cc_args.push_all(rpath::get_rpath_flags(sess, &output)); diff --git a/src/librustc/middle/lang_items.rs b/src/librustc/middle/lang_items.rs index b997c94a71b..84871f74964 100644 --- a/src/librustc/middle/lang_items.rs +++ b/src/librustc/middle/lang_items.rs @@ -75,16 +75,18 @@ pub enum LangItem { ReturnToMutFnLangItem, // 31 CheckNotBorrowedFnLangItem, // 32 StrDupUniqFnLangItem, // 33 + + StartFnLangItem, // 34 } pub struct LanguageItems { - items: [ Option<def_id> * 34 ] + items: [ Option<def_id> * 35 ] } pub impl LanguageItems { static pub fn new(&self) -> LanguageItems { LanguageItems { - items: [ None, ..34 ] + items: [ None, ..35 ] } } @@ -136,6 +138,8 @@ pub impl LanguageItems { 32 => "check_not_borrowed", 33 => "strdup_uniq", + 34 => "start", + _ => "???" } } @@ -248,6 +252,9 @@ pub impl LanguageItems { pub fn strdup_uniq_fn(&const self) -> def_id { self.items[StrDupUniqFnLangItem as uint].get() } + pub fn start_fn(&const self) -> def_id { + self.items[StartFnLangItem as uint].get() + } } fn LanguageItemCollector(crate: @crate, @@ -296,6 +303,7 @@ fn LanguageItemCollector(crate: @crate, item_refs.insert(@~"check_not_borrowed", CheckNotBorrowedFnLangItem as uint); item_refs.insert(@~"strdup_uniq", StrDupUniqFnLangItem as uint); + item_refs.insert(@~"start", StartFnLangItem as uint); LanguageItemCollector { crate: crate, diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs index 9844aa53f46..53555dc9ff8 100644 --- a/src/librustc/middle/trans/base.rs +++ b/src/librustc/middle/trans/base.rs @@ -2267,7 +2267,7 @@ pub fn create_main_wrapper(ccx: @CrateContext, fn main_name() -> ~str { return ~"WinMain@16"; } #[cfg(unix)] fn main_name() -> ~str { return ~"main"; } - let llfty = T_fn(~[ccx.int_type, ccx.int_type], ccx.int_type); + let llfty = T_fn(~[ccx.int_type, T_ptr(T_i8())], ccx.int_type); // FIXME #4404 android JNI hacks let llfn = if *ccx.sess.building_library { @@ -2285,33 +2285,50 @@ pub fn create_main_wrapper(ccx: @CrateContext, llvm::LLVMPositionBuilderAtEnd(bld, llbb); } let crate_map = ccx.crate_map; - let start_ty = T_fn(~[val_ty(rust_main), ccx.int_type, ccx.int_type, - val_ty(crate_map)], ccx.int_type); - let start = decl_cdecl_fn(ccx.llmod, ~"rust_start", start_ty); + let start_def_id = ccx.tcx.lang_items.start_fn(); + let start_fn = if start_def_id.crate == ast::local_crate { + ccx.sess.bug(~"start lang item is never in the local crate") + } else { + let start_fn_type = csearch::get_type(ccx.tcx, + start_def_id).ty; + trans_external_path(ccx, start_def_id, start_fn_type) + }; + + let retptr = unsafe { + llvm::LLVMBuildAlloca(bld, ccx.int_type, noname()) + }; let args = unsafe { + let opaque_rust_main = llvm::LLVMBuildPointerCast( + bld, rust_main, T_ptr(T_i8()), noname()); + let opaque_crate_map = llvm::LLVMBuildPointerCast( + bld, crate_map, T_ptr(T_i8()), noname()); + if *ccx.sess.building_library { ~[ - rust_main, + retptr, + C_null(T_opaque_box_ptr(ccx)), + opaque_rust_main, llvm::LLVMConstInt(T_i32(), 0u as c_ulonglong, False), llvm::LLVMConstInt(T_i32(), 0u as c_ulonglong, False), - crate_map + opaque_crate_map ] } else { ~[ - rust_main, + retptr, + C_null(T_opaque_box_ptr(ccx)), + opaque_rust_main, llvm::LLVMGetParam(llfn, 0 as c_uint), llvm::LLVMGetParam(llfn, 1 as c_uint), - crate_map + opaque_crate_map ] } }; - let result = unsafe { - llvm::LLVMBuildCall(bld, start, vec::raw::to_ptr(args), - args.len() as c_uint, noname()) - }; unsafe { + llvm::LLVMBuildCall(bld, start_fn, vec::raw::to_ptr(args), + args.len() as c_uint, noname()); + let result = llvm::LLVMBuildLoad(bld, retptr, noname()); llvm::LLVMBuildRet(bld, result); } }