File: align-byval-alignment-mismatch.rs

package info (click to toggle)
rustc-web 1.85.0%2Bdfsg3-1~deb12u3
  • links: PTS, VCS
  • area: main
  • in suites: bookworm-proposed-updates
  • size: 1,759,988 kB
  • sloc: xml: 158,127; python: 35,830; javascript: 19,497; cpp: 19,002; sh: 17,245; ansic: 13,127; asm: 4,376; makefile: 1,056; lisp: 29; perl: 29; ruby: 19; sql: 11
file content (126 lines) | stat: -rw-r--r-- 4,066 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
// ignore-tidy-linelength
//@ revisions:i686-linux x86_64-linux

//@[i686-linux] compile-flags: --target i686-unknown-linux-gnu -C panic=abort
//@[i686-linux] needs-llvm-components: x86
//@[x86_64-linux] compile-flags: --target x86_64-unknown-linux-gnu -C panic=abort
//@[x86_64-linux] needs-llvm-components: x86

// Tests that we correctly copy arguments into allocas when the alignment of the byval argument
// is different from the alignment of the Rust type.

// For the following test cases:
// All of the `*_decreases_alignment` functions should codegen to a direct call, since the
// alignment is already sufficient.
// All off the `*_increases_alignment` functions should copy the argument to an alloca
// on i686-unknown-linux-gnu, since the alignment needs to be increased, and should codegen
// to a direct call on x86_64-unknown-linux-gnu, where byval alignment matches Rust alignment.

#![feature(no_core, lang_items)]
#![crate_type = "lib"]
#![no_std]
#![no_core]
#![allow(non_camel_case_types)]

#[lang = "sized"]
trait Sized {}
#[lang = "freeze"]
trait Freeze {}
#[lang = "copy"]
trait Copy {}

// This type has align 1 in Rust, but as a byval argument on i686-linux, it will have align 4.
#[repr(C)]
#[repr(packed)]
struct Align1 {
    x: u128,
    y: u128,
    z: u128,
}

// This type has align 16 in Rust, but as a byval argument on i686-linux, it will have align 4.
#[repr(C)]
#[repr(align(16))]
struct Align16 {
    x: u128,
    y: u128,
    z: u128,
}

extern "C" {
    fn extern_c_align1(x: Align1);
    fn extern_c_align16(x: Align16);
}

// CHECK-LABEL: @rust_to_c_increases_alignment
#[no_mangle]
pub unsafe fn rust_to_c_increases_alignment(x: Align1) {
    // i686-linux: start:
    // i686-linux-NEXT: [[ALLOCA:%[0-9a-z]+]] = alloca [48 x i8], align 4
    // i686-linux-NEXT: call void @llvm.memcpy.{{.+}}(ptr {{.*}}align 4 {{.*}}[[ALLOCA]], ptr {{.*}}align 1 {{.*}}%x
    // i686-linux-NEXT: call void @extern_c_align1({{.+}} [[ALLOCA]])

    // x86_64-linux: start:
    // x86_64-linux-NEXT: call void @extern_c_align1
    extern_c_align1(x);
}

// CHECK-LABEL: @rust_to_c_decreases_alignment
#[no_mangle]
pub unsafe fn rust_to_c_decreases_alignment(x: Align16) {
    // CHECK: start:
    // CHECK-NEXT: call void @extern_c_align16
    extern_c_align16(x);
}

extern "Rust" {
    fn extern_rust_align1(x: Align1);
    fn extern_rust_align16(x: Align16);
}

// CHECK-LABEL: @c_to_rust_decreases_alignment
#[no_mangle]
pub unsafe extern "C" fn c_to_rust_decreases_alignment(x: Align1) {
    // CHECK: start:
    // CHECK-NEXT: call void @extern_rust_align1
    extern_rust_align1(x);
}

// CHECK-LABEL: @c_to_rust_increases_alignment
#[no_mangle]
pub unsafe extern "C" fn c_to_rust_increases_alignment(x: Align16) {
    // i686-linux: start:
    // i686-linux-NEXT: [[ALLOCA:%[0-9a-z]+]] = alloca [48 x i8], align 16
    // i686-linux-NEXT: call void @llvm.memcpy.{{.+}}(ptr {{.*}}align 16 {{.*}}[[ALLOCA]], ptr {{.*}}align 4 {{.*}}%0
    // i686-linux-NEXT: call void @extern_rust_align16({{.+}} [[ALLOCA]])

    // x86_64-linux: start:
    // x86_64-linux-NEXT: call void @extern_rust_align16
    extern_rust_align16(x);
}

extern "Rust" {
    fn extern_rust_ref_align1(x: &Align1);
    fn extern_rust_ref_align16(x: &Align16);
}

// CHECK-LABEL: @c_to_rust_ref_decreases_alignment
#[no_mangle]
pub unsafe extern "C" fn c_to_rust_ref_decreases_alignment(x: Align1) {
    // CHECK: start:
    // CHECK-NEXT: call void @extern_rust_ref_align1
    extern_rust_ref_align1(&x);
}

// CHECK-LABEL: @c_to_rust_ref_increases_alignment
#[no_mangle]
pub unsafe extern "C" fn c_to_rust_ref_increases_alignment(x: Align16) {
    // i686-linux: start:
    // i686-linux-NEXT: [[ALLOCA:%[0-9a-z]+]] = alloca [48 x i8], align 16
    // i686-linux-NEXT: call void @llvm.memcpy.{{.+}}(ptr {{.*}}align 16 {{.*}}[[ALLOCA]], ptr {{.*}}align 4 {{.*}}%0
    // i686-linux-NEXT: call void @extern_rust_ref_align16({{.+}} [[ALLOCA]])

    // x86_64-linux: start:
    // x86_64-linux-NEXT: call void @extern_rust_ref_align16
    extern_rust_ref_align16(&x);
}