Skip to content

Commit 39a3b52

Browse files
committed
Auto merge of #87402 - nagisa:nagisa/request-feature-requests-for-features, r=estebank
Direct users towards using Rust target feature names in CLI This PR consists of a couple of changes on how we handle target features. In particular there is a bug-fix wherein we avoid passing through features that aren't prefixed by `+` or `-` to LLVM. These appear to be causing LLVM to assert, which is pretty poor a behaviour (and also makes it pretty clear we expect feature names to be prefixed). The other commit, I anticipate to be somewhat more controversial is outputting a warning when users specify a LLVM-specific, or otherwise unknown, feature name on the CLI. In those situations we request users to either replace it with a known Rust feature name (e.g. `bmi` -> `bmi1`) or file a feature request. I've a couple motivations for this: first of all, if users are specifying these features on the command line, I'm pretty confident there is also a need for these features to be usable via `#[cfg(target_feature)]` machinery. And second, we're growing a fair number of backends recently and having ability to provide some sort of unified-ish interface in this place seems pretty useful to me. Sponsored by: standard.ai
2 parents f0c4da4 + df701a2 commit 39a3b52

22 files changed

+251
-106
lines changed

compiler/rustc_codegen_gcc/src/lib.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@ impl ExtraBackendMethods for GccCodegenBackend {
132132
base::compile_codegen_unit(tcx, cgu_name)
133133
}
134134

135-
fn target_machine_factory(&self, _sess: &Session, _opt_level: OptLevel) -> TargetMachineFactoryFn<Self> {
135+
fn target_machine_factory(&self, _sess: &Session, _opt_level: OptLevel, _features: &[String]) -> TargetMachineFactoryFn<Self> {
136136
// TODO(antoyo): set opt level.
137137
Arc::new(|_| {
138138
Ok(())

compiler/rustc_codegen_llvm/src/attributes.rs

+11-15
Original file line numberDiff line numberDiff line change
@@ -79,13 +79,11 @@ pub fn sanitize_attrs<'ll>(
7979
}
8080
if enabled.contains(SanitizerSet::MEMTAG) {
8181
// Check to make sure the mte target feature is actually enabled.
82-
let sess = cx.tcx.sess;
83-
let features = llvm_util::llvm_global_features(sess).join(",");
84-
let mte_feature_enabled = features.rfind("+mte");
85-
let mte_feature_disabled = features.rfind("-mte");
86-
87-
if mte_feature_enabled.is_none() || (mte_feature_disabled > mte_feature_enabled) {
88-
sess.err("`-Zsanitizer=memtag` requires `-Ctarget-feature=+mte`");
82+
let features = cx.tcx.global_backend_features(());
83+
let mte_feature =
84+
features.iter().map(|s| &s[..]).rfind(|n| ["+mte", "-mte"].contains(&&n[..]));
85+
if let None | Some("-mte") = mte_feature {
86+
cx.tcx.sess.err("`-Zsanitizer=memtag` requires `-Ctarget-feature=+mte`");
8987
}
9088

9189
attrs.push(llvm::AttributeKind::SanitizeMemTag.create_attr(cx.llcx));
@@ -382,10 +380,7 @@ pub fn from_fn_attrs<'ll, 'tcx>(
382380
let mut function_features = function_features
383381
.iter()
384382
.flat_map(|feat| {
385-
llvm_util::to_llvm_feature(cx.tcx.sess, feat)
386-
.into_iter()
387-
.map(|f| format!("+{}", f))
388-
.collect::<Vec<String>>()
383+
llvm_util::to_llvm_features(cx.tcx.sess, feat).into_iter().map(|f| format!("+{}", f))
389384
})
390385
.chain(codegen_fn_attrs.instruction_set.iter().map(|x| match x {
391386
InstructionSetAttr::ArmA32 => "-thumb-mode".to_string(),
@@ -418,10 +413,11 @@ pub fn from_fn_attrs<'ll, 'tcx>(
418413
}
419414

420415
if !function_features.is_empty() {
421-
let mut global_features = llvm_util::llvm_global_features(cx.tcx.sess);
422-
global_features.extend(function_features.into_iter());
423-
let features = global_features.join(",");
424-
let val = CString::new(features).unwrap();
416+
let global_features = cx.tcx.global_backend_features(()).iter().map(|s| &s[..]);
417+
let val = global_features
418+
.chain(function_features.iter().map(|s| &s[..]))
419+
.intersperse(",")
420+
.collect::<SmallCStr>();
425421
to_add.push(llvm::CreateAttrStringValue(cx.llcx, cstr!("target-features"), &val));
426422
}
427423

compiler/rustc_codegen_llvm/src/back/write.rs

+12-5
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,10 @@ pub fn write_output_file<'ll>(
100100

101101
pub fn create_informational_target_machine(sess: &Session) -> &'static mut llvm::TargetMachine {
102102
let config = TargetMachineFactoryConfig { split_dwarf_file: None };
103-
target_machine_factory(sess, config::OptLevel::No)(config)
103+
// Can't use query system here quite yet because this function is invoked before the query
104+
// system/tcx is set up.
105+
let features = llvm_util::global_llvm_features(sess, false);
106+
target_machine_factory(sess, config::OptLevel::No, &features)(config)
104107
.unwrap_or_else(|err| llvm_err(sess.diagnostic(), &err).raise())
105108
}
106109

@@ -115,8 +118,12 @@ pub fn create_target_machine(tcx: TyCtxt<'_>, mod_name: &str) -> &'static mut ll
115118
None
116119
};
117120
let config = TargetMachineFactoryConfig { split_dwarf_file };
118-
target_machine_factory(tcx.sess, tcx.backend_optimization_level(()))(config)
119-
.unwrap_or_else(|err| llvm_err(tcx.sess.diagnostic(), &err).raise())
121+
target_machine_factory(
122+
&tcx.sess,
123+
tcx.backend_optimization_level(()),
124+
tcx.global_backend_features(()),
125+
)(config)
126+
.unwrap_or_else(|err| llvm_err(tcx.sess.diagnostic(), &err).raise())
120127
}
121128

122129
pub fn to_llvm_opt_settings(
@@ -171,6 +178,7 @@ pub(crate) fn to_llvm_code_model(code_model: Option<CodeModel>) -> llvm::CodeMod
171178
pub fn target_machine_factory(
172179
sess: &Session,
173180
optlvl: config::OptLevel,
181+
target_features: &[String],
174182
) -> TargetMachineFactoryFn<LlvmCodegenBackend> {
175183
let reloc_model = to_llvm_relocation_model(sess.relocation_model());
176184

@@ -195,8 +203,7 @@ pub fn target_machine_factory(
195203

196204
let triple = SmallCStr::new(&sess.target.llvm_target);
197205
let cpu = SmallCStr::new(llvm_util::target_cpu(sess));
198-
let features = llvm_util::llvm_global_features(sess).join(",");
199-
let features = CString::new(features).unwrap();
206+
let features = CString::new(target_features.join(",")).unwrap();
200207
let abi = SmallCStr::new(&sess.target.llvm_abiname);
201208
let trap_unreachable =
202209
sess.opts.debugging_opts.trap_unreachable.unwrap_or(sess.target.trap_unreachable);

compiler/rustc_codegen_llvm/src/lib.rs

+9-1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#![feature(extern_types)]
1212
#![feature(once_cell)]
1313
#![feature(nll)]
14+
#![feature(iter_intersperse)]
1415
#![recursion_limit = "256"]
1516
#![allow(rustc::potential_query_instability)]
1617

@@ -32,6 +33,7 @@ use rustc_data_structures::fx::FxHashMap;
3233
use rustc_errors::{ErrorReported, FatalError, Handler};
3334
use rustc_metadata::EncodedMetadata;
3435
use rustc_middle::dep_graph::{WorkProduct, WorkProductId};
36+
use rustc_middle::ty::query::Providers;
3537
use rustc_middle::ty::TyCtxt;
3638
use rustc_session::config::{OptLevel, OutputFilenames, PrintRequest};
3739
use rustc_session::Session;
@@ -126,8 +128,9 @@ impl ExtraBackendMethods for LlvmCodegenBackend {
126128
&self,
127129
sess: &Session,
128130
optlvl: OptLevel,
131+
target_features: &[String],
129132
) -> TargetMachineFactoryFn<Self> {
130-
back::write::target_machine_factory(sess, optlvl)
133+
back::write::target_machine_factory(sess, optlvl, target_features)
131134
}
132135
fn target_cpu<'b>(&self, sess: &'b Session) -> &'b str {
133136
llvm_util::target_cpu(sess)
@@ -251,6 +254,11 @@ impl CodegenBackend for LlvmCodegenBackend {
251254
llvm_util::init(sess); // Make sure llvm is inited
252255
}
253256

257+
fn provide(&self, providers: &mut Providers) {
258+
providers.global_backend_features =
259+
|tcx, ()| llvm_util::global_llvm_features(tcx.sess, true)
260+
}
261+
254262
fn print(&self, req: PrintRequest, sess: &Session) {
255263
match req {
256264
PrintRequest::RelocationModels => {

0 commit comments

Comments
 (0)