1
+ // RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -fclangir-call-conv-lowering -emit-cir-flat -mmlir --mlir-print-ir-after=cir-call-conv-lowering %s -o %t.cir
2
+ // RUN: FileCheck --input-file=%t.cir %s -check-prefix=CIR
3
+ // RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-llvm %s -o %t.ll -fclangir-call-conv-lowering
4
+ // RUN: FileCheck --input-file=%t.ll %s -check-prefix=LLVM
5
+
6
+ typedef struct {
7
+ int a , b ;
8
+ } S ;
9
+
10
+ // CIR: cir.func @init(%arg0: !u64i
11
+ // CIR: %[[#V0:]] = cir.alloca !ty_S, !cir.ptr<!ty_S>, [""] {alignment = 4 : i64}
12
+ // CIR: %[[#V1:]] = cir.cast(bitcast, %[[#V0]] : !cir.ptr<!ty_S>), !cir.ptr<!u64i>
13
+ // CIR: cir.store %arg0, %[[#V1]] : !u64i, !cir.ptr<!u64i>
14
+ // CIR: %[[#V2:]] = cir.alloca !ty_S, !cir.ptr<!ty_S>, ["__retval"] {alignment = 4 : i64}
15
+ // CIR: %[[#V3:]] = cir.const #cir.int<1> : !s32i
16
+ // CIR: %[[#V4:]] = cir.get_member %[[#V0]][0] {name = "a"} : !cir.ptr<!ty_S> -> !cir.ptr<!s32i>
17
+ // CIR: cir.store %[[#V3]], %[[#V4]] : !s32i, !cir.ptr<!s32i>
18
+ // CIR: %[[#V5:]] = cir.const #cir.int<2> : !s32i
19
+ // CIR: %[[#V6:]] = cir.get_member %[[#V0]][1] {name = "b"} : !cir.ptr<!ty_S> -> !cir.ptr<!s32i>
20
+ // CIR: cir.store %[[#V5]], %[[#V6]] : !s32i, !cir.ptr<!s32i>
21
+ // CIR: cir.copy %[[#V0]] to %[[#V2]] : !cir.ptr<!ty_S>
22
+ // CIR: %[[#V7:]] = cir.cast(bitcast, %[[#V2]] : !cir.ptr<!ty_S>), !cir.ptr<!u64i>
23
+ // CIR: %[[#V8:]] = cir.load %[[#V7]] : !cir.ptr<!u64i>, !u64i
24
+ // CIR: cir.return %[[#V8]] : !u64i
25
+
26
+ // LLVM: @init(i64 %[[#V0:]])
27
+ // LLVM: %[[#V2:]] = alloca %struct.S, i64 1, align 4
28
+ // LLVM: store i64 %[[#V0]], ptr %[[#V2]], align 8
29
+ // LLVM: %[[#V3:]] = alloca %struct.S, i64 1, align 4
30
+ // LLVM: %[[#V4:]] = getelementptr %struct.S, ptr %[[#V2]], i32 0, i32 0
31
+ // LLVM: store i32 1, ptr %[[#V4]], align 4
32
+ // LLVM: %[[#V5:]] = getelementptr %struct.S, ptr %[[#V2]], i32 0, i32 1
33
+ // LLVM: store i32 2, ptr %[[#V5]], align 4
34
+ // LLVM: call void @llvm.memcpy.p0.p0.i32(ptr %[[#V3]], ptr %[[#V2]], i32 8, i1 false)
35
+ // LLVM: %[[#V6:]] = load i64, ptr %[[#V3]], align 8
36
+ // LLVM: ret i64 %[[#V6]]
37
+ S init (S s ) {
38
+ s .a = 1 ;
39
+ s .b = 2 ;
40
+ return s ;
41
+ }
42
+
43
+ // CIR: cir.func no_proto @foo1
44
+ // CIR: %[[#V0:]] = cir.alloca !ty_S, !cir.ptr<!ty_S>, ["s"]
45
+ // CIR: %[[#V1:]] = cir.alloca !ty_S, !cir.ptr<!ty_S>, ["tmp"] {alignment = 4 : i64}
46
+ // CIR: %[[#V2:]] = cir.cast(bitcast, %[[#V0]] : !cir.ptr<!ty_S>), !cir.ptr<!u64i>
47
+ // CIR: %[[#V3:]] = cir.load %[[#V2]] : !cir.ptr<!u64i>, !u64i
48
+ // CIR: %[[#V4:]] = cir.call @init(%[[#V3]]) : (!u64i) -> !u64i
49
+ // CIR: %[[#V5:]] = cir.cast(bitcast, %[[#V1]] : !cir.ptr<!ty_S>), !cir.ptr<!u64i>
50
+ // CIR: cir.store %[[#V4]], %[[#V5]] : !u64i, !cir.ptr<!u64i>
51
+ // CIR: cir.copy %[[#V1]] to %[[#V0]] : !cir.ptr<!ty_S>
52
+ // CIR: cir.return
53
+
54
+ // LLVM: @foo1()
55
+ // LLVM: %[[#V1:]] = alloca %struct.S, i64 1, align 4
56
+ // LLVM: %[[#V2:]] = alloca %struct.S, i64 1, align 4
57
+ // LLVM: %[[#V3:]] = load i64, ptr %[[#V1]], align 8
58
+ // LLVM: %[[#V4:]] = call i64 @init(i64 %[[#V3]])
59
+ // LLVM: store i64 %[[#V4]], ptr %[[#V2]], align 8
60
+ // LLVM: call void @llvm.memcpy.p0.p0.i32(ptr %[[#V1]], ptr %[[#V2]], i32 8, i1 false)
61
+ void foo1 () {
62
+ S s ;
63
+ s = init (s );
64
+ }
65
+
66
+ // CIR: cir.func @foo2(%arg0: !u64i
67
+ // CIR: %[[#V0:]] = cir.alloca !ty_S, !cir.ptr<!ty_S>, [""] {alignment = 4 : i64}
68
+ // CIR: %[[#V1:]] = cir.cast(bitcast, %[[#V0]] : !cir.ptr<!ty_S>), !cir.ptr<!u64i>
69
+ // CIR: cir.store %arg0, %[[#V1]] : !u64i, !cir.ptr<!u64i>
70
+ // CIR: %[[#V2:]] = cir.alloca !ty_S, !cir.ptr<!ty_S>, ["__retval"] {alignment = 4 : i64}
71
+ // CIR: %[[#V3:]] = cir.alloca !ty_S, !cir.ptr<!ty_S>, ["s2"]
72
+ // CIR: %[[#V4:]] = cir.alloca !ty_S, !cir.ptr<!ty_S>, ["tmp"] {alignment = 4 : i64}
73
+ // CIR: %[[#V5:]] = cir.const #cir.const_struct<{#cir.int<1> : !s32i, #cir.int<2> : !s32i}> : !ty_S
74
+ // CIR: cir.store %[[#V5]], %[[#V3]] : !ty_S, !cir.ptr<!ty_S>
75
+ // CIR: %[[#V6:]] = cir.cast(bitcast, %[[#V0]] : !cir.ptr<!ty_S>), !cir.ptr<!u64i>
76
+ // CIR: %[[#V7:]] = cir.load %[[#V6]] : !cir.ptr<!u64i>, !u64i
77
+ // CIR: %[[#V8:]] = cir.call @foo2(%[[#V7]]) : (!u64i) -> !u64i
78
+ // CIR: %[[#V9:]] = cir.cast(bitcast, %[[#V4]] : !cir.ptr<!ty_S>), !cir.ptr<!u64i>
79
+ // CIR: cir.store %[[#V8]], %[[#V9]] : !u64i, !cir.ptr<!u64i>
80
+ // CIR: cir.copy %[[#V4]] to %[[#V0]] : !cir.ptr<!ty_S>
81
+ // CIR: cir.copy %[[#V0]] to %[[#V2]] : !cir.ptr<!ty_S>
82
+ // CIR: %[[#V10:]] = cir.cast(bitcast, %[[#V2]] : !cir.ptr<!ty_S>), !cir.ptr<!u64i>
83
+ // CIR: %[[#V11:]] = cir.load %[[#V10]] : !cir.ptr<!u64i>, !u64i
84
+ // CIR: cir.return %[[#V11]] : !u64i
85
+
86
+ // LLVM: @foo2(i64 %[[#V0:]])
87
+ // LLVM: %[[#V2:]] = alloca %struct.S, i64 1, align 4
88
+ // LLVM: store i64 %[[#V0]], ptr %[[#V2]], align 8
89
+ // LLVM: %[[#V3:]] = alloca %struct.S, i64 1, align 4
90
+ // LLVM: %[[#V4:]] = alloca %struct.S, i64 1, align 4
91
+ // LLVM: %[[#V5:]] = alloca %struct.S, i64 1, align 4
92
+ // LLVM: store %struct.S { i32 1, i32 2 }, ptr %[[#V4]], align 4
93
+ // LLVM: %[[#V6:]] = load i64, ptr %[[#V2]], align 8
94
+ // LLVM: %[[#V7:]] = call i64 @foo2(i64 %[[#V6]])
95
+ // LLVM: store i64 %[[#V7]], ptr %[[#V5]], align 8
96
+ // LLVM: call void @llvm.memcpy.p0.p0.i32(ptr %[[#V2]], ptr %[[#V5]], i32 8, i1 false)
97
+ // LLVM: call void @llvm.memcpy.p0.p0.i32(ptr %[[#V3]], ptr %[[#V2]], i32 8, i1 false)
98
+ // LLVM: %[[#V8:]] = load i64, ptr %[[#V3]], align 8
99
+ // LLVM: ret i64 %[[#V8]]
100
+ S foo2 (S s1 ) {
101
+ S s2 = {1 , 2 };
102
+ s1 = foo2 (s1 );
103
+ return s1 ;
104
+ }
105
+
106
+ typedef struct {
107
+ char a ;
108
+ char b ;
109
+ } S2 ;
110
+
111
+ // CIR: cir.func @init2(%arg0: !u16i
112
+ // CIR: %[[#V0:]] = cir.alloca !ty_S2_, !cir.ptr<!ty_S2_>, [""] {alignment = 4 : i64}
113
+ // CIR: %[[#V1:]] = cir.cast(bitcast, %[[#V0]] : !cir.ptr<!ty_S2_>), !cir.ptr<!u16i>
114
+ // CIR: cir.store %arg0, %[[#V1]] : !u16i, !cir.ptr<!u16i>
115
+ // CIR: %[[#V2:]] = cir.alloca !ty_S2_, !cir.ptr<!ty_S2_>, ["__retval"] {alignment = 1 : i64}
116
+ // CIR: %[[#V3:]] = cir.const #cir.int<1> : !s32i
117
+ // CIR: %[[#V4:]] = cir.cast(integral, %[[#V3]] : !s32i), !s8i
118
+ // CIR: %[[#V5:]] = cir.get_member %[[#V0]][0] {name = "a"} : !cir.ptr<!ty_S2_> -> !cir.ptr<!s8i>
119
+ // CIR: cir.store %[[#V4]], %[[#V5]] : !s8i, !cir.ptr<!s8i>
120
+ // CIR: %[[#V6:]] = cir.const #cir.int<2> : !s32i
121
+ // CIR: %[[#V7:]] = cir.cast(integral, %[[#V6]] : !s32i), !s8i
122
+ // CIR: %[[#V8:]] = cir.get_member %[[#V0]][1] {name = "b"} : !cir.ptr<!ty_S2_> -> !cir.ptr<!s8i>
123
+ // CIR: cir.store %[[#V7]], %[[#V8]] : !s8i, !cir.ptr<!s8i>
124
+ // CIR: cir.copy %[[#V0]] to %[[#V2]] : !cir.ptr<!ty_S2_>
125
+ // CIR: %[[#V9:]] = cir.cast(bitcast, %[[#V2]] : !cir.ptr<!ty_S2_>), !cir.ptr<!u16i>
126
+ // CIR: %[[#V10:]] = cir.load %[[#V9]] : !cir.ptr<!u16i>, !u16i
127
+ // CIR: cir.return %[[#V10]] : !u16i
128
+
129
+ // LLVM: @init2(i16 %[[#V0:]])
130
+ // LLVM: %[[#V2:]] = alloca %struct.S2, i64 1, align 4
131
+ // LLVM: store i16 %[[#V0]], ptr %[[#V2]], align 2
132
+ // LLVM: %[[#V3:]] = alloca %struct.S2, i64 1, align 1
133
+ // LLVM: %[[#V4:]] = getelementptr %struct.S2, ptr %[[#V2]], i32 0, i32 0
134
+ // LLVM: store i8 1, ptr %[[#V4]], align 1
135
+ // LLVM: %[[#V5:]] = getelementptr %struct.S2, ptr %[[#V2]], i32 0, i32 1
136
+ // LLVM: store i8 2, ptr %[[#V5]], align 1
137
+ // LLVM: call void @llvm.memcpy.p0.p0.i32(ptr %[[#V3]], ptr %[[#V2]], i32 2, i1 false)
138
+ // LLVM: %[[#V6:]] = load i16, ptr %[[#V3]], align 2
139
+ // LLVM: ret i16 %[[#V6]]
140
+ S2 init2 (S2 s ) {
141
+ s .a = 1 ;
142
+ s .b = 2 ;
143
+ return s ;
144
+ }
145
+
146
+ // CIR: cir.func no_proto @foo3()
147
+ // CIR: %[[#V0:]] = cir.alloca !ty_S2_, !cir.ptr<!ty_S2_>, ["s"]
148
+ // CIR: %[[#V1:]] = cir.alloca !ty_S2_, !cir.ptr<!ty_S2_>, ["tmp"] {alignment = 1 : i64}
149
+ // CIR: %[[#V2:]] = cir.cast(bitcast, %[[#V0]] : !cir.ptr<!ty_S2_>), !cir.ptr<!u16i>
150
+ // CIR: %[[#V3:]] = cir.load %[[#V2]] : !cir.ptr<!u16i>, !u16i
151
+ // CIR: %[[#V4:]] = cir.call @init2(%[[#V3]]) : (!u16i) -> !u16i
152
+ // CIR: %[[#V5:]] = cir.cast(bitcast, %[[#V1]] : !cir.ptr<!ty_S2_>), !cir.ptr<!u16i>
153
+ // CIR: cir.store %[[#V4]], %[[#V5]] : !u16i, !cir.ptr<!u16i>
154
+ // CIR: cir.copy %[[#V1]] to %[[#V0]] : !cir.ptr<!ty_S2_>
155
+ // CIR: cir.return
156
+
157
+ // LLVM: @foo3()
158
+ // LLVM: %[[#V1:]] = alloca %struct.S2, i64 1, align 1
159
+ // LLVM: %[[#V2:]] = alloca %struct.S2, i64 1, align 1
160
+ // LLVM: %[[#V3:]] = load i16, ptr %[[#V1]], align 2
161
+ // LLVM: %[[#V4:]] = call i16 @init2(i16 %[[#V3]])
162
+ // LLVM: store i16 %[[#V4]], ptr %[[#V2]], align 2
163
+ // LLVM: call void @llvm.memcpy.p0.p0.i32(ptr %[[#V1]], ptr %[[#V2]], i32 2, i1 false)
164
+ void foo3 () {
165
+ S2 s ;
166
+ s = init2 (s );
167
+ }
0 commit comments