Skip to content

Commit 635ccfe

Browse files
committed
Auto merge of rust-lang#77885 - erikdesjardins:probeasm, r=cuviper
Use probe-stack=inline-asm in LLVM 11+ Fixes (?) rust-lang#74405, related to rust-lang#43241 r? `@cuviper`
2 parents 6c869d3 + cd25807 commit 635ccfe

File tree

7 files changed

+62
-10
lines changed

7 files changed

+62
-10
lines changed

compiler/rustc_codegen_llvm/src/attributes.rs

+8-3
Original file line numberDiff line numberDiff line change
@@ -127,13 +127,18 @@ fn set_probestack(cx: &CodegenCx<'ll, '_>, llfn: &'ll Value) {
127127
return;
128128
}
129129

130-
// Flag our internal `__rust_probestack` function as the stack probe symbol.
131-
// This is defined in the `compiler-builtins` crate for each architecture.
132130
llvm::AddFunctionAttrStringValue(
133131
llfn,
134132
llvm::AttributePlace::Function,
135133
const_cstr!("probe-stack"),
136-
const_cstr!("__rust_probestack"),
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+
},
137142
);
138143
}
139144

compiler/rustc_codegen_llvm/src/context.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ pub unsafe fn create_module(
114114
let llmod = llvm::LLVMModuleCreateWithNameInContext(mod_name.as_ptr(), llcx);
115115

116116
let mut target_data_layout = sess.target.data_layout.clone();
117-
if llvm_util::get_major_version() < 10
117+
if llvm_util::get_version() < (10, 0, 0)
118118
&& (sess.target.arch == "x86" || sess.target.arch == "x86_64")
119119
{
120120
target_data_layout = strip_x86_address_spaces(target_data_layout);

compiler/rustc_codegen_llvm/src/llvm/ffi.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1811,6 +1811,7 @@ extern "C" {
18111811
pub fn LLVMRustDebugMetadataVersion() -> u32;
18121812
pub fn LLVMRustVersionMajor() -> u32;
18131813
pub fn LLVMRustVersionMinor() -> u32;
1814+
pub fn LLVMRustVersionPatch() -> u32;
18141815

18151816
pub fn LLVMRustAddModuleFlag(M: &Module, name: *const c_char, value: u32);
18161817

compiler/rustc_codegen_llvm/src/llvm_util.rs

+6-5
Original file line numberDiff line numberDiff line change
@@ -171,16 +171,17 @@ pub fn target_features(sess: &Session) -> Vec<Symbol> {
171171
}
172172

173173
pub fn print_version() {
174+
let (major, minor, patch) = get_version();
175+
println!("LLVM version: {}.{}.{}", major, minor, patch);
176+
}
177+
178+
pub fn get_version() -> (u32, u32, u32) {
174179
// Can be called without initializing LLVM
175180
unsafe {
176-
println!("LLVM version: {}.{}", llvm::LLVMRustVersionMajor(), llvm::LLVMRustVersionMinor());
181+
(llvm::LLVMRustVersionMajor(), llvm::LLVMRustVersionMinor(), llvm::LLVMRustVersionPatch())
177182
}
178183
}
179184

180-
pub fn get_major_version() -> u32 {
181-
unsafe { llvm::LLVMRustVersionMajor() }
182-
}
183-
184185
pub fn print_passes() {
185186
// Can be called without initializing LLVM
186187
unsafe {

compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp

+2
Original file line numberDiff line numberDiff line change
@@ -660,6 +660,8 @@ extern "C" uint32_t LLVMRustDebugMetadataVersion() {
660660
return DEBUG_METADATA_VERSION;
661661
}
662662

663+
extern "C" uint32_t LLVMRustVersionPatch() { return LLVM_VERSION_PATCH; }
664+
663665
extern "C" uint32_t LLVMRustVersionMinor() { return LLVM_VERSION_MINOR; }
664666

665667
extern "C" uint32_t LLVMRustVersionMajor() { return LLVM_VERSION_MAJOR; }

src/test/assembly/stack-probes.rs

+42
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
// min-llvm-version: 11.0.1
2+
// revisions: x86_64 i686
3+
// assembly-output: emit-asm
4+
//[x86_64] compile-flags: --target x86_64-unknown-linux-gnu
5+
//[i686] compile-flags: --target i686-unknown-linux-gnu
6+
// compile-flags: -C llvm-args=--x86-asm-syntax=intel
7+
8+
#![feature(no_core, lang_items)]
9+
#![crate_type = "lib"]
10+
#![no_core]
11+
12+
#[lang = "sized"]
13+
trait Sized {}
14+
#[lang = "copy"]
15+
trait Copy {}
16+
17+
impl Copy for u8 {}
18+
19+
// Check that inline-asm stack probes are generated correctly.
20+
// To avoid making this test fragile to slight asm changes,
21+
// we only check that the stack pointer is decremented by a page at a time,
22+
// instead of matching the whole probe sequence.
23+
24+
// CHECK-LABEL: small_stack_probe:
25+
#[no_mangle]
26+
pub fn small_stack_probe(x: u8, f: fn([u8; 8192])) {
27+
// CHECK-NOT: __rust_probestack
28+
// x86_64: sub rsp, 4096
29+
// i686: sub esp, 4096
30+
let a = [x; 8192];
31+
f(a);
32+
}
33+
34+
// CHECK-LABEL: big_stack_probe:
35+
#[no_mangle]
36+
pub fn big_stack_probe(x: u8, f: fn([u8; 65536])) {
37+
// CHECK-NOT: __rust_probestack
38+
// x86_64: sub rsp, 4096
39+
// i686: sub esp, 4096
40+
let a = [x; 65536];
41+
f(a);
42+
}

src/test/codegen/stack-probes.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,12 @@
1313
// ignore-emscripten
1414
// ignore-windows
1515
// compile-flags: -C no-prepopulate-passes
16+
// min-llvm-version: 11.0.1
1617

1718
#![crate_type = "lib"]
1819

1920
#[no_mangle]
2021
pub fn foo() {
2122
// CHECK: @foo() unnamed_addr #0
22-
// CHECK: attributes #0 = { {{.*}}"probe-stack"="__rust_probestack"{{.*}} }
23+
// CHECK: attributes #0 = { {{.*}}"probe-stack"="inline-asm"{{.*}} }
2324
}

0 commit comments

Comments
 (0)