Skip to content

Commit b490a2a

Browse files
committed
Don't use LLVM's target features
1 parent 567b794 commit b490a2a

File tree

6 files changed

+84
-39
lines changed

6 files changed

+84
-39
lines changed

compiler/rustc_codegen_llvm/src/back/write.rs

+6-2
Original file line numberDiff line numberDiff line change
@@ -95,11 +95,15 @@ pub fn write_output_file<'ll>(
9595
}
9696
}
9797

98-
pub fn create_informational_target_machine(sess: &Session) -> OwnedTargetMachine {
98+
pub fn create_informational_target_machine(
99+
sess: &Session,
100+
extra_features: bool,
101+
) -> OwnedTargetMachine {
99102
let config = TargetMachineFactoryConfig { split_dwarf_file: None, output_obj_file: None };
100103
// Can't use query system here quite yet because this function is invoked before the query
101104
// system/tcx is set up.
102-
let features = llvm_util::global_llvm_features(sess, false);
105+
let features =
106+
if extra_features { llvm_util::global_llvm_features(sess, false) } else { Vec::new() };
103107
target_machine_factory(sess, config::OptLevel::No, &features)(config)
104108
.unwrap_or_else(|err| llvm_err(sess.dcx(), err).raise())
105109
}

compiler/rustc_codegen_llvm/src/context.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,7 @@ pub unsafe fn create_module<'ll>(
149149

150150
// Ensure the data-layout values hardcoded remain the defaults.
151151
{
152-
let tm = crate::back::write::create_informational_target_machine(tcx.sess);
152+
let tm = crate::back::write::create_informational_target_machine(tcx.sess, true);
153153
unsafe {
154154
llvm::LLVMRustSetDataLayoutFromTargetMachine(llmod, &tm);
155155
}

compiler/rustc_codegen_llvm/src/lib.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -434,7 +434,7 @@ impl ModuleLlvm {
434434
ModuleLlvm {
435435
llmod_raw,
436436
llcx,
437-
tm: ManuallyDrop::new(create_informational_target_machine(tcx.sess)),
437+
tm: ManuallyDrop::new(create_informational_target_machine(tcx.sess, true)),
438438
}
439439
}
440440
}

compiler/rustc_codegen_llvm/src/llvm_util.rs

+49-14
Original file line numberDiff line numberDiff line change
@@ -308,7 +308,53 @@ pub fn check_tied_features(
308308
/// Used to generate cfg variables and apply features
309309
/// Must express features in the way Rust understands them
310310
pub fn target_features(sess: &Session, allow_unstable: bool) -> Vec<Symbol> {
311-
let target_machine = create_informational_target_machine(sess);
311+
let rust_features = sess
312+
.target
313+
.supported_target_features()
314+
.iter()
315+
.map(|(feature, _, _)| {
316+
(to_llvm_features(sess, feature).llvm_feature_name, Symbol::intern(feature))
317+
})
318+
.collect::<FxHashMap<_, _>>();
319+
320+
let mut features = FxHashSet::default();
321+
322+
// Add base features for the target
323+
let target_machine = create_informational_target_machine(sess, false);
324+
features.extend(
325+
sess.target
326+
.supported_target_features()
327+
.iter()
328+
.filter(|(feature, _, _)| {
329+
// skip checking special features, as LLVM may not understands them
330+
if RUSTC_SPECIAL_FEATURES.contains(feature) {
331+
return true;
332+
}
333+
// check that all features in a given smallvec are enabled
334+
for llvm_feature in to_llvm_features(sess, feature) {
335+
let cstr = SmallCStr::new(llvm_feature);
336+
if !unsafe { llvm::LLVMRustHasFeature(&target_machine, cstr.as_ptr()) } {
337+
return false;
338+
}
339+
}
340+
true
341+
})
342+
.map(|(feature, _, _)| Symbol::intern(feature)),
343+
);
344+
345+
// Add enabled features
346+
for llvm_feature in global_llvm_features(sess, false) {
347+
let (add, llvm_feature) = llvm_feature.split_at(1);
348+
let feature =
349+
rust_features.get(llvm_feature).cloned().unwrap_or(Symbol::intern(llvm_feature));
350+
if add == "+" {
351+
features.extend(sess.target.implied_target_features(std::iter::once(feature)));
352+
} else if add == "-" {
353+
features.remove(&feature);
354+
}
355+
}
356+
357+
// Filter enabled features based on feature gates
312358
sess.target
313359
.supported_target_features()
314360
.iter()
@@ -320,18 +366,7 @@ pub fn target_features(sess: &Session, allow_unstable: bool) -> Vec<Symbol> {
320366
}
321367
})
322368
.filter(|feature| {
323-
// skip checking special features, as LLVM may not understands them
324-
if RUSTC_SPECIAL_FEATURES.contains(feature) {
325-
return true;
326-
}
327-
// check that all features in a given smallvec are enabled
328-
for llvm_feature in to_llvm_features(sess, feature) {
329-
let cstr = SmallCStr::new(llvm_feature);
330-
if !unsafe { llvm::LLVMRustHasFeature(&target_machine, cstr.as_ptr()) } {
331-
return false;
332-
}
333-
}
334-
true
369+
RUSTC_SPECIAL_FEATURES.contains(feature) || features.contains(&Symbol::intern(feature))
335370
})
336371
.map(|feature| Symbol::intern(feature))
337372
.collect()
@@ -440,7 +475,7 @@ fn print_target_features(out: &mut String, sess: &Session, tm: &llvm::TargetMach
440475

441476
pub(crate) fn print(req: &PrintRequest, mut out: &mut String, sess: &Session) {
442477
require_inited();
443-
let tm = create_informational_target_machine(sess);
478+
let tm = create_informational_target_machine(sess, true);
444479
match req.kind {
445480
PrintKind::TargetCPUs => {
446481
// SAFETY generate a C compatible string from a byte slice to pass

compiler/rustc_codegen_ssa/src/target_features.rs

+2-21
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use rustc_ast::ast;
22
use rustc_attr::InstructionSetAttr;
3-
use rustc_data_structures::fx::{FxHashMap, FxIndexSet};
3+
use rustc_data_structures::fx::FxIndexSet;
44
use rustc_data_structures::unord::{ExtendUnord, UnordMap, UnordSet};
55
use rustc_errors::Applicability;
66
use rustc_hir::def::DefKind;
@@ -165,26 +165,7 @@ pub(crate) fn provide(providers: &mut Providers) {
165165
}
166166
},
167167
implied_target_features: |tcx, feature| {
168-
let implied_features = tcx
169-
.sess
170-
.target
171-
.supported_target_features()
172-
.iter()
173-
.map(|(f, _, i)| (Symbol::intern(f), i))
174-
.collect::<FxHashMap<_, _>>();
175-
176-
// implied target features have their own implied target features, so we traverse the
177-
// map until there are no more features to add
178-
let mut features = UnordSet::new();
179-
let mut new_features = vec![feature];
180-
while let Some(new_feature) = new_features.pop() {
181-
if features.insert(new_feature) {
182-
if let Some(implied_features) = implied_features.get(&new_feature) {
183-
new_features.extend(implied_features.iter().copied().map(Symbol::intern))
184-
}
185-
}
186-
}
187-
features
168+
tcx.sess.target.implied_target_features(std::iter::once(feature)).into()
188169
},
189170
asm_target_features,
190171
..*providers

compiler/rustc_target/src/target_features.rs

+25
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
12
use rustc_span::symbol::{sym, Symbol};
23

34
/// Features that control behaviour of rustc, rather than the codegen.
@@ -469,4 +470,28 @@ impl super::spec::Target {
469470
_ => &[],
470471
}
471472
}
473+
474+
pub fn implied_target_features(
475+
&self,
476+
base_features: impl Iterator<Item = Symbol>,
477+
) -> FxHashSet<Symbol> {
478+
let implied_features = self
479+
.supported_target_features()
480+
.iter()
481+
.map(|(f, _, i)| (Symbol::intern(f), i))
482+
.collect::<FxHashMap<_, _>>();
483+
484+
// implied target features have their own implied target features, so we traverse the
485+
// map until there are no more features to add
486+
let mut features = FxHashSet::default();
487+
let mut new_features = base_features.collect::<Vec<Symbol>>();
488+
while let Some(new_feature) = new_features.pop() {
489+
if features.insert(new_feature) {
490+
if let Some(implied_features) = implied_features.get(&new_feature) {
491+
new_features.extend(implied_features.iter().copied().map(Symbol::intern))
492+
}
493+
}
494+
}
495+
features
496+
}
472497
}

0 commit comments

Comments
 (0)