authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-11-06 22:41:12-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-11-06 22:41:12-05:00
log3a600297ca3f99ee57630c44900eec1fe7c92804
tree9642e53df266077c0ee76c1a045366f8f805fe95
parent4a82c2d124881512548254f5cdff3009b2f424df
parent634e8713c394bacfe080d03256d1dd4f9a43dd8c

Merge remote-tracking branch 'origin/master' into llvm6


19 files changed, 794 insertions(+), 150 deletions(-)

src-self-hosted/main.zig+8-6
......@@ -3,24 +3,27 @@ const io = @import("std").io;
33const os = @import("std").os;
44const heap = @import("std").mem;
55
6// TODO: OutSteam and InStream interface
7// TODO: move allocator to heap namespace
86// TODO: sync up CLI with c++ code
7// TODO: concurrency
98
109error InvalidArgument;
1110error MissingArg0;
1211
1312var arg0: []u8 = undefined;
1413
14var stderr_file: io.File = undefined;
15const stderr = &stderr_file.out_stream;
16
1517pub fn main() -> %void {
18 stderr_file = %return io.getStdErr();
1619 if (internal_main()) |_| {
1720 return;
1821 } else |err| {
1922 if (err == error.InvalidArgument) {
20 io.stderr.printf("\n") %% return err;
21 printUsage(&io.stderr) %% return err;
23 stderr.print("\n") %% return err;
24 printUsage(stderr) %% return err;
2225 } else {
23 io.stderr.printf("{}\n", err) %% return err;
26 stderr.print("{}\n", err) %% return err;
2427 }
2528 return err;
2629 }
......@@ -266,7 +269,6 @@ fn printUsage(outstream: &io.OutStream) -> %void {
266269 \\ --test-cmd-bin appends test binary path to test cmd args
267270 \\
268271 );
269 %return outstream.flush();
270272}
271273
272274const ZIG_ZEN =
src/all_types.hpp+34
......@@ -1211,6 +1211,8 @@ enum BuiltinFnId {
12111211 BuiltinFnIdMaxValue,
12121212 BuiltinFnIdMinValue,
12131213 BuiltinFnIdMemberCount,
1214 BuiltinFnIdMemberType,
1215 BuiltinFnIdMemberName,
12141216 BuiltinFnIdTypeof,
12151217 BuiltinFnIdAddWithOverflow,
12161218 BuiltinFnIdSubWithOverflow,
......@@ -1261,6 +1263,7 @@ enum BuiltinFnId {
12611263 BuiltinFnIdAlignCast,
12621264 BuiltinFnIdOpaqueType,
12631265 BuiltinFnIdSetAlignStack,
1266 BuiltinFnIdArgType,
12641267};
12651268
12661269struct BuiltinFnEntry {
......@@ -1366,6 +1369,12 @@ enum BuildMode {
13661369 BuildModeSafeRelease,
13671370};
13681371
1372enum EmitFileType {
1373 EmitFileTypeBinary,
1374 EmitFileTypeAssembly,
1375 EmitFileTypeLLVMIr,
1376};
1377
13691378struct LinkLib {
13701379 Buf *name;
13711380 Buf *path;
......@@ -1449,6 +1458,7 @@ struct CodeGen {
14491458 TypeTableEntry *entry_arg_tuple;
14501459 } builtin_types;
14511460
1461 EmitFileType emit_file_type;
14521462 ZigTarget zig_target;
14531463 LLVMTargetDataRef target_data_ref;
14541464 unsigned pointer_size_bytes;
......@@ -1837,6 +1847,8 @@ enum IrInstructionId {
18371847 IrInstructionIdMemcpy,
18381848 IrInstructionIdSlice,
18391849 IrInstructionIdMemberCount,
1850 IrInstructionIdMemberType,
1851 IrInstructionIdMemberName,
18401852 IrInstructionIdBreakpoint,
18411853 IrInstructionIdReturnAddress,
18421854 IrInstructionIdFrameAddress,
......@@ -1875,6 +1887,7 @@ enum IrInstructionId {
18751887 IrInstructionIdAlignCast,
18761888 IrInstructionIdOpaqueType,
18771889 IrInstructionIdSetAlignStack,
1890 IrInstructionIdArgType,
18781891};
18791892
18801893struct IrInstruction {
......@@ -2399,6 +2412,20 @@ struct IrInstructionMemberCount {
23992412 IrInstruction *container;
24002413};
24012414
2415struct IrInstructionMemberType {
2416 IrInstruction base;
2417
2418 IrInstruction *container_type;
2419 IrInstruction *member_index;
2420};
2421
2422struct IrInstructionMemberName {
2423 IrInstruction base;
2424
2425 IrInstruction *container_type;
2426 IrInstruction *member_index;
2427};
2428
24022429struct IrInstructionBreakpoint {
24032430 IrInstruction base;
24042431};
......@@ -2675,6 +2702,13 @@ struct IrInstructionSetAlignStack {
26752702 IrInstruction *align_bytes;
26762703};
26772704
2705struct IrInstructionArgType {
2706 IrInstruction base;
2707
2708 IrInstruction *fn_type;
2709 IrInstruction *arg_index;
2710};
2711
26782712static const size_t slice_ptr_index = 0;
26792713static const size_t slice_len_index = 1;
26802714
src/analyze.cpp+140-111
......@@ -1366,119 +1366,140 @@ static void resolve_enum_type(CodeGen *g, TypeTableEntry *enum_type) {
13661366 enum_type->data.enumeration.union_size_bytes = biggest_size_in_bits / 8;
13671367 enum_type->data.enumeration.most_aligned_union_member = most_aligned_union_member;
13681368
1369 if (!enum_type->data.enumeration.is_invalid) {
1370 TypeTableEntry *tag_int_type = get_smallest_unsigned_int_type(g, field_count);
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;
1369 if (enum_type->data.enumeration.is_invalid)
1370 return;
13921371
1393 assert(8*LLVMABIAlignmentOfType(g->target_data_ref, union_type_ref) >= biggest_align_in_bits);
1394 assert(8*LLVMStoreSizeOfType(g->target_data_ref, union_type_ref) >= biggest_size_in_bits);
1372 if (enum_type->zero_bits) {
1373 enum_type->type_ref = LLVMVoidType();
13951374
1396 if (align_of_tag_in_bits >= biggest_align_in_bits) {
1397 enum_type->data.enumeration.gen_tag_index = 0;
1398 enum_type->data.enumeration.gen_union_index = 1;
1399 } else {
1400 enum_type->data.enumeration.gen_union_index = 0;
1401 enum_type->data.enumeration.gen_tag_index = 1;
1402 }
1375 uint64_t debug_size_in_bits = 0;
1376 uint64_t debug_align_in_bits = 0;
1377 ZigLLVMDIType **di_root_members = nullptr;
1378 size_t debug_member_count = 0;
1379 ZigLLVMDIType *replacement_di_type = ZigLLVMCreateDebugStructType(g->dbuilder,
1380 ZigLLVMFileToScope(import->di_file),
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, "");
14031386
1404 // create llvm type for root struct
1405 LLVMTypeRef root_struct_element_types[2];
1406 root_struct_element_types[enum_type->data.enumeration.gen_tag_index] = tag_type_entry->type_ref;
1407 root_struct_element_types[enum_type->data.enumeration.gen_union_index] = union_type_ref;
1408 LLVMStructSetBody(enum_type->type_ref, root_struct_element_types, 2, false);
1409
1410 // create debug type for tag
1411 uint64_t tag_debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, tag_type_entry->type_ref);
1412 uint64_t tag_debug_align_in_bits = 8*LLVMABIAlignmentOfType(g->target_data_ref, tag_type_entry->type_ref);
1413 ZigLLVMDIType *tag_di_type = ZigLLVMCreateDebugEnumerationType(g->dbuilder,
1414 ZigLLVMTypeToScope(enum_type->di_type), "AnonEnum",
1415 import->di_file, (unsigned)(decl_node->line + 1),
1416 tag_debug_size_in_bits, tag_debug_align_in_bits, di_enumerators, field_count,
1417 tag_type_entry->di_type, "");
1418
1419 // create debug type for union
1420 ZigLLVMDIType *union_di_type = ZigLLVMCreateDebugUnionType(g->dbuilder,
1421 ZigLLVMTypeToScope(enum_type->di_type), "AnonUnion",
1422 import->di_file, (unsigned)(decl_node->line + 1),
1423 biggest_size_in_bits, biggest_align_in_bits, 0, union_inner_di_types,
1424 gen_field_count, 0, "");
1425
1426 // create debug types for members of root struct
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;
1387 ZigLLVMReplaceTemporary(g->dbuilder, enum_type->di_type, replacement_di_type);
1388 enum_type->di_type = replacement_di_type;
1389 return;
1390 }
1391
1392 TypeTableEntry *tag_int_type = get_smallest_unsigned_int_type(g, field_count);
1393 TypeTableEntry *tag_type_entry = create_enum_tag_type(g, enum_type, tag_int_type);
1394 enum_type->data.enumeration.tag_type = tag_type_entry;
1395
1396 uint64_t align_of_tag_in_bits = 8*LLVMABIAlignmentOfType(g->target_data_ref, tag_int_type->type_ref);
1397
1398 if (most_aligned_union_member) {
1399 // create llvm type for union
1400 uint64_t padding_in_bits = biggest_size_in_bits - size_of_most_aligned_member_in_bits;
1401 LLVMTypeRef union_type_ref;
1402 if (padding_in_bits > 0) {
1403 TypeTableEntry *u8_type = get_int_type(g, false, 8);
1404 TypeTableEntry *padding_array = get_array_type(g, u8_type, padding_in_bits / 8);
1405 LLVMTypeRef union_element_types[] = {
1406 most_aligned_union_member->type_ref,
1407 padding_array->type_ref,
1408 };
1409 union_type_ref = LLVMStructType(union_element_types, 2, false);
14641410 } else {
1465 // create llvm type for root struct
1466 enum_type->type_ref = tag_type_entry->type_ref;
1467
1468 // create debug type for tag
1469 uint64_t tag_debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, tag_type_entry->type_ref);
1470 uint64_t tag_debug_align_in_bits = 8*LLVMABIAlignmentOfType(g->target_data_ref, tag_type_entry->type_ref);
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, "");
1411 union_type_ref = most_aligned_union_member->type_ref;
1412 }
1413 enum_type->data.enumeration.union_type_ref = union_type_ref;
1414
1415 assert(8*LLVMABIAlignmentOfType(g->target_data_ref, union_type_ref) >= biggest_align_in_bits);
1416 assert(8*LLVMStoreSizeOfType(g->target_data_ref, union_type_ref) >= biggest_size_in_bits);
14781417
1479 ZigLLVMReplaceTemporary(g->dbuilder, enum_type->di_type, tag_di_type);
1480 enum_type->di_type = tag_di_type;
1418 if (align_of_tag_in_bits >= biggest_align_in_bits) {
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;
14811424 }
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;
14821503 }
14831504}
14841505
......@@ -1875,9 +1896,11 @@ static void resolve_enum_zero_bits(CodeGen *g, TypeTableEntry *enum_type) {
18751896 enum_type->data.enumeration.zero_bits_known = true;
18761897
18771898 // also compute abi_alignment
1878 TypeTableEntry *tag_int_type = get_smallest_unsigned_int_type(g, field_count);
1879 uint32_t align_of_tag_in_bytes = LLVMABIAlignmentOfType(g->target_data_ref, tag_int_type->type_ref);
1880 enum_type->data.enumeration.abi_alignment = max(align_of_tag_in_bytes, biggest_align_bytes);
1899 if (!enum_type->zero_bits) {
1900 TypeTableEntry *tag_int_type = get_smallest_unsigned_int_type(g, field_count);
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 }
18811904}
18821905
18831906static void resolve_struct_zero_bits(CodeGen *g, TypeTableEntry *struct_type) {
......@@ -3440,8 +3463,14 @@ void find_libc_lib_path(CodeGen *g) {
34403463 zig_panic("Unable to determine libc lib path.");
34413464 }
34423465 }
3466
34433467 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 }
34453474 }
34463475}
34473476
src/c_tokenizer.cpp+4-1
......@@ -91,6 +91,9 @@
9191 IDENT_START: \
9292 case DIGIT
9393
94#define LINE_ENDING \
95 '\r': \
96 case '\n'
9497
9598static void begin_token(CTokenize *ctok, CTokId id) {
9699 assert(ctok->cur_tok == nullptr);
......@@ -191,7 +194,7 @@ void tokenize_c_macro(CTokenize *ctok, const uint8_t *c) {
191194 case '\\':
192195 ctok->state = CTokStateBackslash;
193196 break;
194 case '\n':
197 case LINE_ENDING:
195198 goto found_end_of_macro;
196199 case IDENT_START:
197200 ctok->state = CTokStateIdentifier;
src/codegen.cpp+67-11
......@@ -189,6 +189,10 @@ void codegen_set_is_test(CodeGen *g, bool is_test_build) {
189189 g->is_test_build = is_test_build;
190190}
191191
192void codegen_set_emit_file_type(CodeGen *g, EmitFileType emit_file_type) {
193 g->emit_file_type = emit_file_type;
194}
195
192196void codegen_set_is_static(CodeGen *g, bool is_static) {
193197 g->is_static = is_static;
194198}
......@@ -3380,6 +3384,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
33803384 case IrInstructionIdEmbedFile:
33813385 case IrInstructionIdIntType:
33823386 case IrInstructionIdMemberCount:
3387 case IrInstructionIdMemberType:
3388 case IrInstructionIdMemberName:
33833389 case IrInstructionIdAlignOf:
33843390 case IrInstructionIdFnProto:
33853391 case IrInstructionIdTestComptime:
......@@ -3397,6 +3403,7 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
33973403 case IrInstructionIdPtrTypeOf:
33983404 case IrInstructionIdOpaqueType:
33993405 case IrInstructionIdSetAlignStack:
3406 case IrInstructionIdArgType:
34003407 zig_unreachable();
34013408 case IrInstructionIdReturn:
34023409 return ir_render_return(g, executable, (IrInstructionReturn *)instruction);
......@@ -4493,24 +4500,70 @@ static void do_code_gen(CodeGen *g) {
44934500 LLVMVerifyModule(g->module, LLVMAbortProcessAction, &error);
44944501#endif
44954502
4496 codegen_add_time_event(g, "LLVM Emit Object");
4503 codegen_add_time_event(g, "LLVM Emit Output");
44974504
44984505 char *err_msg = nullptr;
44994506 Buf *o_basename = buf_create_from_buf(g->root_out_name);
4500 const char *o_ext = target_o_file_ext(&g->zig_target);
4501 buf_append_str(o_basename, o_ext);
4507
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
45024531 Buf *output_path = buf_alloc();
45034532 os_path_join(g->cache_dir, o_basename, output_path);
45044533 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 }
45104534
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;
45124563
4513 g->link_objects.append(output_path);
4564 default:
4565 zig_unreachable();
4566 }
45144567}
45154568
45164569static const uint8_t int_sizes_in_bits[] = {
......@@ -4816,7 +4869,9 @@ static void define_builtin_fns(CodeGen *g) {
48164869 create_builtin_fn(g, BuiltinFnIdMaxValue, "maxValue", 1);
48174870 create_builtin_fn(g, BuiltinFnIdMinValue, "minValue", 1);
48184871 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
48204875 create_builtin_fn(g, BuiltinFnIdAddWithOverflow, "addWithOverflow", 4);
48214876 create_builtin_fn(g, BuiltinFnIdSubWithOverflow, "subWithOverflow", 4);
48224877 create_builtin_fn(g, BuiltinFnIdMulWithOverflow, "mulWithOverflow", 4);
......@@ -4863,6 +4918,7 @@ static void define_builtin_fns(CodeGen *g) {
48634918 create_builtin_fn(g, BuiltinFnIdAlignCast, "alignCast", 2);
48644919 create_builtin_fn(g, BuiltinFnIdOpaqueType, "OpaqueType", 0);
48654920 create_builtin_fn(g, BuiltinFnIdSetAlignStack, "setAlignStack", 1);
4921 create_builtin_fn(g, BuiltinFnIdArgType, "ArgType", 2);
48664922}
48674923
48684924static 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);
2323void codegen_set_is_test(CodeGen *codegen, bool is_test);
2424void codegen_set_each_lib_rpath(CodeGen *codegen, bool each_lib_rpath);
2525
26void codegen_set_emit_file_type(CodeGen *g, EmitFileType emit_file_type);
2627void codegen_set_is_static(CodeGen *codegen, bool is_static);
2728void codegen_set_strip(CodeGen *codegen, bool strip);
2829void codegen_set_errmsg_color(CodeGen *codegen, ErrColor err_color);
src/ir.cpp+303
......@@ -411,6 +411,14 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionMemberCount *) {
411411 return IrInstructionIdMemberCount;
412412}
413413
414static constexpr IrInstructionId ir_instruction_id(IrInstructionMemberType *) {
415 return IrInstructionIdMemberType;
416}
417
418static constexpr IrInstructionId ir_instruction_id(IrInstructionMemberName *) {
419 return IrInstructionIdMemberName;
420}
421
414422static constexpr IrInstructionId ir_instruction_id(IrInstructionBreakpoint *) {
415423 return IrInstructionIdBreakpoint;
416424}
......@@ -567,6 +575,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionSetAlignStack *)
567575 return IrInstructionIdSetAlignStack;
568576}
569577
578static constexpr IrInstructionId ir_instruction_id(IrInstructionArgType *) {
579 return IrInstructionIdArgType;
580}
581
570582template<typename T>
571583static T *ir_create_instruction(IrBuilder *irb, Scope *scope, AstNode *source_node) {
572584 T *special_instruction = allocate<T>(1);
......@@ -1779,6 +1791,32 @@ static IrInstruction *ir_build_member_count(IrBuilder *irb, Scope *scope, AstNod
17791791 return &instruction->base;
17801792}
17811793
1794static 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
1807static 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
17821820static IrInstruction *ir_build_breakpoint(IrBuilder *irb, Scope *scope, AstNode *source_node) {
17831821 IrInstructionBreakpoint *instruction = ir_build_instruction<IrInstructionBreakpoint>(irb, scope, source_node);
17841822 return &instruction->base;
......@@ -2263,6 +2301,19 @@ static IrInstruction *ir_build_set_align_stack(IrBuilder *irb, Scope *scope, Ast
22632301 return &instruction->base;
22642302}
22652303
2304static 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
22662317static IrInstruction *ir_instruction_br_get_dep(IrInstructionBr *instruction, size_t index) {
22672318 return nullptr;
22682319}
......@@ -2710,6 +2761,22 @@ static IrInstruction *ir_instruction_membercount_get_dep(IrInstructionMemberCoun
27102761 }
27112762}
27122763
2764static 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
2772static 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
27132780static IrInstruction *ir_instruction_breakpoint_get_dep(IrInstructionBreakpoint *instruction, size_t index) {
27142781 return nullptr;
27152782}
......@@ -2992,6 +3059,14 @@ static IrInstruction *ir_instruction_setalignstack_get_dep(IrInstructionSetAlign
29923059 }
29933060}
29943061
3062static 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
29953070static IrInstruction *ir_instruction_get_dep(IrInstruction *instruction, size_t index) {
29963071 switch (instruction->id) {
29973072 case IrInstructionIdInvalid:
......@@ -3118,6 +3193,10 @@ static IrInstruction *ir_instruction_get_dep(IrInstruction *instruction, size_t
31183193 return ir_instruction_slice_get_dep((IrInstructionSlice *) instruction, index);
31193194 case IrInstructionIdMemberCount:
31203195 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);
31213200 case IrInstructionIdBreakpoint:
31223201 return ir_instruction_breakpoint_get_dep((IrInstructionBreakpoint *) instruction, index);
31233202 case IrInstructionIdReturnAddress:
......@@ -3194,6 +3273,8 @@ static IrInstruction *ir_instruction_get_dep(IrInstruction *instruction, size_t
31943273 return ir_instruction_opaquetype_get_dep((IrInstructionOpaqueType *) instruction, index);
31953274 case IrInstructionIdSetAlignStack:
31963275 return ir_instruction_setalignstack_get_dep((IrInstructionSetAlignStack *) instruction, index);
3276 case IrInstructionIdArgType:
3277 return ir_instruction_argtype_get_dep((IrInstructionArgType *) instruction, index);
31973278 }
31983279 zig_unreachable();
31993280}
......@@ -4352,6 +4433,36 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
43524433
43534434 return ir_build_member_count(irb, scope, node, arg0_value);
43544435 }
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 }
43554466 case BuiltinFnIdBreakpoint:
43564467 return ir_build_breakpoint(irb, scope, node);
43574468 case BuiltinFnIdReturnAddress:
......@@ -4629,6 +4740,20 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
46294740
46304741 return ir_build_set_align_stack(irb, scope, node, arg0_value);
46314742 }
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 }
46324757 }
46334758 zig_unreachable();
46344759}
......@@ -11643,6 +11768,62 @@ static TypeTableEntry *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstru
1164311768 buf_ptr(&child_type->name), buf_ptr(field_name)));
1164411769 return ira->codegen->builtin_types.entry_invalid;
1164511770 }
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 }
1164611827 } else {
1164711828 ir_add_error(ira, &field_ptr_instruction->base,
1164811829 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
1424014421 return ira->codegen->builtin_types.entry_num_lit_int;
1424114422}
1424214423
14424static 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
14466static 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
1424314508static TypeTableEntry *ir_analyze_instruction_breakpoint(IrAnalyze *ira, IrInstructionBreakpoint *instruction) {
1424414509 ir_build_breakpoint_from(&ira->new_irb, &instruction->base);
1424514510 return ira->codegen->builtin_types.entry_void;
......@@ -15346,6 +15611,35 @@ static TypeTableEntry *ir_analyze_instruction_set_align_stack(IrAnalyze *ira, Ir
1534615611 return ira->codegen->builtin_types.entry_void;
1534715612}
1534815613
15614static 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
1534915643static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstruction *instruction) {
1535015644 switch (instruction->id) {
1535115645 case IrInstructionIdInvalid:
......@@ -15480,6 +15774,10 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi
1548015774 return ir_analyze_instruction_slice(ira, (IrInstructionSlice *)instruction);
1548115775 case IrInstructionIdMemberCount:
1548215776 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);
1548315781 case IrInstructionIdBreakpoint:
1548415782 return ir_analyze_instruction_breakpoint(ira, (IrInstructionBreakpoint *)instruction);
1548515783 case IrInstructionIdReturnAddress:
......@@ -15536,6 +15834,8 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi
1553615834 return ir_analyze_instruction_opaque_type(ira, (IrInstructionOpaqueType *)instruction);
1553715835 case IrInstructionIdSetAlignStack:
1553815836 return ir_analyze_instruction_set_align_stack(ira, (IrInstructionSetAlignStack *)instruction);
15837 case IrInstructionIdArgType:
15838 return ir_analyze_instruction_arg_type(ira, (IrInstructionArgType *)instruction);
1553915839 }
1554015840 zig_unreachable();
1554115841}
......@@ -15687,6 +15987,8 @@ bool ir_has_side_effects(IrInstruction *instruction) {
1568715987 case IrInstructionIdBoolNot:
1568815988 case IrInstructionIdSlice:
1568915989 case IrInstructionIdMemberCount:
15990 case IrInstructionIdMemberType:
15991 case IrInstructionIdMemberName:
1569015992 case IrInstructionIdAlignOf:
1569115993 case IrInstructionIdReturnAddress:
1569215994 case IrInstructionIdFrameAddress:
......@@ -15716,6 +16018,7 @@ bool ir_has_side_effects(IrInstruction *instruction) {
1571616018 case IrInstructionIdTypeId:
1571716019 case IrInstructionIdAlignCast:
1571816020 case IrInstructionIdOpaqueType:
16021 case IrInstructionIdArgType:
1571916022 return false;
1572016023 case IrInstructionIdAsm:
1572116024 {
src/ir_print.cpp+34
......@@ -658,6 +658,22 @@ static void ir_print_member_count(IrPrint *irp, IrInstructionMemberCount *instru
658658 fprintf(irp->f, ")");
659659}
660660
661static 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
669static 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
661677static void ir_print_breakpoint(IrPrint *irp, IrInstructionBreakpoint *instruction) {
662678 fprintf(irp->f, "@breakpoint()");
663679}
......@@ -954,6 +970,15 @@ static void ir_print_set_align_stack(IrPrint *irp, IrInstructionSetAlignStack *i
954970 fprintf(irp->f, ")");
955971}
956972
973static 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
957982static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
958983 ir_print_prefix(irp, instruction);
959984 switch (instruction->id) {
......@@ -1139,6 +1164,12 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
11391164 case IrInstructionIdMemberCount:
11401165 ir_print_member_count(irp, (IrInstructionMemberCount *)instruction);
11411166 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;
11421173 case IrInstructionIdBreakpoint:
11431174 ir_print_breakpoint(irp, (IrInstructionBreakpoint *)instruction);
11441175 break;
......@@ -1256,6 +1287,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
12561287 case IrInstructionIdSetAlignStack:
12571288 ir_print_set_align_stack(irp, (IrInstructionSetAlignStack *)instruction);
12581289 break;
1290 case IrInstructionIdArgType:
1291 ir_print_arg_type(irp, (IrInstructionArgType *)instruction);
1292 break;
12591293 }
12601294 fprintf(irp->f, "\n");
12611295}
src/link.cpp+1-1
......@@ -894,7 +894,7 @@ void codegen_link(CodeGen *g, const char *out_file) {
894894 Buf *o_file_path = g->link_objects.at(0);
895895 int err;
896896 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));
898898 }
899899 }
900900 return;
src/main.cpp+15
......@@ -32,6 +32,7 @@ static int usage(const char *arg0) {
3232 " --assembly $source add assembly file to build\n"
3333 " --cache-dir $path override the cache directory\n"
3434 " --color $auto|off|on enable or disable colored error messages\n"
35 " --emit $filetype emit a specific file format as compilation output\n"
3536 " --enable-timing-info print timing diagnostics\n"
3637 " --libc-include-dir $path directory where libc stdlib.h resides\n"
3738 " --name $name override output name\n"
......@@ -269,6 +270,7 @@ int main(int argc, char **argv) {
269270
270271 char *arg0 = argv[0];
271272 Cmd cmd = CmdInvalid;
273 EmitFileType emit_file_type = EmitFileTypeBinary;
272274 const char *in_file = nullptr;
273275 const char *out_file = nullptr;
274276 const char *out_file_h = nullptr;
......@@ -535,6 +537,17 @@ int main(int argc, char **argv) {
535537 fprintf(stderr, "--color options are 'auto', 'on', or 'off'\n");
536538 return usage(arg0);
537539 }
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 }
538551 } else if (strcmp(arg, "--name") == 0) {
539552 out_name = argv[i];
540553 } else if (strcmp(arg, "--libc-lib-dir") == 0) {
......@@ -815,6 +828,8 @@ int main(int argc, char **argv) {
815828 add_package(g, cur_pkg, g->root_package);
816829
817830 if (cmd == CmdBuild) {
831 codegen_set_emit_file_type(g, emit_file_type);
832
818833 for (size_t i = 0; i < objects.length; i += 1) {
819834 codegen_add_object(g, buf_create_from_str(objects.at(i)));
820835 }
src/target.cpp+8
......@@ -581,6 +581,14 @@ const char *target_o_file_ext(ZigTarget *target) {
581581 }
582582}
583583
584const char *target_asm_file_ext(ZigTarget *target) {
585 return ".s";
586}
587
588const char *target_llvm_ir_file_ext(ZigTarget *target) {
589 return ".ll";
590}
591
584592const char *target_exe_file_ext(ZigTarget *target) {
585593 if (target->os == ZigLLVM_Win32) {
586594 return ".exe";
src/target.hpp+2
......@@ -73,6 +73,8 @@ void resolve_target_object_format(ZigTarget *target);
7373uint32_t target_c_type_size_in_bits(const ZigTarget *target, CIntType id);
7474
7575const char *target_o_file_ext(ZigTarget *target);
76const char *target_asm_file_ext(ZigTarget *target);
77const char *target_llvm_ir_file_ext(ZigTarget *target);
7678const char *target_exe_file_ext(ZigTarget *target);
7779
7880Buf *target_dynamic_linker(ZigTarget *target);
src/zig_llvm.cpp+23-13
......@@ -77,7 +77,7 @@ static const bool assertions_on = false;
7777#endif
7878
7979bool 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)
8181{
8282 std::error_code EC;
8383 raw_fd_ostream dest(filename, EC, sys::fs::F_None);
......@@ -135,18 +135,24 @@ bool ZigLLVMTargetMachineEmitToFile(LLVMTargetMachineRef targ_machine_ref, LLVMM
135135 MPM.add(createTargetTransformInfoWrapperPass(target_machine->getTargetIRAnalysis()));
136136 PMBuilder->populateModulePassManager(MPM);
137137
138 // Set output pass.
138139 TargetMachine::CodeGenFileType ft;
139 switch (file_type) {
140 case LLVMAssemblyFile:
141 ft = TargetMachine::CGFT_AssemblyFile;
142 break;
143 default:
144 ft = TargetMachine::CGFT_ObjectFile;
145 break;
146 }
147 if (target_machine->addPassesToEmitFile(MPM, dest, ft)) {
148 *error_message = strdup("TargetMachine can't emit a file of this type");
149 return true;
140 if (output_type != ZigLLVM_EmitLLVMIr) {
141 switch (output_type) {
142 case ZigLLVM_EmitAssembly:
143 ft = TargetMachine::CGFT_AssemblyFile;
144 break;
145 case ZigLLVM_EmitBinary:
146 ft = TargetMachine::CGFT_ObjectFile;
147 break;
148 default:
149 abort();
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 }
150156 }
151157
152158 // run per function optimization passes
......@@ -158,7 +164,11 @@ bool ZigLLVMTargetMachineEmitToFile(LLVMTargetMachineRef targ_machine_ref, LLVMM
158164
159165 MPM.run(*module);
160166
161 dest.close();
167 if (output_type == ZigLLVM_EmitLLVMIr) {
168 if (LLVMPrintModuleToFile(module_ref, filename, error_message)) {
169 return true;
170 }
171 }
162172
163173 return false;
164174}
src/zig_llvm.hpp+9-1
......@@ -34,8 +34,16 @@ void ZigLLVMInitializeLowerIntrinsicsPass(LLVMPassRegistryRef R);
3434char *ZigLLVMGetHostCPUName(void);
3535char *ZigLLVMGetNativeFeatures(void);
3636
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.
39enum ZigLLVM_EmitOutputType {
40 ZigLLVM_EmitAssembly,
41 ZigLLVM_EmitBinary,
42 ZigLLVM_EmitLLVMIr,
43};
44
3745bool 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);
3947
4048LLVMValueRef ZigLLVMBuildCall(LLVMBuilderRef B, LLVMValueRef Fn, LLVMValueRef *Args,
4149 unsigned NumArgs, unsigned CC, bool always_inline, const char *Name);
std/heap.zig+12-4
......@@ -17,8 +17,8 @@ pub var c_allocator = Allocator {
1717};
1818
1919fn cAlloc(self: &Allocator, n: usize, alignment: usize) -> %[]u8 {
20 if (c.malloc(usize(n))) |mem| {
21 @ptrCast(&u8, mem)[0..n]
20 if (c.malloc(usize(n))) |buf| {
21 @ptrCast(&u8, buf)[0..n]
2222 } else {
2323 error.OutOfMemory
2424 }
......@@ -29,8 +29,8 @@ fn cRealloc(self: &Allocator, old_mem: []u8, new_size: usize, alignment: usize)
2929 old_mem[0..new_size]
3030 } else {
3131 const old_ptr = @ptrCast(&c_void, old_mem.ptr);
32 if (c.realloc(old_ptr, usize(new_size))) |mem| {
33 @ptrCast(&u8, mem)[0..new_size]
32 if (c.realloc(old_ptr, usize(new_size))) |buf| {
33 @ptrCast(&u8, buf)[0..new_size]
3434 } else {
3535 error.OutOfMemory
3636 }
......@@ -136,6 +136,14 @@ pub const IncrementingAllocator = struct {
136136 }
137137};
138138
139test "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
139147test "IncrementingAllocator" {
140148 const total_bytes = 100 * 1024 * 1024;
141149 var inc_allocator = %%IncrementingAllocator.init(total_bytes);
std/io.zig+2-2
......@@ -308,7 +308,7 @@ pub const InStream = struct {
308308 readFn: fn(self: &InStream, buffer: []u8) -> %usize,
309309
310310 /// 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
312312 /// the contents read from the stream are lost.
313313 pub fn readAllBuffer(self: &InStream, buffer: &Buffer, max_size: usize) -> %void {
314314 %return buffer.resize(0);
......@@ -339,7 +339,7 @@ pub const InStream = struct {
339339 var buf = Buffer.initNull(allocator);
340340 defer buf.deinit();
341341
342 %return self.readAllBuffer(self, &buf, max_size);
342 %return self.readAllBuffer(&buf, max_size);
343343 return buf.toOwnedSlice();
344344 }
345345
test/behavior.zig+1
......@@ -29,6 +29,7 @@ comptime {
2929 _ = @import("cases/null.zig");
3030 _ = @import("cases/pub_enum/index.zig");
3131 _ = @import("cases/ref_var_in_if_after_if_2nd_switch_prong.zig");
32 _ = @import("cases/reflection.zig");
3233 _ = @import("cases/sizeof_and_typeof.zig");
3334 _ = @import("cases/slice.zig");
3435 _ = @import("cases/struct.zig");
test/cases/reflection.zig created+70
......@@ -0,0 +1,70 @@
1const assert = @import("std").debug.assert;
2const mem = @import("std").mem;
3
4test "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
13test "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
25fn dummy(a: bool, b: i32, c: f32) -> i32 { 1234 }
26fn dummy_varargs(args: ...) {}
27
28test "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
42test "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
59const Foo = struct {
60 one: i32,
61 two: bool,
62 three: void,
63};
64
65const 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) {
22752275 ,
22762276 ".tmp_source.zig:2:1: error: invalid character: '\\t'");
22772277
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");
22782338}