]> git.lizzy.rs Git - rust.git/commitdiff
Add target_features to TransFnAttrs
authorWesley Wiser <wwiser@gmail.com>
Wed, 28 Feb 2018 01:12:32 +0000 (20:12 -0500)
committerWesley Wiser <wwiser@gmail.com>
Wed, 7 Mar 2018 01:18:51 +0000 (20:18 -0500)
Part of #47320

src/librustc/dep_graph/dep_node.rs
src/librustc/hir/check_attr.rs
src/librustc/hir/mod.rs
src/librustc/ich/impls_hir.rs
src/librustc/ty/maps/mod.rs
src/librustc/ty/maps/plumbing.rs
src/librustc_trans/attributes.rs
src/librustc_trans_utils/trans_crate.rs
src/librustc_typeck/collect.rs

index 2550ef667e0804c92870e70113b2815ef7babaf1..ed46296389da4ba4f0ad96d6f5f83d3fca4183fe 100644 (file)
@@ -636,7 +636,6 @@ pub fn fingerprint_needed_for_crate_hash(self) -> bool {
     [] SubstituteNormalizeAndTestPredicates { key: (DefId, &'tcx Substs<'tcx>) },
 
     [input] TargetFeaturesWhitelist,
-    [] TargetFeaturesEnabled(DefId),
 
     [] InstanceDefSizeEstimate { instance_def: InstanceDef<'tcx> },
 
index a073910fdc83f1d06d23d655189d044a56ea05b7..d22703452605b6bb242a0b91d956ef22fe47d955 100644 (file)
@@ -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() {
index 69f43bc293d0824d51ba95e64f255d44ec6aebe5..b484c62188d39749268f91eeea5f27f5c1be5064 100644 (file)
@@ -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 @@ pub fn new() -> TransFnAttrs {
             flags: TransFnAttrFlags::empty(),
             inline: InlineAttr::None,
             export_name: None,
+            target_features: vec![],
         }
     }
 
index 75c3f8ef28a82bc8de6c99598ab9af93e81dbcd1..69487d3899e7f431edcee8b1e6549f7b18ce391d 100644 (file)
@@ -1148,11 +1148,13 @@ fn hash_stable<W: StableHasherResult>(&self,
             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);
     }
 }
 
index 9fb021ea6d7673d2837b4aab7e962d83a2252c81..43a71f1c0d367ab385449be5ecd9a546e202b7d4 100644 (file)
 
     [] 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>)
index 69332f6502f7e6303a90a1a737aae42556ab4de7..cec3b88b80439608da6e33f85e5ed55a5ce2df23 100644 (file)
@@ -930,7 +930,6 @@ macro_rules! force {
         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); }
index 89ce6bdbb55e2c5e29a81292c53a36d367051192..d5ec8d1b5526256573cf69552de26dc754f878fd 100644 (file)
 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();
-        }
-    }
 }
index 04e993f1b0321bbbac1c91bc22f44e70d16563e1..4667e3633077d3f9dd1d1f4f67eaff2815016693 100644 (file)
@@ -44,6 +44,7 @@
 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 @@ fn metadata_loader(&self) -> Box<MetadataLoader> {
 
     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) {}
index f8e10c208ac6533794f2abfb41ed914f72485ab6..c16d2c593aafc55dea21d11947c28e3cd70458e7 100644 (file)
@@ -36,6 +36,7 @@
 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;
 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);
         }
     }