Don't use LLVM's target features
This commit is contained in:
parent
fbd618d4aa
commit
484aca8857
@ -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 };
|
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
|
// Can't use query system here quite yet because this function is invoked before the query
|
||||||
// system/tcx is set up.
|
// 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)
|
target_machine_factory(sess, config::OptLevel::No, &features)(config)
|
||||||
.unwrap_or_else(|err| llvm_err(sess.dcx(), err).raise())
|
.unwrap_or_else(|err| llvm_err(sess.dcx(), err).raise())
|
||||||
}
|
}
|
||||||
|
@ -149,7 +149,7 @@ pub unsafe fn create_module<'ll>(
|
|||||||
|
|
||||||
// Ensure the data-layout values hardcoded remain the defaults.
|
// 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 {
|
unsafe {
|
||||||
llvm::LLVMRustSetDataLayoutFromTargetMachine(llmod, &tm);
|
llvm::LLVMRustSetDataLayoutFromTargetMachine(llmod, &tm);
|
||||||
}
|
}
|
||||||
|
@ -434,7 +434,7 @@ fn new_metadata(tcx: TyCtxt<'_>, mod_name: &str) -> Self {
|
|||||||
ModuleLlvm {
|
ModuleLlvm {
|
||||||
llmod_raw,
|
llmod_raw,
|
||||||
llcx,
|
llcx,
|
||||||
tm: ManuallyDrop::new(create_informational_target_machine(tcx.sess)),
|
tm: ManuallyDrop::new(create_informational_target_machine(tcx.sess, true)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -308,7 +308,53 @@ pub fn check_tied_features(
|
|||||||
/// Used to generate cfg variables and apply features
|
/// Used to generate cfg variables and apply features
|
||||||
/// Must express features in the way Rust understands them
|
/// Must express features in the way Rust understands them
|
||||||
pub fn target_features(sess: &Session, allow_unstable: bool) -> Vec<Symbol> {
|
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
|
sess.target
|
||||||
.supported_target_features()
|
.supported_target_features()
|
||||||
.iter()
|
.iter()
|
||||||
@ -320,18 +366,7 @@ pub fn target_features(sess: &Session, allow_unstable: bool) -> Vec<Symbol> {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
.filter(|feature| {
|
.filter(|feature| {
|
||||||
// skip checking special features, as LLVM may not understands them
|
RUSTC_SPECIAL_FEATURES.contains(feature) || features.contains(&Symbol::intern(feature))
|
||||||
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))
|
.map(|feature| Symbol::intern(feature))
|
||||||
.collect()
|
.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) {
|
pub(crate) fn print(req: &PrintRequest, mut out: &mut String, sess: &Session) {
|
||||||
require_inited();
|
require_inited();
|
||||||
let tm = create_informational_target_machine(sess);
|
let tm = create_informational_target_machine(sess, true);
|
||||||
match req.kind {
|
match req.kind {
|
||||||
PrintKind::TargetCPUs => {
|
PrintKind::TargetCPUs => {
|
||||||
// SAFETY generate a C compatible string from a byte slice to pass
|
// SAFETY generate a C compatible string from a byte slice to pass
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use rustc_ast::ast;
|
use rustc_ast::ast;
|
||||||
use rustc_attr::InstructionSetAttr;
|
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_data_structures::unord::{ExtendUnord, UnordMap, UnordSet};
|
||||||
use rustc_errors::Applicability;
|
use rustc_errors::Applicability;
|
||||||
use rustc_hir::def::DefKind;
|
use rustc_hir::def::DefKind;
|
||||||
@ -165,26 +165,7 @@ pub(crate) fn provide(providers: &mut Providers) {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
implied_target_features: |tcx, feature| {
|
implied_target_features: |tcx, feature| {
|
||||||
let implied_features = tcx
|
tcx.sess.target.implied_target_features(std::iter::once(feature)).into()
|
||||||
.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
|
|
||||||
},
|
},
|
||||||
asm_target_features,
|
asm_target_features,
|
||||||
..*providers
|
..*providers
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
||||||
use rustc_span::symbol::{sym, Symbol};
|
use rustc_span::symbol::{sym, Symbol};
|
||||||
|
|
||||||
/// Features that control behaviour of rustc, rather than the codegen.
|
/// Features that control behaviour of rustc, rather than the codegen.
|
||||||
@ -469,4 +470,28 @@ pub fn tied_target_features(&self) -> &'static [&'static [&'static str]] {
|
|||||||
_ => &[],
|
_ => &[],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user