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,
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)
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)
}
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
+ }
}
}
}
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;
}
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 {
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()
}
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
}
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,
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;
/// 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;
}
}
}
+#[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() } }
///
/// * `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);
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);
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`.
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() {
#[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;
}
#[cfg(target_os = "win32")]
-mod dl {
+pub mod dl {
use os;
use libc;
use path;
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 {
};
}
}
+
+#[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();
+ };
+ }
+}
//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;
+}
// 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");
+ }
+}
// 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");
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");
+ }
+ }
+}