Skip to content

Commit d39a637

Browse files
committed
Split PAuth target feature
1 parent 56cd04a commit d39a637

File tree

9 files changed

+148
-15
lines changed

9 files changed

+148
-15
lines changed

compiler/rustc_codegen_llvm/src/attributes.rs

+26-5
Original file line numberDiff line numberDiff line change
@@ -322,12 +322,33 @@ pub fn from_fn_attrs<'ll, 'tcx>(
322322
// The target doesn't care; the subtarget reads our attribute.
323323
apply_tune_cpu_attr(cx, llfn);
324324

325-
let mut function_features = codegen_fn_attrs
326-
.target_features
325+
let function_features =
326+
codegen_fn_attrs.target_features.iter().map(|f| f.as_str()).collect::<Vec<&str>>();
327+
328+
if let Some(f) = llvm_util::check_tied_features(
329+
cx.tcx.sess,
330+
&function_features.iter().map(|f| (*f, true)).collect(),
331+
) {
332+
let span = cx
333+
.tcx
334+
.get_attrs(instance.def_id())
335+
.iter()
336+
.find(|a| a.has_name(rustc_span::sym::target_feature))
337+
.map_or_else(|| cx.tcx.def_span(instance.def_id()), |a| a.span);
338+
let msg = format!(
339+
"the target features {} must all be either enabled or disabled together",
340+
f.join(", ")
341+
);
342+
let mut err = cx.tcx.sess.struct_span_err(span, &msg);
343+
err.help("add the missing features in a `target_feature` attribute");
344+
err.emit();
345+
return;
346+
}
347+
348+
let mut function_features = function_features
327349
.iter()
328-
.flat_map(|f| {
329-
let feature = f.as_str();
330-
llvm_util::to_llvm_feature(cx.tcx.sess, feature)
350+
.flat_map(|feat| {
351+
llvm_util::to_llvm_feature(cx.tcx.sess, feat)
331352
.into_iter()
332353
.map(|f| format!("+{}", f))
333354
.collect::<Vec<String>>()

compiler/rustc_codegen_llvm/src/llvm_util.rs

+41-8
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@ use crate::back::write::create_informational_target_machine;
22
use crate::{llvm, llvm_util};
33
use libc::c_int;
44
use libloading::Library;
5-
use rustc_codegen_ssa::target_features::supported_target_features;
6-
use rustc_data_structures::fx::FxHashSet;
5+
use rustc_codegen_ssa::target_features::{supported_target_features, tied_target_features};
6+
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
77
use rustc_fs_util::path_to_c_string;
88
use rustc_middle::bug;
99
use rustc_session::config::PrintRequest;
@@ -191,10 +191,30 @@ pub fn to_llvm_feature<'a>(sess: &Session, s: &'a str) -> Vec<&'a str> {
191191
("aarch64", "frintts") => vec!["fptoint"],
192192
("aarch64", "fcma") => vec!["complxnum"],
193193
("aarch64", "pmuv3") => vec!["perfmon"],
194+
("aarch64", "paca") => vec!["pauth"],
195+
("aarch64", "pacg") => vec!["pauth"],
194196
(_, s) => vec![s],
195197
}
196198
}
197199

200+
// Given a map from target_features to whether they are enabled or disabled,
201+
// ensure only valid combinations are allowed.
202+
pub fn check_tied_features(
203+
sess: &Session,
204+
features: &FxHashMap<&str, bool>,
205+
) -> Option<&'static [&'static str]> {
206+
for tied in tied_target_features(sess) {
207+
// Tied features must be set to the same value, or not set at all
208+
let mut tied_iter = tied.iter();
209+
let enabled = features.get(tied_iter.next().unwrap());
210+
211+
if tied_iter.any(|f| enabled != features.get(f)) {
212+
return Some(tied);
213+
}
214+
}
215+
None
216+
}
217+
198218
pub fn target_features(sess: &Session) -> Vec<Symbol> {
199219
let target_machine = create_informational_target_machine(sess);
200220
supported_target_features(sess)
@@ -395,15 +415,19 @@ pub fn llvm_global_features(sess: &Session) -> Vec<String> {
395415
Some(_) | None => {}
396416
};
397417

418+
fn strip(s: &str) -> &str {
419+
s.strip_prefix(&['+', '-']).unwrap_or(s)
420+
}
421+
398422
let filter = |s: &str| {
399423
if s.is_empty() {
400424
return vec![];
401425
}
402-
let feature = if s.starts_with('+') || s.starts_with('-') {
403-
&s[1..]
404-
} else {
426+
let feature = strip(s);
427+
if feature == s {
405428
return vec![s.to_string()];
406-
};
429+
}
430+
407431
// Rustc-specific feature requests like `+crt-static` or `-crt-static`
408432
// are not passed down to LLVM.
409433
if RUSTC_SPECIFIC_FEATURES.contains(&feature) {
@@ -420,8 +444,17 @@ pub fn llvm_global_features(sess: &Session) -> Vec<String> {
420444
features.extend(sess.target.features.split(',').flat_map(&filter));
421445

422446
// -Ctarget-features
423-
features.extend(sess.opts.cg.target_feature.split(',').flat_map(&filter));
424-
447+
let feats: Vec<&str> = sess.opts.cg.target_feature.split(',').collect();
448+
// LLVM enables based on the last occurence of a feature
449+
if let Some(f) =
450+
check_tied_features(sess, &feats.iter().map(|f| (strip(f), !f.starts_with("-"))).collect())
451+
{
452+
sess.err(&format!(
453+
"Target features {} must all be enabled or disabled together",
454+
f.join(", ")
455+
));
456+
}
457+
features.extend(feats.iter().flat_map(|&f| filter(f)));
425458
features
426459
}
427460

compiler/rustc_codegen_ssa/src/target_features.rs

+13-2
Original file line numberDiff line numberDiff line change
@@ -74,8 +74,10 @@ const AARCH64_ALLOWED_FEATURES: &[(&str, Option<Symbol>)] = &[
7474
("ssbs", Some(sym::aarch64_target_feature)),
7575
// FEAT_SB
7676
("sb", Some(sym::aarch64_target_feature)),
77-
// FEAT_PAUTH
78-
("pauth", Some(sym::aarch64_target_feature)),
77+
// FEAT_PAUTH (address authentication)
78+
("paca", Some(sym::aarch64_target_feature)),
79+
// FEAT_PAUTH (generic authentication)
80+
("pacg", Some(sym::aarch64_target_feature)),
7981
// FEAT_DPB
8082
("dpb", Some(sym::aarch64_target_feature)),
8183
// FEAT_DPB2
@@ -137,6 +139,8 @@ const AARCH64_ALLOWED_FEATURES: &[(&str, Option<Symbol>)] = &[
137139
("v8.7a", Some(sym::aarch64_target_feature)),
138140
];
139141

142+
const AARCH64_TIED_FEATURES: &[&[&str]] = &[&["paca", "pacg"]];
143+
140144
const X86_ALLOWED_FEATURES: &[(&str, Option<Symbol>)] = &[
141145
("adx", Some(sym::adx_target_feature)),
142146
("aes", None),
@@ -256,6 +260,13 @@ pub fn supported_target_features(sess: &Session) -> &'static [(&'static str, Opt
256260
}
257261
}
258262

263+
pub fn tied_target_features(sess: &Session) -> &'static [&'static [&'static str]] {
264+
match &*sess.target.arch {
265+
"aarch64" => AARCH64_TIED_FEATURES,
266+
_ => &[],
267+
}
268+
}
269+
259270
pub(crate) fn provide(providers: &mut Providers) {
260271
providers.supported_target_features = |tcx, cnum| {
261272
assert_eq!(cnum, LOCAL_CRATE);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
error: Target features paca, pacg must all be enabled or disabled together
2+
3+
error: aborting due to previous error
4+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// only-aarch64
2+
// revisions: one two three four
3+
//[one] compile-flags: -C target-feature=+paca
4+
//[two] compile-flags: -C target-feature=-pacg,+pacg
5+
//[three] compile-flags: -C target-feature=+paca,+pacg,-paca
6+
//[four] check-pass
7+
//[four] compile-flags: -C target-feature=-paca,+pacg -C target-feature=+paca
8+
9+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
error: Target features paca, pacg must all be enabled or disabled together
2+
3+
error: aborting due to previous error
4+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
error: Target features paca, pacg must all be enabled or disabled together
2+
3+
error: aborting due to previous error
4+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
// only-aarch64
2+
// build-fail
3+
4+
#![feature(aarch64_target_feature, target_feature_11)]
5+
6+
fn main() {
7+
#[target_feature(enable = "pacg")]
8+
//~^ ERROR must all be either enabled or disabled together
9+
unsafe fn inner() {}
10+
11+
unsafe {
12+
foo();
13+
bar();
14+
baz();
15+
inner();
16+
}
17+
}
18+
19+
#[target_feature(enable = "paca")]
20+
//~^ ERROR must all be either enabled or disabled together
21+
unsafe fn foo() {}
22+
23+
24+
#[target_feature(enable = "paca,pacg")]
25+
unsafe fn bar() {}
26+
27+
#[target_feature(enable = "paca")]
28+
#[target_feature(enable = "pacg")]
29+
unsafe fn baz() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
error: the target features paca, pacg must all be either enabled or disabled together
2+
--> $DIR/tied-features.rs:7:5
3+
|
4+
LL | #[target_feature(enable = "pacg")]
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
6+
|
7+
= help: add the missing features in a `target_feature` attribute
8+
9+
error: the target features paca, pacg must all be either enabled or disabled together
10+
--> $DIR/tied-features.rs:19:1
11+
|
12+
LL | #[target_feature(enable = "paca")]
13+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
14+
|
15+
= help: add the missing features in a `target_feature` attribute
16+
17+
error: aborting due to 2 previous errors
18+

0 commit comments

Comments
 (0)