diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs index 4c679798bce54..4034d1ef8dd94 100644 --- a/src/librustc/middle/trans/base.rs +++ b/src/librustc/middle/trans/base.rs @@ -2442,11 +2442,6 @@ pub fn create_entry_wrapper(ccx: @mut CrateContext, unsafe { llvm::LLVMPositionBuilderAtEnd(bld, llbb); - let crate_map = ccx.crate_map; - let opaque_crate_map = do "crate_map".with_c_str |buf| { - llvm::LLVMBuildPointerCast(bld, crate_map, Type::i8p().to_ref(), buf) - }; - let (start_fn, args) = if use_start_lang_item { let start_def_id = match ccx.tcx.lang_items.require(StartFnLangItem) { Ok(id) => id, @@ -2469,8 +2464,7 @@ pub fn create_entry_wrapper(ccx: @mut CrateContext, C_null(Type::opaque_box(ccx).ptr_to()), opaque_rust_main, llvm::LLVMGetParam(llfn, 0), - llvm::LLVMGetParam(llfn, 1), - opaque_crate_map + llvm::LLVMGetParam(llfn, 1) ] }; (start_fn, args) @@ -2479,8 +2473,7 @@ pub fn create_entry_wrapper(ccx: @mut CrateContext, let args = ~[ C_null(Type::opaque_box(ccx).ptr_to()), llvm::LLVMGetParam(llfn, 0 as c_uint), - llvm::LLVMGetParam(llfn, 1 as c_uint), - opaque_crate_map + llvm::LLVMGetParam(llfn, 1 as c_uint) ]; (rust_main, args) @@ -2661,13 +2654,16 @@ pub fn get_item_val(ccx: @mut CrateContext, id: ast::NodeId) -> ValueRef { } ast::foreign_item_static(*) => { let ident = foreign::link_name(ccx, ni); - let g = do ident.with_c_str |buf| { - unsafe { + unsafe { + let g = do ident.with_c_str |buf| { let ty = type_of(ccx, ty); llvm::LLVMAddGlobal(ccx.llmod, ty.to_ref(), buf) + }; + if attr::contains_name(ni.attrs, "weak_linkage") { + lib::llvm::SetLinkage(g, lib::llvm::ExternalWeakLinkage); } - }; - g + g + } } } } @@ -2985,7 +2981,14 @@ pub fn decl_crate_map(sess: session::Session, mapmeta: LinkMeta, llvm::LLVMAddGlobal(llmod, maptype.to_ref(), buf) } }; - lib::llvm::SetLinkage(map, lib::llvm::ExternalLinkage); + // On windows we'd like to export the toplevel cratemap + // such that we can find it from libstd. + if targ_cfg.os == session::OsWin32 && "toplevel" == mapname { + lib::llvm::SetLinkage(map, lib::llvm::DLLExportLinkage); + } else { + lib::llvm::SetLinkage(map, lib::llvm::ExternalLinkage); + } + return map; } @@ -3140,6 +3143,26 @@ pub fn trans_crate(sess: session::Session, decl_gc_metadata(ccx, llmod_id); fill_crate_map(ccx, ccx.crate_map); + + // NOTE win32: wart with exporting crate_map symbol + // We set the crate map (_rust_crate_map_toplevel) to use dll_export + // linkage but that ends up causing the linker to look for a + // __rust_crate_map_toplevel symbol (extra underscore) which it will + // subsequently fail to find. So to mitigate that we just introduce + // an alias from the symbol it expects to the one that actually exists. + if ccx.sess.targ_cfg.os == session::OsWin32 && + !*ccx.sess.building_library { + + let maptype = val_ty(ccx.crate_map).to_ref(); + + do "__rust_crate_map_toplevel".with_c_str |buf| { + unsafe { + llvm::LLVMAddAlias(ccx.llmod, maptype, + ccx.crate_map, buf); + } + } + } + glue::emit_tydescs(ccx); write_abi_version(ccx); if ccx.sess.opts.debuginfo { diff --git a/src/librustc/middle/typeck/mod.rs b/src/librustc/middle/typeck/mod.rs index 8d7dbdf263ed8..45a65f954a3a9 100644 --- a/src/librustc/middle/typeck/mod.rs +++ b/src/librustc/middle/typeck/mod.rs @@ -402,8 +402,7 @@ fn check_start_fn_ty(ccx: &CrateCtxt, bound_lifetime_names: opt_vec::Empty, inputs: ~[ ty::mk_int(), - ty::mk_imm_ptr(tcx, ty::mk_imm_ptr(tcx, ty::mk_u8())), - ty::mk_imm_ptr(tcx, ty::mk_u8()) + ty::mk_imm_ptr(tcx, ty::mk_imm_ptr(tcx, ty::mk_u8())) ], output: ty::mk_int() } diff --git a/src/libstd/rt/crate_map.rs b/src/libstd/rt/crate_map.rs index 270b5e5b1372e..f73aa1fad67dc 100644 --- a/src/libstd/rt/crate_map.rs +++ b/src/libstd/rt/crate_map.rs @@ -16,7 +16,21 @@ use vec; use hashmap::HashSet; use container::MutableSet; -pub struct ModEntry{ +// Need to tell the linker on OS X to not barf on undefined symbols +// and instead look them up at runtime, which we need to resolve +// the crate_map properly. +#[cfg(target_os = "macos")] +#[link_args = "-undefined dynamic_lookup"] +extern {} + +#[cfg(not(stage0), not(windows))] +extern { + #[weak_linkage] + #[link_name = "_rust_crate_map_toplevel"] + static CRATE_MAP: CrateMap; +} + +pub struct ModEntry { name: *c_char, log_level: *mut u32 } @@ -34,6 +48,30 @@ struct CrateMap { children: [*CrateMap, ..1] } +#[cfg(not(stage0), not(windows))] +pub fn get_crate_map() -> *CrateMap { + &'static CRATE_MAP as *CrateMap +} + +#[cfg(not(stage0), windows)] +#[fixed_stack_segment] +#[inline(never)] +pub fn get_crate_map() -> *CrateMap { + use c_str::ToCStr; + use unstable::dynamic_lib::dl; + + let sym = unsafe { + let module = dl::open_internal(); + let sym = do "__rust_crate_map_toplevel".with_c_str |buf| { + dl::symbol(module, buf) + }; + dl::close(module); + sym + }; + + sym as *CrateMap +} + unsafe fn version(crate_map: *CrateMap) -> i32 { match (*crate_map).version { 1 => return 1, diff --git a/src/libstd/rt/logging.rs b/src/libstd/rt/logging.rs index fbe05267cf4f9..26072079bcc18 100644 --- a/src/libstd/rt/logging.rs +++ b/src/libstd/rt/logging.rs @@ -12,6 +12,7 @@ use libc::{uintptr_t, exit, STDERR_FILENO}; use option::{Some, None, Option}; use rt::util::dumb_println; use rt::crate_map::{ModEntry, iter_crate_map}; +#[cfg(not(stage0))] use rt::crate_map::get_crate_map; use str::StrSlice; use str::raw::from_c_str; use u32; @@ -211,6 +212,7 @@ impl Logger for StdErrLogger { /// Configure logging by traversing the crate map and setting the /// per-module global logging flags based on the logging spec #[fixed_stack_segment] #[inline(never)] +#[cfg(stage0)] pub fn init(crate_map: *u8) { use os; @@ -224,6 +226,22 @@ pub fn init(crate_map: *u8) { } } } +#[cfg(not(stage0))] +pub fn init() { + use os; + + let crate_map = get_crate_map() as *u8; + + let log_spec = os::getenv("RUST_LOG"); + match log_spec { + Some(spec) => { + update_log_settings(crate_map, spec); + } + None => { + update_log_settings(crate_map, ~""); + } + } +} #[fixed_stack_segment] #[inline(never)] pub fn console_on() { unsafe { rust_log_console_on() } } diff --git a/src/libstd/rt/mod.rs b/src/libstd/rt/mod.rs index 6df857b8d5517..1ad258c3edf6c 100644 --- a/src/libstd/rt/mod.rs +++ b/src/libstd/rt/mod.rs @@ -171,11 +171,11 @@ pub mod borrowck; /// /// * `argc` & `argv` - The argument vector. On Unix this information is used /// by os::args. -/// * `crate_map` - Runtime information about the executing crate, mostly for logging /// /// # Return value /// /// The return value is used as the process return code. 0 on success, 101 on error. +#[cfg(stage0)] pub fn start(argc: int, argv: **u8, crate_map: *u8, main: ~fn()) -> int { init(argc, argv, crate_map); @@ -184,12 +184,22 @@ pub fn start(argc: int, argv: **u8, crate_map: *u8, main: ~fn()) -> int { return exit_code; } +#[cfg(not(stage0))] +pub fn start(argc: int, argv: **u8, main: ~fn()) -> int { + + init(argc, argv); + let exit_code = run(main); + cleanup(); + + return exit_code; +} /// Like `start` but creates an additional scheduler on the current thread, /// which in most cases will be the 'main' thread, and pins the main task to it. /// /// This is appropriate for running code that must execute on the main thread, /// such as the platform event loop and GUI. +#[cfg(stage0)] pub fn start_on_main_thread(argc: int, argv: **u8, crate_map: *u8, main: ~fn()) -> int { init(argc, argv, crate_map); let exit_code = run_on_main_thread(main); @@ -197,12 +207,21 @@ pub fn start_on_main_thread(argc: int, argv: **u8, crate_map: *u8, main: ~fn()) return exit_code; } +#[cfg(not(stage0))] +pub fn start_on_main_thread(argc: int, argv: **u8, main: ~fn()) -> int { + init(argc, argv); + let exit_code = run_on_main_thread(main); + cleanup(); + + return exit_code; +} /// One-time runtime initialization. /// /// Initializes global state, including frobbing /// the crate's logging flags, registering GC /// metadata, and storing the process arguments. +#[cfg(stage0)] pub fn init(argc: int, argv: **u8, crate_map: *u8) { // XXX: Derefing these pointers is not safe. // Need to propagate the unsafety to `start`. @@ -212,6 +231,16 @@ pub fn init(argc: int, argv: **u8, crate_map: *u8) { logging::init(crate_map); } } +#[cfg(not(stage0))] +pub fn init(argc: int, argv: **u8) { + // XXX: Derefing these pointers is not safe. + // Need to propagate the unsafety to `start`. + unsafe { + args::init(argc, argv); + env::init(); + logging::init(); + } +} /// One-time runtime cleanup. pub fn cleanup() { diff --git a/src/libstd/unstable/dynamic_lib.rs b/src/libstd/unstable/dynamic_lib.rs index 4c92d9c2e362c..41ff79bc88458 100644 --- a/src/libstd/unstable/dynamic_lib.rs +++ b/src/libstd/unstable/dynamic_lib.rs @@ -138,7 +138,7 @@ mod test { #[cfg(target_os = "android")] #[cfg(target_os = "macos")] #[cfg(target_os = "freebsd")] -mod dl { +pub mod dl { use c_str::ToCStr; use libc; use path; @@ -207,7 +207,7 @@ mod dl { } #[cfg(target_os = "win32")] -mod dl { +pub mod dl { use os; use libc; use path; diff --git a/src/libstd/unstable/lang.rs b/src/libstd/unstable/lang.rs index 1d839b55195be..baa705514894b 100644 --- a/src/libstd/unstable/lang.rs +++ b/src/libstd/unstable/lang.rs @@ -93,6 +93,7 @@ pub unsafe fn check_not_borrowed(a: *u8, borrowck::check_not_borrowed(a, file, line) } +#[cfg(stage0)] #[lang="start"] pub fn start(main: *u8, argc: int, argv: **c_char, crate_map: *u8) -> int { @@ -105,3 +106,16 @@ pub fn start(main: *u8, argc: int, argv: **c_char, }; } } + +#[cfg(not(stage0))] +#[lang="start"] +pub fn start(main: *u8, argc: int, argv: **c_char) -> int { + use rt; + + unsafe { + return do rt::start(argc, argv as **u8) { + let main: extern "Rust" fn() = transmute(main); + main(); + }; + } +} diff --git a/src/test/run-pass/attr-start.rs b/src/test/run-pass/attr-start.rs index ba54e92ef9978..4c9d388dbd77b 100644 --- a/src/test/run-pass/attr-start.rs +++ b/src/test/run-pass/attr-start.rs @@ -11,6 +11,12 @@ //xfail-fast #[start] +#[cfg(stage0)] fn start(_argc: int, _argv: **u8, _crate_map: *u8) -> int { return 0; } +#[start] +#[cfg(not(stage0))] +fn start(_argc: int, _argv: **u8) -> int { + return 0; +} diff --git a/src/test/run-pass/core-rt-smoke.rs b/src/test/run-pass/core-rt-smoke.rs index 10bd013b618bc..d7824a6524fe5 100644 --- a/src/test/run-pass/core-rt-smoke.rs +++ b/src/test/run-pass/core-rt-smoke.rs @@ -13,8 +13,16 @@ // A simple test of starting the runtime manually #[start] +#[cfg(stage0)] fn start(argc: int, argv: **u8, crate_map: *u8) -> int { do std::rt::start(argc, argv, crate_map) { info!("creating my own runtime is joy"); } } +#[start] +#[cfg(not(stage0))] +fn start(argc: int, argv: **u8) -> int { + do std::rt::start(argc, argv) { + info!("creating my own runtime is joy"); + } +} diff --git a/src/test/run-pass/rt-start-main-thread.rs b/src/test/run-pass/rt-start-main-thread.rs index 8328e7416c579..05e7613788579 100644 --- a/src/test/run-pass/rt-start-main-thread.rs +++ b/src/test/run-pass/rt-start-main-thread.rs @@ -11,6 +11,7 @@ // xfail-fast #[start] +#[cfg(stage0)] fn start(argc: int, argv: **u8, crate_map: *u8) -> int { do std::rt::start_on_main_thread(argc, argv, crate_map) { info!("running on main thread"); @@ -18,4 +19,14 @@ fn start(argc: int, argv: **u8, crate_map: *u8) -> int { info!("running on another thread"); } } -} \ No newline at end of file +} +#[start] +#[cfg(not(stage0))] +fn start(argc: int, argv: **u8) -> int { + do std::rt::start_on_main_thread(argc, argv) { + info!("running on main thread"); + do spawn { + info!("running on another thread"); + } + } +}