mirror of
https://github.com/rust-lang/rust.git
synced 2026-04-26 13:01:27 +03:00
103 lines
3.2 KiB
Rust
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);
|
|
}
|