authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-04-27 16:15:41-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-04-27 16:19:20-04:00
log7e11ef79d67d000675e90ddf93fdb78d71cc695d
tree1a6bbe0cd8d5f8f24fd997341ced1e11b444b059
parent7b0542d08b7e8e5ccbe81f495d641305b3b8a264

zig test no longer requires a separate test_runner.o file

See #298

10 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,6 +29,9 @@ rules in written English are subject to naming conventions just like any other
29word. Even acronyms that are only 2 letters long are subject to these29word. Even acronyms that are only 2 letters long are subject to these
30conventions.30conventions.
3131
32These are general rules of thumb; if it makes sense to do something different,
33do what makes sense.
34
32Examples:35Examples:
3336
34```zig37```zig
src/all_types.hpp+3-1
...@@ -1095,6 +1095,7 @@ struct ImportTableEntry {...@@ -1095,6 +1095,7 @@ struct ImportTableEntry {
1095 ScopeDecls *decls_scope;1095 ScopeDecls *decls_scope;
1096 AstNode *c_import_node;1096 AstNode *c_import_node;
1097 bool any_imports_failed;1097 bool any_imports_failed;
1098 bool scanned;
10981099
1099 ZigList<AstNode *> use_decls;1100 ZigList<AstNode *> use_decls;
1100};1101};
...@@ -1398,6 +1399,7 @@ struct CodeGen {...@@ -1398,6 +1399,7 @@ struct CodeGen {
1398 PackageTableEntry *root_package;1399 PackageTableEntry *root_package;
1399 PackageTableEntry *std_package;1400 PackageTableEntry *std_package;
1400 PackageTableEntry *zigrt_package;1401 PackageTableEntry *zigrt_package;
1402 PackageTableEntry *test_runner_package;
1401 Buf *root_out_name;1403 Buf *root_out_name;
1402 bool windows_subsystem_windows;1404 bool windows_subsystem_windows;
1403 bool windows_subsystem_console;1405 bool windows_subsystem_console;
...@@ -1451,7 +1453,7 @@ struct CodeGen {...@@ -1451,7 +1453,7 @@ struct CodeGen {
1451 size_t clang_argv_len;1453 size_t clang_argv_len;
1452 ZigList<const char *> lib_dirs;1454 ZigList<const char *> lib_dirs;
14531455
1454 uint32_t test_fn_count;1456 ZigList<FnTableEntry *> test_fns;
1455 TypeTableEntry *test_fn_type;1457 TypeTableEntry *test_fn_type;
14561458
1457 bool each_lib_rpath;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,6 +1413,71 @@ static bool type_allowed_in_packed_struct(TypeTableEntry *type_entry) {
1413 zig_unreachable();1413 zig_unreachable();
1414}1414}
14151415
1416TypeTableEntry *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
1416static void resolve_struct_type(CodeGen *g, TypeTableEntry *struct_type) {1481static void resolve_struct_type(CodeGen *g, TypeTableEntry *struct_type) {
1417 // if you change the logic of this function likely you must make a similar change in1482 // if you change the logic of this function likely you must make a similar change in
1418 // parseh.cpp1483 // parseh.cpp
...@@ -1823,7 +1888,7 @@ static void typecheck_panic_fn(CodeGen *g, FnTableEntry *panic_fn) {...@@ -1823,7 +1888,7 @@ static void typecheck_panic_fn(CodeGen *g, FnTableEntry *panic_fn) {
1823 }1888 }
1824}1889}
18251890
1826static TypeTableEntry *get_test_fn_type(CodeGen *g) {1891TypeTableEntry *get_test_fn_type(CodeGen *g) {
1827 if (g->test_fn_type)1892 if (g->test_fn_type)
1828 return g->test_fn_type;1893 return g->test_fn_type;
18291894
...@@ -1875,7 +1940,10 @@ static void resolve_decl_fn(CodeGen *g, TldFn *tld_fn) {...@@ -1875,7 +1940,10 @@ static void resolve_decl_fn(CodeGen *g, TldFn *tld_fn) {
1875 if (fn_def_node)1940 if (fn_def_node)
1876 g->fn_defs.append(fn_table_entry);1941 g->fn_defs.append(fn_table_entry);
18771942
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 if (buf_eql_str(&fn_table_entry->symbol_name, "main")) {1947 if (buf_eql_str(&fn_table_entry->symbol_name, "main")) {
1880 g->main_fn = fn_table_entry;1948 g->main_fn = fn_table_entry;
18811949
...@@ -1909,10 +1977,10 @@ static void resolve_decl_fn(CodeGen *g, TldFn *tld_fn) {...@@ -1909,10 +1977,10 @@ static void resolve_decl_fn(CodeGen *g, TldFn *tld_fn) {
1909 fn_table_entry->type_entry = get_test_fn_type(g);1977 fn_table_entry->type_entry = get_test_fn_type(g);
1910 fn_table_entry->body_node = source_node->data.test_decl.body;1978 fn_table_entry->body_node = source_node->data.test_decl.body;
1911 fn_table_entry->is_test = true;1979 fn_table_entry->is_test = true;
1912 g->test_fn_count += 1;
19131980
1914 g->fn_protos.append(fn_table_entry);1981 g->fn_protos.append(fn_table_entry);
1915 g->fn_defs.append(fn_table_entry);1982 g->fn_defs.append(fn_table_entry);
1983 g->test_fns.append(fn_table_entry);
19161984
1917 } else {1985 } else {
1918 zig_unreachable();1986 zig_unreachable();
...@@ -1926,7 +1994,7 @@ static void resolve_decl_comptime(CodeGen *g, TldCompTime *tld_comptime) {...@@ -1926,7 +1994,7 @@ static void resolve_decl_comptime(CodeGen *g, TldCompTime *tld_comptime) {
1926}1994}
19271995
1928static void add_top_level_decl(CodeGen *g, ScopeDecls *decls_scope, Tld *tld) {1996static 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 g->resolve_queue.append(tld);1998 g->resolve_queue.append(tld);
1931 }1999 }
19322000
...@@ -2932,11 +3000,17 @@ ImportTableEntry *add_source_file(CodeGen *g, PackageTableEntry *package, Buf *a...@@ -2932,11 +3000,17 @@ ImportTableEntry *add_source_file(CodeGen *g, PackageTableEntry *package, Buf *a
2932 return import_entry;3000 return import_entry;
2933}3001}
29343002
3003void 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}
29353009
2936void semantic_analyze(CodeGen *g) {3010void semantic_analyze(CodeGen *g) {
2937 for (; g->import_queue_index < g->import_queue.length; g->import_queue_index += 1) {3011 for (; g->import_queue_index < g->import_queue.length; g->import_queue_index += 1) {
2938 ImportTableEntry *import = g->import_queue.at(g->import_queue_index);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 }
29413015
2942 for (; g->use_queue_index < g->use_queue.length; g->use_queue_index += 1) {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,6 +33,9 @@ TypeTableEntry *get_smallest_unsigned_int_type(CodeGen *g, uint64_t x);
33TypeTableEntry *get_error_type(CodeGen *g, TypeTableEntry *child_type);33TypeTableEntry *get_error_type(CodeGen *g, TypeTableEntry *child_type);
34TypeTableEntry *get_bound_fn_type(CodeGen *g, FnTableEntry *fn_entry);34TypeTableEntry *get_bound_fn_type(CodeGen *g, FnTableEntry *fn_entry);
35TypeTableEntry *get_opaque_type(CodeGen *g, Scope *scope, AstNode *source_node, const char *name);35TypeTableEntry *get_opaque_type(CodeGen *g, Scope *scope, AstNode *source_node, const char *name);
36TypeTableEntry *get_struct_type(CodeGen *g, const char *type_name, const char *field_names[],
37 TypeTableEntry *field_types[], size_t field_count);
38TypeTableEntry *get_test_fn_type(CodeGen *g);
36bool handle_is_ptr(TypeTableEntry *type_entry);39bool handle_is_ptr(TypeTableEntry *type_entry);
37void find_libc_include_path(CodeGen *g);40void find_libc_include_path(CodeGen *g);
38void find_libc_lib_path(CodeGen *g);41void find_libc_lib_path(CodeGen *g);
...@@ -60,6 +63,7 @@ ScopeDecls *get_container_scope(TypeTableEntry *type_entry);...@@ -60,6 +63,7 @@ ScopeDecls *get_container_scope(TypeTableEntry *type_entry);
60TypeEnumField *find_enum_type_field(TypeTableEntry *enum_type, Buf *name);63TypeEnumField *find_enum_type_field(TypeTableEntry *enum_type, Buf *name);
61bool is_container_ref(TypeTableEntry *type_entry);64bool is_container_ref(TypeTableEntry *type_entry);
62void scan_decls(CodeGen *g, ScopeDecls *decls_scope, AstNode *node);65void scan_decls(CodeGen *g, ScopeDecls *decls_scope, AstNode *node);
66void scan_import(CodeGen *g, ImportTableEntry *import);
63void preview_use_decl(CodeGen *g, AstNode *node);67void preview_use_decl(CodeGen *g, AstNode *node);
64void resolve_use_decl(CodeGen *g, AstNode *node);68void resolve_use_decl(CodeGen *g, AstNode *node);
65FnTableEntry *scope_fn_entry(Scope *scope);69FnTableEntry *scope_fn_entry(Scope *scope);
src/codegen.cpp+67-97
...@@ -2906,7 +2906,7 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,...@@ -2906,7 +2906,7 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
2906 case IrInstructionIdDeclRef:2906 case IrInstructionIdDeclRef:
2907 case IrInstructionIdSwitchVar:2907 case IrInstructionIdSwitchVar:
2908 case IrInstructionIdSetFnRefInline:2908 case IrInstructionIdSetFnRefInline:
2909 case IrInstructionIdOffsetOf: 2909 case IrInstructionIdOffsetOf:
2910 zig_unreachable();2910 zig_unreachable();
2911 case IrInstructionIdReturn:2911 case IrInstructionIdReturn:
2912 return ir_render_return(g, executable, (IrInstructionReturn *)instruction);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,7 +3087,7 @@ static LLVMValueRef gen_const_ptr_struct_recursive(CodeGen *g, ConstExprValue *s
3087 return LLVMConstInBoundsGEP(base_ptr, indices, 2);3087 return LLVMConstInBoundsGEP(base_ptr, indices, 2);
3088}3088}
30893089
3090static LLVMValueRef pack_const_int(CodeGen *g, LLVMTypeRef big_int_type_ref, ConstExprValue *const_val) { 3090static LLVMValueRef pack_const_int(CodeGen *g, LLVMTypeRef big_int_type_ref, ConstExprValue *const_val) {
3091 switch (const_val->special) {3091 switch (const_val->special) {
3092 case ConstValSpecialRuntime:3092 case ConstValSpecialRuntime:
3093 zig_unreachable();3093 zig_unreachable();
...@@ -3501,50 +3501,6 @@ static void delete_unused_builtin_fns(CodeGen *g) {...@@ -3501,50 +3501,6 @@ static void delete_unused_builtin_fns(CodeGen *g) {
3501 }3501 }
3502}3502}
35033503
3504static 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
3522static 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
3548static void generate_error_name_table(CodeGen *g) {3504static void generate_error_name_table(CodeGen *g) {
3549 if (g->err_name_table != nullptr || !g->generate_error_name_table || g->error_decls.length == 1) {3505 if (g->err_name_table != nullptr || !g->generate_error_name_table || g->error_decls.length == 1) {
3550 return;3506 return;
...@@ -3740,17 +3696,9 @@ static void do_code_gen(CodeGen *g) {...@@ -3740,17 +3696,9 @@ static void do_code_gen(CodeGen *g) {
3740 var->value_ref = global_value;3696 var->value_ref = global_value;
3741 }3697 }
37423698
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 // Generate function prototypes3699 // Generate function prototypes
3750 for (size_t fn_proto_i = 0; fn_proto_i < g->fn_protos.length; fn_proto_i += 1) {3700 for (size_t fn_proto_i = 0; fn_proto_i < g->fn_protos.length; fn_proto_i += 1) {
3751 FnTableEntry *fn_table_entry = g->fn_protos.at(fn_proto_i);3701 FnTableEntry *fn_table_entry = g->fn_protos.at(fn_proto_i);
3752 if (should_skip_fn_codegen(g, fn_table_entry))
3753 continue;
37543702
3755 TypeTableEntry *fn_type = fn_table_entry->type_entry;3703 TypeTableEntry *fn_type = fn_table_entry->type_entry;
3756 FnTypeId *fn_type_id = &fn_type->data.fn.fn_type_id;3704 FnTypeId *fn_type_id = &fn_type->data.fn.fn_type_id;
...@@ -3797,51 +3745,11 @@ static void do_code_gen(CodeGen *g) {...@@ -3797,51 +3745,11 @@ static void do_code_gen(CodeGen *g) {
3797 addLLVMArgAttr(fn_val, (unsigned)gen_index, "byval");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 }
38393749
3840 // Generate function definitions.3750 // Generate function definitions.
3841 for (size_t fn_i = 0; fn_i < g->fn_defs.length; fn_i += 1) {3751 for (size_t fn_i = 0; fn_i < g->fn_defs.length; fn_i += 1) {
3842 FnTableEntry *fn_table_entry = g->fn_defs.at(fn_i);3752 FnTableEntry *fn_table_entry = g->fn_defs.at(fn_i);
3843 if (should_skip_fn_codegen(g, fn_table_entry))
3844 continue;
38453753
3846 LLVMValueRef fn = fn_llvm_value(g, fn_table_entry);3754 LLVMValueRef fn = fn_llvm_value(g, fn_table_entry);
3847 g->cur_fn = fn_table_entry;3755 g->cur_fn = fn_table_entry;
...@@ -4737,10 +4645,16 @@ static ImportTableEntry *add_special_code(CodeGen *g, PackageTableEntry *package...@@ -4737,10 +4645,16 @@ static ImportTableEntry *add_special_code(CodeGen *g, PackageTableEntry *package
4737 return add_source_file(g, package, abs_full_path, import_code);4645 return add_source_file(g, package, abs_full_path, import_code);
4738}4646}
47394647
4740static PackageTableEntry *create_bootstrap_pkg(CodeGen *g) {4648static PackageTableEntry *create_bootstrap_pkg(CodeGen *g, PackageTableEntry *pkg_with_main) {
4741 PackageTableEntry *package = new_package(buf_ptr(g->zig_std_special_dir), "");4649 PackageTableEntry *package = new_package(buf_ptr(g->zig_std_special_dir), "");
4742 package->package_table.put(buf_create_from_str("std"), g->std_package);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
4655static 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 return package;4658 return package;
4745}4659}
47464660
...@@ -4751,6 +4665,54 @@ static PackageTableEntry *create_zigrt_pkg(CodeGen *g) {...@@ -4751,6 +4665,54 @@ static PackageTableEntry *create_zigrt_pkg(CodeGen *g) {
4751 return package;4665 return package;
4752}4666}
47534667
4668static 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
4754static void gen_root_source(CodeGen *g) {4716static void gen_root_source(CodeGen *g) {
4755 if (buf_len(&g->root_package->root_src_path) == 0)4717 if (buf_len(&g->root_package->root_src_path) == 0)
4756 return;4718 return;
...@@ -4779,7 +4741,7 @@ static void gen_root_source(CodeGen *g) {...@@ -4779,7 +4741,7 @@ static void gen_root_source(CodeGen *g) {
4779 if (!g->is_test_build && g->zig_target.os != ZigLLVM_UnknownOS && !g->have_c_main &&4741 if (!g->is_test_build && g->zig_target.os != ZigLLVM_UnknownOS && !g->have_c_main &&
4780 ((g->have_pub_main && g->out_type == OutTypeObj) || g->out_type == OutTypeExe))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 if (!g->omit_zigrt) {4746 if (!g->omit_zigrt) {
4785 g->zigrt_package = create_zigrt_pkg(g);4747 g->zigrt_package = create_zigrt_pkg(g);
...@@ -4793,6 +4755,14 @@ static void gen_root_source(CodeGen *g) {...@@ -4793,6 +4755,14 @@ static void gen_root_source(CodeGen *g) {
4793 if (!g->error_during_imports) {4755 if (!g->error_during_imports) {
4794 semantic_analyze(g);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 }
47964766
4797 if (g->errors.length == 0) {4767 if (g->errors.length == 0) {
4798 if (g->verbose) {4768 if (g->verbose) {
src/ir.cpp+1-1
...@@ -10920,7 +10920,7 @@ static TypeTableEntry *ir_analyze_instruction_import(IrAnalyze *ira, IrInstructi...@@ -10920,7 +10920,7 @@ static TypeTableEntry *ir_analyze_instruction_import(IrAnalyze *ira, IrInstructi
10920 }10920 }
10921 ImportTableEntry *target_import = add_source_file(ira->codegen, target_package, abs_full_path, import_code);10921 ImportTableEntry *target_import = add_source_file(ira->codegen, target_package, abs_full_path, import_code);
1092210922
10923 scan_decls(ira->codegen, target_import->decls_scope, target_import->root);10923 scan_import(ira->codegen, target_import);
1092410924
10925 ConstExprValue *out_val = ir_build_const_from(ira, &import_instruction->base);10925 ConstExprValue *out_val = ir_build_const_from(ira, &import_instruction->base);
10926 out_val->data.x_import = target_import;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,11 +263,6 @@ static void construct_linker_job_elf(LinkJob *lj) {
263 lj->args.append((const char *)buf_ptr(g->link_objects.at(i)));263 lj->args.append((const char *)buf_ptr(g->link_objects.at(i)));
264 }264 }
265265
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 if (!g->link_libc && (g->out_type == OutTypeExe || g->out_type == OutTypeLib)) {266 if (!g->link_libc && (g->out_type == OutTypeExe || g->out_type == OutTypeLib)) {
272 Buf *builtin_o_path = build_o(g, "builtin");267 Buf *builtin_o_path = build_o(g, "builtin");
273 lj->args.append(buf_ptr(builtin_o_path));268 lj->args.append(buf_ptr(builtin_o_path));
...@@ -408,11 +403,6 @@ static void construct_linker_job_coff(LinkJob *lj) {...@@ -408,11 +403,6 @@ static void construct_linker_job_coff(LinkJob *lj) {
408 lj->args.append((const char *)buf_ptr(g->link_objects.at(i)));403 lj->args.append((const char *)buf_ptr(g->link_objects.at(i)));
409 }404 }
410405
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 if (!g->link_libc && (g->out_type == OutTypeExe || g->out_type == OutTypeLib)) {406 if (!g->link_libc && (g->out_type == OutTypeExe || g->out_type == OutTypeLib)) {
417 Buf *builtin_o_path = build_o(g, "builtin");407 Buf *builtin_o_path = build_o(g, "builtin");
418 lj->args.append(buf_ptr(builtin_o_path));408 lj->args.append(buf_ptr(builtin_o_path));
...@@ -674,11 +664,6 @@ static void construct_linker_job_macho(LinkJob *lj) {...@@ -674,11 +664,6 @@ static void construct_linker_job_macho(LinkJob *lj) {
674 lj->args.append((const char *)buf_ptr(g->link_objects.at(i)));664 lj->args.append((const char *)buf_ptr(g->link_objects.at(i)));
675 }665 }
676666
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 for (size_t i = 0; i < g->link_libs.length; i += 1) {667 for (size_t i = 0; i < g->link_libs.length; i += 1) {
683 Buf *link_lib = g->link_libs.at(i);668 Buf *link_lib = g->link_libs.at(i);
684 if (buf_eql_str(link_lib, "c")) {669 if (buf_eql_str(link_lib, "c")) {
src/main.cpp+3-3
...@@ -558,13 +558,13 @@ int main(int argc, char **argv) {...@@ -558,13 +558,13 @@ int main(int argc, char **argv) {
558 codegen_build(g);558 codegen_build(g);
559 codegen_link(g, out_file);559 codegen_link(g, out_file);
560 if (timing_info)560 if (timing_info)
561 codegen_print_timing_report(g, stderr);561 codegen_print_timing_report(g, stdout);
562 return EXIT_SUCCESS;562 return EXIT_SUCCESS;
563 } else if (cmd == CmdParseH) {563 } else if (cmd == CmdParseH) {
564 codegen_parseh(g, in_file_buf);564 codegen_parseh(g, in_file_buf);
565 ast_render_decls(g, stdout, 4, g->root_import);565 ast_render_decls(g, stdout, 4, g->root_import);
566 if (timing_info)566 if (timing_info)
567 codegen_print_timing_report(g, stderr);567 codegen_print_timing_report(g, stdout);
568 return EXIT_SUCCESS;568 return EXIT_SUCCESS;
569 } else if (cmd == CmdTest) {569 } else if (cmd == CmdTest) {
570 codegen_build(g);570 codegen_build(g);
...@@ -576,7 +576,7 @@ int main(int argc, char **argv) {...@@ -576,7 +576,7 @@ int main(int argc, char **argv) {
576 fprintf(stderr, "\nTests failed. Use the following command to reproduce the failure:\n");576 fprintf(stderr, "\nTests failed. Use the following command to reproduce the failure:\n");
577 fprintf(stderr, "./test\n");577 fprintf(stderr, "./test\n");
578 } else if (timing_info) {578 } else if (timing_info) {
579 codegen_print_timing_report(g, stderr);579 codegen_print_timing_report(g, stdout);
580 }580 }
581 return (term.how == TerminationIdClean) ? term.code : -1;581 return (term.how == TerminationIdClean) ? term.code : -1;
582 } else {582 } else {
std/index.zig+21
...@@ -16,3 +16,24 @@ pub const os = @import("os/index.zig");...@@ -16,3 +16,24 @@ pub const os = @import("os/index.zig");
16pub const rand = @import("rand.zig");16pub const rand = @import("rand.zig");
17pub const sort = @import("sort.zig");17pub const sort = @import("sort.zig");
18pub const target = @import("target.zig");18pub const target = @import("target.zig");
19
20test "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,17 +1,11 @@
1const io = @import("std").io;1const io = @import("std").io;
22const test_fn_list = @compileVar("zig_test_fn_slice");
3const TestFn = struct {
4 name: []u8,
5 func: extern fn(),
6};
7
8extern var zig_test_fn_list: []TestFn;
93
10pub fn main() -> %void {4pub fn main() -> %void {
11 for (zig_test_fn_list) |testFn, i| {5 for (test_fn_list) |test_fn, i| {
12 %%io.stderr.printf("Test {}/{} {}...", i + 1, zig_test_fn_list.len, testFn.name);6 %%io.stderr.printf("Test {}/{} {}...", i + 1, test_fn_list.len, test_fn.name);
137
14 testFn.func();8 test_fn.func();
159
16 %%io.stderr.printf("OK\n");10 %%io.stderr.printf("OK\n");
17 }11 }