summaryrefslogtreecommitdiffstats
path: root/tests/codegen
diff options
context:
space:
mode:
Diffstat (limited to 'tests/codegen')
-rw-r--r--tests/codegen/abi-main-signature-16bit-c-int.rs1
-rw-r--r--tests/codegen/addr-of-mutate.rs34
-rw-r--r--tests/codegen/align-fn.rs40
-rw-r--r--tests/codegen/align-offset.rs78
-rw-r--r--tests/codegen/alloc-optimisation.rs3
-rw-r--r--tests/codegen/array-map.rs2
-rw-r--r--tests/codegen/ascii-char.rs37
-rw-r--r--tests/codegen/binary-search-index-no-bound-check.rs4
-rw-r--r--tests/codegen/call-llvm-intrinsics.rs1
-rw-r--r--tests/codegen/catch-unwind.rs2
-rw-r--r--tests/codegen/debug-vtable.rs2
-rw-r--r--tests/codegen/debuginfo-constant-locals.rs28
-rw-r--r--tests/codegen/drop-in-place-noalias.rs38
-rw-r--r--tests/codegen/enable-lto-unit-splitting.rs10
-rw-r--r--tests/codegen/fewer-names.rs14
-rw-r--r--tests/codegen/global_asm.rs1
-rw-r--r--tests/codegen/global_asm_include.rs1
-rw-r--r--tests/codegen/global_asm_x2.rs1
-rw-r--r--tests/codegen/inline-hint.rs2
-rw-r--r--tests/codegen/intrinsics/offset.rs34
-rw-r--r--tests/codegen/intrinsics/transmute-niched.rs184
-rw-r--r--tests/codegen/intrinsics/transmute.rs50
-rw-r--r--tests/codegen/issues/issue-103840.rs1
-rw-r--r--tests/codegen/issues/issue-105386-ub-in-debuginfo.rs3
-rw-r--r--tests/codegen/issues/issue-111603.rs28
-rw-r--r--tests/codegen/issues/issue-73396-bounds-check-after-position.rs30
-rw-r--r--tests/codegen/issues/issue-86106.rs29
-rw-r--r--tests/codegen/local-generics-in-exe-internalized.rs2
-rw-r--r--tests/codegen/loongarch-abi/call-llvm-intrinsics.rs31
-rw-r--r--tests/codegen/loongarch-abi/loongarch64-lp64d-abi.rs293
-rw-r--r--tests/codegen/mem-replace-big-type.rs19
-rw-r--r--tests/codegen/mem-replace-direct-memcpy.rs33
-rw-r--r--tests/codegen/mem-replace-simple-type.rs34
-rw-r--r--tests/codegen/noalias-box-off.rs5
-rw-r--r--tests/codegen/nrvo.rs2
-rw-r--r--tests/codegen/optimize-attr-1.rs2
-rw-r--r--tests/codegen/option-as-slice.rs2
-rw-r--r--tests/codegen/option-nonzero-eq.rs12
-rw-r--r--tests/codegen/remap_path_prefix/auxiliary/xcrate-generic.rs4
-rw-r--r--tests/codegen/remap_path_prefix/xcrate-generic.rs2
-rw-r--r--tests/codegen/repr-transparent-aggregates-1.rs1
-rw-r--r--tests/codegen/repr-transparent-aggregates-2.rs1
-rw-r--r--tests/codegen/repr-transparent.rs1
-rw-r--r--tests/codegen/sanitizer-cfi-add-canonical-jump-tables-flag.rs2
-rw-r--r--tests/codegen/sanitizer-cfi-add-enable-split-lto-unit-flag.rs11
-rw-r--r--tests/codegen/sanitizer-cfi-emit-type-checks-attr-no-sanitize.rs18
-rw-r--r--tests/codegen/sanitizer-cfi-emit-type-checks.rs3
-rw-r--r--tests/codegen/sanitizer-cfi-emit-type-metadata-attr-cfi-encoding.rs48
-rw-r--r--tests/codegen/sanitizer-cfi-emit-type-metadata-id-itanium-cxx-abi.rs345
-rw-r--r--tests/codegen/sanitizer-cfi-emit-type-metadata-itanium-cxx-abi-generalized.rs31
-rw-r--r--tests/codegen/sanitizer-cfi-emit-type-metadata-itanium-cxx-abi-normalized-generalized.rs31
-rw-r--r--tests/codegen/sanitizer-cfi-emit-type-metadata-itanium-cxx-abi-normalized.rs31
-rw-r--r--tests/codegen/sanitizer-cfi-emit-type-metadata-itanium-cxx-abi.rs6
-rw-r--r--tests/codegen/sanitizer-cfi-emit-type-metadata-trait-objects.rs120
-rw-r--r--tests/codegen/sanitizer-cfi-generalize-pointers.rs46
-rw-r--r--tests/codegen/sanitizer-cfi-normalize-integers.rs83
-rw-r--r--tests/codegen/sanitizer-kcfi-emit-kcfi-operand-bundle-attr-no-sanitize.rs30
-rw-r--r--tests/codegen/sanitizer-kcfi-emit-kcfi-operand-bundle-itanium-cxx-abi-generalized.rs44
-rw-r--r--tests/codegen/sanitizer-kcfi-emit-kcfi-operand-bundle-itanium-cxx-abi-normalized-generalized.rs44
-rw-r--r--tests/codegen/sanitizer-kcfi-emit-kcfi-operand-bundle-itanium-cxx-abi-normalized.rs44
-rw-r--r--tests/codegen/sanitizer-kcfi-emit-kcfi-operand-bundle-itanium-cxx-abi.rs12
-rw-r--r--tests/codegen/sanitizer-kcfi-emit-kcfi-operand-bundle.rs27
-rw-r--r--tests/codegen/sanitizer-kcfi-emit-type-metadata-trait-objects.rs144
-rw-r--r--tests/codegen/slice-iter-nonnull.rs77
-rw-r--r--tests/codegen/split-lto-unit.rs11
-rw-r--r--tests/codegen/thread-local.rs8
-rw-r--r--tests/codegen/tied-features-strength.rs29
-rw-r--r--tests/codegen/transmute-optimized.rs109
-rw-r--r--tests/codegen/transmute-scalar.rs14
-rw-r--r--tests/codegen/vec-optimizes-away.rs3
-rw-r--r--tests/codegen/vec-shrink-panik.rs4
71 files changed, 2143 insertions, 334 deletions
diff --git a/tests/codegen/abi-main-signature-16bit-c-int.rs b/tests/codegen/abi-main-signature-16bit-c-int.rs
index 3548cc06a..353e7489b 100644
--- a/tests/codegen/abi-main-signature-16bit-c-int.rs
+++ b/tests/codegen/abi-main-signature-16bit-c-int.rs
@@ -17,6 +17,7 @@
// ignore-wasm32
// ignore-x86
// ignore-x86_64
+// ignore-loongarch64
fn main() {
}
diff --git a/tests/codegen/addr-of-mutate.rs b/tests/codegen/addr-of-mutate.rs
new file mode 100644
index 000000000..bea1aad23
--- /dev/null
+++ b/tests/codegen/addr-of-mutate.rs
@@ -0,0 +1,34 @@
+// compile-flags: -C opt-level=3 -C no-prepopulate-passes
+// min-llvm-version: 15.0 (for opaque pointers)
+
+#![crate_type = "lib"]
+
+// Test for the absence of `readonly` on the argument when it is mutated via `&raw const`.
+// See <https://github.com/rust-lang/rust/issues/111502>.
+
+// CHECK: i8 @foo(ptr noalias nocapture noundef dereferenceable(128) %x)
+#[no_mangle]
+pub fn foo(x: [u8; 128]) -> u8 {
+ let ptr = core::ptr::addr_of!(x).cast_mut();
+ unsafe {
+ (*ptr)[0] = 1;
+ }
+ x[0]
+}
+
+// CHECK: i1 @second(ptr noalias nocapture noundef dereferenceable({{[0-9]+}}) %a_ptr_and_b)
+#[no_mangle]
+pub unsafe fn second(a_ptr_and_b: (*mut (i32, bool), (i64, bool))) -> bool {
+ let b_bool_ptr = core::ptr::addr_of!(a_ptr_and_b.1.1).cast_mut();
+ (*b_bool_ptr) = true;
+ a_ptr_and_b.1.1
+}
+
+// If going through a deref (and there are no other mutating accesses), then `readonly` is fine.
+// CHECK: i1 @third(ptr noalias nocapture noundef readonly dereferenceable({{[0-9]+}}) %a_ptr_and_b)
+#[no_mangle]
+pub unsafe fn third(a_ptr_and_b: (*mut (i32, bool), (i64, bool))) -> bool {
+ let b_bool_ptr = core::ptr::addr_of!((*a_ptr_and_b.0).1).cast_mut();
+ (*b_bool_ptr) = true;
+ a_ptr_and_b.1.1
+}
diff --git a/tests/codegen/align-fn.rs b/tests/codegen/align-fn.rs
index c5886cf28..f3cf614e1 100644
--- a/tests/codegen/align-fn.rs
+++ b/tests/codegen/align-fn.rs
@@ -7,3 +7,43 @@
#[no_mangle]
#[repr(align(16))]
pub fn fn_align() {}
+
+pub struct A;
+
+impl A {
+ // CHECK: align 16
+ #[no_mangle]
+ #[repr(align(16))]
+ pub fn method_align(self) {}
+
+ // CHECK: align 16
+ #[no_mangle]
+ #[repr(align(16))]
+ pub fn associated_fn() {}
+}
+
+trait T: Sized {
+ fn trait_fn() {}
+
+ // CHECK: align 32
+ #[repr(align(32))]
+ fn trait_method(self) {}
+}
+
+impl T for A {
+ // CHECK: align 16
+ #[no_mangle]
+ #[repr(align(16))]
+ fn trait_fn() {}
+
+ // CHECK: align 16
+ #[no_mangle]
+ #[repr(align(16))]
+ fn trait_method(self) {}
+}
+
+impl T for () {}
+
+pub fn foo() {
+ ().trait_method();
+}
diff --git a/tests/codegen/align-offset.rs b/tests/codegen/align-offset.rs
new file mode 100644
index 000000000..7c7660c5a
--- /dev/null
+++ b/tests/codegen/align-offset.rs
@@ -0,0 +1,78 @@
+// compile-flags: -O
+// min-llvm-version: 15.0 (because we're using opaque pointers)
+// ignore-debug (debug assertions in `slice::from_raw_parts` block optimizations)
+
+#![crate_type = "lib"]
+
+// CHECK-LABEL: @align8
+#[no_mangle]
+pub fn align8(p: *const u8) -> bool {
+ // CHECK: ret i1 true
+ p.align_offset(8) < 8
+}
+
+#[repr(align(4))]
+pub struct Align4([u8; 4]);
+
+// CHECK-LABEL: @align_to4
+#[no_mangle]
+pub fn align_to4(x: &[u8]) -> bool {
+ // CHECK: ret i1 true
+ let (prefix, _middle, suffix) = unsafe { x.align_to::<Align4>() };
+ prefix.len() < 4 && suffix.len() < 4
+}
+
+// CHECK-LABEL: @align_offset_byte_ptr(ptr{{.+}}%ptr)
+#[no_mangle]
+pub fn align_offset_byte_ptr(ptr: *const u8) -> usize {
+ // CHECK: %[[ADDR:.+]] = ptrtoint ptr %ptr to [[USIZE:i[0-9]+]]
+ // CHECK: %[[UP:.+]] = add [[USIZE]] %[[ADDR]], 31
+ // CHECK: %[[ALIGNED:.+]] = and [[USIZE]] %[[UP]], -32
+ // CHECK: %[[OFFSET:.+]] = sub [[USIZE]] %[[ALIGNED]], %[[ADDR]]
+
+ // Since we're offsetting a byte pointer, there's no further fixups
+ // CHECK-NOT: shr
+ // CHECK-NOT: div
+ // CHECK-NOT: select
+
+ // CHECK: ret [[USIZE]] %[[OFFSET]]
+ ptr.align_offset(32)
+}
+
+// CHECK-LABEL: @align_offset_word_slice(ptr{{.+}}align 4{{.+}}%slice.0
+#[no_mangle]
+pub fn align_offset_word_slice(slice: &[Align4]) -> usize {
+ // CHECK: %[[ADDR:.+]] = ptrtoint ptr %slice.0 to [[USIZE]]
+ // CHECK: %[[UP:.+]] = add [[USIZE]] %[[ADDR]], 31
+ // CHECK: %[[ALIGNED:.+]] = and [[USIZE]] %[[UP]], -32
+ // CHECK: %[[BOFFSET:.+]] = sub [[USIZE]] %[[ALIGNED]], %[[ADDR]]
+ // CHECK: %[[OFFSET:.+]] = lshr exact [[USIZE]] %[[BOFFSET]], 2
+
+ // Slices are known to be aligned, so we don't need the "maybe -1" path
+ // CHECK-NOT: select
+
+ // CHECK: ret [[USIZE]] %[[OFFSET]]
+ slice.as_ptr().align_offset(32)
+}
+
+
+// CHECK-LABEL: @align_offset_word_ptr(ptr{{.+}}%ptr
+#[no_mangle]
+pub fn align_offset_word_ptr(ptr: *const Align4) -> usize {
+ // CHECK: %[[ADDR:.+]] = ptrtoint ptr %ptr to [[USIZE]]
+ // CHECK: %[[UP:.+]] = add [[USIZE]] %[[ADDR]], 31
+ // CHECK: %[[ALIGNED:.+]] = and [[USIZE]] %[[UP]], -32
+ // CHECK: %[[BOFFSET:.+]] = sub [[USIZE]] %[[ALIGNED]], %[[ADDR]]
+
+ // While we can always get a *byte* offset that will work, if the original
+ // pointer is unaligned it might be impossible to return an *element* offset
+ // that will make it aligned. We want it to be a `select`, not a `br`, so
+ // that the assembly will be branchless.
+ // CHECK: %[[LOW:.+]] = and [[USIZE]] %[[ADDR]], 3
+ // CHECK: %[[ORIGINAL_ALIGNED:.+]] = icmp eq [[USIZE]] %[[LOW]], 0
+ // CHECK: %[[OFFSET:.+]] = lshr exact [[USIZE]] %[[BOFFSET]], 2
+ // CHECK: %[[R:.+]] = select i1 %[[ORIGINAL_ALIGNED]], [[USIZE]] %[[OFFSET]], [[USIZE]] -1
+
+ // CHECK: ret [[USIZE]] %[[R]]
+ ptr.align_offset(32)
+}
diff --git a/tests/codegen/alloc-optimisation.rs b/tests/codegen/alloc-optimisation.rs
index c3ffaeb95..f88d695d8 100644
--- a/tests/codegen/alloc-optimisation.rs
+++ b/tests/codegen/alloc-optimisation.rs
@@ -1,12 +1,13 @@
//
// no-system-llvm
// compile-flags: -O
-#![crate_type="lib"]
+#![crate_type = "lib"]
#[no_mangle]
pub fn alloc_test(data: u32) {
// CHECK-LABEL: @alloc_test
// CHECK-NEXT: start:
+ // CHECK-NEXT: {{.*}} load volatile i8, ptr @__rust_no_alloc_shim_is_unstable, align 1
// CHECK-NEXT: ret void
let x = Box::new(data);
drop(x);
diff --git a/tests/codegen/array-map.rs b/tests/codegen/array-map.rs
index 7b8ab2c79..3706ddf99 100644
--- a/tests/codegen/array-map.rs
+++ b/tests/codegen/array-map.rs
@@ -21,7 +21,7 @@ pub fn short_integer_map(x: [u32; 8]) -> [u32; 8] {
pub fn short_integer_zip_map(x: [u32; 8], y: [u32; 8]) -> [u32; 8] {
// CHECK: %[[A:.+]] = load <8 x i32>
// CHECK: %[[B:.+]] = load <8 x i32>
- // CHECK: sub <8 x i32> %[[A]], %[[B]]
+ // CHECK: sub <8 x i32> %[[B]], %[[A]]
// CHECK: store <8 x i32>
x.zip(y).map(|(x, y)| x - y)
}
diff --git a/tests/codegen/ascii-char.rs b/tests/codegen/ascii-char.rs
new file mode 100644
index 000000000..4167becf5
--- /dev/null
+++ b/tests/codegen/ascii-char.rs
@@ -0,0 +1,37 @@
+// compile-flags: -C opt-level=1
+// ignore-debug (the extra assertions get in the way)
+
+#![crate_type = "lib"]
+#![feature(ascii_char)]
+
+use std::ascii::Char as AsciiChar;
+
+// CHECK-LABEL: i8 @unwrap_digit_from_remainder(i32
+#[no_mangle]
+pub fn unwrap_digit_from_remainder(v: u32) -> AsciiChar {
+ // CHECK-NOT: icmp
+ // CHECK-NOT: panic
+
+ // CHECK: %[[R:.+]] = urem i32 %v, 10
+ // CHECK-NEXT: %[[T:.+]] = trunc i32 %[[R]] to i8
+ // CHECK-NEXT: %[[D:.+]] = or i8 %[[T]], 48
+ // CHECK-NEXT: ret i8 %[[D]]
+
+ // CHECK-NOT: icmp
+ // CHECK-NOT: panic
+ AsciiChar::digit((v % 10) as u8).unwrap()
+}
+
+// CHECK-LABEL: i8 @unwrap_from_masked(i8
+#[no_mangle]
+pub fn unwrap_from_masked(b: u8) -> AsciiChar {
+ // CHECK-NOT: icmp
+ // CHECK-NOT: panic
+
+ // CHECK: %[[M:.+]] = and i8 %b, 127
+ // CHECK-NEXT: ret i8 %[[M]]
+
+ // CHECK-NOT: icmp
+ // CHECK-NOT: panic
+ AsciiChar::from_u8(b & 0x7f).unwrap()
+}
diff --git a/tests/codegen/binary-search-index-no-bound-check.rs b/tests/codegen/binary-search-index-no-bound-check.rs
index c1766a4a4..595969a89 100644
--- a/tests/codegen/binary-search-index-no-bound-check.rs
+++ b/tests/codegen/binary-search-index-no-bound-check.rs
@@ -9,7 +9,9 @@
#[no_mangle]
pub fn binary_search_index_no_bounds_check(s: &[u8]) -> u8 {
// CHECK-NOT: panic
- // CHECK-NOT: slice_index_len_fail
+ // CHECK-NOT: slice_start_index_len_fail
+ // CHECK-NOT: slice_end_index_len_fail
+ // CHECK-NOT: panic_bounds_check
if let Ok(idx) = s.binary_search(&b'\\') {
s[idx]
} else {
diff --git a/tests/codegen/call-llvm-intrinsics.rs b/tests/codegen/call-llvm-intrinsics.rs
index cb8abae19..11f291771 100644
--- a/tests/codegen/call-llvm-intrinsics.rs
+++ b/tests/codegen/call-llvm-intrinsics.rs
@@ -1,6 +1,7 @@
// compile-flags: -C no-prepopulate-passes -Copt-level=0
// ignore-riscv64
+// ignore-loongarch64
#![feature(link_llvm_intrinsics)]
#![crate_type = "lib"]
diff --git a/tests/codegen/catch-unwind.rs b/tests/codegen/catch-unwind.rs
index b90ef104c..6b63b83ef 100644
--- a/tests/codegen/catch-unwind.rs
+++ b/tests/codegen/catch-unwind.rs
@@ -10,6 +10,8 @@
// ignore-riscv64 FIXME
// On s390x the closure is also in another function
// ignore-s390x FIXME
+// On loongarch64 the closure is also in another function
+// ignore-loongarch64 FIXME
#![crate_type = "lib"]
#![feature(c_unwind)]
diff --git a/tests/codegen/debug-vtable.rs b/tests/codegen/debug-vtable.rs
index d82b737de..e52392b26 100644
--- a/tests/codegen/debug-vtable.rs
+++ b/tests/codegen/debug-vtable.rs
@@ -11,8 +11,6 @@
// Make sure that vtables don't have the unnamed_addr attribute when debuginfo is enabled.
// This helps debuggers more reliably map from dyn pointer to concrete type.
-// CHECK: @vtable.0 = private constant <{
-// CHECK: @vtable.1 = private constant <{
// CHECK: @vtable.2 = private constant <{
// CHECK: @vtable.3 = private constant <{
// CHECK: @vtable.4 = private constant <{
diff --git a/tests/codegen/debuginfo-constant-locals.rs b/tests/codegen/debuginfo-constant-locals.rs
new file mode 100644
index 000000000..95a1b8c9d
--- /dev/null
+++ b/tests/codegen/debuginfo-constant-locals.rs
@@ -0,0 +1,28 @@
+// compile-flags: -g -O
+
+// Check that simple constant values are preserved in debuginfo across both MIR opts and LLVM opts
+
+#![crate_type = "lib"]
+
+#[no_mangle]
+pub fn check_it() {
+ let a = 1;
+ let b = 42;
+
+ foo(a + b);
+}
+
+#[inline(never)]
+fn foo(x: i32) {
+ std::process::exit(x);
+}
+
+// CHECK-LABEL: @check_it
+// CHECK: call void @llvm.dbg.value(metadata i32 1, metadata ![[a_metadata:[0-9]+]], metadata !DIExpression())
+// CHECK: call void @llvm.dbg.value(metadata i32 42, metadata ![[b_metadata:[0-9]+]], metadata !DIExpression())
+
+// CHECK: ![[a_metadata]] = !DILocalVariable(name: "a"
+// CHECK-SAME: line: 9
+
+// CHECK: ![[b_metadata]] = !DILocalVariable(name: "b"
+// CHECK-SAME: line: 10
diff --git a/tests/codegen/drop-in-place-noalias.rs b/tests/codegen/drop-in-place-noalias.rs
new file mode 100644
index 000000000..725e6fc04
--- /dev/null
+++ b/tests/codegen/drop-in-place-noalias.rs
@@ -0,0 +1,38 @@
+// compile-flags: -O -C no-prepopulate-passes
+
+// Tests that the compiler can apply `noalias` and other &mut attributes to `drop_in_place`.
+// Note that non-Unpin types should not get `noalias`, matching &mut behavior.
+
+#![crate_type="lib"]
+
+use std::marker::PhantomPinned;
+
+// CHECK: define internal void @{{.*}}core{{.*}}ptr{{.*}}drop_in_place{{.*}}StructUnpin{{.*}}({{.*\*|ptr}} noalias noundef align 4 dereferenceable(12) %{{.+}})
+
+// CHECK: define internal void @{{.*}}core{{.*}}ptr{{.*}}drop_in_place{{.*}}StructNotUnpin{{.*}}({{.*\*|ptr}} noundef nonnull align 4 %{{.+}})
+
+pub struct StructUnpin {
+ a: i32,
+ b: i32,
+ c: i32,
+}
+
+impl Drop for StructUnpin {
+ fn drop(&mut self) {}
+}
+
+pub struct StructNotUnpin {
+ a: i32,
+ b: i32,
+ c: i32,
+ p: PhantomPinned,
+}
+
+impl Drop for StructNotUnpin {
+ fn drop(&mut self) {}
+}
+
+pub unsafe fn main(x: StructUnpin, y: StructNotUnpin) {
+ drop(x);
+ drop(y);
+}
diff --git a/tests/codegen/enable-lto-unit-splitting.rs b/tests/codegen/enable-lto-unit-splitting.rs
new file mode 100644
index 000000000..7daa05f69
--- /dev/null
+++ b/tests/codegen/enable-lto-unit-splitting.rs
@@ -0,0 +1,10 @@
+// Verifies that "EnableSplitLTOUnit" module flag is added.
+//
+// compile-flags: -Clto -Ctarget-feature=-crt-static -Zsplit-lto-unit
+
+#![crate_type="lib"]
+
+pub fn foo() {
+}
+
+// CHECK: !{{[0-9]+}} = !{i32 4, !"EnableSplitLTOUnit", i32 1}
diff --git a/tests/codegen/fewer-names.rs b/tests/codegen/fewer-names.rs
index 7f383a5c1..a09c79592 100644
--- a/tests/codegen/fewer-names.rs
+++ b/tests/codegen/fewer-names.rs
@@ -7,14 +7,14 @@
#[no_mangle]
pub fn sum(x: u32, y: u32) -> u32 {
-// YES-LABEL: define{{.*}}i32 @sum(i32 noundef %0, i32 noundef %1)
-// YES-NEXT: %3 = add i32 %1, %0
-// YES-NEXT: ret i32 %3
+ // YES-LABEL: define{{.*}}i32 @sum(i32 noundef %0, i32 noundef %1)
+ // YES-NEXT: %3 = add i32 %1, %0
+ // YES-NEXT: ret i32 %3
-// NO-LABEL: define{{.*}}i32 @sum(i32 noundef %x, i32 noundef %y)
-// NO-NEXT: start:
-// NO-NEXT: %0 = add i32 %y, %x
-// NO-NEXT: ret i32 %0
+ // NO-LABEL: define{{.*}}i32 @sum(i32 noundef %x, i32 noundef %y)
+ // NO-NEXT: start:
+ // NO-NEXT: %0 = add i32 %y, %x
+ // NO-NEXT: ret i32 %0
let z = x + y;
z
}
diff --git a/tests/codegen/global_asm.rs b/tests/codegen/global_asm.rs
index 9912b1e75..41a99530a 100644
--- a/tests/codegen/global_asm.rs
+++ b/tests/codegen/global_asm.rs
@@ -18,6 +18,7 @@
// ignore-wasm32
// ignore-wasm64
// ignore-emscripten
+// ignore-loongarch64
// compile-flags: -C no-prepopulate-passes
#![crate_type = "lib"]
diff --git a/tests/codegen/global_asm_include.rs b/tests/codegen/global_asm_include.rs
index b68c5ad3b..e25c164f4 100644
--- a/tests/codegen/global_asm_include.rs
+++ b/tests/codegen/global_asm_include.rs
@@ -18,6 +18,7 @@
// ignore-wasm32
// ignore-wasm64
// ignore-emscripten
+// ignore-loongarch64
// compile-flags: -C no-prepopulate-passes
#![crate_type = "lib"]
diff --git a/tests/codegen/global_asm_x2.rs b/tests/codegen/global_asm_x2.rs
index d87e02bef..71ecef124 100644
--- a/tests/codegen/global_asm_x2.rs
+++ b/tests/codegen/global_asm_x2.rs
@@ -18,6 +18,7 @@
// ignore-wasm32
// ignore-wasm64
// ignore-emscripten
+// ignore-loongarch64
// compile-flags: -C no-prepopulate-passes
#![crate_type = "lib"]
diff --git a/tests/codegen/inline-hint.rs b/tests/codegen/inline-hint.rs
index d3ea1915a..bb2a8e6a6 100644
--- a/tests/codegen/inline-hint.rs
+++ b/tests/codegen/inline-hint.rs
@@ -1,7 +1,7 @@
// Checks that closures, constructors, and shims except
// for a drop glue receive inline hint by default.
//
-// compile-flags: -Cno-prepopulate-passes -Csymbol-mangling-version=v0
+// compile-flags: -Cno-prepopulate-passes -Csymbol-mangling-version=v0 -Zinline-mir=no
#![crate_type = "lib"]
pub fn f() {
diff --git a/tests/codegen/intrinsics/offset.rs b/tests/codegen/intrinsics/offset.rs
new file mode 100644
index 000000000..7fc4f4498
--- /dev/null
+++ b/tests/codegen/intrinsics/offset.rs
@@ -0,0 +1,34 @@
+// compile-flags: -O -C no-prepopulate-passes
+// min-llvm-version: 15.0 (because we're using opaque pointers)
+
+#![crate_type = "lib"]
+#![feature(core_intrinsics)]
+
+use std::intrinsics::offset;
+
+// CHECK-LABEL: ptr @offset_zst
+// CHECK-SAME: (ptr noundef %p, [[SIZE:i[0-9]+]] noundef %d)
+#[no_mangle]
+pub unsafe fn offset_zst(p: *const (), d: usize) -> *const () {
+ // CHECK-NOT: getelementptr
+ // CHECK: ret ptr %p
+ offset(p, d)
+}
+
+// CHECK-LABEL: ptr @offset_isize
+// CHECK-SAME: (ptr noundef %p, [[SIZE]] noundef %d)
+#[no_mangle]
+pub unsafe fn offset_isize(p: *const u32, d: isize) -> *const u32 {
+ // CHECK: %[[R:.*]] = getelementptr inbounds i32, ptr %p, [[SIZE]] %d
+ // CHECK-NEXT: ret ptr %[[R]]
+ offset(p, d)
+}
+
+// CHECK-LABEL: ptr @offset_usize
+// CHECK-SAME: (ptr noundef %p, [[SIZE]] noundef %d)
+#[no_mangle]
+pub unsafe fn offset_usize(p: *const u64, d: usize) -> *const u64 {
+ // CHECK: %[[R:.*]] = getelementptr inbounds i64, ptr %p, [[SIZE]] %d
+ // CHECK-NEXT: ret ptr %[[R]]
+ offset(p, d)
+}
diff --git a/tests/codegen/intrinsics/transmute-niched.rs b/tests/codegen/intrinsics/transmute-niched.rs
new file mode 100644
index 000000000..69e9b1d12
--- /dev/null
+++ b/tests/codegen/intrinsics/transmute-niched.rs
@@ -0,0 +1,184 @@
+// revisions: OPT DBG
+// [OPT] compile-flags: -C opt-level=3 -C no-prepopulate-passes
+// [DBG] compile-flags: -C opt-level=0 -C no-prepopulate-passes
+// only-64bit (so I don't need to worry about usize)
+// min-llvm-version: 15.0 # this test assumes `ptr`s
+
+#![crate_type = "lib"]
+
+use std::mem::transmute;
+use std::num::NonZeroU32;
+
+#[repr(u8)]
+pub enum SmallEnum {
+ A = 10,
+ B = 11,
+ C = 12,
+}
+
+// CHECK-LABEL: @check_to_enum(
+#[no_mangle]
+pub unsafe fn check_to_enum(x: i8) -> SmallEnum {
+ // OPT: %0 = icmp uge i8 %x, 10
+ // OPT: call void @llvm.assume(i1 %0)
+ // OPT: %1 = icmp ule i8 %x, 12
+ // OPT: call void @llvm.assume(i1 %1)
+ // DBG-NOT: icmp
+ // DBG-NOT: assume
+ // CHECK: ret i8 %x
+
+ transmute(x)
+}
+
+// CHECK-LABEL: @check_from_enum(
+#[no_mangle]
+pub unsafe fn check_from_enum(x: SmallEnum) -> i8 {
+ // OPT: %0 = icmp uge i8 %x, 10
+ // OPT: call void @llvm.assume(i1 %0)
+ // OPT: %1 = icmp ule i8 %x, 12
+ // OPT: call void @llvm.assume(i1 %1)
+ // DBG-NOT: icmp
+ // DBG-NOT: assume
+ // CHECK: ret i8 %x
+
+ transmute(x)
+}
+
+// CHECK-LABEL: @check_to_ordering(
+#[no_mangle]
+pub unsafe fn check_to_ordering(x: u8) -> std::cmp::Ordering {
+ // OPT: %0 = icmp uge i8 %x, -1
+ // OPT: %1 = icmp ule i8 %x, 1
+ // OPT: %2 = or i1 %0, %1
+ // OPT: call void @llvm.assume(i1 %2)
+ // DBG-NOT: icmp
+ // DBG-NOT: assume
+ // CHECK: ret i8 %x
+
+ transmute(x)
+}
+
+// CHECK-LABEL: @check_from_ordering(
+#[no_mangle]
+pub unsafe fn check_from_ordering(x: std::cmp::Ordering) -> u8 {
+ // OPT: %0 = icmp uge i8 %x, -1
+ // OPT: %1 = icmp ule i8 %x, 1
+ // OPT: %2 = or i1 %0, %1
+ // OPT: call void @llvm.assume(i1 %2)
+ // DBG-NOT: icmp
+ // DBG-NOT: assume
+ // CHECK: ret i8 %x
+
+ transmute(x)
+}
+
+#[repr(i32)]
+pub enum Minus100ToPlus100 {
+ A = -100,
+ B = -90,
+ C = -80,
+ D = -70,
+ E = -60,
+ F = -50,
+ G = -40,
+ H = -30,
+ I = -20,
+ J = -10,
+ K = 0,
+ L = 10,
+ M = 20,
+ N = 30,
+ O = 40,
+ P = 50,
+ Q = 60,
+ R = 70,
+ S = 80,
+ T = 90,
+ U = 100,
+}
+
+// CHECK-LABEL: @check_enum_from_char(
+#[no_mangle]
+pub unsafe fn check_enum_from_char(x: char) -> Minus100ToPlus100 {
+ // OPT: %0 = icmp ule i32 %x, 1114111
+ // OPT: call void @llvm.assume(i1 %0)
+ // OPT: %1 = icmp uge i32 %x, -100
+ // OPT: %2 = icmp ule i32 %x, 100
+ // OPT: %3 = or i1 %1, %2
+ // OPT: call void @llvm.assume(i1 %3)
+ // DBG-NOT: icmp
+ // DBG-NOT: assume
+ // CHECK: ret i32 %x
+
+ transmute(x)
+}
+
+// CHECK-LABEL: @check_enum_to_char(
+#[no_mangle]
+pub unsafe fn check_enum_to_char(x: Minus100ToPlus100) -> char {
+ // OPT: %0 = icmp uge i32 %x, -100
+ // OPT: %1 = icmp ule i32 %x, 100
+ // OPT: %2 = or i1 %0, %1
+ // OPT: call void @llvm.assume(i1 %2)
+ // OPT: %3 = icmp ule i32 %x, 1114111
+ // OPT: call void @llvm.assume(i1 %3)
+ // DBG-NOT: icmp
+ // DBG-NOT: assume
+ // CHECK: ret i32 %x
+
+ transmute(x)
+}
+
+// CHECK-LABEL: @check_swap_pair(
+#[no_mangle]
+pub unsafe fn check_swap_pair(x: (char, NonZeroU32)) -> (NonZeroU32, char) {
+ // OPT: %0 = icmp ule i32 %x.0, 1114111
+ // OPT: call void @llvm.assume(i1 %0)
+ // OPT: %1 = icmp uge i32 %x.0, 1
+ // OPT: call void @llvm.assume(i1 %1)
+ // OPT: %2 = icmp uge i32 %x.1, 1
+ // OPT: call void @llvm.assume(i1 %2)
+ // OPT: %3 = icmp ule i32 %x.1, 1114111
+ // OPT: call void @llvm.assume(i1 %3)
+ // DBG-NOT: icmp
+ // DBG-NOT: assume
+ // CHECK: %[[P1:.+]] = insertvalue { i32, i32 } poison, i32 %x.0, 0
+ // CHECK: %[[P2:.+]] = insertvalue { i32, i32 } %[[P1]], i32 %x.1, 1
+ // CHECK: ret { i32, i32 } %[[P2]]
+
+ transmute(x)
+}
+
+// CHECK-LABEL: @check_bool_from_ordering(
+#[no_mangle]
+pub unsafe fn check_bool_from_ordering(x: std::cmp::Ordering) -> bool {
+ // OPT: %0 = icmp uge i8 %x, -1
+ // OPT: %1 = icmp ule i8 %x, 1
+ // OPT: %2 = or i1 %0, %1
+ // OPT: call void @llvm.assume(i1 %2)
+ // OPT: %3 = icmp ule i8 %x, 1
+ // OPT: call void @llvm.assume(i1 %3)
+ // DBG-NOT: icmp
+ // DBG-NOT: assume
+ // CHECK: %[[R:.+]] = trunc i8 %x to i1
+ // CHECK: ret i1 %[[R]]
+
+ transmute(x)
+}
+
+// CHECK-LABEL: @check_bool_to_ordering(
+#[no_mangle]
+pub unsafe fn check_bool_to_ordering(x: bool) -> std::cmp::Ordering {
+ // CHECK: %0 = zext i1 %x to i8
+ // OPT: %1 = icmp ule i8 %0, 1
+ // OPT: call void @llvm.assume(i1 %1)
+ // OPT: %2 = icmp uge i8 %0, -1
+ // OPT: %3 = icmp ule i8 %0, 1
+ // OPT: %4 = or i1 %2, %3
+ // OPT: call void @llvm.assume(i1 %4)
+ // DBG-NOT: icmp
+ // DBG-NOT: assume
+ // CHECK: ret i8 %0
+
+ transmute(x)
+}
diff --git a/tests/codegen/intrinsics/transmute.rs b/tests/codegen/intrinsics/transmute.rs
index 57f901c67..664e697c2 100644
--- a/tests/codegen/intrinsics/transmute.rs
+++ b/tests/codegen/intrinsics/transmute.rs
@@ -8,10 +8,10 @@
#![feature(inline_const)]
#![allow(unreachable_code)]
-use std::mem::{transmute, MaybeUninit};
+use std::mem::MaybeUninit;
+use std::intrinsics::{transmute, transmute_unchecked};
-// Some of the cases here are statically rejected by `mem::transmute`, so
-// we need to generate custom MIR for those cases to get to codegen.
+// Some of these need custom MIR to not get removed by MIR optimizations.
use std::intrinsics::mir::*;
enum Never {}
@@ -30,59 +30,35 @@ pub struct Aggregate8(u8);
// CHECK-LABEL: @check_bigger_size(
#[no_mangle]
-#[custom_mir(dialect = "runtime", phase = "initial")]
pub unsafe fn check_bigger_size(x: u16) -> u32 {
// CHECK: call void @llvm.trap
- mir!{
- {
- RET = CastTransmute(x);
- Return()
- }
- }
+ transmute_unchecked(x)
}
// CHECK-LABEL: @check_smaller_size(
#[no_mangle]
-#[custom_mir(dialect = "runtime", phase = "initial")]
pub unsafe fn check_smaller_size(x: u32) -> u16 {
// CHECK: call void @llvm.trap
- mir!{
- {
- RET = CastTransmute(x);
- Return()
- }
- }
+ transmute_unchecked(x)
}
// CHECK-LABEL: @check_smaller_array(
#[no_mangle]
-#[custom_mir(dialect = "runtime", phase = "initial")]
pub unsafe fn check_smaller_array(x: [u32; 7]) -> [u32; 3] {
// CHECK: call void @llvm.trap
- mir!{
- {
- RET = CastTransmute(x);
- Return()
- }
- }
+ transmute_unchecked(x)
}
// CHECK-LABEL: @check_bigger_array(
#[no_mangle]
-#[custom_mir(dialect = "runtime", phase = "initial")]
pub unsafe fn check_bigger_array(x: [u32; 3]) -> [u32; 7] {
// CHECK: call void @llvm.trap
- mir!{
- {
- RET = CastTransmute(x);
- Return()
- }
- }
+ transmute_unchecked(x)
}
// CHECK-LABEL: @check_to_uninhabited(
#[no_mangle]
-#[custom_mir(dialect = "runtime", phase = "initial")]
+#[custom_mir(dialect = "runtime", phase = "optimized")]
pub unsafe fn check_to_uninhabited(x: u16) -> BigNever {
// CHECK: call void @llvm.trap
mir!{
@@ -95,7 +71,7 @@ pub unsafe fn check_to_uninhabited(x: u16) -> BigNever {
// CHECK-LABEL: @check_from_uninhabited(
#[no_mangle]
-#[custom_mir(dialect = "runtime", phase = "initial")]
+#[custom_mir(dialect = "runtime", phase = "optimized")]
pub unsafe fn check_from_uninhabited(x: BigNever) -> u16 {
// CHECK: ret i16 poison
mir!{
@@ -169,8 +145,8 @@ pub unsafe fn check_aggregate_from_bool(x: bool) -> Aggregate8 {
#[no_mangle]
pub unsafe fn check_byte_to_bool(x: u8) -> bool {
// CHECK-NOT: alloca
- // CHECK: %0 = trunc i8 %x to i1
- // CHECK: ret i1 %0
+ // CHECK: %[[R:.+]] = trunc i8 %x to i1
+ // CHECK: ret i1 %[[R]]
transmute(x)
}
@@ -178,8 +154,8 @@ pub unsafe fn check_byte_to_bool(x: u8) -> bool {
#[no_mangle]
pub unsafe fn check_byte_from_bool(x: bool) -> u8 {
// CHECK-NOT: alloca
- // CHECK: %0 = zext i1 %x to i8
- // CHECK: ret i8 %0
+ // CHECK: %[[R:.+]] = zext i1 %x to i8
+ // CHECK: ret i8 %[[R:.+]]
transmute(x)
}
diff --git a/tests/codegen/issues/issue-103840.rs b/tests/codegen/issues/issue-103840.rs
index f19d7031b..da64692d2 100644
--- a/tests/codegen/issues/issue-103840.rs
+++ b/tests/codegen/issues/issue-103840.rs
@@ -1,4 +1,5 @@
// compile-flags: -O
+// min-llvm-version: 16.0
#![crate_type = "lib"]
pub fn foo(t: &mut Vec<usize>) {
diff --git a/tests/codegen/issues/issue-105386-ub-in-debuginfo.rs b/tests/codegen/issues/issue-105386-ub-in-debuginfo.rs
index d54ac9e33..2ee4d7cca 100644
--- a/tests/codegen/issues/issue-105386-ub-in-debuginfo.rs
+++ b/tests/codegen/issues/issue-105386-ub-in-debuginfo.rs
@@ -19,4 +19,5 @@ pub fn outer_function(x: S, y: S) -> usize {
// CHECK-NOT: [[ptr_tmp:%.*]] = getelementptr inbounds %"[closure@{{.*.rs}}:9:23: 9:25]", ptr [[spill]]
// CHECK-NOT: [[load:%.*]] = load ptr, ptr
// CHECK: call void @llvm.lifetime.start{{.*}}({{.*}}, ptr [[spill]])
-// CHECK: call void @llvm.memcpy{{.*}}(ptr {{align .*}} [[spill]], ptr {{align .*}} %x
+// CHECK: [[inner:%.*]] = getelementptr inbounds %"{{.*}}", ptr [[spill]]
+// CHECK: call void @llvm.memcpy{{.*}}(ptr {{align .*}} [[inner]], ptr {{align .*}} %x
diff --git a/tests/codegen/issues/issue-111603.rs b/tests/codegen/issues/issue-111603.rs
new file mode 100644
index 000000000..90b3c314d
--- /dev/null
+++ b/tests/codegen/issues/issue-111603.rs
@@ -0,0 +1,28 @@
+// compile-flags: -O
+
+#![crate_type = "lib"]
+#![feature(get_mut_unchecked, new_uninit)]
+
+use std::sync::Arc;
+
+// CHECK-LABEL: @new_uninit
+#[no_mangle]
+pub fn new_uninit(x: u64) -> Arc<[u64; 1000]> {
+ // CHECK: call alloc::sync::arcinner_layout_for_value_layout
+ // CHECK-NOT: call alloc::sync::arcinner_layout_for_value_layout
+ let mut arc = Arc::new_uninit();
+ unsafe { Arc::get_mut_unchecked(&mut arc) }.write([x; 1000]);
+ unsafe { arc.assume_init() }
+}
+
+// CHECK-LABEL: @new_uninit_slice
+#[no_mangle]
+pub fn new_uninit_slice(x: u64) -> Arc<[u64]> {
+ // CHECK: call alloc::sync::arcinner_layout_for_value_layout
+ // CHECK-NOT: call alloc::sync::arcinner_layout_for_value_layout
+ let mut arc = Arc::new_uninit_slice(1000);
+ for elem in unsafe { Arc::get_mut_unchecked(&mut arc) } {
+ elem.write(x);
+ }
+ unsafe { arc.assume_init() }
+}
diff --git a/tests/codegen/issues/issue-73396-bounds-check-after-position.rs b/tests/codegen/issues/issue-73396-bounds-check-after-position.rs
index 8d07a67a1..2d7797887 100644
--- a/tests/codegen/issues/issue-73396-bounds-check-after-position.rs
+++ b/tests/codegen/issues/issue-73396-bounds-check-after-position.rs
@@ -9,7 +9,10 @@
#[no_mangle]
pub fn position_slice_to_no_bounds_check(s: &[u8]) -> &[u8] {
// CHECK-NOT: panic
- // CHECK-NOT: slice_index_len_fail
+ // CHECK-NOT: slice_start_index_len_fail
+ // CHECK-NOT: slice_end_index_len_fail
+ // CHECK-NOT: panic_bounds_check
+ // CHECK-NOT: unreachable
if let Some(idx) = s.iter().position(|b| *b == b'\\') {
&s[..idx]
} else {
@@ -21,7 +24,10 @@ pub fn position_slice_to_no_bounds_check(s: &[u8]) -> &[u8] {
#[no_mangle]
pub fn position_slice_from_no_bounds_check(s: &[u8]) -> &[u8] {
// CHECK-NOT: panic
- // CHECK-NOT: slice_index_len_fail
+ // CHECK-NOT: slice_start_index_len_fail
+ // CHECK-NOT: slice_end_index_len_fail
+ // CHECK-NOT: panic_bounds_check
+ // CHECK-NOT: unreachable
if let Some(idx) = s.iter().position(|b| *b == b'\\') {
&s[idx..]
} else {
@@ -33,7 +39,10 @@ pub fn position_slice_from_no_bounds_check(s: &[u8]) -> &[u8] {
#[no_mangle]
pub fn position_index_no_bounds_check(s: &[u8]) -> u8 {
// CHECK-NOT: panic
- // CHECK-NOT: slice_index_len_fail
+ // CHECK-NOT: slice_start_index_len_fail
+ // CHECK-NOT: slice_end_index_len_fail
+ // CHECK-NOT: panic_bounds_check
+ // CHECK-NOT: unreachable
if let Some(idx) = s.iter().position(|b| *b == b'\\') {
s[idx]
} else {
@@ -44,7 +53,10 @@ pub fn position_index_no_bounds_check(s: &[u8]) -> u8 {
#[no_mangle]
pub fn rposition_slice_to_no_bounds_check(s: &[u8]) -> &[u8] {
// CHECK-NOT: panic
- // CHECK-NOT: slice_index_len_fail
+ // CHECK-NOT: slice_start_index_len_fail
+ // CHECK-NOT: slice_end_index_len_fail
+ // CHECK-NOT: panic_bounds_check
+ // CHECK-NOT: unreachable
if let Some(idx) = s.iter().rposition(|b| *b == b'\\') {
&s[..idx]
} else {
@@ -56,7 +68,10 @@ pub fn rposition_slice_to_no_bounds_check(s: &[u8]) -> &[u8] {
#[no_mangle]
pub fn rposition_slice_from_no_bounds_check(s: &[u8]) -> &[u8] {
// CHECK-NOT: panic
- // CHECK-NOT: slice_index_len_fail
+ // CHECK-NOT: slice_start_index_len_fail
+ // CHECK-NOT: slice_end_index_len_fail
+ // CHECK-NOT: panic_bounds_check
+ // CHECK-NOT: unreachable
if let Some(idx) = s.iter().rposition(|b| *b == b'\\') {
&s[idx..]
} else {
@@ -68,7 +83,10 @@ pub fn rposition_slice_from_no_bounds_check(s: &[u8]) -> &[u8] {
#[no_mangle]
pub fn rposition_index_no_bounds_check(s: &[u8]) -> u8 {
// CHECK-NOT: panic
- // CHECK-NOT: slice_index_len_fail
+ // CHECK-NOT: slice_start_index_len_fail
+ // CHECK-NOT: slice_end_index_len_fail
+ // CHECK-NOT: panic_bounds_check
+ // CHECK-NOT: unreachable
if let Some(idx) = s.iter().rposition(|b| *b == b'\\') {
s[idx]
} else {
diff --git a/tests/codegen/issues/issue-86106.rs b/tests/codegen/issues/issue-86106.rs
index 9ccbcb24f..c0be7fab2 100644
--- a/tests/codegen/issues/issue-86106.rs
+++ b/tests/codegen/issues/issue-86106.rs
@@ -1,4 +1,5 @@
// min-llvm-version: 15.0
+// only-64bit llvm appears to use stores instead of memset on 32bit
// compile-flags: -C opt-level=3 -Z merge-functions=disabled
// The below two functions ensure that both `String::new()` and `"".to_string()`
@@ -9,12 +10,9 @@
// CHECK-LABEL: define void @string_new
#[no_mangle]
pub fn string_new() -> String {
- // CHECK-NOT: load i8
- // CHECK: store i{{32|64}}
+ // CHECK: store ptr inttoptr
// CHECK-NEXT: getelementptr
- // CHECK-NEXT: store ptr
- // CHECK-NEXT: getelementptr
- // CHECK-NEXT: store i{{32|64}}
+ // CHECK-NEXT: call void @llvm.memset
// CHECK-NEXT: ret void
String::new()
}
@@ -22,12 +20,9 @@ pub fn string_new() -> String {
// CHECK-LABEL: define void @empty_to_string
#[no_mangle]
pub fn empty_to_string() -> String {
- // CHECK-NOT: load i8
- // CHECK: store i{{32|64}}
- // CHECK-NEXT: getelementptr
- // CHECK-NEXT: store ptr
+ // CHECK: store ptr inttoptr
// CHECK-NEXT: getelementptr
- // CHECK-NEXT: store i{{32|64}}
+ // CHECK-NEXT: call void @llvm.memset
// CHECK-NEXT: ret void
"".to_string()
}
@@ -38,12 +33,9 @@ pub fn empty_to_string() -> String {
// CHECK-LABEL: @empty_vec
#[no_mangle]
pub fn empty_vec() -> Vec<u8> {
- // CHECK: store i{{32|64}}
- // CHECK-NOT: load i8
+ // CHECK: store ptr inttoptr
// CHECK-NEXT: getelementptr
- // CHECK-NEXT: store ptr
- // CHECK-NEXT: getelementptr
- // CHECK-NEXT: store i{{32|64}}
+ // CHECK-NEXT: call void @llvm.memset
// CHECK-NEXT: ret void
vec![]
}
@@ -51,12 +43,9 @@ pub fn empty_vec() -> Vec<u8> {
// CHECK-LABEL: @empty_vec_clone
#[no_mangle]
pub fn empty_vec_clone() -> Vec<u8> {
- // CHECK: store i{{32|64}}
- // CHECK-NOT: load i8
- // CHECK-NEXT: getelementptr
- // CHECK-NEXT: store ptr
+ // CHECK: store ptr inttoptr
// CHECK-NEXT: getelementptr
- // CHECK-NEXT: store i{{32|64}}
+ // CHECK-NEXT: call void @llvm.memset
// CHECK-NEXT: ret void
vec![].clone()
}
diff --git a/tests/codegen/local-generics-in-exe-internalized.rs b/tests/codegen/local-generics-in-exe-internalized.rs
index e5430fbf1..449c5ca75 100644
--- a/tests/codegen/local-generics-in-exe-internalized.rs
+++ b/tests/codegen/local-generics-in-exe-internalized.rs
@@ -1,4 +1,4 @@
-// compile-flags: -C no-prepopulate-passes -Zshare-generics=yes
+// compile-flags: -C no-prepopulate-passes -Zshare-generics=yes -Zinline-mir=no
// Check that local generics are internalized if they are in the same CGU
diff --git a/tests/codegen/loongarch-abi/call-llvm-intrinsics.rs b/tests/codegen/loongarch-abi/call-llvm-intrinsics.rs
new file mode 100644
index 000000000..4b78f6e24
--- /dev/null
+++ b/tests/codegen/loongarch-abi/call-llvm-intrinsics.rs
@@ -0,0 +1,31 @@
+// compile-flags: -C no-prepopulate-passes
+
+// only-loongarch64
+
+#![feature(link_llvm_intrinsics)]
+#![crate_type = "lib"]
+
+struct A;
+
+impl Drop for A {
+ fn drop(&mut self) {
+ println!("A");
+ }
+}
+
+extern "C" {
+ #[link_name = "llvm.sqrt.f32"]
+ fn sqrt(x: f32) -> f32;
+}
+
+pub fn do_call() {
+ let _a = A;
+
+ unsafe {
+ // Ensure that we `call` LLVM intrinsics instead of trying to `invoke` them
+ // CHECK: store float 4.000000e+00, ptr %{{.}}, align 4
+ // CHECK: load float, ptr %{{.}}, align 4
+ // CHECK: call float @llvm.sqrt.f32(float %{{.}}
+ sqrt(4.0);
+ }
+}
diff --git a/tests/codegen/loongarch-abi/loongarch64-lp64d-abi.rs b/tests/codegen/loongarch-abi/loongarch64-lp64d-abi.rs
new file mode 100644
index 000000000..7555553c2
--- /dev/null
+++ b/tests/codegen/loongarch-abi/loongarch64-lp64d-abi.rs
@@ -0,0 +1,293 @@
+// compile-flags: -C no-prepopulate-passes
+// only-loongarch64
+// only-linux
+
+#![crate_type = "lib"]
+
+// CHECK: define void @f_fpr_tracking(double %0, double %1, double %2, double %3, double %4, double %5, double %6, double %7, i8 noundef zeroext %i)
+#[no_mangle]
+pub extern "C" fn f_fpr_tracking(
+ a: f64,
+ b: f64,
+ c: f64,
+ d: f64,
+ e: f64,
+ f: f64,
+ g: f64,
+ h: f64,
+ i: u8,
+) {
+}
+
+#[repr(C)]
+pub struct Double {
+ f: f64,
+}
+
+#[repr(C)]
+pub struct DoubleDouble {
+ f: f64,
+ g: f64,
+}
+
+#[repr(C)]
+pub struct DoubleFloat {
+ f: f64,
+ g: f32,
+}
+
+// CHECK: define void @f_double_s_arg(double %0)
+#[no_mangle]
+pub extern "C" fn f_double_s_arg(a: Double) {}
+
+// CHECK: define double @f_ret_double_s()
+#[no_mangle]
+pub extern "C" fn f_ret_double_s() -> Double {
+ Double { f: 1. }
+}
+
+// CHECK: define void @f_double_double_s_arg({ double, double } %0)
+#[no_mangle]
+pub extern "C" fn f_double_double_s_arg(a: DoubleDouble) {}
+
+// CHECK: define { double, double } @f_ret_double_double_s()
+#[no_mangle]
+pub extern "C" fn f_ret_double_double_s() -> DoubleDouble {
+ DoubleDouble { f: 1., g: 2. }
+}
+
+// CHECK: define void @f_double_float_s_arg({ double, float } %0)
+#[no_mangle]
+pub extern "C" fn f_double_float_s_arg(a: DoubleFloat) {}
+
+// CHECK: define { double, float } @f_ret_double_float_s()
+#[no_mangle]
+pub extern "C" fn f_ret_double_float_s() -> DoubleFloat {
+ DoubleFloat { f: 1., g: 2. }
+}
+
+// CHECK: define void @f_double_double_s_arg_insufficient_fprs(double %0, double %1, double %2, double %3, double %4, double %5, double %6, [2 x i64] %7)
+#[no_mangle]
+pub extern "C" fn f_double_double_s_arg_insufficient_fprs(
+ a: f64,
+ b: f64,
+ c: f64,
+ d: f64,
+ e: f64,
+ f: f64,
+ g: f64,
+ h: DoubleDouble,
+) {
+}
+
+#[repr(C)]
+pub struct DoubleInt8 {
+ f: f64,
+ i: i8,
+}
+
+#[repr(C)]
+pub struct DoubleUInt8 {
+ f: f64,
+ i: u8,
+}
+
+#[repr(C)]
+pub struct DoubleInt32 {
+ f: f64,
+ i: i32,
+}
+
+#[repr(C)]
+pub struct DoubleInt64 {
+ f: f64,
+ i: i64,
+}
+
+// CHECK: define void @f_double_int8_s_arg({ double, i8 } %0)
+#[no_mangle]
+pub extern "C" fn f_double_int8_s_arg(a: DoubleInt8) {}
+
+// CHECK: define { double, i8 } @f_ret_double_int8_s()
+#[no_mangle]
+pub extern "C" fn f_ret_double_int8_s() -> DoubleInt8 {
+ DoubleInt8 { f: 1., i: 2 }
+}
+
+// CHECK: define void @f_double_int32_s_arg({ double, i32 } %0)
+#[no_mangle]
+pub extern "C" fn f_double_int32_s_arg(a: DoubleInt32) {}
+
+// CHECK: define { double, i32 } @f_ret_double_int32_s()
+#[no_mangle]
+pub extern "C" fn f_ret_double_int32_s() -> DoubleInt32 {
+ DoubleInt32 { f: 1., i: 2 }
+}
+
+// CHECK: define void @f_double_uint8_s_arg({ double, i8 } %0)
+#[no_mangle]
+pub extern "C" fn f_double_uint8_s_arg(a: DoubleUInt8) {}
+
+// CHECK: define { double, i8 } @f_ret_double_uint8_s()
+#[no_mangle]
+pub extern "C" fn f_ret_double_uint8_s() -> DoubleUInt8 {
+ DoubleUInt8 { f: 1., i: 2 }
+}
+
+// CHECK: define void @f_double_int64_s_arg({ double, i64 } %0)
+#[no_mangle]
+pub extern "C" fn f_double_int64_s_arg(a: DoubleInt64) {}
+
+// CHECK: define { double, i64 } @f_ret_double_int64_s()
+#[no_mangle]
+pub extern "C" fn f_ret_double_int64_s() -> DoubleInt64 {
+ DoubleInt64 { f: 1., i: 2 }
+}
+
+// CHECK: define void @f_double_int8_s_arg_insufficient_gprs(i32 noundef signext %a, i32 noundef signext %b, i32 noundef signext %c, i32 noundef signext %d, i32 noundef signext %e, i32 noundef signext %f, i32 noundef signext %g, i32 noundef signext %h, [2 x i64] %0)
+#[no_mangle]
+pub extern "C" fn f_double_int8_s_arg_insufficient_gprs(
+ a: i32,
+ b: i32,
+ c: i32,
+ d: i32,
+ e: i32,
+ f: i32,
+ g: i32,
+ h: i32,
+ i: DoubleInt8,
+) {
+}
+
+// CHECK: define void @f_struct_double_int8_insufficient_fprs(float %0, double %1, double %2, double %3, double %4, double %5, double %6, double %7, [2 x i64] %8)
+#[no_mangle]
+pub extern "C" fn f_struct_double_int8_insufficient_fprs(
+ a: f32,
+ b: f64,
+ c: f64,
+ d: f64,
+ e: f64,
+ f: f64,
+ g: f64,
+ h: f64,
+ i: DoubleInt8,
+) {
+}
+
+#[repr(C)]
+pub struct DoubleArr1 {
+ a: [f64; 1],
+}
+
+// CHECK: define void @f_doublearr1_s_arg(double %0)
+#[no_mangle]
+pub extern "C" fn f_doublearr1_s_arg(a: DoubleArr1) {}
+
+// CHECK: define double @f_ret_doublearr1_s()
+#[no_mangle]
+pub extern "C" fn f_ret_doublearr1_s() -> DoubleArr1 {
+ DoubleArr1 { a: [1.] }
+}
+
+#[repr(C)]
+pub struct DoubleArr2 {
+ a: [f64; 2],
+}
+
+// CHECK: define void @f_doublearr2_s_arg({ double, double } %0)
+#[no_mangle]
+pub extern "C" fn f_doublearr2_s_arg(a: DoubleArr2) {}
+
+// CHECK: define { double, double } @f_ret_doublearr2_s()
+#[no_mangle]
+pub extern "C" fn f_ret_doublearr2_s() -> DoubleArr2 {
+ DoubleArr2 { a: [1., 2.] }
+}
+
+#[repr(C)]
+pub struct Tricky1 {
+ f: [f64; 1],
+}
+
+#[repr(C)]
+pub struct DoubleArr2Tricky1 {
+ g: [Tricky1; 2],
+}
+
+// CHECK: define void @f_doublearr2_tricky1_s_arg({ double, double } %0)
+#[no_mangle]
+pub extern "C" fn f_doublearr2_tricky1_s_arg(a: DoubleArr2Tricky1) {}
+
+// CHECK: define { double, double } @f_ret_doublearr2_tricky1_s()
+#[no_mangle]
+pub extern "C" fn f_ret_doublearr2_tricky1_s() -> DoubleArr2Tricky1 {
+ DoubleArr2Tricky1 { g: [Tricky1 { f: [1.] }, Tricky1 { f: [2.] }] }
+}
+
+#[repr(C)]
+pub struct EmptyStruct {}
+
+#[repr(C)]
+pub struct DoubleArr2Tricky2 {
+ s: EmptyStruct,
+ g: [Tricky1; 2],
+}
+
+// CHECK: define void @f_doublearr2_tricky2_s_arg({ double, double } %0)
+#[no_mangle]
+pub extern "C" fn f_doublearr2_tricky2_s_arg(a: DoubleArr2Tricky2) {}
+
+// CHECK: define { double, double } @f_ret_doublearr2_tricky2_s()
+#[no_mangle]
+pub extern "C" fn f_ret_doublearr2_tricky2_s() -> DoubleArr2Tricky2 {
+ DoubleArr2Tricky2 { s: EmptyStruct {}, g: [Tricky1 { f: [1.] }, Tricky1 { f: [2.] }] }
+}
+
+#[repr(C)]
+pub struct IntDoubleInt {
+ a: i32,
+ b: f64,
+ c: i32,
+}
+
+// CHECK: define void @f_int_double_int_s_arg(ptr noalias nocapture noundef dereferenceable(24) %a)
+#[no_mangle]
+pub extern "C" fn f_int_double_int_s_arg(a: IntDoubleInt) {}
+
+// CHECK: define void @f_ret_int_double_int_s(ptr noalias nocapture noundef sret(%IntDoubleInt) dereferenceable(24) %0)
+#[no_mangle]
+pub extern "C" fn f_ret_int_double_int_s() -> IntDoubleInt {
+ IntDoubleInt { a: 1, b: 2., c: 3 }
+}
+
+#[repr(C)]
+pub struct CharCharDouble {
+ a: u8,
+ b: u8,
+ c: f64,
+}
+
+// CHECK: define void @f_char_char_double_s_arg([2 x i64] %0)
+#[no_mangle]
+pub extern "C" fn f_char_char_double_s_arg(a: CharCharDouble) {}
+
+// CHECK: define [2 x i64] @f_ret_char_char_double_s()
+#[no_mangle]
+pub extern "C" fn f_ret_char_char_double_s() -> CharCharDouble {
+ CharCharDouble { a: 1, b: 2, c: 3. }
+}
+
+#[repr(C)]
+pub union DoubleU {
+ a: f64,
+}
+
+// CHECK: define void @f_double_u_arg(i64 %0)
+#[no_mangle]
+pub extern "C" fn f_double_u_arg(a: DoubleU) {}
+
+// CHECK: define i64 @f_ret_double_u()
+#[no_mangle]
+pub extern "C" fn f_ret_double_u() -> DoubleU {
+ unsafe { DoubleU { a: 1. } }
+}
diff --git a/tests/codegen/mem-replace-big-type.rs b/tests/codegen/mem-replace-big-type.rs
index f6898e2f7..c6b920cf5 100644
--- a/tests/codegen/mem-replace-big-type.rs
+++ b/tests/codegen/mem-replace-big-type.rs
@@ -11,7 +11,9 @@
#[repr(C, align(8))]
pub struct Big([u64; 7]);
pub fn replace_big(dst: &mut Big, src: Big) -> Big {
- // Before the `read_via_copy` intrinsic, this emitted six `memcpy`s.
+ // Back in 1.68, this emitted six `memcpy`s.
+ // `read_via_copy` in 1.69 got that down to three.
+ // `write_via_move` and nvro get this down to the essential two.
std::mem::replace(dst, src)
}
@@ -22,15 +24,10 @@ pub fn replace_big(dst: &mut Big, src: Big) -> Big {
// For a large type, we expect exactly three `memcpy`s
// CHECK-LABEL: define internal void @{{.+}}mem{{.+}}replace{{.+}}sret(%Big)
- // CHECK-NOT: alloca
- // CHECK: alloca %Big
- // CHECK-NOT: alloca
- // CHECK-NOT: call void @llvm.memcpy
- // CHECK: call void @llvm.memcpy.{{.+}}({{i8\*|ptr}} align 8 %{{.*}}, {{i8\*|ptr}} align 8 %{{.*}}, i{{.*}} 56, i1 false)
- // CHECK-NOT: call void @llvm.memcpy
- // CHECK: call void @llvm.memcpy.{{.+}}({{i8\*|ptr}} align 8 %{{.*}}, {{i8\*|ptr}} align 8 %{{.*}}, i{{.*}} 56, i1 false)
- // CHECK-NOT: call void @llvm.memcpy
- // CHECK: call void @llvm.memcpy.{{.+}}({{i8\*|ptr}} align 8 %{{.*}}, {{i8\*|ptr}} align 8 %{{.*}}, i{{.*}} 56, i1 false)
- // CHECK-NOT: call void @llvm.memcpy
+// CHECK-NOT: call void @llvm.memcpy
+// CHECK: call void @llvm.memcpy.{{.+}}({{i8\*|ptr}} align 8 %0, {{i8\*|ptr}} align 8 %dest, i{{.*}} 56, i1 false)
+// CHECK-NOT: call void @llvm.memcpy
+// CHECK: call void @llvm.memcpy.{{.+}}({{i8\*|ptr}} align 8 %dest, {{i8\*|ptr}} align 8 %src, i{{.*}} 56, i1 false)
+// CHECK-NOT: call void @llvm.memcpy
// CHECK-NOT: call void @llvm.memcpy
diff --git a/tests/codegen/mem-replace-direct-memcpy.rs b/tests/codegen/mem-replace-direct-memcpy.rs
deleted file mode 100644
index 83babab4f..000000000
--- a/tests/codegen/mem-replace-direct-memcpy.rs
+++ /dev/null
@@ -1,33 +0,0 @@
-// This test ensures that `mem::replace::<T>` only ever calls `@llvm.memcpy`
-// with `size_of::<T>()` as the size, and never goes through any wrapper that
-// may e.g. multiply `size_of::<T>()` with a variable "count" (which is only
-// known to be `1` after inlining).
-
-// compile-flags: -C no-prepopulate-passes -Zinline-mir=no
-// ignore-debug: the debug assertions get in the way
-
-#![crate_type = "lib"]
-
-pub fn replace_byte(dst: &mut u8, src: u8) -> u8 {
- std::mem::replace(dst, src)
-}
-
-// NOTE(eddyb) the `CHECK-NOT`s ensure that the only calls of `@llvm.memcpy` in
-// the entire output, are the direct calls we want, from `ptr::replace`.
-
-// CHECK-NOT: call void @llvm.memcpy
-
-// For a small type, we expect one each of `load`/`store`/`memcpy` instead
-// CHECK-LABEL: define internal noundef i8 @{{.+}}mem{{.+}}replace
- // CHECK-NOT: alloca
- // CHECK: alloca i8
- // CHECK-NOT: alloca
- // CHECK-NOT: call void @llvm.memcpy
- // CHECK: load i8
- // CHECK-NOT: call void @llvm.memcpy
- // CHECK: store i8
- // CHECK-NOT: call void @llvm.memcpy
- // CHECK: call void @llvm.memcpy.{{.+}}({{i8\*|ptr}} align 1 %{{.*}}, {{i8\*|ptr}} align 1 %{{.*}}, i{{.*}} 1, i1 false)
- // CHECK-NOT: call void @llvm.memcpy
-
-// CHECK-NOT: call void @llvm.memcpy
diff --git a/tests/codegen/mem-replace-simple-type.rs b/tests/codegen/mem-replace-simple-type.rs
new file mode 100644
index 000000000..4253ef136
--- /dev/null
+++ b/tests/codegen/mem-replace-simple-type.rs
@@ -0,0 +1,34 @@
+// compile-flags: -O -C no-prepopulate-passes
+// min-llvm-version: 15.0 (for opaque pointers)
+// only-x86_64 (to not worry about usize differing)
+// ignore-debug (the debug assertions get in the way)
+
+#![crate_type = "lib"]
+
+#[no_mangle]
+// CHECK-LABEL: @replace_usize(
+pub fn replace_usize(r: &mut usize, v: usize) -> usize {
+ // CHECK-NOT: alloca
+ // CHECK: %[[R:.+]] = load i64, ptr %r
+ // CHECK: store i64 %v, ptr %r
+ // CHECK: ret i64 %[[R]]
+ std::mem::replace(r, v)
+}
+
+#[no_mangle]
+// CHECK-LABEL: @replace_ref_str(
+pub fn replace_ref_str<'a>(r: &mut &'a str, v: &'a str) -> &'a str {
+ // CHECK-NOT: alloca
+ // CHECK: %[[A:.+]] = load ptr
+ // CHECK: %[[B:.+]] = load i64
+ // CHECK-NOT: store
+ // CHECK-NOT: load
+ // CHECK: store ptr
+ // CHECK: store i64
+ // CHECK-NOT: load
+ // CHECK-NOT: store
+ // CHECK: %[[P1:.+]] = insertvalue { ptr, i64 } poison, ptr %[[A]], 0
+ // CHECK: %[[P2:.+]] = insertvalue { ptr, i64 } %[[P1]], i64 %[[B]], 1
+ // CHECK: ret { ptr, i64 } %[[P2]]
+ std::mem::replace(r, v)
+}
diff --git a/tests/codegen/noalias-box-off.rs b/tests/codegen/noalias-box-off.rs
index afd17c7c1..c82c53b2a 100644
--- a/tests/codegen/noalias-box-off.rs
+++ b/tests/codegen/noalias-box-off.rs
@@ -4,5 +4,8 @@
// CHECK-LABEL: @box_should_not_have_noalias_if_disabled(
// CHECK-NOT: noalias
+// CHECK-SAME: %foo)
#[no_mangle]
-pub fn box_should_not_have_noalias_if_disabled(_b: Box<u8>) {}
+pub fn box_should_not_have_noalias_if_disabled(foo: Box<u8>) {
+ drop(foo);
+}
diff --git a/tests/codegen/nrvo.rs b/tests/codegen/nrvo.rs
index fddb0d1fb..b2ae99f37 100644
--- a/tests/codegen/nrvo.rs
+++ b/tests/codegen/nrvo.rs
@@ -8,7 +8,7 @@
pub fn nrvo(init: fn(&mut [u8; 4096])) -> [u8; 4096] {
// CHECK-LABEL: nrvo
// CHECK: @llvm.memset
- // CHECK-NOT: @llvm.memcpy
+ // FIXME: turn on nrvo then check-not: @llvm.memcpy
// CHECK: ret
// CHECK-EMPTY
let mut buf = [0; 4096];
diff --git a/tests/codegen/optimize-attr-1.rs b/tests/codegen/optimize-attr-1.rs
index 1d1f0a386..d95ba8530 100644
--- a/tests/codegen/optimize-attr-1.rs
+++ b/tests/codegen/optimize-attr-1.rs
@@ -9,7 +9,7 @@
// CHECK-LABEL: define{{.*}}i32 @nothing
// CHECK-SAME: [[NOTHING_ATTRS:#[0-9]+]]
// SIZE-OPT: ret i32 4
-// SPEEC-OPT: ret i32 4
+// SPEED-OPT: ret i32 4
#[no_mangle]
pub fn nothing() -> i32 {
2 + 2
diff --git a/tests/codegen/option-as-slice.rs b/tests/codegen/option-as-slice.rs
index d735d5583..1edd9ba9f 100644
--- a/tests/codegen/option-as-slice.rs
+++ b/tests/codegen/option-as-slice.rs
@@ -1,5 +1,7 @@
// compile-flags: -O -Z randomize-layout=no
// only-x86_64
+// ignore-llvm-version: 16.0.0
+// ^ needs https://reviews.llvm.org/D146149 in 16.0.1
#![crate_type = "lib"]
#![feature(option_as_slice)]
diff --git a/tests/codegen/option-nonzero-eq.rs b/tests/codegen/option-nonzero-eq.rs
index 835decd3e..a394695f3 100644
--- a/tests/codegen/option-nonzero-eq.rs
+++ b/tests/codegen/option-nonzero-eq.rs
@@ -7,6 +7,9 @@ use core::cmp::Ordering;
use core::num::{NonZeroU32, NonZeroI64};
use core::ptr::NonNull;
+// See also tests/assembly/option-nonzero-eq.rs, for cases with `assume`s in the
+// LLVM and thus don't optimize down clearly here, but do in assembly.
+
// CHECK-lABEL: @non_zero_eq
#[no_mangle]
pub fn non_zero_eq(l: Option<NonZeroU32>, r: Option<NonZeroU32>) -> bool {
@@ -33,12 +36,3 @@ pub fn non_null_eq(l: Option<NonNull<u8>>, r: Option<NonNull<u8>>) -> bool {
// CHECK-NEXT: ret i1
l == r
}
-
-// CHECK-lABEL: @ordering_eq
-#[no_mangle]
-pub fn ordering_eq(l: Option<Ordering>, r: Option<Ordering>) -> bool {
- // CHECK: start:
- // CHECK-NEXT: icmp eq i8
- // CHECK-NEXT: ret i1
- l == r
-}
diff --git a/tests/codegen/remap_path_prefix/auxiliary/xcrate-generic.rs b/tests/codegen/remap_path_prefix/auxiliary/xcrate-generic.rs
index 59092dbf6..15bd0f174 100644
--- a/tests/codegen/remap_path_prefix/auxiliary/xcrate-generic.rs
+++ b/tests/codegen/remap_path_prefix/auxiliary/xcrate-generic.rs
@@ -3,4 +3,6 @@
#![crate_type = "lib"]
-pub fn foo<T>() {}
+pub fn foo<T: Default>() -> T {
+ T::default()
+}
diff --git a/tests/codegen/remap_path_prefix/xcrate-generic.rs b/tests/codegen/remap_path_prefix/xcrate-generic.rs
index 7a9d2ca9b..399deec1f 100644
--- a/tests/codegen/remap_path_prefix/xcrate-generic.rs
+++ b/tests/codegen/remap_path_prefix/xcrate-generic.rs
@@ -7,7 +7,7 @@
extern crate xcrate_generic;
pub fn foo() {
- xcrate_generic::foo::<u32>();
+ println!("{}", xcrate_generic::foo::<u32>());
}
// Here we check that local debuginfo is mapped correctly.
diff --git a/tests/codegen/repr-transparent-aggregates-1.rs b/tests/codegen/repr-transparent-aggregates-1.rs
index f733de12b..9c4b0e58e 100644
--- a/tests/codegen/repr-transparent-aggregates-1.rs
+++ b/tests/codegen/repr-transparent-aggregates-1.rs
@@ -10,6 +10,7 @@
// ignore-riscv64 see codegen/riscv-abi
// ignore-s390x
// ignore-windows
+// ignore-loongarch64
// See repr-transparent.rs
#![feature(transparent_unions)]
diff --git a/tests/codegen/repr-transparent-aggregates-2.rs b/tests/codegen/repr-transparent-aggregates-2.rs
index e9fa5143b..a7bde2d05 100644
--- a/tests/codegen/repr-transparent-aggregates-2.rs
+++ b/tests/codegen/repr-transparent-aggregates-2.rs
@@ -12,6 +12,7 @@
// ignore-sparc64
// ignore-x86
// ignore-x86_64
+// ignore-loongarch64
// See repr-transparent.rs
#![feature(transparent_unions)]
diff --git a/tests/codegen/repr-transparent.rs b/tests/codegen/repr-transparent.rs
index 311cbfbaa..759ddea67 100644
--- a/tests/codegen/repr-transparent.rs
+++ b/tests/codegen/repr-transparent.rs
@@ -3,6 +3,7 @@
// ignore-riscv64 riscv64 has an i128 type used with test_Vector
// see codegen/riscv-abi for riscv functiona call tests
// ignore-s390x s390x with default march passes vector types per reference
+// ignore-loongarch64 see codegen/loongarch-abi for loongarch function call tests
#![crate_type="lib"]
#![feature(repr_simd, transparent_unions)]
diff --git a/tests/codegen/sanitizer-cfi-add-canonical-jump-tables-flag.rs b/tests/codegen/sanitizer-cfi-add-canonical-jump-tables-flag.rs
index c42fbba74..1ee8bdfc3 100644
--- a/tests/codegen/sanitizer-cfi-add-canonical-jump-tables-flag.rs
+++ b/tests/codegen/sanitizer-cfi-add-canonical-jump-tables-flag.rs
@@ -8,4 +8,4 @@
pub fn foo() {
}
-// CHECK: !{{[0-9]+}} = !{i32 2, !"CFI Canonical Jump Tables", i32 1}
+// CHECK: !{{[0-9]+}} = !{i32 4, !"CFI Canonical Jump Tables", i32 1}
diff --git a/tests/codegen/sanitizer-cfi-add-enable-split-lto-unit-flag.rs b/tests/codegen/sanitizer-cfi-add-enable-split-lto-unit-flag.rs
new file mode 100644
index 000000000..68c91384b
--- /dev/null
+++ b/tests/codegen/sanitizer-cfi-add-enable-split-lto-unit-flag.rs
@@ -0,0 +1,11 @@
+// Verifies that "EnableSplitLTOUnit" module flag is added.
+//
+// needs-sanitizer-cfi
+// compile-flags: -Clto -Ctarget-feature=-crt-static -Zsanitizer=cfi
+
+#![crate_type="lib"]
+
+pub fn foo() {
+}
+
+// CHECK: !{{[0-9]+}} = !{i32 4, !"EnableSplitLTOUnit", i32 1}
diff --git a/tests/codegen/sanitizer-cfi-emit-type-checks-attr-no-sanitize.rs b/tests/codegen/sanitizer-cfi-emit-type-checks-attr-no-sanitize.rs
new file mode 100644
index 000000000..2b61c9078
--- /dev/null
+++ b/tests/codegen/sanitizer-cfi-emit-type-checks-attr-no-sanitize.rs
@@ -0,0 +1,18 @@
+// Verifies that pointer type membership tests for indirect calls are omitted.
+//
+// needs-sanitizer-cfi
+// compile-flags: -Clto -Cno-prepopulate-passes -Ctarget-feature=-crt-static -Zsanitizer=cfi -Copt-level=0
+
+#![crate_type="lib"]
+#![feature(no_sanitize)]
+
+#[no_sanitize(cfi)]
+pub fn foo(f: fn(i32) -> i32, arg: i32) -> i32 {
+ // CHECK-LABEL: sanitizer_cfi_emit_type_checks_attr_no_sanitize::foo
+ // CHECK: Function Attrs: {{.*}}
+ // CHECK-LABEL: define{{.*}}foo{{.*}}!type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
+ // CHECK: start:
+ // CHECK-NEXT: {{%.+}} = call i32 %f(i32 %arg)
+ // CHECK-NEXT: ret i32 {{%.+}}
+ f(arg)
+}
diff --git a/tests/codegen/sanitizer-cfi-emit-type-checks.rs b/tests/codegen/sanitizer-cfi-emit-type-checks.rs
index 597b867eb..cea6aac8b 100644
--- a/tests/codegen/sanitizer-cfi-emit-type-checks.rs
+++ b/tests/codegen/sanitizer-cfi-emit-type-checks.rs
@@ -6,13 +6,12 @@
#![crate_type="lib"]
pub fn foo(f: fn(i32) -> i32, arg: i32) -> i32 {
- // CHECK-LABEL: define{{.*}}foo{{.*}}!type !{{[0-9]+}}
+ // CHECK-LABEL: define{{.*}}foo{{.*}}!type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
// CHECK: start:
// CHECK: [[TT:%.+]] = call i1 @llvm.type.test({{i8\*|ptr}} {{%f|%0}}, metadata !"{{[[:print:]]+}}")
// CHECK-NEXT: br i1 [[TT]], label %type_test.pass, label %type_test.fail
// CHECK: type_test.pass:
// CHECK-NEXT: {{%.+}} = call i32 %f(i32 %arg)
- // CHECK-NEXT: br label %bb1
// CHECK: type_test.fail:
// CHECK-NEXT: call void @llvm.trap()
// CHECK-NEXT: unreachable
diff --git a/tests/codegen/sanitizer-cfi-emit-type-metadata-attr-cfi-encoding.rs b/tests/codegen/sanitizer-cfi-emit-type-metadata-attr-cfi-encoding.rs
new file mode 100644
index 000000000..084d8bf80
--- /dev/null
+++ b/tests/codegen/sanitizer-cfi-emit-type-metadata-attr-cfi-encoding.rs
@@ -0,0 +1,48 @@
+// Verifies that user-defined CFI encoding for types are emitted.
+//
+// needs-sanitizer-cfi
+// compile-flags: -Clto -Cno-prepopulate-passes -Ctarget-feature=-crt-static -Zsanitizer=cfi
+
+#![crate_type="lib"]
+#![feature(cfi_encoding, extern_types)]
+
+#[cfi_encoding = "3Foo"]
+pub struct Type1(i32);
+
+extern {
+ #[cfi_encoding = "3Bar"]
+ type Type2;
+}
+
+#[cfi_encoding = "3Baz"]
+#[repr(transparent)]
+pub struct Type3(i32);
+
+pub fn foo0(_: Type1) { }
+// CHECK: define{{.*}}foo0{{.*}}!type ![[TYPE0:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
+pub fn foo1(_: Type1, _: Type1) { }
+// CHECK: define{{.*}}foo1{{.*}}!type ![[TYPE1:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
+pub fn foo2(_: Type1, _: Type1, _: Type1) { }
+// CHECK: define{{.*}}foo2{{.*}}!type ![[TYPE2:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
+pub fn foo3(_: *mut Type2) { }
+// CHECK: define{{.*}}foo3{{.*}}!type ![[TYPE3:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
+pub fn foo4(_: *mut Type2, _: *mut Type2) { }
+// CHECK: define{{.*}}foo4{{.*}}!type ![[TYPE4:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
+pub fn foo5(_: *mut Type2, _: *mut Type2, _: *mut Type2) { }
+// CHECK: define{{.*}}foo5{{.*}}!type ![[TYPE5:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
+pub fn foo6(_: *mut Type3) { }
+// CHECK: define{{.*}}foo6{{.*}}!type ![[TYPE6:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
+pub fn foo7(_: *mut Type3, _: *mut Type3) { }
+// CHECK: define{{.*}}foo7{{.*}}!type ![[TYPE7:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
+pub fn foo8(_: *mut Type3, _: *mut Type3, _: *mut Type3) { }
+// CHECK: define{{.*}}foo8{{.*}}!type ![[TYPE8:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
+
+// CHECK: ![[TYPE0]] = !{i64 0, !"_ZTSFv3FooE"}
+// CHECK: ![[TYPE1]] = !{i64 0, !"_ZTSFv3FooS_E"}
+// CHECK: ![[TYPE2]] = !{i64 0, !"_ZTSFv3FooS_S_E"}
+// CHECK: ![[TYPE3]] = !{i64 0, !"_ZTSFvP3BarE"}
+// CHECK: ![[TYPE4]] = !{i64 0, !"_ZTSFvP3BarS0_E"}
+// CHECK: ![[TYPE5]] = !{i64 0, !"_ZTSFvP3BarS0_S0_E"}
+// CHECK: ![[TYPE6]] = !{i64 0, !"_ZTSFvP3BazE"}
+// CHECK: ![[TYPE7]] = !{i64 0, !"_ZTSFvP3BazS0_E"}
+// CHECK: ![[TYPE8]] = !{i64 0, !"_ZTSFvP3BazS0_S0_E"}
diff --git a/tests/codegen/sanitizer-cfi-emit-type-metadata-id-itanium-cxx-abi.rs b/tests/codegen/sanitizer-cfi-emit-type-metadata-id-itanium-cxx-abi.rs
index b9c339143..ebb26cd35 100644
--- a/tests/codegen/sanitizer-cfi-emit-type-metadata-id-itanium-cxx-abi.rs
+++ b/tests/codegen/sanitizer-cfi-emit-type-metadata-id-itanium-cxx-abi.rs
@@ -10,7 +10,7 @@
#![feature(adt_const_params, extern_types, inline_const, type_alias_impl_trait)]
extern crate core;
-use core::ffi::c_void;
+use core::ffi::*;
use std::marker::PhantomData;
// User-defined type (structure)
@@ -44,7 +44,7 @@ impl<T> Trait1<T> for i32 {
}
// Trait implementation
-impl<T> Trait1<T> for Struct1<T> {
+impl<T, U> Trait1<T> for Struct1<U> {
fn foo(&self) { }
}
@@ -113,9 +113,10 @@ pub fn fn1<'a>() {
let _: Type11 = Quuux;
}
-// repr(transparent) user-defined type
+// Helper type to make Type12 have an unique id
struct Foo(i32);
+// repr(transparent) user-defined type
#[repr(transparent)]
pub struct Type12 {
member1: (),
@@ -131,313 +132,313 @@ pub struct Type13<'a> {
member3: &'a Type13<'a>,
}
-// Helper type to allow `Type14<Bar>` to be a unique ID
+// Helper type to make Type14 have an unique id
pub struct Bar;
-// repr(transparent) parameterized type
+// repr(transparent) user-defined generic type
#[repr(transparent)]
pub struct Type14<T>(T);
pub fn foo0(_: ()) { }
-// CHECK: define{{.*}}foo0{{.*}}!type ![[TYPE0:[0-9]+]]
-pub fn foo1(_: c_void, _: ()) { }
-// CHECK: define{{.*}}foo1{{.*}}!type ![[TYPE1:[0-9]+]]
+// CHECK: define{{.*}}foo0{{.*}}!type ![[TYPE0:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
+pub fn foo1(_: (), _: c_void) { }
+// CHECK: define{{.*}}foo1{{.*}}!type ![[TYPE1:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
pub fn foo2(_: (), _: c_void, _: c_void) { }
-// CHECK: define{{.*}}foo2{{.*}}!type ![[TYPE2:[0-9]+]]
-pub fn foo3(_: *mut c_void) { }
-// CHECK: define{{.*}}foo3{{.*}}!type ![[TYPE3:[0-9]+]]
-pub fn foo4(_: *mut c_void, _: *mut ()) { }
-// CHECK: define{{.*}}foo4{{.*}}!type ![[TYPE4:[0-9]+]]
+// CHECK: define{{.*}}foo2{{.*}}!type ![[TYPE2:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
+pub fn foo3(_: *mut ()) { }
+// CHECK: define{{.*}}foo3{{.*}}!type ![[TYPE3:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
+pub fn foo4(_: *mut (), _: *mut c_void) { }
+// CHECK: define{{.*}}foo4{{.*}}!type ![[TYPE4:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
pub fn foo5(_: *mut (), _: *mut c_void, _: *mut c_void) { }
-// CHECK: define{{.*}}foo5{{.*}}!type ![[TYPE5:[0-9]+]]
-pub fn foo6(_: *const c_void) { }
-// CHECK: define{{.*}}foo6{{.*}}!type ![[TYPE6:[0-9]+]]
-pub fn foo7(_: *const c_void, _: *const ()) { }
-// CHECK: define{{.*}}foo7{{.*}}!type ![[TYPE7:[0-9]+]]
+// CHECK: define{{.*}}foo5{{.*}}!type ![[TYPE5:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
+pub fn foo6(_: *const ()) { }
+// CHECK: define{{.*}}foo6{{.*}}!type ![[TYPE6:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
+pub fn foo7(_: *const (), _: *const c_void) { }
+// CHECK: define{{.*}}foo7{{.*}}!type ![[TYPE7:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
pub fn foo8(_: *const (), _: *const c_void, _: *const c_void) { }
-// CHECK: define{{.*}}foo8{{.*}}!type ![[TYPE8:[0-9]+]]
+// CHECK: define{{.*}}foo8{{.*}}!type ![[TYPE8:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
pub fn foo9(_: bool) { }
-// CHECK: define{{.*}}foo9{{.*}}!type ![[TYPE9:[0-9]+]]
+// CHECK: define{{.*}}foo9{{.*}}!type ![[TYPE9:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
pub fn foo10(_: bool, _: bool) { }
-// CHECK: define{{.*}}foo10{{.*}}!type ![[TYPE10:[0-9]+]]
+// CHECK: define{{.*}}foo10{{.*}}!type ![[TYPE10:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
pub fn foo11(_: bool, _: bool, _: bool) { }
-// CHECK: define{{.*}}foo11{{.*}}!type ![[TYPE11:[0-9]+]]
+// CHECK: define{{.*}}foo11{{.*}}!type ![[TYPE11:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
pub fn foo12(_: i8) { }
-// CHECK: define{{.*}}foo12{{.*}}!type ![[TYPE12:[0-9]+]]
+// CHECK: define{{.*}}foo12{{.*}}!type ![[TYPE12:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
pub fn foo13(_: i8, _: i8) { }
-// CHECK: define{{.*}}foo13{{.*}}!type ![[TYPE13:[0-9]+]]
+// CHECK: define{{.*}}foo13{{.*}}!type ![[TYPE13:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
pub fn foo14(_: i8, _: i8, _: i8) { }
-// CHECK: define{{.*}}foo14{{.*}}!type ![[TYPE14:[0-9]+]]
+// CHECK: define{{.*}}foo14{{.*}}!type ![[TYPE14:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
pub fn foo15(_: i16) { }
-// CHECK: define{{.*}}foo15{{.*}}!type ![[TYPE15:[0-9]+]]
+// CHECK: define{{.*}}foo15{{.*}}!type ![[TYPE15:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
pub fn foo16(_: i16, _: i16) { }
-// CHECK: define{{.*}}foo16{{.*}}!type ![[TYPE16:[0-9]+]]
+// CHECK: define{{.*}}foo16{{.*}}!type ![[TYPE16:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
pub fn foo17(_: i16, _: i16, _: i16) { }
-// CHECK: define{{.*}}foo17{{.*}}!type ![[TYPE17:[0-9]+]]
+// CHECK: define{{.*}}foo17{{.*}}!type ![[TYPE17:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
pub fn foo18(_: i32) { }
-// CHECK: define{{.*}}foo18{{.*}}!type ![[TYPE18:[0-9]+]]
+// CHECK: define{{.*}}foo18{{.*}}!type ![[TYPE18:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
pub fn foo19(_: i32, _: i32) { }
-// CHECK: define{{.*}}foo19{{.*}}!type ![[TYPE19:[0-9]+]]
+// CHECK: define{{.*}}foo19{{.*}}!type ![[TYPE19:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
pub fn foo20(_: i32, _: i32, _: i32) { }
-// CHECK: define{{.*}}foo20{{.*}}!type ![[TYPE20:[0-9]+]]
+// CHECK: define{{.*}}foo20{{.*}}!type ![[TYPE20:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
pub fn foo21(_: i64) { }
-// CHECK: define{{.*}}foo21{{.*}}!type ![[TYPE21:[0-9]+]]
+// CHECK: define{{.*}}foo21{{.*}}!type ![[TYPE21:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
pub fn foo22(_: i64, _: i64) { }
-// CHECK: define{{.*}}foo22{{.*}}!type ![[TYPE22:[0-9]+]]
+// CHECK: define{{.*}}foo22{{.*}}!type ![[TYPE22:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
pub fn foo23(_: i64, _: i64, _: i64) { }
-// CHECK: define{{.*}}foo23{{.*}}!type ![[TYPE23:[0-9]+]]
+// CHECK: define{{.*}}foo23{{.*}}!type ![[TYPE23:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
pub fn foo24(_: i128) { }
-// CHECK: define{{.*}}foo24{{.*}}!type ![[TYPE24:[0-9]+]]
+// CHECK: define{{.*}}foo24{{.*}}!type ![[TYPE24:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
pub fn foo25(_: i128, _: i128) { }
-// CHECK: define{{.*}}foo25{{.*}}!type ![[TYPE25:[0-9]+]]
+// CHECK: define{{.*}}foo25{{.*}}!type ![[TYPE25:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
pub fn foo26(_: i128, _: i128, _: i128) { }
-// CHECK: define{{.*}}foo26{{.*}}!type ![[TYPE26:[0-9]+]]
+// CHECK: define{{.*}}foo26{{.*}}!type ![[TYPE26:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
pub fn foo27(_: isize) { }
-// CHECK: define{{.*}}foo27{{.*}}!type ![[TYPE27:[0-9]+]]
+// CHECK: define{{.*}}foo27{{.*}}!type ![[TYPE27:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
pub fn foo28(_: isize, _: isize) { }
-// CHECK: define{{.*}}foo28{{.*}}!type ![[TYPE28:[0-9]+]]
+// CHECK: define{{.*}}foo28{{.*}}!type ![[TYPE28:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
pub fn foo29(_: isize, _: isize, _: isize) { }
-// CHECK: define{{.*}}foo29{{.*}}!type ![[TYPE29:[0-9]+]]
+// CHECK: define{{.*}}foo29{{.*}}!type ![[TYPE29:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
pub fn foo30(_: u8) { }
-// CHECK: define{{.*}}foo30{{.*}}!type ![[TYPE30:[0-9]+]]
+// CHECK: define{{.*}}foo30{{.*}}!type ![[TYPE30:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
pub fn foo31(_: u8, _: u8) { }
-// CHECK: define{{.*}}foo31{{.*}}!type ![[TYPE31:[0-9]+]]
+// CHECK: define{{.*}}foo31{{.*}}!type ![[TYPE31:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
pub fn foo32(_: u8, _: u8, _: u8) { }
-// CHECK: define{{.*}}foo32{{.*}}!type ![[TYPE32:[0-9]+]]
+// CHECK: define{{.*}}foo32{{.*}}!type ![[TYPE32:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
pub fn foo33(_: u16) { }
-// CHECK: define{{.*}}foo33{{.*}}!type ![[TYPE33:[0-9]+]]
+// CHECK: define{{.*}}foo33{{.*}}!type ![[TYPE33:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
pub fn foo34(_: u16, _: u16) { }
-// CHECK: define{{.*}}foo34{{.*}}!type ![[TYPE34:[0-9]+]]
+// CHECK: define{{.*}}foo34{{.*}}!type ![[TYPE34:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
pub fn foo35(_: u16, _: u16, _: u16) { }
-// CHECK: define{{.*}}foo35{{.*}}!type ![[TYPE35:[0-9]+]]
+// CHECK: define{{.*}}foo35{{.*}}!type ![[TYPE35:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
pub fn foo36(_: u32) { }
-// CHECK: define{{.*}}foo36{{.*}}!type ![[TYPE36:[0-9]+]]
+// CHECK: define{{.*}}foo36{{.*}}!type ![[TYPE36:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
pub fn foo37(_: u32, _: u32) { }
-// CHECK: define{{.*}}foo37{{.*}}!type ![[TYPE37:[0-9]+]]
+// CHECK: define{{.*}}foo37{{.*}}!type ![[TYPE37:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
pub fn foo38(_: u32, _: u32, _: u32) { }
-// CHECK: define{{.*}}foo38{{.*}}!type ![[TYPE38:[0-9]+]]
+// CHECK: define{{.*}}foo38{{.*}}!type ![[TYPE38:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
pub fn foo39(_: u64) { }
-// CHECK: define{{.*}}foo39{{.*}}!type ![[TYPE39:[0-9]+]]
+// CHECK: define{{.*}}foo39{{.*}}!type ![[TYPE39:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
pub fn foo40(_: u64, _: u64) { }
-// CHECK: define{{.*}}foo40{{.*}}!type ![[TYPE40:[0-9]+]]
+// CHECK: define{{.*}}foo40{{.*}}!type ![[TYPE40:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
pub fn foo41(_: u64, _: u64, _: u64) { }
-// CHECK: define{{.*}}foo41{{.*}}!type ![[TYPE41:[0-9]+]]
+// CHECK: define{{.*}}foo41{{.*}}!type ![[TYPE41:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
pub fn foo42(_: u128) { }
-// CHECK: define{{.*}}foo42{{.*}}!type ![[TYPE42:[0-9]+]]
+// CHECK: define{{.*}}foo42{{.*}}!type ![[TYPE42:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
pub fn foo43(_: u128, _: u128) { }
-// CHECK: define{{.*}}foo43{{.*}}!type ![[TYPE43:[0-9]+]]
+// CHECK: define{{.*}}foo43{{.*}}!type ![[TYPE43:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
pub fn foo44(_: u128, _: u128, _: u128) { }
-// CHECK: define{{.*}}foo44{{.*}}!type ![[TYPE44:[0-9]+]]
+// CHECK: define{{.*}}foo44{{.*}}!type ![[TYPE44:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
pub fn foo45(_: usize) { }
-// CHECK: define{{.*}}foo45{{.*}}!type ![[TYPE45:[0-9]+]]
+// CHECK: define{{.*}}foo45{{.*}}!type ![[TYPE45:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
pub fn foo46(_: usize, _: usize) { }
-// CHECK: define{{.*}}foo46{{.*}}!type ![[TYPE46:[0-9]+]]
+// CHECK: define{{.*}}foo46{{.*}}!type ![[TYPE46:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
pub fn foo47(_: usize, _: usize, _: usize) { }
-// CHECK: define{{.*}}foo47{{.*}}!type ![[TYPE47:[0-9]+]]
+// CHECK: define{{.*}}foo47{{.*}}!type ![[TYPE47:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
pub fn foo48(_: f32) { }
-// CHECK: define{{.*}}foo48{{.*}}!type ![[TYPE48:[0-9]+]]
+// CHECK: define{{.*}}foo48{{.*}}!type ![[TYPE48:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
pub fn foo49(_: f32, _: f32) { }
-// CHECK: define{{.*}}foo49{{.*}}!type ![[TYPE49:[0-9]+]]
+// CHECK: define{{.*}}foo49{{.*}}!type ![[TYPE49:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
pub fn foo50(_: f32, _: f32, _: f32) { }
-// CHECK: define{{.*}}foo50{{.*}}!type ![[TYPE50:[0-9]+]]
+// CHECK: define{{.*}}foo50{{.*}}!type ![[TYPE50:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
pub fn foo51(_: f64) { }
-// CHECK: define{{.*}}foo51{{.*}}!type ![[TYPE51:[0-9]+]]
+// CHECK: define{{.*}}foo51{{.*}}!type ![[TYPE51:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
pub fn foo52(_: f64, _: f64) { }
-// CHECK: define{{.*}}foo52{{.*}}!type ![[TYPE52:[0-9]+]]
+// CHECK: define{{.*}}foo52{{.*}}!type ![[TYPE52:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
pub fn foo53(_: f64, _: f64, _: f64) { }
-// CHECK: define{{.*}}foo53{{.*}}!type ![[TYPE53:[0-9]+]]
+// CHECK: define{{.*}}foo53{{.*}}!type ![[TYPE53:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
pub fn foo54(_: char) { }
-// CHECK: define{{.*}}foo54{{.*}}!type ![[TYPE54:[0-9]+]]
+// CHECK: define{{.*}}foo54{{.*}}!type ![[TYPE54:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
pub fn foo55(_: char, _: char) { }
-// CHECK: define{{.*}}foo55{{.*}}!type ![[TYPE55:[0-9]+]]
+// CHECK: define{{.*}}foo55{{.*}}!type ![[TYPE55:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
pub fn foo56(_: char, _: char, _: char) { }
-// CHECK: define{{.*}}foo56{{.*}}!type ![[TYPE56:[0-9]+]]
+// CHECK: define{{.*}}foo56{{.*}}!type ![[TYPE56:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
pub fn foo57(_: &str) { }
-// CHECK: define{{.*}}foo57{{.*}}!type ![[TYPE57:[0-9]+]]
+// CHECK: define{{.*}}foo57{{.*}}!type ![[TYPE57:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
pub fn foo58(_: &str, _: &str) { }
-// CHECK: define{{.*}}foo58{{.*}}!type ![[TYPE58:[0-9]+]]
+// CHECK: define{{.*}}foo58{{.*}}!type ![[TYPE58:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
pub fn foo59(_: &str, _: &str, _: &str) { }
-// CHECK: define{{.*}}foo59{{.*}}!type ![[TYPE59:[0-9]+]]
+// CHECK: define{{.*}}foo59{{.*}}!type ![[TYPE59:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
pub fn foo60(_: (i32, i32)) { }
-// CHECK: define{{.*}}foo60{{.*}}!type ![[TYPE60:[0-9]+]]
+// CHECK: define{{.*}}foo60{{.*}}!type ![[TYPE60:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
pub fn foo61(_: (i32, i32), _: (i32, i32)) { }
-// CHECK: define{{.*}}foo61{{.*}}!type ![[TYPE61:[0-9]+]]
+// CHECK: define{{.*}}foo61{{.*}}!type ![[TYPE61:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
pub fn foo62(_: (i32, i32), _: (i32, i32), _: (i32, i32)) { }
-// CHECK: define{{.*}}foo62{{.*}}!type ![[TYPE62:[0-9]+]]
+// CHECK: define{{.*}}foo62{{.*}}!type ![[TYPE62:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
pub fn foo63(_: [i32; 32]) { }
-// CHECK: define{{.*}}foo63{{.*}}!type ![[TYPE63:[0-9]+]]
+// CHECK: define{{.*}}foo63{{.*}}!type ![[TYPE63:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
pub fn foo64(_: [i32; 32], _: [i32; 32]) { }
-// CHECK: define{{.*}}foo64{{.*}}!type ![[TYPE64:[0-9]+]]
+// CHECK: define{{.*}}foo64{{.*}}!type ![[TYPE64:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
pub fn foo65(_: [i32; 32], _: [i32; 32], _: [i32; 32]) { }
-// CHECK: define{{.*}}foo65{{.*}}!type ![[TYPE65:[0-9]+]]
+// CHECK: define{{.*}}foo65{{.*}}!type ![[TYPE65:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
pub fn foo66(_: &[i32]) { }
-// CHECK: define{{.*}}foo66{{.*}}!type ![[TYPE66:[0-9]+]]
+// CHECK: define{{.*}}foo66{{.*}}!type ![[TYPE66:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
pub fn foo67(_: &[i32], _: &[i32]) { }
-// CHECK: define{{.*}}foo67{{.*}}!type ![[TYPE67:[0-9]+]]
+// CHECK: define{{.*}}foo67{{.*}}!type ![[TYPE67:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
pub fn foo68(_: &[i32], _: &[i32], _: &[i32]) { }
-// CHECK: define{{.*}}foo68{{.*}}!type ![[TYPE68:[0-9]+]]
+// CHECK: define{{.*}}foo68{{.*}}!type ![[TYPE68:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
pub fn foo69(_: &Struct1::<i32>) { }
-// CHECK: define{{.*}}foo69{{.*}}!type ![[TYPE69:[0-9]+]]
+// CHECK: define{{.*}}foo69{{.*}}!type ![[TYPE69:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
pub fn foo70(_: &Struct1::<i32>, _: &Struct1::<i32>) { }
-// CHECK: define{{.*}}foo70{{.*}}!type ![[TYPE70:[0-9]+]]
+// CHECK: define{{.*}}foo70{{.*}}!type ![[TYPE70:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
pub fn foo71(_: &Struct1::<i32>, _: &Struct1::<i32>, _: &Struct1::<i32>) { }
-// CHECK: define{{.*}}foo71{{.*}}!type ![[TYPE71:[0-9]+]]
+// CHECK: define{{.*}}foo71{{.*}}!type ![[TYPE71:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
pub fn foo72(_: &Enum1::<i32>) { }
-// CHECK: define{{.*}}foo72{{.*}}!type ![[TYPE72:[0-9]+]]
+// CHECK: define{{.*}}foo72{{.*}}!type ![[TYPE72:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
pub fn foo73(_: &Enum1::<i32>, _: &Enum1::<i32>) { }
-// CHECK: define{{.*}}foo73{{.*}}!type ![[TYPE73:[0-9]+]]
+// CHECK: define{{.*}}foo73{{.*}}!type ![[TYPE73:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
pub fn foo74(_: &Enum1::<i32>, _: &Enum1::<i32>, _: &Enum1::<i32>) { }
-// CHECK: define{{.*}}foo74{{.*}}!type ![[TYPE74:[0-9]+]]
+// CHECK: define{{.*}}foo74{{.*}}!type ![[TYPE74:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
pub fn foo75(_: &Union1::<i32>) { }
-// CHECK: define{{.*}}foo75{{.*}}!type ![[TYPE75:[0-9]+]]
+// CHECK: define{{.*}}foo75{{.*}}!type ![[TYPE75:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
pub fn foo76(_: &Union1::<i32>, _: &Union1::<i32>) { }
-// CHECK: define{{.*}}foo76{{.*}}!type ![[TYPE76:[0-9]+]]
+// CHECK: define{{.*}}foo76{{.*}}!type ![[TYPE76:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
pub fn foo77(_: &Union1::<i32>, _: &Union1::<i32>, _: &Union1::<i32>) { }
-// CHECK: define{{.*}}foo77{{.*}}!type ![[TYPE77:[0-9]+]]
+// CHECK: define{{.*}}foo77{{.*}}!type ![[TYPE77:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
pub fn foo78(_: *mut type1) { }
-// CHECK: define{{.*}}foo78{{.*}}!type ![[TYPE78:[0-9]+]]
+// CHECK: define{{.*}}foo78{{.*}}!type ![[TYPE78:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
pub fn foo79(_: *mut type1, _: *mut type1) { }
-// CHECK: define{{.*}}foo79{{.*}}!type ![[TYPE79:[0-9]+]]
+// CHECK: define{{.*}}foo79{{.*}}!type ![[TYPE79:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
pub fn foo80(_: *mut type1, _: *mut type1, _: *mut type1) { }
-// CHECK: define{{.*}}foo80{{.*}}!type ![[TYPE80:[0-9]+]]
+// CHECK: define{{.*}}foo80{{.*}}!type ![[TYPE80:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
pub fn foo81(_: &mut i32) { }
-// CHECK: define{{.*}}foo81{{.*}}!type ![[TYPE81:[0-9]+]]
+// CHECK: define{{.*}}foo81{{.*}}!type ![[TYPE81:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
pub fn foo82(_: &mut i32, _: &i32) { }
-// CHECK: define{{.*}}foo82{{.*}}!type ![[TYPE82:[0-9]+]]
+// CHECK: define{{.*}}foo82{{.*}}!type ![[TYPE82:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
pub fn foo83(_: &mut i32, _: &i32, _: &i32) { }
-// CHECK: define{{.*}}foo83{{.*}}!type ![[TYPE83:[0-9]+]]
+// CHECK: define{{.*}}foo83{{.*}}!type ![[TYPE83:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
pub fn foo84(_: &i32) { }
-// CHECK: define{{.*}}foo84{{.*}}!type ![[TYPE84:[0-9]+]]
+// CHECK: define{{.*}}foo84{{.*}}!type ![[TYPE84:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
pub fn foo85(_: &i32, _: &mut i32) { }
-// CHECK: define{{.*}}foo85{{.*}}!type ![[TYPE85:[0-9]+]]
+// CHECK: define{{.*}}foo85{{.*}}!type ![[TYPE85:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
pub fn foo86(_: &i32, _: &mut i32, _: &mut i32) { }
-// CHECK: define{{.*}}foo86{{.*}}!type ![[TYPE86:[0-9]+]]
+// CHECK: define{{.*}}foo86{{.*}}!type ![[TYPE86:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
pub fn foo87(_: *mut i32) { }
-// CHECK: define{{.*}}foo87{{.*}}!type ![[TYPE87:[0-9]+]]
+// CHECK: define{{.*}}foo87{{.*}}!type ![[TYPE87:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
pub fn foo88(_: *mut i32, _: *const i32) { }
-// CHECK: define{{.*}}foo88{{.*}}!type ![[TYPE88:[0-9]+]]
+// CHECK: define{{.*}}foo88{{.*}}!type ![[TYPE88:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
pub fn foo89(_: *mut i32, _: *const i32, _: *const i32) { }
-// CHECK: define{{.*}}foo89{{.*}}!type ![[TYPE89:[0-9]+]]
+// CHECK: define{{.*}}foo89{{.*}}!type ![[TYPE89:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
pub fn foo90(_: *const i32) { }
-// CHECK: define{{.*}}foo90{{.*}}!type ![[TYPE90:[0-9]+]]
+// CHECK: define{{.*}}foo90{{.*}}!type ![[TYPE90:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
pub fn foo91(_: *const i32, _: *mut i32) { }
-// CHECK: define{{.*}}foo91{{.*}}!type ![[TYPE91:[0-9]+]]
+// CHECK: define{{.*}}foo91{{.*}}!type ![[TYPE91:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
pub fn foo92(_: *const i32, _: *mut i32, _: *mut i32) { }
-// CHECK: define{{.*}}foo92{{.*}}!type ![[TYPE92:[0-9]+]]
+// CHECK: define{{.*}}foo92{{.*}}!type ![[TYPE92:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
pub fn foo93(_: fn(i32) -> i32) { }
-// CHECK: define{{.*}}foo93{{.*}}!type ![[TYPE93:[0-9]+]]
+// CHECK: define{{.*}}foo93{{.*}}!type ![[TYPE93:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
pub fn foo94(_: fn(i32) -> i32, _: fn(i32) -> i32) { }
-// CHECK: define{{.*}}foo94{{.*}}!type ![[TYPE94:[0-9]+]]
+// CHECK: define{{.*}}foo94{{.*}}!type ![[TYPE94:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
pub fn foo95(_: fn(i32) -> i32, _: fn(i32) -> i32, _: fn(i32) -> i32) { }
-// CHECK: define{{.*}}foo95{{.*}}!type ![[TYPE95:[0-9]+]]
+// CHECK: define{{.*}}foo95{{.*}}!type ![[TYPE95:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
pub fn foo96(_: &dyn Fn(i32) -> i32) { }
-// CHECK: define{{.*}}foo96{{.*}}!type ![[TYPE96:[0-9]+]]
+// CHECK: define{{.*}}foo96{{.*}}!type ![[TYPE96:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
pub fn foo97(_: &dyn Fn(i32) -> i32, _: &dyn Fn(i32) -> i32) { }
-// CHECK: define{{.*}}foo97{{.*}}!type ![[TYPE97:[0-9]+]]
+// CHECK: define{{.*}}foo97{{.*}}!type ![[TYPE97:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
pub fn foo98(_: &dyn Fn(i32) -> i32, _: &dyn Fn(i32) -> i32, _: &dyn Fn(i32) -> i32) { }
-// CHECK: define{{.*}}foo98{{.*}}!type ![[TYPE98:[0-9]+]]
+// CHECK: define{{.*}}foo98{{.*}}!type ![[TYPE98:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
pub fn foo99(_: &dyn FnMut(i32) -> i32) { }
-// CHECK: define{{.*}}foo99{{.*}}!type ![[TYPE99:[0-9]+]]
+// CHECK: define{{.*}}foo99{{.*}}!type ![[TYPE99:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
pub fn foo100(_: &dyn FnMut(i32) -> i32, _: &dyn FnMut(i32) -> i32) { }
-// CHECK: define{{.*}}foo100{{.*}}!type ![[TYPE100:[0-9]+]]
+// CHECK: define{{.*}}foo100{{.*}}!type ![[TYPE100:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
pub fn foo101(_: &dyn FnMut(i32) -> i32, _: &dyn FnMut(i32) -> i32, _: &dyn FnMut(i32) -> i32) { }
-// CHECK: define{{.*}}foo101{{.*}}!type ![[TYPE101:[0-9]+]]
+// CHECK: define{{.*}}foo101{{.*}}!type ![[TYPE101:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
pub fn foo102(_: &dyn FnOnce(i32) -> i32) { }
-// CHECK: define{{.*}}foo102{{.*}}!type ![[TYPE102:[0-9]+]]
+// CHECK: define{{.*}}foo102{{.*}}!type ![[TYPE102:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
pub fn foo103(_: &dyn FnOnce(i32) -> i32, _: &dyn FnOnce(i32) -> i32) { }
-// CHECK: define{{.*}}foo103{{.*}}!type ![[TYPE103:[0-9]+]]
+// CHECK: define{{.*}}foo103{{.*}}!type ![[TYPE103:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
pub fn foo104(_: &dyn FnOnce(i32) -> i32, _: &dyn FnOnce(i32) -> i32, _: &dyn FnOnce(i32) -> i32) {}
-// CHECK: define{{.*}}foo104{{.*}}!type ![[TYPE104:[0-9]+]]
+// CHECK: define{{.*}}foo104{{.*}}!type ![[TYPE104:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
pub fn foo105(_: &dyn Send) { }
-// CHECK: define{{.*}}foo105{{.*}}!type ![[TYPE105:[0-9]+]]
+// CHECK: define{{.*}}foo105{{.*}}!type ![[TYPE105:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
pub fn foo106(_: &dyn Send, _: &dyn Send) { }
-// CHECK: define{{.*}}foo106{{.*}}!type ![[TYPE106:[0-9]+]]
+// CHECK: define{{.*}}foo106{{.*}}!type ![[TYPE106:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
pub fn foo107(_: &dyn Send, _: &dyn Send, _: &dyn Send) { }
-// CHECK: define{{.*}}foo107{{.*}}!type ![[TYPE107:[0-9]+]]
+// CHECK: define{{.*}}foo107{{.*}}!type ![[TYPE107:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
pub fn foo108(_: Type1) { }
-// CHECK: define{{.*}}foo108{{.*}}!type ![[TYPE108:[0-9]+]]
+// CHECK: define{{.*}}foo108{{.*}}!type ![[TYPE108:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
pub fn foo109(_: Type1, _: Type1) { }
-// CHECK: define{{.*}}foo109{{.*}}!type ![[TYPE109:[0-9]+]]
+// CHECK: define{{.*}}foo109{{.*}}!type ![[TYPE109:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
pub fn foo110(_: Type1, _: Type1, _: Type1) { }
-// CHECK: define{{.*}}foo110{{.*}}!type ![[TYPE110:[0-9]+]]
+// CHECK: define{{.*}}foo110{{.*}}!type ![[TYPE110:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
pub fn foo111(_: Type2) { }
-// CHECK: define{{.*}}foo111{{.*}}!type ![[TYPE111:[0-9]+]]
+// CHECK: define{{.*}}foo111{{.*}}!type ![[TYPE111:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
pub fn foo112(_: Type2, _: Type2) { }
-// CHECK: define{{.*}}foo112{{.*}}!type ![[TYPE112:[0-9]+]]
+// CHECK: define{{.*}}foo112{{.*}}!type ![[TYPE112:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
pub fn foo113(_: Type2, _: Type2, _: Type2) { }
-// CHECK: define{{.*}}foo113{{.*}}!type ![[TYPE113:[0-9]+]]
+// CHECK: define{{.*}}foo113{{.*}}!type ![[TYPE113:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
pub fn foo114(_: Type3) { }
-// CHECK: define{{.*}}foo114{{.*}}!type ![[TYPE114:[0-9]+]]
+// CHECK: define{{.*}}foo114{{.*}}!type ![[TYPE114:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
pub fn foo115(_: Type3, _: Type3) { }
-// CHECK: define{{.*}}foo115{{.*}}!type ![[TYPE115:[0-9]+]]
+// CHECK: define{{.*}}foo115{{.*}}!type ![[TYPE115:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
pub fn foo116(_: Type3, _: Type3, _: Type3) { }
-// CHECK: define{{.*}}foo116{{.*}}!type ![[TYPE116:[0-9]+]]
+// CHECK: define{{.*}}foo116{{.*}}!type ![[TYPE116:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
pub fn foo117(_: Type4) { }
-// CHECK: define{{.*}}foo117{{.*}}!type ![[TYPE117:[0-9]+]]
+// CHECK: define{{.*}}foo117{{.*}}!type ![[TYPE117:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
pub fn foo118(_: Type4, _: Type4) { }
-// CHECK: define{{.*}}foo118{{.*}}!type ![[TYPE118:[0-9]+]]
+// CHECK: define{{.*}}foo118{{.*}}!type ![[TYPE118:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
pub fn foo119(_: Type4, _: Type4, _: Type4) { }
-// CHECK: define{{.*}}foo119{{.*}}!type ![[TYPE119:[0-9]+]]
+// CHECK: define{{.*}}foo119{{.*}}!type ![[TYPE119:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
pub fn foo120(_: Type5) { }
-// CHECK: define{{.*}}foo120{{.*}}!type ![[TYPE120:[0-9]+]]
+// CHECK: define{{.*}}foo120{{.*}}!type ![[TYPE120:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
pub fn foo121(_: Type5, _: Type5) { }
-// CHECK: define{{.*}}foo121{{.*}}!type ![[TYPE121:[0-9]+]]
+// CHECK: define{{.*}}foo121{{.*}}!type ![[TYPE121:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
pub fn foo122(_: Type5, _: Type5, _: Type5) { }
-// CHECK: define{{.*}}foo122{{.*}}!type ![[TYPE122:[0-9]+]]
+// CHECK: define{{.*}}foo122{{.*}}!type ![[TYPE122:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
pub fn foo123(_: Type6) { }
-// CHECK: define{{.*}}foo123{{.*}}!type ![[TYPE123:[0-9]+]]
+// CHECK: define{{.*}}foo123{{.*}}!type ![[TYPE123:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
pub fn foo124(_: Type6, _: Type6) { }
-// CHECK: define{{.*}}foo124{{.*}}!type ![[TYPE124:[0-9]+]]
+// CHECK: define{{.*}}foo124{{.*}}!type ![[TYPE124:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
pub fn foo125(_: Type6, _: Type6, _: Type6) { }
-// CHECK: define{{.*}}foo125{{.*}}!type ![[TYPE125:[0-9]+]]
+// CHECK: define{{.*}}foo125{{.*}}!type ![[TYPE125:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
pub fn foo126(_: Type7) { }
-// CHECK: define{{.*}}foo126{{.*}}!type ![[TYPE126:[0-9]+]]
+// CHECK: define{{.*}}foo126{{.*}}!type ![[TYPE126:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
pub fn foo127(_: Type7, _: Type7) { }
-// CHECK: define{{.*}}foo127{{.*}}!type ![[TYPE127:[0-9]+]]
+// CHECK: define{{.*}}foo127{{.*}}!type ![[TYPE127:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
pub fn foo128(_: Type7, _: Type7, _: Type7) { }
-// CHECK: define{{.*}}foo128{{.*}}!type ![[TYPE128:[0-9]+]]
+// CHECK: define{{.*}}foo128{{.*}}!type ![[TYPE128:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
pub fn foo129(_: Type8) { }
-// CHECK: define{{.*}}foo129{{.*}}!type ![[TYPE129:[0-9]+]]
+// CHECK: define{{.*}}foo129{{.*}}!type ![[TYPE129:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
pub fn foo130(_: Type8, _: Type8) { }
-// CHECK: define{{.*}}foo130{{.*}}!type ![[TYPE130:[0-9]+]]
+// CHECK: define{{.*}}foo130{{.*}}!type ![[TYPE130:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
pub fn foo131(_: Type8, _: Type8, _: Type8) { }
-// CHECK: define{{.*}}foo131{{.*}}!type ![[TYPE131:[0-9]+]]
+// CHECK: define{{.*}}foo131{{.*}}!type ![[TYPE131:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
pub fn foo132(_: Type9) { }
-// CHECK: define{{.*}}foo132{{.*}}!type ![[TYPE132:[0-9]+]]
+// CHECK: define{{.*}}foo132{{.*}}!type ![[TYPE132:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
pub fn foo133(_: Type9, _: Type9) { }
-// CHECK: define{{.*}}foo133{{.*}}!type ![[TYPE133:[0-9]+]]
+// CHECK: define{{.*}}foo133{{.*}}!type ![[TYPE133:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
pub fn foo134(_: Type9, _: Type9, _: Type9) { }
-// CHECK: define{{.*}}foo134{{.*}}!type ![[TYPE134:[0-9]+]]
+// CHECK: define{{.*}}foo134{{.*}}!type ![[TYPE134:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
pub fn foo135(_: Type10) { }
-// CHECK: define{{.*}}foo135{{.*}}!type ![[TYPE135:[0-9]+]]
+// CHECK: define{{.*}}foo135{{.*}}!type ![[TYPE135:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
pub fn foo136(_: Type10, _: Type10) { }
-// CHECK: define{{.*}}foo136{{.*}}!type ![[TYPE136:[0-9]+]]
+// CHECK: define{{.*}}foo136{{.*}}!type ![[TYPE136:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
pub fn foo137(_: Type10, _: Type10, _: Type10) { }
-// CHECK: define{{.*}}foo137{{.*}}!type ![[TYPE137:[0-9]+]]
+// CHECK: define{{.*}}foo137{{.*}}!type ![[TYPE137:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
pub fn foo138(_: Type11) { }
-// CHECK: define{{.*}}foo138{{.*}}!type ![[TYPE138:[0-9]+]]
+// CHECK: define{{.*}}foo138{{.*}}!type ![[TYPE138:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
pub fn foo139(_: Type11, _: Type11) { }
-// CHECK: define{{.*}}foo139{{.*}}!type ![[TYPE139:[0-9]+]]
+// CHECK: define{{.*}}foo139{{.*}}!type ![[TYPE139:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
pub fn foo140(_: Type11, _: Type11, _: Type11) { }
-// CHECK: define{{.*}}foo140{{.*}}!type ![[TYPE140:[0-9]+]]
+// CHECK: define{{.*}}foo140{{.*}}!type ![[TYPE140:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
pub fn foo141(_: Type12) { }
-// CHECK: define{{.*}}foo141{{.*}}!type ![[TYPE141:[0-9]+]]
+// CHECK: define{{.*}}foo141{{.*}}!type ![[TYPE141:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
pub fn foo142(_: Type12, _: Type12) { }
-// CHECK: define{{.*}}foo142{{.*}}!type ![[TYPE142:[0-9]+]]
+// CHECK: define{{.*}}foo142{{.*}}!type ![[TYPE142:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
pub fn foo143(_: Type12, _: Type12, _: Type12) { }
-// CHECK: define{{.*}}foo143{{.*}}!type ![[TYPE143:[0-9]+]]
+// CHECK: define{{.*}}foo143{{.*}}!type ![[TYPE143:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
pub fn foo144(_: Type13) { }
-// CHECK: define{{.*}}foo144{{.*}}!type ![[TYPE144:[0-9]+]]
+// CHECK: define{{.*}}foo144{{.*}}!type ![[TYPE144:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
pub fn foo145(_: Type13, _: Type13) { }
-// CHECK: define{{.*}}foo145{{.*}}!type ![[TYPE145:[0-9]+]]
+// CHECK: define{{.*}}foo145{{.*}}!type ![[TYPE145:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
pub fn foo146(_: Type13, _: Type13, _: Type13) { }
-// CHECK: define{{.*}}foo146{{.*}}!type ![[TYPE146:[0-9]+]]
+// CHECK: define{{.*}}foo146{{.*}}!type ![[TYPE146:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
pub fn foo147(_: Type14<Bar>) { }
-// CHECK: define{{.*}}foo147{{.*}}!type ![[TYPE147:[0-9]+]]
+// CHECK: define{{.*}}foo147{{.*}}!type ![[TYPE147:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
pub fn foo148(_: Type14<Bar>, _: Type14<Bar>) { }
-// CHECK: define{{.*}}foo148{{.*}}!type ![[TYPE148:[0-9]+]]
+// CHECK: define{{.*}}foo148{{.*}}!type ![[TYPE148:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
pub fn foo149(_: Type14<Bar>, _: Type14<Bar>, _: Type14<Bar>) { }
-// CHECK: define{{.*}}foo149{{.*}}!type ![[TYPE149:[0-9]+]]
+// CHECK: define{{.*}}foo149{{.*}}!type ![[TYPE149:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
// CHECK: ![[TYPE0]] = !{i64 0, !"_ZTSFvvE"}
// CHECK: ![[TYPE1]] = !{i64 0, !"_ZTSFvvvE"}
@@ -535,15 +536,15 @@ pub fn foo149(_: Type14<Bar>, _: Type14<Bar>, _: Type14<Bar>) { }
// CHECK: ![[TYPE93]] = !{i64 0, !"_ZTSFvPFu3i32S_EE"}
// CHECK: ![[TYPE94]] = !{i64 0, !"_ZTSFvPFu3i32S_ES0_E"}
// CHECK: ![[TYPE95]] = !{i64 0, !"_ZTSFvPFu3i32S_ES0_S0_E"}
-// CHECK: ![[TYPE96]] = !{i64 0, !"_ZTSFvu3refIu3dynIu{{[0-9]+}}NtNtNtC{{[[:print:]]+}}_4core3ops8function2FnIu5tupleIu3i32EEu{{[0-9]+}}NtNtNtNtC{{[[:print:]]+}}_4core3ops8function6FnOnce6OutputIS0_ES_u6regionEEE"}
-// CHECK: ![[TYPE97]] = !{i64 0, !"_ZTSFvu3refIu3dynIu{{[0-9]+}}NtNtNtC{{[[:print:]]+}}_4core3ops8function2FnIu5tupleIu3i32EEu{{[0-9]+}}NtNtNtNtC{{[[:print:]]+}}_4core3ops8function6FnOnce6OutputIS0_ES_u6regionEES5_E"}
-// CHECK: ![[TYPE98]] = !{i64 0, !"_ZTSFvu3refIu3dynIu{{[0-9]+}}NtNtNtC{{[[:print:]]+}}_4core3ops8function2FnIu5tupleIu3i32EEu{{[0-9]+}}NtNtNtNtC{{[[:print:]]+}}_4core3ops8function6FnOnce6OutputIS0_ES_u6regionEES5_S5_E"}
-// CHECK: ![[TYPE99]] = !{i64 0, !"_ZTSFvu3refIu3dynIu{{[0-9]+}}NtNtNtC{{[[:print:]]+}}_4core3ops8function5FnMutIu5tupleIu3i32EEu{{[0-9]+}}NtNtNtNtC{{[[:print:]]+}}_4core3ops8function6FnOnce6OutputIS0_ES_u6regionEEE"}
-// CHECK: ![[TYPE100]] = !{i64 0, !"_ZTSFvu3refIu3dynIu{{[0-9]+}}NtNtNtC{{[[:print:]]+}}_4core3ops8function5FnMutIu5tupleIu3i32EEu{{[0-9]+}}NtNtNtNtC{{[[:print:]]+}}_4core3ops8function6FnOnce6OutputIS0_ES_u6regionEES5_E"}
-// CHECK: ![[TYPE101]] = !{i64 0, !"_ZTSFvu3refIu3dynIu{{[0-9]+}}NtNtNtC{{[[:print:]]+}}_4core3ops8function5FnMutIu5tupleIu3i32EEu{{[0-9]+}}NtNtNtNtC{{[[:print:]]+}}_4core3ops8function6FnOnce6OutputIS0_ES_u6regionEES5_S5_E"}
-// CHECK: ![[TYPE102]] = !{i64 0, !"_ZTSFvu3refIu3dynIu{{[0-9]+}}NtNtNtC{{[[:print:]]+}}_4core3ops8function6FnOnceIu5tupleIu3i32EEu{{[0-9]+}}NtNtNtNtC{{[[:print:]]+}}_4core3ops8function6FnOnce6OutputIS0_ES_u6regionEEE"}
-// CHECK: ![[TYPE103]] = !{i64 0, !"_ZTSFvu3refIu3dynIu{{[0-9]+}}NtNtNtC{{[[:print:]]+}}_4core3ops8function6FnOnceIu5tupleIu3i32EEu{{[0-9]+}}NtNtNtNtC{{[[:print:]]+}}_4core3ops8function6FnOnce6OutputIS0_ES_u6regionEES5_E"}
-// CHECK: ![[TYPE104]] = !{i64 0, !"_ZTSFvu3refIu3dynIu{{[0-9]+}}NtNtNtC{{[[:print:]]+}}_4core3ops8function6FnOnceIu5tupleIu3i32EEu{{[0-9]+}}NtNtNtNtC{{[[:print:]]+}}_4core3ops8function6FnOnce6OutputIS0_ES_u6regionEES5_S5_E"}
+// CHECK: ![[TYPE96]] = !{i64 0, !"_ZTSFvu3refIu3dynIu{{[0-9]+}}NtNtNtC{{[[:print:]]+}}_4core3ops8function2FnIu5paramEu6regionEEE"}
+// CHECK: ![[TYPE97]] = !{i64 0, !"_ZTSFvu3refIu3dynIu{{[0-9]+}}NtNtNtC{{[[:print:]]+}}_4core3ops8function2FnIu5paramEu6regionEES3_E"}
+// CHECK: ![[TYPE98]] = !{i64 0, !"_ZTSFvu3refIu3dynIu{{[0-9]+}}NtNtNtC{{[[:print:]]+}}_4core3ops8function2FnIu5paramEu6regionEES3_S3_E"}
+// CHECK: ![[TYPE99]] = !{i64 0, !"_ZTSFvu3refIu3dynIu{{[0-9]+}}NtNtNtC{{[[:print:]]+}}_4core3ops8function5FnMutIu5paramEu6regionEEE"}
+// CHECK: ![[TYPE100]] = !{i64 0, !"_ZTSFvu3refIu3dynIu{{[0-9]+}}NtNtNtC{{[[:print:]]+}}_4core3ops8function5FnMutIu5paramEu6regionEES3_E"}
+// CHECK: ![[TYPE101]] = !{i64 0, !"_ZTSFvu3refIu3dynIu{{[0-9]+}}NtNtNtC{{[[:print:]]+}}_4core3ops8function5FnMutIu5paramEu6regionEES3_S3_E"}
+// CHECK: ![[TYPE102]] = !{i64 0, !"_ZTSFvu3refIu3dynIu{{[0-9]+}}NtNtNtC{{[[:print:]]+}}_4core3ops8function6FnOnceIu5paramEu6regionEEE"}
+// CHECK: ![[TYPE103]] = !{i64 0, !"_ZTSFvu3refIu3dynIu{{[0-9]+}}NtNtNtC{{[[:print:]]+}}_4core3ops8function6FnOnceIu5paramEu6regionEES3_E"}
+// CHECK: ![[TYPE104]] = !{i64 0, !"_ZTSFvu3refIu3dynIu{{[0-9]+}}NtNtNtC{{[[:print:]]+}}_4core3ops8function6FnOnceIu5paramEu6regionEES3_S3_E"}
// CHECK: ![[TYPE105]] = !{i64 0, !"_ZTSFvu3refIu3dynIu{{[0-9]+}}NtNtC{{[[:print:]]+}}_4core6marker4Sendu6regionEEE"}
// CHECK: ![[TYPE106]] = !{i64 0, !"_ZTSFvu3refIu3dynIu{{[0-9]+}}NtNtC{{[[:print:]]+}}_4core6marker4Sendu6regionEES2_E"}
// CHECK: ![[TYPE107]] = !{i64 0, !"_ZTSFvu3refIu3dynIu{{[0-9]+}}NtNtC{{[[:print:]]+}}_4core6marker4Sendu6regionEES2_S2_E"}
@@ -565,9 +566,9 @@ pub fn foo149(_: Type14<Bar>, _: Type14<Bar>, _: Type14<Bar>) { }
// CHECK: ![[TYPE123]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NvNINvC{{[[:print:]]+}}_51sanitizer_cfi_emit_type_metadata_id_itanium_cxx_abi3fn18{{[{}][{}]}}impl{{[}][}]}}3fooIu3i32EE"}
// CHECK: ![[TYPE124]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NvNINvC{{[[:print:]]+}}_51sanitizer_cfi_emit_type_metadata_id_itanium_cxx_abi3fn18{{[{}][{}]}}impl{{[}][}]}}3fooIu3i32ES0_E"}
// CHECK: ![[TYPE125]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NvNINvC{{[[:print:]]+}}_51sanitizer_cfi_emit_type_metadata_id_itanium_cxx_abi3fn18{{[{}][{}]}}impl{{[}][}]}}3fooIu3i32ES0_S0_E"}
-// CHECK: ![[TYPE126]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NvNtC{{[[:print:]]+}}_51sanitizer_cfi_emit_type_metadata_id_itanium_cxx_abi6Trait13fooIu3dynIu{{[0-9]+}}NtC{{[[:print:]]+}}_51sanitizer_cfi_emit_type_metadata_id_itanium_cxx_abi6Trait1Iu3i32Eu6regionES_EE"}
-// CHECK: ![[TYPE127]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NvNtC{{[[:print:]]+}}_51sanitizer_cfi_emit_type_metadata_id_itanium_cxx_abi6Trait13fooIu3dynIu{{[0-9]+}}NtC{{[[:print:]]+}}_51sanitizer_cfi_emit_type_metadata_id_itanium_cxx_abi6Trait1Iu3i32Eu6regionES_ES3_E"}
-// CHECK: ![[TYPE128]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NvNtC{{[[:print:]]+}}_51sanitizer_cfi_emit_type_metadata_id_itanium_cxx_abi6Trait13fooIu3dynIu{{[0-9]+}}NtC{{[[:print:]]+}}_51sanitizer_cfi_emit_type_metadata_id_itanium_cxx_abi6Trait1Iu3i32Eu6regionES_ES3_S3_E"}
+// CHECK: ![[TYPE126]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NvNtC{{[[:print:]]+}}_51sanitizer_cfi_emit_type_metadata_id_itanium_cxx_abi6Trait13fooIu3dynIu{{[0-9]+}}NtC{{[[:print:]]+}}_51sanitizer_cfi_emit_type_metadata_id_itanium_cxx_abi6Trait1Iu5paramEu6regionEu3i32EE"}
+// CHECK: ![[TYPE127]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NvNtC{{[[:print:]]+}}_51sanitizer_cfi_emit_type_metadata_id_itanium_cxx_abi6Trait13fooIu3dynIu{{[0-9]+}}NtC{{[[:print:]]+}}_51sanitizer_cfi_emit_type_metadata_id_itanium_cxx_abi6Trait1Iu5paramEu6regionEu3i32ES4_E"}
+// CHECK: ![[TYPE128]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NvNtC{{[[:print:]]+}}_51sanitizer_cfi_emit_type_metadata_id_itanium_cxx_abi6Trait13fooIu3dynIu{{[0-9]+}}NtC{{[[:print:]]+}}_51sanitizer_cfi_emit_type_metadata_id_itanium_cxx_abi6Trait1Iu5paramEu6regionEu3i32ES4_S4_E"}
// CHECK: ![[TYPE129]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NvNtC{{[[:print:]]+}}_51sanitizer_cfi_emit_type_metadata_id_itanium_cxx_abi6Trait13fooIu3i32S_EE"}
// CHECK: ![[TYPE130]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NvNtC{{[[:print:]]+}}_51sanitizer_cfi_emit_type_metadata_id_itanium_cxx_abi6Trait13fooIu3i32S_ES0_E"}
// CHECK: ![[TYPE131]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NvNtC{{[[:print:]]+}}_51sanitizer_cfi_emit_type_metadata_id_itanium_cxx_abi6Trait13fooIu3i32S_ES0_S0_E"}
diff --git a/tests/codegen/sanitizer-cfi-emit-type-metadata-itanium-cxx-abi-generalized.rs b/tests/codegen/sanitizer-cfi-emit-type-metadata-itanium-cxx-abi-generalized.rs
new file mode 100644
index 000000000..78ef0c2c7
--- /dev/null
+++ b/tests/codegen/sanitizer-cfi-emit-type-metadata-itanium-cxx-abi-generalized.rs
@@ -0,0 +1,31 @@
+// Verifies that generalized type metadata for functions are emitted.
+//
+// needs-sanitizer-cfi
+// compile-flags: -Clto -Cno-prepopulate-passes -Ctarget-feature=-crt-static -Zsanitizer=cfi -Zsanitizer-cfi-generalize-pointers
+
+#![crate_type="lib"]
+
+pub fn foo(f: fn(i32) -> i32, arg: i32) -> i32 {
+ // CHECK-LABEL: define{{.*}}foo
+ // CHECK-SAME: {{.*}}!type ![[TYPE1:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}}
+ // CHECK: call i1 @llvm.type.test({{i8\*|ptr}} {{%f|%0}}, metadata !"_ZTSFu3i32S_E.generalized")
+ f(arg)
+}
+
+pub fn bar(f: fn(i32, i32) -> i32, arg1: i32, arg2: i32) -> i32 {
+ // CHECK-LABEL: define{{.*}}bar
+ // CHECK-SAME: {{.*}}!type ![[TYPE2:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}}
+ // CHECK: call i1 @llvm.type.test({{i8\*|ptr}} {{%f|%0}}, metadata !"_ZTSFu3i32S_S_E.generalized")
+ f(arg1, arg2)
+}
+
+pub fn baz(f: fn(i32, i32, i32) -> i32, arg1: i32, arg2: i32, arg3: i32) -> i32 {
+ // CHECK-LABEL: define{{.*}}baz
+ // CHECK-SAME: {{.*}}!type ![[TYPE3:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}}
+ // CHECK: call i1 @llvm.type.test({{i8\*|ptr}} {{%f|%0}}, metadata !"_ZTSFu3i32S_S_S_E.generalized")
+ f(arg1, arg2, arg3)
+}
+
+// CHECK: ![[TYPE1]] = !{i64 0, !"_ZTSFu3i32PKvS_E.generalized"}
+// CHECK: ![[TYPE2]] = !{i64 0, !"_ZTSFu3i32PKvS_S_E.generalized"}
+// CHECK: ![[TYPE3]] = !{i64 0, !"_ZTSFu3i32PKvS_S_S_E.generalized"}
diff --git a/tests/codegen/sanitizer-cfi-emit-type-metadata-itanium-cxx-abi-normalized-generalized.rs b/tests/codegen/sanitizer-cfi-emit-type-metadata-itanium-cxx-abi-normalized-generalized.rs
new file mode 100644
index 000000000..3b72459c4
--- /dev/null
+++ b/tests/codegen/sanitizer-cfi-emit-type-metadata-itanium-cxx-abi-normalized-generalized.rs
@@ -0,0 +1,31 @@
+// Verifies that normalized and generalized type metadata for functions are emitted.
+//
+// needs-sanitizer-cfi
+// compile-flags: -Clto -Cno-prepopulate-passes -Ctarget-feature=-crt-static -Zsanitizer=cfi -Zsanitizer-cfi-normalize-integers -Zsanitizer-cfi-generalize-pointers
+
+#![crate_type="lib"]
+
+pub fn foo(f: fn(i32) -> i32, arg: i32) -> i32 {
+ // CHECK-LABEL: define{{.*}}foo
+ // CHECK-SAME: {{.*}}![[TYPE1:[0-9]+]]
+ // CHECK: call i1 @llvm.type.test({{i8\*|ptr}} {{%f|%0}}, metadata !"_ZTSFu3i32S_E.normalized.generalized")
+ f(arg)
+}
+
+pub fn bar(f: fn(i32, i32) -> i32, arg1: i32, arg2: i32) -> i32 {
+ // CHECK-LABEL: define{{.*}}bar
+ // CHECK-SAME: {{.*}}![[TYPE2:[0-9]+]]
+ // CHECK: call i1 @llvm.type.test({{i8\*|ptr}} {{%f|%0}}, metadata !"_ZTSFu3i32S_S_E.normalized.generalized")
+ f(arg1, arg2)
+}
+
+pub fn baz(f: fn(i32, i32, i32) -> i32, arg1: i32, arg2: i32, arg3: i32) -> i32 {
+ // CHECK-LABEL: define{{.*}}baz
+ // CHECK-SAME: {{.*}}![[TYPE3:[0-9]+]]
+ // CHECK: call i1 @llvm.type.test({{i8\*|ptr}} {{%f|%0}}, metadata !"_ZTSFu3i32S_S_S_E.normalized.generalized")
+ f(arg1, arg2, arg3)
+}
+
+// CHECK: ![[TYPE1]] = !{i64 0, !"_ZTSFu3i32PKvS_E.normalized.generalized"}
+// CHECK: ![[TYPE2]] = !{i64 0, !"_ZTSFu3i32PKvS_S_E.normalized.generalized"}
+// CHECK: ![[TYPE3]] = !{i64 0, !"_ZTSFu3i32PKvS_S_S_E.normalized.generalized"}
diff --git a/tests/codegen/sanitizer-cfi-emit-type-metadata-itanium-cxx-abi-normalized.rs b/tests/codegen/sanitizer-cfi-emit-type-metadata-itanium-cxx-abi-normalized.rs
new file mode 100644
index 000000000..9218e9947
--- /dev/null
+++ b/tests/codegen/sanitizer-cfi-emit-type-metadata-itanium-cxx-abi-normalized.rs
@@ -0,0 +1,31 @@
+// Verifies that normalized type metadata for functions are emitted.
+//
+// needs-sanitizer-cfi
+// compile-flags: -Clto -Cno-prepopulate-passes -Ctarget-feature=-crt-static -Zsanitizer=cfi -Zsanitizer-cfi-normalize-integers
+
+#![crate_type="lib"]
+
+pub fn foo(f: fn(i32) -> i32, arg: i32) -> i32 {
+ // CHECK-LABEL: define{{.*}}foo
+ // CHECK-SAME: {{.*}}!type ![[TYPE1:[0-9]+]] !type !{{[0-9]+}}
+ // CHECK: call i1 @llvm.type.test({{i8\*|ptr}} {{%f|%0}}, metadata !"_ZTSFu3i32S_E.normalized")
+ f(arg)
+}
+
+pub fn bar(f: fn(i32, i32) -> i32, arg1: i32, arg2: i32) -> i32 {
+ // CHECK-LABEL: define{{.*}}bar
+ // CHECK-SAME: {{.*}}!type ![[TYPE2:[0-9]+]] !type !{{[0-9]+}}
+ // CHECK: call i1 @llvm.type.test({{i8\*|ptr}} {{%f|%0}}, metadata !"_ZTSFu3i32S_S_E.normalized")
+ f(arg1, arg2)
+}
+
+pub fn baz(f: fn(i32, i32, i32) -> i32, arg1: i32, arg2: i32, arg3: i32) -> i32 {
+ // CHECK-LABEL: define{{.*}}baz
+ // CHECK-SAME: {{.*}}!type ![[TYPE3:[0-9]+]] !type !{{[0-9]+}}
+ // CHECK: call i1 @llvm.type.test({{i8\*|ptr}} {{%f|%0}}, metadata !"_ZTSFu3i32S_S_S_E.normalized")
+ f(arg1, arg2, arg3)
+}
+
+// CHECK: ![[TYPE1]] = !{i64 0, !"_ZTSFu3i32PFS_S_ES_E.normalized"}
+// CHECK: ![[TYPE2]] = !{i64 0, !"_ZTSFu3i32PFS_S_S_ES_S_E.normalized"}
+// CHECK: ![[TYPE3]] = !{i64 0, !"_ZTSFu3i32PFS_S_S_S_ES_S_S_E.normalized"}
diff --git a/tests/codegen/sanitizer-cfi-emit-type-metadata-itanium-cxx-abi.rs b/tests/codegen/sanitizer-cfi-emit-type-metadata-itanium-cxx-abi.rs
index bafc4c659..f9fd816de 100644
--- a/tests/codegen/sanitizer-cfi-emit-type-metadata-itanium-cxx-abi.rs
+++ b/tests/codegen/sanitizer-cfi-emit-type-metadata-itanium-cxx-abi.rs
@@ -7,21 +7,21 @@
pub fn foo(f: fn(i32) -> i32, arg: i32) -> i32 {
// CHECK-LABEL: define{{.*}}foo
- // CHECK-SAME: {{.*}}!type ![[TYPE1:[0-9]+]]
+ // CHECK-SAME: {{.*}}!type ![[TYPE1:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
// CHECK: call i1 @llvm.type.test({{i8\*|ptr}} {{%f|%0}}, metadata !"_ZTSFu3i32S_E")
f(arg)
}
pub fn bar(f: fn(i32, i32) -> i32, arg1: i32, arg2: i32) -> i32 {
// CHECK-LABEL: define{{.*}}bar
- // CHECK-SAME: {{.*}}!type ![[TYPE2:[0-9]+]]
+ // CHECK-SAME: {{.*}}!type ![[TYPE2:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
// CHECK: call i1 @llvm.type.test({{i8\*|ptr}} {{%f|%0}}, metadata !"_ZTSFu3i32S_S_E")
f(arg1, arg2)
}
pub fn baz(f: fn(i32, i32, i32) -> i32, arg1: i32, arg2: i32, arg3: i32) -> i32 {
// CHECK-LABEL: define{{.*}}baz
- // CHECK-SAME: {{.*}}!type ![[TYPE3:[0-9]+]]
+ // CHECK-SAME: {{.*}}!type ![[TYPE3:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
// CHECK: call i1 @llvm.type.test({{i8\*|ptr}} {{%f|%0}}, metadata !"_ZTSFu3i32S_S_S_E")
f(arg1, arg2, arg3)
}
diff --git a/tests/codegen/sanitizer-cfi-emit-type-metadata-trait-objects.rs b/tests/codegen/sanitizer-cfi-emit-type-metadata-trait-objects.rs
new file mode 100644
index 000000000..0f79adab7
--- /dev/null
+++ b/tests/codegen/sanitizer-cfi-emit-type-metadata-trait-objects.rs
@@ -0,0 +1,120 @@
+// Verifies that type metadata identifiers for trait objects are emitted correctly.
+//
+// needs-sanitizer-cfi
+// compile-flags: -Clto -Cno-prepopulate-passes -Copt-level=0 -Ctarget-feature=-crt-static -Zsanitizer=cfi
+
+#![crate_type="lib"]
+
+pub trait Trait1 {
+ fn foo(&self);
+}
+
+#[derive(Clone, Copy)]
+pub struct Type1;
+
+impl Trait1 for Type1 {
+ fn foo(&self) {
+ }
+}
+
+pub trait Trait2<T> {
+ fn bar(&self);
+}
+
+pub struct Type2;
+
+impl Trait2<i32> for Type2 {
+ fn bar(&self) {
+ }
+}
+
+pub trait Trait3<T> {
+ fn baz(&self, _: &T);
+}
+
+pub struct Type3;
+
+impl<T, U> Trait3<U> for T {
+ fn baz(&self, _: &U) {
+ }
+}
+
+pub trait Trait4<'a, T> {
+ type Output: 'a;
+ fn qux(&self, _: &T) -> Self::Output;
+}
+
+pub struct Type4;
+
+impl<'a, T, U> Trait4<'a, U> for T {
+ type Output = &'a i32;
+ fn qux(&self, _: &U) -> Self::Output {
+ &0
+ }
+}
+
+pub fn foo1(a: &dyn Trait1) {
+ a.foo();
+ // CHECK-LABEL: define{{.*}}4foo1{{.*}}!type !{{[0-9]+}}
+ // CHECK: call i1 @llvm.type.test({{i8\*|ptr}} {{%f|%[0-9]}}, metadata !"[[TYPE1:[[:print:]]+]]")
+}
+
+pub fn bar1() {
+ let a = Type1;
+ let b = &a as &dyn Trait1;
+ b.foo();
+ // CHECK-LABEL: define{{.*}}4bar1{{.*}}!type !{{[0-9]+}}
+ // CHECK: call i1 @llvm.type.test({{i8\*|ptr}} {{%f|%[0-9]}}, metadata !"[[TYPE2:[[:print:]]+]]")
+}
+
+pub fn foo2<T>(a: &dyn Trait2<T>) {
+ a.bar();
+ // CHECK-LABEL: define{{.*}}4foo2{{.*}}!type !{{[0-9]+}}
+ // CHECK: call i1 @llvm.type.test({{i8\*|ptr}} {{%f|%[0-9]}}, metadata !"[[TYPE2:[[:print:]]+]]")
+}
+
+pub fn bar2() {
+ let a = Type2;
+ foo2(&a);
+ let b = &a as &dyn Trait2<i32>;
+ b.bar();
+ // CHECK-LABEL: define{{.*}}4bar2{{.*}}!type !{{[0-9]+}}
+ // CHECK: call i1 @llvm.type.test({{i8\*|ptr}} {{%f|%[0-9]}}, metadata !"[[TYPE2:[[:print:]]+]]")
+}
+
+pub fn foo3(a: &dyn Trait3<Type3>) {
+ let b = Type3;
+ a.baz(&b);
+ // CHECK-LABEL: define{{.*}}4foo3{{.*}}!type !{{[0-9]+}}
+ // CHECK: call i1 @llvm.type.test({{i8\*|ptr}} {{%f|%[0-9]}}, metadata !"[[TYPE3:[[:print:]]+]]")
+}
+
+pub fn bar3() {
+ let a = Type3;
+ foo3(&a);
+ let b = &a as &dyn Trait3<Type3>;
+ b.baz(&a);
+ // CHECK-LABEL: define{{.*}}4bar3{{.*}}!type !{{[0-9]+}}
+ // CHECK: call i1 @llvm.type.test({{i8\*|ptr}} {{%f|%[0-9]}}, metadata !"[[TYPE3:[[:print:]]+]]")
+}
+
+pub fn foo4<'a>(a: &dyn Trait4<'a, Type4, Output = &'a i32>) {
+ let b = Type4;
+ a.qux(&b);
+ // CHECK-LABEL: define{{.*}}4foo4{{.*}}!type !{{[0-9]+}}
+ // CHECK: call i1 @llvm.type.test({{i8\*|ptr}} {{%f|%[0-9]}}, metadata !"[[TYPE4:[[:print:]]+]]")
+}
+
+pub fn bar4<'a>() {
+ let a = Type4;
+ foo4(&a);
+ let b = &a as &dyn Trait4<'a, Type4, Output = &'a i32>;
+ b.qux(&a);
+ // CHECK-LABEL: define{{.*}}4bar4{{.*}}!type !{{[0-9]+}}
+ // CHECK: call i1 @llvm.type.test({{i8\*|ptr}} {{%f|%[0-9]}}, metadata !"[[TYPE4:[[:print:]]+]]")
+}
+
+// CHECK: !{{[0-9]+}} = !{i64 0, !"[[TYPE1]]"}
+// CHECK: !{{[0-9]+}} = !{i64 0, !"[[TYPE2]]"}
+// CHECK: !{{[0-9]+}} = !{i64 0, !"[[TYPE3]]"}
+// CHECK: !{{[0-9]+}} = !{i64 0, !"[[TYPE4]]"}
diff --git a/tests/codegen/sanitizer-cfi-generalize-pointers.rs b/tests/codegen/sanitizer-cfi-generalize-pointers.rs
new file mode 100644
index 000000000..677ebdb27
--- /dev/null
+++ b/tests/codegen/sanitizer-cfi-generalize-pointers.rs
@@ -0,0 +1,46 @@
+// Verifies that pointer types are generalized.
+//
+// needs-sanitizer-cfi
+// compile-flags: -Clto -Cno-prepopulate-passes -Ctarget-feature=-crt-static -Zsanitizer=cfi -Zsanitizer-cfi-generalize-pointers
+
+#![crate_type="lib"]
+
+extern crate core;
+
+pub fn foo0(_: &mut i32) { }
+// CHECK: define{{.*}}foo0{{.*}}!type ![[TYPE0:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}}
+pub fn foo1(_: &mut i32, _: &mut i32) { }
+// CHECK: define{{.*}}foo1{{.*}}!type ![[TYPE1:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}}
+pub fn foo2(_: &mut i32, _: &mut i32, _: &mut i32) { }
+// CHECK: define{{.*}}foo2{{.*}}!type ![[TYPE2:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}}
+pub fn foo3(_: &i32) { }
+// CHECK: define{{.*}}foo3{{.*}}!type ![[TYPE3:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}}
+pub fn foo4(_: &i32, _: &i32) { }
+// CHECK: define{{.*}}foo4{{.*}}!type ![[TYPE4:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}}
+pub fn foo5(_: &i32, _: &i32, _: &i32) { }
+// CHECK: define{{.*}}foo5{{.*}}!type ![[TYPE5:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}}
+pub fn foo6(_: *mut i32) { }
+// CHECK: define{{.*}}foo6{{.*}}!type ![[TYPE6:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}}
+pub fn foo7(_: *mut i32, _: *mut i32) { }
+// CHECK: define{{.*}}foo7{{.*}}!type ![[TYPE7:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}}
+pub fn foo8(_: *mut i32, _: *mut i32, _: *mut i32) { }
+// CHECK: define{{.*}}foo8{{.*}}!type ![[TYPE8:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}}
+pub fn foo9(_: *const i32) { }
+// CHECK: define{{.*}}foo9{{.*}}!type ![[TYPE9:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}}
+pub fn foo10(_: *const i32, _: *const i32) { }
+// CHECK: define{{.*}}foo10{{.*}}!type ![[TYPE10:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}}
+pub fn foo11(_: *const i32, _: *const i32, _: *const i32) { }
+// CHECK: define{{.*}}foo11{{.*}}!type ![[TYPE11:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}}
+
+// CHECK: ![[TYPE0]] = !{i64 0, !"_ZTSFvU3mutu3refIvEE.generalized"}
+// CHECK: ![[TYPE1]] = !{i64 0, !"_ZTSFvU3mutu3refIvES0_E.generalized"}
+// CHECK: ![[TYPE2]] = !{i64 0, !"_ZTSFvU3mutu3refIvES0_S0_E.generalized"}
+// CHECK: ![[TYPE3]] = !{i64 0, !"_ZTSFvu3refIvEE.generalized"}
+// CHECK: ![[TYPE4]] = !{i64 0, !"_ZTSFvu3refIvES_E.generalized"}
+// CHECK: ![[TYPE5]] = !{i64 0, !"_ZTSFvu3refIvES_S_E.generalized"}
+// CHECK: ![[TYPE6]] = !{i64 0, !"_ZTSFvPvE.generalized"}
+// CHECK: ![[TYPE7]] = !{i64 0, !"_ZTSFvPvS_E.generalized"}
+// CHECK: ![[TYPE8]] = !{i64 0, !"_ZTSFvPvS_S_E.generalized"}
+// CHECK: ![[TYPE9]] = !{i64 0, !"_ZTSFvPKvE.generalized"}
+// CHECK: ![[TYPE10]] = !{i64 0, !"_ZTSFvPKvS0_E.generalized"}
+// CHECK: ![[TYPE11]] = !{i64 0, !"_ZTSFvPKvS0_S0_E.generalized"}
diff --git a/tests/codegen/sanitizer-cfi-normalize-integers.rs b/tests/codegen/sanitizer-cfi-normalize-integers.rs
new file mode 100644
index 000000000..aa3913cb8
--- /dev/null
+++ b/tests/codegen/sanitizer-cfi-normalize-integers.rs
@@ -0,0 +1,83 @@
+// Verifies that integer types are normalized.
+//
+// needs-sanitizer-cfi
+// compile-flags: -Clto -Cno-prepopulate-passes -Ctarget-feature=-crt-static -Zsanitizer=cfi -Zsanitizer-cfi-normalize-integers
+
+#![crate_type="lib"]
+
+extern crate core;
+use core::ffi::*;
+
+pub fn foo0(_: bool) { }
+// CHECK: define{{.*}}foo0{{.*}}!type ![[TYPE0:[0-9]+]] !type !{{[0-9]+}}
+pub fn foo1(_: bool, _: c_uchar) { }
+// CHECK: define{{.*}}foo1{{.*}}!type ![[TYPE1:[0-9]+]] !type !{{[0-9]+}}
+pub fn foo2(_: bool, _: c_uchar, _: c_uchar) { }
+// CHECK: define{{.*}}foo2{{.*}}!type ![[TYPE2:[0-9]+]] !type !{{[0-9]+}}
+pub fn foo3(_: isize) { }
+// CHECK: define{{.*}}foo3{{.*}}!type ![[TYPE3:[0-9]+]] !type !{{[0-9]+}}
+pub fn foo4(_: isize, _: c_long) { }
+// CHECK: define{{.*}}foo4{{.*}}!type ![[TYPE4:[0-9]+]] !type !{{[0-9]+}}
+pub fn foo5(_: isize, _: c_long, _: c_longlong) { }
+// CHECK: define{{.*}}foo5{{.*}}!type ![[TYPE5:[0-9]+]] !type !{{[0-9]+}}
+pub fn foo6(_: usize) { }
+// CHECK: define{{.*}}foo6{{.*}}!type ![[TYPE6:[0-9]+]] !type !{{[0-9]+}}
+pub fn foo7(_: usize, _: c_ulong) { }
+// CHECK: define{{.*}}foo7{{.*}}!type ![[TYPE7:[0-9]+]] !type !{{[0-9]+}}
+pub fn foo8(_: usize, _: c_ulong, _: c_ulonglong) { }
+// CHECK: define{{.*}}foo8{{.*}}!type ![[TYPE8:[0-9]+]] !type !{{[0-9]+}}
+pub fn foo9(_: c_schar) { }
+// CHECK: define{{.*}}foo9{{.*}}!type ![[TYPE9:[0-9]+]] !type !{{[0-9]+}}
+pub fn foo10(_: c_char, _: c_schar) { }
+// CHECK: define{{.*}}foo10{{.*}}!type ![[TYPE10:[0-9]+]] !type !{{[0-9]+}}
+pub fn foo11(_: c_char, _: c_schar, _: c_schar) { }
+// CHECK: define{{.*}}foo11{{.*}}!type ![[TYPE11:[0-9]+]] !type !{{[0-9]+}}
+pub fn foo12(_: c_int) { }
+// CHECK: define{{.*}}foo12{{.*}}!type ![[TYPE12:[0-9]+]] !type !{{[0-9]+}}
+pub fn foo13(_: c_int, _: c_int) { }
+// CHECK: define{{.*}}foo13{{.*}}!type ![[TYPE13:[0-9]+]] !type !{{[0-9]+}}
+pub fn foo14(_: c_int, _: c_int, _: c_int) { }
+// CHECK: define{{.*}}foo14{{.*}}!type ![[TYPE14:[0-9]+]] !type !{{[0-9]+}}
+pub fn foo15(_: c_short) { }
+// CHECK: define{{.*}}foo15{{.*}}!type ![[TYPE15:[0-9]+]] !type !{{[0-9]+}}
+pub fn foo16(_: c_short, _: c_short) { }
+// CHECK: define{{.*}}foo16{{.*}}!type ![[TYPE16:[0-9]+]] !type !{{[0-9]+}}
+pub fn foo17(_: c_short, _: c_short, _: c_short) { }
+// CHECK: define{{.*}}foo17{{.*}}!type ![[TYPE17:[0-9]+]] !type !{{[0-9]+}}
+pub fn foo18(_: c_uint) { }
+// CHECK: define{{.*}}foo18{{.*}}!type ![[TYPE18:[0-9]+]] !type !{{[0-9]+}}
+pub fn foo19(_: c_uint, _: c_uint) { }
+// CHECK: define{{.*}}foo19{{.*}}!type ![[TYPE19:[0-9]+]] !type !{{[0-9]+}}
+pub fn foo20(_: c_uint, _: c_uint, _: c_uint) { }
+// CHECK: define{{.*}}foo20{{.*}}!type ![[TYPE20:[0-9]+]] !type !{{[0-9]+}}
+pub fn foo21(_: c_ushort) { }
+// CHECK: define{{.*}}foo21{{.*}}!type ![[TYPE21:[0-9]+]] !type !{{[0-9]+}}
+pub fn foo22(_: c_ushort, _: c_ushort) { }
+// CHECK: define{{.*}}foo22{{.*}}!type ![[TYPE22:[0-9]+]] !type !{{[0-9]+}}
+pub fn foo23(_: c_ushort, _: c_ushort, _: c_ushort) { }
+// CHECK: define{{.*}}foo23{{.*}}!type ![[TYPE23:[0-9]+]] !type !{{[0-9]+}}
+
+// CHECK: ![[TYPE0]] = !{i64 0, !"_ZTSFvu2u8E.normalized"}
+// CHECK: ![[TYPE1]] = !{i64 0, !"_ZTSFvu2u8S_E.normalized"}
+// CHECK: ![[TYPE2]] = !{i64 0, !"_ZTSFvu2u8S_S_E.normalized"}
+// CHECK: ![[TYPE3]] = !{i64 0, !"_ZTSFv{{u3i16|u3i32|u3i64}}E.normalized"}
+// CHECK: ![[TYPE4]] = !{i64 0, !"_ZTSFv{{u3i16|u3i32|u3i64}}{{u3i32|u3i64|S_}}E.normalized"}
+// CHECK: ![[TYPE5]] = !{i64 0, !"_ZTSFv{{u3i16|u3i32|u3i64}}{{u3i32|u3i64|S_}}{{u3i64|S_|S0_}}E.normalized"}
+// CHECK: ![[TYPE6]] = !{i64 0, !"_ZTSFv{{u3u16|u3u32|u3u64}}E.normalized"}
+// CHECK: ![[TYPE7]] = !{i64 0, !"_ZTSFv{{u3u16|u3u32|u3u64}}{{u3u32|u3u64|S_}}E.normalized"}
+// CHECK: ![[TYPE8]] = !{i64 0, !"_ZTSFv{{u3u16|u3u32|u3u64}}{{u3u32|u3u64|S_}}{{u3u64|S_|S0_}}E.normalized"}
+// CHECK: ![[TYPE9]] = !{i64 0, !"_ZTSFvu2i8E.normalized"}
+// CHECK: ![[TYPE10]] = !{i64 0, !"_ZTSFv{{u2i8S_|u2u8u2i8}}E.normalized"}
+// CHECK: ![[TYPE11]] = !{i64 0, !"_ZTSFv{{u2i8S_S_|u2u8u2i8S0_}}E.normalized"}
+// CHECK: ![[TYPE12]] = !{i64 0, !"_ZTSFv{{u3i16|u3i32|u3i64}}E.normalized"}
+// CHECK: ![[TYPE13]] = !{i64 0, !"_ZTSFv{{u3i16|u3i32|u3i64}}S_E.normalized"}
+// CHECK: ![[TYPE14]] = !{i64 0, !"_ZTSFv{{u3i16|u3i32|u3i64}}S_S_E.normalized"}
+// CHECK: ![[TYPE15]] = !{i64 0, !"_ZTSFvu3i16E.normalized"}
+// CHECK: ![[TYPE16]] = !{i64 0, !"_ZTSFvu3i16S_E.normalized"}
+// CHECK: ![[TYPE17]] = !{i64 0, !"_ZTSFvu3i16S_S_E.normalized"}
+// CHECK: ![[TYPE18]] = !{i64 0, !"_ZTSFv{{u3u16|u3u32|u3u64}}E.normalized"}
+// CHECK: ![[TYPE19]] = !{i64 0, !"_ZTSFv{{u3u16|u3u32|u3u64}}S_E.normalized"}
+// CHECK: ![[TYPE20]] = !{i64 0, !"_ZTSFv{{u3u16|u3u32|u3u64}}S_S_E.normalized"}
+// CHECK: ![[TYPE21]] = !{i64 0, !"_ZTSFvu3u16E.normalized"}
+// CHECK: ![[TYPE22]] = !{i64 0, !"_ZTSFvu3u16S_E.normalized"}
+// CHECK: ![[TYPE23]] = !{i64 0, !"_ZTSFvu3u16S_S_E.normalized"}
diff --git a/tests/codegen/sanitizer-kcfi-emit-kcfi-operand-bundle-attr-no-sanitize.rs b/tests/codegen/sanitizer-kcfi-emit-kcfi-operand-bundle-attr-no-sanitize.rs
new file mode 100644
index 000000000..bb317e4a2
--- /dev/null
+++ b/tests/codegen/sanitizer-kcfi-emit-kcfi-operand-bundle-attr-no-sanitize.rs
@@ -0,0 +1,30 @@
+// Verifies that KCFI operand bundles are omitted.
+//
+// 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:
+// compile-flags: -Cno-prepopulate-passes -Zsanitizer=kcfi -Copt-level=0
+
+#![crate_type="lib"]
+#![feature(no_core, no_sanitize, lang_items)]
+#![no_core]
+
+#[lang="sized"]
+trait Sized { }
+#[lang="copy"]
+trait Copy { }
+
+impl Copy for i32 {}
+
+#[no_sanitize(kcfi)]
+pub fn foo(f: fn(i32) -> i32, arg: i32) -> i32 {
+ // CHECK-LABEL: sanitizer_kcfi_emit_kcfi_operand_bundle_attr_no_sanitize::foo
+ // CHECK: Function Attrs: {{.*}}
+ // CHECK-LABEL: define{{.*}}foo{{.*}}!{{<unknown kind #36>|kcfi_type}} !{{[0-9]+}}
+ // CHECK: start:
+ // CHECK-NOT: {{%.+}} = call {{(noundef )*}}i32 %f(i32 {{(noundef )*}}%arg){{.*}}[ "kcfi"(i32 {{[-0-9]+}}) ]
+ // CHECK: ret i32 {{%.+}}
+ f(arg)
+}
diff --git a/tests/codegen/sanitizer-kcfi-emit-kcfi-operand-bundle-itanium-cxx-abi-generalized.rs b/tests/codegen/sanitizer-kcfi-emit-kcfi-operand-bundle-itanium-cxx-abi-generalized.rs
new file mode 100644
index 000000000..29e4df351
--- /dev/null
+++ b/tests/codegen/sanitizer-kcfi-emit-kcfi-operand-bundle-itanium-cxx-abi-generalized.rs
@@ -0,0 +1,44 @@
+// Verifies that generalized KCFI type metadata for functions are emitted.
+//
+// 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:
+// compile-flags: -Cno-prepopulate-passes -Zsanitizer=kcfi -Zsanitizer-cfi-generalize-pointers
+
+#![crate_type="lib"]
+#![feature(no_core, lang_items)]
+#![no_core]
+
+#[lang="sized"]
+trait Sized { }
+#[lang="copy"]
+trait Copy { }
+
+impl Copy for i32 {}
+
+pub fn foo(f: fn(i32) -> i32, arg: i32) -> i32 {
+ // CHECK-LABEL: define{{.*}}foo
+ // CHECK-SAME: {{.*}}!{{<unknown kind #36>|kcfi_type}} ![[TYPE1:[0-9]+]]
+ // CHECK: {{%.+}} = call {{(noundef )*}}i32 %f(i32 {{(noundef )*}}%arg){{.*}}[ "kcfi"(i32 233085384) ]
+ f(arg)
+}
+
+pub fn bar(f: fn(i32, i32) -> i32, arg1: i32, arg2: i32) -> i32 {
+ // CHECK-LABEL: define{{.*}}bar
+ // CHECK-SAME: {{.*}}!{{<unknown kind #36>|kcfi_type}} ![[TYPE2:[0-9]+]]
+ // CHECK: {{%.+}} = call {{(noundef )*}}i32 %f(i32 {{(noundef )*}}%arg1, i32 {{(noundef )*}}%arg2){{.*}}[ "kcfi"(i32 435418021) ]
+ f(arg1, arg2)
+}
+
+pub fn baz(f: fn(i32, i32, i32) -> i32, arg1: i32, arg2: i32, arg3: i32) -> i32 {
+ // CHECK-LABEL: define{{.*}}baz
+ // CHECK-SAME: {{.*}}!{{<unknown kind #36>|kcfi_type}} ![[TYPE3:[0-9]+]]
+ // CHECK: {{%.+}} = call {{(noundef )*}}i32 %f(i32 {{(noundef )*}}%arg1, i32 {{(noundef )*}}%arg2, i32 {{(noundef )*}}%arg3){{.*}}[ "kcfi"(i32 -1003721339) ]
+ f(arg1, arg2, arg3)
+}
+
+// CHECK: ![[TYPE1]] = !{i32 -1741689296}
+// CHECK: ![[TYPE2]] = !{i32 489439372}
+// CHECK: ![[TYPE3]] = !{i32 2026563871}
diff --git a/tests/codegen/sanitizer-kcfi-emit-kcfi-operand-bundle-itanium-cxx-abi-normalized-generalized.rs b/tests/codegen/sanitizer-kcfi-emit-kcfi-operand-bundle-itanium-cxx-abi-normalized-generalized.rs
new file mode 100644
index 000000000..84d678a33
--- /dev/null
+++ b/tests/codegen/sanitizer-kcfi-emit-kcfi-operand-bundle-itanium-cxx-abi-normalized-generalized.rs
@@ -0,0 +1,44 @@
+// Verifies that normalized and generalized KCFI type metadata for functions are emitted.
+//
+// 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:
+// compile-flags: -Cno-prepopulate-passes -Zsanitizer=kcfi -Zsanitizer-cfi-normalize-integers -Zsanitizer-cfi-generalize-pointers
+
+#![crate_type="lib"]
+#![feature(no_core, lang_items)]
+#![no_core]
+
+#[lang="sized"]
+trait Sized { }
+#[lang="copy"]
+trait Copy { }
+
+impl Copy for i32 {}
+
+pub fn foo(f: fn(i32) -> i32, arg: i32) -> i32 {
+ // CHECK-LABEL: define{{.*}}foo
+ // CHECK-SAME: {{.*}}!{{<unknown kind #36>|kcfi_type}} ![[TYPE1:[0-9]+]]
+ // CHECK: {{%.+}} = call {{(noundef )*}}i32 %f(i32 {{(noundef )*}}%arg){{.*}}[ "kcfi"(i32 -686570305) ]
+ f(arg)
+}
+
+pub fn bar(f: fn(i32, i32) -> i32, arg1: i32, arg2: i32) -> i32 {
+ // CHECK-LABEL: define{{.*}}bar
+ // CHECK-SAME: {{.*}}!{{<unknown kind #36>|kcfi_type}} ![[TYPE2:[0-9]+]]
+ // CHECK: {{%.+}} = call {{(noundef )*}}i32 %f(i32 {{(noundef )*}}%arg1, i32 {{(noundef )*}}%arg2){{.*}}[ "kcfi"(i32 1281038450) ]
+ f(arg1, arg2)
+}
+
+pub fn baz(f: fn(i32, i32, i32) -> i32, arg1: i32, arg2: i32, arg3: i32) -> i32 {
+ // CHECK-LABEL: define{{.*}}baz
+ // CHECK-SAME: {{.*}}!{{<unknown kind #36>|kcfi_type}} ![[TYPE3:[0-9]+]]
+ // CHECK: {{%.+}} = call {{(noundef )*}}i32 %f(i32 {{(noundef )*}}%arg1, i32 {{(noundef )*}}%arg2, i32 {{(noundef )*}}%arg3){{.*}}[ "kcfi"(i32 -1751512973) ]
+ f(arg1, arg2, arg3)
+}
+
+// CHECK: ![[TYPE1]] = !{i32 975484707}
+// CHECK: ![[TYPE2]] = !{i32 1658833102}
+// CHECK: ![[TYPE3]] = !{i32 230429758}
diff --git a/tests/codegen/sanitizer-kcfi-emit-kcfi-operand-bundle-itanium-cxx-abi-normalized.rs b/tests/codegen/sanitizer-kcfi-emit-kcfi-operand-bundle-itanium-cxx-abi-normalized.rs
new file mode 100644
index 000000000..761c37a9e
--- /dev/null
+++ b/tests/codegen/sanitizer-kcfi-emit-kcfi-operand-bundle-itanium-cxx-abi-normalized.rs
@@ -0,0 +1,44 @@
+// Verifies that normalized KCFI type metadata for functions are emitted.
+//
+// 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:
+// compile-flags: -Cno-prepopulate-passes -Zsanitizer=kcfi -Zsanitizer-cfi-normalize-integers
+
+#![crate_type="lib"]
+#![feature(no_core, lang_items)]
+#![no_core]
+
+#[lang="sized"]
+trait Sized { }
+#[lang="copy"]
+trait Copy { }
+
+impl Copy for i32 {}
+
+pub fn foo(f: fn(i32) -> i32, arg: i32) -> i32 {
+ // CHECK-LABEL: define{{.*}}foo
+ // CHECK-SAME: {{.*}}!{{<unknown kind #36>|kcfi_type}} ![[TYPE1:[0-9]+]]
+ // CHECK: {{%.+}} = call {{(noundef )*}}i32 %f(i32 {{(noundef )*}}%arg){{.*}}[ "kcfi"(i32 -841055669) ]
+ f(arg)
+}
+
+pub fn bar(f: fn(i32, i32) -> i32, arg1: i32, arg2: i32) -> i32 {
+ // CHECK-LABEL: define{{.*}}bar
+ // CHECK-SAME: {{.*}}!{{<unknown kind #36>|kcfi_type}} ![[TYPE2:[0-9]+]]
+ // CHECK: {{%.+}} = call {{(noundef )*}}i32 %f(i32 {{(noundef )*}}%arg1, i32 {{(noundef )*}}%arg2){{.*}}[ "kcfi"(i32 1390819368) ]
+ f(arg1, arg2)
+}
+
+pub fn baz(f: fn(i32, i32, i32) -> i32, arg1: i32, arg2: i32, arg3: i32) -> i32 {
+ // CHECK-LABEL: define{{.*}}baz
+ // CHECK-SAME: {{.*}}!{{<unknown kind #36>|kcfi_type}} ![[TYPE3:[0-9]+]]
+ // CHECK: {{%.+}} = call {{(noundef )*}}i32 %f(i32 {{(noundef )*}}%arg1, i32 {{(noundef )*}}%arg2, i32 {{(noundef )*}}%arg3){{.*}}[ "kcfi"(i32 586925835) ]
+ f(arg1, arg2, arg3)
+}
+
+// CHECK: ![[TYPE1]] = !{i32 -458317079}
+// CHECK: ![[TYPE2]] = !{i32 1737138182}
+// CHECK: ![[TYPE3]] = !{i32 197182412}
diff --git a/tests/codegen/sanitizer-kcfi-emit-kcfi-operand-bundle-itanium-cxx-abi.rs b/tests/codegen/sanitizer-kcfi-emit-kcfi-operand-bundle-itanium-cxx-abi.rs
index 2537df80a..83cda0ef1 100644
--- a/tests/codegen/sanitizer-kcfi-emit-kcfi-operand-bundle-itanium-cxx-abi.rs
+++ b/tests/codegen/sanitizer-kcfi-emit-kcfi-operand-bundle-itanium-cxx-abi.rs
@@ -20,22 +20,22 @@ impl Copy for i32 {}
pub fn foo(f: fn(i32) -> i32, arg: i32) -> i32 {
// CHECK-LABEL: define{{.*}}foo
- // CHECK-SAME: {{.*}}!{{<unknown kind #36>|kcfi_type}} ![[TYPE1:[0-9]+]]
- // CHECK: call i32 %f(i32 %arg){{.*}}[ "kcfi"(i32 -1666898348) ]
+ // CHECK-SAME: {{.*}}!{{<unknown kind #36>|kcfi_type}} ![[TYPE1:[0-9]+]]
+ // CHECK: {{%.+}} = call {{(noundef )*}}i32 %f(i32 {{(noundef )*}}%arg){{.*}}[ "kcfi"(i32 -1666898348) ]
f(arg)
}
pub fn bar(f: fn(i32, i32) -> i32, arg1: i32, arg2: i32) -> i32 {
// CHECK-LABEL: define{{.*}}bar
- // CHECK-SAME: {{.*}}!{{<unknown kind #36>|kcfi_type}} ![[TYPE2:[0-9]+]]
- // CHECK: call i32 %f(i32 %arg1, i32 %arg2){{.*}}[ "kcfi"(i32 -1789026986) ]
+ // CHECK-SAME: {{.*}}!{{<unknown kind #36>|kcfi_type}} ![[TYPE2:[0-9]+]]
+ // CHECK: {{%.+}} = call {{(noundef )*}}i32 %f(i32 {{(noundef )*}}%arg1, i32 {{(noundef )*}}%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
- // CHECK-SAME: {{.*}}!{{<unknown kind #36>|kcfi_type}} ![[TYPE3:[0-9]+]]
- // CHECK: call i32 %f(i32 %arg1, i32 %arg2, i32 %arg3){{.*}}[ "kcfi"(i32 1248878270) ]
+ // CHECK-SAME: {{.*}}!{{<unknown kind #36>|kcfi_type}} ![[TYPE3:[0-9]+]]
+ // CHECK: {{%.+}} = call {{(noundef )*}}i32 %f(i32 {{(noundef )*}}%arg1, i32 {{(noundef )*}}%arg2, i32 {{(noundef )*}}%arg3){{.*}}[ "kcfi"(i32 1248878270) ]
f(arg1, arg2, arg3)
}
diff --git a/tests/codegen/sanitizer-kcfi-emit-kcfi-operand-bundle.rs b/tests/codegen/sanitizer-kcfi-emit-kcfi-operand-bundle.rs
new file mode 100644
index 000000000..e1d617b5e
--- /dev/null
+++ b/tests/codegen/sanitizer-kcfi-emit-kcfi-operand-bundle.rs
@@ -0,0 +1,27 @@
+// Verifies that KCFI operand bundles are emitted.
+//
+// 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:
+// compile-flags: -Cno-prepopulate-passes -Zsanitizer=kcfi -Copt-level=0
+
+#![crate_type="lib"]
+#![feature(no_core, lang_items)]
+#![no_core]
+
+#[lang="sized"]
+trait Sized { }
+#[lang="copy"]
+trait Copy { }
+
+impl Copy for i32 {}
+
+pub fn foo(f: fn(i32) -> i32, arg: i32) -> i32 {
+ // CHECK-LABEL: define{{.*}}foo{{.*}}!{{<unknown kind #36>|kcfi_type}} !{{[0-9]+}}
+ // CHECK: start:
+ // CHECK-NEXT: {{%.+}} = call {{(noundef )*}}i32 %f(i32 {{(noundef )*}}%arg){{.*}}[ "kcfi"(i32 {{[-0-9]+}}) ]
+ // CHECK-NEXT: ret i32 {{%.+}}
+ f(arg)
+}
diff --git a/tests/codegen/sanitizer-kcfi-emit-type-metadata-trait-objects.rs b/tests/codegen/sanitizer-kcfi-emit-type-metadata-trait-objects.rs
new file mode 100644
index 000000000..004a67e7d
--- /dev/null
+++ b/tests/codegen/sanitizer-kcfi-emit-type-metadata-trait-objects.rs
@@ -0,0 +1,144 @@
+// Verifies that type metadata identifiers for trait objects are emitted correctly.
+//
+// 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:
+// compile-flags: -Cno-prepopulate-passes -Zsanitizer=kcfi -Copt-level=0
+
+#![crate_type="lib"]
+#![feature(arbitrary_self_types, no_core, lang_items)]
+#![no_core]
+
+#[lang="sized"]
+trait Sized { }
+#[lang="copy"]
+trait Copy { }
+#[lang="receiver"]
+trait Receiver { }
+#[lang="dispatch_from_dyn"]
+trait DispatchFromDyn<T> { }
+impl<'a, T: ?Sized + Unsize<U>, U: ?Sized> DispatchFromDyn<&'a U> for &'a T {}
+#[lang = "unsize"]
+trait Unsize<T: ?Sized> { }
+#[lang = "coerce_unsized"]
+pub trait CoerceUnsized<T: ?Sized> { }
+impl<'a, 'b: 'a, T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<&'a U> for &'b T {}
+#[lang="freeze"]
+trait Freeze { }
+#[lang="drop_in_place"]
+fn drop_in_place_fn<T>() { }
+
+pub trait Trait1 {
+ fn foo(&self);
+}
+
+pub struct Type1;
+
+impl Trait1 for Type1 {
+ fn foo(&self) {
+ }
+}
+
+pub trait Trait2<T> {
+ fn bar(&self);
+}
+
+pub struct Type2;
+
+impl Trait2<i32> for Type2 {
+ fn bar(&self) {
+ }
+}
+
+pub trait Trait3<T> {
+ fn baz(&self, _: &T);
+}
+
+pub struct Type3;
+
+impl<T, U> Trait3<U> for T {
+ fn baz(&self, _: &U) {
+ }
+}
+
+pub trait Trait4<'a, T> {
+ type Output: 'a;
+ fn qux(&self, _: &T) -> Self::Output;
+}
+
+pub struct Type4;
+
+impl<'a, T, U> Trait4<'a, U> for T {
+ type Output = &'a i32;
+ fn qux(&self, _: &U) -> Self::Output {
+ &0
+ }
+}
+
+pub fn foo1(a: &dyn Trait1) {
+ a.foo();
+ // CHECK-LABEL: define{{.*}}4foo1{{.*}}!{{<unknown kind #36>|kcfi_type}} !{{[0-9]+}}
+ // CHECK: call void %{{[0-9]}}({{\{\}\*|ptr}} align 1 {{%[a-z]\.0|%_[0-9]}}){{.*}}[ "kcfi"(i32 [[TYPE1:[[:print:]]+]]) ]
+}
+
+pub fn bar1() {
+ let a = Type1;
+ let b = &a as &dyn Trait1;
+ b.foo();
+ // CHECK-LABEL: define{{.*}}4bar1{{.*}}!{{<unknown kind #36>|kcfi_type}} !{{[0-9]+}}
+ // CHECK: call void %{{[0-9]}}({{\{\}\*|ptr}} align 1 {{%[a-z]\.0|%_[0-9]}}){{.*}}[ "kcfi"(i32 [[TYPE1:[[:print:]]+]]) ]
+}
+
+pub fn foo2<T>(a: &dyn Trait2<T>) {
+ a.bar();
+ // CHECK-LABEL: define{{.*}}4foo2{{.*}}!{{<unknown kind #36>|kcfi_type}} !{{[0-9]+}}
+ // CHECK: call void %{{[0-9]}}({{\{\}\*|ptr}} align 1 {{%[a-z]\.0|%_[0-9]}}){{.*}}[ "kcfi"(i32 [[TYPE2:[[:print:]]+]]) ]
+}
+
+pub fn bar2() {
+ let a = Type2;
+ foo2(&a);
+ let b = &a as &dyn Trait2<i32>;
+ b.bar();
+ // CHECK-LABEL: define{{.*}}4bar2{{.*}}!{{<unknown kind #36>|kcfi_type}} !{{[0-9]+}}
+ // CHECK: call void %{{[0-9]}}({{\{\}\*|ptr}} align 1 {{%[a-z]\.0|%_[0-9]}}){{.*}}[ "kcfi"(i32 [[TYPE2:[[:print:]]+]]) ]
+}
+
+pub fn foo3(a: &dyn Trait3<Type3>) {
+ let b = Type3;
+ a.baz(&b);
+ // CHECK-LABEL: define{{.*}}4foo3{{.*}}!{{<unknown kind #36>|kcfi_type}} !{{[0-9]+}}
+ // CHECK: call void %{{[0-9]}}({{\{\}\*|ptr}} align 1 {{%[a-z]\.0|%_[0-9]}}, {{\{\}\*|ptr|%Type3\*}} align 1 {{%[a-z]\.0|%_[0-9]}}){{.*}}[ "kcfi"(i32 [[TYPE3:[[:print:]]+]]) ]
+}
+
+pub fn bar3() {
+ let a = Type3;
+ foo3(&a);
+ let b = &a as &dyn Trait3<Type3>;
+ b.baz(&a);
+ // CHECK-LABEL: define{{.*}}4bar3{{.*}}!{{<unknown kind #36>|kcfi_type}} !{{[0-9]+}}
+ // CHECK: call void %{{[0-9]}}({{\{\}\*|ptr}} align 1 {{%[a-z]\.0|%_[0-9]}}, {{\{\}\*|ptr|%Type3\*}} align 1 {{%[a-z]\.0|%_[0-9]}}){{.*}}[ "kcfi"(i32 [[TYPE3:[[:print:]]+]]) ]
+}
+
+pub fn foo4<'a>(a: &dyn Trait4<'a, Type4, Output = &'a i32>) {
+ let b = Type4;
+ a.qux(&b);
+ // CHECK-LABEL: define{{.*}}4foo4{{.*}}!{{<unknown kind #36>|kcfi_type}} !{{[0-9]+}}
+ // CHECK: call align 4 {{ptr|i32\*}} %{{[0-9]}}({{\{\}\*|ptr}} align 1 {{%[a-z]\.0|%_[0-9]}}, {{\{\}\*|ptr|%Type4\*}} align 1 {{%[a-z]\.0|%_[0-9]}}){{.*}}[ "kcfi"(i32 [[TYPE4:[[:print:]]+]]) ]
+}
+
+pub fn bar4<'a>() {
+ let a = Type4;
+ foo4(&a);
+ let b = &a as &dyn Trait4<'a, Type4, Output = &'a i32>;
+ b.qux(&a);
+ // CHECK-LABEL: define{{.*}}4bar4{{.*}}!{{<unknown kind #36>|kcfi_type}} !{{[0-9]+}}
+ // CHECK: call align 4 {{ptr|i32\*}} %{{[0-9]}}({{\{\}\*|ptr}} align 1 {{%[a-z]\.0|%_[0-9]}}, {{\{\}\*|ptr|%Type4\*}} align 1 {{%[a-z]\.0|%_[0-9]}}){{.*}}[ "kcfi"(i32 [[TYPE4:[[:print:]]+]]) ]
+}
+
+// CHECK: !{{[0-9]+}} = !{i32 [[TYPE1]]}
+// CHECK: !{{[0-9]+}} = !{i32 [[TYPE2]]}
+// CHECK: !{{[0-9]+}} = !{i32 [[TYPE3]]}
+// CHECK: !{{[0-9]+}} = !{i32 [[TYPE4]]}
diff --git a/tests/codegen/slice-iter-nonnull.rs b/tests/codegen/slice-iter-nonnull.rs
new file mode 100644
index 000000000..997bdaf56
--- /dev/null
+++ b/tests/codegen/slice-iter-nonnull.rs
@@ -0,0 +1,77 @@
+// no-system-llvm
+// compile-flags: -O
+// ignore-debug (these add extra checks that make it hard to verify)
+#![crate_type = "lib"]
+
+// The slice iterator used to `assume` that the `start` pointer was non-null.
+// That ought to be unneeded, though, since the type is `NonNull`, so this test
+// confirms that the appropriate metadata is included to denote that.
+
+// CHECK-LABEL: @slice_iter_next(
+#[no_mangle]
+pub fn slice_iter_next<'a>(it: &mut std::slice::Iter<'a, u32>) -> Option<&'a u32> {
+ // CHECK: %[[ENDP:.+]] = getelementptr{{.+}}ptr %it,{{.+}} 1
+ // CHECK: %[[END:.+]] = load ptr, ptr %[[ENDP]]
+ // CHECK-SAME: !nonnull
+ // CHECK-SAME: !noundef
+ // CHECK: %[[START:.+]] = load ptr, ptr %it,
+ // CHECK-SAME: !nonnull
+ // CHECK-SAME: !noundef
+ // CHECK: icmp eq ptr %[[START]], %[[END]]
+
+ // CHECK: store ptr{{.+}}, ptr %it,
+
+ it.next()
+}
+
+// CHECK-LABEL: @slice_iter_next_back(
+#[no_mangle]
+pub fn slice_iter_next_back<'a>(it: &mut std::slice::Iter<'a, u32>) -> Option<&'a u32> {
+ // CHECK: %[[ENDP:.+]] = getelementptr{{.+}}ptr %it,{{.+}} 1
+ // CHECK: %[[END:.+]] = load ptr, ptr %[[ENDP]]
+ // CHECK-SAME: !nonnull
+ // CHECK-SAME: !noundef
+ // CHECK: %[[START:.+]] = load ptr, ptr %it,
+ // CHECK-SAME: !nonnull
+ // CHECK-SAME: !noundef
+ // CHECK: icmp eq ptr %[[START]], %[[END]]
+
+ // CHECK: store ptr{{.+}}, ptr %[[ENDP]],
+
+ it.next_back()
+}
+
+// The slice iterator `new` methods used to `assume` that the pointer is non-null,
+// but passing slices already requires that, to the extent that LLVM actually
+// removed the `call @llvm.assume` anyway. These tests just demonstrate that the
+// attribute is there, and confirms adding the assume back doesn't do anything.
+
+// CHECK-LABEL: @slice_iter_new
+// CHECK-SAME: (ptr noalias noundef nonnull {{.+}} %slice.0, {{.+}} noundef %slice.1)
+#[no_mangle]
+pub fn slice_iter_new(slice: &[u32]) -> std::slice::Iter<'_, u32> {
+ // CHECK-NOT: slice
+ // CHECK: %[[END:.+]] = getelementptr inbounds i32{{.+}} %slice.0{{.+}} %slice.1
+ // CHECK-NOT: slice
+ // CHECK: insertvalue {{.+}} ptr %slice.0, 0
+ // CHECK-NOT: slice
+ // CHECK: insertvalue {{.+}} ptr %[[END]], 1
+ // CHECK-NOT: slice
+ // CHECK: }
+ slice.iter()
+}
+
+// CHECK-LABEL: @slice_iter_mut_new
+// CHECK-SAME: (ptr noalias noundef nonnull {{.+}} %slice.0, {{.+}} noundef %slice.1)
+#[no_mangle]
+pub fn slice_iter_mut_new(slice: &mut [u32]) -> std::slice::IterMut<'_, u32> {
+ // CHECK-NOT: slice
+ // CHECK: %[[END:.+]] = getelementptr inbounds i32{{.+}} %slice.0{{.+}} %slice.1
+ // CHECK-NOT: slice
+ // CHECK: insertvalue {{.+}} ptr %slice.0, 0
+ // CHECK-NOT: slice
+ // CHECK: insertvalue {{.+}} ptr %[[END]], 1
+ // CHECK-NOT: slice
+ // CHECK: }
+ slice.iter_mut()
+}
diff --git a/tests/codegen/split-lto-unit.rs b/tests/codegen/split-lto-unit.rs
new file mode 100644
index 000000000..dc6570be3
--- /dev/null
+++ b/tests/codegen/split-lto-unit.rs
@@ -0,0 +1,11 @@
+// Verifies that "EnableSplitLTOUnit" module flag is added.
+//
+// needs-sanitizer-cfi
+// compile-flags: -Clto -Ctarget-feature=-crt-static -Zsplit-lto-unit
+
+#![crate_type="lib"]
+
+pub fn foo() {
+}
+
+// CHECK: !{{[0-9]+}} = !{i32 4, !"EnableSplitLTOUnit", i32 1}
diff --git a/tests/codegen/thread-local.rs b/tests/codegen/thread-local.rs
index aa7fab7fb..caf0366d2 100644
--- a/tests/codegen/thread-local.rs
+++ b/tests/codegen/thread-local.rs
@@ -20,8 +20,8 @@ thread_local!(static A: Cell<u32> = const { Cell::new(1) });
// CHECK-LABEL: @get
#[no_mangle]
fn get() -> u32 {
- // CHECK: %0 = load i32, {{.*}}[[TLS]]{{.*}}
- // CHECK-NEXT: ret i32 %0
+ // CHECK: [[RET_0:%.+]] = load i32, {{.*}}[[TLS]]{{.*}}
+ // CHECK-NEXT: ret i32 [[RET_0]]
A.with(|a| a.get())
}
@@ -36,8 +36,8 @@ fn set(v: u32) {
// CHECK-LABEL: @get_aux
#[no_mangle]
fn get_aux() -> u64 {
- // CHECK: %0 = load i64, {{.*}}[[TLS_AUX]]
- // CHECK-NEXT: ret i64 %0
+ // CHECK: [[RET_1:%.+]] = load i64, {{.*}}[[TLS_AUX]]
+ // CHECK-NEXT: ret i64 [[RET_1]]
aux::A.with(|a| a.get())
}
diff --git a/tests/codegen/tied-features-strength.rs b/tests/codegen/tied-features-strength.rs
new file mode 100644
index 000000000..51334c121
--- /dev/null
+++ b/tests/codegen/tied-features-strength.rs
@@ -0,0 +1,29 @@
+// ignore-tidy-linelength
+// revisions: ENABLE_SVE DISABLE_SVE DISABLE_NEON ENABLE_NEON
+// compile-flags: --crate-type=rlib --target=aarch64-unknown-linux-gnu
+// needs-llvm-components: aarch64
+
+// The "+v8a" feature is matched as optional as it isn't added when we
+// are targeting older LLVM versions. Once the min supported version
+// is LLVM-14 we can remove the optional regex matching for this feature.
+
+// [ENABLE_SVE] compile-flags: -C target-feature=+sve
+// ENABLE_SVE: attributes #0 = { {{.*}} "target-features"="{{((\+outline-atomics,?)|(\+v8a,?)?|(\+sve,?)|(\+neon,?))*}}" }
+
+// [DISABLE_SVE] compile-flags: -C target-feature=-sve
+// DISABLE_SVE: attributes #0 = { {{.*}} "target-features"="{{((\+outline-atomics,?)|(\+v8a,?)?|(-sve,?)|(\+neon,?))*}}" }
+
+// [DISABLE_NEON] compile-flags: -C target-feature=-neon
+// DISABLE_NEON: attributes #0 = { {{.*}} "target-features"="{{((\+outline-atomics,?)|(\+v8a,?)?|(-fp-armv8,?)|(-neon,?))*}}" }
+
+// [ENABLE_NEON] compile-flags: -C target-feature=+neon
+// ENABLE_NEON: attributes #0 = { {{.*}} "target-features"="{{((\+outline-atomics,?)|(\+v8a,?)?|(\+fp-armv8,?)|(\+neon,?))*}}" }
+
+
+#![feature(no_core, lang_items)]
+#![no_core]
+
+#[lang = "sized"]
+trait Sized {}
+
+pub fn test() {}
diff --git a/tests/codegen/transmute-optimized.rs b/tests/codegen/transmute-optimized.rs
new file mode 100644
index 000000000..461dd550c
--- /dev/null
+++ b/tests/codegen/transmute-optimized.rs
@@ -0,0 +1,109 @@
+// compile-flags: -O -Z merge-functions=disabled
+// min-llvm-version: 15.0 # this test uses `ptr`s
+// ignore-debug
+
+#![crate_type = "lib"]
+
+// This tests that LLVM can optimize based on the niches in the source or
+// destination types for transmutes.
+
+#[repr(u32)]
+pub enum AlwaysZero32 { X = 0 }
+
+// CHECK-LABEL: i32 @issue_109958(i32
+#[no_mangle]
+pub fn issue_109958(x: AlwaysZero32) -> i32 {
+ // CHECK: ret i32 0
+ unsafe { std::mem::transmute(x) }
+}
+
+// CHECK-LABEL: i1 @reference_is_null(ptr
+#[no_mangle]
+pub fn reference_is_null(x: &i32) -> bool {
+ // CHECK: ret i1 false
+ let p: *const i32 = unsafe { std::mem::transmute(x) };
+ p.is_null()
+}
+
+// CHECK-LABEL: i1 @non_null_is_null(ptr
+#[no_mangle]
+pub fn non_null_is_null(x: std::ptr::NonNull<i32>) -> bool {
+ // CHECK: ret i1 false
+ let p: *const i32 = unsafe { std::mem::transmute(x) };
+ p.is_null()
+}
+
+// CHECK-LABEL: i1 @non_zero_is_null(
+#[no_mangle]
+pub fn non_zero_is_null(x: std::num::NonZeroUsize) -> bool {
+ // CHECK: ret i1 false
+ let p: *const i32 = unsafe { std::mem::transmute(x) };
+ p.is_null()
+}
+
+// CHECK-LABEL: i1 @non_null_is_zero(ptr
+#[no_mangle]
+pub fn non_null_is_zero(x: std::ptr::NonNull<i32>) -> bool {
+ // CHECK: ret i1 false
+ let a: isize = unsafe { std::mem::transmute(x) };
+ a == 0
+}
+
+// CHECK-LABEL: i1 @bool_ordering_is_ge(i1
+#[no_mangle]
+pub fn bool_ordering_is_ge(x: bool) -> bool {
+ // CHECK: ret i1 true
+ let y: std::cmp::Ordering = unsafe { std::mem::transmute(x) };
+ y.is_ge()
+}
+
+// CHECK-LABEL: i1 @ordering_is_ge_then_transmute_to_bool(i8
+#[no_mangle]
+pub fn ordering_is_ge_then_transmute_to_bool(x: std::cmp::Ordering) -> bool {
+ let r = x.is_ge();
+ let _: bool = unsafe { std::mem::transmute(x) };
+ r
+}
+
+// CHECK-LABEL: i32 @normal_div(i32
+#[no_mangle]
+pub fn normal_div(a: u32, b: u32) -> u32 {
+ // CHECK: call core::panicking::panic
+ a / b
+}
+
+// CHECK-LABEL: i32 @div_transmute_nonzero(i32
+#[no_mangle]
+pub fn div_transmute_nonzero(a: u32, b: std::num::NonZeroI32) -> u32 {
+ // CHECK-NOT: call core::panicking::panic
+ // CHECK: %[[R:.+]] = udiv i32 %a, %b
+ // CHECK-NEXT: ret i32 %[[R]]
+ // CHECK-NOT: call core::panicking::panic
+ let d: u32 = unsafe { std::mem::transmute(b) };
+ a / d
+}
+
+#[repr(i8)]
+pub enum OneTwoThree { One = 1, Two = 2, Three = 3 }
+
+// CHECK-LABEL: i8 @ordering_transmute_onetwothree(i8
+#[no_mangle]
+pub unsafe fn ordering_transmute_onetwothree(x: std::cmp::Ordering) -> OneTwoThree {
+ // CHECK: ret i8 1
+ std::mem::transmute(x)
+}
+
+// CHECK-LABEL: i8 @onetwothree_transmute_ordering(i8
+#[no_mangle]
+pub unsafe fn onetwothree_transmute_ordering(x: OneTwoThree) -> std::cmp::Ordering {
+ // CHECK: ret i8 1
+ std::mem::transmute(x)
+}
+
+// CHECK-LABEL: i1 @char_is_negative(i32
+#[no_mangle]
+pub fn char_is_negative(c: char) -> bool {
+ // CHECK: ret i1 false
+ let x: i32 = unsafe { std::mem::transmute(c) };
+ x < 0
+}
diff --git a/tests/codegen/transmute-scalar.rs b/tests/codegen/transmute-scalar.rs
index af2cef472..a0894a505 100644
--- a/tests/codegen/transmute-scalar.rs
+++ b/tests/codegen/transmute-scalar.rs
@@ -1,4 +1,4 @@
-// compile-flags: -O -C no-prepopulate-passes
+// compile-flags: -C opt-level=0 -C no-prepopulate-passes
// min-llvm-version: 15.0 # this test assumes `ptr`s and thus no `pointercast`s
#![crate_type = "lib"]
@@ -10,7 +10,7 @@
// However, `bitcast`s and `ptrtoint`s and `inttoptr`s are still worth doing when
// that allows us to avoid the `alloca`s entirely; see `rvalue_creates_operand`.
-// CHECK-LABEL: define{{.*}}i32 @f32_to_bits(float noundef %x)
+// CHECK-LABEL: define{{.*}}i32 @f32_to_bits(float %x)
// CHECK: %0 = bitcast float %x to i32
// CHECK-NEXT: ret i32 %0
#[no_mangle]
@@ -18,7 +18,7 @@ pub fn f32_to_bits(x: f32) -> u32 {
unsafe { std::mem::transmute(x) }
}
-// CHECK-LABEL: define{{.*}}i8 @bool_to_byte(i1 noundef zeroext %b)
+// CHECK-LABEL: define{{.*}}i8 @bool_to_byte(i1 zeroext %b)
// CHECK: %0 = zext i1 %b to i8
// CHECK-NEXT: ret i8 %0
#[no_mangle]
@@ -26,7 +26,7 @@ pub fn bool_to_byte(b: bool) -> u8 {
unsafe { std::mem::transmute(b) }
}
-// CHECK-LABEL: define{{.*}}noundef zeroext i1 @byte_to_bool(i8 noundef %byte)
+// CHECK-LABEL: define{{.*}}zeroext i1 @byte_to_bool(i8 %byte)
// CHECK: %0 = trunc i8 %byte to i1
// CHECK-NEXT: ret i1 %0
#[no_mangle]
@@ -34,14 +34,14 @@ pub unsafe fn byte_to_bool(byte: u8) -> bool {
std::mem::transmute(byte)
}
-// CHECK-LABEL: define{{.*}}ptr @ptr_to_ptr(ptr noundef %p)
+// CHECK-LABEL: define{{.*}}ptr @ptr_to_ptr(ptr %p)
// CHECK: ret ptr %p
#[no_mangle]
pub fn ptr_to_ptr(p: *mut u16) -> *mut u8 {
unsafe { std::mem::transmute(p) }
}
-// CHECK: define{{.*}}[[USIZE:i[0-9]+]] @ptr_to_int(ptr noundef %p)
+// CHECK: define{{.*}}[[USIZE:i[0-9]+]] @ptr_to_int(ptr %p)
// CHECK: %0 = ptrtoint ptr %p to [[USIZE]]
// CHECK-NEXT: ret [[USIZE]] %0
#[no_mangle]
@@ -49,7 +49,7 @@ pub fn ptr_to_int(p: *mut u16) -> usize {
unsafe { std::mem::transmute(p) }
}
-// CHECK: define{{.*}}ptr @int_to_ptr([[USIZE]] noundef %i)
+// CHECK: define{{.*}}ptr @int_to_ptr([[USIZE]] %i)
// CHECK: %0 = inttoptr [[USIZE]] %i to ptr
// CHECK-NEXT: ret ptr %0
#[no_mangle]
diff --git a/tests/codegen/vec-optimizes-away.rs b/tests/codegen/vec-optimizes-away.rs
index 9143fad23..6f477a796 100644
--- a/tests/codegen/vec-optimizes-away.rs
+++ b/tests/codegen/vec-optimizes-away.rs
@@ -1,12 +1,13 @@
// ignore-debug: the debug assertions get in the way
// no-system-llvm
// compile-flags: -O
-#![crate_type="lib"]
+#![crate_type = "lib"]
#[no_mangle]
pub fn sum_me() -> i32 {
// CHECK-LABEL: @sum_me
// CHECK-NEXT: {{^.*:$}}
+ // CHECK-NEXT: {{.*}} load volatile i8, ptr @__rust_no_alloc_shim_is_unstable, align 1
// CHECK-NEXT: ret i32 6
vec![1, 2, 3].iter().sum::<i32>()
}
diff --git a/tests/codegen/vec-shrink-panik.rs b/tests/codegen/vec-shrink-panik.rs
index b3c3483fe..88b7edff2 100644
--- a/tests/codegen/vec-shrink-panik.rs
+++ b/tests/codegen/vec-shrink-panik.rs
@@ -25,7 +25,7 @@ pub fn issue71861(vec: Vec<u32>) -> Box<[u32]> {
// Call to panic_cannot_unwind in case of double-panic is expected
// on LLVM 16 and older, but other panics are not.
- // CHECK: cleanup
+ // old: filter
// old-NEXT: ; call core::panicking::panic_cannot_unwind
// old-NEXT: panic_cannot_unwind
@@ -40,7 +40,7 @@ pub fn issue75636<'a>(iter: &[&'a str]) -> Box<[&'a str]> {
// Call to panic_cannot_unwind in case of double-panic is expected,
// on LLVM 16 and older, but other panics are not.
- // CHECK: cleanup
+ // old: filter
// old-NEXT: ; call core::panicking::panic_cannot_unwind
// old-NEXT: panic_cannot_unwind