about summary refs log tree commit diff
path: root/src/librustc
diff options
context:
space:
mode:
authorJakub Bukaj <jakub@jakub.cc>2014-11-18 00:23:50 +0100
committerJakub Bukaj <jakub@jakub.cc>2014-11-18 00:23:50 +0100
commitfcf9fb61574a415653fa0c787058972312ce1235 (patch)
treeb1118890b3dbea75a886d0dc14abd4ba5e7b2ed0 /src/librustc
parentf09279395b6ca40f1398277971586197f949738a (diff)
parent33893aebcf19f6bf7e0102406117afa34a955425 (diff)
downloadrust-fcf9fb61574a415653fa0c787058972312ce1235.tar.gz
rust-fcf9fb61574a415653fa0c787058972312ce1235.zip
rollup merge of #18890: luqmana/tf
This is especially useful for declaring a static with external linkage in an executable. There isn't any way to do that currently since we mark everything in an executable as internal by default.

Also, a quick fix to have the no-compiler-rt target option respected when building staticlibs as well.
Diffstat (limited to 'src/librustc')
-rw-r--r--src/librustc/back/link.rs4
-rw-r--r--src/librustc/lint/builtin.rs1
-rw-r--r--src/librustc/middle/trans/base.rs45
-rw-r--r--src/librustc/middle/trans/foreign.rs29
4 files changed, 50 insertions, 29 deletions
diff --git a/src/librustc/back/link.rs b/src/librustc/back/link.rs
index 97ab3209d28..766715ff251 100644
--- a/src/librustc/back/link.rs
+++ b/src/librustc/back/link.rs
@@ -728,7 +728,9 @@ fn link_staticlib(sess: &Session, obj_filename: &Path, out_filename: &Path) {
     if sess.target.target.options.morestack {
         ab.add_native_library("morestack").unwrap();
     }
-    ab.add_native_library("compiler-rt").unwrap();
+    if !sess.target.target.options.no_compiler_rt {
+        ab.add_native_library("compiler-rt").unwrap();
+    }
 
     let crates = sess.cstore.get_used_crates(cstore::RequireStatic);
     let mut all_native_libs = vec![];
diff --git a/src/librustc/lint/builtin.rs b/src/librustc/lint/builtin.rs
index 4247d192d6d..df014eb1206 100644
--- a/src/librustc/lint/builtin.rs
+++ b/src/librustc/lint/builtin.rs
@@ -623,6 +623,7 @@ impl LintPass for UnusedAttributes {
             "link",
             "link_name",
             "link_section",
+            "linkage",
             "no_builtins",
             "no_mangle",
             "no_split_stack",
diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs
index b267d1d7f3e..77ee433e62b 100644
--- a/src/librustc/middle/trans/base.rs
+++ b/src/librustc/middle/trans/base.rs
@@ -36,7 +36,7 @@ use driver::config::{NoDebugInfo, FullDebugInfo};
 use driver::driver::{CrateAnalysis, CrateTranslation, ModuleTranslation};
 use driver::session::Session;
 use lint;
-use llvm::{BasicBlockRef, ValueRef, Vector, get_param};
+use llvm::{BasicBlockRef, Linkage, ValueRef, Vector, get_param};
 use llvm;
 use metadata::{csearch, encoder, loader};
 use middle::astencode;
@@ -2137,6 +2137,32 @@ impl<'a, 'tcx, 'v> Visitor<'v> for TransItemVisitor<'a, 'tcx> {
     }
 }
 
+pub fn llvm_linkage_by_name(name: &str) -> Option<Linkage> {
+    // Use the names from src/llvm/docs/LangRef.rst here. Most types are only
+    // applicable to variable declarations and may not really make sense for
+    // Rust code in the first place but whitelist them anyway and trust that
+    // the user knows what s/he's doing. Who knows, unanticipated use cases
+    // may pop up in the future.
+    //
+    // ghost, dllimport, dllexport and linkonce_odr_autohide are not supported
+    // and don't have to be, LLVM treats them as no-ops.
+    match name {
+        "appending" => Some(llvm::AppendingLinkage),
+        "available_externally" => Some(llvm::AvailableExternallyLinkage),
+        "common" => Some(llvm::CommonLinkage),
+        "extern_weak" => Some(llvm::ExternalWeakLinkage),
+        "external" => Some(llvm::ExternalLinkage),
+        "internal" => Some(llvm::InternalLinkage),
+        "linkonce" => Some(llvm::LinkOnceAnyLinkage),
+        "linkonce_odr" => Some(llvm::LinkOnceODRLinkage),
+        "private" => Some(llvm::PrivateLinkage),
+        "weak" => Some(llvm::WeakAnyLinkage),
+        "weak_odr" => Some(llvm::WeakODRLinkage),
+        _ => None,
+    }
+}
+
+
 /// Enum describing the origin of an LLVM `Value`, for linkage purposes.
 pub enum ValueOrigin {
     /// The LLVM `Value` is in this context because the corresponding item was
@@ -2175,6 +2201,23 @@ pub fn update_linkage(ccx: &CrateContext,
     }
 
     match id {
+        Some(id) => {
+            let item = ccx.tcx().map.get(id);
+            if let ast_map::NodeItem(i) = item {
+                if let Some(name) =  attr::first_attr_value_str_by_name(i.attrs[], "linkage") {
+                    if let Some(linkage) = llvm_linkage_by_name(name.get()) {
+                        llvm::SetLinkage(llval, linkage);
+                    } else {
+                        ccx.sess().span_fatal(i.span, "invalid linkage specified");
+                    }
+                    return;
+                }
+            }
+        }
+        _ => {}
+    }
+
+    match id {
         Some(id) if ccx.reachable().contains(&id) => {
             llvm::SetLinkage(llval, llvm::ExternalLinkage);
         },
diff --git a/src/librustc/middle/trans/foreign.rs b/src/librustc/middle/trans/foreign.rs
index 1afb73b08f7..940319d050b 100644
--- a/src/librustc/middle/trans/foreign.rs
+++ b/src/librustc/middle/trans/foreign.rs
@@ -10,10 +10,10 @@
 
 
 use back::{link};
-use llvm::{ValueRef, CallConv, Linkage, get_param};
+use llvm::{ValueRef, CallConv, get_param};
 use llvm;
 use middle::weak_lang_items;
-use middle::trans::base::push_ctxt;
+use middle::trans::base::{llvm_linkage_by_name, push_ctxt};
 use middle::trans::base;
 use middle::trans::build::*;
 use middle::trans::cabi;
@@ -101,31 +101,6 @@ pub fn llvm_calling_convention(ccx: &CrateContext,
     }
 }
 
-pub fn llvm_linkage_by_name(name: &str) -> Option<Linkage> {
-    // Use the names from src/llvm/docs/LangRef.rst here. Most types are only
-    // applicable to variable declarations and may not really make sense for
-    // Rust code in the first place but whitelist them anyway and trust that
-    // the user knows what s/he's doing. Who knows, unanticipated use cases
-    // may pop up in the future.
-    //
-    // ghost, dllimport, dllexport and linkonce_odr_autohide are not supported
-    // and don't have to be, LLVM treats them as no-ops.
-    match name {
-        "appending" => Some(llvm::AppendingLinkage),
-        "available_externally" => Some(llvm::AvailableExternallyLinkage),
-        "common" => Some(llvm::CommonLinkage),
-        "extern_weak" => Some(llvm::ExternalWeakLinkage),
-        "external" => Some(llvm::ExternalLinkage),
-        "internal" => Some(llvm::InternalLinkage),
-        "linkonce" => Some(llvm::LinkOnceAnyLinkage),
-        "linkonce_odr" => Some(llvm::LinkOnceODRLinkage),
-        "private" => Some(llvm::PrivateLinkage),
-        "weak" => Some(llvm::WeakAnyLinkage),
-        "weak_odr" => Some(llvm::WeakODRLinkage),
-        _ => None,
-    }
-}
-
 pub fn register_static(ccx: &CrateContext,
                        foreign_item: &ast::ForeignItem) -> ValueRef {
     let ty = ty::node_id_to_type(ccx.tcx(), foreign_item.id);