From a99e97af97f5f86e1892ec2bf633105384ed8bee Mon Sep 17 00:00:00 2001 From: Erik Desjardins Date: Thu, 8 Dec 2022 01:30:07 -0500 Subject: Add 0..=isize::MAX range metadata to size loads from vtables --- src/test/codegen/dst-vtable-align-nonzero.rs | 18 ++++++++++++++ src/test/codegen/dst-vtable-size-range.rs | 37 ++++++++++++++++++++++++++++ 2 files changed, 55 insertions(+) create mode 100644 src/test/codegen/dst-vtable-size-range.rs (limited to 'src/test/codegen') diff --git a/src/test/codegen/dst-vtable-align-nonzero.rs b/src/test/codegen/dst-vtable-align-nonzero.rs index 14c4c3f30f9..7ebb4173d56 100644 --- a/src/test/codegen/dst-vtable-align-nonzero.rs +++ b/src/test/codegen/dst-vtable-align-nonzero.rs @@ -1,6 +1,7 @@ // compile-flags: -O #![crate_type = "lib"] +#![feature(core_intrinsics)] // This test checks that we annotate alignment loads from vtables with nonzero range metadata, // and that this allows LLVM to eliminate redundant `align >= 1` checks. @@ -42,4 +43,21 @@ pub fn does_not_eliminate_runtime_check_when_align_2( &x.dst } +// CHECK-LABEL: @align_load_from_align_of_val +#[no_mangle] +pub fn align_load_from_align_of_val(x: &dyn Trait) -> usize { + // CHECK: {{%[0-9]+}} = load [[USIZE]], {{.+}} !range [[RANGE_META]] + core::mem::align_of_val(x) +} + +// CHECK-LABEL: @align_load_from_vtable_align_intrinsic +#[no_mangle] +pub unsafe fn align_load_from_vtable_align_intrinsic(x: &dyn Trait) -> usize { + let (data, vtable): (*const (), *const ()) = core::mem::transmute(x); + // CHECK: {{%[0-9]+}} = load [[USIZE]], {{.+}} !range [[RANGE_META]] + let align = core::intrinsics::vtable_align(vtable); + // make this function unique so it doesn't get merged with the previous + align + 1 +} + // CHECK: [[RANGE_META]] = !{[[USIZE]] 1, [[USIZE]] 0} diff --git a/src/test/codegen/dst-vtable-size-range.rs b/src/test/codegen/dst-vtable-size-range.rs new file mode 100644 index 00000000000..cec5876b348 --- /dev/null +++ b/src/test/codegen/dst-vtable-size-range.rs @@ -0,0 +1,37 @@ +// compile-flags: -O + +#![crate_type = "lib"] +#![feature(core_intrinsics)] + +// Check that we annotate size loads from vtables with 0..(isize::MAX + 1) range metadata. + +pub trait Trait { + fn f(&self); +} + +// Note that rustc uses inclusive bounds, but LLVM uses exclusive bounds for range metadata. +// CHECK-LABEL: @generate_exclusive_bound +#[no_mangle] +pub fn generate_exclusive_bound() -> usize { + // CHECK: ret [[USIZE:i[0-9]+]] [[EXCLUSIVE_BOUND:[-0-9]+]] + isize::MAX as usize + 1 +} + +// CHECK-LABEL: @size_load_from_size_of_val +#[no_mangle] +pub fn size_load_from_size_of_val(x: &dyn Trait) -> usize { + // CHECK: {{%[0-9]+}} = load [[USIZE]], {{.+}} !range [[RANGE_META:![0-9]+]] + core::mem::size_of_val(x) +} + +// CHECK-LABEL: @size_load_from_vtable_size_intrinsic +#[no_mangle] +pub unsafe fn size_load_from_vtable_size_intrinsic(x: &dyn Trait) -> usize { + let (data, vtable): (*const (), *const ()) = core::mem::transmute(x); + // CHECK: {{%[0-9]+}} = load [[USIZE]], {{.+}} !range [[RANGE_META]] + let size = core::intrinsics::vtable_size(vtable); + // make this function unique so it doesn't get merged with the previous + size + 1 +} + +// CHECK: [[RANGE_META]] = !{[[USIZE]] 0, [[USIZE]] [[EXCLUSIVE_BOUND]]} -- cgit 1.4.1-3-g733a5 From e01d944c6c33a76cdbd1a257743d8c41a8203e89 Mon Sep 17 00:00:00 2001 From: Erik Desjardins Date: Thu, 8 Dec 2022 19:33:14 -0500 Subject: disable mergefunc instead of making fns unique --- src/test/codegen/dst-vtable-align-nonzero.rs | 6 ++---- src/test/codegen/dst-vtable-size-range.rs | 6 ++---- 2 files changed, 4 insertions(+), 8 deletions(-) (limited to 'src/test/codegen') diff --git a/src/test/codegen/dst-vtable-align-nonzero.rs b/src/test/codegen/dst-vtable-align-nonzero.rs index 7ebb4173d56..54f6e7f992f 100644 --- a/src/test/codegen/dst-vtable-align-nonzero.rs +++ b/src/test/codegen/dst-vtable-align-nonzero.rs @@ -1,4 +1,4 @@ -// compile-flags: -O +// compile-flags: -O -Z merge-functions=disabled #![crate_type = "lib"] #![feature(core_intrinsics)] @@ -55,9 +55,7 @@ pub fn align_load_from_align_of_val(x: &dyn Trait) -> usize { pub unsafe fn align_load_from_vtable_align_intrinsic(x: &dyn Trait) -> usize { let (data, vtable): (*const (), *const ()) = core::mem::transmute(x); // CHECK: {{%[0-9]+}} = load [[USIZE]], {{.+}} !range [[RANGE_META]] - let align = core::intrinsics::vtable_align(vtable); - // make this function unique so it doesn't get merged with the previous - align + 1 + core::intrinsics::vtable_align(vtable) } // CHECK: [[RANGE_META]] = !{[[USIZE]] 1, [[USIZE]] 0} diff --git a/src/test/codegen/dst-vtable-size-range.rs b/src/test/codegen/dst-vtable-size-range.rs index cec5876b348..671c8abdebd 100644 --- a/src/test/codegen/dst-vtable-size-range.rs +++ b/src/test/codegen/dst-vtable-size-range.rs @@ -1,4 +1,4 @@ -// compile-flags: -O +// compile-flags: -O -Z merge-functions=disabled #![crate_type = "lib"] #![feature(core_intrinsics)] @@ -29,9 +29,7 @@ pub fn size_load_from_size_of_val(x: &dyn Trait) -> usize { pub unsafe fn size_load_from_vtable_size_intrinsic(x: &dyn Trait) -> usize { let (data, vtable): (*const (), *const ()) = core::mem::transmute(x); // CHECK: {{%[0-9]+}} = load [[USIZE]], {{.+}} !range [[RANGE_META]] - let size = core::intrinsics::vtable_size(vtable); - // make this function unique so it doesn't get merged with the previous - size + 1 + core::intrinsics::vtable_size(vtable) } // CHECK: [[RANGE_META]] = !{[[USIZE]] 0, [[USIZE]] [[EXCLUSIVE_BOUND]]} -- cgit 1.4.1-3-g733a5 From 295f5f514bf423e79ad67ed99c6d90944b299c10 Mon Sep 17 00:00:00 2001 From: Tim Neumann Date: Sun, 11 Dec 2022 19:05:37 +0000 Subject: KCFI test: Also support LLVM 16 output --- .../sanitizer-kcfi-emit-kcfi-operand-bundle-itanium-cxx-abi.rs | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) (limited to 'src/test/codegen') diff --git a/src/test/codegen/sanitizer-kcfi-emit-kcfi-operand-bundle-itanium-cxx-abi.rs b/src/test/codegen/sanitizer-kcfi-emit-kcfi-operand-bundle-itanium-cxx-abi.rs index 0afd9727517..8e0d02550ee 100644 --- a/src/test/codegen/sanitizer-kcfi-emit-kcfi-operand-bundle-itanium-cxx-abi.rs +++ b/src/test/codegen/sanitizer-kcfi-emit-kcfi-operand-bundle-itanium-cxx-abi.rs @@ -20,24 +20,21 @@ impl Copy for i32 {} pub fn foo(f: fn(i32) -> i32, arg: i32) -> i32 { // CHECK-LABEL: define{{.*}}foo - // FIXME(rcvalle): Change to !kcfi_type when Rust is updated to LLVM 16 - // CHECK-SAME: {{.*}}! ![[TYPE1:[0-9]+]] + // CHECK-SAME: {{.*}}!{{|kcfi_type}} ![[TYPE1:[0-9]+]] // CHECK: call i32 %f(i32 %arg){{.*}}[ "kcfi"(i32 -1666898348) ] f(arg) } pub fn bar(f: fn(i32, i32) -> i32, arg1: i32, arg2: i32) -> i32 { // CHECK-LABEL: define{{.*}}bar - // FIXME(rcvalle): Change to !kcfi_type when Rust is updated to LLVM 16 - // CHECK-SAME: {{.*}}! ![[TYPE2:[0-9]+]] + // CHECK-SAME: {{.*}}!{{|kcfi_type}} ![[TYPE2:[0-9]+]] // CHECK: call i32 %f(i32 %arg1, i32 %arg2){{.*}}[ "kcfi"(i32 -1789026986) ] f(arg1, arg2) } pub fn baz(f: fn(i32, i32, i32) -> i32, arg1: i32, arg2: i32, arg3: i32) -> i32 { // CHECK-LABEL: define{{.*}}baz - // FIXME(rcvalle): Change to !kcfi_type when Rust is updated to LLVM 16 - // CHECK-SAME: {{.*}}! ![[TYPE3:[0-9]+]] + // CHECK-SAME: {{.*}}!{{|kcfi_type}} ![[TYPE3:[0-9]+]] // CHECK: call i32 %f(i32 %arg1, i32 %arg2, i32 %arg3){{.*}}[ "kcfi"(i32 1248878270) ] f(arg1, arg2, arg3) } -- cgit 1.4.1-3-g733a5 From 8751d3b2e9a2fa903822a1f9061c0fe2c4c0bef2 Mon Sep 17 00:00:00 2001 From: Collin Baker Date: Fri, 16 Dec 2022 17:32:29 -0500 Subject: Make enum-match.rs test robust against variable name changes https://reviews.llvm.org/D140192 caused the LLVM variable generated for enum discriminant checks to be named differently (%narrow vs %1). This adjusts the test CHECK directives to match any name. --- src/test/codegen/enum-match.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/test/codegen') diff --git a/src/test/codegen/enum-match.rs b/src/test/codegen/enum-match.rs index 44f1b408d21..827eb20154a 100644 --- a/src/test/codegen/enum-match.rs +++ b/src/test/codegen/enum-match.rs @@ -34,8 +34,8 @@ pub enum Enum1 { // CHECK: define i8 @match1{{.*}} // CHECK-NEXT: start: -// CHECK-NEXT: %1 = {{.*}}call i8 @llvm.usub.sat.i8(i8 %0, i8 1) -// CHECK-NEXT: switch i8 %1, label {{.*}} [ +// CHECK-NEXT: [[DISCR:%.*]] = {{.*}}call i8 @llvm.usub.sat.i8(i8 %0, i8 1) +// CHECK-NEXT: switch i8 [[DISCR]], label {{.*}} [ #[no_mangle] pub fn match1(e: Enum1) -> u8 { use Enum1::*; -- cgit 1.4.1-3-g733a5 From a65ec44779ab2c01ba937b40496ca648626d0308 Mon Sep 17 00:00:00 2001 From: Miguel Ojeda Date: Sat, 17 Dec 2022 02:50:08 +0100 Subject: Add `-Zno-jump-tables` This flag mimics GCC/Clang's `-fno-jump-tables` [1][2], which makes the codegen backend avoid generating jump tables when lowering switches. In the case of LLVM, the `"no-jump-tables"="true"` function attribute is added to every function. The kernel currently needs it for x86 when enabling IBT [3], as well as for Alpha (plus VDSO objects in MIPS/LoongArch). [1] https://gcc.gnu.org/onlinedocs/gcc/Code-Gen-Options.html#index-fno-jump-tables [2] https://clang.llvm.org/docs/ClangCommandLineReference.html#cmdoption-clang-fjump-tables [3] https://github.com/torvalds/linux/blob/v6.1/arch/x86/Makefile#L75-L83 Signed-off-by: Miguel Ojeda --- compiler/rustc_codegen_llvm/src/attributes.rs | 9 +++++++ compiler/rustc_interface/src/tests.rs | 1 + compiler/rustc_session/src/options.rs | 2 ++ src/test/assembly/x86_64-no-jump-tables.rs | 34 +++++++++++++++++++++++++++ src/test/codegen/no-jump-tables.rs | 22 +++++++++++++++++ src/test/rustdoc-ui/z-help.stdout | 1 + 6 files changed, 69 insertions(+) create mode 100644 src/test/assembly/x86_64-no-jump-tables.rs create mode 100644 src/test/codegen/no-jump-tables.rs (limited to 'src/test/codegen') diff --git a/compiler/rustc_codegen_llvm/src/attributes.rs b/compiler/rustc_codegen_llvm/src/attributes.rs index f3bdacf6085..487eead22b8 100644 --- a/compiler/rustc_codegen_llvm/src/attributes.rs +++ b/compiler/rustc_codegen_llvm/src/attributes.rs @@ -137,6 +137,14 @@ fn instrument_function_attr<'ll>(cx: &CodegenCx<'ll, '_>) -> Option<&'ll Attribu } } +fn nojumptables_attr<'ll>(cx: &CodegenCx<'ll, '_>) -> Option<&'ll Attribute> { + if !cx.sess().opts.unstable_opts.no_jump_tables { + return None; + } + + Some(llvm::CreateAttrStringValue(cx.llcx, "no-jump-tables", "true")) +} + fn probestack_attr<'ll>(cx: &CodegenCx<'ll, '_>) -> Option<&'ll Attribute> { // Currently stack probes seem somewhat incompatible with the address // sanitizer and thread sanitizer. With asan we're already protected from @@ -293,6 +301,7 @@ pub fn from_fn_attrs<'ll, 'tcx>( // FIXME: none of these three functions interact with source level attributes. to_add.extend(frame_pointer_type_attr(cx)); to_add.extend(instrument_function_attr(cx)); + to_add.extend(nojumptables_attr(cx)); to_add.extend(probestack_attr(cx)); to_add.extend(stackprotector_attr(cx)); diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index e903cb86dd2..ff2196d5857 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -754,6 +754,7 @@ fn test_unstable_options_tracking_hash() { tracked!(move_size_limit, Some(4096)); tracked!(mutable_noalias, Some(true)); tracked!(no_generate_arange_section, true); + tracked!(no_jump_tables, true); tracked!(no_link, true); tracked!(no_profiler_runtime, true); tracked!(no_unique_section_names, true); diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index 9e130287104..40bc669707a 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -1421,6 +1421,8 @@ options! { "run all passes except codegen; no output"), no_generate_arange_section: bool = (false, parse_no_flag, [TRACKED], "omit DWARF address ranges that give faster lookups"), + no_jump_tables: bool = (false, parse_no_flag, [TRACKED], + "disable the jump tables and lookup tables that can be generated from a switch case lowering"), no_leak_check: bool = (false, parse_no_flag, [UNTRACKED], "disable the 'leak check' for subtyping; unsound, but useful for tests"), no_link: bool = (false, parse_no_flag, [TRACKED], diff --git a/src/test/assembly/x86_64-no-jump-tables.rs b/src/test/assembly/x86_64-no-jump-tables.rs new file mode 100644 index 00000000000..007c3591a4a --- /dev/null +++ b/src/test/assembly/x86_64-no-jump-tables.rs @@ -0,0 +1,34 @@ +// Test that jump tables are (not) emitted when the `-Zno-jump-tables` +// flag is (not) set. + +// revisions: unset set +// assembly-output: emit-asm +// compile-flags: -O +// [set] compile-flags: -Zno-jump-tables +// only-x86_64 + +#![crate_type = "lib"] + +extern "C" { + fn bar1(); + fn bar2(); + fn bar3(); + fn bar4(); + fn bar5(); + fn bar6(); +} + +// CHECK-LABEL: foo: +#[no_mangle] +pub unsafe fn foo(x: i32) { + // unset: LJTI0_0 + // set-NOT: LJTI0_0 + match x { + 1 => bar1(), + 2 => bar2(), + 3 => bar3(), + 4 => bar4(), + 5 => bar5(), + _ => bar6(), + } +} diff --git a/src/test/codegen/no-jump-tables.rs b/src/test/codegen/no-jump-tables.rs new file mode 100644 index 00000000000..8e2cb47566e --- /dev/null +++ b/src/test/codegen/no-jump-tables.rs @@ -0,0 +1,22 @@ +// Test that the `no-jump-tables` function attribute are (not) emitted when +// the `-Zno-jump-tables` flag is (not) set. + +// revisions: unset set +// needs-llvm-components: x86 +// compile-flags: --target x86_64-unknown-linux-gnu +// [set] compile-flags: -Zno-jump-tables + +#![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: attributes #0 = { {{.*}}"no-jump-tables"="true"{{.*}} } + // set: attributes #0 = { {{.*}}"no-jump-tables"="true"{{.*}} } +} diff --git a/src/test/rustdoc-ui/z-help.stdout b/src/test/rustdoc-ui/z-help.stdout index 3537e669608..53677b18377 100644 --- a/src/test/rustdoc-ui/z-help.stdout +++ b/src/test/rustdoc-ui/z-help.stdout @@ -92,6 +92,7 @@ -Z no-analysis=val -- parse and expand the source, but run no analysis -Z no-codegen=val -- run all passes except codegen; no output -Z no-generate-arange-section=val -- omit DWARF address ranges that give faster lookups + -Z no-jump-tables=val -- disable the jump tables and lookup tables that can be generated from a switch case lowering -Z no-leak-check=val -- disable the 'leak check' for subtyping; unsound, but useful for tests -Z no-link=val -- compile without linking -Z no-parallel-llvm=val -- run LLVM in non-parallel mode (while keeping codegen-units and ThinLTO) -- cgit 1.4.1-3-g733a5 From 9c9fa567f8ca5bf43b481407ab78508652970594 Mon Sep 17 00:00:00 2001 From: Krasimir Georgiev Date: Wed, 21 Dec 2022 14:19:04 +0000 Subject: codegen tests: adapt patterns to also work with v0 symbol mangling No functional changes intended. These tests were failing under `new-symbol-mangling = true`. This adapts the patterns to work in this case. --- src/test/codegen/unwind-abis/c-unwind-abi-panic-abort.rs | 3 ++- src/test/codegen/unwind-and-panic-abort.rs | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) (limited to 'src/test/codegen') diff --git a/src/test/codegen/unwind-abis/c-unwind-abi-panic-abort.rs b/src/test/codegen/unwind-abis/c-unwind-abi-panic-abort.rs index 8447bbeb1ed..34fd401f9e4 100644 --- a/src/test/codegen/unwind-abis/c-unwind-abi-panic-abort.rs +++ b/src/test/codegen/unwind-abis/c-unwind-abi-panic-abort.rs @@ -9,7 +9,8 @@ // CHECK: @rust_item_that_can_unwind() unnamed_addr [[ATTR0:#[0-9]+]] #[no_mangle] pub unsafe extern "C-unwind" fn rust_item_that_can_unwind() { - // CHECK: call void @_ZN4core9panicking15panic_no_unwind + // Handle both legacy and v0 symbol mangling. + // CHECK: call void @{{.*core9panicking15panic_no_unwind}} may_unwind(); } diff --git a/src/test/codegen/unwind-and-panic-abort.rs b/src/test/codegen/unwind-and-panic-abort.rs index f238741e599..b370191bf8c 100644 --- a/src/test/codegen/unwind-and-panic-abort.rs +++ b/src/test/codegen/unwind-and-panic-abort.rs @@ -9,7 +9,8 @@ extern "C-unwind" { // CHECK: Function Attrs:{{.*}}nounwind // CHECK-NEXT: define{{.*}}void @foo -// CHECK: call void @_ZN4core9panicking15panic_no_unwind +// Handle both legacy and v0 symbol mangling. +// CHECK: call void @{{.*core9panicking15panic_no_unwind}} #[no_mangle] pub unsafe extern "C" fn foo() { bar(); -- cgit 1.4.1-3-g733a5