| author | |
| committer | |
| log | 2bf6c28bc3e535deb651d5b37e332226e0d38930 |
| tree | bb206f61ac612f1c991a7c1c58176a163d51a74f |
| parent | 54a8b6a110fa779a2fc12b901b96b6e072bca7cf |
hello_libc.zig can produce a windows build14 files changed, 893 insertions(+), 309 deletions(-)
CMakeLists.txt+9| ... | @@ -14,6 +14,14 @@ set(ZIG_VERSION_PATCH 0) | ... | @@ -14,6 +14,14 @@ set(ZIG_VERSION_PATCH 0) |
| 14 | set(ZIG_VERSION "${ZIG_VERSION_MAJOR}.${ZIG_VERSION_MINOR}.${ZIG_VERSION_PATCH}") | 14 | set(ZIG_VERSION "${ZIG_VERSION_MAJOR}.${ZIG_VERSION_MINOR}.${ZIG_VERSION_PATCH}") |
| 15 | message("Configuring zig version ${ZIG_VERSION}") | 15 | message("Configuring zig version ${ZIG_VERSION}") |
| 16 | 16 | ||
| 17 | set(ZIG_LIBC_LIB_DIR "" CACHE STRING "Default native target libc directory where crt1.o can be found") | ||
| 18 | set(ZIG_LIBC_STATIC_LIB_DIR "" CACHE STRING "Default native target libc directory where crtbeginT.o can be found") | ||
| 19 | set(ZIG_LIBC_INCLUDE_DIR "/usr/include" CACHE STRING "Default native target libc include directory") | ||
| 20 | set(ZIG_LD_PATH "ld" CACHE STRING "Path to ld for the native target") | ||
| 21 | set(ZIG_DYNAMIC_LINKER "" CACHE STRING "Override dynamic linker for native target") | ||
| 22 | |||
| 23 | |||
| 24 | |||
| 17 | find_package(llvm) | 25 | find_package(llvm) |
| 18 | include_directories(${LLVM_INCLUDE_DIRS}) | 26 | include_directories(${LLVM_INCLUDE_DIRS}) |
| 19 | link_directories(${LLVM_LIBDIRS}) | 27 | link_directories(${LLVM_LIBDIRS}) |
| ... | @@ -27,6 +35,7 @@ include_directories( | ... | @@ -27,6 +35,7 @@ include_directories( |
| 27 | ) | 35 | ) |
| 28 | 36 | ||
| 29 | set(ZIG_SOURCES | 37 | set(ZIG_SOURCES |
| 38 | "${CMAKE_SOURCE_DIR}/src/link.cpp" | ||
| 30 | "${CMAKE_SOURCE_DIR}/src/target.cpp" | 39 | "${CMAKE_SOURCE_DIR}/src/target.cpp" |
| 31 | "${CMAKE_SOURCE_DIR}/src/ast_render.cpp" | 40 | "${CMAKE_SOURCE_DIR}/src/ast_render.cpp" |
| 32 | "${CMAKE_SOURCE_DIR}/src/bignum.cpp" | 41 | "${CMAKE_SOURCE_DIR}/src/bignum.cpp" |
src/all_types.hpp+8| ... | @@ -14,6 +14,7 @@ | ... | @@ -14,6 +14,7 @@ |
| 14 | #include "hash_map.hpp" | 14 | #include "hash_map.hpp" |
| 15 | #include "errmsg.hpp" | 15 | #include "errmsg.hpp" |
| 16 | #include "bignum.hpp" | 16 | #include "bignum.hpp" |
| 17 | #include "target.hpp" | ||
| 17 | 18 | ||
| 18 | struct AstNode; | 19 | struct AstNode; |
| 19 | struct ImportTableEntry; | 20 | struct ImportTableEntry; |
| ... | @@ -1109,6 +1110,7 @@ struct CodeGen { | ... | @@ -1109,6 +1110,7 @@ struct CodeGen { |
| 1109 | TypeTableEntry *entry_pure_error; | 1110 | TypeTableEntry *entry_pure_error; |
| 1110 | } builtin_types; | 1111 | } builtin_types; |
| 1111 | 1112 | ||
| 1113 | ZigTarget zig_target; | ||
| 1112 | LLVMTargetDataRef target_data_ref; | 1114 | LLVMTargetDataRef target_data_ref; |
| 1113 | unsigned pointer_size_bytes; | 1115 | unsigned pointer_size_bytes; |
| 1114 | bool is_big_endian; | 1116 | bool is_big_endian; |
| ... | @@ -1120,12 +1122,18 @@ struct CodeGen { | ... | @@ -1120,12 +1122,18 @@ struct CodeGen { |
| 1120 | Buf *libc_static_lib_dir; | 1122 | Buf *libc_static_lib_dir; |
| 1121 | Buf *libc_include_dir; | 1123 | Buf *libc_include_dir; |
| 1122 | Buf *dynamic_linker; | 1124 | Buf *dynamic_linker; |
| 1125 | Buf *linker_path; | ||
| 1126 | Buf triple_str; | ||
| 1123 | bool is_release_build; | 1127 | bool is_release_build; |
| 1124 | bool is_test_build; | 1128 | bool is_test_build; |
| 1125 | LLVMTargetMachineRef target_machine; | 1129 | LLVMTargetMachineRef target_machine; |
| 1126 | LLVMZigDIFile *dummy_di_file; | 1130 | LLVMZigDIFile *dummy_di_file; |
| 1131 | bool is_native_target; | ||
| 1127 | Buf *root_source_dir; | 1132 | Buf *root_source_dir; |
| 1128 | Buf *root_out_name; | 1133 | Buf *root_out_name; |
| 1134 | bool windows_subsystem_windows; | ||
| 1135 | bool windows_subsystem_console; | ||
| 1136 | bool windows_linker_unicode; | ||
| 1129 | 1137 | ||
| 1130 | // The function definitions this module includes. There must be a corresponding | 1138 | // The function definitions this module includes. There must be a corresponding |
| 1131 | // fn_protos entry. | 1139 | // fn_protos entry. |
src/analyze.cpp+3-3| ... | @@ -5929,13 +5929,13 @@ bool handle_is_ptr(TypeTableEntry *type_entry) { | ... | @@ -5929,13 +5929,13 @@ bool handle_is_ptr(TypeTableEntry *type_entry) { |
| 5929 | void find_libc_path(CodeGen *g) { | 5929 | void find_libc_path(CodeGen *g) { |
| 5930 | // later we can handle this better by reporting an error via the normal mechanism | 5930 | // later we can handle this better by reporting an error via the normal mechanism |
| 5931 | if (!g->libc_lib_dir || buf_len(g->libc_lib_dir) == 0) { | 5931 | if (!g->libc_lib_dir || buf_len(g->libc_lib_dir) == 0) { |
| 5932 | zig_panic("Unable to determine libc lib path. probably need to reconfigure"); | 5932 | zig_panic("Unable to determine libc lib path."); |
| 5933 | } | 5933 | } |
| 5934 | if (!g->libc_static_lib_dir || buf_len(g->libc_static_lib_dir) == 0) { | 5934 | if (!g->libc_static_lib_dir || buf_len(g->libc_static_lib_dir) == 0) { |
| 5935 | zig_panic("Unable to determine libc static lib path. probably need to reconfigure"); | 5935 | zig_panic("Unable to determine libc static lib path."); |
| 5936 | } | 5936 | } |
| 5937 | if (!g->libc_include_dir || buf_len(g->libc_include_dir) == 0) { | 5937 | if (!g->libc_include_dir || buf_len(g->libc_include_dir) == 0) { |
| 5938 | zig_panic("Unable to determine libc include path. probably need to reconfigure"); | 5938 | zig_panic("Unable to determine libc include path."); |
| 5939 | } | 5939 | } |
| 5940 | } | 5940 | } |
| 5941 | 5941 |
src/codegen.cpp+56-277| ... | @@ -15,12 +15,14 @@ | ... | @@ -15,12 +15,14 @@ |
| 15 | #include "errmsg.hpp" | 15 | #include "errmsg.hpp" |
| 16 | #include "parseh.hpp" | 16 | #include "parseh.hpp" |
| 17 | #include "ast_render.hpp" | 17 | #include "ast_render.hpp" |
| 18 | #include "target.hpp" | ||
| 19 | #include "link.hpp" | ||
| 18 | 20 | ||
| 19 | #include <stdio.h> | 21 | #include <stdio.h> |
| 20 | #include <errno.h> | 22 | #include <errno.h> |
| 21 | 23 | ||
| 22 | 24 | ||
| 23 | CodeGen *codegen_create(Buf *root_source_dir) { | 25 | CodeGen *codegen_create(Buf *root_source_dir, const ZigTarget *target) { |
| 24 | CodeGen *g = allocate<CodeGen>(1); | 26 | CodeGen *g = allocate<CodeGen>(1); |
| 25 | g->link_table.init(32); | 27 | g->link_table.init(32); |
| 26 | g->import_table.init(32); | 28 | g->import_table.init(32); |
| ... | @@ -33,11 +35,29 @@ CodeGen *codegen_create(Buf *root_source_dir) { | ... | @@ -33,11 +35,29 @@ CodeGen *codegen_create(Buf *root_source_dir) { |
| 33 | g->is_test_build = false; | 35 | g->is_test_build = false; |
| 34 | g->root_source_dir = root_source_dir; | 36 | g->root_source_dir = root_source_dir; |
| 35 | g->error_value_count = 1; | 37 | g->error_value_count = 1; |
| 36 | g->dynamic_linker = buf_create_from_str(ZIG_DYNAMIC_LINKER); | ||
| 37 | 38 | ||
| 38 | g->libc_lib_dir = buf_create_from_str(ZIG_LIBC_LIB_DIR); | 39 | if (target) { |
| 39 | g->libc_static_lib_dir = buf_create_from_str(ZIG_LIBC_STATIC_LIB_DIR); | 40 | // cross compiling, so we can't rely on all the configured stuff since |
| 40 | g->libc_include_dir = buf_create_from_str(ZIG_LIBC_INCLUDE_DIR); | 41 | // that's for native compilation |
| 42 | g->zig_target = *target; | ||
| 43 | resolve_target_object_format(&g->zig_target); | ||
| 44 | |||
| 45 | g->dynamic_linker = buf_create_from_str(""); | ||
| 46 | g->libc_lib_dir = buf_create_from_str(""); | ||
| 47 | g->libc_static_lib_dir = buf_create_from_str(""); | ||
| 48 | g->libc_include_dir = buf_create_from_str(""); | ||
| 49 | g->linker_path = buf_create_from_str(""); | ||
| 50 | } else { | ||
| 51 | // native compilation, we can rely on the configuration stuff | ||
| 52 | g->is_native_target = true; | ||
| 53 | get_native_target(&g->zig_target); | ||
| 54 | |||
| 55 | g->dynamic_linker = buf_create_from_str(ZIG_DYNAMIC_LINKER); | ||
| 56 | g->libc_lib_dir = buf_create_from_str(ZIG_LIBC_LIB_DIR); | ||
| 57 | g->libc_static_lib_dir = buf_create_from_str(ZIG_LIBC_STATIC_LIB_DIR); | ||
| 58 | g->libc_include_dir = buf_create_from_str(ZIG_LIBC_INCLUDE_DIR); | ||
| 59 | g->linker_path = buf_create_from_str(ZIG_LD_PATH); | ||
| 60 | } | ||
| 41 | 61 | ||
| 42 | return g; | 62 | return g; |
| 43 | } | 63 | } |
| ... | @@ -95,10 +115,23 @@ void codegen_set_dynamic_linker(CodeGen *g, Buf *dynamic_linker) { | ... | @@ -95,10 +115,23 @@ void codegen_set_dynamic_linker(CodeGen *g, Buf *dynamic_linker) { |
| 95 | g->dynamic_linker = dynamic_linker; | 115 | g->dynamic_linker = dynamic_linker; |
| 96 | } | 116 | } |
| 97 | 117 | ||
| 118 | void codegen_set_linker_path(CodeGen *g, Buf *linker_path) { | ||
| 119 | g->linker_path = linker_path; | ||
| 120 | } | ||
| 121 | |||
| 98 | void codegen_add_lib_dir(CodeGen *g, const char *dir) { | 122 | void codegen_add_lib_dir(CodeGen *g, const char *dir) { |
| 99 | g->lib_dirs.append(dir); | 123 | g->lib_dirs.append(dir); |
| 100 | } | 124 | } |
| 101 | 125 | ||
| 126 | void codegen_set_windows_subsystem(CodeGen *g, bool mwindows, bool mconsole) { | ||
| 127 | g->windows_subsystem_windows = mwindows; | ||
| 128 | g->windows_subsystem_console = mconsole; | ||
| 129 | } | ||
| 130 | |||
| 131 | void codegen_set_windows_unicode(CodeGen *g, bool municode) { | ||
| 132 | g->windows_linker_unicode = municode; | ||
| 133 | } | ||
| 134 | |||
| 102 | static LLVMValueRef gen_expr(CodeGen *g, AstNode *expr_node); | 135 | static LLVMValueRef gen_expr(CodeGen *g, AstNode *expr_node); |
| 103 | static LLVMValueRef gen_lvalue(CodeGen *g, AstNode *expr_node, AstNode *node, TypeTableEntry **out_type_entry); | 136 | static LLVMValueRef gen_lvalue(CodeGen *g, AstNode *expr_node, AstNode *node, TypeTableEntry **out_type_entry); |
| 104 | static LLVMValueRef gen_field_access_expr(CodeGen *g, AstNode *node, bool is_lvalue); | 137 | static LLVMValueRef gen_field_access_expr(CodeGen *g, AstNode *node, bool is_lvalue); |
| ... | @@ -3502,34 +3535,35 @@ static void init(CodeGen *g, Buf *source_path) { | ... | @@ -3502,34 +3535,35 @@ static void init(CodeGen *g, Buf *source_path) { |
| 3502 | g->lib_search_paths.append(g->root_source_dir); | 3535 | g->lib_search_paths.append(g->root_source_dir); |
| 3503 | g->lib_search_paths.append(buf_create_from_str(ZIG_STD_DIR)); | 3536 | g->lib_search_paths.append(buf_create_from_str(ZIG_STD_DIR)); |
| 3504 | 3537 | ||
| 3505 | LLVMInitializeAllTargets(); | ||
| 3506 | LLVMInitializeAllTargetMCs(); | ||
| 3507 | LLVMInitializeAllAsmPrinters(); | ||
| 3508 | LLVMInitializeAllAsmParsers(); | ||
| 3509 | LLVMInitializeNativeTarget(); | ||
| 3510 | |||
| 3511 | char *native_triple = LLVMGetDefaultTargetTriple(); | ||
| 3512 | |||
| 3513 | g->module = LLVMModuleCreateWithName(buf_ptr(source_path)); | 3538 | g->module = LLVMModuleCreateWithName(buf_ptr(source_path)); |
| 3514 | 3539 | ||
| 3515 | LLVMSetTarget(g->module, native_triple); | 3540 | get_target_triple(&g->triple_str, &g->zig_target); |
| 3541 | |||
| 3542 | LLVMSetTarget(g->module, buf_ptr(&g->triple_str)); | ||
| 3516 | 3543 | ||
| 3517 | LLVMTargetRef target_ref; | 3544 | LLVMTargetRef target_ref; |
| 3518 | char *err_msg = nullptr; | 3545 | char *err_msg = nullptr; |
| 3519 | if (LLVMGetTargetFromTriple(native_triple, &target_ref, &err_msg)) { | 3546 | if (LLVMGetTargetFromTriple(buf_ptr(&g->triple_str), &target_ref, &err_msg)) { |
| 3520 | zig_panic("unable to get target from triple: %s", err_msg); | 3547 | zig_panic("unable to create target based on: %s", buf_ptr(&g->triple_str)); |
| 3521 | } | 3548 | } |
| 3522 | 3549 | ||
| 3523 | 3550 | ||
| 3524 | char *native_cpu = LLVMZigGetHostCPUName(); | ||
| 3525 | char *native_features = LLVMZigGetNativeFeatures(); | ||
| 3526 | |||
| 3527 | LLVMCodeGenOptLevel opt_level = g->is_release_build ? LLVMCodeGenLevelAggressive : LLVMCodeGenLevelNone; | 3551 | LLVMCodeGenOptLevel opt_level = g->is_release_build ? LLVMCodeGenLevelAggressive : LLVMCodeGenLevelNone; |
| 3528 | 3552 | ||
| 3529 | LLVMRelocMode reloc_mode = g->is_static ? LLVMRelocStatic : LLVMRelocPIC; | 3553 | LLVMRelocMode reloc_mode = g->is_static ? LLVMRelocStatic : LLVMRelocPIC; |
| 3530 | 3554 | ||
| 3531 | g->target_machine = LLVMCreateTargetMachine(target_ref, native_triple, | 3555 | const char *target_specific_cpu_args; |
| 3532 | native_cpu, native_features, opt_level, reloc_mode, LLVMCodeModelDefault); | 3556 | const char *target_specific_features; |
| 3557 | if (g->is_native_target) { | ||
| 3558 | target_specific_cpu_args = LLVMZigGetHostCPUName(); | ||
| 3559 | target_specific_features = LLVMZigGetNativeFeatures(); | ||
| 3560 | } else { | ||
| 3561 | target_specific_cpu_args = ""; | ||
| 3562 | target_specific_features = ""; | ||
| 3563 | } | ||
| 3564 | |||
| 3565 | g->target_machine = LLVMCreateTargetMachine(target_ref, buf_ptr(&g->triple_str), | ||
| 3566 | target_specific_cpu_args, target_specific_features, opt_level, reloc_mode, LLVMCodeModelDefault); | ||
| 3533 | 3567 | ||
| 3534 | g->target_data_ref = LLVMGetTargetMachineData(g->target_machine); | 3568 | g->target_data_ref = LLVMGetTargetMachineData(g->target_machine); |
| 3535 | 3569 | ||
| ... | @@ -3902,7 +3936,7 @@ static void to_c_type(CodeGen *g, AstNode *type_node, Buf *out_buf) { | ... | @@ -3902,7 +3936,7 @@ static void to_c_type(CodeGen *g, AstNode *type_node, Buf *out_buf) { |
| 3902 | } | 3936 | } |
| 3903 | } | 3937 | } |
| 3904 | 3938 | ||
| 3905 | static void generate_h_file(CodeGen *g) { | 3939 | void codegen_generate_h_file(CodeGen *g) { |
| 3906 | assert(!g->is_test_build); | 3940 | assert(!g->is_test_build); |
| 3907 | 3941 | ||
| 3908 | Buf *h_file_out_path = buf_sprintf("%s.h", buf_ptr(g->root_out_name)); | 3942 | Buf *h_file_out_path = buf_sprintf("%s.h", buf_ptr(g->root_out_name)); |
| ... | @@ -3989,258 +4023,3 @@ static void generate_h_file(CodeGen *g) { | ... | @@ -3989,258 +4023,3 @@ static void generate_h_file(CodeGen *g) { |
| 3989 | if (fclose(out_h)) | 4023 | if (fclose(out_h)) |
| 3990 | zig_panic("unable to close h file: %s", strerror(errno)); | 4024 | zig_panic("unable to close h file: %s", strerror(errno)); |
| 3991 | } | 4025 | } |
| 3992 | |||
| 3993 | static const char *get_libc_file(CodeGen *g, const char *file) { | ||
| 3994 | Buf *out_buf = buf_alloc(); | ||
| 3995 | os_path_join(g->libc_lib_dir, buf_create_from_str(file), out_buf); | ||
| 3996 | return buf_ptr(out_buf); | ||
| 3997 | } | ||
| 3998 | |||
| 3999 | static const char *get_libc_static_file(CodeGen *g, const char *file) { | ||
| 4000 | Buf *out_buf = buf_alloc(); | ||
| 4001 | os_path_join(g->libc_static_lib_dir, buf_create_from_str(file), out_buf); | ||
| 4002 | return buf_ptr(out_buf); | ||
| 4003 | } | ||
| 4004 | |||
| 4005 | static Buf *build_o(CodeGen *parent_gen, const char *oname) { | ||
| 4006 | Buf *source_basename = buf_sprintf("%s.zig", oname); | ||
| 4007 | Buf *std_dir_path = buf_create_from_str(ZIG_STD_DIR); | ||
| 4008 | |||
| 4009 | CodeGen *child_gen = codegen_create(std_dir_path); | ||
| 4010 | child_gen->link_libc = parent_gen->link_libc; | ||
| 4011 | |||
| 4012 | codegen_set_is_release(child_gen, parent_gen->is_release_build); | ||
| 4013 | |||
| 4014 | codegen_set_strip(child_gen, parent_gen->strip_debug_symbols); | ||
| 4015 | codegen_set_is_static(child_gen, parent_gen->is_static); | ||
| 4016 | |||
| 4017 | codegen_set_out_type(child_gen, OutTypeObj); | ||
| 4018 | codegen_set_out_name(child_gen, buf_create_from_str(oname)); | ||
| 4019 | |||
| 4020 | codegen_set_verbose(child_gen, parent_gen->verbose); | ||
| 4021 | codegen_set_errmsg_color(child_gen, parent_gen->err_color); | ||
| 4022 | |||
| 4023 | Buf *full_path = buf_alloc(); | ||
| 4024 | os_path_join(std_dir_path, source_basename, full_path); | ||
| 4025 | Buf source_code = BUF_INIT; | ||
| 4026 | if (os_fetch_file_path(full_path, &source_code)) { | ||
| 4027 | zig_panic("unable to fetch file: %s\n", buf_ptr(full_path)); | ||
| 4028 | } | ||
| 4029 | |||
| 4030 | codegen_add_root_code(child_gen, std_dir_path, source_basename, &source_code); | ||
| 4031 | Buf *o_out = buf_sprintf("%s.o", oname); | ||
| 4032 | codegen_link(child_gen, buf_ptr(o_out)); | ||
| 4033 | |||
| 4034 | return o_out; | ||
| 4035 | } | ||
| 4036 | |||
| 4037 | void codegen_link(CodeGen *g, const char *out_file) { | ||
| 4038 | bool is_optimized = g->is_release_build; | ||
| 4039 | if (is_optimized) { | ||
| 4040 | if (g->verbose) { | ||
| 4041 | fprintf(stderr, "\nOptimization:\n"); | ||
| 4042 | fprintf(stderr, "---------------\n"); | ||
| 4043 | } | ||
| 4044 | |||
| 4045 | LLVMZigOptimizeModule(g->target_machine, g->module); | ||
| 4046 | |||
| 4047 | if (g->verbose) { | ||
| 4048 | LLVMDumpModule(g->module); | ||
| 4049 | } | ||
| 4050 | } | ||
| 4051 | if (g->verbose) { | ||
| 4052 | fprintf(stderr, "\nLink:\n"); | ||
| 4053 | fprintf(stderr, "-------\n"); | ||
| 4054 | } | ||
| 4055 | |||
| 4056 | if (!out_file) { | ||
| 4057 | assert(g->root_out_name); | ||
| 4058 | out_file = buf_ptr(g->root_out_name); | ||
| 4059 | } | ||
| 4060 | |||
| 4061 | Buf out_file_o = BUF_INIT; | ||
| 4062 | buf_init_from_str(&out_file_o, out_file); | ||
| 4063 | |||
| 4064 | if (g->out_type != OutTypeObj) { | ||
| 4065 | buf_append_str(&out_file_o, ".o"); | ||
| 4066 | } | ||
| 4067 | |||
| 4068 | char *err_msg = nullptr; | ||
| 4069 | if (LLVMTargetMachineEmitToFile(g->target_machine, g->module, buf_ptr(&out_file_o), | ||
| 4070 | LLVMObjectFile, &err_msg)) | ||
| 4071 | { | ||
| 4072 | zig_panic("unable to write object file: %s", err_msg); | ||
| 4073 | } | ||
| 4074 | |||
| 4075 | if (g->out_type == OutTypeObj) { | ||
| 4076 | if (g->verbose) { | ||
| 4077 | fprintf(stderr, "OK\n"); | ||
| 4078 | } | ||
| 4079 | return; | ||
| 4080 | } | ||
| 4081 | |||
| 4082 | if (g->out_type == OutTypeLib && g->is_static) { | ||
| 4083 | // invoke `ar` | ||
| 4084 | // example: | ||
| 4085 | // # static link into libfoo.a | ||
| 4086 | // ar rcs libfoo.a foo1.o foo2.o | ||
| 4087 | zig_panic("TODO invoke ar"); | ||
| 4088 | return; | ||
| 4089 | } | ||
| 4090 | |||
| 4091 | bool link_in_crt = (g->link_libc && g->out_type == OutTypeExe); | ||
| 4092 | if (link_in_crt) { | ||
| 4093 | find_libc_path(g); | ||
| 4094 | } | ||
| 4095 | |||
| 4096 | |||
| 4097 | |||
| 4098 | // invoke `ld` | ||
| 4099 | ZigList<const char *> args = {0}; | ||
| 4100 | |||
| 4101 | // TODO make this target dependent | ||
| 4102 | args.append("-m"); | ||
| 4103 | args.append("elf_x86_64"); | ||
| 4104 | |||
| 4105 | if (g->is_static) { | ||
| 4106 | args.append("-static"); | ||
| 4107 | } | ||
| 4108 | |||
| 4109 | args.append("-o"); | ||
| 4110 | args.append(out_file); | ||
| 4111 | |||
| 4112 | if (link_in_crt) { | ||
| 4113 | const char *crt1o; | ||
| 4114 | const char *crtbegino; | ||
| 4115 | if (g->is_static) { | ||
| 4116 | crt1o = "crt1.o"; | ||
| 4117 | crtbegino = "crtbeginT.o"; | ||
| 4118 | } else { | ||
| 4119 | crt1o = "Scrt1.o"; | ||
| 4120 | crtbegino = "crtbegin.o"; | ||
| 4121 | } | ||
| 4122 | args.append(get_libc_file(g, crt1o)); | ||
| 4123 | args.append(get_libc_file(g, "crti.o")); | ||
| 4124 | args.append(get_libc_static_file(g, crtbegino)); | ||
| 4125 | } | ||
| 4126 | |||
| 4127 | for (int i = 0; i < g->lib_dirs.length; i += 1) { | ||
| 4128 | const char *lib_dir = g->lib_dirs.at(i); | ||
| 4129 | args.append("-L"); | ||
| 4130 | args.append(lib_dir); | ||
| 4131 | } | ||
| 4132 | |||
| 4133 | if (g->link_libc) { | ||
| 4134 | args.append("-L"); | ||
| 4135 | args.append(buf_ptr(g->libc_lib_dir)); | ||
| 4136 | |||
| 4137 | args.append("-L"); | ||
| 4138 | args.append(buf_ptr(g->libc_static_lib_dir)); | ||
| 4139 | } | ||
| 4140 | |||
| 4141 | if (g->dynamic_linker && buf_len(g->dynamic_linker) > 0) { | ||
| 4142 | args.append("-dynamic-linker"); | ||
| 4143 | args.append(buf_ptr(g->dynamic_linker)); | ||
| 4144 | } else { | ||
| 4145 | args.append("-dynamic-linker"); | ||
| 4146 | args.append(buf_ptr(get_dynamic_linker(g->target_machine))); | ||
| 4147 | } | ||
| 4148 | |||
| 4149 | if (g->out_type == OutTypeLib) { | ||
| 4150 | Buf *out_lib_so = buf_sprintf("lib%s.so.%d.%d.%d", | ||
| 4151 | buf_ptr(g->root_out_name), g->version_major, g->version_minor, g->version_patch); | ||
| 4152 | Buf *soname = buf_sprintf("lib%s.so.%d", buf_ptr(g->root_out_name), g->version_major); | ||
| 4153 | args.append("-shared"); | ||
| 4154 | args.append("-soname"); | ||
| 4155 | args.append(buf_ptr(soname)); | ||
| 4156 | out_file = buf_ptr(out_lib_so); | ||
| 4157 | } | ||
| 4158 | |||
| 4159 | // .o files | ||
| 4160 | args.append((const char *)buf_ptr(&out_file_o)); | ||
| 4161 | |||
| 4162 | if (g->is_test_build) { | ||
| 4163 | const char *test_runner_name = g->link_libc ? "test_runner_libc" : "test_runner_nolibc"; | ||
| 4164 | Buf *test_runner_o_path = build_o(g, test_runner_name); | ||
| 4165 | args.append(buf_ptr(test_runner_o_path)); | ||
| 4166 | } | ||
| 4167 | |||
| 4168 | if (!g->link_libc && (g->out_type == OutTypeExe || g->out_type == OutTypeLib)) { | ||
| 4169 | Buf *builtin_o_path = build_o(g, "builtin"); | ||
| 4170 | args.append(buf_ptr(builtin_o_path)); | ||
| 4171 | } | ||
| 4172 | |||
| 4173 | auto it = g->link_table.entry_iterator(); | ||
| 4174 | for (;;) { | ||
| 4175 | auto *entry = it.next(); | ||
| 4176 | if (!entry) | ||
| 4177 | break; | ||
| 4178 | |||
| 4179 | // we handle libc explicitly, don't do it here | ||
| 4180 | if (!buf_eql_str(entry->key, "c")) { | ||
| 4181 | Buf *arg = buf_sprintf("-l%s", buf_ptr(entry->key)); | ||
| 4182 | args.append(buf_ptr(arg)); | ||
| 4183 | } | ||
| 4184 | } | ||
| 4185 | |||
| 4186 | |||
| 4187 | // libc dep | ||
| 4188 | if (g->link_libc) { | ||
| 4189 | if (g->is_static) { | ||
| 4190 | args.append("--start-group"); | ||
| 4191 | args.append("-lgcc"); | ||
| 4192 | args.append("-lgcc_eh"); | ||
| 4193 | args.append("-lc"); | ||
| 4194 | args.append("--end-group"); | ||
| 4195 | } else { | ||
| 4196 | args.append("-lgcc"); | ||
| 4197 | args.append("--as-needed"); | ||
| 4198 | args.append("-lgcc_s"); | ||
| 4199 | args.append("--no-as-needed"); | ||
| 4200 | args.append("-lc"); | ||
| 4201 | args.append("-lgcc"); | ||
| 4202 | args.append("--as-needed"); | ||
| 4203 | args.append("-lgcc_s"); | ||
| 4204 | args.append("--no-as-needed"); | ||
| 4205 | } | ||
| 4206 | } | ||
| 4207 | |||
| 4208 | // crt end | ||
| 4209 | if (link_in_crt) { | ||
| 4210 | args.append(get_libc_static_file(g, "crtend.o")); | ||
| 4211 | args.append(get_libc_file(g, "crtn.o")); | ||
| 4212 | } | ||
| 4213 | |||
| 4214 | if (g->verbose) { | ||
| 4215 | fprintf(stderr, "ld"); | ||
| 4216 | for (int i = 0; i < args.length; i += 1) { | ||
| 4217 | fprintf(stderr, " %s", args.at(i)); | ||
| 4218 | } | ||
| 4219 | fprintf(stderr, "\n"); | ||
| 4220 | } | ||
| 4221 | |||
| 4222 | int return_code; | ||
| 4223 | Buf ld_stderr = BUF_INIT; | ||
| 4224 | Buf ld_stdout = BUF_INIT; | ||
| 4225 | os_exec_process("ld", args, &return_code, &ld_stderr, &ld_stdout); | ||
| 4226 | |||
| 4227 | if (return_code != 0) { | ||
| 4228 | fprintf(stderr, "ld failed with return code %d\n", return_code); | ||
| 4229 | fprintf(stderr, "ld "); | ||
| 4230 | for (int i = 0; i < args.length; i += 1) { | ||
| 4231 | fprintf(stderr, "%s ", args.at(i)); | ||
| 4232 | } | ||
| 4233 | fprintf(stderr, "\n%s\n", buf_ptr(&ld_stderr)); | ||
| 4234 | exit(1); | ||
| 4235 | } else if (buf_len(&ld_stderr)) { | ||
| 4236 | fprintf(stderr, "%s\n", buf_ptr(&ld_stderr)); | ||
| 4237 | } | ||
| 4238 | |||
| 4239 | if (g->out_type == OutTypeLib) { | ||
| 4240 | generate_h_file(g); | ||
| 4241 | } | ||
| 4242 | |||
| 4243 | if (g->verbose) { | ||
| 4244 | fprintf(stderr, "OK\n"); | ||
| 4245 | } | ||
| 4246 | } |
src/codegen.hpp+7-3| ... | @@ -10,10 +10,11 @@ | ... | @@ -10,10 +10,11 @@ |
| 10 | 10 | ||
| 11 | #include "parser.hpp" | 11 | #include "parser.hpp" |
| 12 | #include "errmsg.hpp" | 12 | #include "errmsg.hpp" |
| 13 | #include "target.hpp" | ||
| 13 | 14 | ||
| 14 | #include <stdio.h> | 15 | #include <stdio.h> |
| 15 | 16 | ||
| 16 | CodeGen *codegen_create(Buf *root_source_dir); | 17 | CodeGen *codegen_create(Buf *root_source_dir, const ZigTarget *target); |
| 17 | 18 | ||
| 18 | void codegen_set_clang_argv(CodeGen *codegen, const char **args, int len); | 19 | void codegen_set_clang_argv(CodeGen *codegen, const char **args, int len); |
| 19 | void codegen_set_is_release(CodeGen *codegen, bool is_release); | 20 | void codegen_set_is_release(CodeGen *codegen, bool is_release); |
| ... | @@ -29,13 +30,16 @@ void codegen_set_libc_lib_dir(CodeGen *codegen, Buf *libc_lib_dir); | ... | @@ -29,13 +30,16 @@ void codegen_set_libc_lib_dir(CodeGen *codegen, Buf *libc_lib_dir); |
| 29 | void codegen_set_libc_static_lib_dir(CodeGen *g, Buf *libc_static_lib_dir); | 30 | void codegen_set_libc_static_lib_dir(CodeGen *g, Buf *libc_static_lib_dir); |
| 30 | void codegen_set_libc_include_dir(CodeGen *codegen, Buf *libc_include_dir); | 31 | void codegen_set_libc_include_dir(CodeGen *codegen, Buf *libc_include_dir); |
| 31 | void codegen_set_dynamic_linker(CodeGen *g, Buf *dynamic_linker); | 32 | void codegen_set_dynamic_linker(CodeGen *g, Buf *dynamic_linker); |
| 33 | void codegen_set_linker_path(CodeGen *g, Buf *linker_path); | ||
| 34 | void codegen_set_windows_subsystem(CodeGen *g, bool mwindows, bool mconsole); | ||
| 35 | void codegen_set_windows_unicode(CodeGen *g, bool municode); | ||
| 32 | void codegen_add_lib_dir(CodeGen *codegen, const char *dir); | 36 | void codegen_add_lib_dir(CodeGen *codegen, const char *dir); |
| 33 | 37 | ||
| 34 | void codegen_add_root_code(CodeGen *g, Buf *source_dir, Buf *source_basename, Buf *source_code); | 38 | void codegen_add_root_code(CodeGen *g, Buf *source_dir, Buf *source_basename, Buf *source_code); |
| 35 | 39 | ||
| 36 | void codegen_link(CodeGen *g, const char *out_file); | ||
| 37 | |||
| 38 | void codegen_parseh(CodeGen *g, Buf *src_dirname, Buf *src_basename, Buf *source_code); | 40 | void codegen_parseh(CodeGen *g, Buf *src_dirname, Buf *src_basename, Buf *source_code); |
| 39 | void codegen_render_ast(CodeGen *g, FILE *f, int indent_size); | 41 | void codegen_render_ast(CodeGen *g, FILE *f, int indent_size); |
| 40 | 42 | ||
| 43 | void codegen_generate_h_file(CodeGen *g); | ||
| 44 | |||
| 41 | #endif | 45 | #endif |
src/config.h.in+1| ... | @@ -11,6 +11,7 @@ | ... | @@ -11,6 +11,7 @@ |
| 11 | #define ZIG_LIBC_INCLUDE_DIR "@ZIG_LIBC_INCLUDE_DIR@" | 11 | #define ZIG_LIBC_INCLUDE_DIR "@ZIG_LIBC_INCLUDE_DIR@" |
| 12 | #define ZIG_LIBC_LIB_DIR "@ZIG_LIBC_LIB_DIR@" | 12 | #define ZIG_LIBC_LIB_DIR "@ZIG_LIBC_LIB_DIR@" |
| 13 | #define ZIG_LIBC_STATIC_LIB_DIR "@ZIG_LIBC_STATIC_LIB_DIR@" | 13 | #define ZIG_LIBC_STATIC_LIB_DIR "@ZIG_LIBC_STATIC_LIB_DIR@" |
| 14 | #define ZIG_LD_PATH "@ZIG_LD_PATH@" | ||
| 14 | #define ZIG_DYNAMIC_LINKER "@ZIG_DYNAMIC_LINKER@" | 15 | #define ZIG_DYNAMIC_LINKER "@ZIG_DYNAMIC_LINKER@" |
| 15 | 16 | ||
| 16 | #cmakedefine ZIG_LLVM_OLD_CXX_ABI | 17 | #cmakedefine ZIG_LLVM_OLD_CXX_ABI |
src/link.cpp created+518| ... | @@ -0,0 +1,518 @@ | ||
| 1 | /* | ||
| 2 | * Copyright (c) 2015 Andrew Kelley | ||
| 3 | * | ||
| 4 | * This file is part of zig, which is MIT licensed. | ||
| 5 | * See http://opensource.org/licenses/MIT | ||
| 6 | */ | ||
| 7 | |||
| 8 | #include "link.hpp" | ||
| 9 | #include "os.hpp" | ||
| 10 | #include "config.h" | ||
| 11 | #include "codegen.hpp" | ||
| 12 | #include "analyze.hpp" | ||
| 13 | |||
| 14 | struct LinkJob { | ||
| 15 | CodeGen *codegen; | ||
| 16 | Buf out_file; | ||
| 17 | ZigList<const char *> args; | ||
| 18 | bool link_in_crt; | ||
| 19 | Buf out_file_o; | ||
| 20 | }; | ||
| 21 | |||
| 22 | static const char *get_libc_file(CodeGen *g, const char *file) { | ||
| 23 | Buf *out_buf = buf_alloc(); | ||
| 24 | os_path_join(g->libc_lib_dir, buf_create_from_str(file), out_buf); | ||
| 25 | return buf_ptr(out_buf); | ||
| 26 | } | ||
| 27 | |||
| 28 | static const char *get_libc_static_file(CodeGen *g, const char *file) { | ||
| 29 | Buf *out_buf = buf_alloc(); | ||
| 30 | os_path_join(g->libc_static_lib_dir, buf_create_from_str(file), out_buf); | ||
| 31 | return buf_ptr(out_buf); | ||
| 32 | } | ||
| 33 | |||
| 34 | static Buf *build_o(CodeGen *parent_gen, const char *oname) { | ||
| 35 | Buf *source_basename = buf_sprintf("%s.zig", oname); | ||
| 36 | Buf *std_dir_path = buf_create_from_str(ZIG_STD_DIR); | ||
| 37 | |||
| 38 | ZigTarget *child_target = parent_gen->is_native_target ? nullptr : &parent_gen->zig_target; | ||
| 39 | CodeGen *child_gen = codegen_create(std_dir_path, child_target); | ||
| 40 | child_gen->link_libc = parent_gen->link_libc; | ||
| 41 | |||
| 42 | codegen_set_is_release(child_gen, parent_gen->is_release_build); | ||
| 43 | |||
| 44 | codegen_set_strip(child_gen, parent_gen->strip_debug_symbols); | ||
| 45 | codegen_set_is_static(child_gen, parent_gen->is_static); | ||
| 46 | |||
| 47 | codegen_set_out_type(child_gen, OutTypeObj); | ||
| 48 | codegen_set_out_name(child_gen, buf_create_from_str(oname)); | ||
| 49 | |||
| 50 | codegen_set_verbose(child_gen, parent_gen->verbose); | ||
| 51 | codegen_set_errmsg_color(child_gen, parent_gen->err_color); | ||
| 52 | |||
| 53 | Buf *full_path = buf_alloc(); | ||
| 54 | os_path_join(std_dir_path, source_basename, full_path); | ||
| 55 | Buf source_code = BUF_INIT; | ||
| 56 | if (os_fetch_file_path(full_path, &source_code)) { | ||
| 57 | zig_panic("unable to fetch file: %s\n", buf_ptr(full_path)); | ||
| 58 | } | ||
| 59 | |||
| 60 | codegen_add_root_code(child_gen, std_dir_path, source_basename, &source_code); | ||
| 61 | Buf *o_out = buf_sprintf("%s.o", oname); | ||
| 62 | codegen_link(child_gen, buf_ptr(o_out)); | ||
| 63 | |||
| 64 | return o_out; | ||
| 65 | } | ||
| 66 | |||
| 67 | static const char *get_o_file_extension(CodeGen *g) { | ||
| 68 | if (g->zig_target.environ == ZigLLVM_MSVC) { | ||
| 69 | return ".obj"; | ||
| 70 | } else { | ||
| 71 | return ".o"; | ||
| 72 | } | ||
| 73 | } | ||
| 74 | |||
| 75 | static const char *get_exe_file_extension(CodeGen *g) { | ||
| 76 | if (g->zig_target.os == ZigLLVM_Win32) { | ||
| 77 | return ".exe"; | ||
| 78 | } else { | ||
| 79 | return ""; | ||
| 80 | } | ||
| 81 | } | ||
| 82 | |||
| 83 | static void construct_linker_job_linux(LinkJob *lj) { | ||
| 84 | CodeGen *g = lj->codegen; | ||
| 85 | |||
| 86 | lj->args.append("-m"); | ||
| 87 | lj->args.append("elf_x86_64"); | ||
| 88 | |||
| 89 | if (g->is_static) { | ||
| 90 | lj->args.append("-static"); | ||
| 91 | } | ||
| 92 | |||
| 93 | lj->args.append("-o"); | ||
| 94 | lj->args.append(buf_ptr(&lj->out_file)); | ||
| 95 | |||
| 96 | if (lj->link_in_crt) { | ||
| 97 | const char *crt1o; | ||
| 98 | const char *crtbegino; | ||
| 99 | if (g->is_static) { | ||
| 100 | crt1o = "crt1.o"; | ||
| 101 | crtbegino = "crtbeginT.o"; | ||
| 102 | } else { | ||
| 103 | crt1o = "Scrt1.o"; | ||
| 104 | crtbegino = "crtbegin.o"; | ||
| 105 | } | ||
| 106 | lj->args.append(get_libc_file(g, crt1o)); | ||
| 107 | lj->args.append(get_libc_file(g, "crti.o")); | ||
| 108 | lj->args.append(get_libc_static_file(g, crtbegino)); | ||
| 109 | } | ||
| 110 | |||
| 111 | for (int i = 0; i < g->lib_dirs.length; i += 1) { | ||
| 112 | const char *lib_dir = g->lib_dirs.at(i); | ||
| 113 | lj->args.append("-L"); | ||
| 114 | lj->args.append(lib_dir); | ||
| 115 | } | ||
| 116 | |||
| 117 | if (g->link_libc) { | ||
| 118 | lj->args.append("-L"); | ||
| 119 | lj->args.append(buf_ptr(g->libc_lib_dir)); | ||
| 120 | |||
| 121 | lj->args.append("-L"); | ||
| 122 | lj->args.append(buf_ptr(g->libc_static_lib_dir)); | ||
| 123 | } | ||
| 124 | |||
| 125 | if (g->dynamic_linker && buf_len(g->dynamic_linker) > 0) { | ||
| 126 | lj->args.append("-dynamic-linker"); | ||
| 127 | lj->args.append(buf_ptr(g->dynamic_linker)); | ||
| 128 | } else { | ||
| 129 | lj->args.append("-dynamic-linker"); | ||
| 130 | lj->args.append(buf_ptr(get_dynamic_linker(g->target_machine))); | ||
| 131 | } | ||
| 132 | |||
| 133 | if (g->out_type == OutTypeLib) { | ||
| 134 | buf_resize(&lj->out_file, 0); | ||
| 135 | buf_appendf(&lj->out_file, "lib%s.so.%d.%d.%d", | ||
| 136 | buf_ptr(g->root_out_name), g->version_major, g->version_minor, g->version_patch); | ||
| 137 | Buf *soname = buf_sprintf("lib%s.so.%d", buf_ptr(g->root_out_name), g->version_major); | ||
| 138 | lj->args.append("-shared"); | ||
| 139 | lj->args.append("-soname"); | ||
| 140 | lj->args.append(buf_ptr(soname)); | ||
| 141 | } | ||
| 142 | |||
| 143 | // .o files | ||
| 144 | lj->args.append((const char *)buf_ptr(&lj->out_file_o)); | ||
| 145 | |||
| 146 | if (g->is_test_build) { | ||
| 147 | const char *test_runner_name = g->link_libc ? "test_runner_libc" : "test_runner_nolibc"; | ||
| 148 | Buf *test_runner_o_path = build_o(g, test_runner_name); | ||
| 149 | lj->args.append(buf_ptr(test_runner_o_path)); | ||
| 150 | } | ||
| 151 | |||
| 152 | if (!g->link_libc && (g->out_type == OutTypeExe || g->out_type == OutTypeLib)) { | ||
| 153 | Buf *builtin_o_path = build_o(g, "builtin"); | ||
| 154 | lj->args.append(buf_ptr(builtin_o_path)); | ||
| 155 | } | ||
| 156 | |||
| 157 | auto it = g->link_table.entry_iterator(); | ||
| 158 | for (;;) { | ||
| 159 | auto *entry = it.next(); | ||
| 160 | if (!entry) | ||
| 161 | break; | ||
| 162 | |||
| 163 | // we handle libc explicitly, don't do it here | ||
| 164 | if (!buf_eql_str(entry->key, "c")) { | ||
| 165 | Buf *arg = buf_sprintf("-l%s", buf_ptr(entry->key)); | ||
| 166 | lj->args.append(buf_ptr(arg)); | ||
| 167 | } | ||
| 168 | } | ||
| 169 | |||
| 170 | |||
| 171 | // libc dep | ||
| 172 | if (g->link_libc) { | ||
| 173 | if (g->is_static) { | ||
| 174 | lj->args.append("--start-group"); | ||
| 175 | lj->args.append("-lgcc"); | ||
| 176 | lj->args.append("-lgcc_eh"); | ||
| 177 | lj->args.append("-lc"); | ||
| 178 | lj->args.append("--end-group"); | ||
| 179 | } else { | ||
| 180 | lj->args.append("-lgcc"); | ||
| 181 | lj->args.append("--as-needed"); | ||
| 182 | lj->args.append("-lgcc_s"); | ||
| 183 | lj->args.append("--no-as-needed"); | ||
| 184 | lj->args.append("-lc"); | ||
| 185 | lj->args.append("-lgcc"); | ||
| 186 | lj->args.append("--as-needed"); | ||
| 187 | lj->args.append("-lgcc_s"); | ||
| 188 | lj->args.append("--no-as-needed"); | ||
| 189 | } | ||
| 190 | } | ||
| 191 | |||
| 192 | // crt end | ||
| 193 | if (lj->link_in_crt) { | ||
| 194 | lj->args.append(get_libc_static_file(g, "crtend.o")); | ||
| 195 | lj->args.append(get_libc_file(g, "crtn.o")); | ||
| 196 | } | ||
| 197 | } | ||
| 198 | |||
| 199 | static bool is_target_cyg_mingw(const ZigTarget *target) { | ||
| 200 | return (target->os == ZigLLVM_Win32 && target->environ == ZigLLVM_Cygnus) || | ||
| 201 | (target->os == ZigLLVM_Win32 && target->environ == ZigLLVM_GNU); | ||
| 202 | } | ||
| 203 | |||
| 204 | static void construct_linker_job_mingw(LinkJob *lj) { | ||
| 205 | CodeGen *g = lj->codegen; | ||
| 206 | |||
| 207 | if (g->zig_target.arch.arch == ZigLLVM_x86) { | ||
| 208 | lj->args.append("-m"); | ||
| 209 | lj->args.append("i386pe"); | ||
| 210 | } else if (g->zig_target.arch.arch == ZigLLVM_x86_64) { | ||
| 211 | lj->args.append("-m"); | ||
| 212 | lj->args.append("i386pep"); | ||
| 213 | } else if (g->zig_target.arch.arch == ZigLLVM_arm) { | ||
| 214 | lj->args.append("-m"); | ||
| 215 | lj->args.append("thumb2pe"); | ||
| 216 | } | ||
| 217 | |||
| 218 | if (g->windows_subsystem_windows) { | ||
| 219 | lj->args.append("--subsystem"); | ||
| 220 | lj->args.append("windows"); | ||
| 221 | } else if (g->windows_subsystem_console) { | ||
| 222 | lj->args.append("--subsystem"); | ||
| 223 | lj->args.append("console"); | ||
| 224 | } | ||
| 225 | |||
| 226 | bool dll = g->out_type == OutTypeLib; | ||
| 227 | bool shared = !g->is_static && dll; | ||
| 228 | if (g->is_static) { | ||
| 229 | lj->args.append("-Bstatic"); | ||
| 230 | } else { | ||
| 231 | if (dll) { | ||
| 232 | lj->args.append("--dll"); | ||
| 233 | } else if (shared) { | ||
| 234 | lj->args.append("--shared"); | ||
| 235 | } | ||
| 236 | lj->args.append("-Bdynamic"); | ||
| 237 | if (dll || shared) { | ||
| 238 | lj->args.append("-e"); | ||
| 239 | if (g->zig_target.arch.arch == ZigLLVM_x86) { | ||
| 240 | lj->args.append("_DllMainCRTStartup@12"); | ||
| 241 | } else { | ||
| 242 | lj->args.append("DllMainCRTStartup"); | ||
| 243 | } | ||
| 244 | lj->args.append("--enable-auto-image-base"); | ||
| 245 | } | ||
| 246 | } | ||
| 247 | |||
| 248 | lj->args.append("-o"); | ||
| 249 | lj->args.append(buf_ptr(&lj->out_file)); | ||
| 250 | |||
| 251 | if (lj->link_in_crt) { | ||
| 252 | if (shared || dll) { | ||
| 253 | lj->args.append(get_libc_file(g, "dllcrt2.o")); | ||
| 254 | } else { | ||
| 255 | if (g->windows_linker_unicode) { | ||
| 256 | lj->args.append(get_libc_file(g, "crt2u.o")); | ||
| 257 | } else { | ||
| 258 | lj->args.append(get_libc_file(g, "crt2.o")); | ||
| 259 | } | ||
| 260 | } | ||
| 261 | lj->args.append(get_libc_static_file(g, "crtbegin.o")); | ||
| 262 | } | ||
| 263 | |||
| 264 | for (int i = 0; i < g->lib_dirs.length; i += 1) { | ||
| 265 | const char *lib_dir = g->lib_dirs.at(i); | ||
| 266 | lj->args.append("-L"); | ||
| 267 | lj->args.append(lib_dir); | ||
| 268 | } | ||
| 269 | |||
| 270 | if (g->link_libc) { | ||
| 271 | lj->args.append("-L"); | ||
| 272 | lj->args.append(buf_ptr(g->libc_lib_dir)); | ||
| 273 | |||
| 274 | lj->args.append("-L"); | ||
| 275 | lj->args.append(buf_ptr(g->libc_static_lib_dir)); | ||
| 276 | } | ||
| 277 | |||
| 278 | lj->args.append((const char *)buf_ptr(&lj->out_file_o)); | ||
| 279 | |||
| 280 | if (g->link_libc) { | ||
| 281 | if (g->is_static) { | ||
| 282 | lj->args.append("--start-group"); | ||
| 283 | } | ||
| 284 | |||
| 285 | lj->args.append("-lmingw32"); | ||
| 286 | |||
| 287 | lj->args.append("-lgcc"); | ||
| 288 | bool is_android = (g->zig_target.environ == ZigLLVM_Android); | ||
| 289 | bool is_cyg_ming = is_target_cyg_mingw(&g->zig_target); | ||
| 290 | if (!g->is_static && !is_android) { | ||
| 291 | if (!is_cyg_ming) { | ||
| 292 | lj->args.append("--as-needed"); | ||
| 293 | } | ||
| 294 | //lj->args.append("-lgcc_s"); | ||
| 295 | if (!is_cyg_ming) { | ||
| 296 | lj->args.append("--no-as-needed"); | ||
| 297 | } | ||
| 298 | } | ||
| 299 | if (g->is_static && !is_android) { | ||
| 300 | //lj->args.append("-lgcc_eh"); | ||
| 301 | } | ||
| 302 | if (is_android && !g->is_static) { | ||
| 303 | lj->args.append("-ldl"); | ||
| 304 | } | ||
| 305 | |||
| 306 | lj->args.append("-lmoldname"); | ||
| 307 | lj->args.append("-lmingwex"); | ||
| 308 | lj->args.append("-lmsvcrt"); | ||
| 309 | |||
| 310 | |||
| 311 | if (g->windows_subsystem_windows) { | ||
| 312 | lj->args.append("-lgdi32"); | ||
| 313 | lj->args.append("-lcomdlg32"); | ||
| 314 | } | ||
| 315 | lj->args.append("-ladvapi32"); | ||
| 316 | lj->args.append("-lshell32"); | ||
| 317 | lj->args.append("-luser32"); | ||
| 318 | lj->args.append("-lkernel32"); | ||
| 319 | |||
| 320 | if (g->is_static) { | ||
| 321 | lj->args.append("--end-group"); | ||
| 322 | } | ||
| 323 | |||
| 324 | if (lj->link_in_crt) { | ||
| 325 | lj->args.append(get_libc_static_file(g, "crtend.o")); | ||
| 326 | } | ||
| 327 | } | ||
| 328 | } | ||
| 329 | |||
| 330 | static void construct_linker_job(LinkJob *lj) { | ||
| 331 | switch (lj->codegen->zig_target.os) { | ||
| 332 | case ZigLLVM_UnknownOS: | ||
| 333 | zig_unreachable(); | ||
| 334 | case ZigLLVM_Linux: | ||
| 335 | if (lj->codegen->zig_target.arch.arch == ZigLLVM_hexagon) { | ||
| 336 | zig_panic("TODO construct hexagon_TC linker job"); | ||
| 337 | } else { | ||
| 338 | return construct_linker_job_linux(lj); | ||
| 339 | } | ||
| 340 | case ZigLLVM_CloudABI: | ||
| 341 | zig_panic("TODO construct CloudABI linker job"); | ||
| 342 | case ZigLLVM_Darwin: | ||
| 343 | case ZigLLVM_MacOSX: | ||
| 344 | case ZigLLVM_IOS: | ||
| 345 | zig_panic("TODO construct DarwinClang linker job"); | ||
| 346 | case ZigLLVM_DragonFly: | ||
| 347 | zig_panic("TODO construct DragonFly linker job"); | ||
| 348 | case ZigLLVM_OpenBSD: | ||
| 349 | zig_panic("TODO construct OpenBSD linker job"); | ||
| 350 | case ZigLLVM_Bitrig: | ||
| 351 | zig_panic("TODO construct Bitrig linker job"); | ||
| 352 | case ZigLLVM_NetBSD: | ||
| 353 | zig_panic("TODO construct NetBSD linker job"); | ||
| 354 | case ZigLLVM_FreeBSD: | ||
| 355 | zig_panic("TODO construct FreeBSD linker job"); | ||
| 356 | case ZigLLVM_Minix: | ||
| 357 | zig_panic("TODO construct Minix linker job"); | ||
| 358 | case ZigLLVM_NaCl: | ||
| 359 | zig_panic("TODO construct NaCl_TC linker job"); | ||
| 360 | case ZigLLVM_Solaris: | ||
| 361 | zig_panic("TODO construct Solaris linker job"); | ||
| 362 | case ZigLLVM_Win32: | ||
| 363 | switch (lj->codegen->zig_target.environ) { | ||
| 364 | default: | ||
| 365 | if (lj->codegen->zig_target.oformat == ZigLLVM_ELF) { | ||
| 366 | zig_panic("TODO construct Generic_ELF linker job"); | ||
| 367 | } else if (lj->codegen->zig_target.oformat == ZigLLVM_MachO) { | ||
| 368 | zig_panic("TODO construct MachO linker job"); | ||
| 369 | } else { | ||
| 370 | zig_panic("TODO construct Generic_GCC linker job"); | ||
| 371 | } | ||
| 372 | case ZigLLVM_GNU: | ||
| 373 | return construct_linker_job_mingw(lj); | ||
| 374 | case ZigLLVM_Itanium: | ||
| 375 | zig_panic("TODO construct CrossWindowsToolChain linker job"); | ||
| 376 | case ZigLLVM_MSVC: | ||
| 377 | case ZigLLVM_UnknownEnvironment: | ||
| 378 | zig_panic("TODO construct MSVC linker job"); | ||
| 379 | } | ||
| 380 | case ZigLLVM_CUDA: | ||
| 381 | zig_panic("TODO construct Cuda linker job"); | ||
| 382 | default: | ||
| 383 | // Of these targets, Hexagon is the only one that might have | ||
| 384 | // an OS of Linux, in which case it got handled above already. | ||
| 385 | if (lj->codegen->zig_target.arch.arch == ZigLLVM_tce) { | ||
| 386 | zig_panic("TODO construct TCE linker job"); | ||
| 387 | } else if (lj->codegen->zig_target.arch.arch == ZigLLVM_hexagon) { | ||
| 388 | zig_panic("TODO construct Hexagon_TC linker job"); | ||
| 389 | } else if (lj->codegen->zig_target.arch.arch == ZigLLVM_xcore) { | ||
| 390 | zig_panic("TODO construct XCore linker job"); | ||
| 391 | } else if (lj->codegen->zig_target.arch.arch == ZigLLVM_shave) { | ||
| 392 | zig_panic("TODO construct SHAVE linker job"); | ||
| 393 | } else if (lj->codegen->zig_target.oformat == ZigLLVM_ELF) { | ||
| 394 | zig_panic("TODO construct Generic_ELF linker job"); | ||
| 395 | } else if (lj->codegen->zig_target.oformat == ZigLLVM_MachO) { | ||
| 396 | zig_panic("TODO construct MachO linker job"); | ||
| 397 | } else { | ||
| 398 | zig_panic("TODO construct Generic_GCC linker job"); | ||
| 399 | } | ||
| 400 | |||
| 401 | } | ||
| 402 | } | ||
| 403 | |||
| 404 | static void ensure_we_have_linker_path(CodeGen *g) { | ||
| 405 | if (!g->linker_path || buf_len(g->linker_path) == 0) { | ||
| 406 | zig_panic("zig does not know the path to the linker"); | ||
| 407 | } | ||
| 408 | } | ||
| 409 | |||
| 410 | void codegen_link(CodeGen *g, const char *out_file) { | ||
| 411 | LinkJob lj = {0}; | ||
| 412 | lj.codegen = g; | ||
| 413 | if (out_file) { | ||
| 414 | buf_init_from_str(&lj.out_file, out_file); | ||
| 415 | } else { | ||
| 416 | buf_resize(&lj.out_file, 0); | ||
| 417 | } | ||
| 418 | |||
| 419 | bool is_optimized = g->is_release_build; | ||
| 420 | if (is_optimized) { | ||
| 421 | if (g->verbose) { | ||
| 422 | fprintf(stderr, "\nOptimization:\n"); | ||
| 423 | fprintf(stderr, "---------------\n"); | ||
| 424 | } | ||
| 425 | |||
| 426 | LLVMZigOptimizeModule(g->target_machine, g->module); | ||
| 427 | |||
| 428 | if (g->verbose) { | ||
| 429 | LLVMDumpModule(g->module); | ||
| 430 | } | ||
| 431 | } | ||
| 432 | if (g->verbose) { | ||
| 433 | fprintf(stderr, "\nLink:\n"); | ||
| 434 | fprintf(stderr, "-------\n"); | ||
| 435 | } | ||
| 436 | |||
| 437 | if (buf_len(&lj.out_file) == 0) { | ||
| 438 | assert(g->root_out_name); | ||
| 439 | buf_init_from_buf(&lj.out_file, g->root_out_name); | ||
| 440 | buf_append_str(&lj.out_file, get_exe_file_extension(g)); | ||
| 441 | } | ||
| 442 | |||
| 443 | buf_init_from_buf(&lj.out_file_o, &lj.out_file); | ||
| 444 | |||
| 445 | if (g->out_type != OutTypeObj) { | ||
| 446 | const char *o_ext = get_o_file_extension(g); | ||
| 447 | buf_append_str(&lj.out_file_o, o_ext); | ||
| 448 | } | ||
| 449 | |||
| 450 | char *err_msg = nullptr; | ||
| 451 | if (LLVMTargetMachineEmitToFile(g->target_machine, g->module, buf_ptr(&lj.out_file_o), | ||
| 452 | LLVMObjectFile, &err_msg)) | ||
| 453 | { | ||
| 454 | zig_panic("unable to write object file: %s", err_msg); | ||
| 455 | } | ||
| 456 | |||
| 457 | if (g->out_type == OutTypeObj) { | ||
| 458 | if (g->verbose) { | ||
| 459 | fprintf(stderr, "OK\n"); | ||
| 460 | } | ||
| 461 | return; | ||
| 462 | } | ||
| 463 | |||
| 464 | if (g->out_type == OutTypeLib && g->is_static) { | ||
| 465 | // invoke `ar` | ||
| 466 | // example: | ||
| 467 | // # static link into libfoo.a | ||
| 468 | // ar rcs libfoo.a foo1.o foo2.o | ||
| 469 | zig_panic("TODO invoke ar"); | ||
| 470 | return; | ||
| 471 | } | ||
| 472 | |||
| 473 | lj.link_in_crt = (g->link_libc && g->out_type == OutTypeExe); | ||
| 474 | if (lj.link_in_crt) { | ||
| 475 | find_libc_path(g); | ||
| 476 | } | ||
| 477 | |||
| 478 | |||
| 479 | |||
| 480 | // invoke `ld` | ||
| 481 | ensure_we_have_linker_path(g); | ||
| 482 | |||
| 483 | construct_linker_job(&lj); | ||
| 484 | |||
| 485 | |||
| 486 | if (g->verbose) { | ||
| 487 | fprintf(stderr, "%s", buf_ptr(g->linker_path)); | ||
| 488 | for (int i = 0; i < lj.args.length; i += 1) { | ||
| 489 | fprintf(stderr, " %s", lj.args.at(i)); | ||
| 490 | } | ||
| 491 | fprintf(stderr, "\n"); | ||
| 492 | } | ||
| 493 | |||
| 494 | int return_code; | ||
| 495 | Buf ld_stderr = BUF_INIT; | ||
| 496 | Buf ld_stdout = BUF_INIT; | ||
| 497 | os_exec_process(buf_ptr(g->linker_path), lj.args, &return_code, &ld_stderr, &ld_stdout); | ||
| 498 | |||
| 499 | if (return_code != 0) { | ||
| 500 | fprintf(stderr, "linker failed with return code %d\n", return_code); | ||
| 501 | fprintf(stderr, "%s ", buf_ptr(g->linker_path)); | ||
| 502 | for (int i = 0; i < lj.args.length; i += 1) { | ||
| 503 | fprintf(stderr, "%s ", lj.args.at(i)); | ||
| 504 | } | ||
| 505 | fprintf(stderr, "\n%s\n", buf_ptr(&ld_stderr)); | ||
| 506 | exit(1); | ||
| 507 | } else if (buf_len(&ld_stderr)) { | ||
| 508 | fprintf(stderr, "%s\n", buf_ptr(&ld_stderr)); | ||
| 509 | } | ||
| 510 | |||
| 511 | if (g->out_type == OutTypeLib) { | ||
| 512 | codegen_generate_h_file(g); | ||
| 513 | } | ||
| 514 | |||
| 515 | if (g->verbose) { | ||
| 516 | fprintf(stderr, "OK\n"); | ||
| 517 | } | ||
| 518 | } | ||
src/link.hpp created+17| ... | @@ -0,0 +1,17 @@ | ||
| 1 | /* | ||
| 2 | * Copyright (c) 2015 Andrew Kelley | ||
| 3 | * | ||
| 4 | * This file is part of zig, which is MIT licensed. | ||
| 5 | * See http://opensource.org/licenses/MIT | ||
| 6 | */ | ||
| 7 | |||
| 8 | #ifndef ZIG_LINK_HPP | ||
| 9 | #define ZIG_LINK_HPP | ||
| 10 | |||
| 11 | #include "all_types.hpp" | ||
| 12 | |||
| 13 | void codegen_link(CodeGen *g, const char *out_file); | ||
| 14 | |||
| 15 | |||
| 16 | #endif | ||
| 17 | |||
src/main.cpp+75-16| ... | @@ -11,6 +11,7 @@ | ... | @@ -11,6 +11,7 @@ |
| 11 | #include "os.hpp" | 11 | #include "os.hpp" |
| 12 | #include "error.hpp" | 12 | #include "error.hpp" |
| 13 | #include "target.hpp" | 13 | #include "target.hpp" |
| 14 | #include "link.hpp" | ||
| 14 | 15 | ||
| 15 | #include <stdio.h> | 16 | #include <stdio.h> |
| 16 | 17 | ||
| ... | @@ -31,26 +32,27 @@ static int usage(const char *arg0) { | ... | @@ -31,26 +32,27 @@ static int usage(const char *arg0) { |
| 31 | " --output [file] override destination path\n" | 32 | " --output [file] override destination path\n" |
| 32 | " --verbose turn on compiler debug output\n" | 33 | " --verbose turn on compiler debug output\n" |
| 33 | " --color [auto|off|on] enable or disable colored error messages\n" | 34 | " --color [auto|off|on] enable or disable colored error messages\n" |
| 34 | " --libc-lib-dir [path] set the C compiler data path\n" | 35 | " --libc-lib-dir [path] directory where libc crt1.o resides\n" |
| 35 | " --libc-static-lib-dir [path] set the C compiler data path\n" | 36 | " --libc-static-lib-dir [path] directory where libc crtbeginT.o resides\n" |
| 36 | " --libc-include-dir [path] set the C compiler data path\n" | 37 | " --libc-include-dir [path] directory where libc stdlib.h resides\n" |
| 37 | " --dynamic-linker [path] set the path to ld.so\n" | 38 | " --dynamic-linker [path] set the path to ld.so\n" |
| 39 | " --ld-path [path] set the path to the linker\n" | ||
| 38 | " -isystem [dir] add additional search path for other .h files\n" | 40 | " -isystem [dir] add additional search path for other .h files\n" |
| 39 | " -dirafter [dir] same as -isystem but do it last\n" | 41 | " -dirafter [dir] same as -isystem but do it last\n" |
| 40 | " --library-path [dir] add a directory to the library search path\n" | 42 | " --library-path [dir] add a directory to the library search path\n" |
| 43 | " --target-arch [name] specify target architecture\n" | ||
| 44 | " --target-os [name] specify target operating system\n" | ||
| 45 | " --target-environ [name] specify target environment\n" | ||
| 46 | " -mwindows (windows only) --subsystem windows to the linker\n" | ||
| 47 | " -mconsole (windows only) --subsystem console to the linker\n" | ||
| 48 | " -municode (windows only) link with unicode\n" | ||
| 41 | , arg0); | 49 | , arg0); |
| 42 | return EXIT_FAILURE; | 50 | return EXIT_FAILURE; |
| 43 | } | 51 | } |
| 44 | 52 | ||
| 45 | static int print_target_list(FILE *f) { | 53 | static int print_target_list(FILE *f) { |
| 46 | ZigLLVM_ArchType native_arch_type; | 54 | ZigTarget native; |
| 47 | ZigLLVM_SubArchType native_sub_arch_type; | 55 | get_native_target(&native); |
| 48 | ZigLLVM_VendorType native_vendor_type; | ||
| 49 | ZigLLVM_OSType native_os_type; | ||
| 50 | ZigLLVM_EnvironmentType native_environ_type; | ||
| 51 | |||
| 52 | ZigLLVMGetNativeTarget(&native_arch_type, &native_sub_arch_type, &native_vendor_type, | ||
| 53 | &native_os_type, &native_environ_type); | ||
| 54 | 56 | ||
| 55 | fprintf(f, "Architectures:\n"); | 57 | fprintf(f, "Architectures:\n"); |
| 56 | int arch_count = target_arch_count(); | 58 | int arch_count = target_arch_count(); |
| ... | @@ -58,7 +60,7 @@ static int print_target_list(FILE *f) { | ... | @@ -58,7 +60,7 @@ static int print_target_list(FILE *f) { |
| 58 | const ArchType *arch = get_target_arch(arch_i); | 60 | const ArchType *arch = get_target_arch(arch_i); |
| 59 | const char *sub_arch_str = (arch->sub_arch == ZigLLVM_NoSubArch) ? | 61 | const char *sub_arch_str = (arch->sub_arch == ZigLLVM_NoSubArch) ? |
| 60 | "" : ZigLLVMGetSubArchTypeName(arch->sub_arch); | 62 | "" : ZigLLVMGetSubArchTypeName(arch->sub_arch); |
| 61 | const char *native_str = (native_arch_type == arch->arch && native_sub_arch_type == arch->sub_arch) ? | 63 | const char *native_str = (native.arch.arch == arch->arch && native.arch.sub_arch == arch->sub_arch) ? |
| 62 | " (native)" : ""; | 64 | " (native)" : ""; |
| 63 | fprintf(f, " %s%s%s\n", ZigLLVMGetArchTypeName(arch->arch), sub_arch_str, native_str); | 65 | fprintf(f, " %s%s%s\n", ZigLLVMGetArchTypeName(arch->arch), sub_arch_str, native_str); |
| 64 | } | 66 | } |
| ... | @@ -67,15 +69,15 @@ static int print_target_list(FILE *f) { | ... | @@ -67,15 +69,15 @@ static int print_target_list(FILE *f) { |
| 67 | int os_count = target_os_count(); | 69 | int os_count = target_os_count(); |
| 68 | for (int i = 0; i < os_count; i += 1) { | 70 | for (int i = 0; i < os_count; i += 1) { |
| 69 | ZigLLVM_OSType os_type = get_target_os(i); | 71 | ZigLLVM_OSType os_type = get_target_os(i); |
| 70 | const char *native_str = (native_os_type == os_type) ? " (native)" : ""; | 72 | const char *native_str = (native.os == os_type) ? " (native)" : ""; |
| 71 | fprintf(f, " %s%s\n", get_target_os_name(os_type), native_str); | 73 | fprintf(f, " %s%s\n", get_target_os_name(os_type), native_str); |
| 72 | } | 74 | } |
| 73 | 75 | ||
| 74 | fprintf(f, "\nABIs:\n"); | 76 | fprintf(f, "\nEnvironments:\n"); |
| 75 | int environ_count = target_environ_count(); | 77 | int environ_count = target_environ_count(); |
| 76 | for (int i = 0; i < environ_count; i += 1) { | 78 | for (int i = 0; i < environ_count; i += 1) { |
| 77 | ZigLLVM_EnvironmentType environ_type = get_target_environ(i); | 79 | ZigLLVM_EnvironmentType environ_type = get_target_environ(i); |
| 78 | const char *native_str = (native_environ_type == environ_type) ? " (native)" : ""; | 80 | const char *native_str = (native.environ == environ_type) ? " (native)" : ""; |
| 79 | fprintf(f, " %s%s\n", ZigLLVMGetEnvironmentTypeName(environ_type), native_str); | 81 | fprintf(f, " %s%s\n", ZigLLVMGetEnvironmentTypeName(environ_type), native_str); |
| 80 | } | 82 | } |
| 81 | 83 | ||
| ... | @@ -107,9 +109,16 @@ int main(int argc, char **argv) { | ... | @@ -107,9 +109,16 @@ int main(int argc, char **argv) { |
| 107 | const char *libc_static_lib_dir = nullptr; | 109 | const char *libc_static_lib_dir = nullptr; |
| 108 | const char *libc_include_dir = nullptr; | 110 | const char *libc_include_dir = nullptr; |
| 109 | const char *dynamic_linker = nullptr; | 111 | const char *dynamic_linker = nullptr; |
| 112 | const char *linker_path = nullptr; | ||
| 110 | ZigList<const char *> clang_argv = {0}; | 113 | ZigList<const char *> clang_argv = {0}; |
| 111 | ZigList<const char *> lib_dirs = {0}; | 114 | ZigList<const char *> lib_dirs = {0}; |
| 112 | int err; | 115 | int err; |
| 116 | const char *target_arch = nullptr; | ||
| 117 | const char *target_os = nullptr; | ||
| 118 | const char *target_environ = nullptr; | ||
| 119 | bool mwindows = false; | ||
| 120 | bool mconsole = false; | ||
| 121 | bool municode = false; | ||
| 113 | 122 | ||
| 114 | for (int i = 1; i < argc; i += 1) { | 123 | for (int i = 1; i < argc; i += 1) { |
| 115 | char *arg = argv[i]; | 124 | char *arg = argv[i]; |
| ... | @@ -123,6 +132,12 @@ int main(int argc, char **argv) { | ... | @@ -123,6 +132,12 @@ int main(int argc, char **argv) { |
| 123 | is_static = true; | 132 | is_static = true; |
| 124 | } else if (strcmp(arg, "--verbose") == 0) { | 133 | } else if (strcmp(arg, "--verbose") == 0) { |
| 125 | verbose = true; | 134 | verbose = true; |
| 135 | } else if (strcmp(arg, "-mwindows") == 0) { | ||
| 136 | mwindows = true; | ||
| 137 | } else if (strcmp(arg, "-mconsole") == 0) { | ||
| 138 | mconsole = true; | ||
| 139 | } else if (strcmp(arg, "-municode") == 0) { | ||
| 140 | municode = true; | ||
| 126 | } else if (i + 1 >= argc) { | 141 | } else if (i + 1 >= argc) { |
| 127 | return usage(arg0); | 142 | return usage(arg0); |
| 128 | } else { | 143 | } else { |
| ... | @@ -161,6 +176,8 @@ int main(int argc, char **argv) { | ... | @@ -161,6 +176,8 @@ int main(int argc, char **argv) { |
| 161 | libc_include_dir = argv[i]; | 176 | libc_include_dir = argv[i]; |
| 162 | } else if (strcmp(arg, "--dynamic-linker") == 0) { | 177 | } else if (strcmp(arg, "--dynamic-linker") == 0) { |
| 163 | dynamic_linker = argv[i]; | 178 | dynamic_linker = argv[i]; |
| 179 | } else if (strcmp(arg, "--ld-path") == 0) { | ||
| 180 | linker_path = argv[i]; | ||
| 164 | } else if (strcmp(arg, "-isystem") == 0) { | 181 | } else if (strcmp(arg, "-isystem") == 0) { |
| 165 | clang_argv.append("-isystem"); | 182 | clang_argv.append("-isystem"); |
| 166 | clang_argv.append(argv[i]); | 183 | clang_argv.append(argv[i]); |
| ... | @@ -169,7 +186,14 @@ int main(int argc, char **argv) { | ... | @@ -169,7 +186,14 @@ int main(int argc, char **argv) { |
| 169 | clang_argv.append(argv[i]); | 186 | clang_argv.append(argv[i]); |
| 170 | } else if (strcmp(arg, "--library-path") == 0) { | 187 | } else if (strcmp(arg, "--library-path") == 0) { |
| 171 | lib_dirs.append(argv[i]); | 188 | lib_dirs.append(argv[i]); |
| 189 | } else if (strcmp(arg, "--target-arch") == 0) { | ||
| 190 | target_arch = argv[i]; | ||
| 191 | } else if (strcmp(arg, "--target-os") == 0) { | ||
| 192 | target_os = argv[i]; | ||
| 193 | } else if (strcmp(arg, "--target-environ") == 0) { | ||
| 194 | target_environ = argv[i]; | ||
| 172 | } else { | 195 | } else { |
| 196 | fprintf(stderr, "Invalid argument: %s\n", arg); | ||
| 173 | return usage(arg0); | 197 | return usage(arg0); |
| 174 | } | 198 | } |
| 175 | } | 199 | } |
| ... | @@ -216,6 +240,36 @@ int main(int argc, char **argv) { | ... | @@ -216,6 +240,36 @@ int main(int argc, char **argv) { |
| 216 | if (!in_file) | 240 | if (!in_file) |
| 217 | return usage(arg0); | 241 | return usage(arg0); |
| 218 | 242 | ||
| 243 | init_all_targets(); | ||
| 244 | |||
| 245 | ZigTarget alloc_target; | ||
| 246 | ZigTarget *target; | ||
| 247 | if (!target_arch && !target_os && !target_environ) { | ||
| 248 | target = nullptr; | ||
| 249 | } else { | ||
| 250 | target = &alloc_target; | ||
| 251 | get_unknown_target(target); | ||
| 252 | if (target_arch) { | ||
| 253 | if (parse_target_arch(target_arch, &target->arch)) { | ||
| 254 | fprintf(stderr, "invalid --target-arch argument\n"); | ||
| 255 | return usage(arg0); | ||
| 256 | } | ||
| 257 | } | ||
| 258 | if (target_os) { | ||
| 259 | if (parse_target_os(target_os, &target->os)) { | ||
| 260 | fprintf(stderr, "invalid --target-os argument\n"); | ||
| 261 | return usage(arg0); | ||
| 262 | } | ||
| 263 | } | ||
| 264 | if (target_environ) { | ||
| 265 | if (parse_target_environ(target_environ, &target->environ)) { | ||
| 266 | fprintf(stderr, "invalid --target-environ argument\n"); | ||
| 267 | return usage(arg0); | ||
| 268 | } | ||
| 269 | } | ||
| 270 | } | ||
| 271 | |||
| 272 | |||
| 219 | Buf in_file_buf = BUF_INIT; | 273 | Buf in_file_buf = BUF_INIT; |
| 220 | buf_init_from_str(&in_file_buf, in_file); | 274 | buf_init_from_str(&in_file_buf, in_file); |
| 221 | 275 | ||
| ... | @@ -237,7 +291,7 @@ int main(int argc, char **argv) { | ... | @@ -237,7 +291,7 @@ int main(int argc, char **argv) { |
| 237 | } | 291 | } |
| 238 | } | 292 | } |
| 239 | 293 | ||
| 240 | CodeGen *g = codegen_create(&root_source_dir); | 294 | CodeGen *g = codegen_create(&root_source_dir, target); |
| 241 | codegen_set_is_release(g, is_release_build); | 295 | codegen_set_is_release(g, is_release_build); |
| 242 | codegen_set_is_test(g, cmd == CmdTest); | 296 | codegen_set_is_test(g, cmd == CmdTest); |
| 243 | 297 | ||
| ... | @@ -262,6 +316,8 @@ int main(int argc, char **argv) { | ... | @@ -262,6 +316,8 @@ int main(int argc, char **argv) { |
| 262 | codegen_set_libc_include_dir(g, buf_create_from_str(libc_include_dir)); | 316 | codegen_set_libc_include_dir(g, buf_create_from_str(libc_include_dir)); |
| 263 | if (dynamic_linker) | 317 | if (dynamic_linker) |
| 264 | codegen_set_dynamic_linker(g, buf_create_from_str(dynamic_linker)); | 318 | codegen_set_dynamic_linker(g, buf_create_from_str(dynamic_linker)); |
| 319 | if (linker_path) | ||
| 320 | codegen_set_linker_path(g, buf_create_from_str(linker_path)); | ||
| 265 | codegen_set_verbose(g, verbose); | 321 | codegen_set_verbose(g, verbose); |
| 266 | codegen_set_errmsg_color(g, color); | 322 | codegen_set_errmsg_color(g, color); |
| 267 | 323 | ||
| ... | @@ -269,6 +325,9 @@ int main(int argc, char **argv) { | ... | @@ -269,6 +325,9 @@ int main(int argc, char **argv) { |
| 269 | codegen_add_lib_dir(g, lib_dirs.at(i)); | 325 | codegen_add_lib_dir(g, lib_dirs.at(i)); |
| 270 | } | 326 | } |
| 271 | 327 | ||
| 328 | codegen_set_windows_subsystem(g, mwindows, mconsole); | ||
| 329 | codegen_set_windows_unicode(g, municode); | ||
| 330 | |||
| 272 | if (cmd == CmdBuild) { | 331 | if (cmd == CmdBuild) { |
| 273 | codegen_add_root_code(g, &root_source_dir, &root_source_name, &root_source_code); | 332 | codegen_add_root_code(g, &root_source_dir, &root_source_name, &root_source_code); |
| 274 | codegen_link(g, out_file); | 333 | codegen_link(g, out_file); |
src/parseh.cpp+5| ... | @@ -1540,6 +1540,11 @@ int parse_h_file(ImportTableEntry *import, ZigList<ErrorMsg *> *errors, const ch | ... | @@ -1540,6 +1540,11 @@ int parse_h_file(ImportTableEntry *import, ZigList<ErrorMsg *> *errors, const ch |
| 1540 | clang_argv.append("-Xclang"); | 1540 | clang_argv.append("-Xclang"); |
| 1541 | clang_argv.append("-detailed-preprocessing-record"); | 1541 | clang_argv.append("-detailed-preprocessing-record"); |
| 1542 | 1542 | ||
| 1543 | if (!c->codegen->is_native_target) { | ||
| 1544 | clang_argv.append("-target"); | ||
| 1545 | clang_argv.append(buf_ptr(&c->codegen->triple_str)); | ||
| 1546 | } | ||
| 1547 | |||
| 1543 | clang_argv.append(target_file); | 1548 | clang_argv.append(target_file); |
| 1544 | 1549 | ||
| 1545 | // to make the [start...end] argument work | 1550 | // to make the [start...end] argument work |
src/target.cpp+127| ... | @@ -7,6 +7,9 @@ | ... | @@ -7,6 +7,9 @@ |
| 7 | 7 | ||
| 8 | #include "target.hpp" | 8 | #include "target.hpp" |
| 9 | #include "util.hpp" | 9 | #include "util.hpp" |
| 10 | #include "error.hpp" | ||
| 11 | |||
| 12 | #include <stdio.h> | ||
| 10 | 13 | ||
| 11 | static const ArchType arch_list[] = { | 14 | static const ArchType arch_list[] = { |
| 12 | {ZigLLVM_arm, ZigLLVM_ARMSubArch_v8_1a}, | 15 | {ZigLLVM_arm, ZigLLVM_ARMSubArch_v8_1a}, |
| ... | @@ -158,3 +161,127 @@ int target_environ_count(void) { | ... | @@ -158,3 +161,127 @@ int target_environ_count(void) { |
| 158 | ZigLLVM_EnvironmentType get_target_environ(int index) { | 161 | ZigLLVM_EnvironmentType get_target_environ(int index) { |
| 159 | return environ_list[index]; | 162 | return environ_list[index]; |
| 160 | } | 163 | } |
| 164 | |||
| 165 | void get_native_target(ZigTarget *target) { | ||
| 166 | ZigLLVMGetNativeTarget( | ||
| 167 | &target->arch.arch, | ||
| 168 | &target->arch.sub_arch, | ||
| 169 | &target->vendor, | ||
| 170 | &target->os, | ||
| 171 | &target->environ, | ||
| 172 | &target->oformat); | ||
| 173 | } | ||
| 174 | |||
| 175 | void get_unknown_target(ZigTarget *target) { | ||
| 176 | target->arch.arch = ZigLLVM_UnknownArch; | ||
| 177 | target->arch.sub_arch = ZigLLVM_NoSubArch; | ||
| 178 | target->vendor = ZigLLVM_UnknownVendor; | ||
| 179 | target->os = ZigLLVM_UnknownOS; | ||
| 180 | target->environ = ZigLLVM_UnknownEnvironment; | ||
| 181 | target->oformat = ZigLLVM_UnknownObjectFormat; | ||
| 182 | } | ||
| 183 | |||
| 184 | int parse_target_arch(const char *str, ArchType *out_arch) { | ||
| 185 | for (int i = 0; i < array_length(arch_list); i += 1) { | ||
| 186 | const ArchType *arch = &arch_list[i]; | ||
| 187 | char arch_name[50]; | ||
| 188 | const char *sub_str = (arch->sub_arch == ZigLLVM_NoSubArch) ? | ||
| 189 | "" : ZigLLVMGetSubArchTypeName(arch->sub_arch); | ||
| 190 | sprintf(arch_name, "%s%s", ZigLLVMGetArchTypeName(arch->arch), sub_str); | ||
| 191 | if (strcmp(arch_name, str) == 0) { | ||
| 192 | *out_arch = *arch; | ||
| 193 | return 0; | ||
| 194 | } | ||
| 195 | } | ||
| 196 | return ErrorFileNotFound; | ||
| 197 | } | ||
| 198 | |||
| 199 | int parse_target_os(const char *str, ZigLLVM_OSType *out_os) { | ||
| 200 | for (int i = 0; i < array_length(os_list); i += 1) { | ||
| 201 | ZigLLVM_OSType os = os_list[i]; | ||
| 202 | const char *os_name = get_target_os_name(os); | ||
| 203 | if (strcmp(os_name, str) == 0) { | ||
| 204 | *out_os = os; | ||
| 205 | return 0; | ||
| 206 | } | ||
| 207 | } | ||
| 208 | return ErrorFileNotFound; | ||
| 209 | } | ||
| 210 | |||
| 211 | int parse_target_environ(const char *str, ZigLLVM_EnvironmentType *out_environ) { | ||
| 212 | for (int i = 0; i < array_length(environ_list); i += 1) { | ||
| 213 | ZigLLVM_EnvironmentType environ = environ_list[i]; | ||
| 214 | const char *environ_name = ZigLLVMGetEnvironmentTypeName(environ); | ||
| 215 | if (strcmp(environ_name, str) == 0) { | ||
| 216 | *out_environ = environ; | ||
| 217 | return 0; | ||
| 218 | } | ||
| 219 | } | ||
| 220 | return ErrorFileNotFound; | ||
| 221 | } | ||
| 222 | |||
| 223 | void init_all_targets(void) { | ||
| 224 | LLVMInitializeAllTargets(); | ||
| 225 | LLVMInitializeAllTargetInfos(); | ||
| 226 | LLVMInitializeAllTargetMCs(); | ||
| 227 | LLVMInitializeAllAsmPrinters(); | ||
| 228 | LLVMInitializeAllAsmParsers(); | ||
| 229 | } | ||
| 230 | |||
| 231 | void get_target_triple(Buf *triple, const ZigTarget *target) { | ||
| 232 | ZigLLVMGetTargetTriple(triple, target->arch.arch, target->arch.sub_arch, | ||
| 233 | target->vendor, target->os, target->environ, target->oformat); | ||
| 234 | } | ||
| 235 | |||
| 236 | static bool is_os_darwin(ZigTarget *target) { | ||
| 237 | switch (target->os) { | ||
| 238 | case ZigLLVM_Darwin: | ||
| 239 | case ZigLLVM_IOS: | ||
| 240 | case ZigLLVM_MacOSX: | ||
| 241 | return true; | ||
| 242 | default: | ||
| 243 | return false; | ||
| 244 | } | ||
| 245 | } | ||
| 246 | |||
| 247 | void resolve_target_object_format(ZigTarget *target) { | ||
| 248 | if (target->oformat != ZigLLVM_UnknownObjectFormat) { | ||
| 249 | return; | ||
| 250 | } | ||
| 251 | switch (target->arch.arch) { | ||
| 252 | default: | ||
| 253 | break; | ||
| 254 | case ZigLLVM_hexagon: | ||
| 255 | case ZigLLVM_mips: | ||
| 256 | case ZigLLVM_mipsel: | ||
| 257 | case ZigLLVM_mips64: | ||
| 258 | case ZigLLVM_mips64el: | ||
| 259 | case ZigLLVM_r600: | ||
| 260 | case ZigLLVM_amdgcn: | ||
| 261 | case ZigLLVM_sparc: | ||
| 262 | case ZigLLVM_sparcv9: | ||
| 263 | case ZigLLVM_systemz: | ||
| 264 | case ZigLLVM_xcore: | ||
| 265 | case ZigLLVM_ppc64le: | ||
| 266 | target->oformat = ZigLLVM_ELF; | ||
| 267 | return; | ||
| 268 | |||
| 269 | case ZigLLVM_ppc: | ||
| 270 | case ZigLLVM_ppc64: | ||
| 271 | if (is_os_darwin(target)) { | ||
| 272 | target->oformat = ZigLLVM_MachO; | ||
| 273 | return; | ||
| 274 | } | ||
| 275 | target->oformat = ZigLLVM_ELF; | ||
| 276 | return; | ||
| 277 | } | ||
| 278 | |||
| 279 | if (is_os_darwin(target)) { | ||
| 280 | target->oformat = ZigLLVM_MachO; | ||
| 281 | return; | ||
| 282 | } else if (target->os == ZigLLVM_Win32) { | ||
| 283 | target->oformat = ZigLLVM_COFF; | ||
| 284 | return; | ||
| 285 | } | ||
| 286 | target->oformat = ZigLLVM_ELF; | ||
| 287 | } |
src/target.hpp+24| ... | @@ -10,11 +10,21 @@ | ... | @@ -10,11 +10,21 @@ |
| 10 | 10 | ||
| 11 | #include <zig_llvm.hpp> | 11 | #include <zig_llvm.hpp> |
| 12 | 12 | ||
| 13 | struct Buf; | ||
| 14 | |||
| 13 | struct ArchType { | 15 | struct ArchType { |
| 14 | ZigLLVM_ArchType arch; | 16 | ZigLLVM_ArchType arch; |
| 15 | ZigLLVM_SubArchType sub_arch; | 17 | ZigLLVM_SubArchType sub_arch; |
| 16 | }; | 18 | }; |
| 17 | 19 | ||
| 20 | struct ZigTarget { | ||
| 21 | ArchType arch; | ||
| 22 | ZigLLVM_VendorType vendor; | ||
| 23 | ZigLLVM_OSType os; | ||
| 24 | ZigLLVM_EnvironmentType environ; | ||
| 25 | ZigLLVM_ObjectFormatType oformat; | ||
| 26 | }; | ||
| 27 | |||
| 18 | int target_arch_count(void); | 28 | int target_arch_count(void); |
| 19 | const ArchType *get_target_arch(int index); | 29 | const ArchType *get_target_arch(int index); |
| 20 | 30 | ||
| ... | @@ -28,4 +38,18 @@ const char *get_target_os_name(ZigLLVM_OSType os_type); | ... | @@ -28,4 +38,18 @@ const char *get_target_os_name(ZigLLVM_OSType os_type); |
| 28 | int target_environ_count(void); | 38 | int target_environ_count(void); |
| 29 | ZigLLVM_EnvironmentType get_target_environ(int index); | 39 | ZigLLVM_EnvironmentType get_target_environ(int index); |
| 30 | 40 | ||
| 41 | void get_native_target(ZigTarget *target); | ||
| 42 | void get_unknown_target(ZigTarget *target); | ||
| 43 | |||
| 44 | int parse_target_arch(const char *str, ArchType *arch); | ||
| 45 | int parse_target_os(const char *str, ZigLLVM_OSType *os); | ||
| 46 | int parse_target_environ(const char *str, ZigLLVM_EnvironmentType *environ); | ||
| 47 | |||
| 48 | void init_all_targets(void); | ||
| 49 | |||
| 50 | void get_target_triple(Buf *triple, const ZigTarget *target); | ||
| 51 | |||
| 52 | void resolve_target_object_format(ZigTarget *target); | ||
| 53 | |||
| 54 | |||
| 31 | #endif | 55 | #endif |
src/zig_llvm.cpp+26-1| ... | @@ -14,6 +14,7 @@ | ... | @@ -14,6 +14,7 @@ |
| 14 | 14 | ||
| 15 | #include "zig_llvm.hpp" | 15 | #include "zig_llvm.hpp" |
| 16 | 16 | ||
| 17 | |||
| 17 | /* | 18 | /* |
| 18 | * The point of this file is to contain all the LLVM C++ API interaction so that: | 19 | * The point of this file is to contain all the LLVM C++ API interaction so that: |
| 19 | * 1. The compile time of other files is kept under control. | 20 | * 1. The compile time of other files is kept under control. |
| ... | @@ -520,6 +521,11 @@ static_assert((Triple::VendorType)ZigLLVM_LastVendorType == Triple::LastVendorTy | ... | @@ -520,6 +521,11 @@ static_assert((Triple::VendorType)ZigLLVM_LastVendorType == Triple::LastVendorTy |
| 520 | static_assert((Triple::OSType)ZigLLVM_LastOSType == Triple::LastOSType, ""); | 521 | static_assert((Triple::OSType)ZigLLVM_LastOSType == Triple::LastOSType, ""); |
| 521 | static_assert((Triple::EnvironmentType)ZigLLVM_LastEnvironmentType == Triple::LastEnvironmentType, ""); | 522 | static_assert((Triple::EnvironmentType)ZigLLVM_LastEnvironmentType == Triple::LastEnvironmentType, ""); |
| 522 | 523 | ||
| 524 | static_assert((Triple::ObjectFormatType)ZigLLVM_UnknownObjectFormat == Triple::UnknownObjectFormat, ""); | ||
| 525 | static_assert((Triple::ObjectFormatType)ZigLLVM_COFF == Triple::COFF, ""); | ||
| 526 | static_assert((Triple::ObjectFormatType)ZigLLVM_ELF == Triple::ELF, ""); | ||
| 527 | static_assert((Triple::ObjectFormatType)ZigLLVM_MachO == Triple::MachO, ""); | ||
| 528 | |||
| 523 | const char *ZigLLVMGetArchTypeName(ZigLLVM_ArchType arch) { | 529 | const char *ZigLLVMGetArchTypeName(ZigLLVM_ArchType arch) { |
| 524 | return Triple::getArchTypeName((Triple::ArchType)arch); | 530 | return Triple::getArchTypeName((Triple::ArchType)arch); |
| 525 | } | 531 | } |
| ... | @@ -537,7 +543,8 @@ const char *ZigLLVMGetEnvironmentTypeName(ZigLLVM_EnvironmentType environ) { | ... | @@ -537,7 +543,8 @@ const char *ZigLLVMGetEnvironmentTypeName(ZigLLVM_EnvironmentType environ) { |
| 537 | } | 543 | } |
| 538 | 544 | ||
| 539 | void ZigLLVMGetNativeTarget(ZigLLVM_ArchType *arch_type, ZigLLVM_SubArchType *sub_arch_type, | 545 | void ZigLLVMGetNativeTarget(ZigLLVM_ArchType *arch_type, ZigLLVM_SubArchType *sub_arch_type, |
| 540 | ZigLLVM_VendorType *vendor_type, ZigLLVM_OSType *os_type, ZigLLVM_EnvironmentType *environ_type) | 546 | ZigLLVM_VendorType *vendor_type, ZigLLVM_OSType *os_type, ZigLLVM_EnvironmentType *environ_type, |
| 547 | ZigLLVM_ObjectFormatType *oformat) | ||
| 541 | { | 548 | { |
| 542 | char *native_triple = LLVMGetDefaultTargetTriple(); | 549 | char *native_triple = LLVMGetDefaultTargetTriple(); |
| 543 | Triple triple(native_triple); | 550 | Triple triple(native_triple); |
| ... | @@ -547,6 +554,7 @@ void ZigLLVMGetNativeTarget(ZigLLVM_ArchType *arch_type, ZigLLVM_SubArchType *su | ... | @@ -547,6 +554,7 @@ void ZigLLVMGetNativeTarget(ZigLLVM_ArchType *arch_type, ZigLLVM_SubArchType *su |
| 547 | *vendor_type = (ZigLLVM_VendorType)triple.getVendor(); | 554 | *vendor_type = (ZigLLVM_VendorType)triple.getVendor(); |
| 548 | *os_type = (ZigLLVM_OSType)triple.getOS(); | 555 | *os_type = (ZigLLVM_OSType)triple.getOS(); |
| 549 | *environ_type = (ZigLLVM_EnvironmentType)triple.getEnvironment(); | 556 | *environ_type = (ZigLLVM_EnvironmentType)triple.getEnvironment(); |
| 557 | *oformat = (ZigLLVM_ObjectFormatType)triple.getObjectFormat(); | ||
| 550 | 558 | ||
| 551 | free(native_triple); | 559 | free(native_triple); |
| 552 | } | 560 | } |
| ... | @@ -594,6 +602,23 @@ const char *ZigLLVMGetSubArchTypeName(ZigLLVM_SubArchType sub_arch) { | ... | @@ -594,6 +602,23 @@ const char *ZigLLVMGetSubArchTypeName(ZigLLVM_SubArchType sub_arch) { |
| 594 | 602 | ||
| 595 | #include "buffer.hpp" | 603 | #include "buffer.hpp" |
| 596 | 604 | ||
| 605 | void ZigLLVMGetTargetTriple(Buf *out_buf, ZigLLVM_ArchType arch_type, ZigLLVM_SubArchType sub_arch_type, | ||
| 606 | ZigLLVM_VendorType vendor_type, ZigLLVM_OSType os_type, ZigLLVM_EnvironmentType environ_type, | ||
| 607 | ZigLLVM_ObjectFormatType oformat) | ||
| 608 | { | ||
| 609 | Triple triple; | ||
| 610 | |||
| 611 | triple.setArch((Triple::ArchType)arch_type); | ||
| 612 | // TODO how to set the sub arch? | ||
| 613 | triple.setVendor((Triple::VendorType)vendor_type); | ||
| 614 | triple.setOS((Triple::OSType)os_type); | ||
| 615 | triple.setEnvironment((Triple::EnvironmentType)environ_type); | ||
| 616 | triple.setObjectFormat((Triple::ObjectFormatType)oformat); | ||
| 617 | |||
| 618 | const std::string &str = triple.str(); | ||
| 619 | buf_init_from_mem(out_buf, str.c_str(), str.size()); | ||
| 620 | } | ||
| 621 | |||
| 597 | enum FloatAbi { | 622 | enum FloatAbi { |
| 598 | FloatAbiHard, | 623 | FloatAbiHard, |
| 599 | FloatAbiSoft, | 624 | FloatAbiSoft, |
src/zig_llvm.hpp+17-9| ... | @@ -189,6 +189,7 @@ enum ZigLLVM_ArchType { | ... | @@ -189,6 +189,7 @@ enum ZigLLVM_ArchType { |
| 189 | ZigLLVM_shave, // SHAVE: Movidius vector VLIW processors | 189 | ZigLLVM_shave, // SHAVE: Movidius vector VLIW processors |
| 190 | ZigLLVM_wasm32, // WebAssembly with 32-bit pointers | 190 | ZigLLVM_wasm32, // WebAssembly with 32-bit pointers |
| 191 | ZigLLVM_wasm64, // WebAssembly with 64-bit pointers | 191 | ZigLLVM_wasm64, // WebAssembly with 64-bit pointers |
| 192 | |||
| 192 | ZigLLVM_LastArchType = ZigLLVM_wasm64 | 193 | ZigLLVM_LastArchType = ZigLLVM_wasm64 |
| 193 | }; | 194 | }; |
| 194 | 195 | ||
| ... | @@ -227,6 +228,7 @@ enum ZigLLVM_VendorType { | ... | @@ -227,6 +228,7 @@ enum ZigLLVM_VendorType { |
| 227 | ZigLLVM_MipsTechnologies, | 228 | ZigLLVM_MipsTechnologies, |
| 228 | ZigLLVM_NVIDIA, | 229 | ZigLLVM_NVIDIA, |
| 229 | ZigLLVM_CSR, | 230 | ZigLLVM_CSR, |
| 231 | |||
| 230 | ZigLLVM_LastVendorType = ZigLLVM_CSR | 232 | ZigLLVM_LastVendorType = ZigLLVM_CSR |
| 231 | }; | 233 | }; |
| 232 | enum ZigLLVM_OSType { | 234 | enum ZigLLVM_OSType { |
| ... | @@ -256,6 +258,7 @@ enum ZigLLVM_OSType { | ... | @@ -256,6 +258,7 @@ enum ZigLLVM_OSType { |
| 256 | ZigLLVM_NVCL, // NVIDIA OpenCL | 258 | ZigLLVM_NVCL, // NVIDIA OpenCL |
| 257 | ZigLLVM_AMDHSA, // AMD HSA Runtime | 259 | ZigLLVM_AMDHSA, // AMD HSA Runtime |
| 258 | ZigLLVM_PS4, | 260 | ZigLLVM_PS4, |
| 261 | |||
| 259 | ZigLLVM_LastOSType = ZigLLVM_PS4 | 262 | ZigLLVM_LastOSType = ZigLLVM_PS4 |
| 260 | }; | 263 | }; |
| 261 | enum ZigLLVM_EnvironmentType { | 264 | enum ZigLLVM_EnvironmentType { |
| ... | @@ -273,14 +276,15 @@ enum ZigLLVM_EnvironmentType { | ... | @@ -273,14 +276,15 @@ enum ZigLLVM_EnvironmentType { |
| 273 | ZigLLVM_MSVC, | 276 | ZigLLVM_MSVC, |
| 274 | ZigLLVM_Itanium, | 277 | ZigLLVM_Itanium, |
| 275 | ZigLLVM_Cygnus, | 278 | ZigLLVM_Cygnus, |
| 276 | ZigLLVM_LastEnvironmentType = ZigLLVM_Cygnus | 279 | |
| 280 | ZigLLVM_LastEnvironmentType = ZigLLVM_Cygnus, | ||
| 277 | }; | 281 | }; |
| 278 | enum ZigLLVM_ObjectFormatType { | 282 | enum ZigLLVM_ObjectFormatType { |
| 279 | ZigLLVM_UnknownObjectFormat, | 283 | ZigLLVM_UnknownObjectFormat, |
| 280 | 284 | ||
| 281 | ZigLLVM_COFF, | 285 | ZigLLVM_COFF, |
| 282 | ZigLLVM_ELF, | 286 | ZigLLVM_ELF, |
| 283 | ZigLLVM_MachO, | 287 | ZigLLVM_MachO, |
| 284 | }; | 288 | }; |
| 285 | 289 | ||
| 286 | const char *ZigLLVMGetArchTypeName(ZigLLVM_ArchType arch); | 290 | const char *ZigLLVMGetArchTypeName(ZigLLVM_ArchType arch); |
| ... | @@ -289,14 +293,18 @@ const char *ZigLLVMGetVendorTypeName(ZigLLVM_VendorType vendor); | ... | @@ -289,14 +293,18 @@ const char *ZigLLVMGetVendorTypeName(ZigLLVM_VendorType vendor); |
| 289 | const char *ZigLLVMGetOSTypeName(ZigLLVM_OSType os); | 293 | const char *ZigLLVMGetOSTypeName(ZigLLVM_OSType os); |
| 290 | const char *ZigLLVMGetEnvironmentTypeName(ZigLLVM_EnvironmentType environ); | 294 | const char *ZigLLVMGetEnvironmentTypeName(ZigLLVM_EnvironmentType environ); |
| 291 | 295 | ||
| 292 | void ZigLLVMGetNativeTarget(ZigLLVM_ArchType *arch_type, ZigLLVM_SubArchType *sub_arch_type, | ||
| 293 | ZigLLVM_VendorType *vendor_type, ZigLLVM_OSType *os_type, ZigLLVM_EnvironmentType *environ_type); | ||
| 294 | |||
| 295 | |||
| 296 | /* | 296 | /* |
| 297 | * This stuff is not LLVM API but it depends on the LLVM C++ API so we put it here. | 297 | * This stuff is not LLVM API but it depends on the LLVM C++ API so we put it here. |
| 298 | */ | 298 | */ |
| 299 | struct Buf; | 299 | struct Buf; |
| 300 | void ZigLLVMGetNativeTarget(ZigLLVM_ArchType *arch_type, ZigLLVM_SubArchType *sub_arch_type, | ||
| 301 | ZigLLVM_VendorType *vendor_type, ZigLLVM_OSType *os_type, ZigLLVM_EnvironmentType *environ_type, | ||
| 302 | ZigLLVM_ObjectFormatType *oformat); | ||
| 303 | void ZigLLVMGetTargetTriple(Buf *out_buf, ZigLLVM_ArchType arch_type, ZigLLVM_SubArchType sub_arch_type, | ||
| 304 | ZigLLVM_VendorType vendor_type, ZigLLVM_OSType os_type, ZigLLVM_EnvironmentType environ_type, | ||
| 305 | ZigLLVM_ObjectFormatType oformat); | ||
| 306 | |||
| 307 | |||
| 300 | Buf *get_dynamic_linker(LLVMTargetMachineRef target_machine); | 308 | Buf *get_dynamic_linker(LLVMTargetMachineRef target_machine); |
| 301 | 309 | ||
| 302 | #endif | 310 | #endif |