| author | |
| committer | |
| log | d65cd73a8bfe39349be09a5f76f8477f3e3210b9 |
| tree | b97b4c6ab21e19acd276cdf38aec5ad1cb2db268 |
| parent | 8c10b6dcbddc58b488e399690e8ddefb4bafb816 |
closes #243
I also added --grep to ./run_tests if you want to single out
some specific tests9 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]; |
| 1463 | 1463 | ||
| 1464 | Buf global_asm; | 1464 | Buf global_asm; |
| 1465 | ZigList<Buf *> link_objects; | ||
| 1465 | }; | 1466 | }; |
| 1466 | 1467 | ||
| 1467 | enum VarLinkage { | 1468 | enum 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 | #endif | 3745 | #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 | } |
| 3747 | 3759 | ||
| 3748 | static const size_t int_sizes_in_bits[] = { | 3760 | static 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 | } |
| 4552 | 4564 | ||
| 4565 | void codegen_add_object(CodeGen *g, Buf *object_path) { | ||
| 4566 | g->link_objects.append(object_path); | ||
| 4567 | } | ||
| 4568 | |||
| 4553 | 4569 | ||
| 4554 | static const char *c_int_type_names[] = { | 4570 | static 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); |
| 48 | PackageTableEntry *new_package(const char *root_src_dir, const char *root_src_path); | 48 | PackageTableEntry *new_package(const char *root_src_dir, const char *root_src_path); |
| 49 | void codegen_add_root_code(CodeGen *g, Buf *source_dir, Buf *source_basename, Buf *source_code); | 49 | void codegen_add_root_code(CodeGen *g, Buf *source_dir, Buf *source_basename, Buf *source_code); |
| 50 | void codegen_add_root_assembly(CodeGen *g, Buf *source_dir, Buf *source_basename, Buf *source_code); | 50 | void codegen_add_root_assembly(CodeGen *g, Buf *source_dir, Buf *source_basename, Buf *source_code); |
| 51 | void codegen_add_object(CodeGen *g, Buf *object_path); | ||
| 51 | 52 | ||
| 52 | void codegen_parseh(CodeGen *g, Buf *src_dirname, Buf *src_basename, Buf *source_code); | 53 | void codegen_parseh(CodeGen *g, Buf *src_dirname, Buf *src_basename, Buf *source_code); |
| 53 | void codegen_render_ast(CodeGen *g, FILE *f, int indent_size); | 54 | void 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 | }; |
| 22 | 21 | ||
| ... | @@ -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 | } |
| 34 | 33 | ||
| 35 | static 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 | |||
| 43 | static Buf *build_o(CodeGen *parent_gen, const char *oname) { | 34 | static 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); |
| 45 | 36 | ||
| ... | @@ -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 | } |
| 79 | 70 | ||
| 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)); |
| 84 | 75 | ||
| ... | @@ -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 | } |
| 275 | 266 | ||
| 276 | // .o files | 267 | // .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 | } | ||
| 278 | 271 | ||
| 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 | } |
| 419 | 412 | ||
| 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 | } | ||
| 421 | 416 | ||
| 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 | } |
| 683 | 678 | ||
| 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 | } | ||
| 685 | 682 | ||
| 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 | } | ||
| 792 | 776 | ||
| 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 | }; |
| 112 | 115 | ||
| 113 | int main(int argc, char **argv) { | 116 | int 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}; | ||
| 150 | 154 | ||
| 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 | } | ||
| 350 | 376 | ||
| 351 | assert(cmd != CmdBuild || out_type != OutTypeUnknown); | 377 | assert((cmd != CmdBuild && cmd != CmdLink) || out_type != OutTypeUnknown); |
| 352 | 378 | ||
| 353 | init_all_targets(); | 379 | init_all_targets(); |
| 354 | 380 | ||
| ... | @@ -379,10 +405,9 @@ int main(int argc, char **argv) { | ... | @@ -379,10 +405,9 @@ int main(int argc, char **argv) { |
| 379 | } | 405 | } |
| 380 | } | 406 | } |
| 381 | 407 | ||
| 382 | bool need_name = (cmd == CmdBuild || cmd == CmdAsm); | 408 | bool need_name = (cmd == CmdBuild || cmd == CmdAsm || cmd == CmdLink); |
| 383 | 409 | ||
| 384 | Buf in_file_buf = BUF_INIT; | 410 | Buf in_file_buf = BUF_INIT; |
| 385 | buf_init_from_str(&in_file_buf, in_file); | ||
| 386 | 411 | ||
| 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) { |
| 390 | 415 | ||
| 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, ""); | ||
| 400 | 418 | ||
| 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, ""); | ||
| 407 | 429 | ||
| 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 | } |
| 414 | 448 | ||
| 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); |
| 54 | 54 | ||
| 55 | int os_file_exists(Buf *full_path, bool *result); | 55 | int os_file_exists(Buf *full_path, bool *result); |
| 56 | 56 | ||
| 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 | #endif | 73 | #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 | |||
| 531 | const 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); |
| 72 | 72 | ||
| 73 | int get_c_type_size_in_bits(const ZigTarget *target, CIntType id); | 73 | int get_c_type_size_in_bits(const ZigTarget *target, CIntType id); |
| 74 | 74 | ||
| 75 | const char *target_o_file_ext(ZigTarget *target); | ||
| 76 | |||
| 75 | #endif | 77 | #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 | }; |
| 22 | 23 | ||
| 23 | struct TestSourceFile { | 24 | struct 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 | } |
| 91 | 93 | ||
| 94 | static 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 | |||
| 92 | static TestCase *add_simple_case_libc(const char *case_name, const char *source, const char *output) { | 125 | static 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 | } |
| 130 | 163 | ||
| 131 | static void add_debug_safety_case(const char *case_name, const char *source) { | 164 | static 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); | ||
| 161 | 171 | ||
| 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); |
| 164 | 174 | ||
| 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"); |
| 167 | 177 | ||
| 168 | test_case->compiler_args.append("--release"); | 178 | test_case->compiler_args.append("--output"); |
| 179 | test_case->compiler_args.append(tmp_exe_path); | ||
| 169 | 180 | ||
| 170 | test_cases.append(test_case); | 181 | test_cases.append(test_case); |
| 171 | } | ||
| 172 | } | 182 | } |
| 173 | 183 | ||
| 174 | static TestCase *add_parseh_case(const char *case_name, AllowWarnings allow_warnings, | 184 | static 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 | } |
| 1867 | pub fn main() -> %void { | 1877 | pub fn main() -> %void { |
| 1868 | if (!@compileVar("is_release")) { | 1878 | @panic("oh no"); |
| 1869 | @panic("oh no"); | ||
| 1870 | } | ||
| 1871 | } | 1879 | } |
| 1872 | )SOURCE"); | 1880 | )SOURCE"); |
| 1873 | 1881 | ||
| ... | @@ -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 | } |
| 2377 | 2385 | ||
| 2386 | static 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 | |||
| 2405 | msg: | ||
| 2406 | .ascii "Hello, world!\n" | ||
| 2407 | )SOURCE", "Hello, world!\n"); | ||
| 2408 | |||
| 2409 | #endif | ||
| 2410 | } | ||
| 2411 | |||
| 2378 | 2412 | ||
| 2379 | static void print_compiler_invocation(TestCase *test_case) { | 2413 | static 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 | } |
| 2386 | 2420 | ||
| 2421 | static 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 | |||
| 2387 | static void print_exe_invocation(TestCase *test_case) { | 2430 | static 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 | } |
| 2522 | 2582 | ||
| 2523 | static void run_all_tests(void) { | 2583 | static 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 | } |
| 2539 | 2603 | ||
| 2540 | static int usage(const char *arg0) { | 2604 | static 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 | } |
| 2544 | 2608 | ||
| 2545 | int main(int argc, char **argv) { | 2609 | int 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 | } |