| ... | ... | @@ -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, |