| author | |
| committer | |
| log | 3a600297ca3f99ee57630c44900eec1fe7c92804 |
| tree | 9642e53df266077c0ee76c1a045366f8f805fe95 |
| parent | 4a82c2d124881512548254f5cdff3009b2f424df |
| parent | 634e8713c394bacfe080d03256d1dd4f9a43dd8c |
19 files changed, 794 insertions(+), 150 deletions(-)
src-self-hosted/main.zig+8-6| ... | @@ -3,24 +3,27 @@ const io = @import("std").io; | ... | @@ -3,24 +3,27 @@ const io = @import("std").io; |
| 3 | const os = @import("std").os; | 3 | const os = @import("std").os; |
| 4 | const heap = @import("std").mem; | 4 | const heap = @import("std").mem; |
| 5 | 5 | ||
| 6 | // TODO: OutSteam and InStream interface | ||
| 7 | // TODO: move allocator to heap namespace | ||
| 8 | // TODO: sync up CLI with c++ code | 6 | // TODO: sync up CLI with c++ code |
| 7 | // TODO: concurrency | ||
| 9 | 8 | ||
| 10 | error InvalidArgument; | 9 | error InvalidArgument; |
| 11 | error MissingArg0; | 10 | error MissingArg0; |
| 12 | 11 | ||
| 13 | var arg0: []u8 = undefined; | 12 | var arg0: []u8 = undefined; |
| 14 | 13 | ||
| 14 | var stderr_file: io.File = undefined; | ||
| 15 | const stderr = &stderr_file.out_stream; | ||
| 16 | |||
| 15 | pub fn main() -> %void { | 17 | pub fn main() -> %void { |
| 18 | stderr_file = %return io.getStdErr(); | ||
| 16 | if (internal_main()) |_| { | 19 | if (internal_main()) |_| { |
| 17 | return; | 20 | return; |
| 18 | } else |err| { | 21 | } else |err| { |
| 19 | if (err == error.InvalidArgument) { | 22 | if (err == error.InvalidArgument) { |
| 20 | io.stderr.printf("\n") %% return err; | 23 | stderr.print("\n") %% return err; |
| 21 | printUsage(&io.stderr) %% return err; | 24 | printUsage(stderr) %% return err; |
| 22 | } else { | 25 | } else { |
| 23 | io.stderr.printf("{}\n", err) %% return err; | 26 | stderr.print("{}\n", err) %% return err; |
| 24 | } | 27 | } |
| 25 | return err; | 28 | return err; |
| 26 | } | 29 | } |
| ... | @@ -266,7 +269,6 @@ fn printUsage(outstream: &io.OutStream) -> %void { | ... | @@ -266,7 +269,6 @@ fn printUsage(outstream: &io.OutStream) -> %void { |
| 266 | \\ --test-cmd-bin appends test binary path to test cmd args | 269 | \\ --test-cmd-bin appends test binary path to test cmd args |
| 267 | \\ | 270 | \\ |
| 268 | ); | 271 | ); |
| 269 | %return outstream.flush(); | ||
| 270 | } | 272 | } |
| 271 | 273 | ||
| 272 | const ZIG_ZEN = | 274 | const ZIG_ZEN = |
src/all_types.hpp+34| ... | @@ -1211,6 +1211,8 @@ enum BuiltinFnId { | ... | @@ -1211,6 +1211,8 @@ enum BuiltinFnId { |
| 1211 | BuiltinFnIdMaxValue, | 1211 | BuiltinFnIdMaxValue, |
| 1212 | BuiltinFnIdMinValue, | 1212 | BuiltinFnIdMinValue, |
| 1213 | BuiltinFnIdMemberCount, | 1213 | BuiltinFnIdMemberCount, |
| 1214 | BuiltinFnIdMemberType, | ||
| 1215 | BuiltinFnIdMemberName, | ||
| 1214 | BuiltinFnIdTypeof, | 1216 | BuiltinFnIdTypeof, |
| 1215 | BuiltinFnIdAddWithOverflow, | 1217 | BuiltinFnIdAddWithOverflow, |
| 1216 | BuiltinFnIdSubWithOverflow, | 1218 | BuiltinFnIdSubWithOverflow, |
| ... | @@ -1261,6 +1263,7 @@ enum BuiltinFnId { | ... | @@ -1261,6 +1263,7 @@ enum BuiltinFnId { |
| 1261 | BuiltinFnIdAlignCast, | 1263 | BuiltinFnIdAlignCast, |
| 1262 | BuiltinFnIdOpaqueType, | 1264 | BuiltinFnIdOpaqueType, |
| 1263 | BuiltinFnIdSetAlignStack, | 1265 | BuiltinFnIdSetAlignStack, |
| 1266 | BuiltinFnIdArgType, | ||
| 1264 | }; | 1267 | }; |
| 1265 | 1268 | ||
| 1266 | struct BuiltinFnEntry { | 1269 | struct BuiltinFnEntry { |
| ... | @@ -1366,6 +1369,12 @@ enum BuildMode { | ... | @@ -1366,6 +1369,12 @@ enum BuildMode { |
| 1366 | BuildModeSafeRelease, | 1369 | BuildModeSafeRelease, |
| 1367 | }; | 1370 | }; |
| 1368 | 1371 | ||
| 1372 | enum EmitFileType { | ||
| 1373 | EmitFileTypeBinary, | ||
| 1374 | EmitFileTypeAssembly, | ||
| 1375 | EmitFileTypeLLVMIr, | ||
| 1376 | }; | ||
| 1377 | |||
| 1369 | struct LinkLib { | 1378 | struct LinkLib { |
| 1370 | Buf *name; | 1379 | Buf *name; |
| 1371 | Buf *path; | 1380 | Buf *path; |
| ... | @@ -1449,6 +1458,7 @@ struct CodeGen { | ... | @@ -1449,6 +1458,7 @@ struct CodeGen { |
| 1449 | TypeTableEntry *entry_arg_tuple; | 1458 | TypeTableEntry *entry_arg_tuple; |
| 1450 | } builtin_types; | 1459 | } builtin_types; |
| 1451 | 1460 | ||
| 1461 | EmitFileType emit_file_type; | ||
| 1452 | ZigTarget zig_target; | 1462 | ZigTarget zig_target; |
| 1453 | LLVMTargetDataRef target_data_ref; | 1463 | LLVMTargetDataRef target_data_ref; |
| 1454 | unsigned pointer_size_bytes; | 1464 | unsigned pointer_size_bytes; |
| ... | @@ -1837,6 +1847,8 @@ enum IrInstructionId { | ... | @@ -1837,6 +1847,8 @@ enum IrInstructionId { |
| 1837 | IrInstructionIdMemcpy, | 1847 | IrInstructionIdMemcpy, |
| 1838 | IrInstructionIdSlice, | 1848 | IrInstructionIdSlice, |
| 1839 | IrInstructionIdMemberCount, | 1849 | IrInstructionIdMemberCount, |
| 1850 | IrInstructionIdMemberType, | ||
| 1851 | IrInstructionIdMemberName, | ||
| 1840 | IrInstructionIdBreakpoint, | 1852 | IrInstructionIdBreakpoint, |
| 1841 | IrInstructionIdReturnAddress, | 1853 | IrInstructionIdReturnAddress, |
| 1842 | IrInstructionIdFrameAddress, | 1854 | IrInstructionIdFrameAddress, |
| ... | @@ -1875,6 +1887,7 @@ enum IrInstructionId { | ... | @@ -1875,6 +1887,7 @@ enum IrInstructionId { |
| 1875 | IrInstructionIdAlignCast, | 1887 | IrInstructionIdAlignCast, |
| 1876 | IrInstructionIdOpaqueType, | 1888 | IrInstructionIdOpaqueType, |
| 1877 | IrInstructionIdSetAlignStack, | 1889 | IrInstructionIdSetAlignStack, |
| 1890 | IrInstructionIdArgType, | ||
| 1878 | }; | 1891 | }; |
| 1879 | 1892 | ||
| 1880 | struct IrInstruction { | 1893 | struct IrInstruction { |
| ... | @@ -2399,6 +2412,20 @@ struct IrInstructionMemberCount { | ... | @@ -2399,6 +2412,20 @@ struct IrInstructionMemberCount { |
| 2399 | IrInstruction *container; | 2412 | IrInstruction *container; |
| 2400 | }; | 2413 | }; |
| 2401 | 2414 | ||
| 2415 | struct IrInstructionMemberType { | ||
| 2416 | IrInstruction base; | ||
| 2417 | |||
| 2418 | IrInstruction *container_type; | ||
| 2419 | IrInstruction *member_index; | ||
| 2420 | }; | ||
| 2421 | |||
| 2422 | struct IrInstructionMemberName { | ||
| 2423 | IrInstruction base; | ||
| 2424 | |||
| 2425 | IrInstruction *container_type; | ||
| 2426 | IrInstruction *member_index; | ||
| 2427 | }; | ||
| 2428 | |||
| 2402 | struct IrInstructionBreakpoint { | 2429 | struct IrInstructionBreakpoint { |
| 2403 | IrInstruction base; | 2430 | IrInstruction base; |
| 2404 | }; | 2431 | }; |
| ... | @@ -2675,6 +2702,13 @@ struct IrInstructionSetAlignStack { | ... | @@ -2675,6 +2702,13 @@ struct IrInstructionSetAlignStack { |
| 2675 | IrInstruction *align_bytes; | 2702 | IrInstruction *align_bytes; |
| 2676 | }; | 2703 | }; |
| 2677 | 2704 | ||
| 2705 | struct IrInstructionArgType { | ||
| 2706 | IrInstruction base; | ||
| 2707 | |||
| 2708 | IrInstruction *fn_type; | ||
| 2709 | IrInstruction *arg_index; | ||
| 2710 | }; | ||
| 2711 | |||
| 2678 | static const size_t slice_ptr_index = 0; | 2712 | static const size_t slice_ptr_index = 0; |
| 2679 | static const size_t slice_len_index = 1; | 2713 | static const size_t slice_len_index = 1; |
| 2680 | 2714 |
src/analyze.cpp+140-111| ... | @@ -1366,119 +1366,140 @@ static void resolve_enum_type(CodeGen *g, TypeTableEntry *enum_type) { | ... | @@ -1366,119 +1366,140 @@ static void resolve_enum_type(CodeGen *g, TypeTableEntry *enum_type) { |
| 1366 | enum_type->data.enumeration.union_size_bytes = biggest_size_in_bits / 8; | 1366 | enum_type->data.enumeration.union_size_bytes = biggest_size_in_bits / 8; |
| 1367 | enum_type->data.enumeration.most_aligned_union_member = most_aligned_union_member; | 1367 | enum_type->data.enumeration.most_aligned_union_member = most_aligned_union_member; |
| 1368 | 1368 | ||
| 1369 | if (!enum_type->data.enumeration.is_invalid) { | 1369 | if (enum_type->data.enumeration.is_invalid) |
| 1370 | TypeTableEntry *tag_int_type = get_smallest_unsigned_int_type(g, field_count); | 1370 | return; |
| 1371 | TypeTableEntry *tag_type_entry = create_enum_tag_type(g, enum_type, tag_int_type); | ||
| 1372 | enum_type->data.enumeration.tag_type = tag_type_entry; | ||
| 1373 | |||
| 1374 | uint64_t align_of_tag_in_bits = 8*LLVMABIAlignmentOfType(g->target_data_ref, tag_int_type->type_ref); | ||
| 1375 | |||
| 1376 | if (most_aligned_union_member) { | ||
| 1377 | // create llvm type for union | ||
| 1378 | uint64_t padding_in_bits = biggest_size_in_bits - size_of_most_aligned_member_in_bits; | ||
| 1379 | LLVMTypeRef union_type_ref; | ||
| 1380 | if (padding_in_bits > 0) { | ||
| 1381 | TypeTableEntry *u8_type = get_int_type(g, false, 8); | ||
| 1382 | TypeTableEntry *padding_array = get_array_type(g, u8_type, padding_in_bits / 8); | ||
| 1383 | LLVMTypeRef union_element_types[] = { | ||
| 1384 | most_aligned_union_member->type_ref, | ||
| 1385 | padding_array->type_ref, | ||
| 1386 | }; | ||
| 1387 | union_type_ref = LLVMStructType(union_element_types, 2, false); | ||
| 1388 | } else { | ||
| 1389 | union_type_ref = most_aligned_union_member->type_ref; | ||
| 1390 | } | ||
| 1391 | enum_type->data.enumeration.union_type_ref = union_type_ref; | ||
| 1392 | 1371 | ||
| 1393 | assert(8*LLVMABIAlignmentOfType(g->target_data_ref, union_type_ref) >= biggest_align_in_bits); | 1372 | if (enum_type->zero_bits) { |
| 1394 | assert(8*LLVMStoreSizeOfType(g->target_data_ref, union_type_ref) >= biggest_size_in_bits); | 1373 | enum_type->type_ref = LLVMVoidType(); |
| 1395 | 1374 | ||
| 1396 | if (align_of_tag_in_bits >= biggest_align_in_bits) { | 1375 | uint64_t debug_size_in_bits = 0; |
| 1397 | enum_type->data.enumeration.gen_tag_index = 0; | 1376 | uint64_t debug_align_in_bits = 0; |
| 1398 | enum_type->data.enumeration.gen_union_index = 1; | 1377 | ZigLLVMDIType **di_root_members = nullptr; |
| 1399 | } else { | 1378 | size_t debug_member_count = 0; |
| 1400 | enum_type->data.enumeration.gen_union_index = 0; | 1379 | ZigLLVMDIType *replacement_di_type = ZigLLVMCreateDebugStructType(g->dbuilder, |
| 1401 | enum_type->data.enumeration.gen_tag_index = 1; | 1380 | ZigLLVMFileToScope(import->di_file), |
| 1402 | } | 1381 | buf_ptr(&enum_type->name), |
| 1382 | import->di_file, (unsigned)(decl_node->line + 1), | ||
| 1383 | debug_size_in_bits, | ||
| 1384 | debug_align_in_bits, | ||
| 1385 | 0, nullptr, di_root_members, (int)debug_member_count, 0, nullptr, ""); | ||
| 1403 | 1386 | ||
| 1404 | // create llvm type for root struct | 1387 | ZigLLVMReplaceTemporary(g->dbuilder, enum_type->di_type, replacement_di_type); |
| 1405 | LLVMTypeRef root_struct_element_types[2]; | 1388 | enum_type->di_type = replacement_di_type; |
| 1406 | root_struct_element_types[enum_type->data.enumeration.gen_tag_index] = tag_type_entry->type_ref; | 1389 | return; |
| 1407 | root_struct_element_types[enum_type->data.enumeration.gen_union_index] = union_type_ref; | 1390 | } |
| 1408 | LLVMStructSetBody(enum_type->type_ref, root_struct_element_types, 2, false); | 1391 | |
| 1409 | 1392 | TypeTableEntry *tag_int_type = get_smallest_unsigned_int_type(g, field_count); | |
| 1410 | // create debug type for tag | 1393 | TypeTableEntry *tag_type_entry = create_enum_tag_type(g, enum_type, tag_int_type); |
| 1411 | uint64_t tag_debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, tag_type_entry->type_ref); | 1394 | enum_type->data.enumeration.tag_type = tag_type_entry; |
| 1412 | uint64_t tag_debug_align_in_bits = 8*LLVMABIAlignmentOfType(g->target_data_ref, tag_type_entry->type_ref); | 1395 | |
| 1413 | ZigLLVMDIType *tag_di_type = ZigLLVMCreateDebugEnumerationType(g->dbuilder, | 1396 | uint64_t align_of_tag_in_bits = 8*LLVMABIAlignmentOfType(g->target_data_ref, tag_int_type->type_ref); |
| 1414 | ZigLLVMTypeToScope(enum_type->di_type), "AnonEnum", | 1397 | |
| 1415 | import->di_file, (unsigned)(decl_node->line + 1), | 1398 | if (most_aligned_union_member) { |
| 1416 | tag_debug_size_in_bits, tag_debug_align_in_bits, di_enumerators, field_count, | 1399 | // create llvm type for union |
| 1417 | tag_type_entry->di_type, ""); | 1400 | uint64_t padding_in_bits = biggest_size_in_bits - size_of_most_aligned_member_in_bits; |
| 1418 | 1401 | LLVMTypeRef union_type_ref; | |
| 1419 | // create debug type for union | 1402 | if (padding_in_bits > 0) { |
| 1420 | ZigLLVMDIType *union_di_type = ZigLLVMCreateDebugUnionType(g->dbuilder, | 1403 | TypeTableEntry *u8_type = get_int_type(g, false, 8); |
| 1421 | ZigLLVMTypeToScope(enum_type->di_type), "AnonUnion", | 1404 | TypeTableEntry *padding_array = get_array_type(g, u8_type, padding_in_bits / 8); |
| 1422 | import->di_file, (unsigned)(decl_node->line + 1), | 1405 | LLVMTypeRef union_element_types[] = { |
| 1423 | biggest_size_in_bits, biggest_align_in_bits, 0, union_inner_di_types, | 1406 | most_aligned_union_member->type_ref, |
| 1424 | gen_field_count, 0, ""); | 1407 | padding_array->type_ref, |
| 1425 | 1408 | }; | |
| 1426 | // create debug types for members of root struct | 1409 | union_type_ref = LLVMStructType(union_element_types, 2, false); |
| 1427 | uint64_t tag_offset_in_bits = 8*LLVMOffsetOfElement(g->target_data_ref, enum_type->type_ref, | ||
| 1428 | enum_type->data.enumeration.gen_tag_index); | ||
| 1429 | ZigLLVMDIType *tag_member_di_type = ZigLLVMCreateDebugMemberType(g->dbuilder, | ||
| 1430 | ZigLLVMTypeToScope(enum_type->di_type), "tag_field", | ||
| 1431 | import->di_file, (unsigned)(decl_node->line + 1), | ||
| 1432 | tag_debug_size_in_bits, | ||
| 1433 | tag_debug_align_in_bits, | ||
| 1434 | tag_offset_in_bits, | ||
| 1435 | 0, tag_di_type); | ||
| 1436 | |||
| 1437 | uint64_t union_offset_in_bits = 8*LLVMOffsetOfElement(g->target_data_ref, enum_type->type_ref, | ||
| 1438 | enum_type->data.enumeration.gen_union_index); | ||
| 1439 | ZigLLVMDIType *union_member_di_type = ZigLLVMCreateDebugMemberType(g->dbuilder, | ||
| 1440 | ZigLLVMTypeToScope(enum_type->di_type), "union_field", | ||
| 1441 | import->di_file, (unsigned)(decl_node->line + 1), | ||
| 1442 | biggest_size_in_bits, | ||
| 1443 | biggest_align_in_bits, | ||
| 1444 | union_offset_in_bits, | ||
| 1445 | 0, union_di_type); | ||
| 1446 | |||
| 1447 | // create debug type for root struct | ||
| 1448 | ZigLLVMDIType *di_root_members[2]; | ||
| 1449 | di_root_members[enum_type->data.enumeration.gen_tag_index] = tag_member_di_type; | ||
| 1450 | di_root_members[enum_type->data.enumeration.gen_union_index] = union_member_di_type; | ||
| 1451 | |||
| 1452 | uint64_t debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, enum_type->type_ref); | ||
| 1453 | uint64_t debug_align_in_bits = 8*LLVMABISizeOfType(g->target_data_ref, enum_type->type_ref); | ||
| 1454 | ZigLLVMDIType *replacement_di_type = ZigLLVMCreateDebugStructType(g->dbuilder, | ||
| 1455 | ZigLLVMFileToScope(import->di_file), | ||
| 1456 | buf_ptr(&enum_type->name), | ||
| 1457 | import->di_file, (unsigned)(decl_node->line + 1), | ||
| 1458 | debug_size_in_bits, | ||
| 1459 | debug_align_in_bits, | ||
| 1460 | 0, nullptr, di_root_members, 2, 0, nullptr, ""); | ||
| 1461 | |||
| 1462 | ZigLLVMReplaceTemporary(g->dbuilder, enum_type->di_type, replacement_di_type); | ||
| 1463 | enum_type->di_type = replacement_di_type; | ||
| 1464 | } else { | 1410 | } else { |
| 1465 | // create llvm type for root struct | 1411 | union_type_ref = most_aligned_union_member->type_ref; |
| 1466 | enum_type->type_ref = tag_type_entry->type_ref; | 1412 | } |
| 1467 | 1413 | enum_type->data.enumeration.union_type_ref = union_type_ref; | |
| 1468 | // create debug type for tag | 1414 | |
| 1469 | uint64_t tag_debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, tag_type_entry->type_ref); | 1415 | assert(8*LLVMABIAlignmentOfType(g->target_data_ref, union_type_ref) >= biggest_align_in_bits); |
| 1470 | uint64_t tag_debug_align_in_bits = 8*LLVMABIAlignmentOfType(g->target_data_ref, tag_type_entry->type_ref); | 1416 | assert(8*LLVMStoreSizeOfType(g->target_data_ref, union_type_ref) >= biggest_size_in_bits); |
| 1471 | ZigLLVMDIType *tag_di_type = ZigLLVMCreateDebugEnumerationType(g->dbuilder, | ||
| 1472 | ZigLLVMFileToScope(import->di_file), buf_ptr(&enum_type->name), | ||
| 1473 | import->di_file, (unsigned)(decl_node->line + 1), | ||
| 1474 | tag_debug_size_in_bits, | ||
| 1475 | tag_debug_align_in_bits, | ||
| 1476 | di_enumerators, field_count, | ||
| 1477 | tag_type_entry->di_type, ""); | ||
| 1478 | 1417 | ||
| 1479 | ZigLLVMReplaceTemporary(g->dbuilder, enum_type->di_type, tag_di_type); | 1418 | if (align_of_tag_in_bits >= biggest_align_in_bits) { |
| 1480 | enum_type->di_type = tag_di_type; | 1419 | enum_type->data.enumeration.gen_tag_index = 0; |
| 1420 | enum_type->data.enumeration.gen_union_index = 1; | ||
| 1421 | } else { | ||
| 1422 | enum_type->data.enumeration.gen_union_index = 0; | ||
| 1423 | enum_type->data.enumeration.gen_tag_index = 1; | ||
| 1481 | } | 1424 | } |
| 1425 | |||
| 1426 | // create llvm type for root struct | ||
| 1427 | LLVMTypeRef root_struct_element_types[2]; | ||
| 1428 | root_struct_element_types[enum_type->data.enumeration.gen_tag_index] = tag_type_entry->type_ref; | ||
| 1429 | root_struct_element_types[enum_type->data.enumeration.gen_union_index] = union_type_ref; | ||
| 1430 | LLVMStructSetBody(enum_type->type_ref, root_struct_element_types, 2, false); | ||
| 1431 | |||
| 1432 | // create debug type for tag | ||
| 1433 | uint64_t tag_debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, tag_type_entry->type_ref); | ||
| 1434 | uint64_t tag_debug_align_in_bits = 8*LLVMABIAlignmentOfType(g->target_data_ref, tag_type_entry->type_ref); | ||
| 1435 | ZigLLVMDIType *tag_di_type = ZigLLVMCreateDebugEnumerationType(g->dbuilder, | ||
| 1436 | ZigLLVMTypeToScope(enum_type->di_type), "AnonEnum", | ||
| 1437 | import->di_file, (unsigned)(decl_node->line + 1), | ||
| 1438 | tag_debug_size_in_bits, tag_debug_align_in_bits, di_enumerators, field_count, | ||
| 1439 | tag_type_entry->di_type, ""); | ||
| 1440 | |||
| 1441 | // create debug type for union | ||
| 1442 | ZigLLVMDIType *union_di_type = ZigLLVMCreateDebugUnionType(g->dbuilder, | ||
| 1443 | ZigLLVMTypeToScope(enum_type->di_type), "AnonUnion", | ||
| 1444 | import->di_file, (unsigned)(decl_node->line + 1), | ||
| 1445 | biggest_size_in_bits, biggest_align_in_bits, 0, union_inner_di_types, | ||
| 1446 | gen_field_count, 0, ""); | ||
| 1447 | |||
| 1448 | // create debug types for members of root struct | ||
| 1449 | uint64_t tag_offset_in_bits = 8*LLVMOffsetOfElement(g->target_data_ref, enum_type->type_ref, | ||
| 1450 | enum_type->data.enumeration.gen_tag_index); | ||
| 1451 | ZigLLVMDIType *tag_member_di_type = ZigLLVMCreateDebugMemberType(g->dbuilder, | ||
| 1452 | ZigLLVMTypeToScope(enum_type->di_type), "tag_field", | ||
| 1453 | import->di_file, (unsigned)(decl_node->line + 1), | ||
| 1454 | tag_debug_size_in_bits, | ||
| 1455 | tag_debug_align_in_bits, | ||
| 1456 | tag_offset_in_bits, | ||
| 1457 | 0, tag_di_type); | ||
| 1458 | |||
| 1459 | uint64_t union_offset_in_bits = 8*LLVMOffsetOfElement(g->target_data_ref, enum_type->type_ref, | ||
| 1460 | enum_type->data.enumeration.gen_union_index); | ||
| 1461 | ZigLLVMDIType *union_member_di_type = ZigLLVMCreateDebugMemberType(g->dbuilder, | ||
| 1462 | ZigLLVMTypeToScope(enum_type->di_type), "union_field", | ||
| 1463 | import->di_file, (unsigned)(decl_node->line + 1), | ||
| 1464 | biggest_size_in_bits, | ||
| 1465 | biggest_align_in_bits, | ||
| 1466 | union_offset_in_bits, | ||
| 1467 | 0, union_di_type); | ||
| 1468 | |||
| 1469 | // create debug type for root struct | ||
| 1470 | ZigLLVMDIType *di_root_members[2]; | ||
| 1471 | di_root_members[enum_type->data.enumeration.gen_tag_index] = tag_member_di_type; | ||
| 1472 | di_root_members[enum_type->data.enumeration.gen_union_index] = union_member_di_type; | ||
| 1473 | |||
| 1474 | uint64_t debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, enum_type->type_ref); | ||
| 1475 | uint64_t debug_align_in_bits = 8*LLVMABISizeOfType(g->target_data_ref, enum_type->type_ref); | ||
| 1476 | ZigLLVMDIType *replacement_di_type = ZigLLVMCreateDebugStructType(g->dbuilder, | ||
| 1477 | ZigLLVMFileToScope(import->di_file), | ||
| 1478 | buf_ptr(&enum_type->name), | ||
| 1479 | import->di_file, (unsigned)(decl_node->line + 1), | ||
| 1480 | debug_size_in_bits, | ||
| 1481 | debug_align_in_bits, | ||
| 1482 | 0, nullptr, di_root_members, 2, 0, nullptr, ""); | ||
| 1483 | |||
| 1484 | ZigLLVMReplaceTemporary(g->dbuilder, enum_type->di_type, replacement_di_type); | ||
| 1485 | enum_type->di_type = replacement_di_type; | ||
| 1486 | } else { | ||
| 1487 | // create llvm type for root struct | ||
| 1488 | enum_type->type_ref = tag_type_entry->type_ref; | ||
| 1489 | |||
| 1490 | // create debug type for tag | ||
| 1491 | uint64_t tag_debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, tag_type_entry->type_ref); | ||
| 1492 | uint64_t tag_debug_align_in_bits = 8*LLVMABIAlignmentOfType(g->target_data_ref, tag_type_entry->type_ref); | ||
| 1493 | ZigLLVMDIType *tag_di_type = ZigLLVMCreateDebugEnumerationType(g->dbuilder, | ||
| 1494 | ZigLLVMFileToScope(import->di_file), buf_ptr(&enum_type->name), | ||
| 1495 | import->di_file, (unsigned)(decl_node->line + 1), | ||
| 1496 | tag_debug_size_in_bits, | ||
| 1497 | tag_debug_align_in_bits, | ||
| 1498 | di_enumerators, field_count, | ||
| 1499 | tag_type_entry->di_type, ""); | ||
| 1500 | |||
| 1501 | ZigLLVMReplaceTemporary(g->dbuilder, enum_type->di_type, tag_di_type); | ||
| 1502 | enum_type->di_type = tag_di_type; | ||
| 1482 | } | 1503 | } |
| 1483 | } | 1504 | } |
| 1484 | 1505 | ||
| ... | @@ -1875,9 +1896,11 @@ static void resolve_enum_zero_bits(CodeGen *g, TypeTableEntry *enum_type) { | ... | @@ -1875,9 +1896,11 @@ static void resolve_enum_zero_bits(CodeGen *g, TypeTableEntry *enum_type) { |
| 1875 | enum_type->data.enumeration.zero_bits_known = true; | 1896 | enum_type->data.enumeration.zero_bits_known = true; |
| 1876 | 1897 | ||
| 1877 | // also compute abi_alignment | 1898 | // also compute abi_alignment |
| 1878 | TypeTableEntry *tag_int_type = get_smallest_unsigned_int_type(g, field_count); | 1899 | if (!enum_type->zero_bits) { |
| 1879 | uint32_t align_of_tag_in_bytes = LLVMABIAlignmentOfType(g->target_data_ref, tag_int_type->type_ref); | 1900 | TypeTableEntry *tag_int_type = get_smallest_unsigned_int_type(g, field_count); |
| 1880 | enum_type->data.enumeration.abi_alignment = max(align_of_tag_in_bytes, biggest_align_bytes); | 1901 | uint32_t align_of_tag_in_bytes = LLVMABIAlignmentOfType(g->target_data_ref, tag_int_type->type_ref); |
| 1902 | enum_type->data.enumeration.abi_alignment = max(align_of_tag_in_bytes, biggest_align_bytes); | ||
| 1903 | } | ||
| 1881 | } | 1904 | } |
| 1882 | 1905 | ||
| 1883 | static void resolve_struct_zero_bits(CodeGen *g, TypeTableEntry *struct_type) { | 1906 | static void resolve_struct_zero_bits(CodeGen *g, TypeTableEntry *struct_type) { |
| ... | @@ -3440,8 +3463,14 @@ void find_libc_lib_path(CodeGen *g) { | ... | @@ -3440,8 +3463,14 @@ void find_libc_lib_path(CodeGen *g) { |
| 3440 | zig_panic("Unable to determine libc lib path."); | 3463 | zig_panic("Unable to determine libc lib path."); |
| 3441 | } | 3464 | } |
| 3442 | } | 3465 | } |
| 3466 | |||
| 3443 | if (!g->libc_static_lib_dir || buf_len(g->libc_static_lib_dir) == 0) { | 3467 | if (!g->libc_static_lib_dir || buf_len(g->libc_static_lib_dir) == 0) { |
| 3444 | zig_panic("Unable to determine libc static lib path."); | 3468 | if ((g->zig_target.os == ZigLLVM_Win32) && (g->msvc_lib_dir != NULL)) { |
| 3469 | return; | ||
| 3470 | } | ||
| 3471 | else { | ||
| 3472 | zig_panic("Unable to determine libc static lib path."); | ||
| 3473 | } | ||
| 3445 | } | 3474 | } |
| 3446 | } | 3475 | } |
| 3447 | 3476 |
src/c_tokenizer.cpp+4-1| ... | @@ -91,6 +91,9 @@ | ... | @@ -91,6 +91,9 @@ |
| 91 | IDENT_START: \ | 91 | IDENT_START: \ |
| 92 | case DIGIT | 92 | case DIGIT |
| 93 | 93 | ||
| 94 | #define LINE_ENDING \ | ||
| 95 | '\r': \ | ||
| 96 | case '\n' | ||
| 94 | 97 | ||
| 95 | static void begin_token(CTokenize *ctok, CTokId id) { | 98 | static void begin_token(CTokenize *ctok, CTokId id) { |
| 96 | assert(ctok->cur_tok == nullptr); | 99 | assert(ctok->cur_tok == nullptr); |
| ... | @@ -191,7 +194,7 @@ void tokenize_c_macro(CTokenize *ctok, const uint8_t *c) { | ... | @@ -191,7 +194,7 @@ void tokenize_c_macro(CTokenize *ctok, const uint8_t *c) { |
| 191 | case '\\': | 194 | case '\\': |
| 192 | ctok->state = CTokStateBackslash; | 195 | ctok->state = CTokStateBackslash; |
| 193 | break; | 196 | break; |
| 194 | case '\n': | 197 | case LINE_ENDING: |
| 195 | goto found_end_of_macro; | 198 | goto found_end_of_macro; |
| 196 | case IDENT_START: | 199 | case IDENT_START: |
| 197 | ctok->state = CTokStateIdentifier; | 200 | ctok->state = CTokStateIdentifier; |
src/codegen.cpp+67-11| ... | @@ -189,6 +189,10 @@ void codegen_set_is_test(CodeGen *g, bool is_test_build) { | ... | @@ -189,6 +189,10 @@ void codegen_set_is_test(CodeGen *g, bool is_test_build) { |
| 189 | g->is_test_build = is_test_build; | 189 | g->is_test_build = is_test_build; |
| 190 | } | 190 | } |
| 191 | 191 | ||
| 192 | void codegen_set_emit_file_type(CodeGen *g, EmitFileType emit_file_type) { | ||
| 193 | g->emit_file_type = emit_file_type; | ||
| 194 | } | ||
| 195 | |||
| 192 | void codegen_set_is_static(CodeGen *g, bool is_static) { | 196 | void codegen_set_is_static(CodeGen *g, bool is_static) { |
| 193 | g->is_static = is_static; | 197 | g->is_static = is_static; |
| 194 | } | 198 | } |
| ... | @@ -3380,6 +3384,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable, | ... | @@ -3380,6 +3384,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable, |
| 3380 | case IrInstructionIdEmbedFile: | 3384 | case IrInstructionIdEmbedFile: |
| 3381 | case IrInstructionIdIntType: | 3385 | case IrInstructionIdIntType: |
| 3382 | case IrInstructionIdMemberCount: | 3386 | case IrInstructionIdMemberCount: |
| 3387 | case IrInstructionIdMemberType: | ||
| 3388 | case IrInstructionIdMemberName: | ||
| 3383 | case IrInstructionIdAlignOf: | 3389 | case IrInstructionIdAlignOf: |
| 3384 | case IrInstructionIdFnProto: | 3390 | case IrInstructionIdFnProto: |
| 3385 | case IrInstructionIdTestComptime: | 3391 | case IrInstructionIdTestComptime: |
| ... | @@ -3397,6 +3403,7 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable, | ... | @@ -3397,6 +3403,7 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable, |
| 3397 | case IrInstructionIdPtrTypeOf: | 3403 | case IrInstructionIdPtrTypeOf: |
| 3398 | case IrInstructionIdOpaqueType: | 3404 | case IrInstructionIdOpaqueType: |
| 3399 | case IrInstructionIdSetAlignStack: | 3405 | case IrInstructionIdSetAlignStack: |
| 3406 | case IrInstructionIdArgType: | ||
| 3400 | zig_unreachable(); | 3407 | zig_unreachable(); |
| 3401 | case IrInstructionIdReturn: | 3408 | case IrInstructionIdReturn: |
| 3402 | return ir_render_return(g, executable, (IrInstructionReturn *)instruction); | 3409 | return ir_render_return(g, executable, (IrInstructionReturn *)instruction); |
| ... | @@ -4493,24 +4500,70 @@ static void do_code_gen(CodeGen *g) { | ... | @@ -4493,24 +4500,70 @@ static void do_code_gen(CodeGen *g) { |
| 4493 | LLVMVerifyModule(g->module, LLVMAbortProcessAction, &error); | 4500 | LLVMVerifyModule(g->module, LLVMAbortProcessAction, &error); |
| 4494 | #endif | 4501 | #endif |
| 4495 | 4502 | ||
| 4496 | codegen_add_time_event(g, "LLVM Emit Object"); | 4503 | codegen_add_time_event(g, "LLVM Emit Output"); |
| 4497 | 4504 | ||
| 4498 | char *err_msg = nullptr; | 4505 | char *err_msg = nullptr; |
| 4499 | Buf *o_basename = buf_create_from_buf(g->root_out_name); | 4506 | Buf *o_basename = buf_create_from_buf(g->root_out_name); |
| 4500 | const char *o_ext = target_o_file_ext(&g->zig_target); | 4507 | |
| 4501 | buf_append_str(o_basename, o_ext); | 4508 | switch (g->emit_file_type) { |
| 4509 | case EmitFileTypeBinary: | ||
| 4510 | { | ||
| 4511 | const char *o_ext = target_o_file_ext(&g->zig_target); | ||
| 4512 | buf_append_str(o_basename, o_ext); | ||
| 4513 | break; | ||
| 4514 | } | ||
| 4515 | case EmitFileTypeAssembly: | ||
| 4516 | { | ||
| 4517 | const char *asm_ext = target_asm_file_ext(&g->zig_target); | ||
| 4518 | buf_append_str(o_basename, asm_ext); | ||
| 4519 | break; | ||
| 4520 | } | ||
| 4521 | case EmitFileTypeLLVMIr: | ||
| 4522 | { | ||
| 4523 | const char *llvm_ir_ext = target_llvm_ir_file_ext(&g->zig_target); | ||
| 4524 | buf_append_str(o_basename, llvm_ir_ext); | ||
| 4525 | break; | ||
| 4526 | } | ||
| 4527 | default: | ||
| 4528 | zig_unreachable(); | ||
| 4529 | } | ||
| 4530 | |||
| 4502 | Buf *output_path = buf_alloc(); | 4531 | Buf *output_path = buf_alloc(); |
| 4503 | os_path_join(g->cache_dir, o_basename, output_path); | 4532 | os_path_join(g->cache_dir, o_basename, output_path); |
| 4504 | ensure_cache_dir(g); | 4533 | ensure_cache_dir(g); |
| 4505 | if (ZigLLVMTargetMachineEmitToFile(g->target_machine, g->module, buf_ptr(output_path), | ||
| 4506 | LLVMObjectFile, &err_msg, g->build_mode == BuildModeDebug)) | ||
| 4507 | { | ||
| 4508 | zig_panic("unable to write object file %s: %s", buf_ptr(output_path), err_msg); | ||
| 4509 | } | ||
| 4510 | 4534 | ||
| 4511 | validate_inline_fns(g); | 4535 | switch (g->emit_file_type) { |
| 4536 | case EmitFileTypeBinary: | ||
| 4537 | if (ZigLLVMTargetMachineEmitToFile(g->target_machine, g->module, buf_ptr(output_path), | ||
| 4538 | ZigLLVM_EmitBinary, &err_msg, g->build_mode == BuildModeDebug)) | ||
| 4539 | { | ||
| 4540 | zig_panic("unable to write object file %s: %s", buf_ptr(output_path), err_msg); | ||
| 4541 | } | ||
| 4542 | validate_inline_fns(g); | ||
| 4543 | g->link_objects.append(output_path); | ||
| 4544 | break; | ||
| 4545 | |||
| 4546 | case EmitFileTypeAssembly: | ||
| 4547 | if (ZigLLVMTargetMachineEmitToFile(g->target_machine, g->module, buf_ptr(output_path), | ||
| 4548 | ZigLLVM_EmitAssembly, &err_msg, g->build_mode == BuildModeDebug)) | ||
| 4549 | { | ||
| 4550 | zig_panic("unable to write assembly file %s: %s", buf_ptr(output_path), err_msg); | ||
| 4551 | } | ||
| 4552 | validate_inline_fns(g); | ||
| 4553 | break; | ||
| 4554 | |||
| 4555 | case EmitFileTypeLLVMIr: | ||
| 4556 | if (ZigLLVMTargetMachineEmitToFile(g->target_machine, g->module, buf_ptr(output_path), | ||
| 4557 | ZigLLVM_EmitLLVMIr, &err_msg, g->build_mode == BuildModeDebug)) | ||
| 4558 | { | ||
| 4559 | zig_panic("unable to write llvm-ir file %s: %s", buf_ptr(output_path), err_msg); | ||
| 4560 | } | ||
| 4561 | validate_inline_fns(g); | ||
| 4562 | break; | ||
| 4512 | 4563 | ||
| 4513 | g->link_objects.append(output_path); | 4564 | default: |
| 4565 | zig_unreachable(); | ||
| 4566 | } | ||
| 4514 | } | 4567 | } |
| 4515 | 4568 | ||
| 4516 | static const uint8_t int_sizes_in_bits[] = { | 4569 | static const uint8_t int_sizes_in_bits[] = { |
| ... | @@ -4816,7 +4869,9 @@ static void define_builtin_fns(CodeGen *g) { | ... | @@ -4816,7 +4869,9 @@ static void define_builtin_fns(CodeGen *g) { |
| 4816 | create_builtin_fn(g, BuiltinFnIdMaxValue, "maxValue", 1); | 4869 | create_builtin_fn(g, BuiltinFnIdMaxValue, "maxValue", 1); |
| 4817 | create_builtin_fn(g, BuiltinFnIdMinValue, "minValue", 1); | 4870 | create_builtin_fn(g, BuiltinFnIdMinValue, "minValue", 1); |
| 4818 | create_builtin_fn(g, BuiltinFnIdMemberCount, "memberCount", 1); | 4871 | create_builtin_fn(g, BuiltinFnIdMemberCount, "memberCount", 1); |
| 4819 | create_builtin_fn(g, BuiltinFnIdTypeof, "typeOf", 1); | 4872 | create_builtin_fn(g, BuiltinFnIdMemberType, "memberType", 2); |
| 4873 | create_builtin_fn(g, BuiltinFnIdMemberName, "memberName", 2); | ||
| 4874 | create_builtin_fn(g, BuiltinFnIdTypeof, "typeOf", 1); // TODO rename to TypeOf | ||
| 4820 | create_builtin_fn(g, BuiltinFnIdAddWithOverflow, "addWithOverflow", 4); | 4875 | create_builtin_fn(g, BuiltinFnIdAddWithOverflow, "addWithOverflow", 4); |
| 4821 | create_builtin_fn(g, BuiltinFnIdSubWithOverflow, "subWithOverflow", 4); | 4876 | create_builtin_fn(g, BuiltinFnIdSubWithOverflow, "subWithOverflow", 4); |
| 4822 | create_builtin_fn(g, BuiltinFnIdMulWithOverflow, "mulWithOverflow", 4); | 4877 | create_builtin_fn(g, BuiltinFnIdMulWithOverflow, "mulWithOverflow", 4); |
| ... | @@ -4863,6 +4918,7 @@ static void define_builtin_fns(CodeGen *g) { | ... | @@ -4863,6 +4918,7 @@ static void define_builtin_fns(CodeGen *g) { |
| 4863 | create_builtin_fn(g, BuiltinFnIdAlignCast, "alignCast", 2); | 4918 | create_builtin_fn(g, BuiltinFnIdAlignCast, "alignCast", 2); |
| 4864 | create_builtin_fn(g, BuiltinFnIdOpaqueType, "OpaqueType", 0); | 4919 | create_builtin_fn(g, BuiltinFnIdOpaqueType, "OpaqueType", 0); |
| 4865 | create_builtin_fn(g, BuiltinFnIdSetAlignStack, "setAlignStack", 1); | 4920 | create_builtin_fn(g, BuiltinFnIdSetAlignStack, "setAlignStack", 1); |
| 4921 | create_builtin_fn(g, BuiltinFnIdArgType, "ArgType", 2); | ||
| 4866 | } | 4922 | } |
| 4867 | 4923 | ||
| 4868 | static const char *bool_to_str(bool b) { | 4924 | static const char *bool_to_str(bool b) { |
src/codegen.hpp+1| ... | @@ -23,6 +23,7 @@ void codegen_set_llvm_argv(CodeGen *codegen, const char **args, size_t len); | ... | @@ -23,6 +23,7 @@ void codegen_set_llvm_argv(CodeGen *codegen, const char **args, size_t len); |
| 23 | void codegen_set_is_test(CodeGen *codegen, bool is_test); | 23 | void codegen_set_is_test(CodeGen *codegen, bool is_test); |
| 24 | void codegen_set_each_lib_rpath(CodeGen *codegen, bool each_lib_rpath); | 24 | void codegen_set_each_lib_rpath(CodeGen *codegen, bool each_lib_rpath); |
| 25 | 25 | ||
| 26 | void codegen_set_emit_file_type(CodeGen *g, EmitFileType emit_file_type); | ||
| 26 | void codegen_set_is_static(CodeGen *codegen, bool is_static); | 27 | void codegen_set_is_static(CodeGen *codegen, bool is_static); |
| 27 | void codegen_set_strip(CodeGen *codegen, bool strip); | 28 | void codegen_set_strip(CodeGen *codegen, bool strip); |
| 28 | void codegen_set_errmsg_color(CodeGen *codegen, ErrColor err_color); | 29 | void codegen_set_errmsg_color(CodeGen *codegen, ErrColor err_color); |
src/ir.cpp+303| ... | @@ -411,6 +411,14 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionMemberCount *) { | ... | @@ -411,6 +411,14 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionMemberCount *) { |
| 411 | return IrInstructionIdMemberCount; | 411 | return IrInstructionIdMemberCount; |
| 412 | } | 412 | } |
| 413 | 413 | ||
| 414 | static constexpr IrInstructionId ir_instruction_id(IrInstructionMemberType *) { | ||
| 415 | return IrInstructionIdMemberType; | ||
| 416 | } | ||
| 417 | |||
| 418 | static constexpr IrInstructionId ir_instruction_id(IrInstructionMemberName *) { | ||
| 419 | return IrInstructionIdMemberName; | ||
| 420 | } | ||
| 421 | |||
| 414 | static constexpr IrInstructionId ir_instruction_id(IrInstructionBreakpoint *) { | 422 | static constexpr IrInstructionId ir_instruction_id(IrInstructionBreakpoint *) { |
| 415 | return IrInstructionIdBreakpoint; | 423 | return IrInstructionIdBreakpoint; |
| 416 | } | 424 | } |
| ... | @@ -567,6 +575,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionSetAlignStack *) | ... | @@ -567,6 +575,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionSetAlignStack *) |
| 567 | return IrInstructionIdSetAlignStack; | 575 | return IrInstructionIdSetAlignStack; |
| 568 | } | 576 | } |
| 569 | 577 | ||
| 578 | static constexpr IrInstructionId ir_instruction_id(IrInstructionArgType *) { | ||
| 579 | return IrInstructionIdArgType; | ||
| 580 | } | ||
| 581 | |||
| 570 | template<typename T> | 582 | template<typename T> |
| 571 | static T *ir_create_instruction(IrBuilder *irb, Scope *scope, AstNode *source_node) { | 583 | static T *ir_create_instruction(IrBuilder *irb, Scope *scope, AstNode *source_node) { |
| 572 | T *special_instruction = allocate<T>(1); | 584 | T *special_instruction = allocate<T>(1); |
| ... | @@ -1779,6 +1791,32 @@ static IrInstruction *ir_build_member_count(IrBuilder *irb, Scope *scope, AstNod | ... | @@ -1779,6 +1791,32 @@ static IrInstruction *ir_build_member_count(IrBuilder *irb, Scope *scope, AstNod |
| 1779 | return &instruction->base; | 1791 | return &instruction->base; |
| 1780 | } | 1792 | } |
| 1781 | 1793 | ||
| 1794 | static IrInstruction *ir_build_member_type(IrBuilder *irb, Scope *scope, AstNode *source_node, | ||
| 1795 | IrInstruction *container_type, IrInstruction *member_index) | ||
| 1796 | { | ||
| 1797 | IrInstructionMemberType *instruction = ir_build_instruction<IrInstructionMemberType>(irb, scope, source_node); | ||
| 1798 | instruction->container_type = container_type; | ||
| 1799 | instruction->member_index = member_index; | ||
| 1800 | |||
| 1801 | ir_ref_instruction(container_type, irb->current_basic_block); | ||
| 1802 | ir_ref_instruction(member_index, irb->current_basic_block); | ||
| 1803 | |||
| 1804 | return &instruction->base; | ||
| 1805 | } | ||
| 1806 | |||
| 1807 | static IrInstruction *ir_build_member_name(IrBuilder *irb, Scope *scope, AstNode *source_node, | ||
| 1808 | IrInstruction *container_type, IrInstruction *member_index) | ||
| 1809 | { | ||
| 1810 | IrInstructionMemberName *instruction = ir_build_instruction<IrInstructionMemberName>(irb, scope, source_node); | ||
| 1811 | instruction->container_type = container_type; | ||
| 1812 | instruction->member_index = member_index; | ||
| 1813 | |||
| 1814 | ir_ref_instruction(container_type, irb->current_basic_block); | ||
| 1815 | ir_ref_instruction(member_index, irb->current_basic_block); | ||
| 1816 | |||
| 1817 | return &instruction->base; | ||
| 1818 | } | ||
| 1819 | |||
| 1782 | static IrInstruction *ir_build_breakpoint(IrBuilder *irb, Scope *scope, AstNode *source_node) { | 1820 | static IrInstruction *ir_build_breakpoint(IrBuilder *irb, Scope *scope, AstNode *source_node) { |
| 1783 | IrInstructionBreakpoint *instruction = ir_build_instruction<IrInstructionBreakpoint>(irb, scope, source_node); | 1821 | IrInstructionBreakpoint *instruction = ir_build_instruction<IrInstructionBreakpoint>(irb, scope, source_node); |
| 1784 | return &instruction->base; | 1822 | return &instruction->base; |
| ... | @@ -2263,6 +2301,19 @@ static IrInstruction *ir_build_set_align_stack(IrBuilder *irb, Scope *scope, Ast | ... | @@ -2263,6 +2301,19 @@ static IrInstruction *ir_build_set_align_stack(IrBuilder *irb, Scope *scope, Ast |
| 2263 | return &instruction->base; | 2301 | return &instruction->base; |
| 2264 | } | 2302 | } |
| 2265 | 2303 | ||
| 2304 | static IrInstruction *ir_build_arg_type(IrBuilder *irb, Scope *scope, AstNode *source_node, | ||
| 2305 | IrInstruction *fn_type, IrInstruction *arg_index) | ||
| 2306 | { | ||
| 2307 | IrInstructionArgType *instruction = ir_build_instruction<IrInstructionArgType>(irb, scope, source_node); | ||
| 2308 | instruction->fn_type = fn_type; | ||
| 2309 | instruction->arg_index = arg_index; | ||
| 2310 | |||
| 2311 | ir_ref_instruction(fn_type, irb->current_basic_block); | ||
| 2312 | ir_ref_instruction(arg_index, irb->current_basic_block); | ||
| 2313 | |||
| 2314 | return &instruction->base; | ||
| 2315 | } | ||
| 2316 | |||
| 2266 | static IrInstruction *ir_instruction_br_get_dep(IrInstructionBr *instruction, size_t index) { | 2317 | static IrInstruction *ir_instruction_br_get_dep(IrInstructionBr *instruction, size_t index) { |
| 2267 | return nullptr; | 2318 | return nullptr; |
| 2268 | } | 2319 | } |
| ... | @@ -2710,6 +2761,22 @@ static IrInstruction *ir_instruction_membercount_get_dep(IrInstructionMemberCoun | ... | @@ -2710,6 +2761,22 @@ static IrInstruction *ir_instruction_membercount_get_dep(IrInstructionMemberCoun |
| 2710 | } | 2761 | } |
| 2711 | } | 2762 | } |
| 2712 | 2763 | ||
| 2764 | static IrInstruction *ir_instruction_membertype_get_dep(IrInstructionMemberType *instruction, size_t index) { | ||
| 2765 | switch (index) { | ||
| 2766 | case 0: return instruction->container_type; | ||
| 2767 | case 1: return instruction->member_index; | ||
| 2768 | default: return nullptr; | ||
| 2769 | } | ||
| 2770 | } | ||
| 2771 | |||
| 2772 | static IrInstruction *ir_instruction_membername_get_dep(IrInstructionMemberName *instruction, size_t index) { | ||
| 2773 | switch (index) { | ||
| 2774 | case 0: return instruction->container_type; | ||
| 2775 | case 1: return instruction->member_index; | ||
| 2776 | default: return nullptr; | ||
| 2777 | } | ||
| 2778 | } | ||
| 2779 | |||
| 2713 | static IrInstruction *ir_instruction_breakpoint_get_dep(IrInstructionBreakpoint *instruction, size_t index) { | 2780 | static IrInstruction *ir_instruction_breakpoint_get_dep(IrInstructionBreakpoint *instruction, size_t index) { |
| 2714 | return nullptr; | 2781 | return nullptr; |
| 2715 | } | 2782 | } |
| ... | @@ -2992,6 +3059,14 @@ static IrInstruction *ir_instruction_setalignstack_get_dep(IrInstructionSetAlign | ... | @@ -2992,6 +3059,14 @@ static IrInstruction *ir_instruction_setalignstack_get_dep(IrInstructionSetAlign |
| 2992 | } | 3059 | } |
| 2993 | } | 3060 | } |
| 2994 | 3061 | ||
| 3062 | static IrInstruction *ir_instruction_argtype_get_dep(IrInstructionArgType *instruction, size_t index) { | ||
| 3063 | switch (index) { | ||
| 3064 | case 0: return instruction->fn_type; | ||
| 3065 | case 1: return instruction->arg_index; | ||
| 3066 | default: return nullptr; | ||
| 3067 | } | ||
| 3068 | } | ||
| 3069 | |||
| 2995 | static IrInstruction *ir_instruction_get_dep(IrInstruction *instruction, size_t index) { | 3070 | static IrInstruction *ir_instruction_get_dep(IrInstruction *instruction, size_t index) { |
| 2996 | switch (instruction->id) { | 3071 | switch (instruction->id) { |
| 2997 | case IrInstructionIdInvalid: | 3072 | case IrInstructionIdInvalid: |
| ... | @@ -3118,6 +3193,10 @@ static IrInstruction *ir_instruction_get_dep(IrInstruction *instruction, size_t | ... | @@ -3118,6 +3193,10 @@ static IrInstruction *ir_instruction_get_dep(IrInstruction *instruction, size_t |
| 3118 | return ir_instruction_slice_get_dep((IrInstructionSlice *) instruction, index); | 3193 | return ir_instruction_slice_get_dep((IrInstructionSlice *) instruction, index); |
| 3119 | case IrInstructionIdMemberCount: | 3194 | case IrInstructionIdMemberCount: |
| 3120 | return ir_instruction_membercount_get_dep((IrInstructionMemberCount *) instruction, index); | 3195 | return ir_instruction_membercount_get_dep((IrInstructionMemberCount *) instruction, index); |
| 3196 | case IrInstructionIdMemberType: | ||
| 3197 | return ir_instruction_membertype_get_dep((IrInstructionMemberType *) instruction, index); | ||
| 3198 | case IrInstructionIdMemberName: | ||
| 3199 | return ir_instruction_membername_get_dep((IrInstructionMemberName *) instruction, index); | ||
| 3121 | case IrInstructionIdBreakpoint: | 3200 | case IrInstructionIdBreakpoint: |
| 3122 | return ir_instruction_breakpoint_get_dep((IrInstructionBreakpoint *) instruction, index); | 3201 | return ir_instruction_breakpoint_get_dep((IrInstructionBreakpoint *) instruction, index); |
| 3123 | case IrInstructionIdReturnAddress: | 3202 | case IrInstructionIdReturnAddress: |
| ... | @@ -3194,6 +3273,8 @@ static IrInstruction *ir_instruction_get_dep(IrInstruction *instruction, size_t | ... | @@ -3194,6 +3273,8 @@ static IrInstruction *ir_instruction_get_dep(IrInstruction *instruction, size_t |
| 3194 | return ir_instruction_opaquetype_get_dep((IrInstructionOpaqueType *) instruction, index); | 3273 | return ir_instruction_opaquetype_get_dep((IrInstructionOpaqueType *) instruction, index); |
| 3195 | case IrInstructionIdSetAlignStack: | 3274 | case IrInstructionIdSetAlignStack: |
| 3196 | return ir_instruction_setalignstack_get_dep((IrInstructionSetAlignStack *) instruction, index); | 3275 | return ir_instruction_setalignstack_get_dep((IrInstructionSetAlignStack *) instruction, index); |
| 3276 | case IrInstructionIdArgType: | ||
| 3277 | return ir_instruction_argtype_get_dep((IrInstructionArgType *) instruction, index); | ||
| 3197 | } | 3278 | } |
| 3198 | zig_unreachable(); | 3279 | zig_unreachable(); |
| 3199 | } | 3280 | } |
| ... | @@ -4352,6 +4433,36 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo | ... | @@ -4352,6 +4433,36 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo |
| 4352 | 4433 | ||
| 4353 | return ir_build_member_count(irb, scope, node, arg0_value); | 4434 | return ir_build_member_count(irb, scope, node, arg0_value); |
| 4354 | } | 4435 | } |
| 4436 | case BuiltinFnIdMemberType: | ||
| 4437 | { | ||
| 4438 | AstNode *arg0_node = node->data.fn_call_expr.params.at(0); | ||
| 4439 | IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope); | ||
| 4440 | if (arg0_value == irb->codegen->invalid_instruction) | ||
| 4441 | return arg0_value; | ||
| 4442 | |||
| 4443 | AstNode *arg1_node = node->data.fn_call_expr.params.at(1); | ||
| 4444 | IrInstruction *arg1_value = ir_gen_node(irb, arg1_node, scope); | ||
| 4445 | if (arg1_value == irb->codegen->invalid_instruction) | ||
| 4446 | return arg1_value; | ||
| 4447 | |||
| 4448 | |||
| 4449 | return ir_build_member_type(irb, scope, node, arg0_value, arg1_value); | ||
| 4450 | } | ||
| 4451 | case BuiltinFnIdMemberName: | ||
| 4452 | { | ||
| 4453 | AstNode *arg0_node = node->data.fn_call_expr.params.at(0); | ||
| 4454 | IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope); | ||
| 4455 | if (arg0_value == irb->codegen->invalid_instruction) | ||
| 4456 | return arg0_value; | ||
| 4457 | |||
| 4458 | AstNode *arg1_node = node->data.fn_call_expr.params.at(1); | ||
| 4459 | IrInstruction *arg1_value = ir_gen_node(irb, arg1_node, scope); | ||
| 4460 | if (arg1_value == irb->codegen->invalid_instruction) | ||
| 4461 | return arg1_value; | ||
| 4462 | |||
| 4463 | |||
| 4464 | return ir_build_member_name(irb, scope, node, arg0_value, arg1_value); | ||
| 4465 | } | ||
| 4355 | case BuiltinFnIdBreakpoint: | 4466 | case BuiltinFnIdBreakpoint: |
| 4356 | return ir_build_breakpoint(irb, scope, node); | 4467 | return ir_build_breakpoint(irb, scope, node); |
| 4357 | case BuiltinFnIdReturnAddress: | 4468 | case BuiltinFnIdReturnAddress: |
| ... | @@ -4629,6 +4740,20 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo | ... | @@ -4629,6 +4740,20 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo |
| 4629 | 4740 | ||
| 4630 | return ir_build_set_align_stack(irb, scope, node, arg0_value); | 4741 | return ir_build_set_align_stack(irb, scope, node, arg0_value); |
| 4631 | } | 4742 | } |
| 4743 | case BuiltinFnIdArgType: | ||
| 4744 | { | ||
| 4745 | AstNode *arg0_node = node->data.fn_call_expr.params.at(0); | ||
| 4746 | IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope); | ||
| 4747 | if (arg0_value == irb->codegen->invalid_instruction) | ||
| 4748 | return arg0_value; | ||
| 4749 | |||
| 4750 | AstNode *arg1_node = node->data.fn_call_expr.params.at(1); | ||
| 4751 | IrInstruction *arg1_value = ir_gen_node(irb, arg1_node, scope); | ||
| 4752 | if (arg1_value == irb->codegen->invalid_instruction) | ||
| 4753 | return arg1_value; | ||
| 4754 | |||
| 4755 | return ir_build_arg_type(irb, scope, node, arg0_value, arg1_value); | ||
| 4756 | } | ||
| 4632 | } | 4757 | } |
| 4633 | zig_unreachable(); | 4758 | zig_unreachable(); |
| 4634 | } | 4759 | } |
| ... | @@ -11643,6 +11768,62 @@ static TypeTableEntry *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstru | ... | @@ -11643,6 +11768,62 @@ static TypeTableEntry *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstru |
| 11643 | buf_ptr(&child_type->name), buf_ptr(field_name))); | 11768 | buf_ptr(&child_type->name), buf_ptr(field_name))); |
| 11644 | return ira->codegen->builtin_types.entry_invalid; | 11769 | return ira->codegen->builtin_types.entry_invalid; |
| 11645 | } | 11770 | } |
| 11771 | } else if (child_type->id == TypeTableEntryIdErrorUnion) { | ||
| 11772 | if (buf_eql_str(field_name, "Child")) { | ||
| 11773 | bool ptr_is_const = true; | ||
| 11774 | bool ptr_is_volatile = false; | ||
| 11775 | return ir_analyze_const_ptr(ira, &field_ptr_instruction->base, | ||
| 11776 | create_const_type(ira->codegen, child_type->data.error.child_type), | ||
| 11777 | ira->codegen->builtin_types.entry_type, | ||
| 11778 | ConstPtrMutComptimeConst, ptr_is_const, ptr_is_volatile); | ||
| 11779 | } else { | ||
| 11780 | ir_add_error(ira, &field_ptr_instruction->base, | ||
| 11781 | buf_sprintf("type '%s' has no member called '%s'", | ||
| 11782 | buf_ptr(&child_type->name), buf_ptr(field_name))); | ||
| 11783 | return ira->codegen->builtin_types.entry_invalid; | ||
| 11784 | } | ||
| 11785 | } else if (child_type->id == TypeTableEntryIdMaybe) { | ||
| 11786 | if (buf_eql_str(field_name, "Child")) { | ||
| 11787 | bool ptr_is_const = true; | ||
| 11788 | bool ptr_is_volatile = false; | ||
| 11789 | return ir_analyze_const_ptr(ira, &field_ptr_instruction->base, | ||
| 11790 | create_const_type(ira->codegen, child_type->data.maybe.child_type), | ||
| 11791 | ira->codegen->builtin_types.entry_type, | ||
| 11792 | ConstPtrMutComptimeConst, ptr_is_const, ptr_is_volatile); | ||
| 11793 | } else { | ||
| 11794 | ir_add_error(ira, &field_ptr_instruction->base, | ||
| 11795 | buf_sprintf("type '%s' has no member called '%s'", | ||
| 11796 | buf_ptr(&child_type->name), buf_ptr(field_name))); | ||
| 11797 | return ira->codegen->builtin_types.entry_invalid; | ||
| 11798 | } | ||
| 11799 | } else if (child_type->id == TypeTableEntryIdFn) { | ||
| 11800 | if (buf_eql_str(field_name, "ReturnType")) { | ||
| 11801 | bool ptr_is_const = true; | ||
| 11802 | bool ptr_is_volatile = false; | ||
| 11803 | return ir_analyze_const_ptr(ira, &field_ptr_instruction->base, | ||
| 11804 | create_const_type(ira->codegen, child_type->data.fn.fn_type_id.return_type), | ||
| 11805 | ira->codegen->builtin_types.entry_type, | ||
| 11806 | ConstPtrMutComptimeConst, ptr_is_const, ptr_is_volatile); | ||
| 11807 | } else if (buf_eql_str(field_name, "is_var_args")) { | ||
| 11808 | bool ptr_is_const = true; | ||
| 11809 | bool ptr_is_volatile = false; | ||
| 11810 | return ir_analyze_const_ptr(ira, &field_ptr_instruction->base, | ||
| 11811 | create_const_bool(ira->codegen, child_type->data.fn.fn_type_id.is_var_args), | ||
| 11812 | ira->codegen->builtin_types.entry_bool, | ||
| 11813 | ConstPtrMutComptimeConst, ptr_is_const, ptr_is_volatile); | ||
| 11814 | } else if (buf_eql_str(field_name, "arg_count")) { | ||
| 11815 | bool ptr_is_const = true; | ||
| 11816 | bool ptr_is_volatile = false; | ||
| 11817 | return ir_analyze_const_ptr(ira, &field_ptr_instruction->base, | ||
| 11818 | create_const_usize(ira->codegen, child_type->data.fn.fn_type_id.param_count), | ||
| 11819 | ira->codegen->builtin_types.entry_usize, | ||
| 11820 | ConstPtrMutComptimeConst, ptr_is_const, ptr_is_volatile); | ||
| 11821 | } else { | ||
| 11822 | ir_add_error(ira, &field_ptr_instruction->base, | ||
| 11823 | buf_sprintf("type '%s' has no member called '%s'", | ||
| 11824 | buf_ptr(&child_type->name), buf_ptr(field_name))); | ||
| 11825 | return ira->codegen->builtin_types.entry_invalid; | ||
| 11826 | } | ||
| 11646 | } else { | 11827 | } else { |
| 11647 | ir_add_error(ira, &field_ptr_instruction->base, | 11828 | ir_add_error(ira, &field_ptr_instruction->base, |
| 11648 | buf_sprintf("type '%s' does not support field access", buf_ptr(&child_type->name))); | 11829 | buf_sprintf("type '%s' does not support field access", buf_ptr(&child_type->name))); |
| ... | @@ -14240,6 +14421,90 @@ static TypeTableEntry *ir_analyze_instruction_member_count(IrAnalyze *ira, IrIns | ... | @@ -14240,6 +14421,90 @@ static TypeTableEntry *ir_analyze_instruction_member_count(IrAnalyze *ira, IrIns |
| 14240 | return ira->codegen->builtin_types.entry_num_lit_int; | 14421 | return ira->codegen->builtin_types.entry_num_lit_int; |
| 14241 | } | 14422 | } |
| 14242 | 14423 | ||
| 14424 | static TypeTableEntry *ir_analyze_instruction_member_type(IrAnalyze *ira, IrInstructionMemberType *instruction) { | ||
| 14425 | IrInstruction *container_type_value = instruction->container_type->other; | ||
| 14426 | TypeTableEntry *container_type = ir_resolve_type(ira, container_type_value); | ||
| 14427 | if (type_is_invalid(container_type)) | ||
| 14428 | return ira->codegen->builtin_types.entry_invalid; | ||
| 14429 | |||
| 14430 | uint64_t member_index; | ||
| 14431 | IrInstruction *index_value = instruction->member_index->other; | ||
| 14432 | if (!ir_resolve_usize(ira, index_value, &member_index)) | ||
| 14433 | return ira->codegen->builtin_types.entry_invalid; | ||
| 14434 | |||
| 14435 | if (container_type->id == TypeTableEntryIdStruct) { | ||
| 14436 | if (member_index >= container_type->data.structure.src_field_count) { | ||
| 14437 | ir_add_error(ira, index_value, | ||
| 14438 | buf_sprintf("member index %" ZIG_PRI_u64 " out of bounds; '%s' has %" PRIu32 " members", | ||
| 14439 | member_index, buf_ptr(&container_type->name), container_type->data.structure.src_field_count)); | ||
| 14440 | return ira->codegen->builtin_types.entry_invalid; | ||
| 14441 | } | ||
| 14442 | TypeStructField *field = &container_type->data.structure.fields[member_index]; | ||
| 14443 | |||
| 14444 | ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base); | ||
| 14445 | out_val->data.x_type = field->type_entry; | ||
| 14446 | return ira->codegen->builtin_types.entry_type; | ||
| 14447 | } else if (container_type->id == TypeTableEntryIdEnum) { | ||
| 14448 | if (member_index >= container_type->data.enumeration.src_field_count) { | ||
| 14449 | ir_add_error(ira, index_value, | ||
| 14450 | buf_sprintf("member index %" ZIG_PRI_u64 " out of bounds; '%s' has %" PRIu32 " members", | ||
| 14451 | member_index, buf_ptr(&container_type->name), container_type->data.enumeration.src_field_count)); | ||
| 14452 | return ira->codegen->builtin_types.entry_invalid; | ||
| 14453 | } | ||
| 14454 | TypeEnumField *field = &container_type->data.enumeration.fields[member_index]; | ||
| 14455 | |||
| 14456 | ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base); | ||
| 14457 | out_val->data.x_type = field->type_entry; | ||
| 14458 | return ira->codegen->builtin_types.entry_type; | ||
| 14459 | } else { | ||
| 14460 | ir_add_error(ira, container_type_value, | ||
| 14461 | buf_sprintf("type '%s' does not support @memberType", buf_ptr(&container_type->name))); | ||
| 14462 | return ira->codegen->builtin_types.entry_invalid; | ||
| 14463 | } | ||
| 14464 | } | ||
| 14465 | |||
| 14466 | static TypeTableEntry *ir_analyze_instruction_member_name(IrAnalyze *ira, IrInstructionMemberName *instruction) { | ||
| 14467 | IrInstruction *container_type_value = instruction->container_type->other; | ||
| 14468 | TypeTableEntry *container_type = ir_resolve_type(ira, container_type_value); | ||
| 14469 | if (type_is_invalid(container_type)) | ||
| 14470 | return ira->codegen->builtin_types.entry_invalid; | ||
| 14471 | |||
| 14472 | uint64_t member_index; | ||
| 14473 | IrInstruction *index_value = instruction->member_index->other; | ||
| 14474 | if (!ir_resolve_usize(ira, index_value, &member_index)) | ||
| 14475 | return ira->codegen->builtin_types.entry_invalid; | ||
| 14476 | |||
| 14477 | if (container_type->id == TypeTableEntryIdStruct) { | ||
| 14478 | if (member_index >= container_type->data.structure.src_field_count) { | ||
| 14479 | ir_add_error(ira, index_value, | ||
| 14480 | buf_sprintf("member index %" ZIG_PRI_u64 " out of bounds; '%s' has %" PRIu32 " members", | ||
| 14481 | member_index, buf_ptr(&container_type->name), container_type->data.structure.src_field_count)); | ||
| 14482 | return ira->codegen->builtin_types.entry_invalid; | ||
| 14483 | } | ||
| 14484 | TypeStructField *field = &container_type->data.structure.fields[member_index]; | ||
| 14485 | |||
| 14486 | ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base); | ||
| 14487 | init_const_str_lit(ira->codegen, out_val, field->name); | ||
| 14488 | return out_val->type; | ||
| 14489 | } else if (container_type->id == TypeTableEntryIdEnum) { | ||
| 14490 | if (member_index >= container_type->data.enumeration.src_field_count) { | ||
| 14491 | ir_add_error(ira, index_value, | ||
| 14492 | buf_sprintf("member index %" ZIG_PRI_u64 " out of bounds; '%s' has %" PRIu32 " members", | ||
| 14493 | member_index, buf_ptr(&container_type->name), container_type->data.enumeration.src_field_count)); | ||
| 14494 | return ira->codegen->builtin_types.entry_invalid; | ||
| 14495 | } | ||
| 14496 | TypeEnumField *field = &container_type->data.enumeration.fields[member_index]; | ||
| 14497 | |||
| 14498 | ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base); | ||
| 14499 | init_const_str_lit(ira->codegen, out_val, field->name); | ||
| 14500 | return out_val->type; | ||
| 14501 | } else { | ||
| 14502 | ir_add_error(ira, container_type_value, | ||
| 14503 | buf_sprintf("type '%s' does not support @memberName", buf_ptr(&container_type->name))); | ||
| 14504 | return ira->codegen->builtin_types.entry_invalid; | ||
| 14505 | } | ||
| 14506 | } | ||
| 14507 | |||
| 14243 | static TypeTableEntry *ir_analyze_instruction_breakpoint(IrAnalyze *ira, IrInstructionBreakpoint *instruction) { | 14508 | static TypeTableEntry *ir_analyze_instruction_breakpoint(IrAnalyze *ira, IrInstructionBreakpoint *instruction) { |
| 14244 | ir_build_breakpoint_from(&ira->new_irb, &instruction->base); | 14509 | ir_build_breakpoint_from(&ira->new_irb, &instruction->base); |
| 14245 | return ira->codegen->builtin_types.entry_void; | 14510 | return ira->codegen->builtin_types.entry_void; |
| ... | @@ -15346,6 +15611,35 @@ static TypeTableEntry *ir_analyze_instruction_set_align_stack(IrAnalyze *ira, Ir | ... | @@ -15346,6 +15611,35 @@ static TypeTableEntry *ir_analyze_instruction_set_align_stack(IrAnalyze *ira, Ir |
| 15346 | return ira->codegen->builtin_types.entry_void; | 15611 | return ira->codegen->builtin_types.entry_void; |
| 15347 | } | 15612 | } |
| 15348 | 15613 | ||
| 15614 | static TypeTableEntry *ir_analyze_instruction_arg_type(IrAnalyze *ira, IrInstructionArgType *instruction) { | ||
| 15615 | IrInstruction *fn_type_inst = instruction->fn_type->other; | ||
| 15616 | TypeTableEntry *fn_type = ir_resolve_type(ira, fn_type_inst); | ||
| 15617 | if (type_is_invalid(fn_type)) | ||
| 15618 | return ira->codegen->builtin_types.entry_invalid; | ||
| 15619 | |||
| 15620 | IrInstruction *arg_index_inst = instruction->arg_index->other; | ||
| 15621 | uint64_t arg_index; | ||
| 15622 | if (!ir_resolve_usize(ira, arg_index_inst, &arg_index)) | ||
| 15623 | return ira->codegen->builtin_types.entry_invalid; | ||
| 15624 | |||
| 15625 | if (fn_type->id != TypeTableEntryIdFn) { | ||
| 15626 | ir_add_error(ira, fn_type_inst, buf_sprintf("expected function, found '%s'", buf_ptr(&fn_type->name))); | ||
| 15627 | return ira->codegen->builtin_types.entry_invalid; | ||
| 15628 | } | ||
| 15629 | |||
| 15630 | FnTypeId *fn_type_id = &fn_type->data.fn.fn_type_id; | ||
| 15631 | if (arg_index >= fn_type_id->param_count) { | ||
| 15632 | ir_add_error(ira, arg_index_inst, | ||
| 15633 | buf_sprintf("arg index %" ZIG_PRI_u64 " out of bounds; '%s' has %" ZIG_PRI_usize " arguments", | ||
| 15634 | arg_index, buf_ptr(&fn_type->name), fn_type_id->param_count)); | ||
| 15635 | return ira->codegen->builtin_types.entry_invalid; | ||
| 15636 | } | ||
| 15637 | |||
| 15638 | ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base); | ||
| 15639 | out_val->data.x_type = fn_type_id->param_info[arg_index].type; | ||
| 15640 | return ira->codegen->builtin_types.entry_type; | ||
| 15641 | } | ||
| 15642 | |||
| 15349 | static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstruction *instruction) { | 15643 | static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstruction *instruction) { |
| 15350 | switch (instruction->id) { | 15644 | switch (instruction->id) { |
| 15351 | case IrInstructionIdInvalid: | 15645 | case IrInstructionIdInvalid: |
| ... | @@ -15480,6 +15774,10 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi | ... | @@ -15480,6 +15774,10 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi |
| 15480 | return ir_analyze_instruction_slice(ira, (IrInstructionSlice *)instruction); | 15774 | return ir_analyze_instruction_slice(ira, (IrInstructionSlice *)instruction); |
| 15481 | case IrInstructionIdMemberCount: | 15775 | case IrInstructionIdMemberCount: |
| 15482 | return ir_analyze_instruction_member_count(ira, (IrInstructionMemberCount *)instruction); | 15776 | return ir_analyze_instruction_member_count(ira, (IrInstructionMemberCount *)instruction); |
| 15777 | case IrInstructionIdMemberType: | ||
| 15778 | return ir_analyze_instruction_member_type(ira, (IrInstructionMemberType *)instruction); | ||
| 15779 | case IrInstructionIdMemberName: | ||
| 15780 | return ir_analyze_instruction_member_name(ira, (IrInstructionMemberName *)instruction); | ||
| 15483 | case IrInstructionIdBreakpoint: | 15781 | case IrInstructionIdBreakpoint: |
| 15484 | return ir_analyze_instruction_breakpoint(ira, (IrInstructionBreakpoint *)instruction); | 15782 | return ir_analyze_instruction_breakpoint(ira, (IrInstructionBreakpoint *)instruction); |
| 15485 | case IrInstructionIdReturnAddress: | 15783 | case IrInstructionIdReturnAddress: |
| ... | @@ -15536,6 +15834,8 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi | ... | @@ -15536,6 +15834,8 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi |
| 15536 | return ir_analyze_instruction_opaque_type(ira, (IrInstructionOpaqueType *)instruction); | 15834 | return ir_analyze_instruction_opaque_type(ira, (IrInstructionOpaqueType *)instruction); |
| 15537 | case IrInstructionIdSetAlignStack: | 15835 | case IrInstructionIdSetAlignStack: |
| 15538 | return ir_analyze_instruction_set_align_stack(ira, (IrInstructionSetAlignStack *)instruction); | 15836 | return ir_analyze_instruction_set_align_stack(ira, (IrInstructionSetAlignStack *)instruction); |
| 15837 | case IrInstructionIdArgType: | ||
| 15838 | return ir_analyze_instruction_arg_type(ira, (IrInstructionArgType *)instruction); | ||
| 15539 | } | 15839 | } |
| 15540 | zig_unreachable(); | 15840 | zig_unreachable(); |
| 15541 | } | 15841 | } |
| ... | @@ -15687,6 +15987,8 @@ bool ir_has_side_effects(IrInstruction *instruction) { | ... | @@ -15687,6 +15987,8 @@ bool ir_has_side_effects(IrInstruction *instruction) { |
| 15687 | case IrInstructionIdBoolNot: | 15987 | case IrInstructionIdBoolNot: |
| 15688 | case IrInstructionIdSlice: | 15988 | case IrInstructionIdSlice: |
| 15689 | case IrInstructionIdMemberCount: | 15989 | case IrInstructionIdMemberCount: |
| 15990 | case IrInstructionIdMemberType: | ||
| 15991 | case IrInstructionIdMemberName: | ||
| 15690 | case IrInstructionIdAlignOf: | 15992 | case IrInstructionIdAlignOf: |
| 15691 | case IrInstructionIdReturnAddress: | 15993 | case IrInstructionIdReturnAddress: |
| 15692 | case IrInstructionIdFrameAddress: | 15994 | case IrInstructionIdFrameAddress: |
| ... | @@ -15716,6 +16018,7 @@ bool ir_has_side_effects(IrInstruction *instruction) { | ... | @@ -15716,6 +16018,7 @@ bool ir_has_side_effects(IrInstruction *instruction) { |
| 15716 | case IrInstructionIdTypeId: | 16018 | case IrInstructionIdTypeId: |
| 15717 | case IrInstructionIdAlignCast: | 16019 | case IrInstructionIdAlignCast: |
| 15718 | case IrInstructionIdOpaqueType: | 16020 | case IrInstructionIdOpaqueType: |
| 16021 | case IrInstructionIdArgType: | ||
| 15719 | return false; | 16022 | return false; |
| 15720 | case IrInstructionIdAsm: | 16023 | case IrInstructionIdAsm: |
| 15721 | { | 16024 | { |
src/ir_print.cpp+34| ... | @@ -658,6 +658,22 @@ static void ir_print_member_count(IrPrint *irp, IrInstructionMemberCount *instru | ... | @@ -658,6 +658,22 @@ static void ir_print_member_count(IrPrint *irp, IrInstructionMemberCount *instru |
| 658 | fprintf(irp->f, ")"); | 658 | fprintf(irp->f, ")"); |
| 659 | } | 659 | } |
| 660 | 660 | ||
| 661 | static void ir_print_member_type(IrPrint *irp, IrInstructionMemberType *instruction) { | ||
| 662 | fprintf(irp->f, "@memberType("); | ||
| 663 | ir_print_other_instruction(irp, instruction->container_type); | ||
| 664 | fprintf(irp->f, ", "); | ||
| 665 | ir_print_other_instruction(irp, instruction->member_index); | ||
| 666 | fprintf(irp->f, ")"); | ||
| 667 | } | ||
| 668 | |||
| 669 | static void ir_print_member_name(IrPrint *irp, IrInstructionMemberName *instruction) { | ||
| 670 | fprintf(irp->f, "@memberName("); | ||
| 671 | ir_print_other_instruction(irp, instruction->container_type); | ||
| 672 | fprintf(irp->f, ", "); | ||
| 673 | ir_print_other_instruction(irp, instruction->member_index); | ||
| 674 | fprintf(irp->f, ")"); | ||
| 675 | } | ||
| 676 | |||
| 661 | static void ir_print_breakpoint(IrPrint *irp, IrInstructionBreakpoint *instruction) { | 677 | static void ir_print_breakpoint(IrPrint *irp, IrInstructionBreakpoint *instruction) { |
| 662 | fprintf(irp->f, "@breakpoint()"); | 678 | fprintf(irp->f, "@breakpoint()"); |
| 663 | } | 679 | } |
| ... | @@ -954,6 +970,15 @@ static void ir_print_set_align_stack(IrPrint *irp, IrInstructionSetAlignStack *i | ... | @@ -954,6 +970,15 @@ static void ir_print_set_align_stack(IrPrint *irp, IrInstructionSetAlignStack *i |
| 954 | fprintf(irp->f, ")"); | 970 | fprintf(irp->f, ")"); |
| 955 | } | 971 | } |
| 956 | 972 | ||
| 973 | static void ir_print_arg_type(IrPrint *irp, IrInstructionArgType *instruction) { | ||
| 974 | fprintf(irp->f, "@ArgType("); | ||
| 975 | ir_print_other_instruction(irp, instruction->fn_type); | ||
| 976 | fprintf(irp->f, ","); | ||
| 977 | ir_print_other_instruction(irp, instruction->arg_index); | ||
| 978 | fprintf(irp->f, ")"); | ||
| 979 | } | ||
| 980 | |||
| 981 | |||
| 957 | static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) { | 982 | static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) { |
| 958 | ir_print_prefix(irp, instruction); | 983 | ir_print_prefix(irp, instruction); |
| 959 | switch (instruction->id) { | 984 | switch (instruction->id) { |
| ... | @@ -1139,6 +1164,12 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) { | ... | @@ -1139,6 +1164,12 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) { |
| 1139 | case IrInstructionIdMemberCount: | 1164 | case IrInstructionIdMemberCount: |
| 1140 | ir_print_member_count(irp, (IrInstructionMemberCount *)instruction); | 1165 | ir_print_member_count(irp, (IrInstructionMemberCount *)instruction); |
| 1141 | break; | 1166 | break; |
| 1167 | case IrInstructionIdMemberType: | ||
| 1168 | ir_print_member_type(irp, (IrInstructionMemberType *)instruction); | ||
| 1169 | break; | ||
| 1170 | case IrInstructionIdMemberName: | ||
| 1171 | ir_print_member_name(irp, (IrInstructionMemberName *)instruction); | ||
| 1172 | break; | ||
| 1142 | case IrInstructionIdBreakpoint: | 1173 | case IrInstructionIdBreakpoint: |
| 1143 | ir_print_breakpoint(irp, (IrInstructionBreakpoint *)instruction); | 1174 | ir_print_breakpoint(irp, (IrInstructionBreakpoint *)instruction); |
| 1144 | break; | 1175 | break; |
| ... | @@ -1256,6 +1287,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) { | ... | @@ -1256,6 +1287,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) { |
| 1256 | case IrInstructionIdSetAlignStack: | 1287 | case IrInstructionIdSetAlignStack: |
| 1257 | ir_print_set_align_stack(irp, (IrInstructionSetAlignStack *)instruction); | 1288 | ir_print_set_align_stack(irp, (IrInstructionSetAlignStack *)instruction); |
| 1258 | break; | 1289 | break; |
| 1290 | case IrInstructionIdArgType: | ||
| 1291 | ir_print_arg_type(irp, (IrInstructionArgType *)instruction); | ||
| 1292 | break; | ||
| 1259 | } | 1293 | } |
| 1260 | fprintf(irp->f, "\n"); | 1294 | fprintf(irp->f, "\n"); |
| 1261 | } | 1295 | } |
src/link.cpp+1-1| ... | @@ -894,7 +894,7 @@ void codegen_link(CodeGen *g, const char *out_file) { | ... | @@ -894,7 +894,7 @@ void codegen_link(CodeGen *g, const char *out_file) { |
| 894 | Buf *o_file_path = g->link_objects.at(0); | 894 | Buf *o_file_path = g->link_objects.at(0); |
| 895 | int err; | 895 | int err; |
| 896 | if ((err = os_rename(o_file_path, &lj.out_file))) { | 896 | if ((err = os_rename(o_file_path, &lj.out_file))) { |
| 897 | zig_panic("unable to rename object file into final output: %s", err_str(err)); | 897 | zig_panic("unable to rename object file %s into final output %s: %s", buf_ptr(o_file_path), buf_ptr(&lj.out_file), err_str(err)); |
| 898 | } | 898 | } |
| 899 | } | 899 | } |
| 900 | return; | 900 | return; |
src/main.cpp+15| ... | @@ -32,6 +32,7 @@ static int usage(const char *arg0) { | ... | @@ -32,6 +32,7 @@ static int usage(const char *arg0) { |
| 32 | " --assembly $source add assembly file to build\n" | 32 | " --assembly $source add assembly file to build\n" |
| 33 | " --cache-dir $path override the cache directory\n" | 33 | " --cache-dir $path override the cache directory\n" |
| 34 | " --color $auto|off|on enable or disable colored error messages\n" | 34 | " --color $auto|off|on enable or disable colored error messages\n" |
| 35 | " --emit $filetype emit a specific file format as compilation output\n" | ||
| 35 | " --enable-timing-info print timing diagnostics\n" | 36 | " --enable-timing-info print timing diagnostics\n" |
| 36 | " --libc-include-dir $path directory where libc stdlib.h resides\n" | 37 | " --libc-include-dir $path directory where libc stdlib.h resides\n" |
| 37 | " --name $name override output name\n" | 38 | " --name $name override output name\n" |
| ... | @@ -269,6 +270,7 @@ int main(int argc, char **argv) { | ... | @@ -269,6 +270,7 @@ int main(int argc, char **argv) { |
| 269 | 270 | ||
| 270 | char *arg0 = argv[0]; | 271 | char *arg0 = argv[0]; |
| 271 | Cmd cmd = CmdInvalid; | 272 | Cmd cmd = CmdInvalid; |
| 273 | EmitFileType emit_file_type = EmitFileTypeBinary; | ||
| 272 | const char *in_file = nullptr; | 274 | const char *in_file = nullptr; |
| 273 | const char *out_file = nullptr; | 275 | const char *out_file = nullptr; |
| 274 | const char *out_file_h = nullptr; | 276 | const char *out_file_h = nullptr; |
| ... | @@ -535,6 +537,17 @@ int main(int argc, char **argv) { | ... | @@ -535,6 +537,17 @@ int main(int argc, char **argv) { |
| 535 | fprintf(stderr, "--color options are 'auto', 'on', or 'off'\n"); | 537 | fprintf(stderr, "--color options are 'auto', 'on', or 'off'\n"); |
| 536 | return usage(arg0); | 538 | return usage(arg0); |
| 537 | } | 539 | } |
| 540 | } else if (strcmp(arg, "--emit") == 0) { | ||
| 541 | if (strcmp(argv[i], "asm") == 0) { | ||
| 542 | emit_file_type = EmitFileTypeAssembly; | ||
| 543 | } else if (strcmp(argv[i], "bin") == 0) { | ||
| 544 | emit_file_type = EmitFileTypeBinary; | ||
| 545 | } else if (strcmp(argv[i], "llvm-ir") == 0) { | ||
| 546 | emit_file_type = EmitFileTypeLLVMIr; | ||
| 547 | } else { | ||
| 548 | fprintf(stderr, "--emit options are 'asm', 'bin', or 'llvm-ir'\n"); | ||
| 549 | return usage(arg0); | ||
| 550 | } | ||
| 538 | } else if (strcmp(arg, "--name") == 0) { | 551 | } else if (strcmp(arg, "--name") == 0) { |
| 539 | out_name = argv[i]; | 552 | out_name = argv[i]; |
| 540 | } else if (strcmp(arg, "--libc-lib-dir") == 0) { | 553 | } else if (strcmp(arg, "--libc-lib-dir") == 0) { |
| ... | @@ -815,6 +828,8 @@ int main(int argc, char **argv) { | ... | @@ -815,6 +828,8 @@ int main(int argc, char **argv) { |
| 815 | add_package(g, cur_pkg, g->root_package); | 828 | add_package(g, cur_pkg, g->root_package); |
| 816 | 829 | ||
| 817 | if (cmd == CmdBuild) { | 830 | if (cmd == CmdBuild) { |
| 831 | codegen_set_emit_file_type(g, emit_file_type); | ||
| 832 | |||
| 818 | for (size_t i = 0; i < objects.length; i += 1) { | 833 | for (size_t i = 0; i < objects.length; i += 1) { |
| 819 | codegen_add_object(g, buf_create_from_str(objects.at(i))); | 834 | codegen_add_object(g, buf_create_from_str(objects.at(i))); |
| 820 | } | 835 | } |
src/target.cpp+8| ... | @@ -581,6 +581,14 @@ const char *target_o_file_ext(ZigTarget *target) { | ... | @@ -581,6 +581,14 @@ const char *target_o_file_ext(ZigTarget *target) { |
| 581 | } | 581 | } |
| 582 | } | 582 | } |
| 583 | 583 | ||
| 584 | const char *target_asm_file_ext(ZigTarget *target) { | ||
| 585 | return ".s"; | ||
| 586 | } | ||
| 587 | |||
| 588 | const char *target_llvm_ir_file_ext(ZigTarget *target) { | ||
| 589 | return ".ll"; | ||
| 590 | } | ||
| 591 | |||
| 584 | const char *target_exe_file_ext(ZigTarget *target) { | 592 | const char *target_exe_file_ext(ZigTarget *target) { |
| 585 | if (target->os == ZigLLVM_Win32) { | 593 | if (target->os == ZigLLVM_Win32) { |
| 586 | return ".exe"; | 594 | return ".exe"; |
src/target.hpp+2| ... | @@ -73,6 +73,8 @@ void resolve_target_object_format(ZigTarget *target); | ... | @@ -73,6 +73,8 @@ void resolve_target_object_format(ZigTarget *target); |
| 73 | uint32_t target_c_type_size_in_bits(const ZigTarget *target, CIntType id); | 73 | uint32_t target_c_type_size_in_bits(const ZigTarget *target, CIntType id); |
| 74 | 74 | ||
| 75 | const char *target_o_file_ext(ZigTarget *target); | 75 | const char *target_o_file_ext(ZigTarget *target); |
| 76 | const char *target_asm_file_ext(ZigTarget *target); | ||
| 77 | const char *target_llvm_ir_file_ext(ZigTarget *target); | ||
| 76 | const char *target_exe_file_ext(ZigTarget *target); | 78 | const char *target_exe_file_ext(ZigTarget *target); |
| 77 | 79 | ||
| 78 | Buf *target_dynamic_linker(ZigTarget *target); | 80 | Buf *target_dynamic_linker(ZigTarget *target); |
src/zig_llvm.cpp+23-13| ... | @@ -77,7 +77,7 @@ static const bool assertions_on = false; | ... | @@ -77,7 +77,7 @@ static const bool assertions_on = false; |
| 77 | #endif | 77 | #endif |
| 78 | 78 | ||
| 79 | bool ZigLLVMTargetMachineEmitToFile(LLVMTargetMachineRef targ_machine_ref, LLVMModuleRef module_ref, | 79 | bool ZigLLVMTargetMachineEmitToFile(LLVMTargetMachineRef targ_machine_ref, LLVMModuleRef module_ref, |
| 80 | const char *filename, LLVMCodeGenFileType file_type, char **error_message, bool is_debug) | 80 | const char *filename, ZigLLVM_EmitOutputType output_type, char **error_message, bool is_debug) |
| 81 | { | 81 | { |
| 82 | std::error_code EC; | 82 | std::error_code EC; |
| 83 | raw_fd_ostream dest(filename, EC, sys::fs::F_None); | 83 | raw_fd_ostream dest(filename, EC, sys::fs::F_None); |
| ... | @@ -135,18 +135,24 @@ bool ZigLLVMTargetMachineEmitToFile(LLVMTargetMachineRef targ_machine_ref, LLVMM | ... | @@ -135,18 +135,24 @@ bool ZigLLVMTargetMachineEmitToFile(LLVMTargetMachineRef targ_machine_ref, LLVMM |
| 135 | MPM.add(createTargetTransformInfoWrapperPass(target_machine->getTargetIRAnalysis())); | 135 | MPM.add(createTargetTransformInfoWrapperPass(target_machine->getTargetIRAnalysis())); |
| 136 | PMBuilder->populateModulePassManager(MPM); | 136 | PMBuilder->populateModulePassManager(MPM); |
| 137 | 137 | ||
| 138 | // Set output pass. | ||
| 138 | TargetMachine::CodeGenFileType ft; | 139 | TargetMachine::CodeGenFileType ft; |
| 139 | switch (file_type) { | 140 | if (output_type != ZigLLVM_EmitLLVMIr) { |
| 140 | case LLVMAssemblyFile: | 141 | switch (output_type) { |
| 141 | ft = TargetMachine::CGFT_AssemblyFile; | 142 | case ZigLLVM_EmitAssembly: |
| 142 | break; | 143 | ft = TargetMachine::CGFT_AssemblyFile; |
| 143 | default: | 144 | break; |
| 144 | ft = TargetMachine::CGFT_ObjectFile; | 145 | case ZigLLVM_EmitBinary: |
| 145 | break; | 146 | ft = TargetMachine::CGFT_ObjectFile; |
| 146 | } | 147 | break; |
| 147 | if (target_machine->addPassesToEmitFile(MPM, dest, ft)) { | 148 | default: |
| 148 | *error_message = strdup("TargetMachine can't emit a file of this type"); | 149 | abort(); |
| 149 | return true; | 150 | } |
| 151 | |||
| 152 | if (target_machine->addPassesToEmitFile(MPM, dest, ft)) { | ||
| 153 | *error_message = strdup("TargetMachine can't emit a file of this type"); | ||
| 154 | return true; | ||
| 155 | } | ||
| 150 | } | 156 | } |
| 151 | 157 | ||
| 152 | // run per function optimization passes | 158 | // run per function optimization passes |
| ... | @@ -158,7 +164,11 @@ bool ZigLLVMTargetMachineEmitToFile(LLVMTargetMachineRef targ_machine_ref, LLVMM | ... | @@ -158,7 +164,11 @@ bool ZigLLVMTargetMachineEmitToFile(LLVMTargetMachineRef targ_machine_ref, LLVMM |
| 158 | 164 | ||
| 159 | MPM.run(*module); | 165 | MPM.run(*module); |
| 160 | 166 | ||
| 161 | dest.close(); | 167 | if (output_type == ZigLLVM_EmitLLVMIr) { |
| 168 | if (LLVMPrintModuleToFile(module_ref, filename, error_message)) { | ||
| 169 | return true; | ||
| 170 | } | ||
| 171 | } | ||
| 162 | 172 | ||
| 163 | return false; | 173 | return false; |
| 164 | } | 174 | } |
src/zig_llvm.hpp+9-1| ... | @@ -34,8 +34,16 @@ void ZigLLVMInitializeLowerIntrinsicsPass(LLVMPassRegistryRef R); | ... | @@ -34,8 +34,16 @@ void ZigLLVMInitializeLowerIntrinsicsPass(LLVMPassRegistryRef R); |
| 34 | char *ZigLLVMGetHostCPUName(void); | 34 | char *ZigLLVMGetHostCPUName(void); |
| 35 | char *ZigLLVMGetNativeFeatures(void); | 35 | char *ZigLLVMGetNativeFeatures(void); |
| 36 | 36 | ||
| 37 | // We use a custom enum here since LLVM does not expose LLVMIr as an emit | ||
| 38 | // output through the same mechanism as assembly/binary. | ||
| 39 | enum ZigLLVM_EmitOutputType { | ||
| 40 | ZigLLVM_EmitAssembly, | ||
| 41 | ZigLLVM_EmitBinary, | ||
| 42 | ZigLLVM_EmitLLVMIr, | ||
| 43 | }; | ||
| 44 | |||
| 37 | bool ZigLLVMTargetMachineEmitToFile(LLVMTargetMachineRef targ_machine_ref, LLVMModuleRef module_ref, | 45 | bool ZigLLVMTargetMachineEmitToFile(LLVMTargetMachineRef targ_machine_ref, LLVMModuleRef module_ref, |
| 38 | const char *filename, LLVMCodeGenFileType file_type, char **error_message, bool is_debug); | 46 | const char *filename, ZigLLVM_EmitOutputType output_type, char **error_message, bool is_debug); |
| 39 | 47 | ||
| 40 | LLVMValueRef ZigLLVMBuildCall(LLVMBuilderRef B, LLVMValueRef Fn, LLVMValueRef *Args, | 48 | LLVMValueRef ZigLLVMBuildCall(LLVMBuilderRef B, LLVMValueRef Fn, LLVMValueRef *Args, |
| 41 | unsigned NumArgs, unsigned CC, bool always_inline, const char *Name); | 49 | unsigned NumArgs, unsigned CC, bool always_inline, const char *Name); |
std/heap.zig+12-4| ... | @@ -17,8 +17,8 @@ pub var c_allocator = Allocator { | ... | @@ -17,8 +17,8 @@ pub var c_allocator = Allocator { |
| 17 | }; | 17 | }; |
| 18 | 18 | ||
| 19 | fn cAlloc(self: &Allocator, n: usize, alignment: usize) -> %[]u8 { | 19 | fn cAlloc(self: &Allocator, n: usize, alignment: usize) -> %[]u8 { |
| 20 | if (c.malloc(usize(n))) |mem| { | 20 | if (c.malloc(usize(n))) |buf| { |
| 21 | @ptrCast(&u8, mem)[0..n] | 21 | @ptrCast(&u8, buf)[0..n] |
| 22 | } else { | 22 | } else { |
| 23 | error.OutOfMemory | 23 | error.OutOfMemory |
| 24 | } | 24 | } |
| ... | @@ -29,8 +29,8 @@ fn cRealloc(self: &Allocator, old_mem: []u8, new_size: usize, alignment: usize) | ... | @@ -29,8 +29,8 @@ fn cRealloc(self: &Allocator, old_mem: []u8, new_size: usize, alignment: usize) |
| 29 | old_mem[0..new_size] | 29 | old_mem[0..new_size] |
| 30 | } else { | 30 | } else { |
| 31 | const old_ptr = @ptrCast(&c_void, old_mem.ptr); | 31 | const old_ptr = @ptrCast(&c_void, old_mem.ptr); |
| 32 | if (c.realloc(old_ptr, usize(new_size))) |mem| { | 32 | if (c.realloc(old_ptr, usize(new_size))) |buf| { |
| 33 | @ptrCast(&u8, mem)[0..new_size] | 33 | @ptrCast(&u8, buf)[0..new_size] |
| 34 | } else { | 34 | } else { |
| 35 | error.OutOfMemory | 35 | error.OutOfMemory |
| 36 | } | 36 | } |
| ... | @@ -136,6 +136,14 @@ pub const IncrementingAllocator = struct { | ... | @@ -136,6 +136,14 @@ pub const IncrementingAllocator = struct { |
| 136 | } | 136 | } |
| 137 | }; | 137 | }; |
| 138 | 138 | ||
| 139 | test "c_allocator" { | ||
| 140 | if (builtin.link_libc) { | ||
| 141 | var slice = c_allocator.alloc(u8, 50) %% return; | ||
| 142 | defer c_allocator.free(slice); | ||
| 143 | slice = c_allocator.realloc(u8, slice, 100) %% return; | ||
| 144 | } | ||
| 145 | } | ||
| 146 | |||
| 139 | test "IncrementingAllocator" { | 147 | test "IncrementingAllocator" { |
| 140 | const total_bytes = 100 * 1024 * 1024; | 148 | const total_bytes = 100 * 1024 * 1024; |
| 141 | var inc_allocator = %%IncrementingAllocator.init(total_bytes); | 149 | var inc_allocator = %%IncrementingAllocator.init(total_bytes); |
std/io.zig+2-2| ... | @@ -308,7 +308,7 @@ pub const InStream = struct { | ... | @@ -308,7 +308,7 @@ pub const InStream = struct { |
| 308 | readFn: fn(self: &InStream, buffer: []u8) -> %usize, | 308 | readFn: fn(self: &InStream, buffer: []u8) -> %usize, |
| 309 | 309 | ||
| 310 | /// Replaces `buffer` contents by reading from the stream until it is finished. | 310 | /// Replaces `buffer` contents by reading from the stream until it is finished. |
| 311 | /// If `buffer.len()` woould exceed `max_size`, `error.StreamTooLong` is returned and | 311 | /// If `buffer.len()` would exceed `max_size`, `error.StreamTooLong` is returned and |
| 312 | /// the contents read from the stream are lost. | 312 | /// the contents read from the stream are lost. |
| 313 | pub fn readAllBuffer(self: &InStream, buffer: &Buffer, max_size: usize) -> %void { | 313 | pub fn readAllBuffer(self: &InStream, buffer: &Buffer, max_size: usize) -> %void { |
| 314 | %return buffer.resize(0); | 314 | %return buffer.resize(0); |
| ... | @@ -339,7 +339,7 @@ pub const InStream = struct { | ... | @@ -339,7 +339,7 @@ pub const InStream = struct { |
| 339 | var buf = Buffer.initNull(allocator); | 339 | var buf = Buffer.initNull(allocator); |
| 340 | defer buf.deinit(); | 340 | defer buf.deinit(); |
| 341 | 341 | ||
| 342 | %return self.readAllBuffer(self, &buf, max_size); | 342 | %return self.readAllBuffer(&buf, max_size); |
| 343 | return buf.toOwnedSlice(); | 343 | return buf.toOwnedSlice(); |
| 344 | } | 344 | } |
| 345 | 345 |
test/behavior.zig+1| ... | @@ -29,6 +29,7 @@ comptime { | ... | @@ -29,6 +29,7 @@ comptime { |
| 29 | _ = @import("cases/null.zig"); | 29 | _ = @import("cases/null.zig"); |
| 30 | _ = @import("cases/pub_enum/index.zig"); | 30 | _ = @import("cases/pub_enum/index.zig"); |
| 31 | _ = @import("cases/ref_var_in_if_after_if_2nd_switch_prong.zig"); | 31 | _ = @import("cases/ref_var_in_if_after_if_2nd_switch_prong.zig"); |
| 32 | _ = @import("cases/reflection.zig"); | ||
| 32 | _ = @import("cases/sizeof_and_typeof.zig"); | 33 | _ = @import("cases/sizeof_and_typeof.zig"); |
| 33 | _ = @import("cases/slice.zig"); | 34 | _ = @import("cases/slice.zig"); |
| 34 | _ = @import("cases/struct.zig"); | 35 | _ = @import("cases/struct.zig"); |
test/cases/reflection.zig created+70| ... | @@ -0,0 +1,70 @@ | ||
| 1 | const assert = @import("std").debug.assert; | ||
| 2 | const mem = @import("std").mem; | ||
| 3 | |||
| 4 | test "reflection: array, pointer, nullable, error union type child" { | ||
| 5 | comptime { | ||
| 6 | assert(([10]u8).Child == u8); | ||
| 7 | assert((&u8).Child == u8); | ||
| 8 | assert((%u8).Child == u8); | ||
| 9 | assert((?u8).Child == u8); | ||
| 10 | } | ||
| 11 | } | ||
| 12 | |||
| 13 | test "reflection: function return type, var args, and param types" { | ||
| 14 | comptime { | ||
| 15 | assert(@typeOf(dummy).ReturnType == i32); | ||
| 16 | assert(!@typeOf(dummy).is_var_args); | ||
| 17 | assert(@typeOf(dummy_varargs).is_var_args); | ||
| 18 | assert(@typeOf(dummy).arg_count == 3); | ||
| 19 | assert(@ArgType(@typeOf(dummy), 0) == bool); | ||
| 20 | assert(@ArgType(@typeOf(dummy), 1) == i32); | ||
| 21 | assert(@ArgType(@typeOf(dummy), 2) == f32); | ||
| 22 | } | ||
| 23 | } | ||
| 24 | |||
| 25 | fn dummy(a: bool, b: i32, c: f32) -> i32 { 1234 } | ||
| 26 | fn dummy_varargs(args: ...) {} | ||
| 27 | |||
| 28 | test "reflection: struct member types and names" { | ||
| 29 | comptime { | ||
| 30 | assert(@memberCount(Foo) == 3); | ||
| 31 | |||
| 32 | assert(@memberType(Foo, 0) == i32); | ||
| 33 | assert(@memberType(Foo, 1) == bool); | ||
| 34 | assert(@memberType(Foo, 2) == void); | ||
| 35 | |||
| 36 | assert(mem.eql(u8, @memberName(Foo, 0), "one")); | ||
| 37 | assert(mem.eql(u8, @memberName(Foo, 1), "two")); | ||
| 38 | assert(mem.eql(u8, @memberName(Foo, 2), "three")); | ||
| 39 | } | ||
| 40 | } | ||
| 41 | |||
| 42 | test "reflection: enum member types and names" { | ||
| 43 | comptime { | ||
| 44 | assert(@memberCount(Bar) == 4); | ||
| 45 | |||
| 46 | assert(@memberType(Bar, 0) == void); | ||
| 47 | assert(@memberType(Bar, 1) == i32); | ||
| 48 | assert(@memberType(Bar, 2) == bool); | ||
| 49 | assert(@memberType(Bar, 3) == f64); | ||
| 50 | |||
| 51 | assert(mem.eql(u8, @memberName(Bar, 0), "One")); | ||
| 52 | assert(mem.eql(u8, @memberName(Bar, 1), "Two")); | ||
| 53 | assert(mem.eql(u8, @memberName(Bar, 2), "Three")); | ||
| 54 | assert(mem.eql(u8, @memberName(Bar, 3), "Four")); | ||
| 55 | } | ||
| 56 | |||
| 57 | } | ||
| 58 | |||
| 59 | const Foo = struct { | ||
| 60 | one: i32, | ||
| 61 | two: bool, | ||
| 62 | three: void, | ||
| 63 | }; | ||
| 64 | |||
| 65 | const Bar = enum { | ||
| 66 | One, | ||
| 67 | Two: i32, | ||
| 68 | Three: bool, | ||
| 69 | Four: f64, | ||
| 70 | }; | ||
test/compile_errors.zig+60| ... | @@ -2275,4 +2275,64 @@ pub fn addCases(cases: &tests.CompileErrorContext) { | ... | @@ -2275,4 +2275,64 @@ pub fn addCases(cases: &tests.CompileErrorContext) { |
| 2275 | , | 2275 | , |
| 2276 | ".tmp_source.zig:2:1: error: invalid character: '\\t'"); | 2276 | ".tmp_source.zig:2:1: error: invalid character: '\\t'"); |
| 2277 | 2277 | ||
| 2278 | cases.add("@ArgType given non function parameter", | ||
| 2279 | \\comptime { | ||
| 2280 | \\ _ = @ArgType(i32, 3); | ||
| 2281 | \\} | ||
| 2282 | , | ||
| 2283 | ".tmp_source.zig:2:18: error: expected function, found 'i32'"); | ||
| 2284 | |||
| 2285 | cases.add("@ArgType arg index out of bounds", | ||
| 2286 | \\comptime { | ||
| 2287 | \\ _ = @ArgType(@typeOf(add), 2); | ||
| 2288 | \\} | ||
| 2289 | \\fn add(a: i32, b: i32) -> i32 { return a + b; } | ||
| 2290 | , | ||
| 2291 | ".tmp_source.zig:2:32: error: arg index 2 out of bounds; 'fn(i32, i32) -> i32' has 2 arguments"); | ||
| 2292 | |||
| 2293 | cases.add("@memberType on unsupported type", | ||
| 2294 | \\comptime { | ||
| 2295 | \\ _ = @memberType(i32, 0); | ||
| 2296 | \\} | ||
| 2297 | , | ||
| 2298 | ".tmp_source.zig:2:21: error: type 'i32' does not support @memberType"); | ||
| 2299 | |||
| 2300 | cases.add("@memberType struct out of bounds", | ||
| 2301 | \\comptime { | ||
| 2302 | \\ _ = @memberType(Foo, 0); | ||
| 2303 | \\} | ||
| 2304 | \\const Foo = struct {}; | ||
| 2305 | , | ||
| 2306 | ".tmp_source.zig:2:26: error: member index 0 out of bounds; 'Foo' has 0 members"); | ||
| 2307 | |||
| 2308 | cases.add("@memberType enum out of bounds", | ||
| 2309 | \\comptime { | ||
| 2310 | \\ _ = @memberType(Foo, 0); | ||
| 2311 | \\} | ||
| 2312 | \\const Foo = enum {}; | ||
| 2313 | , | ||
| 2314 | ".tmp_source.zig:2:26: error: member index 0 out of bounds; 'Foo' has 0 members"); | ||
| 2315 | |||
| 2316 | cases.add("@memberName on unsupported type", | ||
| 2317 | \\comptime { | ||
| 2318 | \\ _ = @memberName(i32, 0); | ||
| 2319 | \\} | ||
| 2320 | , | ||
| 2321 | ".tmp_source.zig:2:21: error: type 'i32' does not support @memberName"); | ||
| 2322 | |||
| 2323 | cases.add("@memberName struct out of bounds", | ||
| 2324 | \\comptime { | ||
| 2325 | \\ _ = @memberName(Foo, 0); | ||
| 2326 | \\} | ||
| 2327 | \\const Foo = struct {}; | ||
| 2328 | , | ||
| 2329 | ".tmp_source.zig:2:26: error: member index 0 out of bounds; 'Foo' has 0 members"); | ||
| 2330 | |||
| 2331 | cases.add("@memberName enum out of bounds", | ||
| 2332 | \\comptime { | ||
| 2333 | \\ _ = @memberName(Foo, 0); | ||
| 2334 | \\} | ||
| 2335 | \\const Foo = enum {}; | ||
| 2336 | , | ||
| 2337 | ".tmp_source.zig:2:26: error: member index 0 out of bounds; 'Foo' has 0 members"); | ||
| 2278 | } | 2338 | } |