@@ -95,8 +95,7 @@ UNIT_TEST_CASE_WITH_ZONE(NativeCallingConvention_struct3bytesx10) {
95
95
member_types.Add (&int8type);
96
96
member_types.Add (&int8type);
97
97
member_types.Add (&int8type);
98
- const auto & struct_type =
99
- NativeCompoundType::FromNativeTypes (Z, member_types);
98
+ const auto & struct_type = NativeStructType::FromNativeTypes (Z, member_types);
100
99
101
100
auto & arguments = *new (Z) NativeTypes (Z, 10 );
102
101
arguments.Add (&struct_type);
@@ -138,8 +137,7 @@ UNIT_TEST_CASE_WITH_ZONE(NativeCallingConvention_struct16bytesHomogenousx10) {
138
137
member_types.Add (&float_type);
139
138
member_types.Add (&float_type);
140
139
member_types.Add (&float_type);
141
- const auto & struct_type =
142
- NativeCompoundType::FromNativeTypes (Z, member_types);
140
+ const auto & struct_type = NativeStructType::FromNativeTypes (Z, member_types);
143
141
144
142
auto & arguments = *new (Z) NativeTypes (Z, 13 );
145
143
arguments.Add (&struct_type);
@@ -174,14 +172,13 @@ UNIT_TEST_CASE_WITH_ZONE(NativeCallingConvention_struct16bytesHomogenousx10_2) {
174
172
auto & full_float_member_types = *new (Z) NativeTypes (Z, 1 );
175
173
full_float_member_types.Add (&float_2_array_type);
176
174
const auto & float_array_struct_type =
177
- NativeCompoundType ::FromNativeTypes (Z, full_float_member_types);
175
+ NativeStructType ::FromNativeTypes (Z, full_float_member_types);
178
176
179
177
auto & member_types = *new (Z) NativeTypes (Z, 3 );
180
178
member_types.Add (&float_1_array_type);
181
179
member_types.Add (&float_array_struct_type);
182
180
member_types.Add (&float_type);
183
- const auto & struct_type =
184
- NativeCompoundType::FromNativeTypes (Z, member_types);
181
+ const auto & struct_type = NativeStructType::FromNativeTypes (Z, member_types);
185
182
186
183
auto & arguments = *new (Z) NativeTypes (Z, 13 );
187
184
arguments.Add (&struct_type);
@@ -203,6 +200,55 @@ UNIT_TEST_CASE_WITH_ZONE(NativeCallingConvention_struct16bytesHomogenousx10_2) {
203
200
RunSignatureTest (Z, " struct16bytesHomogenousx10" , arguments, struct_type);
204
201
}
205
202
203
+ // Test with homogenous union.
204
+ //
205
+ // Even though the number of floats nested is different, this is still laid
206
+ // out as a homogeneous aggregate in arm64 and arm hardfp.
207
+ //
208
+ // Even though the member sizes are different, these unions are still passed in
209
+ // xmm registers on Linux/MacOS x64.
210
+ //
211
+ // See the *.expect in ./unit_tests for this behavior.
212
+ UNIT_TEST_CASE_WITH_ZONE (NativeCallingConvention_union16bytesHomogenousx10) {
213
+ const auto & float_type = *new (Z) NativePrimitiveType (kFloat );
214
+ const auto & int8type = *new (Z) NativePrimitiveType (kInt8 );
215
+
216
+ const auto & float_array_type = *new (Z) NativeArrayType (float_type, 3 );
217
+
218
+ auto & struct_member_types = *new (Z) NativeTypes (Z, 4 );
219
+ struct_member_types.Add (&float_type);
220
+ struct_member_types.Add (&float_type);
221
+ struct_member_types.Add (&float_type);
222
+ struct_member_types.Add (&float_type);
223
+ const auto & struct_type =
224
+ NativeStructType::FromNativeTypes (Z, struct_member_types);
225
+
226
+ auto & member_types = *new (Z) NativeTypes (Z, 2 );
227
+ member_types.Add (&float_array_type);
228
+ member_types.Add (&struct_type);
229
+ const auto & union_type = NativeUnionType::FromNativeTypes (Z, member_types);
230
+
231
+ EXPECT_EQ (16 , union_type.SizeInBytes ());
232
+ EXPECT (union_type.ContainsHomogenuousFloats ());
233
+
234
+ auto & arguments = *new (Z) NativeTypes (Z, 13 );
235
+ arguments.Add (&union_type);
236
+ arguments.Add (&union_type);
237
+ arguments.Add (&union_type);
238
+ arguments.Add (&union_type);
239
+ arguments.Add (&union_type);
240
+ arguments.Add (&union_type);
241
+ arguments.Add (&union_type);
242
+ arguments.Add (&union_type);
243
+ arguments.Add (&union_type);
244
+ arguments.Add (&int8type); // Check integer register back filling, if any.
245
+ arguments.Add (&union_type); // Check stack alignment of struct.
246
+
247
+ // Identical expectation files as previous test, struct contains the same
248
+ // members, but nested in arrays and nested structs.
249
+ RunSignatureTest (Z, " union16bytesHomogenousx10" , arguments, union_type);
250
+ }
251
+
206
252
// A fairly big struct.
207
253
//
208
254
// On arm, split up in 8-byte chunks. The first chunk goes into two registers,
@@ -237,8 +283,7 @@ UNIT_TEST_CASE_WITH_ZONE(NativeCallingConvention_struct128bytesx1) {
237
283
member_types.Add (&int64_type);
238
284
member_types.Add (&int64_type);
239
285
member_types.Add (&int64_type);
240
- const auto & struct_type =
241
- NativeCompoundType::FromNativeTypes (Z, member_types);
286
+ const auto & struct_type = NativeStructType::FromNativeTypes (Z, member_types);
242
287
243
288
auto & arguments = *new (Z) NativeTypes (Z, 2 );
244
289
arguments.Add (&struct_type);
@@ -260,8 +305,7 @@ UNIT_TEST_CASE_WITH_ZONE(NativeCallingConvention_struct16bytesMixedx10) {
260
305
member_types.Add (&float_type);
261
306
member_types.Add (&int32_type);
262
307
member_types.Add (&int32_type);
263
- const auto & struct_type =
264
- NativeCompoundType::FromNativeTypes (Z, member_types);
308
+ const auto & struct_type = NativeStructType::FromNativeTypes (Z, member_types);
265
309
266
310
auto & arguments = *new (Z) NativeTypes (Z, 11 );
267
311
arguments.Add (&struct_type);
@@ -291,8 +335,7 @@ UNIT_TEST_CASE_WITH_ZONE(NativeCallingConvention_struct16bytesMixedx10_2) {
291
335
member_types.Add (&float_type);
292
336
member_types.Add (&int32_type);
293
337
member_types.Add (&int32_type);
294
- const auto & struct_type =
295
- NativeCompoundType::FromNativeTypes (Z, member_types);
338
+ const auto & struct_type = NativeStructType::FromNativeTypes (Z, member_types);
296
339
297
340
auto & arguments = *new (Z) NativeTypes (Z, 15 );
298
341
arguments.Add (&float_type);
@@ -342,20 +385,19 @@ UNIT_TEST_CASE_WITH_ZONE(NativeCallingConvention_struct16bytesMixedx10_3) {
342
385
half_float_member_types.Add (&int32_type);
343
386
half_float_member_types.Add (&float_type);
344
387
const auto & half_float_type =
345
- NativeCompoundType ::FromNativeTypes (Z, half_float_member_types);
388
+ NativeStructType ::FromNativeTypes (Z, half_float_member_types);
346
389
347
390
const auto & float_array_type = *new (Z) NativeArrayType (float_type, 1 );
348
391
auto & full_float_member_types = *new (Z) NativeTypes (Z, 1 );
349
392
full_float_member_types.Add (&float_array_type);
350
393
const auto & full_float_type =
351
- NativeCompoundType ::FromNativeTypes (Z, full_float_member_types);
394
+ NativeStructType ::FromNativeTypes (Z, full_float_member_types);
352
395
353
396
auto & member_types = *new (Z) NativeTypes (Z, 3 );
354
397
member_types.Add (&int32_type);
355
398
member_types.Add (&half_float_type);
356
399
member_types.Add (&full_float_type);
357
- const auto & struct_type =
358
- NativeCompoundType::FromNativeTypes (Z, member_types);
400
+ const auto & struct_type = NativeStructType::FromNativeTypes (Z, member_types);
359
401
360
402
auto & arguments = *new (Z) NativeTypes (Z, 11 );
361
403
arguments.Add (&struct_type);
@@ -389,8 +431,7 @@ UNIT_TEST_CASE_WITH_ZONE(NativeCallingConvention_struct8bytesx1) {
389
431
member_types.Add (&int8type);
390
432
member_types.Add (&int8type);
391
433
member_types.Add (&int8type);
392
- const auto & struct_type =
393
- NativeCompoundType::FromNativeTypes (Z, member_types);
434
+ const auto & struct_type = NativeStructType::FromNativeTypes (Z, member_types);
394
435
395
436
auto & arguments = *new (Z) NativeTypes (Z, 1 );
396
437
arguments.Add (&struct_type);
@@ -418,7 +459,7 @@ UNIT_TEST_CASE_WITH_ZONE(NativeCallingConvention_struct8bytesPackedx10) {
418
459
member_types.Add (&int8_type);
419
460
member_types.Add (&int8_type);
420
461
const auto & struct_type =
421
- NativeCompoundType ::FromNativeTypes (Z, member_types, /* packing=*/ 1 );
462
+ NativeStructType ::FromNativeTypes (Z, member_types, /* packing=*/ 1 );
422
463
EXPECT_EQ (8 , struct_type.SizeInBytes ());
423
464
EXPECT (struct_type.ContainsUnalignedMembers ());
424
465
@@ -456,7 +497,7 @@ UNIT_TEST_CASE_WITH_ZONE(NativeCallingConvention_structPacked) {
456
497
member_types.Add (&int8_type);
457
498
member_types.Add (&double_type);
458
499
const auto & struct_type =
459
- NativeCompoundType ::FromNativeTypes (Z, member_types, /* packing=*/ 1 );
500
+ NativeStructType ::FromNativeTypes (Z, member_types, /* packing=*/ 1 );
460
501
EXPECT_EQ (9 , struct_type.SizeInBytes ());
461
502
EXPECT (struct_type.ContainsUnalignedMembers ());
462
503
@@ -469,6 +510,51 @@ UNIT_TEST_CASE_WITH_ZONE(NativeCallingConvention_structPacked) {
469
510
RunSignatureTest (Z, " structPacked" , arguments, struct_type);
470
511
}
471
512
513
+ // The union is only 5 bytes because it's members are packed.
514
+ //
515
+ // Many calling conventions pass this struct in single registers or less
516
+ // stack slots because of this.
517
+ //
518
+ // Non-windows x64 passes this struct on the stack instead of in a single
519
+ // CPU register, because it contains a mis-aligned member.
520
+ //
521
+ // See the *.expect in ./unit_tests for this behavior.
522
+ UNIT_TEST_CASE_WITH_ZONE (NativeCallingConvention_union5bytesPackedx10) {
523
+ const auto & uint8_type = *new (Z) NativePrimitiveType (kUint8 );
524
+ const auto & uint32_type = *new (Z) NativePrimitiveType (kUint32 );
525
+
526
+ auto & inner_members = *new (Z) NativeTypes (Z, 2 );
527
+ inner_members.Add (&uint8_type);
528
+ inner_members.Add (&uint32_type);
529
+ const intptr_t packing = 1 ;
530
+ const auto & struct_type =
531
+ NativeStructType::FromNativeTypes (Z, inner_members, packing);
532
+
533
+ const auto & array_type = *new (Z) NativeArrayType (uint8_type, 5 );
534
+
535
+ auto & member_types = *new (Z) NativeTypes (Z, 2 );
536
+ member_types.Add (&array_type);
537
+ member_types.Add (&struct_type);
538
+ const auto & union_type = NativeUnionType::FromNativeTypes (Z, member_types);
539
+
540
+ EXPECT_EQ (5 , union_type.SizeInBytes ());
541
+ EXPECT_EQ (1 , union_type.AlignmentInBytesField ());
542
+
543
+ auto & arguments = *new (Z) NativeTypes (Z, 10 );
544
+ arguments.Add (&union_type);
545
+ arguments.Add (&union_type);
546
+ arguments.Add (&union_type);
547
+ arguments.Add (&union_type);
548
+ arguments.Add (&union_type);
549
+ arguments.Add (&union_type);
550
+ arguments.Add (&union_type);
551
+ arguments.Add (&union_type);
552
+ arguments.Add (&union_type);
553
+ arguments.Add (&union_type);
554
+
555
+ RunSignatureTest (Z, " union5bytesPackedx10" , arguments, union_type);
556
+ }
557
+
472
558
} // namespace ffi
473
559
} // namespace compiler
474
560
} // namespace dart
0 commit comments