Don't use LLVM's target features

This commit is contained in:
Caleb Zulawski 2024-08-03 04:45:48 -04:00
parent fbd618d4aa
commit 484aca8857
6 changed files with 84 additions and 39 deletions

View file

@ -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())
}

View file

@ -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);
}

View file

@ -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)),
}
}
}

View file

@ -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