Skip to content

Commit 85a464c

Browse files
Rollup merge of rust-lang#140740 - ojeda:indirect-branch-cs-prefix, r=davidtwco
Add `-Zindirect-branch-cs-prefix` Cc: ``@azhogin`` ``@Darksonn`` This goes on top of rust-lang#135927, i.e. please skip the first commit here. Please feel free to inherit it there. In fact, I am not sure if there is any use case for the flag without `-Zretpoline*`. GCC and Clang allow it, though. There is a `FIXME` for two `ignore`s in the test that I took from another test I did in the past -- they may be needed or not here since I didn't run the full CI. Either way, it is not critical. Tracking issue: rust-lang#116852. MCP: rust-lang/compiler-team#868.
2 parents 350d0ef + 5d6ec1e commit 85a464c

File tree

11 files changed

+112
-0
lines changed

11 files changed

+112
-0
lines changed

compiler/rustc_codegen_llvm/src/context.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -457,6 +457,15 @@ pub(crate) unsafe fn create_module<'ll>(
457457
}
458458
}
459459

460+
if sess.opts.unstable_opts.indirect_branch_cs_prefix {
461+
llvm::add_module_flag_u32(
462+
llmod,
463+
llvm::ModuleFlagMergeBehavior::Override,
464+
"indirect_branch_cs_prefix",
465+
1,
466+
);
467+
}
468+
460469
match (sess.opts.unstable_opts.small_data_threshold, sess.target.small_data_threshold_support())
461470
{
462471
// Set up the small-data optimization limit for architectures that use

compiler/rustc_interface/src/tests.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -807,6 +807,7 @@ fn test_unstable_options_tracking_hash() {
807807
tracked!(hint_mostly_unused, true);
808808
tracked!(human_readable_cgu_names, true);
809809
tracked!(incremental_ignore_spans, true);
810+
tracked!(indirect_branch_cs_prefix, true);
810811
tracked!(inline_mir, Some(true));
811812
tracked!(inline_mir_hint_threshold, Some(123));
812813
tracked!(inline_mir_threshold, Some(123));

compiler/rustc_session/messages.ftl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,8 @@ session_hexadecimal_float_literal_not_supported = hexadecimal float literal is n
4949
session_incompatible_linker_flavor = linker flavor `{$flavor}` is incompatible with the current target
5050
.note = compatible flavors are: {$compatible_list}
5151
52+
session_indirect_branch_cs_prefix_requires_x86_or_x86_64 = `-Zindirect-branch-cs-prefix` is only supported on x86 and x86_64
53+
5254
session_instrumentation_not_supported = {$us} instrumentation is not supported for this target
5355
5456
session_int_literal_too_large = integer literal is too large

compiler/rustc_session/src/errors.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -471,6 +471,10 @@ pub(crate) struct FunctionReturnRequiresX86OrX8664;
471471
#[diag(session_function_return_thunk_extern_requires_non_large_code_model)]
472472
pub(crate) struct FunctionReturnThunkExternRequiresNonLargeCodeModel;
473473

474+
#[derive(Diagnostic)]
475+
#[diag(session_indirect_branch_cs_prefix_requires_x86_or_x86_64)]
476+
pub(crate) struct IndirectBranchCsPrefixRequiresX86OrX8664;
477+
474478
#[derive(Diagnostic)]
475479
#[diag(session_unsupported_regparm)]
476480
pub(crate) struct UnsupportedRegparm {

compiler/rustc_session/src/options.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2295,6 +2295,8 @@ options! {
22952295
- hashes of green query instances
22962296
- hash collisions of query keys
22972297
- hash collisions when creating dep-nodes"),
2298+
indirect_branch_cs_prefix: bool = (false, parse_bool, [TRACKED TARGET_MODIFIER],
2299+
"add `cs` prefix to `call` and `jmp` to indirect thunks (default: no)"),
22982300
inline_llvm: bool = (true, parse_bool, [TRACKED],
22992301
"enable LLVM inlining (default: yes)"),
23002302
inline_mir: Option<bool> = (None, parse_opt_bool, [TRACKED],

compiler/rustc_session/src/session.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1368,6 +1368,12 @@ fn validate_commandline_args_with_session_available(sess: &Session) {
13681368
}
13691369
}
13701370

1371+
if sess.opts.unstable_opts.indirect_branch_cs_prefix {
1372+
if sess.target.arch != "x86" && sess.target.arch != "x86_64" {
1373+
sess.dcx().emit_err(errors::IndirectBranchCsPrefixRequiresX86OrX8664);
1374+
}
1375+
}
1376+
13711377
if let Some(regparm) = sess.opts.unstable_opts.regparm {
13721378
if regparm > 3 {
13731379
sess.dcx().emit_err(errors::UnsupportedRegparm { regparm });
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# `indirect-branch-cs-prefix`
2+
3+
The tracking issue for this feature is: https://github.com/rust-lang/rust/issues/116852.
4+
5+
------------------------
6+
7+
Option `-Zindirect-branch-cs-prefix` controls whether a `cs` prefix is added to
8+
`call` and `jmp` to indirect thunks.
9+
10+
It is equivalent to [Clang]'s and [GCC]'s `-mindirect-branch-cs-prefix`. The
11+
Linux kernel uses it for RETPOLINE builds. For details, see
12+
[LLVM commit 6f867f910283] ("[X86] Support ``-mindirect-branch-cs-prefix`` for
13+
call and jmp to indirect thunk") which introduces the feature.
14+
15+
Only x86 and x86_64 are supported.
16+
17+
[Clang]: https://clang.llvm.org/docs/ClangCommandLineReference.html#cmdoption-clang-mindirect-branch-cs-prefix
18+
[GCC]: https://gcc.gnu.org/onlinedocs/gcc/x86-Options.html#index-mindirect-branch-cs-prefix
19+
[LLVM commit 6f867f910283]: https://github.com/llvm/llvm-project/commit/6f867f9102838ebe314c1f3661fdf95700386e5a
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// Test that the `cs` prefix is (not) added into a `call` and a `jmp` to the
2+
// indirect thunk when the `-Zindirect-branch-cs-prefix` flag is (not) set.
3+
4+
//@ revisions: unset set
5+
//@ assembly-output: emit-asm
6+
//@ compile-flags: -Copt-level=3 -Cunsafe-allow-abi-mismatch=retpoline,retpoline-external-thunk,indirect-branch-cs-prefix -Zretpoline-external-thunk
7+
//@ [set] compile-flags: -Zindirect-branch-cs-prefix
8+
//@ only-x86_64
9+
10+
#![crate_type = "lib"]
11+
12+
// CHECK-LABEL: foo:
13+
#[no_mangle]
14+
pub fn foo(g: fn()) {
15+
// unset-NOT: cs
16+
// unset: callq {{__x86_indirect_thunk.*}}
17+
// set: cs
18+
// set-NEXT: callq {{__x86_indirect_thunk.*}}
19+
g();
20+
21+
// unset-NOT: cs
22+
// unset: jmp {{__x86_indirect_thunk.*}}
23+
// set: cs
24+
// set-NEXT: jmp {{__x86_indirect_thunk.*}}
25+
g();
26+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// Test that the `indirect_branch_cs_prefix` module attribute is (not)
2+
// emitted when the `-Zindirect-branch-cs-prefix` flag is (not) set.
3+
4+
//@ add-core-stubs
5+
//@ revisions: unset set
6+
//@ needs-llvm-components: x86
7+
//@ compile-flags: --target x86_64-unknown-linux-gnu
8+
//@ [set] compile-flags: -Zindirect-branch-cs-prefix
9+
10+
#![crate_type = "lib"]
11+
#![feature(no_core, lang_items)]
12+
#![no_core]
13+
14+
extern crate minicore;
15+
use minicore::*;
16+
17+
// unset-NOT: !{{[0-9]+}} = !{i32 4, !"indirect_branch_cs_prefix", i32 1}
18+
// set: !{{[0-9]+}} = !{i32 4, !"indirect_branch_cs_prefix", i32 1}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
error: `-Zindirect-branch-cs-prefix` is only supported on x86 and x86_64
2+
3+
error: aborting due to 1 previous error
4+

0 commit comments

Comments
 (0)