Add -Zindirect-branch-cs-prefix option

This is intended to be used for Linux kernel RETPOLINE builds.

Signed-off-by: Miguel Ojeda <ojeda@kernel.org>
This commit is contained in:
Miguel Ojeda
2025-05-07 15:38:14 +02:00
parent 1cd7080c3a
commit 1a29d9c23f
9 changed files with 88 additions and 5 deletions
+2
View File
@@ -49,6 +49,8 @@ session_hexadecimal_float_literal_not_supported = hexadecimal float literal is n
session_incompatible_linker_flavor = linker flavor `{$flavor}` is incompatible with the current target
.note = compatible flavors are: {$compatible_list}
session_indirect_branch_cs_prefix_requires_x86_or_x86_64 = `-Zindirect-branch-cs-prefix` is only supported on x86 and x86_64
session_instrumentation_not_supported = {$us} instrumentation is not supported for this target
session_int_literal_too_large = integer literal is too large
+4
View File
@@ -471,6 +471,10 @@ pub(crate) struct IncompatibleLinkerFlavor {
#[diag(session_function_return_thunk_extern_requires_non_large_code_model)]
pub(crate) struct FunctionReturnThunkExternRequiresNonLargeCodeModel;
#[derive(Diagnostic)]
#[diag(session_indirect_branch_cs_prefix_requires_x86_or_x86_64)]
pub(crate) struct IndirectBranchCsPrefixRequiresX86OrX8664;
#[derive(Diagnostic)]
#[diag(session_unsupported_regparm)]
pub(crate) struct UnsupportedRegparm {
+1 -1
View File
@@ -2296,7 +2296,7 @@ pub(crate) fn parse_align(slot: &mut Option<Align>, v: Option<&str>) -> bool {
- hash collisions of query keys
- hash collisions when creating dep-nodes"),
indirect_branch_cs_prefix: bool = (false, parse_bool, [TRACKED TARGET_MODIFIER],
"add cs prefix to call and jmp to indirect thunk (default: no)"),
"add `cs` prefix to `call` and `jmp` to indirect thunks (default: no)"),
inline_llvm: bool = (true, parse_bool, [TRACKED],
"enable LLVM inlining (default: yes)"),
inline_mir: Option<bool> = (None, parse_opt_bool, [TRACKED],
+6
View File
@@ -1368,6 +1368,12 @@ fn validate_commandline_args_with_session_available(sess: &Session) {
}
}
if sess.opts.unstable_opts.indirect_branch_cs_prefix {
if sess.target.arch != "x86" && sess.target.arch != "x86_64" {
sess.dcx().emit_err(errors::IndirectBranchCsPrefixRequiresX86OrX8664);
}
}
if let Some(regparm) = sess.opts.unstable_opts.regparm {
if regparm > 3 {
sess.dcx().emit_err(errors::UnsupportedRegparm { regparm });
@@ -0,0 +1,19 @@
# `indirect-branch-cs-prefix`
The tracking issue for this feature is: https://github.com/rust-lang/rust/issues/116852.
------------------------
Option `-Zindirect-branch-cs-prefix` controls whether a `cs` prefix is added to
`call` and `jmp` to indirect thunks.
It is equivalent to [Clang]'s and [GCC]'s `-mindirect-branch-cs-prefix`. The
Linux kernel uses it for RETPOLINE builds. For details, see
[LLVM commit 6f867f910283] ("[X86] Support ``-mindirect-branch-cs-prefix`` for
call and jmp to indirect thunk") which introduces the feature.
Only x86 and x86_64 are supported.
[Clang]: https://clang.llvm.org/docs/ClangCommandLineReference.html#cmdoption-clang-mindirect-branch-cs-prefix
[GCC]: https://gcc.gnu.org/onlinedocs/gcc/x86-Options.html#index-mindirect-branch-cs-prefix
[LLVM commit 6f867f910283]: https://github.com/llvm/llvm-project/commit/6f867f9102838ebe314c1f3661fdf95700386e5a
@@ -0,0 +1,27 @@
// Test that the `cs` prefix is (not) added into a `call` and a `jmp` to the
// indirect thunk when the `-Zindirect-branch-cs-prefix` flag is (not) set.
//@ revisions: unset set
//@ assembly-output: emit-asm
//@ compile-flags: -Copt-level=3 -Cunsafe-allow-abi-mismatch=retpoline,retpoline-external-thunk,indirect-branch-cs-prefix -Zretpoline-external-thunk
//@ [set] compile-flags: -Zindirect-branch-cs-prefix
//@ only-x86_64
//@ ignore-apple Symbol is called `___x86_indirect_thunk` (Darwin's extra underscore)
#![crate_type = "lib"]
// CHECK-LABEL: foo:
#[no_mangle]
pub fn foo(g: fn()) {
// unset-NOT: cs
// unset: callq {{__x86_indirect_thunk.*}}
// set: cs
// set-NEXT: callq {{__x86_indirect_thunk.*}}
g();
// unset-NOT: cs
// unset: jmp {{__x86_indirect_thunk.*}}
// set: cs
// set-NEXT: jmp {{__x86_indirect_thunk.*}}
g();
}
@@ -1,5 +1,5 @@
// Test that the `indirect_branch_cs_prefix` module attribute is (not) emitted when the
// `-Zindirect-branch-cs-prefix` flag is (not) set.
// Test that the `indirect_branch_cs_prefix` module attribute is (not)
// emitted when the `-Zindirect-branch-cs-prefix` flag is (not) set.
//@ add-core-stubs
//@ revisions: unset set
@@ -11,8 +11,8 @@
#![feature(no_core, lang_items)]
#![no_core]
#[lang = "sized"]
trait Sized {}
extern crate minicore;
use minicore::*;
// unset-NOT: !{{[0-9]+}} = !{i32 4, !"indirect_branch_cs_prefix", i32 1}
// set: !{{[0-9]+}} = !{i32 4, !"indirect_branch_cs_prefix", i32 1}
@@ -0,0 +1,4 @@
error: `-Zindirect-branch-cs-prefix` is only supported on x86 and x86_64
error: aborting due to 1 previous error
@@ -0,0 +1,21 @@
//@ revisions: x86 x86_64 aarch64
//@ compile-flags: -Zindirect-branch-cs-prefix
//@[x86] check-pass
//@[x86] needs-llvm-components: x86
//@[x86] compile-flags: --target i686-unknown-linux-gnu
//@[x86_64] check-pass
//@[x86_64] needs-llvm-components: x86
//@[x86_64] compile-flags: --target x86_64-unknown-linux-gnu
//@[aarch64] check-fail
//@[aarch64] needs-llvm-components: aarch64
//@[aarch64] compile-flags: --target aarch64-unknown-linux-gnu
#![feature(no_core)]
#![no_core]
#![no_main]
//[aarch64]~? ERROR `-Zindirect-branch-cs-prefix` is only supported on x86 and x86_64