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,14 +171,15 @@ pub fn target_features(sess: &Session) -> Vec { } pub fn print_version() { - // Can be called without initializing LLVM - unsafe { - println!("LLVM version: {}.{}", llvm::LLVMRustVersionMajor(), llvm::LLVMRustVersionMinor()); - } + let (major, minor, patch) = get_version(); + println!("LLVM version: {}.{}.{}", major, minor, patch); } -pub fn get_major_version() -> u32 { - unsafe { llvm::LLVMRustVersionMajor() } +pub fn get_version() -> (u32, u32, u32) { + // Can be called without initializing LLVM + unsafe { + (llvm::LLVMRustVersionMajor(), llvm::LLVMRustVersionMinor(), llvm::LLVMRustVersionPatch()) + } } pub fn print_passes() { 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"{{.*}} } }