Files
rust/tests/codegen-llvm/indirect-bycopy-bymove-byval.rs

103 lines
3.2 KiB
Rust

//! Regression test for issue <https://github.com/rust-lang/rust/issues/155241>.
//! Arguments passed indirectly via a hidden pointer must be copied to an alloca,
//! except for by-val or by-move.
//@ add-minicore
//@ revisions: x64-linux i686-linux i686-windows
//@ compile-flags: -Cno-prepopulate-passes -Copt-level=3
//@[x64-linux] compile-flags: --target x86_64-unknown-linux-gnu
//@[x64-linux] needs-llvm-components: x86
//@[i686-linux] compile-flags: --target i686-unknown-linux-gnu
//@[i686-linux] needs-llvm-components: x86
//@[i686-windows] compile-flags: --target i686-pc-windows-msvc
//@[i686-windows] needs-llvm-components: x86
#![crate_type = "lib"]
#![feature(stmt_expr_attributes, no_core)]
#![expect(unused)]
#![no_std]
#![no_core]
extern crate minicore;
use minicore::*;
struct Thing(u64, u64, u64);
impl Copy for Thing {}
// The argument of the second call is a by-move argument.
// CHECK-LABEL: @normal
// CHECK: call void @llvm.memcpy{{.*}}(ptr{{.*}} [[normal_V1:%.*]], ptr{{.*}} %value,
// CHECK: call void @opaque(ptr{{.*}} [[normal_V1]])
// CHECK: call void @opaque(ptr{{.*}} %value)
// CHECK: call void @llvm.memcpy{{.*}}(ptr{{.*}} [[normal_V3:%.*]], ptr{{.*}} @anon{{.*}},
// CHECK: call void @opaque(ptr{{.*}} [[normal_V3]])
#[unsafe(no_mangle)]
pub fn normal() {
#[inline(never)]
#[unsafe(no_mangle)]
fn opaque(mut thing: Thing) {
thing.0 = 1;
}
let value = Thing(0, 0, 0);
opaque(value);
opaque(value);
const VALUE: Thing = Thing(0, 0, 0);
opaque(VALUE);
}
// The argument of the second call is a by-move argument.
// CHECK-LABEL: @untupled
// CHECK: call void @llvm.memcpy{{.*}}(ptr{{.*}} [[untupled_V1:%.*]], ptr{{.*}} %value
// CHECK: call indirect_bycopy_bymove_byval::untupled::{closure#0}
// CHECK-NEXT: call void @{{.*}}(ptr {{.*}}, ptr{{.*}} [[untupled_V1]])
// CHECK: call indirect_bycopy_bymove_byval::untupled::{closure#1}
// CHECK-NEXT: call void @{{.*}}(ptr {{.*}}, ptr{{.*}} %value)
// CHECK: call void @llvm.memcpy{{.*}}(ptr{{.*}} [[untupled_V3:%.*]], ptr{{.*}} @anon{{.*}}
// CHECK: call indirect_bycopy_bymove_byval::untupled::{closure#2}
// CHECK-NEXT: call void @{{.*}}(ptr {{.*}}, ptr{{.*}} [[untupled_V3]])
#[unsafe(no_mangle)]
pub fn untupled() {
let value = (Thing(0, 0, 0),);
(#[inline(never)]
|mut thing: Thing| {
thing.0 = 1;
})
.call(value);
(#[inline(never)]
|mut thing: Thing| {
thing.0 = 2;
})
.call(value);
const VALUE: (Thing,) = (Thing(0, 0, 0),);
(#[inline(never)]
|mut thing: Thing| {
thing.0 = 3;
})
.call(VALUE);
}
// All memcpy calls are redundant for byval.
// CHECK-LABEL: @byval
// CHECK: call void @opaque_byval(ptr{{.*}} byval([24 x i8]){{.*}} %value)
// CHECK: call void @opaque_byval(ptr{{.*}} byval([24 x i8]){{.*}} %value)
// CHECK: call void @opaque_byval(ptr{{.*}} byval([24 x i8]){{.*}} @anon{{.*}})
#[unsafe(no_mangle)]
pub fn byval() {
#[repr(C)]
struct Thing(u64, u64, u64);
impl Copy for Thing {}
#[inline(never)]
#[unsafe(no_mangle)]
extern "C" fn opaque_byval(mut thing: Thing) {
thing.0 = 1;
}
let value = Thing(0, 0, 0);
opaque_byval(value);
opaque_byval(value);
const VALUE: Thing = Thing(0, 0, 0);
opaque_byval(VALUE);
}