| author | |
| committer | |
| log | 7e11ef79d67d000675e90ddf93fdb78d71cc695d |
| tree | 1a6bbe0cd8d5f8f24fd997341ced1e11b444b059 |
| parent | 7b0542d08b7e8e5ccbe81f495d641305b3b8a264 |
See #29810 files changed, 185 insertions(+), 132 deletions(-)
doc/style.md+3| ... | ... | @@ -29,6 +29,9 @@ rules in written English are subject to naming conventions just like any other |
| 29 | 29 | word. Even acronyms that are only 2 letters long are subject to these |
| 30 | 30 | conventions. |
| 31 | 31 | |
| 32 | These are general rules of thumb; if it makes sense to do something different, | |
| 33 | do what makes sense. | |
| 34 | ||
| 32 | 35 | Examples: |
| 33 | 36 | |
| 34 | 37 | ```zig |
src/all_types.hpp+3-1| ... | ... | @@ -1095,6 +1095,7 @@ struct ImportTableEntry { |
| 1095 | 1095 | ScopeDecls *decls_scope; |
| 1096 | 1096 | AstNode *c_import_node; |
| 1097 | 1097 | bool any_imports_failed; |
| 1098 | bool scanned; | |
| 1098 | 1099 | |
| 1099 | 1100 | ZigList<AstNode *> use_decls; |
| 1100 | 1101 | }; |
| ... | ... | @@ -1398,6 +1399,7 @@ struct CodeGen { |
| 1398 | 1399 | PackageTableEntry *root_package; |
| 1399 | 1400 | PackageTableEntry *std_package; |
| 1400 | 1401 | PackageTableEntry *zigrt_package; |
| 1402 | PackageTableEntry *test_runner_package; | |
| 1401 | 1403 | Buf *root_out_name; |
| 1402 | 1404 | bool windows_subsystem_windows; |
| 1403 | 1405 | bool windows_subsystem_console; |
| ... | ... | @@ -1451,7 +1453,7 @@ struct CodeGen { |
| 1451 | 1453 | size_t clang_argv_len; |
| 1452 | 1454 | ZigList<const char *> lib_dirs; |
| 1453 | 1455 | |
| 1454 | uint32_t test_fn_count; | |
| 1456 | ZigList<FnTableEntry *> test_fns; | |
| 1455 | 1457 | TypeTableEntry *test_fn_type; |
| 1456 | 1458 | |
| 1457 | 1459 | bool each_lib_rpath; |
src/analyze.cpp+79-5| ... | ... | @@ -1413,6 +1413,71 @@ static bool type_allowed_in_packed_struct(TypeTableEntry *type_entry) { |
| 1413 | 1413 | zig_unreachable(); |
| 1414 | 1414 | } |
| 1415 | 1415 | |
| 1416 | TypeTableEntry *get_struct_type(CodeGen *g, const char *type_name, const char *field_names[], | |
| 1417 | TypeTableEntry *field_types[], size_t field_count) | |
| 1418 | { | |
| 1419 | TypeTableEntry *struct_type = new_type_table_entry(TypeTableEntryIdStruct); | |
| 1420 | ||
| 1421 | buf_init_from_str(&struct_type->name, type_name); | |
| 1422 | ||
| 1423 | struct_type->data.structure.src_field_count = field_count; | |
| 1424 | struct_type->data.structure.gen_field_count = field_count; | |
| 1425 | struct_type->data.structure.zero_bits_known = true; | |
| 1426 | struct_type->data.structure.complete = true; | |
| 1427 | struct_type->data.structure.fields = allocate<TypeStructField>(field_count); | |
| 1428 | ||
| 1429 | ZigLLVMDIType **di_element_types = allocate<ZigLLVMDIType*>(field_count); | |
| 1430 | LLVMTypeRef *element_types = allocate<LLVMTypeRef>(field_count); | |
| 1431 | for (size_t i = 0; i < field_count; i += 1) { | |
| 1432 | element_types[i] = field_types[i]->type_ref; | |
| 1433 | ||
| 1434 | TypeStructField *field = &struct_type->data.structure.fields[i]; | |
| 1435 | field->name = buf_create_from_str(field_names[i]); | |
| 1436 | field->type_entry = field_types[i]; | |
| 1437 | field->src_index = i; | |
| 1438 | field->gen_index = i; | |
| 1439 | } | |
| 1440 | ||
| 1441 | struct_type->type_ref = LLVMStructCreateNamed(LLVMGetGlobalContext(), type_name); | |
| 1442 | LLVMStructSetBody(struct_type->type_ref, element_types, field_count, false); | |
| 1443 | ||
| 1444 | struct_type->di_type = ZigLLVMCreateReplaceableCompositeType(g->dbuilder, | |
| 1445 | ZigLLVMTag_DW_structure_type(), type_name, | |
| 1446 | ZigLLVMCompileUnitToScope(g->compile_unit), nullptr, 0); | |
| 1447 | ||
| 1448 | for (size_t i = 0; i < field_count; i += 1) { | |
| 1449 | TypeStructField *type_struct_field = &struct_type->data.structure.fields[i]; | |
| 1450 | TypeTableEntry *field_type = type_struct_field->type_entry; | |
| 1451 | uint64_t debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, field_type->type_ref); | |
| 1452 | uint64_t debug_align_in_bits = 8*LLVMABISizeOfType(g->target_data_ref, field_type->type_ref); | |
| 1453 | uint64_t debug_offset_in_bits = 8*LLVMOffsetOfElement(g->target_data_ref, struct_type->type_ref, i); | |
| 1454 | di_element_types[i] = ZigLLVMCreateDebugMemberType(g->dbuilder, | |
| 1455 | ZigLLVMTypeToScope(struct_type->di_type), buf_ptr(type_struct_field->name), | |
| 1456 | nullptr, 0, | |
| 1457 | debug_size_in_bits, | |
| 1458 | debug_align_in_bits, | |
| 1459 | debug_offset_in_bits, | |
| 1460 | 0, field_type->di_type); | |
| 1461 | ||
| 1462 | assert(di_element_types[i]); | |
| 1463 | } | |
| 1464 | ||
| 1465 | uint64_t debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, struct_type->type_ref); | |
| 1466 | uint64_t debug_align_in_bits = 8*LLVMABISizeOfType(g->target_data_ref, struct_type->type_ref); | |
| 1467 | ZigLLVMDIType *replacement_di_type = ZigLLVMCreateDebugStructType(g->dbuilder, | |
| 1468 | ZigLLVMCompileUnitToScope(g->compile_unit), | |
| 1469 | type_name, nullptr, 0, | |
| 1470 | debug_size_in_bits, | |
| 1471 | debug_align_in_bits, | |
| 1472 | 0, | |
| 1473 | nullptr, di_element_types, field_count, 0, nullptr, ""); | |
| 1474 | ||
| 1475 | ZigLLVMReplaceTemporary(g->dbuilder, struct_type->di_type, replacement_di_type); | |
| 1476 | struct_type->di_type = replacement_di_type; | |
| 1477 | ||
| 1478 | return struct_type; | |
| 1479 | } | |
| 1480 | ||
| 1416 | 1481 | static void resolve_struct_type(CodeGen *g, TypeTableEntry *struct_type) { |
| 1417 | 1482 | // if you change the logic of this function likely you must make a similar change in |
| 1418 | 1483 | // parseh.cpp |
| ... | ... | @@ -1823,7 +1888,7 @@ static void typecheck_panic_fn(CodeGen *g, FnTableEntry *panic_fn) { |
| 1823 | 1888 | } |
| 1824 | 1889 | } |
| 1825 | 1890 | |
| 1826 | static TypeTableEntry *get_test_fn_type(CodeGen *g) { | |
| 1891 | TypeTableEntry *get_test_fn_type(CodeGen *g) { | |
| 1827 | 1892 | if (g->test_fn_type) |
| 1828 | 1893 | return g->test_fn_type; |
| 1829 | 1894 | |
| ... | ... | @@ -1875,7 +1940,10 @@ static void resolve_decl_fn(CodeGen *g, TldFn *tld_fn) { |
| 1875 | 1940 | if (fn_def_node) |
| 1876 | 1941 | g->fn_defs.append(fn_table_entry); |
| 1877 | 1942 | |
| 1878 | if (g->have_pub_main && import == g->root_import && scope_is_root_decls(tld_fn->base.parent_scope)) { | |
| 1943 | if (g->have_pub_main && scope_is_root_decls(tld_fn->base.parent_scope) && | |
| 1944 | ((!g->is_test_build && import == g->root_import) || | |
| 1945 | (g->is_test_build && import == g->test_runner_import))) | |
| 1946 | { | |
| 1879 | 1947 | if (buf_eql_str(&fn_table_entry->symbol_name, "main")) { |
| 1880 | 1948 | g->main_fn = fn_table_entry; |
| 1881 | 1949 | |
| ... | ... | @@ -1909,10 +1977,10 @@ static void resolve_decl_fn(CodeGen *g, TldFn *tld_fn) { |
| 1909 | 1977 | fn_table_entry->type_entry = get_test_fn_type(g); |
| 1910 | 1978 | fn_table_entry->body_node = source_node->data.test_decl.body; |
| 1911 | 1979 | fn_table_entry->is_test = true; |
| 1912 | g->test_fn_count += 1; | |
| 1913 | 1980 | |
| 1914 | 1981 | g->fn_protos.append(fn_table_entry); |
| 1915 | 1982 | g->fn_defs.append(fn_table_entry); |
| 1983 | g->test_fns.append(fn_table_entry); | |
| 1916 | 1984 | |
| 1917 | 1985 | } else { |
| 1918 | 1986 | zig_unreachable(); |
| ... | ... | @@ -1926,7 +1994,7 @@ static void resolve_decl_comptime(CodeGen *g, TldCompTime *tld_comptime) { |
| 1926 | 1994 | } |
| 1927 | 1995 | |
| 1928 | 1996 | static void add_top_level_decl(CodeGen *g, ScopeDecls *decls_scope, Tld *tld) { |
| 1929 | if (tld->visib_mod == VisibModExport || (tld->id == TldIdVar && g->is_test_build)) { | |
| 1997 | if (tld->visib_mod == VisibModExport) { | |
| 1930 | 1998 | g->resolve_queue.append(tld); |
| 1931 | 1999 | } |
| 1932 | 2000 | |
| ... | ... | @@ -2932,11 +3000,17 @@ ImportTableEntry *add_source_file(CodeGen *g, PackageTableEntry *package, Buf *a |
| 2932 | 3000 | return import_entry; |
| 2933 | 3001 | } |
| 2934 | 3002 | |
| 3003 | void scan_import(CodeGen *g, ImportTableEntry *import) { | |
| 3004 | if (!import->scanned) { | |
| 3005 | import->scanned = true; | |
| 3006 | scan_decls(g, import->decls_scope, import->root); | |
| 3007 | } | |
| 3008 | } | |
| 2935 | 3009 | |
| 2936 | 3010 | void semantic_analyze(CodeGen *g) { |
| 2937 | 3011 | for (; g->import_queue_index < g->import_queue.length; g->import_queue_index += 1) { |
| 2938 | 3012 | ImportTableEntry *import = g->import_queue.at(g->import_queue_index); |
| 2939 | scan_decls(g, import->decls_scope, import->root); | |
| 3013 | scan_import(g, import); | |
| 2940 | 3014 | } |
| 2941 | 3015 | |
| 2942 | 3016 | for (; g->use_queue_index < g->use_queue.length; g->use_queue_index += 1) { |
src/analyze.hpp+4| ... | ... | @@ -33,6 +33,9 @@ TypeTableEntry *get_smallest_unsigned_int_type(CodeGen *g, uint64_t x); |
| 33 | 33 | TypeTableEntry *get_error_type(CodeGen *g, TypeTableEntry *child_type); |
| 34 | 34 | TypeTableEntry *get_bound_fn_type(CodeGen *g, FnTableEntry *fn_entry); |
| 35 | 35 | TypeTableEntry *get_opaque_type(CodeGen *g, Scope *scope, AstNode *source_node, const char *name); |
| 36 | TypeTableEntry *get_struct_type(CodeGen *g, const char *type_name, const char *field_names[], | |
| 37 | TypeTableEntry *field_types[], size_t field_count); | |
| 38 | TypeTableEntry *get_test_fn_type(CodeGen *g); | |
| 36 | 39 | bool handle_is_ptr(TypeTableEntry *type_entry); |
| 37 | 40 | void find_libc_include_path(CodeGen *g); |
| 38 | 41 | void find_libc_lib_path(CodeGen *g); |
| ... | ... | @@ -60,6 +63,7 @@ ScopeDecls *get_container_scope(TypeTableEntry *type_entry); |
| 60 | 63 | TypeEnumField *find_enum_type_field(TypeTableEntry *enum_type, Buf *name); |
| 61 | 64 | bool is_container_ref(TypeTableEntry *type_entry); |
| 62 | 65 | void scan_decls(CodeGen *g, ScopeDecls *decls_scope, AstNode *node); |
| 66 | void scan_import(CodeGen *g, ImportTableEntry *import); | |
| 63 | 67 | void preview_use_decl(CodeGen *g, AstNode *node); |
| 64 | 68 | void resolve_use_decl(CodeGen *g, AstNode *node); |
| 65 | 69 | FnTableEntry *scope_fn_entry(Scope *scope); |
src/codegen.cpp+67-97| ... | ... | @@ -2906,7 +2906,7 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable, |
| 2906 | 2906 | case IrInstructionIdDeclRef: |
| 2907 | 2907 | case IrInstructionIdSwitchVar: |
| 2908 | 2908 | case IrInstructionIdSetFnRefInline: |
| 2909 | case IrInstructionIdOffsetOf: | |
| 2909 | case IrInstructionIdOffsetOf: | |
| 2910 | 2910 | zig_unreachable(); |
| 2911 | 2911 | case IrInstructionIdReturn: |
| 2912 | 2912 | return ir_render_return(g, executable, (IrInstructionReturn *)instruction); |
| ... | ... | @@ -3087,7 +3087,7 @@ static LLVMValueRef gen_const_ptr_struct_recursive(CodeGen *g, ConstExprValue *s |
| 3087 | 3087 | return LLVMConstInBoundsGEP(base_ptr, indices, 2); |
| 3088 | 3088 | } |
| 3089 | 3089 | |
| 3090 | static LLVMValueRef pack_const_int(CodeGen *g, LLVMTypeRef big_int_type_ref, ConstExprValue *const_val) { | |
| 3090 | static LLVMValueRef pack_const_int(CodeGen *g, LLVMTypeRef big_int_type_ref, ConstExprValue *const_val) { | |
| 3091 | 3091 | switch (const_val->special) { |
| 3092 | 3092 | case ConstValSpecialRuntime: |
| 3093 | 3093 | zig_unreachable(); |
| ... | ... | @@ -3501,50 +3501,6 @@ static void delete_unused_builtin_fns(CodeGen *g) { |
| 3501 | 3501 | } |
| 3502 | 3502 | } |
| 3503 | 3503 | |
| 3504 | static bool should_skip_fn_codegen(CodeGen *g, FnTableEntry *fn_entry) { | |
| 3505 | if (g->is_test_build) { | |
| 3506 | if (fn_entry->is_test) { | |
| 3507 | return false; | |
| 3508 | } | |
| 3509 | if (fn_entry == g->main_fn) { | |
| 3510 | return true; | |
| 3511 | } | |
| 3512 | return false; | |
| 3513 | } | |
| 3514 | ||
| 3515 | if (fn_entry->is_test) { | |
| 3516 | return true; | |
| 3517 | } | |
| 3518 | ||
| 3519 | return false; | |
| 3520 | } | |
| 3521 | ||
| 3522 | static LLVMValueRef gen_test_fn_val(CodeGen *g, FnTableEntry *fn_entry) { | |
| 3523 | // Must match TestFn struct from test_runner.zig | |
| 3524 | Buf *fn_name = &fn_entry->symbol_name; | |
| 3525 | LLVMValueRef str_init = LLVMConstString(buf_ptr(fn_name), (unsigned)buf_len(fn_name), true); | |
| 3526 | LLVMValueRef str_global_val = LLVMAddGlobal(g->module, LLVMTypeOf(str_init), ""); | |
| 3527 | LLVMSetInitializer(str_global_val, str_init); | |
| 3528 | LLVMSetLinkage(str_global_val, LLVMPrivateLinkage); | |
| 3529 | LLVMSetGlobalConstant(str_global_val, true); | |
| 3530 | LLVMSetUnnamedAddr(str_global_val, true); | |
| 3531 | ||
| 3532 | LLVMValueRef len_val = LLVMConstInt(g->builtin_types.entry_usize->type_ref, buf_len(fn_name), false); | |
| 3533 | ||
| 3534 | LLVMTypeRef ptr_type = LLVMPointerType(g->builtin_types.entry_u8->type_ref, 0); | |
| 3535 | LLVMValueRef name_fields[] = { | |
| 3536 | LLVMConstBitCast(str_global_val, ptr_type), | |
| 3537 | len_val, | |
| 3538 | }; | |
| 3539 | ||
| 3540 | LLVMValueRef name_val = LLVMConstStruct(name_fields, 2, false); | |
| 3541 | LLVMValueRef fields[] = { | |
| 3542 | name_val, | |
| 3543 | fn_llvm_value(g, fn_entry), | |
| 3544 | }; | |
| 3545 | return LLVMConstStruct(fields, 2, false); | |
| 3546 | } | |
| 3547 | ||
| 3548 | 3504 | static void generate_error_name_table(CodeGen *g) { |
| 3549 | 3505 | if (g->err_name_table != nullptr || !g->generate_error_name_table || g->error_decls.length == 1) { |
| 3550 | 3506 | return; |
| ... | ... | @@ -3740,17 +3696,9 @@ static void do_code_gen(CodeGen *g) { |
| 3740 | 3696 | var->value_ref = global_value; |
| 3741 | 3697 | } |
| 3742 | 3698 | |
| 3743 | LLVMValueRef *test_fn_vals = nullptr; | |
| 3744 | uint32_t next_test_index = 0; | |
| 3745 | if (g->is_test_build) { | |
| 3746 | test_fn_vals = allocate<LLVMValueRef>(g->test_fn_count); | |
| 3747 | } | |
| 3748 | ||
| 3749 | 3699 | // Generate function prototypes |
| 3750 | 3700 | for (size_t fn_proto_i = 0; fn_proto_i < g->fn_protos.length; fn_proto_i += 1) { |
| 3751 | 3701 | FnTableEntry *fn_table_entry = g->fn_protos.at(fn_proto_i); |
| 3752 | if (should_skip_fn_codegen(g, fn_table_entry)) | |
| 3753 | continue; | |
| 3754 | 3702 | |
| 3755 | 3703 | TypeTableEntry *fn_type = fn_table_entry->type_entry; |
| 3756 | 3704 | FnTypeId *fn_type_id = &fn_type->data.fn.fn_type_id; |
| ... | ... | @@ -3797,51 +3745,11 @@ static void do_code_gen(CodeGen *g) { |
| 3797 | 3745 | addLLVMArgAttr(fn_val, (unsigned)gen_index, "byval"); |
| 3798 | 3746 | } |
| 3799 | 3747 | } |
| 3800 | ||
| 3801 | if (fn_table_entry->is_test) { | |
| 3802 | test_fn_vals[next_test_index] = gen_test_fn_val(g, fn_table_entry); | |
| 3803 | next_test_index += 1; | |
| 3804 | } | |
| 3805 | } | |
| 3806 | ||
| 3807 | // Generate the list of test function pointers. | |
| 3808 | if (g->is_test_build) { | |
| 3809 | if (g->test_fn_count == 0) { | |
| 3810 | fprintf(stderr, "No tests to run.\n"); | |
| 3811 | exit(0); | |
| 3812 | } | |
| 3813 | assert(g->test_fn_count > 0); | |
| 3814 | assert(next_test_index == g->test_fn_count); | |
| 3815 | ||
| 3816 | LLVMValueRef test_fn_array_init = LLVMConstArray(LLVMTypeOf(test_fn_vals[0]), | |
| 3817 | test_fn_vals, g->test_fn_count); | |
| 3818 | LLVMValueRef test_fn_array_val = LLVMAddGlobal(g->module, | |
| 3819 | LLVMTypeOf(test_fn_array_init), ""); | |
| 3820 | LLVMSetInitializer(test_fn_array_val, test_fn_array_init); | |
| 3821 | LLVMSetLinkage(test_fn_array_val, LLVMInternalLinkage); | |
| 3822 | LLVMSetGlobalConstant(test_fn_array_val, true); | |
| 3823 | LLVMSetUnnamedAddr(test_fn_array_val, true); | |
| 3824 | ||
| 3825 | LLVMValueRef len_val = LLVMConstInt(g->builtin_types.entry_usize->type_ref, g->test_fn_count, false); | |
| 3826 | LLVMTypeRef ptr_type = LLVMPointerType(LLVMTypeOf(test_fn_vals[0]), 0); | |
| 3827 | LLVMValueRef fields[] = { | |
| 3828 | LLVMConstBitCast(test_fn_array_val, ptr_type), | |
| 3829 | len_val, | |
| 3830 | }; | |
| 3831 | LLVMValueRef test_fn_slice_init = LLVMConstStruct(fields, 2, false); | |
| 3832 | LLVMValueRef test_fn_slice_val = LLVMAddGlobal(g->module, | |
| 3833 | LLVMTypeOf(test_fn_slice_init), "zig_test_fn_list"); | |
| 3834 | LLVMSetInitializer(test_fn_slice_val, test_fn_slice_init); | |
| 3835 | LLVMSetLinkage(test_fn_slice_val, LLVMExternalLinkage); | |
| 3836 | LLVMSetGlobalConstant(test_fn_slice_val, true); | |
| 3837 | LLVMSetUnnamedAddr(test_fn_slice_val, true); | |
| 3838 | 3748 | } |
| 3839 | 3749 | |
| 3840 | 3750 | // Generate function definitions. |
| 3841 | 3751 | for (size_t fn_i = 0; fn_i < g->fn_defs.length; fn_i += 1) { |
| 3842 | 3752 | FnTableEntry *fn_table_entry = g->fn_defs.at(fn_i); |
| 3843 | if (should_skip_fn_codegen(g, fn_table_entry)) | |
| 3844 | continue; | |
| 3845 | 3753 | |
| 3846 | 3754 | LLVMValueRef fn = fn_llvm_value(g, fn_table_entry); |
| 3847 | 3755 | g->cur_fn = fn_table_entry; |
| ... | ... | @@ -4737,10 +4645,16 @@ static ImportTableEntry *add_special_code(CodeGen *g, PackageTableEntry *package |
| 4737 | 4645 | return add_source_file(g, package, abs_full_path, import_code); |
| 4738 | 4646 | } |
| 4739 | 4647 | |
| 4740 | static PackageTableEntry *create_bootstrap_pkg(CodeGen *g) { | |
| 4648 | static PackageTableEntry *create_bootstrap_pkg(CodeGen *g, PackageTableEntry *pkg_with_main) { | |
| 4741 | 4649 | PackageTableEntry *package = new_package(buf_ptr(g->zig_std_special_dir), ""); |
| 4742 | 4650 | package->package_table.put(buf_create_from_str("std"), g->std_package); |
| 4743 | package->package_table.put(buf_create_from_str("@root"), g->root_package); | |
| 4651 | package->package_table.put(buf_create_from_str("@root"), pkg_with_main); | |
| 4652 | return package; | |
| 4653 | } | |
| 4654 | ||
| 4655 | static PackageTableEntry *create_test_runner_pkg(CodeGen *g) { | |
| 4656 | PackageTableEntry *package = new_package(buf_ptr(g->zig_std_special_dir), "test_runner.zig"); | |
| 4657 | package->package_table.put(buf_create_from_str("std"), g->std_package); | |
| 4744 | 4658 | return package; |
| 4745 | 4659 | } |
| 4746 | 4660 | |
| ... | ... | @@ -4751,6 +4665,54 @@ static PackageTableEntry *create_zigrt_pkg(CodeGen *g) { |
| 4751 | 4665 | return package; |
| 4752 | 4666 | } |
| 4753 | 4667 | |
| 4668 | static void create_test_compile_var_and_add_test_runner(CodeGen *g) { | |
| 4669 | assert(g->is_test_build); | |
| 4670 | ||
| 4671 | if (g->test_fns.length == 0) { | |
| 4672 | fprintf(stderr, "No tests to run.\n"); | |
| 4673 | exit(0); | |
| 4674 | } | |
| 4675 | ||
| 4676 | TypeTableEntry *str_type = get_slice_type(g, g->builtin_types.entry_u8, true); | |
| 4677 | TypeTableEntry *fn_type = get_test_fn_type(g); | |
| 4678 | ||
| 4679 | const char *field_names[] = { "name", "func", }; | |
| 4680 | TypeTableEntry *field_types[] = { str_type, fn_type, }; | |
| 4681 | TypeTableEntry *struct_type = get_struct_type(g, "ZigTestFn", field_names, field_types, 2); | |
| 4682 | ||
| 4683 | ConstExprValue *test_fn_array = allocate<ConstExprValue>(1); | |
| 4684 | test_fn_array->type = get_array_type(g, struct_type, g->test_fns.length); | |
| 4685 | test_fn_array->special = ConstValSpecialStatic; | |
| 4686 | test_fn_array->data.x_array.s_none.elements = allocate<ConstExprValue>(g->test_fns.length); | |
| 4687 | ||
| 4688 | for (size_t i = 0; i < g->test_fns.length; i += 1) { | |
| 4689 | FnTableEntry *test_fn_entry = g->test_fns.at(i); | |
| 4690 | ||
| 4691 | ConstExprValue *this_val = &test_fn_array->data.x_array.s_none.elements[i]; | |
| 4692 | this_val->special = ConstValSpecialStatic; | |
| 4693 | this_val->type = struct_type; | |
| 4694 | this_val->data.x_struct.parent.id = ConstParentIdArray; | |
| 4695 | this_val->data.x_struct.parent.data.p_array.array_val = test_fn_array; | |
| 4696 | this_val->data.x_struct.parent.data.p_array.elem_index = i; | |
| 4697 | this_val->data.x_struct.fields = allocate<ConstExprValue>(2); | |
| 4698 | ||
| 4699 | ConstExprValue *name_field = &this_val->data.x_struct.fields[0]; | |
| 4700 | ConstExprValue *name_array_val = create_const_str_lit(g, &test_fn_entry->symbol_name); | |
| 4701 | init_const_slice(g, name_field, name_array_val, 0, buf_len(&test_fn_entry->symbol_name), true); | |
| 4702 | ||
| 4703 | ConstExprValue *fn_field = &this_val->data.x_struct.fields[1]; | |
| 4704 | fn_field->type = fn_type; | |
| 4705 | fn_field->special = ConstValSpecialStatic; | |
| 4706 | fn_field->data.x_fn.fn_entry = test_fn_entry; | |
| 4707 | } | |
| 4708 | ||
| 4709 | ConstExprValue *test_fn_slice = create_const_slice(g, test_fn_array, 0, g->test_fns.length, true); | |
| 4710 | ||
| 4711 | g->compile_vars.put(buf_create_from_str("zig_test_fn_slice"), test_fn_slice); | |
| 4712 | g->test_runner_package = create_test_runner_pkg(g); | |
| 4713 | g->test_runner_import = add_special_code(g, g->test_runner_package, "test_runner.zig"); | |
| 4714 | } | |
| 4715 | ||
| 4754 | 4716 | static void gen_root_source(CodeGen *g) { |
| 4755 | 4717 | if (buf_len(&g->root_package->root_src_path) == 0) |
| 4756 | 4718 | return; |
| ... | ... | @@ -4779,7 +4741,7 @@ static void gen_root_source(CodeGen *g) { |
| 4779 | 4741 | if (!g->is_test_build && g->zig_target.os != ZigLLVM_UnknownOS && !g->have_c_main && |
| 4780 | 4742 | ((g->have_pub_main && g->out_type == OutTypeObj) || g->out_type == OutTypeExe)) |
| 4781 | 4743 | { |
| 4782 | g->bootstrap_import = add_special_code(g, create_bootstrap_pkg(g), "bootstrap.zig"); | |
| 4744 | g->bootstrap_import = add_special_code(g, create_bootstrap_pkg(g, g->root_package), "bootstrap.zig"); | |
| 4783 | 4745 | } |
| 4784 | 4746 | if (!g->omit_zigrt) { |
| 4785 | 4747 | g->zigrt_package = create_zigrt_pkg(g); |
| ... | ... | @@ -4793,6 +4755,14 @@ static void gen_root_source(CodeGen *g) { |
| 4793 | 4755 | if (!g->error_during_imports) { |
| 4794 | 4756 | semantic_analyze(g); |
| 4795 | 4757 | } |
| 4758 | if (g->is_test_build) { | |
| 4759 | create_test_compile_var_and_add_test_runner(g); | |
| 4760 | g->bootstrap_import = add_special_code(g, create_bootstrap_pkg(g, g->test_runner_package), "bootstrap.zig"); | |
| 4761 | ||
| 4762 | if (!g->error_during_imports) { | |
| 4763 | semantic_analyze(g); | |
| 4764 | } | |
| 4765 | } | |
| 4796 | 4766 | |
| 4797 | 4767 | if (g->errors.length == 0) { |
| 4798 | 4768 | if (g->verbose) { |
src/ir.cpp+1-1| ... | ... | @@ -10920,7 +10920,7 @@ static TypeTableEntry *ir_analyze_instruction_import(IrAnalyze *ira, IrInstructi |
| 10920 | 10920 | } |
| 10921 | 10921 | ImportTableEntry *target_import = add_source_file(ira->codegen, target_package, abs_full_path, import_code); |
| 10922 | 10922 | |
| 10923 | scan_decls(ira->codegen, target_import->decls_scope, target_import->root); | |
| 10923 | scan_import(ira->codegen, target_import); | |
| 10924 | 10924 | |
| 10925 | 10925 | ConstExprValue *out_val = ir_build_const_from(ira, &import_instruction->base); |
| 10926 | 10926 | out_val->data.x_import = target_import; |
src/link.cpp-15| ... | ... | @@ -263,11 +263,6 @@ static void construct_linker_job_elf(LinkJob *lj) { |
| 263 | 263 | lj->args.append((const char *)buf_ptr(g->link_objects.at(i))); |
| 264 | 264 | } |
| 265 | 265 | |
| 266 | if (g->is_test_build) { | |
| 267 | Buf *test_runner_o_path = build_o(g, "test_runner"); | |
| 268 | lj->args.append(buf_ptr(test_runner_o_path)); | |
| 269 | } | |
| 270 | ||
| 271 | 266 | if (!g->link_libc && (g->out_type == OutTypeExe || g->out_type == OutTypeLib)) { |
| 272 | 267 | Buf *builtin_o_path = build_o(g, "builtin"); |
| 273 | 268 | lj->args.append(buf_ptr(builtin_o_path)); |
| ... | ... | @@ -408,11 +403,6 @@ static void construct_linker_job_coff(LinkJob *lj) { |
| 408 | 403 | lj->args.append((const char *)buf_ptr(g->link_objects.at(i))); |
| 409 | 404 | } |
| 410 | 405 | |
| 411 | if (g->is_test_build) { | |
| 412 | Buf *test_runner_o_path = build_o(g, "test_runner"); | |
| 413 | lj->args.append(buf_ptr(test_runner_o_path)); | |
| 414 | } | |
| 415 | ||
| 416 | 406 | if (!g->link_libc && (g->out_type == OutTypeExe || g->out_type == OutTypeLib)) { |
| 417 | 407 | Buf *builtin_o_path = build_o(g, "builtin"); |
| 418 | 408 | lj->args.append(buf_ptr(builtin_o_path)); |
| ... | ... | @@ -674,11 +664,6 @@ static void construct_linker_job_macho(LinkJob *lj) { |
| 674 | 664 | lj->args.append((const char *)buf_ptr(g->link_objects.at(i))); |
| 675 | 665 | } |
| 676 | 666 | |
| 677 | if (g->is_test_build) { | |
| 678 | Buf *test_runner_o_path = build_o(g, "test_runner"); | |
| 679 | lj->args.append(buf_ptr(test_runner_o_path)); | |
| 680 | } | |
| 681 | ||
| 682 | 667 | for (size_t i = 0; i < g->link_libs.length; i += 1) { |
| 683 | 668 | Buf *link_lib = g->link_libs.at(i); |
| 684 | 669 | if (buf_eql_str(link_lib, "c")) { |
src/main.cpp+3-3| ... | ... | @@ -558,13 +558,13 @@ int main(int argc, char **argv) { |
| 558 | 558 | codegen_build(g); |
| 559 | 559 | codegen_link(g, out_file); |
| 560 | 560 | if (timing_info) |
| 561 | codegen_print_timing_report(g, stderr); | |
| 561 | codegen_print_timing_report(g, stdout); | |
| 562 | 562 | return EXIT_SUCCESS; |
| 563 | 563 | } else if (cmd == CmdParseH) { |
| 564 | 564 | codegen_parseh(g, in_file_buf); |
| 565 | 565 | ast_render_decls(g, stdout, 4, g->root_import); |
| 566 | 566 | if (timing_info) |
| 567 | codegen_print_timing_report(g, stderr); | |
| 567 | codegen_print_timing_report(g, stdout); | |
| 568 | 568 | return EXIT_SUCCESS; |
| 569 | 569 | } else if (cmd == CmdTest) { |
| 570 | 570 | codegen_build(g); |
| ... | ... | @@ -576,7 +576,7 @@ int main(int argc, char **argv) { |
| 576 | 576 | fprintf(stderr, "\nTests failed. Use the following command to reproduce the failure:\n"); |
| 577 | 577 | fprintf(stderr, "./test\n"); |
| 578 | 578 | } else if (timing_info) { |
| 579 | codegen_print_timing_report(g, stderr); | |
| 579 | codegen_print_timing_report(g, stdout); | |
| 580 | 580 | } |
| 581 | 581 | return (term.how == TerminationIdClean) ? term.code : -1; |
| 582 | 582 | } else { |
std/index.zig+21| ... | ... | @@ -16,3 +16,24 @@ pub const os = @import("os/index.zig"); |
| 16 | 16 | pub const rand = @import("rand.zig"); |
| 17 | 17 | pub const sort = @import("sort.zig"); |
| 18 | 18 | pub const target = @import("target.zig"); |
| 19 | ||
| 20 | test "std" { | |
| 21 | // run tests from these | |
| 22 | _ = @import("base64.zig"); | |
| 23 | _ = @import("buffer.zig"); | |
| 24 | _ = @import("build.zig"); | |
| 25 | _ = @import("c/index.zig"); | |
| 26 | _ = @import("cstr.zig"); | |
| 27 | _ = @import("debug.zig"); | |
| 28 | _ = @import("fmt.zig"); | |
| 29 | _ = @import("hash_map.zig"); | |
| 30 | _ = @import("io.zig"); | |
| 31 | _ = @import("list.zig"); | |
| 32 | _ = @import("math.zig"); | |
| 33 | _ = @import("mem.zig"); | |
| 34 | _ = @import("net.zig"); | |
| 35 | _ = @import("os/index.zig"); | |
| 36 | _ = @import("rand.zig"); | |
| 37 | _ = @import("sort.zig"); | |
| 38 | _ = @import("target.zig"); | |
| 39 | } |
std/special/test_runner.zig+4-10| ... | ... | @@ -1,17 +1,11 @@ |
| 1 | 1 | const io = @import("std").io; |
| 2 | ||
| 3 | const TestFn = struct { | |
| 4 | name: []u8, | |
| 5 | func: extern fn(), | |
| 6 | }; | |
| 7 | ||
| 8 | extern var zig_test_fn_list: []TestFn; | |
| 2 | const test_fn_list = @compileVar("zig_test_fn_slice"); | |
| 9 | 3 | |
| 10 | 4 | pub fn main() -> %void { |
| 11 | for (zig_test_fn_list) |testFn, i| { | |
| 12 | %%io.stderr.printf("Test {}/{} {}...", i + 1, zig_test_fn_list.len, testFn.name); | |
| 5 | for (test_fn_list) |test_fn, i| { | |
| 6 | %%io.stderr.printf("Test {}/{} {}...", i + 1, test_fn_list.len, test_fn.name); | |
| 13 | 7 | |
| 14 | testFn.func(); | |
| 8 | test_fn.func(); | |
| 15 | 9 | |
| 16 | 10 | %%io.stderr.printf("OK\n"); |
| 17 | 11 | } |