about summary refs log tree commit diff
diff options
context:
space:
mode:
authorErik Desjardins <erikdesjardins@users.noreply.github.com>2020-10-12 22:33:27 -0400
committerErik Desjardins <erikdesjardins@users.noreply.github.com>2021-01-14 22:49:16 -0500
commitcd2580722375671fa2967661f65b7b33570547ec (patch)
tree2a7c80c04b77f40691edd1da05e0d54e0930873f
parente38fb306b7f5e65cca34df2dab1f0db15e1defb4 (diff)
downloadrust-cd2580722375671fa2967661f65b7b33570547ec.tar.gz
rust-cd2580722375671fa2967661f65b7b33570547ec.zip
Use probe-stack=inline-asm in LLVM 11+
-rw-r--r--compiler/rustc_codegen_llvm/src/attributes.rs11
-rw-r--r--compiler/rustc_codegen_llvm/src/context.rs2
-rw-r--r--compiler/rustc_codegen_llvm/src/llvm/ffi.rs1
-rw-r--r--compiler/rustc_codegen_llvm/src/llvm_util.rs11
-rw-r--r--compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp2
-rw-r--r--src/test/assembly/stack-probes.rs42
-rw-r--r--src/test/codegen/stack-probes.rs3
7 files changed, 62 insertions, 10 deletions
diff --git a/compiler/rustc_codegen_llvm/src/attributes.rs b/compiler/rustc_codegen_llvm/src/attributes.rs
index 97c38e04bc1..700f32e15b9 100644
--- a/compiler/rustc_codegen_llvm/src/attributes.rs
+++ b/compiler/rustc_codegen_llvm/src/attributes.rs
@@ -127,13 +127,18 @@ fn set_probestack(cx: &CodegenCx<'ll, '_>, llfn: &'ll Value) {
         return;
     }
 
-    // Flag our internal `__rust_probestack` function as the stack probe symbol.
-    // This is defined in the `compiler-builtins` crate for each architecture.
     llvm::AddFunctionAttrStringValue(
         llfn,
         llvm::AttributePlace::Function,
         const_cstr!("probe-stack"),
-        const_cstr!("__rust_probestack"),
+        if llvm_util::get_version() < (11, 0, 1) {
+            // Flag our internal `__rust_probestack` function as the stack probe symbol.
+            // This is defined in the `compiler-builtins` crate for each architecture.
+            const_cstr!("__rust_probestack")
+        } else {
+            // On LLVM 11+, emit inline asm for stack probes instead of a function call.
+            const_cstr!("inline-asm")
+        },
     );
 }
 
diff --git a/compiler/rustc_codegen_llvm/src/context.rs b/compiler/rustc_codegen_llvm/src/context.rs
index 8dd40308075..6acd26bd415 100644
--- a/compiler/rustc_codegen_llvm/src/context.rs
+++ b/compiler/rustc_codegen_llvm/src/context.rs
@@ -114,7 +114,7 @@ pub unsafe fn create_module(
     let llmod = llvm::LLVMModuleCreateWithNameInContext(mod_name.as_ptr(), llcx);
 
     let mut target_data_layout = sess.target.data_layout.clone();
-    if llvm_util::get_major_version() < 10
+    if llvm_util::get_version() < (10, 0, 0)
         && (sess.target.arch == "x86" || sess.target.arch == "x86_64")
     {
         target_data_layout = strip_x86_address_spaces(target_data_layout);
diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
index eb4f36266db..d9f42efebab 100644
--- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
+++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
@@ -1811,6 +1811,7 @@ extern "C" {
     pub fn LLVMRustDebugMetadataVersion() -> u32;
     pub fn LLVMRustVersionMajor() -> u32;
     pub fn LLVMRustVersionMinor() -> u32;
+    pub fn LLVMRustVersionPatch() -> u32;
 
     pub fn LLVMRustAddModuleFlag(M: &Module, name: *const c_char, value: u32);
 
diff --git a/compiler/rustc_codegen_llvm/src/llvm_util.rs b/compiler/rustc_codegen_llvm/src/llvm_util.rs
index a9d57ea8b8a..6c2a871e520 100644
--- a/compiler/rustc_codegen_llvm/src/llvm_util.rs
+++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs
@@ -171,16 +171,17 @@ pub fn target_features(sess: &Session) -> Vec<Symbol> {
 }
 
 pub fn print_version() {
+    let (major, minor, patch) = get_version();
+    println!("LLVM version: {}.{}.{}", major, minor, patch);
+}
+
+pub fn get_version() -> (u32, u32, u32) {
     // Can be called without initializing LLVM
     unsafe {
-        println!("LLVM version: {}.{}", llvm::LLVMRustVersionMajor(), llvm::LLVMRustVersionMinor());
+        (llvm::LLVMRustVersionMajor(), llvm::LLVMRustVersionMinor(), llvm::LLVMRustVersionPatch())
     }
 }
 
-pub fn get_major_version() -> u32 {
-    unsafe { llvm::LLVMRustVersionMajor() }
-}
-
 pub fn print_passes() {
     // Can be called without initializing LLVM
     unsafe {
diff --git a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
index 1d6f00562f1..1d89fc80496 100644
--- a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
+++ b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
@@ -660,6 +660,8 @@ extern "C" uint32_t LLVMRustDebugMetadataVersion() {
   return DEBUG_METADATA_VERSION;
 }
 
+extern "C" uint32_t LLVMRustVersionPatch() { return LLVM_VERSION_PATCH; }
+
 extern "C" uint32_t LLVMRustVersionMinor() { return LLVM_VERSION_MINOR; }
 
 extern "C" uint32_t LLVMRustVersionMajor() { return LLVM_VERSION_MAJOR; }
diff --git a/src/test/assembly/stack-probes.rs b/src/test/assembly/stack-probes.rs
new file mode 100644
index 00000000000..9597e242f1b
--- /dev/null
+++ b/src/test/assembly/stack-probes.rs
@@ -0,0 +1,42 @@
+// min-llvm-version: 11.0.1
+// revisions: x86_64 i686
+// assembly-output: emit-asm
+//[x86_64] compile-flags: --target x86_64-unknown-linux-gnu
+//[i686] compile-flags: --target i686-unknown-linux-gnu
+// compile-flags: -C llvm-args=--x86-asm-syntax=intel
+
+#![feature(no_core, lang_items)]
+#![crate_type = "lib"]
+#![no_core]
+
+#[lang = "sized"]
+trait Sized {}
+#[lang = "copy"]
+trait Copy {}
+
+impl Copy for u8 {}
+
+// Check that inline-asm stack probes are generated correctly.
+// To avoid making this test fragile to slight asm changes,
+// we only check that the stack pointer is decremented by a page at a time,
+// instead of matching the whole probe sequence.
+
+// CHECK-LABEL: small_stack_probe:
+#[no_mangle]
+pub fn small_stack_probe(x: u8, f: fn([u8; 8192])) {
+    // CHECK-NOT: __rust_probestack
+    // x86_64: sub rsp, 4096
+    // i686: sub esp, 4096
+    let a = [x; 8192];
+    f(a);
+}
+
+// CHECK-LABEL: big_stack_probe:
+#[no_mangle]
+pub fn big_stack_probe(x: u8, f: fn([u8; 65536])) {
+    // CHECK-NOT: __rust_probestack
+    // x86_64: sub rsp, 4096
+    // i686: sub esp, 4096
+    let a = [x; 65536];
+    f(a);
+}
diff --git a/src/test/codegen/stack-probes.rs b/src/test/codegen/stack-probes.rs
index 3e3222d4735..b05787df8e3 100644
--- a/src/test/codegen/stack-probes.rs
+++ b/src/test/codegen/stack-probes.rs
@@ -13,11 +13,12 @@
 // ignore-emscripten
 // ignore-windows
 // compile-flags: -C no-prepopulate-passes
+// min-llvm-version: 11.0.1
 
 #![crate_type = "lib"]
 
 #[no_mangle]
 pub fn foo() {
 // CHECK: @foo() unnamed_addr #0
-// CHECK: attributes #0 = { {{.*}}"probe-stack"="__rust_probestack"{{.*}} }
+// CHECK: attributes #0 = { {{.*}}"probe-stack"="inline-asm"{{.*}} }
 }