diff --git a/src/libgreen/lib.rs b/src/libgreen/lib.rs index d7e94c6d48eba..ff35141530b9d 100644 --- a/src/libgreen/lib.rs +++ b/src/libgreen/lib.rs @@ -56,8 +56,18 @@ pub mod sleeper_list; pub mod stack; pub mod task; +#[boot] +#[cfg(not(stage0))] +pub fn boot(main: fn()) { + simple::task().run(|| { + do run { + main(); + }; + }); +} + #[lang = "start"] -#[cfg(not(test))] +#[cfg(not(test), stage0)] pub fn lang_start(main: *u8, argc: int, argv: **u8) -> int { use std::cast; do start(argc, argv) { diff --git a/src/libnative/lib.rs b/src/libnative/lib.rs index 80eb8c00cfdf7..fcd2df4559957 100644 --- a/src/libnative/lib.rs +++ b/src/libnative/lib.rs @@ -33,27 +33,23 @@ mod bookeeping; pub mod io; pub mod task; -// XXX: this should not exist here -#[cfg(stage0, nativestart)] -#[lang = "start"] -pub fn lang_start(main: *u8, argc: int, argv: **u8) -> int { - use std::cast; - use std::task; - - do start(argc, argv) { +#[cfg(not(stage0))] +#[boot] +pub fn boot(main: fn()) { + task::new().run(||{ + use std::task; // Instead of invoking main directly on this thread, invoke it on // another spawned thread that we are guaranteed to know the size of the // stack of. Currently, we do not have a method of figuring out the size // of the main thread's stack, so for stack overflow detection to work // we must spawn the task in a subtask which we know the stack size of. - let main: extern "Rust" fn() = unsafe { cast::transmute(main) }; let mut task = task::task(); task.name("
"); match do task.try { main() } { Ok(()) => { os::set_exit_status(0); } Err(..) => { os::set_exit_status(rt::DEFAULT_ERROR_CODE); } } - } + }); } /// Executes the given procedure after initializing the runtime with the given diff --git a/src/libnative/task.rs b/src/libnative/task.rs index 9b6a26291a1c3..f8b8bf5392c68 100644 --- a/src/libnative/task.rs +++ b/src/libnative/task.rs @@ -107,10 +107,10 @@ pub fn spawn_opts(opts: TaskOpts, f: proc()) { // This structure is the glue between channels and the 1:1 scheduling mode. This // structure is allocated once per task. -struct Ops { - lock: Mutex, // native synchronization - awoken: bool, // used to prevent spurious wakeups - io: io::IoFactory, // local I/O factory +pub struct Ops { + priv lock: Mutex, // native synchronization + priv awoken: bool, // used to prevent spurious wakeups + priv io: io::IoFactory, // local I/O factory // This field holds the known bounds of the stack in (lo, hi) form. Not all // native tasks necessarily know their precise bounds, hence this is diff --git a/src/librustc/driver/driver.rs b/src/librustc/driver/driver.rs index 4657d69732354..1dbed2e87b23c 100644 --- a/src/librustc/driver/driver.rs +++ b/src/librustc/driver/driver.rs @@ -248,6 +248,9 @@ pub fn phase_3_run_analysis_passes(sess: Session, time(time_passes, "looking for entry point", (), |_| middle::entry::find_entry_point(sess, crate, ast_map)); + time(time_passes, "looking for boot function", (), + |_| middle::entry::find_boot_fn(sess, crate)); + let freevars = time(time_passes, "freevar finding", (), |_| freevars::annotate_freevars(def_map, crate)); @@ -912,6 +915,7 @@ pub fn build_session_(sopts: @session::options, // For a library crate, this is always none entry_fn: RefCell::new(None), entry_type: Cell::new(None), + boot_fn: Cell::new(None), span_diagnostic: span_diagnostic_handler, filesearch: filesearch, building_library: Cell::new(false), diff --git a/src/librustc/driver/session.rs b/src/librustc/driver/session.rs index 0176c3fa1e06f..40492b3181fb2 100644 --- a/src/librustc/driver/session.rs +++ b/src/librustc/driver/session.rs @@ -17,16 +17,15 @@ use metadata::filesearch; use metadata; use middle::lint; +use syntax; +use syntax::abi; +use syntax::ast; use syntax::attr::AttrMetaMethods; -use syntax::ast::NodeId; -use syntax::ast::{IntTy, UintTy}; use syntax::codemap::Span; +use syntax::codemap; use syntax::diagnostic; use syntax::parse::ParseSess; -use syntax::{ast, codemap}; -use syntax::abi; use syntax::parse::token; -use syntax; use std::cell::{Cell, RefCell}; use std::hashmap::{HashMap,HashSet}; @@ -35,8 +34,8 @@ pub struct config { os: abi::Os, arch: abi::Architecture, target_strs: target_strs::t, - int_type: IntTy, - uint_type: UintTy, + int_type: ast::IntTy, + uint_type: ast::UintTy, } pub static verbose: uint = 1 << 0; @@ -210,6 +209,7 @@ pub struct Session_ { entry_fn: RefCell>, entry_type: Cell>, span_diagnostic: @diagnostic::SpanHandler, + boot_fn: Cell>, filesearch: @filesearch::FileSearch, building_library: Cell, working_dir: Path, diff --git a/src/librustc/front/std_inject.rs b/src/librustc/front/std_inject.rs index ae593783213ce..3a20b94fccdb4 100644 --- a/src/librustc/front/std_inject.rs +++ b/src/librustc/front/std_inject.rs @@ -40,6 +40,10 @@ fn use_uv(crate: &ast::Crate) -> bool { !attr::contains_name(crate.attrs, "no_uv") } +fn use_stdboot(crate: &ast::Crate) -> bool { + !attr::contains_name(crate.attrs, "no_boot") +} + fn no_prelude(attrs: &[ast::Attribute]) -> bool { attr::contains_name(attrs, "no_implicit_prelude") } @@ -67,25 +71,28 @@ impl fold::Folder for StandardLibraryInjector { span: DUMMY_SP }]; - if use_uv(&crate) && !self.sess.building_library.get() { - vis.push(ast::ViewItem { + if use_stdboot(&crate) && !self.sess.building_library.get() { + let boot = attr::mk_word_item(@"boot"); + vis.push(ast::view_item { node: ast::ViewItemExternMod(self.sess.ident_of("green"), Some((format!("green\\#{}", VERSION).to_managed(), ast::CookedStr)), ast::DUMMY_NODE_ID), - attrs: ~[], - vis: ast::Private, - span: DUMMY_SP - }); - vis.push(ast::ViewItem { - node: ast::ViewItemExternMod(self.sess.ident_of("rustuv"), - Some((format!("rustuv\\#{}", VERSION).to_managed(), - ast::CookedStr)), - ast::DUMMY_NODE_ID), - attrs: ~[], + attrs: ~[attr::mk_attr(boot)], vis: ast::Private, span: DUMMY_SP }); + if use_uv(&crate) { + vis.push(ast::view_item { + node: ast::view_item_extern_mod(self.sess.ident_of("rustuv"), + Some((format!("rustuv\\#{}", VERSION).to_managed(), + ast::CookedStr)), + ast::DUMMY_NODE_ID), + attrs: ~[], + vis: ast::Private, + span: DUMMY_SP + }); + } } vis.push_all(crate.module.view_items); diff --git a/src/librustc/metadata/common.rs b/src/librustc/metadata/common.rs index 2d86a36dd60ab..f304993409a4c 100644 --- a/src/librustc/metadata/common.rs +++ b/src/librustc/metadata/common.rs @@ -204,6 +204,8 @@ pub static tag_native_libraries_lib: uint = 0x104; pub static tag_native_libraries_name: uint = 0x105; pub static tag_native_libraries_kind: uint = 0x106; +pub static tag_boot_fn: uint = 0x107; + #[deriving(Clone)] pub struct LinkMeta { crateid: CrateId, diff --git a/src/librustc/metadata/csearch.rs b/src/librustc/metadata/csearch.rs index 6dad364e661ba..cb322870e0824 100644 --- a/src/librustc/metadata/csearch.rs +++ b/src/librustc/metadata/csearch.rs @@ -301,3 +301,8 @@ pub fn get_trait_of_method(cstore: @cstore::CStore, decoder::get_trait_of_method(cdata, def_id.node, tcx) } +pub fn get_boot_fn(cstore: @mut cstore::CStore, + crate: ast::CrateNum) -> Option { + let cdata = cstore.get_crate_data(crate); + decoder::get_boot_fn(cdata) +} diff --git a/src/librustc/metadata/decoder.rs b/src/librustc/metadata/decoder.rs index ca35b1ae96b02..d1963ec6d88ae 100644 --- a/src/librustc/metadata/decoder.rs +++ b/src/librustc/metadata/decoder.rs @@ -1275,3 +1275,9 @@ pub fn get_native_libraries(cdata: Cmd) -> ~[(cstore::NativeLibaryKind, ~str)] { }); return result; } + +pub fn get_boot_fn(cdata: Cmd) -> Option { + reader::maybe_get_doc(reader::Doc(cdata.data()), tag_boot_fn).map(|doc| { + item_def_id(doc, cdata) + }) +} diff --git a/src/librustc/metadata/encoder.rs b/src/librustc/metadata/encoder.rs index a860b148aa9d2..d812263c307b5 100644 --- a/src/librustc/metadata/encoder.rs +++ b/src/librustc/metadata/encoder.rs @@ -79,6 +79,7 @@ struct Stats { dep_bytes: Cell, lang_item_bytes: Cell, native_lib_bytes: Cell, + boot_fn_bytes: Cell, impl_bytes: Cell, misc_bytes: Cell, item_bytes: Cell, @@ -1692,6 +1693,17 @@ fn encode_native_libraries(ecx: &EncodeContext, ebml_w: &mut writer::Encoder) { ebml_w.end_tag(); } +fn encode_boot_fn(ecx: &EncodeContext, ebml_w: &mut writer::Encoder) { + match *ecx.tcx.sess.boot_fn { + Some(did) => { + ebml_w.start_tag(tag_boot_fn); + encode_def_id(ebml_w, did); + ebml_w.end_tag(); + } + None => {} + }; +} + struct ImplVisitor<'a,'b> { ecx: &'a EncodeContext<'a>, ebml_w: &'a mut writer::Encoder<'b>, @@ -1816,6 +1828,7 @@ fn encode_metadata_inner(wr: &mut MemWriter, parms: EncodeParams, crate: &Crate) dep_bytes: Cell::new(0), lang_item_bytes: Cell::new(0), native_lib_bytes: Cell::new(0), + boot_fn_bytes: Cell::new(0), impl_bytes: Cell::new(0), misc_bytes: Cell::new(0), item_bytes: Cell::new(0), @@ -1874,6 +1887,11 @@ fn encode_metadata_inner(wr: &mut MemWriter, parms: EncodeParams, crate: &Crate) encode_native_libraries(&ecx, &mut ebml_w); ecx.stats.native_lib_bytes.set(ebml_w.writer.tell() - i); + // Encode the native libraries used + i = wr.tell(); + encode_boot_fn(&ecx, &mut ebml_w); + ecx.stats.boot_fn_bytes = wr.tell() - i; + // Encode the def IDs of impls, for coherence checking. i = ebml_w.writer.tell(); encode_impls(&ecx, crate, &mut ebml_w); @@ -1911,6 +1929,7 @@ fn encode_metadata_inner(wr: &mut MemWriter, parms: EncodeParams, crate: &Crate) println!(" dep bytes: {}", ecx.stats.dep_bytes.get()); println!(" lang item bytes: {}", ecx.stats.lang_item_bytes.get()); println!(" native bytes: {}", ecx.stats.native_lib_bytes.get()); + println!(" boot fn bytes: {}", ecx.stats.boot_fn_bytes.get()); println!(" impl bytes: {}", ecx.stats.impl_bytes.get()); println!(" misc bytes: {}", ecx.stats.misc_bytes.get()); println!(" item bytes: {}", ecx.stats.item_bytes.get()); diff --git a/src/librustc/middle/entry.rs b/src/librustc/middle/entry.rs index d6e4ad641822a..55a72195c5215 100644 --- a/src/librustc/middle/entry.rs +++ b/src/librustc/middle/entry.rs @@ -8,10 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - use driver::session; use driver::session::Session; -use syntax::ast::{Crate, NodeId, Item, ItemFn}; +use metadata::csearch; + +use syntax::ast; use syntax::ast_map; use syntax::attr; use syntax::codemap::Span; @@ -25,26 +26,26 @@ struct EntryContext { ast_map: ast_map::Map, // The top-level function called 'main' - main_fn: Option<(NodeId, Span)>, + main_fn: Option<(ast::NodeId, Span)>, // The function that has attribute named 'main' - attr_main_fn: Option<(NodeId, Span)>, + attr_main_fn: Option<(ast::NodeId, Span)>, // The function that has the attribute 'start' on it - start_fn: Option<(NodeId, Span)>, + start_fn: Option<(ast::NodeId, Span)>, // The functions that one might think are 'main' but aren't, e.g. // main functions not defined at the top level. For diagnostics. - non_main_fns: ~[(NodeId, Span)], + non_main_fns: ~[(ast::NodeId, Span)], } impl Visitor<()> for EntryContext { - fn visit_item(&mut self, item: &Item, _:()) { + fn visit_item(&mut self, item: &ast::Item, _:()) { find_item(item, self); } } -pub fn find_entry_point(session: Session, crate: &Crate, ast_map: ast_map::Map) { +pub fn find_entry_point(session: Session, crate: &ast::Crate, ast_map: ast_map::Map) { if session.building_library.get() { // No need to find a main function return; @@ -70,9 +71,9 @@ pub fn find_entry_point(session: Session, crate: &Crate, ast_map: ast_map::Map) configure_main(&mut ctxt); } -fn find_item(item: &Item, ctxt: &mut EntryContext) { +fn find_item(item: &ast::Item, ctxt: &mut EntryContext) { match item.node { - ItemFn(..) => { + ast::ItemFn(..) => { if item.ident.name == special_idents::main.name { { let ast_map = ctxt.ast_map.borrow(); @@ -151,3 +152,89 @@ fn configure_main(this: &mut EntryContext) { } } } + +struct BootFinder { + local_candidates: ~[(ast::NodeId, Span)], + extern_candidates: ~[(ast::CrateNum, Span)], + sess: Session, +} + +pub fn find_boot_fn(sess: Session, crate: &ast::Crate) { + let mut cx = BootFinder { + local_candidates: ~[], + extern_candidates: ~[], + sess: sess, + }; + visit::walk_crate(&mut cx, crate, ()); + match cx.local_candidates.len() + cx.extern_candidates.len() { + 0 => { + if !sess.building_library.get() { + match sess.entry_type.get() { + Some(session::EntryNone) => {}, + Some(session::EntryStart) => {}, + Some(session::EntryMain) => { + sess.err("main function found but no #[boot] \ + functions found"); + } + None => { + sess.bug("expected entry calculation by now"); + } + } + } + } + + 1 => { + for &(id, _) in cx.local_candidates.iter() { + sess.boot_fn.set(Some(ast::DefId { + crate: ast::LOCAL_CRATE, + node: id, + })); + } + for &(cnum, span) in cx.extern_candidates.iter() { + sess.boot_fn.set(csearch::get_boot_fn(sess.cstore, cnum)); + if sess.boot_fn.get().is_none() { + sess.span_err(span, "no #[boot] function found in crate"); + } + } + } + + _ => { + sess.err("too many #[boot] functions found"); + let lcandidates = cx.local_candidates.iter().map(|&(_, span)| span); + let ecandidates = cx.extern_candidates.iter().map(|&(_, span)| span); + for (i, span) in ecandidates.chain(lcandidates).enumerate() { + sess.span_note(span, format!(r"candidate \#{}", i)); + } + } + } + + sess.abort_if_errors(); +} + +impl Visitor<()> for BootFinder { + fn visit_item(&mut self, it: @ast::item, _: ()) { + match it.node { + ast::item_fn(..) if attr::contains_name(it.attrs, "boot") => { + self.local_candidates.push((it.id, it.span)) + } + _ => {} + } + visit::walk_item(self, it, ()); + } + + fn visit_view_item(&mut self, it: &ast::view_item, _: ()) { + match it.node { + ast::view_item_extern_mod(name, _, _, _) => { + if attr::contains_name(it.attrs, "boot") { + self.sess.cstore.iter_crate_data(|num, meta| { + if meta.name == self.sess.str_of(name) { + self.extern_candidates.push((num, it.span)); + } + }); + } + } + _ => {} + } + visit::walk_view_item(self, it, ()); + } +} diff --git a/src/librustc/middle/lint.rs b/src/librustc/middle/lint.rs index a954c59ff1276..db6e4ab83beed 100644 --- a/src/librustc/middle/lint.rs +++ b/src/librustc/middle/lint.rs @@ -877,7 +877,7 @@ fn check_heap_item(cx: &Context, it: &ast::Item) { } static crate_attrs: &'static [&'static str] = &[ - "crate_type", "feature", "no_uv", "no_main", "no_std", "crate_id", + "crate_type", "feature", "no_uv", "no_main", "no_std", "crate_id", "no_boot", "desc", "comment", "license", "copyright", // not used in rustc now ]; @@ -906,7 +906,7 @@ static other_attrs: &'static [&'static str] = &[ // fn-level "test", "bench", "should_fail", "ignore", "inline", "lang", "main", "start", - "no_split_stack", "cold", + "no_split_stack", "cold", "boot", // internal attribute: bypass privacy inside items "!resolve_unexported", diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs index aaa8d071aff5d..eced8b7302d94 100644 --- a/src/librustc/middle/trans/base.rs +++ b/src/librustc/middle/trans/base.rs @@ -2429,7 +2429,7 @@ pub fn trans_mod(ccx: @CrateContext, m: &ast::Mod) { } } -fn finish_register_fn(ccx: @CrateContext, sp: Span, sym: ~str, node_id: ast::NodeId, +fn finish_register_fn(ccx: @CrateContext, sym: ~str, node_id: ast::NodeId, llfn: ValueRef) { { let mut item_symbols = ccx.item_symbols.borrow_mut(); @@ -2442,14 +2442,9 @@ fn finish_register_fn(ccx: @CrateContext, sp: Span, sym: ~str, node_id: ast::Nod lib::llvm::SetLinkage(llfn, lib::llvm::InternalLinkage); } } - - if is_entry_fn(&ccx.sess, node_id) && !ccx.sess.building_library.get() { - create_entry_wrapper(ccx, sp, llfn); - } } pub fn register_fn(ccx: @CrateContext, - sp: Span, sym: ~str, node_id: ast::NodeId, node_type: ty::t) @@ -2463,13 +2458,12 @@ pub fn register_fn(ccx: @CrateContext, }; let llfn = decl_rust_fn(ccx, f.sig.inputs, f.sig.output, sym); - finish_register_fn(ccx, sp, sym, node_id, llfn); + finish_register_fn(ccx, sym, node_id, llfn); llfn } // only use this for foreign function ABIs and glue, use `register_fn` for Rust functions pub fn register_fn_llvmty(ccx: @CrateContext, - sp: Span, sym: ~str, node_id: ast::NodeId, cc: lib::llvm::CallConv, @@ -2480,34 +2474,35 @@ pub fn register_fn_llvmty(ccx: @CrateContext, ast_map::path_to_str(item_path(ccx, &node_id), token::get_ident_interner())); let llfn = decl_fn(ccx.llmod, sym, cc, fn_ty); - finish_register_fn(ccx, sp, sym, node_id, llfn); + finish_register_fn(ccx, sym, node_id, llfn); llfn } -pub fn is_entry_fn(sess: &Session, node_id: ast::NodeId) -> bool { - match sess.entry_fn.get() { - Some((entry_id, _)) => node_id == entry_id, - None => false - } -} - // Create a _rust_main(args: ~[str]) function which will be called from the // runtime rust_start function -pub fn create_entry_wrapper(ccx: @CrateContext, - _sp: Span, - main_llfn: ValueRef) { - let et = ccx.sess.entry_type.get().unwrap(); - match et { +pub fn create_entry_wrapper(ccx: @CrateContext) { + if *ccx.sess.building_library { return } + + let main_llfn = ccx.sess.entry_fn.map(|(id, _)| get_item_val(ccx, id)); + let main_llfn = main_llfn.expect("needs main function in trans"); + match ccx.sess.entry_type.expect("need entry calculation in trans") { + session::EntryNone => {} // Do nothing. session::EntryMain => { - create_entry_fn(ccx, main_llfn, true); + let did = ccx.sess.boot_fn.expect("need boot function in trans"); + let boot_llfn = if ast_util::is_local(did) { + get_item_val(ccx, did.node) + } else { + let boot_fn_type = csearch::get_type(ccx.tcx, did).ty; + trans_external_path(ccx, did, boot_fn_type) + }; + create_entry_fn(ccx, main_llfn, Some(boot_llfn)); } - session::EntryStart => create_entry_fn(ccx, main_llfn, false), - session::EntryNone => {} // Do nothing. + session::EntryStart => create_entry_fn(ccx, main_llfn, None), } fn create_entry_fn(ccx: @CrateContext, rust_main: ValueRef, - use_start_lang_item: bool) { + rust_boot: Option) { let llfty = Type::func([ccx.int_type, Type::i8().ptr_to().ptr_to()], &ccx.int_type); @@ -2521,47 +2516,53 @@ pub fn create_entry_wrapper(ccx: @CrateContext, unsafe { llvm::LLVMPositionBuilderAtEnd(bld, llbb); - let (start_fn, args) = if use_start_lang_item { - let start_def_id = match ccx.tcx.lang_items.require(StartFnLangItem) { - Ok(id) => id, - Err(s) => { ccx.tcx.sess.fatal(s); } - }; - let start_fn = if start_def_id.crate == ast::LOCAL_CRATE { - get_item_val(ccx, start_def_id.node) - } 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 args = { - let opaque_rust_main = "rust_main".with_c_str(|buf| { - llvm::LLVMBuildPointerCast(bld, rust_main, Type::i8p().to_ref(), buf) - }); - - ~[ + let (start_fn, args) = match rust_boot { + Some(rust_boot) => { + let start = ccx.tcx.lang_items.require(StartFnLangItem); + let start_def_id = match start { + Ok(id) => id, + Err(s) => { ccx.tcx.sess.fatal(s); } + }; + let start_fn = if start_def_id.crate == ast::LOCAL_CRATE { + get_item_val(ccx, start_def_id.node) + } 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 args = { + let opaque_rust_main = "rust_main".with_c_str(|buf| { + llvm::LLVMBuildPointerCast(bld, rust_main, + Type::i8p().to_ref(), buf) + }); + let opaque_rust_boot = "rust_boot".with_c_str(|buf| { + llvm::LLVMBuildPointerCast(bld, rust_boot, + Type::i8p().to_ref(), buf) + }); + ~[ + C_null(Type::opaque_box(ccx).ptr_to()), + opaque_rust_main, + opaque_rust_boot, + llvm::LLVMGetParam(llfn, 0), + llvm::LLVMGetParam(llfn, 1) + ] + }; + (start_fn, args) + } + None => { + debug!("using user-defined start fn"); + let args = ~[ C_null(Type::opaque_box(ccx).ptr_to()), - opaque_rust_main, - llvm::LLVMGetParam(llfn, 0), - llvm::LLVMGetParam(llfn, 1) - ] - }; - (start_fn, args) - } else { - debug!("using user-defined start fn"); - let args = ~[ - C_null(Type::opaque_box(ccx).ptr_to()), - llvm::LLVMGetParam(llfn, 0 as c_uint), - llvm::LLVMGetParam(llfn, 1 as c_uint) - ]; - - (rust_main, args) - }; + llvm::LLVMGetParam(llfn, 0 as c_uint), + llvm::LLVMGetParam(llfn, 1 as c_uint) + ]; + (rust_main, args) + } + }; let result = llvm::LLVMBuildCall(bld, start_fn, args.as_ptr(), args.len() as c_uint, noname()); - llvm::LLVMBuildRet(bld, result); } } @@ -2722,10 +2723,9 @@ pub fn get_item_val(ccx: @CrateContext, id: ast::NodeId) -> ValueRef { ast::ItemFn(_, purity, _, _, _) => { let llfn = if purity != ast::ExternFn { - register_fn(ccx, i.span, sym, i.id, ty) + register_fn(ccx, sym, i.id, ty) } else { foreign::register_rust_fn_with_foreign_abi(ccx, - i.span, sym, i.id) }; @@ -2826,7 +2826,7 @@ pub fn get_item_val(ccx: @CrateContext, id: ast::NodeId) -> ValueRef { llfn = match enm.node { ast::ItemEnum(_, _) => { - register_fn(ccx, (*v).span, sym, id, ty) + register_fn(ccx, sym, id, ty) } _ => fail!("NodeVariant, shouldn't happen") }; @@ -2850,8 +2850,7 @@ pub fn get_item_val(ccx: @CrateContext, id: ast::NodeId) -> ValueRef { let ty = ty::node_id_to_type(ccx.tcx, ctor_id); let sym = exported_name(ccx, (*struct_path).clone(), ty, struct_item.attrs); - let llfn = register_fn(ccx, struct_item.span, - sym, ctor_id, ty); + let llfn = register_fn(ccx, sym, ctor_id, ty); set_inline_hint(llfn); llfn } @@ -2892,7 +2891,7 @@ pub fn register_method(ccx: @CrateContext, let sym = exported_name(ccx, path, mty, m.attrs); - let llfn = register_fn(ccx, m.span, sym, id, mty); + let llfn = register_fn(ccx, sym, id, mty); set_llvm_fn_attrs(m.attrs, llfn); llfn } @@ -3338,6 +3337,7 @@ pub fn trans_crate(sess: session::Session, trans_mod(ccx, &crate.module); } + create_entry_wrapper(ccx); decl_gc_metadata(ccx, llmod_id); fill_crate_map(ccx, ccx.crate_map); diff --git a/src/librustc/middle/trans/foreign.rs b/src/librustc/middle/trans/foreign.rs index 487aaa528eda2..0f6b74b7ad439 100644 --- a/src/librustc/middle/trans/foreign.rs +++ b/src/librustc/middle/trans/foreign.rs @@ -30,7 +30,6 @@ use std::libc::c_uint; use std::vec; use syntax::abi::{Cdecl, Aapcs, C, AbiSet, Win64}; use syntax::abi::{RustIntrinsic, Rust, Stdcall, Fastcall, System}; -use syntax::codemap::Span; use syntax::parse::token::special_idents; use syntax::{ast}; use syntax::{attr, ast_map}; @@ -408,7 +407,6 @@ pub fn trans_foreign_mod(ccx: @CrateContext, // correct code in the first place, but this is much simpler. pub fn register_rust_fn_with_foreign_abi(ccx: @CrateContext, - sp: Span, sym: ~str, node_id: ast::NodeId) -> ValueRef { @@ -425,7 +423,6 @@ pub fn register_rust_fn_with_foreign_abi(ccx: @CrateContext, _ => lib::llvm::CCallConv }; let llfn = base::register_fn_llvmty(ccx, - sp, sym, node_id, cconv, diff --git a/src/libstd/unstable/lang.rs b/src/libstd/unstable/lang.rs index e7e8cec9d5f17..53db28eb87f22 100644 --- a/src/libstd/unstable/lang.rs +++ b/src/libstd/unstable/lang.rs @@ -79,3 +79,19 @@ pub unsafe fn check_not_borrowed(a: *u8, line: size_t) { borrowck::check_not_borrowed(a, file, line) } + +#[lang = "start"] +#[cfg(not(stage0))] +pub fn lang_start(main: *u8, boot: *u8, argc: int, argv: **u8) -> int { + use cast; + use rt; + use os; + rt::init(argc, argv); + { + let main: fn() = unsafe { cast::transmute(main) }; + let boot: fn(fn()) = unsafe { cast::transmute(boot) }; + boot(main); + } + unsafe { rt::cleanup(); } + os::get_exit_status() +} diff --git a/src/test/compile-fail/boot-1.rs b/src/test/compile-fail/boot-1.rs new file mode 100644 index 0000000000000..e648493463798 --- /dev/null +++ b/src/test/compile-fail/boot-1.rs @@ -0,0 +1,15 @@ +// Copyright 2013 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// error-pattern: no #[boot] functions found + +#[no_boot]; + +fn main() {} diff --git a/src/test/compile-fail/boot-2.rs b/src/test/compile-fail/boot-2.rs new file mode 100644 index 0000000000000..b3a8dfc7c1400 --- /dev/null +++ b/src/test/compile-fail/boot-2.rs @@ -0,0 +1,19 @@ +// Copyright 2013 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// error-pattern: too many #[boot] functions found + +#[no_boot]; + +#[boot] extern mod green; +#[boot] extern mod native; + +fn main() {} + diff --git a/src/test/compile-fail/boot-3.rs b/src/test/compile-fail/boot-3.rs new file mode 100644 index 0000000000000..1965804f8c01b --- /dev/null +++ b/src/test/compile-fail/boot-3.rs @@ -0,0 +1,22 @@ +// Copyright 2013 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// error-pattern: too many #[boot] functions found + +#[no_boot]; + +#[boot] extern mod green; + +#[boot] +fn boot() {} + +fn main() {} + + diff --git a/src/test/compile-fail/boot-4.rs b/src/test/compile-fail/boot-4.rs new file mode 100644 index 0000000000000..ae693b9fef44d --- /dev/null +++ b/src/test/compile-fail/boot-4.rs @@ -0,0 +1,19 @@ +// Copyright 2013 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// error-pattern: too many #[boot] functions found + +#[boot] +fn boot() {} + +fn main() {} + + + diff --git a/src/test/run-pass/boot-1.rs b/src/test/run-pass/boot-1.rs new file mode 100644 index 0000000000000..ce3dac6c8f9d2 --- /dev/null +++ b/src/test/run-pass/boot-1.rs @@ -0,0 +1,16 @@ +// Copyright 2013 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#[no_boot]; + +#[boot] fn boot(_: fn()) {} + +fn main() {} + diff --git a/src/test/run-pass/boot-2.rs b/src/test/run-pass/boot-2.rs new file mode 100644 index 0000000000000..4947ba20199d6 --- /dev/null +++ b/src/test/run-pass/boot-2.rs @@ -0,0 +1,29 @@ +// Copyright 2013 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#[no_boot]; + +#[boot] extern mod green; + +use std::rt::task::Task; +use std::rt::local::Local; +use std::rt::Runtime; + +fn main() { + let mut t = Local::borrow(None::); + match t.get().maybe_take_runtime::() { + Some(rt) => { + t.get().put_runtime(rt as ~Runtime); + } + None => fail!() + } +} + + diff --git a/src/test/run-pass/boot-3.rs b/src/test/run-pass/boot-3.rs new file mode 100644 index 0000000000000..327f6585ee018 --- /dev/null +++ b/src/test/run-pass/boot-3.rs @@ -0,0 +1,30 @@ +// Copyright 2013 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#[no_boot]; + +#[boot] extern mod native; + +use std::rt::task::Task; +use std::rt::local::Local; +use std::rt::Runtime; + +fn main() { + let mut t = Local::borrow(None::); + match t.get().maybe_take_runtime::() { + Some(rt) => { + t.get().put_runtime(rt as ~Runtime); + } + None => fail!() + } +} + + + diff --git a/src/test/run-pass/boot-4.rs b/src/test/run-pass/boot-4.rs new file mode 100644 index 0000000000000..547026feb5c62 --- /dev/null +++ b/src/test/run-pass/boot-4.rs @@ -0,0 +1,15 @@ +// Copyright 2013 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +extern mod native; +extern mod green; + +fn main() { +}