about summary refs log tree commit diff
diff options
context:
space:
mode:
authorGuillaume Gomez <guillaume1.gomez@gmail.com>2025-05-05 21:32:34 +0200
committerGitHub <noreply@github.com>2025-05-05 21:32:34 +0200
commit0d7067d7b2ff319bd11e503a4afd8718f1d77ead (patch)
tree602d6acd187bb1a04eae1e7246382805ee4fdf21
parent6cee5bf5566d626741c6fd08a2217878faa77aac (diff)
parent4b58c5034a59f58b9ba1a713a667b4d9ffc1df34 (diff)
downloadrust-0d7067d7b2ff319bd11e503a4afd8718f1d77ead.tar.gz
rust-0d7067d7b2ff319bd11e503a4afd8718f1d77ead.zip
Rollup merge of #140661 - Darksonn:fixedx18-tm, r=wesleywiser
Make `-Zfixed-x18` into a target modifier

As part of #136966, the `-Zfixed-x18` flag should be turned into a target modifier. This is a blocker to stabilization of the flag. The flag was originally added in #124655 and the MCP for its addition is [MCP#748](https://github.com/rust-lang/compiler-team/issues/748).

On some aarch64 targets, the x18 register is used as a temporary caller-saved register by default. When the `-Zfixed-x18` flag is passed, this is turned off so that the compiler doesn't use the x18 register. This allows end-users to use the x18 register for other purposes. For example, by accessing it with inline asm you can use the register as a very efficient thread-local variable. Another common use-case is to store the stack pointer needed by the shadow-call-stack sanitizer. There are also some aarch64 targets where not using x18 is the default – in those cases the flag is a no-op.

Note that this flag does not *on its own* cause an ABI mismatch. What actually causes an ABI mismatch is when you have different compilation units that *disagree* on what it should be used for. But having a CU that uses it and another CU that doesn't normally isn't enough to trigger an ABI problem. However, we still consider the flag to be a target modifier in all cases, since it is assumed that you are passing the flag because you intend to assign some other meaning to the register. Rejecting all flag mismatches even if not all are unsound is consistent with [RFC#3716](https://rust-lang.github.io/rfcs/3716-target-modifiers.html). See the headings "not all mismatches are unsound" and "cases that are not caught" for additional discussion of this.

On aarch64 targets where `-Zfixed-x18` is not a no-op, it is an error to pass `-Zsanitizer=shadow-call-stack` without also passing `-Zfixed-x18`.
-rw-r--r--compiler/rustc_session/src/options.rs2
-rw-r--r--tests/ui/target_modifiers/auxiliary/fixed_x18.rs7
-rw-r--r--tests/ui/target_modifiers/incompatible_fixedx18.error_generated.stderr13
-rw-r--r--tests/ui/target_modifiers/incompatible_fixedx18.rs17
4 files changed, 38 insertions, 1 deletions
diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs
index 440e8f808c7..b95ebfbe89f 100644
--- a/compiler/rustc_session/src/options.rs
+++ b/compiler/rustc_session/src/options.rs
@@ -2210,7 +2210,7 @@ options! {
     fewer_names: Option<bool> = (None, parse_opt_bool, [TRACKED],
         "reduce memory use by retaining fewer names within compilation artifacts (LLVM-IR) \
         (default: no)"),
-    fixed_x18: bool = (false, parse_bool, [TRACKED],
+    fixed_x18: bool = (false, parse_bool, [TRACKED TARGET_MODIFIER],
         "make the x18 register reserved on AArch64 (default: no)"),
     flatten_format_args: bool = (true, parse_bool, [TRACKED],
         "flatten nested format_args!() and literals into a simplified format_args!() call \
diff --git a/tests/ui/target_modifiers/auxiliary/fixed_x18.rs b/tests/ui/target_modifiers/auxiliary/fixed_x18.rs
new file mode 100644
index 00000000000..32eff76ec54
--- /dev/null
+++ b/tests/ui/target_modifiers/auxiliary/fixed_x18.rs
@@ -0,0 +1,7 @@
+//@ no-prefer-dynamic
+//@ compile-flags: --target aarch64-unknown-none -Zfixed-x18
+//@ needs-llvm-components: aarch64
+
+#![feature(no_core)]
+#![crate_type = "rlib"]
+#![no_core]
diff --git a/tests/ui/target_modifiers/incompatible_fixedx18.error_generated.stderr b/tests/ui/target_modifiers/incompatible_fixedx18.error_generated.stderr
new file mode 100644
index 00000000000..096d7cb5f25
--- /dev/null
+++ b/tests/ui/target_modifiers/incompatible_fixedx18.error_generated.stderr
@@ -0,0 +1,13 @@
+error: mixing `-Zfixed-x18` will cause an ABI mismatch in crate `incompatible_fixedx18`
+  --> $DIR/incompatible_fixedx18.rs:12:1
+   |
+LL | #![feature(no_core)]
+   | ^
+   |
+   = help: the `-Zfixed-x18` flag modifies the ABI so Rust crates compiled with different values of this flag cannot be used together safely
+   = note: unset `-Zfixed-x18` in this crate is incompatible with `-Zfixed-x18=` in dependency `fixed_x18`
+   = help: set `-Zfixed-x18=` in this crate or unset `-Zfixed-x18` in `fixed_x18`
+   = help: if you are sure this will not cause problems, you may use `-Cunsafe-allow-abi-mismatch=fixed-x18` to silence this error
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/target_modifiers/incompatible_fixedx18.rs b/tests/ui/target_modifiers/incompatible_fixedx18.rs
new file mode 100644
index 00000000000..6c13984f608
--- /dev/null
+++ b/tests/ui/target_modifiers/incompatible_fixedx18.rs
@@ -0,0 +1,17 @@
+//@ aux-build:fixed_x18.rs
+//@ compile-flags: --target aarch64-unknown-none
+//@ needs-llvm-components: aarch64
+
+//@ revisions:allow_match allow_mismatch error_generated
+//@[allow_match] compile-flags: -Zfixed-x18
+//@[allow_mismatch] compile-flags: -Cunsafe-allow-abi-mismatch=fixed-x18
+//@[error_generated] compile-flags:
+//@[allow_mismatch] check-pass
+//@[allow_match] check-pass
+
+#![feature(no_core)]
+//[error_generated]~^ ERROR mixing `-Zfixed-x18` will cause an ABI mismatch in crate `incompatible_fixedx18`
+#![crate_type = "rlib"]
+#![no_core]
+
+extern crate fixed_x18;