@@ -1245,9 +1245,10 @@ static void resolve_enum_type(CodeGen *g, TypeTableEntry *enum_type) {
1245
1245
uint32_t gen_field_count = enum_type->data .enumeration .gen_field_count ;
1246
1246
ZigLLVMDIType **union_inner_di_types = allocate<ZigLLVMDIType*>(gen_field_count);
1247
1247
1248
- TypeTableEntry *biggest_union_member = nullptr ;
1248
+ TypeTableEntry *most_aligned_union_member = nullptr ;
1249
+ uint64_t size_of_most_aligned_member_in_bits = 0 ;
1249
1250
uint64_t biggest_align_in_bits = 0 ;
1250
- uint64_t biggest_union_member_size_in_bits = 0 ;
1251
+ uint64_t biggest_size_in_bits = 0 ;
1251
1252
1252
1253
Scope *scope = &enum_type->data .enumeration .decls_scope ->base ;
1253
1254
ImportTableEntry *import = get_scope_import (scope);
@@ -1271,27 +1272,28 @@ static void resolve_enum_type(CodeGen *g, TypeTableEntry *enum_type) {
1271
1272
if (!type_has_bits (field_type))
1272
1273
continue ;
1273
1274
1274
- uint64_t debug_size_in_bits = 8 *LLVMStoreSizeOfType (g->target_data_ref , field_type->type_ref );
1275
- uint64_t debug_align_in_bits = 8 *LLVMABISizeOfType (g->target_data_ref , field_type->type_ref );
1275
+ uint64_t store_size_in_bits = 8 *LLVMStoreSizeOfType (g->target_data_ref , field_type->type_ref );
1276
+ uint64_t preferred_align_in_bits = 8 *LLVMPreferredAlignmentOfType (g->target_data_ref , field_type->type_ref );
1276
1277
1277
- assert (debug_size_in_bits > 0 );
1278
- assert (debug_align_in_bits > 0 );
1278
+ assert (store_size_in_bits > 0 );
1279
+ assert (preferred_align_in_bits > 0 );
1279
1280
1280
1281
union_inner_di_types[type_enum_field->gen_index ] = ZigLLVMCreateDebugMemberType (g->dbuilder ,
1281
1282
ZigLLVMTypeToScope (enum_type->di_type ), buf_ptr (type_enum_field->name ),
1282
1283
import->di_file , (unsigned )(field_node->line + 1 ),
1283
- debug_size_in_bits ,
1284
- debug_align_in_bits ,
1284
+ store_size_in_bits ,
1285
+ preferred_align_in_bits ,
1285
1286
0 ,
1286
1287
0 , field_type->di_type );
1287
1288
1288
- biggest_align_in_bits = max (biggest_align_in_bits, debug_align_in_bits );
1289
+ biggest_size_in_bits = max (biggest_size_in_bits, store_size_in_bits );
1289
1290
1290
- if (!biggest_union_member ||
1291
- debug_size_in_bits > biggest_union_member_size_in_bits )
1291
+ if (!most_aligned_union_member ||
1292
+ preferred_align_in_bits > biggest_align_in_bits )
1292
1293
{
1293
- biggest_union_member = field_type;
1294
- biggest_union_member_size_in_bits = debug_size_in_bits;
1294
+ most_aligned_union_member = field_type;
1295
+ biggest_align_in_bits = preferred_align_in_bits;
1296
+ size_of_most_aligned_member_in_bits = store_size_in_bits;
1295
1297
}
1296
1298
}
1297
1299
@@ -1300,27 +1302,52 @@ static void resolve_enum_type(CodeGen *g, TypeTableEntry *enum_type) {
1300
1302
enum_type->data .enumeration .complete = true ;
1301
1303
1302
1304
if (!enum_type->data .enumeration .is_invalid ) {
1303
- enum_type->data .enumeration .union_type = biggest_union_member;
1304
-
1305
1305
TypeTableEntry *tag_int_type = get_smallest_unsigned_int_type (g, field_count);
1306
1306
TypeTableEntry *tag_type_entry = create_enum_tag_type (g, enum_type, tag_int_type);
1307
1307
enum_type->data .enumeration .tag_type = tag_type_entry;
1308
1308
1309
- if (biggest_union_member) {
1309
+ uint64_t align_of_tag_in_bits = 8 *LLVMPreferredAlignmentOfType (g->target_data_ref , tag_int_type->type_ref );
1310
+
1311
+ if (most_aligned_union_member) {
1310
1312
// create llvm type for union
1311
- LLVMTypeRef union_element_type = biggest_union_member->type_ref ;
1312
- LLVMTypeRef union_type_ref = LLVMStructType (&union_element_type, 1 , false );
1313
+ uint64_t padding_in_bits = biggest_size_in_bits - size_of_most_aligned_member_in_bits;
1314
+ LLVMTypeRef union_type_ref;
1315
+ if (padding_in_bits > 0 ) {
1316
+ TypeTableEntry *u8_type = get_int_type (g, false , 8 );
1317
+ TypeTableEntry *padding_array = get_array_type (g, u8_type, padding_in_bits / 8 );
1318
+ LLVMTypeRef union_element_types[] = {
1319
+ most_aligned_union_member->type_ref ,
1320
+ padding_array->type_ref ,
1321
+ };
1322
+ union_type_ref = LLVMStructType (union_element_types, 2 , false );
1323
+ } else {
1324
+ LLVMTypeRef union_element_types[] = {
1325
+ most_aligned_union_member->type_ref ,
1326
+ };
1327
+ union_type_ref = LLVMStructType (union_element_types, 1 , false );
1328
+ }
1329
+ enum_type->data .enumeration .union_type_ref = union_type_ref;
1330
+
1331
+ assert (8 *LLVMPreferredAlignmentOfType (g->target_data_ref , union_type_ref) >= biggest_align_in_bits);
1332
+ assert (8 *LLVMStoreSizeOfType (g->target_data_ref , union_type_ref) >= biggest_size_in_bits);
1333
+
1334
+ if (align_of_tag_in_bits >= biggest_align_in_bits) {
1335
+ enum_type->data .enumeration .gen_tag_index = 0 ;
1336
+ enum_type->data .enumeration .gen_union_index = 1 ;
1337
+ } else {
1338
+ enum_type->data .enumeration .gen_union_index = 0 ;
1339
+ enum_type->data .enumeration .gen_tag_index = 1 ;
1340
+ }
1313
1341
1314
1342
// create llvm type for root struct
1315
- LLVMTypeRef root_struct_element_types[] = {
1316
- tag_type_entry->type_ref ,
1317
- union_type_ref,
1318
- };
1343
+ LLVMTypeRef root_struct_element_types[2 ];
1344
+ root_struct_element_types[enum_type->data .enumeration .gen_tag_index ] = tag_type_entry->type_ref ;
1345
+ root_struct_element_types[enum_type->data .enumeration .gen_union_index ] = union_type_ref;
1319
1346
LLVMStructSetBody (enum_type->type_ref , root_struct_element_types, 2 , false );
1320
1347
1321
1348
// create debug type for tag
1322
1349
uint64_t tag_debug_size_in_bits = 8 *LLVMStoreSizeOfType (g->target_data_ref , tag_type_entry->type_ref );
1323
- uint64_t tag_debug_align_in_bits = 8 *LLVMABISizeOfType (g->target_data_ref , tag_type_entry->type_ref );
1350
+ uint64_t tag_debug_align_in_bits = 8 *LLVMPreferredAlignmentOfType (g->target_data_ref , tag_type_entry->type_ref );
1324
1351
ZigLLVMDIType *tag_di_type = ZigLLVMCreateDebugEnumerationType (g->dbuilder ,
1325
1352
ZigLLVMTypeToScope (enum_type->di_type ), " AnonEnum" ,
1326
1353
import->di_file , (unsigned )(decl_node->line + 1 ),
@@ -1331,11 +1358,12 @@ static void resolve_enum_type(CodeGen *g, TypeTableEntry *enum_type) {
1331
1358
ZigLLVMDIType *union_di_type = ZigLLVMCreateDebugUnionType (g->dbuilder ,
1332
1359
ZigLLVMTypeToScope (enum_type->di_type ), " AnonUnion" ,
1333
1360
import->di_file , (unsigned )(decl_node->line + 1 ),
1334
- biggest_union_member_size_in_bits , biggest_align_in_bits, 0 , union_inner_di_types,
1361
+ biggest_size_in_bits , biggest_align_in_bits, 0 , union_inner_di_types,
1335
1362
gen_field_count, 0 , " " );
1336
1363
1337
1364
// create debug types for members of root struct
1338
- uint64_t tag_offset_in_bits = 8 *LLVMOffsetOfElement (g->target_data_ref , enum_type->type_ref , 0 );
1365
+ uint64_t tag_offset_in_bits = 8 *LLVMOffsetOfElement (g->target_data_ref , enum_type->type_ref ,
1366
+ enum_type->data .enumeration .gen_tag_index );
1339
1367
ZigLLVMDIType *tag_member_di_type = ZigLLVMCreateDebugMemberType (g->dbuilder ,
1340
1368
ZigLLVMTypeToScope (enum_type->di_type ), " tag_field" ,
1341
1369
import->di_file , (unsigned )(decl_node->line + 1 ),
@@ -1344,21 +1372,20 @@ static void resolve_enum_type(CodeGen *g, TypeTableEntry *enum_type) {
1344
1372
tag_offset_in_bits,
1345
1373
0 , tag_di_type);
1346
1374
1347
- uint64_t union_offset_in_bits = 8 *LLVMOffsetOfElement (g->target_data_ref , enum_type->type_ref , 1 );
1375
+ uint64_t union_offset_in_bits = 8 *LLVMOffsetOfElement (g->target_data_ref , enum_type->type_ref ,
1376
+ enum_type->data .enumeration .gen_union_index );
1348
1377
ZigLLVMDIType *union_member_di_type = ZigLLVMCreateDebugMemberType (g->dbuilder ,
1349
1378
ZigLLVMTypeToScope (enum_type->di_type ), " union_field" ,
1350
1379
import->di_file , (unsigned )(decl_node->line + 1 ),
1351
- biggest_union_member_size_in_bits ,
1380
+ biggest_size_in_bits ,
1352
1381
biggest_align_in_bits,
1353
1382
union_offset_in_bits,
1354
1383
0 , union_di_type);
1355
1384
1356
1385
// create debug type for root struct
1357
- ZigLLVMDIType *di_root_members[] = {
1358
- tag_member_di_type,
1359
- union_member_di_type,
1360
- };
1361
-
1386
+ ZigLLVMDIType *di_root_members[2 ];
1387
+ di_root_members[enum_type->data .enumeration .gen_tag_index ] = tag_member_di_type;
1388
+ di_root_members[enum_type->data .enumeration .gen_union_index ] = union_member_di_type;
1362
1389
1363
1390
uint64_t debug_size_in_bits = 8 *LLVMStoreSizeOfType (g->target_data_ref , enum_type->type_ref );
1364
1391
uint64_t debug_align_in_bits = 8 *LLVMABISizeOfType (g->target_data_ref , enum_type->type_ref );
@@ -1378,7 +1405,7 @@ static void resolve_enum_type(CodeGen *g, TypeTableEntry *enum_type) {
1378
1405
1379
1406
// create debug type for tag
1380
1407
uint64_t tag_debug_size_in_bits = 8 *LLVMStoreSizeOfType (g->target_data_ref , tag_type_entry->type_ref );
1381
- uint64_t tag_debug_align_in_bits = 8 *LLVMABISizeOfType (g->target_data_ref , tag_type_entry->type_ref );
1408
+ uint64_t tag_debug_align_in_bits = 8 *LLVMPreferredAlignmentOfType (g->target_data_ref , tag_type_entry->type_ref );
1382
1409
ZigLLVMDIType *tag_di_type = ZigLLVMCreateDebugEnumerationType (g->dbuilder ,
1383
1410
ZigLLVMFileToScope (import->di_file ), buf_ptr (&enum_type->name ),
1384
1411
import->di_file , (unsigned )(decl_node->line + 1 ),
@@ -2541,7 +2568,7 @@ bool types_match_const_cast_only(TypeTableEntry *expected_type, TypeTableEntry *
2541
2568
if (expected_type->data .fn .is_generic != actual_type->data .fn .is_generic ) {
2542
2569
return false ;
2543
2570
}
2544
- if (!expected_type->data .fn .is_generic &&
2571
+ if (!expected_type->data .fn .is_generic &&
2545
2572
actual_type->data .fn .fn_type_id .return_type ->id != TypeTableEntryIdUnreachable &&
2546
2573
!types_match_const_cast_only (
2547
2574
expected_type->data .fn .fn_type_id .return_type ,
0 commit comments