-
Notifications
You must be signed in to change notification settings - Fork 13.4k
Add -Zfunction-return={keep,thunk-extern}
option
#116892
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,7 @@ | ||
use crate::code_stats::CodeStats; | ||
pub use crate::code_stats::{DataTypeKind, FieldInfo, FieldKind, SizeKind, VariantInfo}; | ||
use crate::config::{ | ||
self, CrateType, InstrumentCoverage, OptLevel, OutFileName, OutputType, | ||
self, CrateType, FunctionReturn, InstrumentCoverage, OptLevel, OutFileName, OutputType, | ||
RemapPathScopeComponents, SwitchWithOptPath, | ||
}; | ||
use crate::config::{ErrorOutputType, Input}; | ||
|
@@ -1678,6 +1678,28 @@ fn validate_commandline_args_with_session_available(sess: &Session) { | |
sess.emit_err(errors::IncompatibleLinkerFlavor { flavor, compatible_list }); | ||
} | ||
} | ||
|
||
if sess.opts.unstable_opts.function_return != FunctionReturn::default() { | ||
if sess.target.arch != "x86" && sess.target.arch != "x86_64" { | ||
sess.emit_err(errors::FunctionReturnRequiresX86OrX8664); | ||
} | ||
} | ||
|
||
// The code model check applies to `thunk` and `thunk-extern`, but not `thunk-inline`, so it is | ||
// kept as a `match` to force a change if new ones are added, even if we currently only support | ||
// `thunk-extern` like Clang. | ||
match sess.opts.unstable_opts.function_return { | ||
FunctionReturn::Keep => (), | ||
FunctionReturn::ThunkExtern => { | ||
// FIXME: In principle, the inherited base LLVM target code model could be large, | ||
// but this only checks whether we were passed one explicitly (like Clang does). | ||
Comment on lines
+1694
to
+1695
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If there is a way to get the effective code model, it would be nice to use it. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe check There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That covers even less, no? i.e. |
||
if let Some(code_model) = sess.code_model() | ||
&& code_model == CodeModel::Large | ||
{ | ||
sess.emit_err(errors::FunctionReturnThunkExternRequiresNonLargeCodeModel); | ||
} | ||
} | ||
} | ||
} | ||
|
||
/// Holds data on the current incremental compilation session, if there is one. | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
# `function-return` | ||
|
||
The tracking issue for this feature is: https://github.com/rust-lang/rust/issues/116853. | ||
|
||
------------------------ | ||
|
||
Option `-Zfunction-return` controls how function returns are converted. | ||
|
||
It is equivalent to [Clang]'s and [GCC]'s `-mfunction-return`. The Linux kernel | ||
uses it for RETHUNK builds. For details, see [LLVM commit 2240d72f15f3] ("[X86] | ||
initial -mfunction-return=thunk-extern support") which introduces the feature. | ||
|
||
Supported values for this option are: | ||
|
||
- `keep`: do not convert function returns. | ||
- `thunk-extern`: convert function returns (`ret`) to jumps (`jmp`) | ||
to an external symbol called `__x86_return_thunk`. | ||
|
||
Like in Clang, GCC's values `thunk` and `thunk-inline` are not supported. | ||
|
||
Only x86 and non-large code models are supported. | ||
|
||
[Clang]: https://clang.llvm.org/docs/ClangCommandLineReference.html#cmdoption-clang-mfunction-return | ||
[GCC]: https://gcc.gnu.org/onlinedocs/gcc/x86-Options.html#index-mfunction-return | ||
[LLVM commit 2240d72f15f3]: https://github.com/llvm/llvm-project/commit/2240d72f15f3b7b9d9fb65450f9bf635fd310f6f |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
// Test that the function return is (not) converted into a jump to the thunk | ||
// when the `-Zfunction-return={keep,thunk-extern}` flag is (not) set. | ||
|
||
// revisions: unset keep thunk-extern keep-thunk-extern thunk-extern-keep | ||
// assembly-output: emit-asm | ||
// compile-flags: -O | ||
// [keep] compile-flags: -Zfunction-return=keep | ||
// [thunk-extern] compile-flags: -Zfunction-return=thunk-extern | ||
// [keep-thunk-extern] compile-flags: -Zfunction-return=keep -Zfunction-return=thunk-extern | ||
// [thunk-extern-keep] compile-flags: -Zfunction-return=thunk-extern -Zfunction-return=keep | ||
// only-x86_64 | ||
// ignore-x86_64-apple-darwin Symbol is called `___x86_return_thunk` (Darwin's extra underscore) | ||
// ignore-sgx Tests incompatible with LVI mitigations | ||
|
||
#![crate_type = "lib"] | ||
|
||
// CHECK-LABEL: foo: | ||
#[no_mangle] | ||
pub unsafe fn foo() { | ||
// unset: ret | ||
ojeda marked this conversation as resolved.
Show resolved
Hide resolved
|
||
// unset-NOT: jmp __x86_return_thunk | ||
// keep: ret | ||
ojeda marked this conversation as resolved.
Show resolved
Hide resolved
|
||
// keep-NOT: jmp __x86_return_thunk | ||
// thunk-extern: jmp __x86_return_thunk | ||
// thunk-extern-NOT: ret | ||
// keep-thunk-extern: jmp __x86_return_thunk | ||
// keep-thunk-extern-NOT: ret | ||
// thunk-extern-keep: ret | ||
ojeda marked this conversation as resolved.
Show resolved
Hide resolved
|
||
// thunk-extern-keep-NOT: jmp __x86_return_thunk | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
// Test that the `fn_ret_thunk_extern` function attribute is (not) emitted when | ||
// the `-Zfunction-return={keep,thunk-extern}` flag is (not) set. | ||
|
||
// revisions: unset keep thunk-extern keep-thunk-extern thunk-extern-keep | ||
// needs-llvm-components: x86 | ||
// compile-flags: --target x86_64-unknown-linux-gnu | ||
// [keep] compile-flags: -Zfunction-return=keep | ||
// [thunk-extern] compile-flags: -Zfunction-return=thunk-extern | ||
// [keep-thunk-extern] compile-flags: -Zfunction-return=keep -Zfunction-return=thunk-extern | ||
// [thunk-extern-keep] compile-flags: -Zfunction-return=thunk-extern -Zfunction-return=keep | ||
|
||
#![crate_type = "lib"] | ||
#![feature(no_core, lang_items)] | ||
#![no_core] | ||
|
||
#[lang = "sized"] | ||
trait Sized {} | ||
|
||
#[no_mangle] | ||
pub fn foo() { | ||
// CHECK: @foo() unnamed_addr #0 | ||
|
||
// unset-NOT: fn_ret_thunk_extern | ||
// keep-NOT: fn_ret_thunk_extern | ||
// thunk-extern: attributes #0 = { {{.*}}fn_ret_thunk_extern{{.*}} } | ||
// keep-thunk-extern: attributes #0 = { {{.*}}fn_ret_thunk_extern{{.*}} } | ||
// thunk-extern-keep-NOT: fn_ret_thunk_extern | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
error: `-Zfunction-return` (except `keep`) is only supported on x86 and x86_64 | ||
|
||
error: aborting due to 1 previous error | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
// revisions: x86 x86_64 aarch64 | ||
|
||
// compile-flags: -Zfunction-return=thunk-extern | ||
|
||
//[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 | ||
//[aarch64] error-pattern: `-Zfunction-return` (except `keep`) is only supported on x86 and x86_64 | ||
|
||
#![feature(no_core)] | ||
#![no_core] | ||
#![no_main] |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
error: `-Zfunction-return=thunk-extern` is only supported on non-large code models | ||
|
||
error: aborting due to 1 previous error | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
// revisions: small kernel medium large | ||
|
||
// needs-llvm-components: x86 | ||
// compile-flags: --target x86_64-unknown-linux-gnu -Zfunction-return=thunk-extern | ||
|
||
//[small] check-pass | ||
//[small] compile-flags: -Ccode-model=small | ||
|
||
//[kernel] check-pass | ||
//[kernel] compile-flags: -Ccode-model=kernel | ||
|
||
//[medium] check-pass | ||
//[medium] compile-flags: -Ccode-model=medium | ||
|
||
//[large] check-fail | ||
//[large] compile-flags: -Ccode-model=large | ||
//[large] error-pattern: `-Zfunction-return=thunk-extern` is only supported on non-large code models | ||
|
||
#![feature(no_core)] | ||
#![no_core] | ||
#![no_main] |
Uh oh!
There was an error while loading. Please reload this page.