about summary refs log tree commit diff
path: root/src/librustc
diff options
context:
space:
mode:
Diffstat (limited to 'src/librustc')
-rw-r--r--src/librustc/front/std_inject.rs29
-rw-r--r--src/librustc/middle/lang_items.rs199
-rw-r--r--src/librustc/middle/trans/base.rs62
3 files changed, 165 insertions, 125 deletions
diff --git a/src/librustc/front/std_inject.rs b/src/librustc/front/std_inject.rs
index 2253f151ddf..b34829bf47f 100644
--- a/src/librustc/front/std_inject.rs
+++ b/src/librustc/front/std_inject.rs
@@ -35,6 +35,10 @@ fn use_std(crate: &ast::Crate) -> bool {
     !attr::contains_name(crate.attrs, "no_std")
 }
 
+fn use_uv(crate: &ast::Crate) -> bool {
+    !attr::contains_name(crate.attrs, "no_uv")
+}
+
 fn no_prelude(attrs: &[ast::Attribute]) -> bool {
     attr::contains_name(attrs, "no_implicit_prelude")
 }
@@ -53,19 +57,30 @@ struct StandardLibraryInjector {
 impl fold::ast_fold for StandardLibraryInjector {
     fn fold_crate(&self, crate: ast::Crate) -> ast::Crate {
         let version = STD_VERSION.to_managed();
-        let vi1 = ast::view_item {
+        let vers_item = attr::mk_name_value_item_str(@"vers", version);
+        let mut vis = ~[ast::view_item {
             node: ast::view_item_extern_mod(self.sess.ident_of("std"),
                                             None,
-                                            ~[],
+                                            ~[vers_item.clone()],
                                             ast::DUMMY_NODE_ID),
-            attrs: ~[
-                attr::mk_attr(attr::mk_name_value_item_str(@"vers", version))
-            ],
+            attrs: ~[],
             vis: ast::private,
             span: dummy_sp()
-        };
+        }];
+
+        if use_uv(&crate) && !*self.sess.building_library {
+            vis.push(ast::view_item {
+                node: ast::view_item_extern_mod(self.sess.ident_of("rustuv"),
+                                                None,
+                                                ~[vers_item],
+                                                ast::DUMMY_NODE_ID),
+                attrs: ~[],
+                vis: ast::private,
+                span: dummy_sp()
+            });
+        }
 
-        let vis = vec::append(~[vi1], crate.module.view_items);
+        vis.push_all(crate.module.view_items);
         let mut new_module = ast::_mod {
             view_items: vis,
             ..crate.module.clone()
diff --git a/src/librustc/middle/lang_items.rs b/src/librustc/middle/lang_items.rs
index 6c15dc019ea..e8d6a7267df 100644
--- a/src/librustc/middle/lang_items.rs
+++ b/src/librustc/middle/lang_items.rs
@@ -24,10 +24,9 @@ use driver::session::Session;
 use metadata::csearch::each_lang_item;
 use metadata::cstore::iter_crate_data;
 use middle::ty::{BuiltinBound, BoundFreeze, BoundSend, BoundSized};
-use syntax::ast::{Crate, DefId, MetaItem};
+use syntax::ast;
 use syntax::ast_util::local_def;
 use syntax::attr::AttrMetaMethods;
-use syntax::ast::{item};
 use syntax::visit;
 use syntax::visit::Visitor;
 
@@ -81,20 +80,22 @@ pub enum LangItem {
     TyDescStructLangItem,              // 36
     TyVisitorTraitLangItem,            // 37
     OpaqueStructLangItem,              // 38
+
+    EventLoopFactoryLangItem,          // 39
 }
 
 pub struct LanguageItems {
-    items: [Option<DefId>, ..39]
+    items: [Option<ast::DefId>, ..40]
 }
 
 impl LanguageItems {
     pub fn new() -> LanguageItems {
         LanguageItems {
-            items: [ None, ..39 ]
+            items: [ None, ..40 ]
         }
     }
 
-    pub fn items<'a>(&'a self) -> Enumerate<vec::VecIterator<'a, Option<DefId>>> {
+    pub fn items<'a>(&'a self) -> Enumerate<vec::VecIterator<'a, Option<ast::DefId>>> {
         self.items.iter().enumerate()
     }
 
@@ -145,13 +146,15 @@ impl LanguageItems {
             37 => "ty_visitor",
             38 => "opaque",
 
+            39 => "event_loop_factory",
+
             _ => "???"
         }
     }
 
     // FIXME #4621: Method macros sure would be nice here.
 
-    pub fn require(&self, it: LangItem) -> Result<DefId, ~str> {
+    pub fn require(&self, it: LangItem) -> Result<ast::DefId, ~str> {
         match self.items[it as uint] {
             Some(id) => Ok(id),
             None => Err(format!("requires `{}` lang_item",
@@ -159,7 +162,7 @@ impl LanguageItems {
         }
     }
 
-    pub fn to_builtin_kind(&self, id: DefId) -> Option<BuiltinBound> {
+    pub fn to_builtin_kind(&self, id: ast::DefId) -> Option<BuiltinBound> {
         if Some(id) == self.freeze_trait() {
             Some(BoundFreeze)
         } else if Some(id) == self.send_trait() {
@@ -171,162 +174,166 @@ impl LanguageItems {
         }
     }
 
-    pub fn freeze_trait(&self) -> Option<DefId> {
+    pub fn freeze_trait(&self) -> Option<ast::DefId> {
         self.items[FreezeTraitLangItem as uint]
     }
-    pub fn send_trait(&self) -> Option<DefId> {
+    pub fn send_trait(&self) -> Option<ast::DefId> {
         self.items[SendTraitLangItem as uint]
     }
-    pub fn sized_trait(&self) -> Option<DefId> {
+    pub fn sized_trait(&self) -> Option<ast::DefId> {
         self.items[SizedTraitLangItem as uint]
     }
 
-    pub fn drop_trait(&self) -> Option<DefId> {
+    pub fn drop_trait(&self) -> Option<ast::DefId> {
         self.items[DropTraitLangItem as uint]
     }
 
-    pub fn add_trait(&self) -> Option<DefId> {
+    pub fn add_trait(&self) -> Option<ast::DefId> {
         self.items[AddTraitLangItem as uint]
     }
-    pub fn sub_trait(&self) -> Option<DefId> {
+    pub fn sub_trait(&self) -> Option<ast::DefId> {
         self.items[SubTraitLangItem as uint]
     }
-    pub fn mul_trait(&self) -> Option<DefId> {
+    pub fn mul_trait(&self) -> Option<ast::DefId> {
         self.items[MulTraitLangItem as uint]
     }
-    pub fn div_trait(&self) -> Option<DefId> {
+    pub fn div_trait(&self) -> Option<ast::DefId> {
         self.items[DivTraitLangItem as uint]
     }
-    pub fn rem_trait(&self) -> Option<DefId> {
+    pub fn rem_trait(&self) -> Option<ast::DefId> {
         self.items[RemTraitLangItem as uint]
     }
-    pub fn neg_trait(&self) -> Option<DefId> {
+    pub fn neg_trait(&self) -> Option<ast::DefId> {
         self.items[NegTraitLangItem as uint]
     }
-    pub fn not_trait(&self) -> Option<DefId> {
+    pub fn not_trait(&self) -> Option<ast::DefId> {
         self.items[NotTraitLangItem as uint]
     }
-    pub fn bitxor_trait(&self) -> Option<DefId> {
+    pub fn bitxor_trait(&self) -> Option<ast::DefId> {
         self.items[BitXorTraitLangItem as uint]
     }
-    pub fn bitand_trait(&self) -> Option<DefId> {
+    pub fn bitand_trait(&self) -> Option<ast::DefId> {
         self.items[BitAndTraitLangItem as uint]
     }
-    pub fn bitor_trait(&self) -> Option<DefId> {
+    pub fn bitor_trait(&self) -> Option<ast::DefId> {
         self.items[BitOrTraitLangItem as uint]
     }
-    pub fn shl_trait(&self) -> Option<DefId> {
+    pub fn shl_trait(&self) -> Option<ast::DefId> {
         self.items[ShlTraitLangItem as uint]
     }
-    pub fn shr_trait(&self) -> Option<DefId> {
+    pub fn shr_trait(&self) -> Option<ast::DefId> {
         self.items[ShrTraitLangItem as uint]
     }
-    pub fn index_trait(&self) -> Option<DefId> {
+    pub fn index_trait(&self) -> Option<ast::DefId> {
         self.items[IndexTraitLangItem as uint]
     }
 
-    pub fn eq_trait(&self) -> Option<DefId> {
+    pub fn eq_trait(&self) -> Option<ast::DefId> {
         self.items[EqTraitLangItem as uint]
     }
-    pub fn ord_trait(&self) -> Option<DefId> {
+    pub fn ord_trait(&self) -> Option<ast::DefId> {
         self.items[OrdTraitLangItem as uint]
     }
 
-    pub fn str_eq_fn(&self) -> Option<DefId> {
+    pub fn str_eq_fn(&self) -> Option<ast::DefId> {
         self.items[StrEqFnLangItem as uint]
     }
-    pub fn uniq_str_eq_fn(&self) -> Option<DefId> {
+    pub fn uniq_str_eq_fn(&self) -> Option<ast::DefId> {
         self.items[UniqStrEqFnLangItem as uint]
     }
-    pub fn fail_fn(&self) -> Option<DefId> {
+    pub fn fail_fn(&self) -> Option<ast::DefId> {
         self.items[FailFnLangItem as uint]
     }
-    pub fn fail_bounds_check_fn(&self) -> Option<DefId> {
+    pub fn fail_bounds_check_fn(&self) -> Option<ast::DefId> {
         self.items[FailBoundsCheckFnLangItem as uint]
     }
-    pub fn exchange_malloc_fn(&self) -> Option<DefId> {
+    pub fn exchange_malloc_fn(&self) -> Option<ast::DefId> {
         self.items[ExchangeMallocFnLangItem as uint]
     }
-    pub fn closure_exchange_malloc_fn(&self) -> Option<DefId> {
+    pub fn closure_exchange_malloc_fn(&self) -> Option<ast::DefId> {
         self.items[ClosureExchangeMallocFnLangItem as uint]
     }
-    pub fn exchange_free_fn(&self) -> Option<DefId> {
+    pub fn exchange_free_fn(&self) -> Option<ast::DefId> {
         self.items[ExchangeFreeFnLangItem as uint]
     }
-    pub fn malloc_fn(&self) -> Option<DefId> {
+    pub fn malloc_fn(&self) -> Option<ast::DefId> {
         self.items[MallocFnLangItem as uint]
     }
-    pub fn free_fn(&self) -> Option<DefId> {
+    pub fn free_fn(&self) -> Option<ast::DefId> {
         self.items[FreeFnLangItem as uint]
     }
-    pub fn borrow_as_imm_fn(&self) -> Option<DefId> {
+    pub fn borrow_as_imm_fn(&self) -> Option<ast::DefId> {
         self.items[BorrowAsImmFnLangItem as uint]
     }
-    pub fn borrow_as_mut_fn(&self) -> Option<DefId> {
+    pub fn borrow_as_mut_fn(&self) -> Option<ast::DefId> {
         self.items[BorrowAsMutFnLangItem as uint]
     }
-    pub fn return_to_mut_fn(&self) -> Option<DefId> {
+    pub fn return_to_mut_fn(&self) -> Option<ast::DefId> {
         self.items[ReturnToMutFnLangItem as uint]
     }
-    pub fn check_not_borrowed_fn(&self) -> Option<DefId> {
+    pub fn check_not_borrowed_fn(&self) -> Option<ast::DefId> {
         self.items[CheckNotBorrowedFnLangItem as uint]
     }
-    pub fn strdup_uniq_fn(&self) -> Option<DefId> {
+    pub fn strdup_uniq_fn(&self) -> Option<ast::DefId> {
         self.items[StrDupUniqFnLangItem as uint]
     }
-    pub fn record_borrow_fn(&self) -> Option<DefId> {
+    pub fn record_borrow_fn(&self) -> Option<ast::DefId> {
         self.items[RecordBorrowFnLangItem as uint]
     }
-    pub fn unrecord_borrow_fn(&self) -> Option<DefId> {
+    pub fn unrecord_borrow_fn(&self) -> Option<ast::DefId> {
         self.items[UnrecordBorrowFnLangItem as uint]
     }
-    pub fn start_fn(&self) -> Option<DefId> {
+    pub fn start_fn(&self) -> Option<ast::DefId> {
         self.items[StartFnLangItem as uint]
     }
-    pub fn ty_desc(&self) -> Option<DefId> {
+    pub fn ty_desc(&self) -> Option<ast::DefId> {
         self.items[TyDescStructLangItem as uint]
     }
-    pub fn ty_visitor(&self) -> Option<DefId> {
+    pub fn ty_visitor(&self) -> Option<ast::DefId> {
         self.items[TyVisitorTraitLangItem as uint]
     }
-    pub fn opaque(&self) -> Option<DefId> {
+    pub fn opaque(&self) -> Option<ast::DefId> {
         self.items[OpaqueStructLangItem as uint]
     }
+    pub fn event_loop_factory(&self) -> Option<ast::DefId> {
+        self.items[EventLoopFactoryLangItem as uint]
+    }
 }
 
-struct LanguageItemCollector<'self> {
+struct LanguageItemCollector {
     items: LanguageItems,
 
-    crate: &'self Crate,
     session: Session,
 
     item_refs: HashMap<&'static str, uint>,
 }
 
 struct LanguageItemVisitor<'self> {
-    this: *mut LanguageItemCollector<'self>,
+    this: &'self mut LanguageItemCollector,
 }
 
 impl<'self> Visitor<()> for LanguageItemVisitor<'self> {
-
-    fn visit_item(&mut self, item:@item, _:()) {
-
-                for attribute in item.attrs.iter() {
-                    unsafe {
-                        (*self.this).match_and_collect_meta_item(
-                            local_def(item.id),
-                            attribute.node.value
-                        );
+    fn visit_item(&mut self, item: @ast::item, _: ()) {
+        match extract(item.attrs) {
+            Some(value) => {
+                let item_index = self.this.item_refs.find_equiv(&value).map(|x| *x);
+
+                match item_index {
+                    Some(item_index) => {
+                        self.this.collect_item(item_index, local_def(item.id))
                     }
+                    None => {}
                 }
+            }
+            None => {}
+        }
 
         visit::walk_item(self, item, ());
     }
 }
 
-impl<'self> LanguageItemCollector<'self> {
-    pub fn new<'a>(crate: &'a Crate, session: Session)
-                   -> LanguageItemCollector<'a> {
+impl LanguageItemCollector {
+    pub fn new(session: Session) -> LanguageItemCollector {
         let mut item_refs = HashMap::new();
 
         item_refs.insert("freeze", FreezeTraitLangItem as uint);
@@ -374,27 +381,16 @@ impl<'self> LanguageItemCollector<'self> {
         item_refs.insert("ty_desc", TyDescStructLangItem as uint);
         item_refs.insert("ty_visitor", TyVisitorTraitLangItem as uint);
         item_refs.insert("opaque", OpaqueStructLangItem as uint);
+        item_refs.insert("event_loop_factory", EventLoopFactoryLangItem as uint);
 
         LanguageItemCollector {
-            crate: crate,
             session: session,
             items: LanguageItems::new(),
             item_refs: item_refs
         }
     }
 
-    pub fn match_and_collect_meta_item(&mut self,
-                                       item_def_id: DefId,
-                                       meta_item: &MetaItem) {
-        match meta_item.name_str_pair() {
-            Some((key, value)) => {
-                self.match_and_collect_item(item_def_id, key, value);
-            }
-            None => {} // skip
-        }
-    }
-
-    pub fn collect_item(&mut self, item_index: uint, item_def_id: DefId) {
+    pub fn collect_item(&mut self, item_index: uint, item_def_id: ast::DefId) {
         // Check for duplicates.
         match self.items.items[item_index] {
             Some(original_def_id) if original_def_id != item_def_id => {
@@ -410,33 +406,9 @@ impl<'self> LanguageItemCollector<'self> {
         self.items.items[item_index] = Some(item_def_id);
     }
 
-    pub fn match_and_collect_item(&mut self,
-                                  item_def_id: DefId,
-                                  key: &str,
-                                  value: @str) {
-        if "lang" != key {
-            return;    // Didn't match.
-        }
-
-        let item_index = self.item_refs.find_equiv(&value).map(|x| *x);
-        // prevent borrow checker from considering         ^~~~~~~~~~~
-        // self to be borrowed (annoying)
-
-        match item_index {
-            Some(item_index) => {
-                self.collect_item(item_index, item_def_id);
-            }
-            None => {
-                // Didn't match.
-                return;
-            }
-        }
-    }
-
-    pub fn collect_local_language_items(&mut self) {
-        let this: *mut LanguageItemCollector = &mut *self;
-        let mut v = LanguageItemVisitor { this: this };
-        visit::walk_crate(&mut v, self.crate, ());
+    pub fn collect_local_language_items(&mut self, crate: &ast::Crate) {
+        let mut v = LanguageItemVisitor { this: self };
+        visit::walk_crate(&mut v, crate, ());
     }
 
     pub fn collect_external_language_items(&mut self) {
@@ -444,24 +416,37 @@ impl<'self> LanguageItemCollector<'self> {
         do iter_crate_data(crate_store) |crate_number, _crate_metadata| {
             do each_lang_item(crate_store, crate_number)
                     |node_id, item_index| {
-                let def_id = DefId { crate: crate_number, node: node_id };
+                let def_id = ast::DefId { crate: crate_number, node: node_id };
                 self.collect_item(item_index, def_id);
                 true
             };
         }
     }
 
-    pub fn collect(&mut self) {
-        self.collect_local_language_items();
+    pub fn collect(&mut self, crate: &ast::Crate) {
+        self.collect_local_language_items(crate);
         self.collect_external_language_items();
     }
 }
 
-pub fn collect_language_items(crate: &Crate,
+pub fn extract(attrs: &[ast::Attribute]) -> Option<@str> {
+    for attribute in attrs.iter() {
+        match attribute.name_str_pair() {
+            Some((key, value)) if "lang" == key => {
+                return Some(value);
+            }
+            Some(*) | None => {}
+        }
+    }
+
+    return None;
+}
+
+pub fn collect_language_items(crate: &ast::Crate,
                               session: Session)
                            -> LanguageItems {
-    let mut collector = LanguageItemCollector::new(crate, session);
-    collector.collect();
+    let mut collector = LanguageItemCollector::new(session);
+    collector.collect(crate);
     let LanguageItemCollector { items, _ } = collector;
     session.abort_if_errors();
     items
diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs
index 74f9e2114e1..665aaad5f47 100644
--- a/src/librustc/middle/trans/base.rs
+++ b/src/librustc/middle/trans/base.rs
@@ -2596,16 +2596,36 @@ pub fn get_item_val(ccx: @mut CrateContext, id: ast::NodeId) -> ValueRef {
                             foreign::register_foreign_item_fn(ccx, abis, &path, ni)
                         }
                         ast::foreign_item_static(*) => {
-                            let ident = foreign::link_name(ccx, ni);
-                            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);
+                            // Treat the crate map static specially in order to
+                            // a weak-linkage-like functionality where it's
+                            // dynamically resolved at runtime. If we're
+                            // building a library, then we declare the static
+                            // with weak linkage, but if we're building a
+                            // library then we've already declared the crate map
+                            // so use that instead.
+                            if attr::contains_name(ni.attrs, "crate_map") {
+                                if *ccx.sess.building_library {
+                                    let s = "_rust_crate_map_toplevel";
+                                    let g = unsafe { do s.with_c_str |buf| {
+                                        let ty = type_of(ccx, ty);
+                                        llvm::LLVMAddGlobal(ccx.llmod,
+                                                            ty.to_ref(), buf)
+                                    } };
+                                    lib::llvm::SetLinkage(g,
+                                        lib::llvm::ExternalWeakLinkage);
+                                    g
+                                } else {
+                                    ccx.crate_map
+                                }
+                            } else {
+                                let ident = foreign::link_name(ccx, ni);
+                                unsafe {
+                                    do ident.with_c_str |buf| {
+                                        let ty = type_of(ccx, ty);
+                                        llvm::LLVMAddGlobal(ccx.llmod,
+                                                            ty.to_ref(), buf)
+                                    }
                                 }
-                                g
                             }
                         }
                     }
@@ -2929,7 +2949,12 @@ pub fn decl_crate_map(sess: session::Session, mapmeta: LinkMeta,
 
     let sym_name = ~"_rust_crate_map_" + mapname;
     let slicetype = Type::struct_([int_type, int_type], false);
-    let maptype = Type::struct_([Type::i32(), slicetype, slicetype], false);
+    let maptype = Type::struct_([
+        Type::i32(),        // version
+        slicetype,          // child modules
+        slicetype,          // sub crate-maps
+        int_type.ptr_to(),  // event loop factory
+    ], false);
     let map = do sym_name.with_c_str |buf| {
         unsafe {
             llvm::LLVMAddGlobal(llmod, maptype.to_ref(), buf)
@@ -2964,6 +2989,20 @@ pub fn fill_crate_map(ccx: &mut CrateContext, map: ValueRef) {
         subcrates.push(p2i(ccx, cr));
         i += 1;
     }
+    let event_loop_factory = if !*ccx.sess.building_library {
+        match ccx.tcx.lang_items.event_loop_factory() {
+            Some(did) => unsafe {
+                let name = csearch::get_symbol(ccx.sess.cstore, did);
+                let global = do name.with_c_str |buf| {
+                    llvm::LLVMAddGlobal(ccx.llmod, ccx.int_type.to_ref(), buf)
+                };
+                global
+            },
+            None => C_null(ccx.int_type.ptr_to())
+        }
+    } else {
+        C_null(ccx.int_type.ptr_to())
+    };
     unsafe {
         let maptype = Type::array(&ccx.int_type, subcrates.len() as u64);
         let vec_elements = do "_crate_map_child_vectors".with_c_str |buf| {
@@ -2983,7 +3022,8 @@ pub fn fill_crate_map(ccx: &mut CrateContext, map: ValueRef) {
              C_struct([
                 p2i(ccx, vec_elements),
                 C_uint(ccx, subcrates.len())
-             ], false)
+             ], false),
+            event_loop_factory,
         ], false));
     }
 }