Skip to content
This repository was archived by the owner on May 28, 2025. It is now read-only.

Commit 72c7b70

Browse files
committed
Auto merge of rust-lang#80838 - nagisa:nagisa/stack-probe-type, r=cuviper
Target stack-probe support configurable finely This adds capability to configure the target's stack probe support in a more precise manner than just on/off. In particular now we allow choosing between always inline-asm, always call or either one of those depending on the LLVM version. Note that this removes the ability to turn off the generation of the stack-probe attribute. This is valid to replace it with inline-asm for all targets because `probe-stack="inline-asm"` will not generate any machine code on targets that do not currently support stack probes. This makes support for stack probes on targets that don't have any right now automatic with LLVM upgrades in the future. (This is valid to do based on the fact that clang unconditionally sets this attribute when `-fstack-clash-protection` is used, AFAICT) cc rust-lang#77885 r? `@cuviper`
2 parents 85e355e + 1b15ec6 commit 72c7b70

35 files changed

+205
-87
lines changed

compiler/rustc_codegen_llvm/src/attributes.rs

Lines changed: 26 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ use rustc_middle::ty::query::Providers;
1313
use rustc_middle::ty::{self, TyCtxt};
1414
use rustc_session::config::{OptLevel, SanitizerSet};
1515
use rustc_session::Session;
16+
use rustc_target::spec::StackProbeType;
1617

1718
use crate::attributes;
1819
use crate::llvm::AttributePlace::Function;
@@ -98,12 +99,6 @@ fn set_instrument_function(cx: &CodegenCx<'ll, '_>, llfn: &'ll Value) {
9899
}
99100

100101
fn set_probestack(cx: &CodegenCx<'ll, '_>, llfn: &'ll Value) {
101-
// Only use stack probes if the target specification indicates that we
102-
// should be using stack probes
103-
if !cx.sess().target.stack_probes {
104-
return;
105-
}
106-
107102
// Currently stack probes seem somewhat incompatible with the address
108103
// sanitizer and thread sanitizer. With asan we're already protected from
109104
// stack overflow anyway so we don't really need stack probes regardless.
@@ -127,19 +122,31 @@ fn set_probestack(cx: &CodegenCx<'ll, '_>, llfn: &'ll Value) {
127122
return;
128123
}
129124

130-
llvm::AddFunctionAttrStringValue(
131-
llfn,
132-
llvm::AttributePlace::Function,
133-
const_cstr!("probe-stack"),
134-
if llvm_util::get_version() < (11, 0, 1) {
135-
// Flag our internal `__rust_probestack` function as the stack probe symbol.
136-
// This is defined in the `compiler-builtins` crate for each architecture.
137-
const_cstr!("__rust_probestack")
138-
} else {
139-
// On LLVM 11+, emit inline asm for stack probes instead of a function call.
140-
const_cstr!("inline-asm")
141-
},
142-
);
125+
let attr_value = match cx.sess().target.stack_probes {
126+
StackProbeType::None => None,
127+
// Request LLVM to generate the probes inline. If the given LLVM version does not support
128+
// this, no probe is generated at all (even if the attribute is specified).
129+
StackProbeType::Inline => Some(const_cstr!("inline-asm")),
130+
// Flag our internal `__rust_probestack` function as the stack probe symbol.
131+
// This is defined in the `compiler-builtins` crate for each architecture.
132+
StackProbeType::Call => Some(const_cstr!("__rust_probestack")),
133+
// Pick from the two above based on the LLVM version.
134+
StackProbeType::InlineOrCall { min_llvm_version_for_inline } => {
135+
if llvm_util::get_version() < min_llvm_version_for_inline {
136+
Some(const_cstr!("__rust_probestack"))
137+
} else {
138+
Some(const_cstr!("inline-asm"))
139+
}
140+
}
141+
};
142+
if let Some(attr_value) = attr_value {
143+
llvm::AddFunctionAttrStringValue(
144+
llfn,
145+
llvm::AttributePlace::Function,
146+
const_cstr!("probe-stack"),
147+
attr_value,
148+
);
149+
}
143150
}
144151

145152
pub fn llvm_target_features(sess: &Session) -> impl Iterator<Item = &str> {

compiler/rustc_target/src/spec/i386_apple_ios.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use super::apple_sdk_base::{opts, Arch};
2-
use crate::spec::{Target, TargetOptions};
2+
use crate::spec::{StackProbeType, Target, TargetOptions};
33

44
pub fn target() -> Target {
55
let base = opts("ios", Arch::I386);
@@ -10,6 +10,10 @@ pub fn target() -> Target {
1010
f64:32:64-f80:128-n8:16:32-S128"
1111
.to_string(),
1212
arch: "x86".to_string(),
13-
options: TargetOptions { max_atomic_width: Some(64), stack_probes: true, ..base },
13+
options: TargetOptions {
14+
max_atomic_width: Some(64),
15+
stack_probes: StackProbeType::InlineOrCall { min_llvm_version_for_inline: (11, 0, 1) },
16+
..base
17+
},
1418
}
1519
}

compiler/rustc_target/src/spec/i686_apple_darwin.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
1-
use crate::spec::{LinkerFlavor, Target, TargetOptions};
1+
use crate::spec::{LinkerFlavor, StackProbeType, Target, TargetOptions};
22

33
pub fn target() -> Target {
44
let mut base = super::apple_base::opts("macos");
55
base.cpu = "yonah".to_string();
66
base.max_atomic_width = Some(64);
77
base.pre_link_args.insert(LinkerFlavor::Gcc, vec!["-m32".to_string()]);
88
base.link_env_remove.extend(super::apple_base::macos_link_env_remove());
9-
base.stack_probes = true;
9+
base.stack_probes = StackProbeType::InlineOrCall { min_llvm_version_for_inline: (11, 0, 1) };
1010
base.eliminate_frame_pointer = false;
1111

1212
// Clang automatically chooses a more specific target based on

compiler/rustc_target/src/spec/i686_linux_android.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use crate::spec::Target;
1+
use crate::spec::{StackProbeType, Target};
22

33
// See https://developer.android.com/ndk/guides/abis.html#x86
44
// for target ABI requirements.
@@ -11,7 +11,7 @@ pub fn target() -> Target {
1111
// http://developer.android.com/ndk/guides/abis.html#x86
1212
base.cpu = "pentiumpro".to_string();
1313
base.features = "+mmx,+sse,+sse2,+sse3,+ssse3".to_string();
14-
base.stack_probes = true;
14+
base.stack_probes = StackProbeType::InlineOrCall { min_llvm_version_for_inline: (11, 0, 1) };
1515

1616
Target {
1717
llvm_target: "i686-linux-android".to_string(),

compiler/rustc_target/src/spec/i686_unknown_freebsd.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use crate::spec::{LinkerFlavor, Target};
1+
use crate::spec::{LinkerFlavor, StackProbeType, Target};
22

33
pub fn target() -> Target {
44
let mut base = super::freebsd_base::opts();
@@ -7,7 +7,7 @@ pub fn target() -> Target {
77
let pre_link_args = base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap();
88
pre_link_args.push("-m32".to_string());
99
pre_link_args.push("-Wl,-znotext".to_string());
10-
base.stack_probes = true;
10+
base.stack_probes = StackProbeType::InlineOrCall { min_llvm_version_for_inline: (11, 0, 1) };
1111

1212
Target {
1313
llvm_target: "i686-unknown-freebsd".to_string(),

compiler/rustc_target/src/spec/i686_unknown_haiku.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
1-
use crate::spec::{LinkerFlavor, Target};
1+
use crate::spec::{LinkerFlavor, StackProbeType, Target};
22

33
pub fn target() -> Target {
44
let mut base = super::haiku_base::opts();
55
base.cpu = "pentium4".to_string();
66
base.max_atomic_width = Some(64);
77
base.pre_link_args.insert(LinkerFlavor::Gcc, vec!["-m32".to_string()]);
8-
base.stack_probes = true;
8+
base.stack_probes = StackProbeType::InlineOrCall { min_llvm_version_for_inline: (11, 0, 1) };
99

1010
Target {
1111
llvm_target: "i686-unknown-haiku".to_string(),

compiler/rustc_target/src/spec/i686_unknown_linux_gnu.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
1-
use crate::spec::{LinkerFlavor, Target};
1+
use crate::spec::{LinkerFlavor, StackProbeType, Target};
22

33
pub fn target() -> Target {
44
let mut base = super::linux_gnu_base::opts();
55
base.cpu = "pentium4".to_string();
66
base.max_atomic_width = Some(64);
77
base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m32".to_string());
8-
base.stack_probes = true;
8+
base.stack_probes = StackProbeType::InlineOrCall { min_llvm_version_for_inline: (11, 0, 1) };
99

1010
Target {
1111
llvm_target: "i686-unknown-linux-gnu".to_string(),

compiler/rustc_target/src/spec/i686_unknown_linux_musl.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
1-
use crate::spec::{LinkerFlavor, Target};
1+
use crate::spec::{LinkerFlavor, StackProbeType, Target};
22

33
pub fn target() -> Target {
44
let mut base = super::linux_musl_base::opts();
55
base.cpu = "pentium4".to_string();
66
base.max_atomic_width = Some(64);
77
base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m32".to_string());
88
base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-Wl,-melf_i386".to_string());
9-
base.stack_probes = true;
9+
base.stack_probes = StackProbeType::InlineOrCall { min_llvm_version_for_inline: (11, 0, 1) };
1010

1111
// The unwinder used by i686-unknown-linux-musl, the LLVM libunwind
1212
// implementation, apparently relies on frame pointers existing... somehow.

compiler/rustc_target/src/spec/i686_unknown_netbsd.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
1-
use crate::spec::{LinkerFlavor, Target, TargetOptions};
1+
use crate::spec::{LinkerFlavor, StackProbeType, Target, TargetOptions};
22

33
pub fn target() -> Target {
44
let mut base = super::netbsd_base::opts();
55
base.cpu = "pentium4".to_string();
66
base.max_atomic_width = Some(64);
77
base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m32".to_string());
8-
base.stack_probes = true;
8+
base.stack_probes = StackProbeType::InlineOrCall { min_llvm_version_for_inline: (11, 0, 1) };
99

1010
Target {
1111
llvm_target: "i686-unknown-netbsdelf".to_string(),

compiler/rustc_target/src/spec/i686_unknown_openbsd.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
1-
use crate::spec::{LinkerFlavor, Target};
1+
use crate::spec::{LinkerFlavor, StackProbeType, Target};
22

33
pub fn target() -> Target {
44
let mut base = super::openbsd_base::opts();
55
base.cpu = "pentium4".to_string();
66
base.max_atomic_width = Some(64);
77
base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m32".to_string());
88
base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-fuse-ld=lld".to_string());
9-
base.stack_probes = true;
9+
base.stack_probes = StackProbeType::InlineOrCall { min_llvm_version_for_inline: (11, 0, 1) };
1010

1111
Target {
1212
llvm_target: "i686-unknown-openbsd".to_string(),

0 commit comments

Comments
 (0)