authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-04-05 07:46:50-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-04-05 07:49:40-04:00
logd65cd73a8bfe39349be09a5f76f8477f3e3210b9
treeb97b4c6ab21e19acd276cdf38aec5ad1cb2db268
parent8c10b6dcbddc58b488e399690e8ddefb4bafb816

add support to use zig as a linker driver

closes #243 I also added --grep to ./run_tests if you want to single out some specific tests

9 files changed, 236 insertions(+), 91 deletions(-)

src/all_types.hpp+1
...@@ -1462,6 +1462,7 @@ struct CodeGen {...@@ -1462,6 +1462,7 @@ struct CodeGen {
1462 ConstExprValue panic_msg_vals[PanicMsgIdCount];1462 ConstExprValue panic_msg_vals[PanicMsgIdCount];
14631463
1464 Buf global_asm;1464 Buf global_asm;
1465 ZigList<Buf *> link_objects;
1465};1466};
14661467
1467enum VarLinkage {1468enum VarLinkage {
src/codegen.cpp+16
...@@ -3743,6 +3743,18 @@ static void do_code_gen(CodeGen *g) {...@@ -3743,6 +3743,18 @@ static void do_code_gen(CodeGen *g) {
3743 char *error = nullptr;3743 char *error = nullptr;
3744 LLVMVerifyModule(g->module, LLVMAbortProcessAction, &error);3744 LLVMVerifyModule(g->module, LLVMAbortProcessAction, &error);
3745#endif3745#endif
3746
3747 char *err_msg = nullptr;
3748 Buf *out_file_o = buf_create_from_buf(g->root_out_name);
3749 const char *o_ext = target_o_file_ext(&g->zig_target);
3750 buf_append_str(out_file_o, o_ext);
3751 if (LLVMTargetMachineEmitToFile(g->target_machine, g->module, buf_ptr(out_file_o),
3752 LLVMObjectFile, &err_msg))
3753 {
3754 zig_panic("unable to write object file: %s", err_msg);
3755 }
3756
3757 g->link_objects.append(out_file_o);
3746}3758}
37473759
3748static const size_t int_sizes_in_bits[] = {3760static const size_t int_sizes_in_bits[] = {
...@@ -4550,6 +4562,10 @@ void codegen_add_root_assembly(CodeGen *g, Buf *src_dir, Buf *src_basename, Buf...@@ -4550,6 +4562,10 @@ void codegen_add_root_assembly(CodeGen *g, Buf *src_dir, Buf *src_basename, Buf
4550 do_code_gen(g);4562 do_code_gen(g);
4551}4563}
45524564
4565void codegen_add_object(CodeGen *g, Buf *object_path) {
4566 g->link_objects.append(object_path);
4567}
4568
45534569
4554static const char *c_int_type_names[] = {4570static const char *c_int_type_names[] = {
4555 [CIntTypeShort] = "short",4571 [CIntTypeShort] = "short",
src/codegen.hpp+1
...@@ -48,6 +48,7 @@ void codegen_set_omit_zigrt(CodeGen *g, bool omit_zigrt);...@@ -48,6 +48,7 @@ void codegen_set_omit_zigrt(CodeGen *g, bool omit_zigrt);
48PackageTableEntry *new_package(const char *root_src_dir, const char *root_src_path);48PackageTableEntry *new_package(const char *root_src_dir, const char *root_src_path);
49void codegen_add_root_code(CodeGen *g, Buf *source_dir, Buf *source_basename, Buf *source_code);49void codegen_add_root_code(CodeGen *g, Buf *source_dir, Buf *source_basename, Buf *source_code);
50void codegen_add_root_assembly(CodeGen *g, Buf *source_dir, Buf *source_basename, Buf *source_code);50void codegen_add_root_assembly(CodeGen *g, Buf *source_dir, Buf *source_basename, Buf *source_code);
51void codegen_add_object(CodeGen *g, Buf *object_path);
5152
52void codegen_parseh(CodeGen *g, Buf *src_dirname, Buf *src_basename, Buf *source_code);53void codegen_parseh(CodeGen *g, Buf *src_dirname, Buf *src_basename, Buf *source_code);
53void codegen_render_ast(CodeGen *g, FILE *f, int indent_size);54void codegen_render_ast(CodeGen *g, FILE *f, int indent_size);
src/link.cpp+10-26
...@@ -16,7 +16,6 @@ struct LinkJob {...@@ -16,7 +16,6 @@ struct LinkJob {
16 Buf out_file;16 Buf out_file;
17 ZigList<const char *> args;17 ZigList<const char *> args;
18 bool link_in_crt;18 bool link_in_crt;
19 Buf out_file_o;
20 HashMap<Buf *, bool, buf_hash, buf_eql_buf> rpath_table;19 HashMap<Buf *, bool, buf_hash, buf_eql_buf> rpath_table;
21};20};
2221
...@@ -32,14 +31,6 @@ static const char *get_libc_static_file(CodeGen *g, const char *file) {...@@ -32,14 +31,6 @@ static const char *get_libc_static_file(CodeGen *g, const char *file) {
32 return buf_ptr(out_buf);31 return buf_ptr(out_buf);
33}32}
3433
35static const char *get_o_file_extension(CodeGen *g) {
36 if (g->zig_target.env_type == ZigLLVM_MSVC) {
37 return ".obj";
38 } else {
39 return ".o";
40 }
41}
42
43static Buf *build_o(CodeGen *parent_gen, const char *oname) {34static Buf *build_o(CodeGen *parent_gen, const char *oname) {
44 Buf *source_basename = buf_sprintf("%s.zig", oname);35 Buf *source_basename = buf_sprintf("%s.zig", oname);
4536
...@@ -78,7 +69,7 @@ static Buf *build_o(CodeGen *parent_gen, const char *oname) {...@@ -78,7 +69,7 @@ static Buf *build_o(CodeGen *parent_gen, const char *oname) {
78 }69 }
7970
80 codegen_add_root_code(child_gen, parent_gen->zig_std_special_dir, source_basename, &source_code);71 codegen_add_root_code(child_gen, parent_gen->zig_std_special_dir, source_basename, &source_code);
81 const char *o_ext = get_o_file_extension(child_gen);72 const char *o_ext = target_o_file_ext(&child_gen->zig_target);
82 Buf *o_out = buf_sprintf("%s%s", oname, o_ext);73 Buf *o_out = buf_sprintf("%s%s", oname, o_ext);
83 codegen_link(child_gen, buf_ptr(o_out));74 codegen_link(child_gen, buf_ptr(o_out));
8475
...@@ -274,7 +265,9 @@ static void construct_linker_job_elf(LinkJob *lj) {...@@ -274,7 +265,9 @@ static void construct_linker_job_elf(LinkJob *lj) {
274 }265 }
275266
276 // .o files267 // .o files
277 lj->args.append((const char *)buf_ptr(&lj->out_file_o));268 for (size_t i = 0; i < g->link_objects.length; i += 1) {
269 lj->args.append((const char *)buf_ptr(g->link_objects.at(i)));
270 }
278271
279 if (g->is_test_build) {272 if (g->is_test_build) {
280 Buf *test_runner_o_path = build_o(g, "test_runner");273 Buf *test_runner_o_path = build_o(g, "test_runner");
...@@ -417,7 +410,9 @@ static void construct_linker_job_coff(LinkJob *lj) {...@@ -417,7 +410,9 @@ static void construct_linker_job_coff(LinkJob *lj) {
417 lj->args.append(buf_ptr(g->libc_static_lib_dir));410 lj->args.append(buf_ptr(g->libc_static_lib_dir));
418 }411 }
419412
420 lj->args.append((const char *)buf_ptr(&lj->out_file_o));413 for (size_t i = 0; i < g->link_objects.length; i += 1) {
414 lj->args.append((const char *)buf_ptr(g->link_objects.at(i)));
415 }
421416
422 if (g->is_test_build) {417 if (g->is_test_build) {
423 Buf *test_runner_o_path = build_o(g, "test_runner");418 Buf *test_runner_o_path = build_o(g, "test_runner");
...@@ -681,7 +676,9 @@ static void construct_linker_job_macho(LinkJob *lj) {...@@ -681,7 +676,9 @@ static void construct_linker_job_macho(LinkJob *lj) {
681 lj->args.append(lib_dir);676 lj->args.append(lib_dir);
682 }677 }
683678
684 lj->args.append((const char *)buf_ptr(&lj->out_file_o));679 for (size_t i = 0; i < g->link_objects.length; i += 1) {
680 lj->args.append((const char *)buf_ptr(g->link_objects.at(i)));
681 }
685682
686 if (g->is_test_build) {683 if (g->is_test_build) {
687 Buf *test_runner_o_path = build_o(g, "test_runner");684 Buf *test_runner_o_path = build_o(g, "test_runner");
...@@ -776,19 +773,6 @@ void codegen_link(CodeGen *g, const char *out_file) {...@@ -776,19 +773,6 @@ void codegen_link(CodeGen *g, const char *out_file) {
776 buf_append_str(&lj.out_file, get_exe_file_extension(g));773 buf_append_str(&lj.out_file, get_exe_file_extension(g));
777 }774 }
778 }775 }
779 buf_init_from_buf(&lj.out_file_o, &lj.out_file);
780
781 if (g->out_type != OutTypeObj || !override_out_file) {
782 const char *o_ext = get_o_file_extension(g);
783 buf_append_str(&lj.out_file_o, o_ext);
784 }
785
786 char *err_msg = nullptr;
787 if (LLVMTargetMachineEmitToFile(g->target_machine, g->module, buf_ptr(&lj.out_file_o),
788 LLVMObjectFile, &err_msg))
789 {
790 zig_panic("unable to write object file: %s", err_msg);
791 }
792776
793 if (g->out_type == OutTypeObj) {777 if (g->out_type == OutTypeObj) {
794 if (g->want_h_file) {778 if (g->want_h_file) {
src/main.cpp+62-22
...@@ -24,6 +24,8 @@ static int usage(const char *arg0) {...@@ -24,6 +24,8 @@ static int usage(const char *arg0) {
24 " build_exe [source] create executable from source\n"24 " build_exe [source] create executable from source\n"
25 " build_lib [source] create library from source\n"25 " build_lib [source] create library from source\n"
26 " build_obj [source] create object from source\n"26 " build_obj [source] create object from source\n"
27 " link_exe [objects] create executable from objects\n"
28 " link_lib [objects] create library from objects\n"
27 " parseh [source] convert a c header file to zig extern declarations\n"29 " parseh [source] convert a c header file to zig extern declarations\n"
28 " targets list available compilation targets\n"30 " targets list available compilation targets\n"
29 " test [source] create and run a test build\n"31 " test [source] create and run a test build\n"
...@@ -108,6 +110,7 @@ enum Cmd {...@@ -108,6 +110,7 @@ enum Cmd {
108 CmdParseH,110 CmdParseH,
109 CmdTargets,111 CmdTargets,
110 CmdAsm,112 CmdAsm,
113 CmdLink,
111};114};
112115
113int main(int argc, char **argv) {116int main(int argc, char **argv) {
...@@ -147,6 +150,7 @@ int main(int argc, char **argv) {...@@ -147,6 +150,7 @@ int main(int argc, char **argv) {
147 const char *linker_script = nullptr;150 const char *linker_script = nullptr;
148 ZigList<const char *> rpath_list = {0};151 ZigList<const char *> rpath_list = {0};
149 bool each_lib_rpath = false;152 bool each_lib_rpath = false;
153 ZigList<const char *> objects = {0};
150154
151 if (argc >= 2 && strcmp(argv[1], "build") == 0) {155 if (argc >= 2 && strcmp(argv[1], "build") == 0) {
152 const char *zig_exe_path = arg0;156 const char *zig_exe_path = arg0;
...@@ -304,6 +308,12 @@ int main(int argc, char **argv) {...@@ -304,6 +308,12 @@ int main(int argc, char **argv) {
304 } else if (strcmp(arg, "build_lib") == 0) {308 } else if (strcmp(arg, "build_lib") == 0) {
305 cmd = CmdBuild;309 cmd = CmdBuild;
306 out_type = OutTypeLib;310 out_type = OutTypeLib;
311 } else if (strcmp(arg, "link_lib") == 0) {
312 cmd = CmdLink;
313 out_type = OutTypeLib;
314 } else if (strcmp(arg, "link_exe") == 0) {
315 cmd = CmdLink;
316 out_type = OutTypeExe;
307 } else if (strcmp(arg, "version") == 0) {317 } else if (strcmp(arg, "version") == 0) {
308 cmd = CmdVersion;318 cmd = CmdVersion;
309 } else if (strcmp(arg, "parseh") == 0) {319 } else if (strcmp(arg, "parseh") == 0) {
...@@ -330,6 +340,9 @@ int main(int argc, char **argv) {...@@ -330,6 +340,9 @@ int main(int argc, char **argv) {
330 return usage(arg0);340 return usage(arg0);
331 }341 }
332 break;342 break;
343 case CmdLink:
344 objects.append(arg);
345 break;
333 case CmdVersion:346 case CmdVersion:
334 case CmdTargets:347 case CmdTargets:
335 return usage(arg0);348 return usage(arg0);
...@@ -344,11 +357,24 @@ int main(int argc, char **argv) {...@@ -344,11 +357,24 @@ int main(int argc, char **argv) {
344 case CmdParseH:357 case CmdParseH:
345 case CmdTest:358 case CmdTest:
346 case CmdAsm:359 case CmdAsm:
360 case CmdLink:
347 {361 {
348 if (!in_file)362 bool one_source_input = (cmd == CmdBuild || cmd == CmdParseH || cmd == CmdTest || cmd == CmdAsm);
349 return usage(arg0);363 if (one_source_input) {
364 if (!in_file) {
365 fprintf(stderr, "Expected source file argument.\n");
366 return usage(arg0);
367 }
368 } else if (cmd == CmdLink) {
369 if (objects.length == 0) {
370 fprintf(stderr, "Expected one or more object arguments.\n");
371 return usage(arg0);
372 }
373 } else {
374 zig_unreachable();
375 }
350376
351 assert(cmd != CmdBuild || out_type != OutTypeUnknown);377 assert((cmd != CmdBuild && cmd != CmdLink) || out_type != OutTypeUnknown);
352378
353 init_all_targets();379 init_all_targets();
354380
...@@ -379,10 +405,9 @@ int main(int argc, char **argv) {...@@ -379,10 +405,9 @@ int main(int argc, char **argv) {
379 }405 }
380 }406 }
381407
382 bool need_name = (cmd == CmdBuild || cmd == CmdAsm);408 bool need_name = (cmd == CmdBuild || cmd == CmdAsm || cmd == CmdLink);
383409
384 Buf in_file_buf = BUF_INIT;410 Buf in_file_buf = BUF_INIT;
385 buf_init_from_str(&in_file_buf, in_file);
386411
387 Buf root_source_dir = BUF_INIT;412 Buf root_source_dir = BUF_INIT;
388 Buf root_source_code = BUF_INIT;413 Buf root_source_code = BUF_INIT;
...@@ -390,26 +415,35 @@ int main(int argc, char **argv) {...@@ -390,26 +415,35 @@ int main(int argc, char **argv) {
390415
391 Buf *buf_out_name = (cmd == CmdTest) ? buf_create_from_str("test") :416 Buf *buf_out_name = (cmd == CmdTest) ? buf_create_from_str("test") :
392 (out_name == nullptr) ? nullptr : buf_create_from_str(out_name);417 (out_name == nullptr) ? nullptr : buf_create_from_str(out_name);
393 if (buf_eql_str(&in_file_buf, "-")) {
394 os_get_cwd(&root_source_dir);
395 if ((err = os_fetch_file(stdin, &root_source_code))) {
396 fprintf(stderr, "unable to read stdin: %s\n", err_str(err));
397 return 1;
398 }
399 buf_init_from_str(&root_source_name, "");
400418
401 } else {419 if (one_source_input) {
402 os_path_split(&in_file_buf, &root_source_dir, &root_source_name);420 buf_init_from_str(&in_file_buf, in_file);
403 if ((err = os_fetch_file_path(buf_create_from_str(in_file), &root_source_code))) {421
404 fprintf(stderr, "unable to open '%s': %s\n", in_file, err_str(err));422 if (buf_eql_str(&in_file_buf, "-")) {
405 return 1;423 os_get_cwd(&root_source_dir);
406 }424 if ((err = os_fetch_file(stdin, &root_source_code))) {
425 fprintf(stderr, "unable to read stdin: %s\n", err_str(err));
426 return 1;
427 }
428 buf_init_from_str(&root_source_name, "");
407429
408 if (need_name && buf_out_name == nullptr) {430 } else {
409 buf_out_name = buf_alloc();431 os_path_split(&in_file_buf, &root_source_dir, &root_source_name);
410 Buf ext_name = BUF_INIT;432 if ((err = os_fetch_file_path(buf_create_from_str(in_file), &root_source_code))) {
411 os_path_extname(&root_source_name, buf_out_name, &ext_name);433 fprintf(stderr, "unable to open '%s': %s\n", in_file, err_str(err));
434 return 1;
435 }
436
437 if (need_name && buf_out_name == nullptr) {
438 buf_out_name = buf_alloc();
439 Buf ext_name = BUF_INIT;
440 os_path_extname(&root_source_name, buf_out_name, &ext_name);
441 }
412 }442 }
443 } else if (cmd == CmdLink) {
444 os_get_cwd(&root_source_dir);
445 } else {
446 zig_unreachable();
413 }447 }
414448
415 if (need_name && buf_out_name == nullptr) {449 if (need_name && buf_out_name == nullptr) {
...@@ -484,6 +518,12 @@ int main(int argc, char **argv) {...@@ -484,6 +518,12 @@ int main(int argc, char **argv) {
484 codegen_add_root_code(g, &root_source_dir, &root_source_name, &root_source_code);518 codegen_add_root_code(g, &root_source_dir, &root_source_name, &root_source_code);
485 codegen_link(g, out_file);519 codegen_link(g, out_file);
486 return EXIT_SUCCESS;520 return EXIT_SUCCESS;
521 } else if (cmd == CmdLink) {
522 for (size_t i = 0; i < objects.length; i += 1) {
523 codegen_add_object(g, buf_create_from_str(objects.at(i)));
524 }
525 codegen_link(g, out_file);
526 return EXIT_SUCCESS;
487 } else if (cmd == CmdAsm) {527 } else if (cmd == CmdAsm) {
488 codegen_add_root_assembly(g, &root_source_dir, &root_source_name, &root_source_code);528 codegen_add_root_assembly(g, &root_source_dir, &root_source_name, &root_source_code);
489 codegen_link(g, out_file);529 codegen_link(g, out_file);
src/os.hpp+16
...@@ -54,4 +54,20 @@ int os_delete_file(Buf *path);...@@ -54,4 +54,20 @@ int os_delete_file(Buf *path);
5454
55int os_file_exists(Buf *full_path, bool *result);55int os_file_exists(Buf *full_path, bool *result);
5656
57#if defined(__APPLE__)
58#define ZIG_OS_DARWIN
59#elif defined(_WIN32)
60#define ZIG_OS_WINDOWS
61#elif defined(__linux__)
62#define ZIG_OS_LINUX
63#else
64#define ZIG_OS_UNKNOWN
65#endif
66
67#if defined(__x86_64__)
68#define ZIG_ARCH_X86_64
69#else
70#define ZIG_ARCH_UNKNOWN
71#endif
72
57#endif73#endif
src/target.cpp+9
...@@ -527,3 +527,12 @@ int get_c_type_size_in_bits(const ZigTarget *target, CIntType id) {...@@ -527,3 +527,12 @@ int get_c_type_size_in_bits(const ZigTarget *target, CIntType id) {
527 }527 }
528 zig_unreachable();528 zig_unreachable();
529}529}
530
531const char *target_o_file_ext(ZigTarget *target) {
532 if (target->env_type == ZigLLVM_MSVC) {
533 return ".obj";
534 } else {
535 return ".o";
536 }
537}
538
src/target.hpp+2
...@@ -72,4 +72,6 @@ void resolve_target_object_format(ZigTarget *target);...@@ -72,4 +72,6 @@ void resolve_target_object_format(ZigTarget *target);
7272
73int get_c_type_size_in_bits(const ZigTarget *target, CIntType id);73int get_c_type_size_in_bits(const ZigTarget *target, CIntType id);
7474
75const char *target_o_file_ext(ZigTarget *target);
76
75#endif77#endif
test/run_tests.cpp+119-43
...@@ -18,6 +18,7 @@ enum TestSpecial {...@@ -18,6 +18,7 @@ enum TestSpecial {
18 TestSpecialNone,18 TestSpecialNone,
19 TestSpecialSelfHosted,19 TestSpecialSelfHosted,
20 TestSpecialStd,20 TestSpecialStd,
21 TestSpecialLinkStep,
21};22};
2223
23struct TestSourceFile {24struct TestSourceFile {
...@@ -36,6 +37,7 @@ struct TestCase {...@@ -36,6 +37,7 @@ struct TestCase {
36 ZigList<TestSourceFile> source_files;37 ZigList<TestSourceFile> source_files;
37 ZigList<const char *> compile_errors;38 ZigList<const char *> compile_errors;
38 ZigList<const char *> compiler_args;39 ZigList<const char *> compiler_args;
40 ZigList<const char *> linker_args;
39 ZigList<const char *> program_args;41 ZigList<const char *> program_args;
40 bool is_parseh;42 bool is_parseh;
41 TestSpecial special;43 TestSpecial special;
...@@ -89,6 +91,37 @@ static TestCase *add_simple_case(const char *case_name, const char *source, cons...@@ -89,6 +91,37 @@ static TestCase *add_simple_case(const char *case_name, const char *source, cons
89 return test_case;91 return test_case;
90}92}
9193
94static TestCase *add_asm_case(const char *case_name, const char *source, const char *output) {
95 TestCase *test_case = allocate<TestCase>(1);
96 test_case->case_name = case_name;
97 test_case->output = output;
98 test_case->special = TestSpecialLinkStep;
99
100 test_case->source_files.resize(1);
101 test_case->source_files.at(0).relative_path = ".tmp_source.s";
102 test_case->source_files.at(0).source_code = source;
103
104 test_case->compiler_args.append("asm");
105 test_case->compiler_args.append(".tmp_source.s");
106 test_case->compiler_args.append("--name");
107 test_case->compiler_args.append("test");
108 test_case->compiler_args.append("--color");
109 test_case->compiler_args.append("on");
110
111 test_case->linker_args.append("link_exe");
112 test_case->linker_args.append("test.o");
113 test_case->linker_args.append("--name");
114 test_case->linker_args.append("test");
115 test_case->linker_args.append("--output");
116 test_case->linker_args.append(tmp_exe_path);
117 test_case->linker_args.append("--color");
118 test_case->linker_args.append("on");
119
120 test_cases.append(test_case);
121
122 return test_case;
123}
124
92static TestCase *add_simple_case_libc(const char *case_name, const char *source, const char *output) {125static TestCase *add_simple_case_libc(const char *case_name, const char *source, const char *output) {
93 TestCase *tc = add_simple_case(case_name, source, output);126 TestCase *tc = add_simple_case(case_name, source, output);
94 tc->compiler_args.append("--library");127 tc->compiler_args.append("--library");
...@@ -129,46 +162,23 @@ static TestCase *add_compile_fail_case(const char *case_name, const char *source...@@ -129,46 +162,23 @@ static TestCase *add_compile_fail_case(const char *case_name, const char *source
129}162}
130163
131static void add_debug_safety_case(const char *case_name, const char *source) {164static void add_debug_safety_case(const char *case_name, const char *source) {
132 {165 TestCase *test_case = allocate<TestCase>(1);
133 TestCase *test_case = allocate<TestCase>(1);166 test_case->is_debug_safety = true;
134 test_case->is_debug_safety = true;167 test_case->case_name = buf_ptr(buf_sprintf("%s", case_name));
135 test_case->case_name = buf_ptr(buf_sprintf("%s (debug)", case_name));168 test_case->source_files.resize(1);
136 test_case->source_files.resize(1);169 test_case->source_files.at(0).relative_path = tmp_source_path;
137 test_case->source_files.at(0).relative_path = tmp_source_path;170 test_case->source_files.at(0).source_code = source;
138 test_case->source_files.at(0).source_code = source;
139
140 test_case->compiler_args.append("build_exe");
141 test_case->compiler_args.append(tmp_source_path);
142
143 test_case->compiler_args.append("--name");
144 test_case->compiler_args.append("test");
145
146 test_case->compiler_args.append("--output");
147 test_case->compiler_args.append(tmp_exe_path);
148
149 test_cases.append(test_case);
150 }
151 {
152 TestCase *test_case = allocate<TestCase>(1);
153 test_case->case_name = buf_ptr(buf_sprintf("%s (release)", case_name));
154 test_case->source_files.resize(1);
155 test_case->source_files.at(0).relative_path = tmp_source_path;
156 test_case->source_files.at(0).source_code = source;
157 test_case->output = "";
158
159 test_case->compiler_args.append("build_exe");
160 test_case->compiler_args.append(tmp_source_path);
161171
162 test_case->compiler_args.append("--name");172 test_case->compiler_args.append("build_exe");
163 test_case->compiler_args.append("test");173 test_case->compiler_args.append(tmp_source_path);
164174
165 test_case->compiler_args.append("--output");175 test_case->compiler_args.append("--name");
166 test_case->compiler_args.append(tmp_exe_path);176 test_case->compiler_args.append("test");
167177
168 test_case->compiler_args.append("--release");178 test_case->compiler_args.append("--output");
179 test_case->compiler_args.append(tmp_exe_path);
169180
170 test_cases.append(test_case);181 test_cases.append(test_case);
171 }
172}182}
173183
174static TestCase *add_parseh_case(const char *case_name, AllowWarnings allow_warnings,184static TestCase *add_parseh_case(const char *case_name, AllowWarnings allow_warnings,
...@@ -1865,9 +1875,7 @@ pub fn panic(message: []const u8) -> noreturn {...@@ -1865,9 +1875,7 @@ pub fn panic(message: []const u8) -> noreturn {
1865 while (true) {}1875 while (true) {}
1866}1876}
1867pub fn main() -> %void {1877pub fn main() -> %void {
1868 if (!@compileVar("is_release")) {1878 @panic("oh no");
1869 @panic("oh no");
1870 }
1871}1879}
1872 )SOURCE");1880 )SOURCE");
18731881
...@@ -2375,6 +2383,32 @@ static void add_std_lib_tests(void) {...@@ -2375,6 +2383,32 @@ static void add_std_lib_tests(void) {
2375 }2383 }
2376}2384}
23772385
2386static void add_asm_tests(void) {
2387#if defined(ZIG_OS_LINUX) && defined(ZIG_ARCH_X86_64)
2388 add_asm_case("assemble and link hello world linux x86_64", R"SOURCE(
2389.text
2390.globl _start
2391
2392_start:
2393 mov rax, 1
2394 mov rdi, 1
2395 lea rsi, msg
2396 mov rdx, 14
2397 syscall
2398
2399 mov rax, 60
2400 mov rdi, 0
2401 syscall
2402
2403.data
2404
2405msg:
2406 .ascii "Hello, world!\n"
2407 )SOURCE", "Hello, world!\n");
2408
2409#endif
2410}
2411
23782412
2379static void print_compiler_invocation(TestCase *test_case) {2413static void print_compiler_invocation(TestCase *test_case) {
2380 printf("%s", zig_exe);2414 printf("%s", zig_exe);
...@@ -2384,6 +2418,15 @@ static void print_compiler_invocation(TestCase *test_case) {...@@ -2384,6 +2418,15 @@ static void print_compiler_invocation(TestCase *test_case) {
2384 printf("\n");2418 printf("\n");
2385}2419}
23862420
2421static void print_linker_invocation(TestCase *test_case) {
2422 printf("%s", zig_exe);
2423 for (size_t i = 0; i < test_case->linker_args.length; i += 1) {
2424 printf(" %s", test_case->linker_args.at(i));
2425 }
2426 printf("\n");
2427}
2428
2429
2387static void print_exe_invocation(TestCase *test_case) {2430static void print_exe_invocation(TestCase *test_case) {
2388 printf("%s", tmp_exe_path);2431 printf("%s", tmp_exe_path);
2389 for (size_t i = 0; i < test_case->program_args.length; i += 1) {2432 for (size_t i = 0; i < test_case->program_args.length; i += 1) {
...@@ -2470,6 +2513,23 @@ static void run_test(TestCase *test_case) {...@@ -2470,6 +2513,23 @@ static void run_test(TestCase *test_case) {
2470 }2513 }
2471 }2514 }
2472 } else {2515 } else {
2516 if (test_case->special == TestSpecialLinkStep) {
2517 Buf link_stderr = BUF_INIT;
2518 Buf link_stdout = BUF_INIT;
2519 int err;
2520 Termination term;
2521 if ((err = os_exec_process(zig_exe, test_case->linker_args, &term, &link_stderr, &link_stdout))) {
2522 fprintf(stderr, "Unable to exec %s: %s\n", zig_exe, err_str(err));
2523 }
2524
2525 if (term.how != TerminationIdClean || term.code != 0) {
2526 printf("\nLink failed:\n");
2527 print_linker_invocation(test_case);
2528 printf("%s\n", buf_ptr(&zig_stderr));
2529 exit(1);
2530 }
2531 }
2532
2473 Buf program_stderr = BUF_INIT;2533 Buf program_stderr = BUF_INIT;
2474 Buf program_stdout = BUF_INIT;2534 Buf program_stdout = BUF_INIT;
2475 os_exec_process(tmp_exe_path, test_case->program_args, &term, &program_stderr, &program_stdout);2535 os_exec_process(tmp_exe_path, test_case->program_args, &term, &program_stderr, &program_stdout);
...@@ -2520,9 +2580,13 @@ static void run_test(TestCase *test_case) {...@@ -2520,9 +2580,13 @@ static void run_test(TestCase *test_case) {
2520 }2580 }
2521}2581}
25222582
2523static void run_all_tests(void) {2583static void run_all_tests(const char *grep_text) {
2524 for (size_t i = 0; i < test_cases.length; i += 1) {2584 for (size_t i = 0; i < test_cases.length; i += 1) {
2525 TestCase *test_case = test_cases.at(i);2585 TestCase *test_case = test_cases.at(i);
2586 if (grep_text != nullptr && strstr(test_case->case_name, grep_text) == nullptr) {
2587 continue;
2588 }
2589
2526 printf("Test %zu/%zu %s...", i + 1, test_cases.length, test_case->case_name);2590 printf("Test %zu/%zu %s...", i + 1, test_cases.length, test_case->case_name);
2527 fflush(stdout);2591 fflush(stdout);
2528 run_test(test_case);2592 run_test(test_case);
...@@ -2538,13 +2602,24 @@ static void cleanup(void) {...@@ -2538,13 +2602,24 @@ static void cleanup(void) {
2538}2602}
25392603
2540static int usage(const char *arg0) {2604static int usage(const char *arg0) {
2541 fprintf(stderr, "Usage: %s\n", arg0);2605 fprintf(stderr, "Usage: %s [--grep text]\n", arg0);
2542 return 1;2606 return 1;
2543}2607}
25442608
2545int main(int argc, char **argv) {2609int main(int argc, char **argv) {
2610 const char *grep_text = nullptr;
2546 for (int i = 1; i < argc; i += 1) {2611 for (int i = 1; i < argc; i += 1) {
2547 return usage(argv[0]);2612 const char *arg = argv[i];
2613 if (i + 1 >= argc) {
2614 return usage(argv[0]);
2615 } else {
2616 i += 1;
2617 if (strcmp(arg, "--grep") == 0) {
2618 grep_text = argv[i];
2619 } else {
2620 return usage(argv[0]);
2621 }
2622 }
2548 }2623 }
2549 add_compiling_test_cases();2624 add_compiling_test_cases();
2550 add_debug_safety_test_cases();2625 add_debug_safety_test_cases();
...@@ -2552,6 +2627,7 @@ int main(int argc, char **argv) {...@@ -2552,6 +2627,7 @@ int main(int argc, char **argv) {
2552 add_parseh_test_cases();2627 add_parseh_test_cases();
2553 add_self_hosted_tests();2628 add_self_hosted_tests();
2554 add_std_lib_tests();2629 add_std_lib_tests();
2555 run_all_tests();2630 add_asm_tests();
2631 run_all_tests(grep_text);
2556 cleanup();2632 cleanup();
2557}2633}