about summary refs log tree commit diff
diff options
context:
space:
mode:
authorWesley Wiser <wwiser@gmail.com>2018-02-27 20:12:32 -0500
committerWesley Wiser <wwiser@gmail.com>2018-03-06 20:18:51 -0500
commit07890c5c59b3a6b33a03aee009307f8e7b3ece96 (patch)
tree12ce0978bca16fb831fbad551572782ba365a6c1
parent39f9d23b656d5fc5bfaf8cc8b85dceb1e8b91b99 (diff)
downloadrust-07890c5c59b3a6b33a03aee009307f8e7b3ece96.tar.gz
rust-07890c5c59b3a6b33a03aee009307f8e7b3ece96.zip
Add target_features to TransFnAttrs
Part of #47320
-rw-r--r--src/librustc/dep_graph/dep_node.rs1
-rw-r--r--src/librustc/hir/check_attr.rs2
-rw-r--r--src/librustc/hir/mod.rs2
-rw-r--r--src/librustc/ich/impls_hir.rs2
-rw-r--r--src/librustc/ty/maps/mod.rs1
-rw-r--r--src/librustc/ty/maps/plumbing.rs1
-rw-r--r--src/librustc_trans/attributes.rs105
-rw-r--r--src/librustc_trans_utils/trans_crate.rs6
-rw-r--r--src/librustc_typeck/collect.rs82
9 files changed, 101 insertions, 101 deletions
diff --git a/src/librustc/dep_graph/dep_node.rs b/src/librustc/dep_graph/dep_node.rs
index 2550ef667e0..ed46296389d 100644
--- a/src/librustc/dep_graph/dep_node.rs
+++ b/src/librustc/dep_graph/dep_node.rs
@@ -636,7 +636,6 @@ define_dep_nodes!( <'tcx>
     [] SubstituteNormalizeAndTestPredicates { key: (DefId, &'tcx Substs<'tcx>) },
 
     [input] TargetFeaturesWhitelist,
-    [] TargetFeaturesEnabled(DefId),
 
     [] InstanceDefSizeEstimate { instance_def: InstanceDef<'tcx> },
 
diff --git a/src/librustc/hir/check_attr.rs b/src/librustc/hir/check_attr.rs
index a073910fdc8..d2270345260 100644
--- a/src/librustc/hir/check_attr.rs
+++ b/src/librustc/hir/check_attr.rs
@@ -47,7 +47,7 @@ struct CheckAttrVisitor<'a, 'tcx: 'a> {
 impl<'a, 'tcx> CheckAttrVisitor<'a, 'tcx> {
     /// Check any attribute.
     fn check_attributes(&self, item: &hir::Item, target: Target) {
-        self.tcx.target_features_enabled(self.tcx.hir.local_def_id(item.id));
+        self.tcx.trans_fn_attrs(self.tcx.hir.local_def_id(item.id));
 
         for attr in &item.attrs {
             if let Some(name) = attr.name() {
diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs
index 69f43bc293d..b484c62188d 100644
--- a/src/librustc/hir/mod.rs
+++ b/src/librustc/hir/mod.rs
@@ -2217,6 +2217,7 @@ pub struct TransFnAttrs {
     pub flags: TransFnAttrFlags,
     pub inline: InlineAttr,
     pub export_name: Option<Symbol>,
+    pub target_features: Vec<Symbol>,
 }
 
 bitflags! {
@@ -2238,6 +2239,7 @@ impl TransFnAttrs {
             flags: TransFnAttrFlags::empty(),
             inline: InlineAttr::None,
             export_name: None,
+            target_features: vec![],
         }
     }
 
diff --git a/src/librustc/ich/impls_hir.rs b/src/librustc/ich/impls_hir.rs
index 75c3f8ef28a..69487d3899e 100644
--- a/src/librustc/ich/impls_hir.rs
+++ b/src/librustc/ich/impls_hir.rs
@@ -1148,11 +1148,13 @@ impl<'hir> HashStable<StableHashingContext<'hir>> for hir::TransFnAttrs
             flags,
             inline,
             export_name,
+            ref target_features,
         } = *self;
 
         flags.hash_stable(hcx, hasher);
         inline.hash_stable(hcx, hasher);
         export_name.hash_stable(hcx, hasher);
+        target_features.hash_stable(hcx, hasher);
     }
 }
 
diff --git a/src/librustc/ty/maps/mod.rs b/src/librustc/ty/maps/mod.rs
index 9fb021ea6d7..43a71f1c0d3 100644
--- a/src/librustc/ty/maps/mod.rs
+++ b/src/librustc/ty/maps/mod.rs
@@ -384,7 +384,6 @@ define_maps! { <'tcx>
 
     [] fn target_features_whitelist:
         target_features_whitelist_node(CrateNum) -> Lrc<FxHashSet<String>>,
-    [] fn target_features_enabled: TargetFeaturesEnabled(DefId) -> Lrc<Vec<String>>,
 
     // Get an estimate of the size of an InstanceDef based on its MIR for CGU partitioning.
     [] fn instance_def_size_estimate: instance_def_size_estimate_dep_node(ty::InstanceDef<'tcx>)
diff --git a/src/librustc/ty/maps/plumbing.rs b/src/librustc/ty/maps/plumbing.rs
index 69332f6502f..cec3b88b804 100644
--- a/src/librustc/ty/maps/plumbing.rs
+++ b/src/librustc/ty/maps/plumbing.rs
@@ -930,7 +930,6 @@ pub fn force_from_dep_node<'a, 'gcx, 'lcx>(tcx: TyCtxt<'a, 'gcx, 'lcx>,
         DepKind::OutputFilenames => { force!(output_filenames, LOCAL_CRATE); }
 
         DepKind::TargetFeaturesWhitelist => { force!(target_features_whitelist, LOCAL_CRATE); }
-        DepKind::TargetFeaturesEnabled => { force!(target_features_enabled, def_id!()); }
 
         DepKind::GetSymbolExportLevel => { force!(symbol_export_level, def_id!()); }
         DepKind::Features => { force!(features_query, LOCAL_CRATE); }
diff --git a/src/librustc_trans/attributes.rs b/src/librustc_trans/attributes.rs
index 89ce6bdbb55..d5ec8d1b552 100644
--- a/src/librustc_trans/attributes.rs
+++ b/src/librustc_trans/attributes.rs
@@ -12,19 +12,15 @@
 use std::ffi::{CStr, CString};
 
 use rustc::hir::TransFnAttrFlags;
-use rustc::hir::Unsafety;
 use rustc::hir::def_id::{DefId, LOCAL_CRATE};
 use rustc::session::config::Sanitizer;
-use rustc::ty::TyCtxt;
 use rustc::ty::maps::Providers;
-use rustc_data_structures::fx::FxHashSet;
 use rustc_data_structures::sync::Lrc;
 
 use llvm::{self, Attribute, ValueRef};
 use llvm::AttributePlace::Function;
 use llvm_util;
 pub use syntax::attr::{self, InlineAttr};
-use syntax::ast;
 use context::CodegenCx;
 
 /// Mark LLVM function to use provided inline heuristic.
@@ -127,10 +123,18 @@ pub fn from_fn_attrs(cx: &CodegenCx, llfn: ValueRef, id: DefId) {
         unwind(llfn, false);
     }
 
-    let target_features = cx.tcx.target_features_enabled(id);
-
-    if !target_features.is_empty() {
-        let val = CString::new(target_features.join(",")).unwrap();
+    let features =
+        trans_fn_attrs.target_features
+        .iter()
+        .map(|f| {
+            let feature = &*f.as_str();
+            format!("+{}", llvm_util::to_llvm_feature(cx.tcx.sess, feature))
+        })
+        .collect::<Vec<String>>()
+        .join(",");
+
+    if !features.is_empty() {
+        let val = CString::new(features).unwrap();
         llvm::AddFunctionAttrStringValue(
             llfn, llvm::AttributePlace::Function,
             cstr("target-features\0"), &val);
@@ -149,89 +153,4 @@ pub fn provide(providers: &mut Providers) {
             .map(|c| c.to_string())
             .collect())
     };
-
-    providers.target_features_enabled = |tcx, id| {
-        let whitelist = tcx.target_features_whitelist(LOCAL_CRATE);
-        let mut target_features = Vec::new();
-        for attr in tcx.get_attrs(id).iter() {
-            if !attr.check_name("target_feature") {
-                continue
-            }
-            if let Some(val) = attr.value_str() {
-                for feat in val.as_str().split(",").map(|f| f.trim()) {
-                    if !feat.is_empty() && !feat.contains('\0') {
-                        target_features.push(feat.to_string());
-                    }
-                }
-                let msg = "#[target_feature = \"..\"] is deprecated and will \
-                           eventually be removed, use \
-                           #[target_feature(enable = \"..\")] instead";
-                tcx.sess.span_warn(attr.span, &msg);
-                continue
-            }
-
-            if tcx.fn_sig(id).unsafety() == Unsafety::Normal {
-                let msg = "#[target_feature(..)] can only be applied to \
-                           `unsafe` function";
-                tcx.sess.span_err(attr.span, msg);
-            }
-            from_target_feature(tcx, attr, &whitelist, &mut target_features);
-        }
-        Lrc::new(target_features)
-    };
-}
-
-fn from_target_feature(
-    tcx: TyCtxt,
-    attr: &ast::Attribute,
-    whitelist: &FxHashSet<String>,
-    target_features: &mut Vec<String>,
-) {
-    let list = match attr.meta_item_list() {
-        Some(list) => list,
-        None => {
-            let msg = "#[target_feature] attribute must be of the form \
-                       #[target_feature(..)]";
-            tcx.sess.span_err(attr.span, &msg);
-            return
-        }
-    };
-
-    for item in list {
-        if !item.check_name("enable") {
-            let msg = "#[target_feature(..)] only accepts sub-keys of `enable` \
-                       currently";
-            tcx.sess.span_err(item.span, &msg);
-            continue
-        }
-        let value = match item.value_str() {
-            Some(list) => list,
-            None => {
-                let msg = "#[target_feature] attribute must be of the form \
-                           #[target_feature(enable = \"..\")]";
-                tcx.sess.span_err(item.span, &msg);
-                continue
-            }
-        };
-        let value = value.as_str();
-        for feature in value.split(',') {
-            if whitelist.contains(feature) {
-                let llvm_feature = llvm_util::to_llvm_feature(&tcx.sess, feature);
-                target_features.push(format!("+{}", llvm_feature));
-                continue
-            }
-
-            let msg = format!("the feature named `{}` is not valid for \
-                               this target", feature);
-            let mut err = tcx.sess.struct_span_err(item.span, &msg);
-
-            if feature.starts_with("+") {
-                let valid = whitelist.contains(&feature[1..]);
-                if valid {
-                    err.help("consider removing the leading `+` in the feature name");
-                }
-            }
-            err.emit();
-        }
-    }
 }
diff --git a/src/librustc_trans_utils/trans_crate.rs b/src/librustc_trans_utils/trans_crate.rs
index 04e993f1b03..4667e363307 100644
--- a/src/librustc_trans_utils/trans_crate.rs
+++ b/src/librustc_trans_utils/trans_crate.rs
@@ -44,6 +44,7 @@ use rustc::middle::cstore::EncodedMetadata;
 use rustc::middle::cstore::MetadataLoader;
 use rustc::dep_graph::DepGraph;
 use rustc_back::target::Target;
+use rustc_data_structures::fx::FxHashSet;
 use rustc_mir::monomorphize::collector;
 use link::{build_link_meta, out_filename};
 
@@ -198,8 +199,9 @@ impl TransCrate for MetadataOnlyTransCrate {
 
     fn provide(&self, providers: &mut Providers) {
         ::symbol_names::provide(providers);
-        providers.target_features_enabled = |_tcx, _id| {
-            Lrc::new(Vec::new()) // Just a dummy
+
+        providers.target_features_whitelist = |_tcx, _cnum| {
+            Lrc::new(FxHashSet()) // Just a dummy
         };
     }
     fn provide_extern(&self, _providers: &mut Providers) {}
diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs
index f8e10c208ac..c16d2c593aa 100644
--- a/src/librustc_typeck/collect.rs
+++ b/src/librustc_typeck/collect.rs
@@ -36,6 +36,7 @@ use rustc::ty::{ToPredicate, ReprOptions};
 use rustc::ty::{self, AdtKind, ToPolyTraitRef, Ty, TyCtxt};
 use rustc::ty::maps::Providers;
 use rustc::ty::util::IntTypeExt;
+use rustc::util::nodemap::FxHashSet;
 use util::nodemap::FxHashMap;
 
 use rustc_const_math::ConstInt;
@@ -47,10 +48,10 @@ use syntax::codemap::Spanned;
 use syntax::symbol::{Symbol, keywords};
 use syntax_pos::{Span, DUMMY_SP};
 
-use rustc::hir::{self, map as hir_map, TransFnAttrs, TransFnAttrFlags};
+use rustc::hir::{self, map as hir_map, TransFnAttrs, TransFnAttrFlags, Unsafety};
 use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap};
 use rustc::hir::def::{Def, CtorKind};
-use rustc::hir::def_id::DefId;
+use rustc::hir::def_id::{DefId, LOCAL_CRATE};
 
 ///////////////////////////////////////////////////////////////////////////
 // Main entry point
@@ -1727,11 +1728,68 @@ fn is_foreign_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     }
 }
 
+fn from_target_feature(
+    tcx: TyCtxt,
+    attr: &ast::Attribute,
+    whitelist: &FxHashSet<String>,
+    target_features: &mut Vec<Symbol>,
+) {
+    let list = match attr.meta_item_list() {
+        Some(list) => list,
+        None => {
+            let msg = "#[target_feature] attribute must be of the form \
+                       #[target_feature(..)]";
+            tcx.sess.span_err(attr.span, &msg);
+            return
+        }
+    };
+
+    for item in list {
+        if !item.check_name("enable") {
+            let msg = "#[target_feature(..)] only accepts sub-keys of `enable` \
+                       currently";
+            tcx.sess.span_err(item.span, &msg);
+            continue
+        }
+        let value = match item.value_str() {
+            Some(list) => list,
+            None => {
+                let msg = "#[target_feature] attribute must be of the form \
+                           #[target_feature(enable = \"..\")]";
+                tcx.sess.span_err(item.span, &msg);
+                continue
+            }
+        };
+        let value = value.as_str();
+        for feature in value.split(',') {
+            if whitelist.contains(feature) {
+                target_features.push(Symbol::intern(feature));
+                continue
+            }
+
+            let msg = format!("the feature named `{}` is not valid for \
+                               this target", feature);
+            let mut err = tcx.sess.struct_span_err(item.span, &msg);
+
+            if feature.starts_with("+") {
+                let valid = whitelist.contains(&feature[1..]);
+                if valid {
+                    err.help("consider removing the leading `+` in the feature name");
+                }
+            }
+            err.emit();
+        }
+    }
+}
+
+
 fn trans_fn_attrs<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, id: DefId) -> TransFnAttrs {
     let attrs = tcx.get_attrs(id);
 
     let mut trans_fn_attrs = TransFnAttrs::new();
 
+    let whitelist = tcx.target_features_whitelist(LOCAL_CRATE);
+
     for attr in attrs.iter() {
         if attr.check_name("cold") {
             trans_fn_attrs.flags |= TransFnAttrFlags::COLD;
@@ -1790,6 +1848,26 @@ fn trans_fn_attrs<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, id: DefId) -> TransFnAt
                     .span_label(attr.span, "did you mean #[export_name=\"*\"]?")
                     .emit();
             }
+        } else if attr.check_name("target_feature") {
+            if let Some(val) = attr.value_str() {
+                for feat in val.as_str().split(",").map(|f| f.trim()) {
+                    if !feat.is_empty() && !feat.contains('\0') {
+                        trans_fn_attrs.target_features.push(Symbol::intern(feat));
+                    }
+                }
+                let msg = "#[target_feature = \"..\"] is deprecated and will \
+                           eventually be removed, use \
+                           #[target_feature(enable = \"..\")] instead";
+                tcx.sess.span_warn(attr.span, &msg);
+                continue
+            }
+
+            if tcx.fn_sig(id).unsafety() == Unsafety::Normal {
+                let msg = "#[target_feature(..)] can only be applied to \
+                           `unsafe` function";
+                tcx.sess.span_err(attr.span, msg);
+            }
+            from_target_feature(tcx, attr, &whitelist, &mut trans_fn_attrs.target_features);
         }
     }