about summary refs log tree commit diff
diff options
context:
space:
mode:
authorCaleb Zulawski <caleb.zulawski@gmail.com>2024-08-03 04:45:48 -0400
committerCaleb Zulawski <caleb.zulawski@gmail.com>2024-08-07 00:41:48 -0400
commit484aca885765739d5fa1f3d77e082552d8c4bc58 (patch)
treefef49ea3f2d6988581d0212073bfcfbb110d2f0c
parentfbd618d4aa8f3a6c998b81aa83a543d4c09d9bb3 (diff)
downloadrust-484aca885765739d5fa1f3d77e082552d8c4bc58.tar.gz
rust-484aca885765739d5fa1f3d77e082552d8c4bc58.zip
Don't use LLVM's target features
-rw-r--r--compiler/rustc_codegen_llvm/src/back/write.rs8
-rw-r--r--compiler/rustc_codegen_llvm/src/context.rs2
-rw-r--r--compiler/rustc_codegen_llvm/src/lib.rs2
-rw-r--r--compiler/rustc_codegen_llvm/src/llvm_util.rs63
-rw-r--r--compiler/rustc_codegen_ssa/src/target_features.rs23
-rw-r--r--compiler/rustc_target/src/target_features.rs25
6 files changed, 84 insertions, 39 deletions
diff --git a/compiler/rustc_codegen_llvm/src/back/write.rs b/compiler/rustc_codegen_llvm/src/back/write.rs
index 5a7909d1511..890fcf508a8 100644
--- a/compiler/rustc_codegen_llvm/src/back/write.rs
+++ b/compiler/rustc_codegen_llvm/src/back/write.rs
@@ -95,11 +95,15 @@ pub fn write_output_file<'ll>(
     }
 }
 
-pub fn create_informational_target_machine(sess: &Session) -> OwnedTargetMachine {
+pub fn create_informational_target_machine(
+    sess: &Session,
+    extra_features: bool,
+) -> OwnedTargetMachine {
     let config = TargetMachineFactoryConfig { split_dwarf_file: None, output_obj_file: None };
     // Can't use query system here quite yet because this function is invoked before the query
     // system/tcx is set up.
-    let features = llvm_util::global_llvm_features(sess, false);
+    let features =
+        if extra_features { llvm_util::global_llvm_features(sess, false) } else { Vec::new() };
     target_machine_factory(sess, config::OptLevel::No, &features)(config)
         .unwrap_or_else(|err| llvm_err(sess.dcx(), err).raise())
 }
diff --git a/compiler/rustc_codegen_llvm/src/context.rs b/compiler/rustc_codegen_llvm/src/context.rs
index ea930421b58..1dc3fbfc7b3 100644
--- a/compiler/rustc_codegen_llvm/src/context.rs
+++ b/compiler/rustc_codegen_llvm/src/context.rs
@@ -149,7 +149,7 @@ pub unsafe fn create_module<'ll>(
 
     // Ensure the data-layout values hardcoded remain the defaults.
     {
-        let tm = crate::back::write::create_informational_target_machine(tcx.sess);
+        let tm = crate::back::write::create_informational_target_machine(tcx.sess, true);
         unsafe {
             llvm::LLVMRustSetDataLayoutFromTargetMachine(llmod, &tm);
         }
diff --git a/compiler/rustc_codegen_llvm/src/lib.rs b/compiler/rustc_codegen_llvm/src/lib.rs
index 41e9cfd1066..333f1fdf6e0 100644
--- a/compiler/rustc_codegen_llvm/src/lib.rs
+++ b/compiler/rustc_codegen_llvm/src/lib.rs
@@ -434,7 +434,7 @@ impl ModuleLlvm {
             ModuleLlvm {
                 llmod_raw,
                 llcx,
-                tm: ManuallyDrop::new(create_informational_target_machine(tcx.sess)),
+                tm: ManuallyDrop::new(create_informational_target_machine(tcx.sess, true)),
             }
         }
     }
diff --git a/compiler/rustc_codegen_llvm/src/llvm_util.rs b/compiler/rustc_codegen_llvm/src/llvm_util.rs
index c70f6dd8180..e85974b7cc1 100644
--- a/compiler/rustc_codegen_llvm/src/llvm_util.rs
+++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs
@@ -308,7 +308,53 @@ pub fn check_tied_features(
 /// Used to generate cfg variables and apply features
 /// Must express features in the way Rust understands them
 pub fn target_features(sess: &Session, allow_unstable: bool) -> Vec<Symbol> {
-    let target_machine = create_informational_target_machine(sess);
+    let rust_features = sess
+        .target
+        .supported_target_features()
+        .iter()
+        .map(|(feature, _, _)| {
+            (to_llvm_features(sess, feature).llvm_feature_name, Symbol::intern(feature))
+        })
+        .collect::<FxHashMap<_, _>>();
+
+    let mut features = FxHashSet::default();
+
+    // Add base features for the target
+    let target_machine = create_informational_target_machine(sess, false);
+    features.extend(
+        sess.target
+            .supported_target_features()
+            .iter()
+            .filter(|(feature, _, _)| {
+                // skip checking special features, as LLVM may not understands them
+                if RUSTC_SPECIAL_FEATURES.contains(feature) {
+                    return true;
+                }
+                // check that all features in a given smallvec are enabled
+                for llvm_feature in to_llvm_features(sess, feature) {
+                    let cstr = SmallCStr::new(llvm_feature);
+                    if !unsafe { llvm::LLVMRustHasFeature(&target_machine, cstr.as_ptr()) } {
+                        return false;
+                    }
+                }
+                true
+            })
+            .map(|(feature, _, _)| Symbol::intern(feature)),
+    );
+
+    // Add enabled features
+    for llvm_feature in global_llvm_features(sess, false) {
+        let (add, llvm_feature) = llvm_feature.split_at(1);
+        let feature =
+            rust_features.get(llvm_feature).cloned().unwrap_or(Symbol::intern(llvm_feature));
+        if add == "+" {
+            features.extend(sess.target.implied_target_features(std::iter::once(feature)));
+        } else if add == "-" {
+            features.remove(&feature);
+        }
+    }
+
+    // Filter enabled features based on feature gates
     sess.target
         .supported_target_features()
         .iter()
@@ -320,18 +366,7 @@ pub fn target_features(sess: &Session, allow_unstable: bool) -> Vec<Symbol> {
             }
         })
         .filter(|feature| {
-            // skip checking special features, as LLVM may not understands them
-            if RUSTC_SPECIAL_FEATURES.contains(feature) {
-                return true;
-            }
-            // check that all features in a given smallvec are enabled
-            for llvm_feature in to_llvm_features(sess, feature) {
-                let cstr = SmallCStr::new(llvm_feature);
-                if !unsafe { llvm::LLVMRustHasFeature(&target_machine, cstr.as_ptr()) } {
-                    return false;
-                }
-            }
-            true
+            RUSTC_SPECIAL_FEATURES.contains(feature) || features.contains(&Symbol::intern(feature))
         })
         .map(|feature| Symbol::intern(feature))
         .collect()
@@ -440,7 +475,7 @@ fn print_target_features(out: &mut String, sess: &Session, tm: &llvm::TargetMach
 
 pub(crate) fn print(req: &PrintRequest, mut out: &mut String, sess: &Session) {
     require_inited();
-    let tm = create_informational_target_machine(sess);
+    let tm = create_informational_target_machine(sess, true);
     match req.kind {
         PrintKind::TargetCPUs => {
             // SAFETY generate a C compatible string from a byte slice to pass
diff --git a/compiler/rustc_codegen_ssa/src/target_features.rs b/compiler/rustc_codegen_ssa/src/target_features.rs
index 536f39375bb..c84b844cd04 100644
--- a/compiler/rustc_codegen_ssa/src/target_features.rs
+++ b/compiler/rustc_codegen_ssa/src/target_features.rs
@@ -1,6 +1,6 @@
 use rustc_ast::ast;
 use rustc_attr::InstructionSetAttr;
-use rustc_data_structures::fx::{FxHashMap, FxIndexSet};
+use rustc_data_structures::fx::FxIndexSet;
 use rustc_data_structures::unord::{ExtendUnord, UnordMap, UnordSet};
 use rustc_errors::Applicability;
 use rustc_hir::def::DefKind;
@@ -165,26 +165,7 @@ pub(crate) fn provide(providers: &mut Providers) {
             }
         },
         implied_target_features: |tcx, feature| {
-            let implied_features = tcx
-                .sess
-                .target
-                .supported_target_features()
-                .iter()
-                .map(|(f, _, i)| (Symbol::intern(f), i))
-                .collect::<FxHashMap<_, _>>();
-
-            // implied target features have their own implied target features, so we traverse the
-            // map until there are no more features to add
-            let mut features = UnordSet::new();
-            let mut new_features = vec![feature];
-            while let Some(new_feature) = new_features.pop() {
-                if features.insert(new_feature) {
-                    if let Some(implied_features) = implied_features.get(&new_feature) {
-                        new_features.extend(implied_features.iter().copied().map(Symbol::intern))
-                    }
-                }
-            }
-            features
+            tcx.sess.target.implied_target_features(std::iter::once(feature)).into()
         },
         asm_target_features,
         ..*providers
diff --git a/compiler/rustc_target/src/target_features.rs b/compiler/rustc_target/src/target_features.rs
index f408db1dcba..0e9979e1bb7 100644
--- a/compiler/rustc_target/src/target_features.rs
+++ b/compiler/rustc_target/src/target_features.rs
@@ -1,3 +1,4 @@
+use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_span::symbol::{sym, Symbol};
 
 /// Features that control behaviour of rustc, rather than the codegen.
@@ -469,4 +470,28 @@ impl super::spec::Target {
             _ => &[],
         }
     }
+
+    pub fn implied_target_features(
+        &self,
+        base_features: impl Iterator<Item = Symbol>,
+    ) -> FxHashSet<Symbol> {
+        let implied_features = self
+            .supported_target_features()
+            .iter()
+            .map(|(f, _, i)| (Symbol::intern(f), i))
+            .collect::<FxHashMap<_, _>>();
+
+        // implied target features have their own implied target features, so we traverse the
+        // map until there are no more features to add
+        let mut features = FxHashSet::default();
+        let mut new_features = base_features.collect::<Vec<Symbol>>();
+        while let Some(new_feature) = new_features.pop() {
+            if features.insert(new_feature) {
+                if let Some(implied_features) = implied_features.get(&new_feature) {
+                    new_features.extend(implied_features.iter().copied().map(Symbol::intern))
+                }
+            }
+        }
+        features
+    }
 }