about summary refs log tree commit diff
path: root/tests/codegen
diff options
context:
space:
mode:
Diffstat (limited to 'tests/codegen')
-rw-r--r--tests/codegen/enum/enum-aggregate.rs15
-rw-r--r--tests/codegen/enum/enum-match.rs2
-rw-r--r--tests/codegen/error-provide.rs6
-rw-r--r--tests/codegen/fn-parameters-on-different-lines-debuginfo.rs22
-rw-r--r--tests/codegen/intrinsics/transmute.rs37
-rw-r--r--tests/codegen/sanitizer/kcfi/naked-function.rs47
-rw-r--r--tests/codegen/simd/aggregate-simd.rs106
-rw-r--r--tests/codegen/union-aggregate.rs23
8 files changed, 228 insertions, 30 deletions
diff --git a/tests/codegen/enum/enum-aggregate.rs b/tests/codegen/enum/enum-aggregate.rs
index b6a9b8dd814..0161e5f3fa1 100644
--- a/tests/codegen/enum/enum-aggregate.rs
+++ b/tests/codegen/enum/enum-aggregate.rs
@@ -112,17 +112,14 @@ fn make_uninhabited_err_indirectly(n: Never) -> Result<u32, Never> {
 
 #[no_mangle]
 fn make_fully_uninhabited_result(v: u32, n: Never) -> Result<(u32, Never), (Never, u32)> {
-    // We don't try to do this in SSA form since the whole type is uninhabited.
+    // Actually reaching this would be UB, so we don't actually build a result.
 
     // CHECK-LABEL: { i32, i32 } @make_fully_uninhabited_result(i32 %v)
-    // CHECK: %[[ALLOC_V:.+]] = alloca [4 x i8]
-    // CHECK: %[[RET:.+]] = alloca [8 x i8]
-    // CHECK: store i32 %v, ptr %[[ALLOC_V]]
-    // CHECK: %[[TEMP_V:.+]] = load i32, ptr %[[ALLOC_V]]
-    // CHECK: %[[INNER:.+]] = getelementptr inbounds i8, ptr %[[RET]]
-    // CHECK: store i32 %[[TEMP_V]], ptr %[[INNER]]
-    // CHECK: call void @llvm.trap()
-    // CHECK: unreachable
+    // CHECK-NEXT: start:
+    // CHECK-NEXT: call void @llvm.trap()
+    // CHECK-NEXT: call void @llvm.trap()
+    // CHECK-NEXT: call void @llvm.trap()
+    // CHECK-NEXT: unreachable
     Ok((v, n))
 }
 
diff --git a/tests/codegen/enum/enum-match.rs b/tests/codegen/enum/enum-match.rs
index 6da6ad1f078..98635008d06 100644
--- a/tests/codegen/enum/enum-match.rs
+++ b/tests/codegen/enum/enum-match.rs
@@ -98,7 +98,7 @@ pub enum Enum2 {
     E,
 }
 
-// CHECK-LABEL: define{{( dso_local)?}} noundef{{( range\(i8 [0-9]+, [0-9]+\))?}} i8 @match2(i8{{.+}}%0)
+// CHECK-LABEL: define{{( dso_local)?}} noundef{{( range\(i8 [0-9]+, -?[0-9]+\))?}} i8 @match2(i8{{.+}}%0)
 // CHECK-NEXT: start:
 // CHECK-NEXT: %[[REL_VAR:.+]] = add i8 %0, 2
 // CHECK-NEXT: %[[REL_VAR_WIDE:.+]] = zext i8 %[[REL_VAR]] to i64
diff --git a/tests/codegen/error-provide.rs b/tests/codegen/error-provide.rs
index 25a66078fd4..7f091e34359 100644
--- a/tests/codegen/error-provide.rs
+++ b/tests/codegen/error-provide.rs
@@ -37,9 +37,9 @@ impl std::error::Error for MyError {
         // and eliminate redundant ones, rather than compare one-by-one.
 
         // CHECK-NEXT: start:
-        // CHECK-NEXT: %[[SCRUTINEE:[^ ]+]] = load i64, ptr
-        // CHECK-NEXT: switch i64 %[[SCRUTINEE]], label %{{.*}} [
-        // CHECK-COUNT-3: i64 {{.*}}, label %{{.*}}
+        // CHECK-NEXT: %[[SCRUTINEE:[^ ]+]] = load i128, ptr
+        // CHECK-NEXT: switch i128 %[[SCRUTINEE]], label %{{.*}} [
+        // CHECK-COUNT-3: i128 {{.*}}, label %{{.*}}
         // CHECK-NEXT: ]
         request
             .provide_ref::<MyBacktrace1>(&self.backtrace1)
diff --git a/tests/codegen/fn-parameters-on-different-lines-debuginfo.rs b/tests/codegen/fn-parameters-on-different-lines-debuginfo.rs
new file mode 100644
index 00000000000..2097567f322
--- /dev/null
+++ b/tests/codegen/fn-parameters-on-different-lines-debuginfo.rs
@@ -0,0 +1,22 @@
+//! Make sure that line debuginfo of function parameters are correct even if
+//! they are not on the same line. Regression test for
+// <https://github.com/rust-lang/rust/issues/45010>.
+
+//@ compile-flags: -g -Copt-level=0
+
+#[rustfmt::skip] // Having parameters on different lines is crucial for this test.
+pub fn foo(
+    x_parameter_not_in_std: i32,
+    y_parameter_not_in_std: i32,
+) -> i32 {
+    x_parameter_not_in_std + y_parameter_not_in_std
+}
+
+fn main() {
+    foo(42, 43); // Ensure `wasm32-wasip1` keeps `foo()` (even if `-Copt-level=0`)
+}
+
+// CHECK: !DILocalVariable(name: "x_parameter_not_in_std", arg: 1,
+// CHECK-SAME: line: 9
+// CHECK: !DILocalVariable(name: "y_parameter_not_in_std", arg: 2,
+// CHECK-SAME: line: 10
diff --git a/tests/codegen/intrinsics/transmute.rs b/tests/codegen/intrinsics/transmute.rs
index e375724bc1b..c9a1cd58af3 100644
--- a/tests/codegen/intrinsics/transmute.rs
+++ b/tests/codegen/intrinsics/transmute.rs
@@ -29,28 +29,28 @@ pub struct Aggregate8(u8);
 // CHECK-LABEL: @check_bigger_size(
 #[no_mangle]
 pub unsafe fn check_bigger_size(x: u16) -> u32 {
-    // CHECK: call void @llvm.assume(i1 false)
+    // CHECK: store i1 true, ptr poison, align 1
     transmute_unchecked(x)
 }
 
 // CHECK-LABEL: @check_smaller_size(
 #[no_mangle]
 pub unsafe fn check_smaller_size(x: u32) -> u16 {
-    // CHECK: call void @llvm.assume(i1 false)
+    // CHECK: store i1 true, ptr poison, align 1
     transmute_unchecked(x)
 }
 
 // CHECK-LABEL: @check_smaller_array(
 #[no_mangle]
 pub unsafe fn check_smaller_array(x: [u32; 7]) -> [u32; 3] {
-    // CHECK: call void @llvm.assume(i1 false)
+    // CHECK: store i1 true, ptr poison, align 1
     transmute_unchecked(x)
 }
 
 // CHECK-LABEL: @check_bigger_array(
 #[no_mangle]
 pub unsafe fn check_bigger_array(x: [u32; 3]) -> [u32; 7] {
-    // CHECK: call void @llvm.assume(i1 false)
+    // CHECK: store i1 true, ptr poison, align 1
     transmute_unchecked(x)
 }
 
@@ -58,9 +58,9 @@ pub unsafe fn check_bigger_array(x: [u32; 3]) -> [u32; 7] {
 #[no_mangle]
 #[custom_mir(dialect = "runtime", phase = "optimized")]
 pub unsafe fn check_to_empty_array(x: [u32; 5]) -> [u32; 0] {
-    // CHECK-NOT: trap
-    // CHECK: call void @llvm.trap
-    // CHECK-NOT: trap
+    // CHECK: start
+    // CHECK-NEXT: store i1 true, ptr poison, align 1
+    // CHECK-NEXT: ret void
     mir! {
         {
             RET = CastTransmute(x);
@@ -73,9 +73,9 @@ pub unsafe fn check_to_empty_array(x: [u32; 5]) -> [u32; 0] {
 #[no_mangle]
 #[custom_mir(dialect = "runtime", phase = "optimized")]
 pub unsafe fn check_from_empty_array(x: [u32; 0]) -> [u32; 5] {
-    // CHECK-NOT: call
-    // CHECK: call void @llvm.assume(i1 false)
-    // CHECK-NOT: call
+    // CHECK: start
+    // CHECK-NEXT: store i1 true, ptr poison, align 1
+    // CHECK-NEXT: ret void
     mir! {
         {
             RET = CastTransmute(x);
@@ -88,9 +88,9 @@ pub unsafe fn check_from_empty_array(x: [u32; 0]) -> [u32; 5] {
 #[no_mangle]
 #[custom_mir(dialect = "runtime", phase = "optimized")]
 pub unsafe fn check_to_uninhabited(x: u16) {
-    // CHECK-NOT: trap
-    // CHECK: call void @llvm.trap
-    // CHECK-NOT: trap
+    // CHECK: start
+    // CHECK-NEXT: store i1 true, ptr poison, align 1
+    // CHECK-NEXT: ret void
     mir! {
         let temp: BigNever;
         {
@@ -104,7 +104,9 @@ pub unsafe fn check_to_uninhabited(x: u16) {
 #[no_mangle]
 #[custom_mir(dialect = "runtime", phase = "optimized")]
 pub unsafe fn check_from_uninhabited(x: BigNever) -> u16 {
-    // CHECK: ret i16 poison
+    // CHECK: start
+    // CHECK-NEXT: store i1 true, ptr poison, align 1
+    // CHECK-NEXT: ret i16 poison
     mir! {
         {
             RET = CastTransmute(x);
@@ -401,9 +403,9 @@ pub unsafe fn check_issue_109992(x: ()) -> [(); 1] {
 pub unsafe fn check_unit_to_never(x: ()) {
     // This uses custom MIR to avoid MIR optimizations having removed ZST ops.
 
-    // CHECK-NOT: trap
-    // CHECK: call void @llvm.trap
-    // CHECK-NOT: trap
+    // CHECK: start
+    // CHECK-NEXT: store i1 true, ptr poison, align 1
+    // CHECK-NEXT: ret void
     mir! {
         let temp: ZstNever;
         {
@@ -420,6 +422,7 @@ pub unsafe fn check_unit_from_never(x: ZstNever) -> () {
     // This uses custom MIR to avoid MIR optimizations having removed ZST ops.
 
     // CHECK: start
+    // CHECK-NEXT: store i1 true, ptr poison, align 1
     // CHECK-NEXT: ret void
     mir! {
         {
diff --git a/tests/codegen/sanitizer/kcfi/naked-function.rs b/tests/codegen/sanitizer/kcfi/naked-function.rs
new file mode 100644
index 00000000000..2c8cdc919b8
--- /dev/null
+++ b/tests/codegen/sanitizer/kcfi/naked-function.rs
@@ -0,0 +1,47 @@
+//@ add-core-stubs
+//@ revisions: aarch64 x86_64
+//@ [aarch64] compile-flags: --target aarch64-unknown-none
+//@ [aarch64] needs-llvm-components: aarch64
+//@ [x86_64] compile-flags: --target x86_64-unknown-none
+//@ [x86_64] needs-llvm-components: x86
+//@ compile-flags: -Ctarget-feature=-crt-static -Zsanitizer=kcfi -Cno-prepopulate-passes -Copt-level=0
+
+#![feature(no_core, lang_items)]
+#![crate_type = "lib"]
+#![no_core]
+
+extern crate minicore;
+use minicore::*;
+
+struct Thing;
+trait MyTrait {
+    #[unsafe(naked)]
+    extern "C" fn my_naked_function() {
+        // the real function is defined
+        // CHECK: .globl
+        // CHECK-SAME: my_naked_function
+        naked_asm!("ret")
+    }
+}
+impl MyTrait for Thing {}
+
+// the shim calls the real function
+// CHECK-LABEL: define
+// CHECK-SAME: my_naked_function
+// CHECK-SAME: reify.shim.fnptr
+
+// CHECK-LABEL: main
+#[unsafe(no_mangle)]
+pub fn main() {
+    // Trick the compiler into generating an indirect call.
+    const F: extern "C" fn() = Thing::my_naked_function;
+
+    // main calls the shim function
+    // CHECK: call void
+    // CHECK-SAME: my_naked_function
+    // CHECK-SAME: reify.shim.fnptr
+    (F)();
+}
+
+// CHECK: declare !kcfi_type
+// CHECK-SAME: my_naked_function
diff --git a/tests/codegen/simd/aggregate-simd.rs b/tests/codegen/simd/aggregate-simd.rs
new file mode 100644
index 00000000000..065e429a4c7
--- /dev/null
+++ b/tests/codegen/simd/aggregate-simd.rs
@@ -0,0 +1,106 @@
+//@ compile-flags: -C opt-level=3 -C no-prepopulate-passes
+//@ only-64bit
+
+#![feature(core_intrinsics, repr_simd)]
+#![no_std]
+#![crate_type = "lib"]
+
+use core::intrinsics::simd::{simd_add, simd_extract};
+
+#[repr(simd)]
+#[derive(Clone, Copy)]
+pub struct Simd<T, const N: usize>([T; N]);
+
+#[repr(simd, packed)]
+#[derive(Clone, Copy)]
+pub struct PackedSimd<T, const N: usize>([T; N]);
+
+#[repr(transparent)]
+pub struct Transparent<T>(T);
+
+// These tests don't actually care about the add/extract, but it ensures the
+// aggregated temporaries are only used in potentially-SSA ways.
+
+#[no_mangle]
+pub fn simd_aggregate_pot(x: [u32; 4], y: [u32; 4]) -> u32 {
+    // CHECK-LABEL: simd_aggregate_pot
+    // CHECK: %a = load <4 x i32>, ptr %x, align 4
+    // CHECK: %b = load <4 x i32>, ptr %y, align 4
+    // CHECK: add <4 x i32> %a, %b
+
+    unsafe {
+        let a = Simd(x);
+        let b = Simd(y);
+        let c = simd_add(a, b);
+        simd_extract(c, 1)
+    }
+}
+
+#[no_mangle]
+pub fn simd_aggregate_npot(x: [u32; 7], y: [u32; 7]) -> u32 {
+    // CHECK-LABEL: simd_aggregate_npot
+    // CHECK: %a = load <7 x i32>, ptr %x, align 4
+    // CHECK: %b = load <7 x i32>, ptr %y, align 4
+    // CHECK: add <7 x i32> %a, %b
+
+    unsafe {
+        let a = Simd(x);
+        let b = Simd(y);
+        let c = simd_add(a, b);
+        simd_extract(c, 1)
+    }
+}
+
+#[no_mangle]
+pub fn packed_simd_aggregate_pot(x: [u32; 4], y: [u32; 4]) -> u32 {
+    // CHECK-LABEL: packed_simd_aggregate_pot
+    // CHECK: %a = load <4 x i32>, ptr %x, align 4
+    // CHECK: %b = load <4 x i32>, ptr %y, align 4
+    // CHECK: add <4 x i32> %a, %b
+
+    unsafe {
+        let a = PackedSimd(x);
+        let b = PackedSimd(y);
+        let c = simd_add(a, b);
+        simd_extract(c, 1)
+    }
+}
+
+#[no_mangle]
+pub fn packed_simd_aggregate_npot(x: [u32; 7], y: [u32; 7]) -> u32 {
+    // CHECK-LABEL: packed_simd_aggregate_npot
+    // CHECK: %b = alloca [28 x i8], align 4
+    // CHECK: %a = alloca [28 x i8], align 4
+    // CHECK: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %a, ptr align 4 %x, i64 28, i1 false)
+    // CHECK: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %b, ptr align 4 %y, i64 28, i1 false)
+    // CHECK: %[[TEMPA:.+]] = load <7 x i32>, ptr %a, align 4
+    // CHECK: %[[TEMPB:.+]] = load <7 x i32>, ptr %b, align 4
+    // CHECK: add <7 x i32> %[[TEMPA]], %[[TEMPB]]
+
+    unsafe {
+        let a = PackedSimd(x);
+        let b = PackedSimd(y);
+        let c = simd_add(a, b);
+        simd_extract(c, 1)
+    }
+}
+
+#[no_mangle]
+pub fn transparent_simd_aggregate(x: [u32; 4]) -> u32 {
+    // The transparent wrapper can just use the same SSA value as its field.
+    // No extra processing or spilling needed.
+
+    // CHECK-LABEL: transparent_simd_aggregate
+    // CHECK-NOT: alloca
+    // CHECK: %[[RET:.+]] = alloca [4 x i8]
+    // CHECK-NOT: alloca
+    // CHECK: %a = load <4 x i32>, ptr %x, align 4
+    // CHECK: %[[TEMP:.+]] = extractelement <4 x i32> %a, i32 1
+    // CHECK: store i32 %[[TEMP]], ptr %[[RET]]
+
+    unsafe {
+        let a = Simd(x);
+        let b = Transparent(a);
+        simd_extract(b.0, 1)
+    }
+}
diff --git a/tests/codegen/union-aggregate.rs b/tests/codegen/union-aggregate.rs
index 3c6053379fa..aac66c5dcdd 100644
--- a/tests/codegen/union-aggregate.rs
+++ b/tests/codegen/union-aggregate.rs
@@ -4,6 +4,7 @@
 
 #![crate_type = "lib"]
 #![feature(transparent_unions)]
+#![feature(repr_simd)]
 
 #[repr(transparent)]
 union MU<T: Copy> {
@@ -83,3 +84,25 @@ fn make_mu_pair_uninit() -> MU<(u8, u32)> {
     // CHECK-NEXT: ret { i8, i32 } undef
     MU { uninit: () }
 }
+
+#[repr(simd)]
+#[derive(Copy, Clone)]
+struct I32X32([i32; 32]);
+
+#[no_mangle]
+fn make_mu_simd(x: I32X32) -> MU<I32X32> {
+    // CHECK-LABEL: void @make_mu_simd(ptr{{.+}}%_0, ptr{{.+}}%x)
+    // CHECK-NEXT: start:
+    // CHECK-NEXT: %[[TEMP:.+]] = load <32 x i32>, ptr %x,
+    // CHECK-NEXT: store <32 x i32> %[[TEMP]], ptr %_0,
+    // CHECK-NEXT: ret void
+    MU { value: x }
+}
+
+#[no_mangle]
+fn make_mu_simd_uninit() -> MU<I32X32> {
+    // CHECK-LABEL: void @make_mu_simd_uninit(ptr{{.+}}%_0)
+    // CHECK-NEXT: start:
+    // CHECK-NEXT: ret void
+    MU { uninit: () }
+}