@@ -125,4 +125,84 @@ S1 s1(S1 arg) {
125125 // CHECK: %[[#V18:]] = cir.load %[[#V17]] : !cir.ptr<!u64i>, !u64i
126126 // CHECK: cir.return %[[#V18]] : !u64i
127127 return {1 , 2 };
128- }
128+ }
129+
130+ // / Test call conv lowering for flattened structs. ///
131+
132+ struct S2 {
133+ int x, y, z;
134+ };
135+
136+ // COM: Function prologue
137+
138+ // CHECK: cir.func @_Z2s22S2(%[[ARG0:[a-z0-9]+]]: !u64i {{.*}}, %[[ARG1:[a-z0-9]+]]: !s32i {{.*}}) -> !ty_anon_struct
139+ // CHECK: %[[#F0:]] = cir.alloca !ty_S2_, !cir.ptr<!ty_S2_>
140+ // CHECK: %[[#F1:]] = cir.alloca !ty_anon_struct, !cir.ptr<!ty_anon_struct>
141+ // CHECK: %[[#F2:]] = cir.get_member %[[#F1]][0]{{.*}} : !cir.ptr<!ty_anon_struct> -> !cir.ptr<!u64i>
142+ // CHECK: cir.store %[[ARG0]], %[[#F2]] : !u64i, !cir.ptr<!u64i>
143+ // CHECK: %[[#F3:]] = cir.get_member %[[#F1]][1]{{.*}} : !cir.ptr<!ty_anon_struct> -> !cir.ptr<!s32i>
144+ // CHECK: cir.store %[[ARG1]], %[[#F3]] : !s32i, !cir.ptr<!s32i>
145+ // CHECK: %[[#F4:]] = cir.cast(bitcast, %[[#F1]] : !cir.ptr<!ty_anon_struct>), !cir.ptr<!void>
146+ // CHECK: %[[#F5:]] = cir.cast(bitcast, %[[#F0]] : !cir.ptr<!ty_S2_>), !cir.ptr<!void>
147+ // CHECK: %[[#F6:]] = cir.const #cir.int<12> : !u64i
148+ // CHECK: cir.libc.memcpy %[[#F6]] bytes from %[[#F4]] to %[[#F5]]
149+ S2 s2 (S2 arg) {
150+ // CHECK: %[[#F7:]] = cir.alloca !ty_S2_, !cir.ptr<!ty_S2_>, ["__retval"] {alignment = 4 : i64}
151+ // CHECK: %[[#F8:]] = cir.alloca !ty_S2_, !cir.ptr<!ty_S2_>, ["agg.tmp0"] {alignment = 4 : i64}
152+ // CHECK: %[[#F9:]] = cir.alloca !ty_S2_, !cir.ptr<!ty_S2_>, ["agg.tmp1"] {alignment = 4 : i64}
153+ // CHECK: %[[#F10:]] = cir.alloca !ty_anon_struct, !cir.ptr<!ty_anon_struct>, ["tmp"] {alignment = 8 : i64}
154+ // CHECK: %[[#F11:]] = cir.alloca !ty_S2_, !cir.ptr<!ty_S2_>, ["tmp"] {alignment = 4 : i64}
155+ // CHECK: %[[#F12:]] = cir.alloca !ty_anon_struct, !cir.ptr<!ty_anon_struct>, ["tmp"] {alignment = 8 : i64}
156+ // CHECK: %[[#F13:]] = cir.alloca !ty_anon_struct, !cir.ptr<!ty_anon_struct>, ["tmp"] {alignment = 8 : i64}
157+
158+ // COM: Construction of S2 { 1, 2, 3 }.
159+
160+ // CHECK: %[[#F14:]] = cir.get_member %[[#F8]][0] {{.*}} : !cir.ptr<!ty_S2_> -> !cir.ptr<!s32i>
161+ // CHECK: %[[#F15:]] = cir.const #cir.int<1> : !s32i
162+ // CHECK: cir.store %[[#F15]], %[[#F14]] : !s32i, !cir.ptr<!s32i>
163+ // CHECK: %[[#F16:]] = cir.get_member %[[#F8]][1] {{.*}} : !cir.ptr<!ty_S2_> -> !cir.ptr<!s32i>
164+ // CHECK: %[[#F17:]] = cir.const #cir.int<2> : !s32i
165+ // CHECK: cir.store %[[#F17]], %[[#F16]] : !s32i, !cir.ptr<!s32i>
166+ // CHECK: %[[#F18:]] = cir.get_member %[[#F8]][2] {{.*}} : !cir.ptr<!ty_S2_> -> !cir.ptr<!s32i>
167+ // CHECK: %[[#F19:]] = cir.const #cir.int<3> : !s32i
168+ // CHECK: cir.store %[[#F19]], %[[#F18]] : !s32i, !cir.ptr<!s32i>
169+
170+ // COM: Flattening of the struct.
171+ // COM: { i32, i32, i32 } -> { i64, i32 }.
172+
173+ // CHECK: %[[#F20:]] = cir.load %[[#F8]] : !cir.ptr<!ty_S2_>, !ty_S2_
174+ // CHECK: cir.store %[[#F20]], %[[#F11]] : !ty_S2_, !cir.ptr<!ty_S2_>
175+ // CHECK: %[[#F21:]] = cir.cast(bitcast, %[[#F11]] : !cir.ptr<!ty_S2_>), !cir.ptr<!void>
176+ // CHECK: %[[#F22:]] = cir.cast(bitcast, %[[#F10]] : !cir.ptr<!ty_anon_struct>), !cir.ptr<!void>
177+ // CHECK: %[[#F23:]] = cir.const #cir.int<12> : !u64i
178+ // CHECK: cir.libc.memcpy %[[#F23]] bytes from %[[#F21]] to %[[#F22]]
179+
180+ // COM: Function call.
181+ // COM: Retrieve the two values in { i64, i32 }.
182+
183+ // CHECK: %[[#F24:]] = cir.get_member %[[#F10]][0] {name = ""} : !cir.ptr<!ty_anon_struct> -> !cir.ptr<!u64i>
184+ // CHECK: %[[#F25:]] = cir.load %[[#F24]] : !cir.ptr<!u64i>, !u64i
185+ // CHECK: %[[#F26:]] = cir.get_member %[[#F10]][1] {name = ""} : !cir.ptr<!ty_anon_struct> -> !cir.ptr<!s32i>
186+ // CHECK: %[[#F27:]] = cir.load %[[#F26]] : !cir.ptr<!s32i>, !s32i
187+ // CHECK: %[[#F28:]] = cir.call @_Z2s22S2(%[[#F25]], %[[#F27]]) : (!u64i, !s32i) -> !ty_anon_struct
188+ // CHECK: cir.store %[[#F28]], %[[#F12]] : !ty_anon_struct, !cir.ptr<!ty_anon_struct>
189+
190+ // CHECK: %[[#F29:]] = cir.cast(bitcast, %[[#F12]] : !cir.ptr<!ty_anon_struct>), !cir.ptr<!void>
191+ // CHECK: %[[#F30:]] = cir.cast(bitcast, %[[#F9]] : !cir.ptr<!ty_S2_>), !cir.ptr<!void>
192+ // CHECK: %[[#F31:]] = cir.const #cir.int<12> : !u64i
193+ // CHECK: cir.libc.memcpy %[[#F31]] bytes from %[[#F29]] to %[[#F30]]
194+
195+ // COM: Construct S2 { 1, 2, 3 } again.
196+ // COM: It has been tested above, so no duplication here.
197+
198+ // COM: For return, the first two fields of S2 is also coerced.
199+
200+ // CHECK: %[[#F39:]] = cir.cast(bitcast, %[[#F7]] : !cir.ptr<!ty_S2_>), !cir.ptr<!void>
201+ // CHECK: %[[#F40:]] = cir.cast(bitcast, %[[#F13]] : !cir.ptr<!ty_anon_struct>), !cir.ptr<!void>
202+ // CHECK: %[[#F41:]] = cir.const #cir.int<12> : !u64i
203+ // cir.libc.memcpy %[[#F41]] bytes from %[[#F39]] to %[[#F40]]
204+ // CHECK: %[[#F42:]] = cir.load %[[#F13]] : !cir.ptr<!ty_anon_struct>, !ty_anon_struct
205+ // cir.return %[[#F42]] : !ty_anon_struct
206+ s2 ({ 1 , 2 , 3 });
207+ return { 1 , 2 , 3 };
208+ }
0 commit comments