authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-02-11 01:33:27-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-02-11 01:33:27-07:00
log2bf6c28bc3e535deb651d5b37e332226e0d38930
treebb206f61ac612f1c991a7c1c58176a163d51a74f
parent54a8b6a110fa779a2fc12b901b96b6e072bca7cf

ability to cross compile

hello_libc.zig can produce a windows build

14 files changed, 893 insertions(+), 309 deletions(-)

CMakeLists.txt+9
......@@ -14,6 +14,14 @@ set(ZIG_VERSION_PATCH 0)
1414set(ZIG_VERSION "${ZIG_VERSION_MAJOR}.${ZIG_VERSION_MINOR}.${ZIG_VERSION_PATCH}")
1515message("Configuring zig version ${ZIG_VERSION}")
1616
17set(ZIG_LIBC_LIB_DIR "" CACHE STRING "Default native target libc directory where crt1.o can be found")
18set(ZIG_LIBC_STATIC_LIB_DIR "" CACHE STRING "Default native target libc directory where crtbeginT.o can be found")
19set(ZIG_LIBC_INCLUDE_DIR "/usr/include" CACHE STRING "Default native target libc include directory")
20set(ZIG_LD_PATH "ld" CACHE STRING "Path to ld for the native target")
21set(ZIG_DYNAMIC_LINKER "" CACHE STRING "Override dynamic linker for native target")
22
23
24
1725find_package(llvm)
1826include_directories(${LLVM_INCLUDE_DIRS})
1927link_directories(${LLVM_LIBDIRS})
......@@ -27,6 +35,7 @@ include_directories(
2735)
2836
2937set(ZIG_SOURCES
38 "${CMAKE_SOURCE_DIR}/src/link.cpp"
3039 "${CMAKE_SOURCE_DIR}/src/target.cpp"
3140 "${CMAKE_SOURCE_DIR}/src/ast_render.cpp"
3241 "${CMAKE_SOURCE_DIR}/src/bignum.cpp"
src/all_types.hpp+8
......@@ -14,6 +14,7 @@
1414#include "hash_map.hpp"
1515#include "errmsg.hpp"
1616#include "bignum.hpp"
17#include "target.hpp"
1718
1819struct AstNode;
1920struct ImportTableEntry;
......@@ -1109,6 +1110,7 @@ struct CodeGen {
11091110 TypeTableEntry *entry_pure_error;
11101111 } builtin_types;
11111112
1113 ZigTarget zig_target;
11121114 LLVMTargetDataRef target_data_ref;
11131115 unsigned pointer_size_bytes;
11141116 bool is_big_endian;
......@@ -1120,12 +1122,18 @@ struct CodeGen {
11201122 Buf *libc_static_lib_dir;
11211123 Buf *libc_include_dir;
11221124 Buf *dynamic_linker;
1125 Buf *linker_path;
1126 Buf triple_str;
11231127 bool is_release_build;
11241128 bool is_test_build;
11251129 LLVMTargetMachineRef target_machine;
11261130 LLVMZigDIFile *dummy_di_file;
1131 bool is_native_target;
11271132 Buf *root_source_dir;
11281133 Buf *root_out_name;
1134 bool windows_subsystem_windows;
1135 bool windows_subsystem_console;
1136 bool windows_linker_unicode;
11291137
11301138 // The function definitions this module includes. There must be a corresponding
11311139 // fn_protos entry.
src/analyze.cpp+3-3
......@@ -5929,13 +5929,13 @@ bool handle_is_ptr(TypeTableEntry *type_entry) {
59295929void find_libc_path(CodeGen *g) {
59305930 // later we can handle this better by reporting an error via the normal mechanism
59315931 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.");
59335933 }
59345934 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.");
59365936 }
59375937 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.");
59395939 }
59405940}
59415941
src/codegen.cpp+56-277
......@@ -15,12 +15,14 @@
1515#include "errmsg.hpp"
1616#include "parseh.hpp"
1717#include "ast_render.hpp"
18#include "target.hpp"
19#include "link.hpp"
1820
1921#include <stdio.h>
2022#include <errno.h>
2123
2224
23CodeGen *codegen_create(Buf *root_source_dir) {
25CodeGen *codegen_create(Buf *root_source_dir, const ZigTarget *target) {
2426 CodeGen *g = allocate<CodeGen>(1);
2527 g->link_table.init(32);
2628 g->import_table.init(32);
......@@ -33,11 +35,29 @@ CodeGen *codegen_create(Buf *root_source_dir) {
3335 g->is_test_build = false;
3436 g->root_source_dir = root_source_dir;
3537 g->error_value_count = 1;
36 g->dynamic_linker = buf_create_from_str(ZIG_DYNAMIC_LINKER);
3738
38 g->libc_lib_dir = buf_create_from_str(ZIG_LIBC_LIB_DIR);
39 g->libc_static_lib_dir = buf_create_from_str(ZIG_LIBC_STATIC_LIB_DIR);
40 g->libc_include_dir = buf_create_from_str(ZIG_LIBC_INCLUDE_DIR);
39 if (target) {
40 // cross compiling, so we can't rely on all the configured stuff since
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 }
4161
4262 return g;
4363}
......@@ -95,10 +115,23 @@ void codegen_set_dynamic_linker(CodeGen *g, Buf *dynamic_linker) {
95115 g->dynamic_linker = dynamic_linker;
96116}
97117
118void codegen_set_linker_path(CodeGen *g, Buf *linker_path) {
119 g->linker_path = linker_path;
120}
121
98122void codegen_add_lib_dir(CodeGen *g, const char *dir) {
99123 g->lib_dirs.append(dir);
100124}
101125
126void codegen_set_windows_subsystem(CodeGen *g, bool mwindows, bool mconsole) {
127 g->windows_subsystem_windows = mwindows;
128 g->windows_subsystem_console = mconsole;
129}
130
131void codegen_set_windows_unicode(CodeGen *g, bool municode) {
132 g->windows_linker_unicode = municode;
133}
134
102135static LLVMValueRef gen_expr(CodeGen *g, AstNode *expr_node);
103136static LLVMValueRef gen_lvalue(CodeGen *g, AstNode *expr_node, AstNode *node, TypeTableEntry **out_type_entry);
104137static LLVMValueRef gen_field_access_expr(CodeGen *g, AstNode *node, bool is_lvalue);
......@@ -3502,34 +3535,35 @@ static void init(CodeGen *g, Buf *source_path) {
35023535 g->lib_search_paths.append(g->root_source_dir);
35033536 g->lib_search_paths.append(buf_create_from_str(ZIG_STD_DIR));
35043537
3505 LLVMInitializeAllTargets();
3506 LLVMInitializeAllTargetMCs();
3507 LLVMInitializeAllAsmPrinters();
3508 LLVMInitializeAllAsmParsers();
3509 LLVMInitializeNativeTarget();
3510
3511 char *native_triple = LLVMGetDefaultTargetTriple();
3512
35133538 g->module = LLVMModuleCreateWithName(buf_ptr(source_path));
35143539
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));
35163543
35173544 LLVMTargetRef target_ref;
35183545 char *err_msg = nullptr;
3519 if (LLVMGetTargetFromTriple(native_triple, &target_ref, &err_msg)) {
3520 zig_panic("unable to get target from triple: %s", err_msg);
3546 if (LLVMGetTargetFromTriple(buf_ptr(&g->triple_str), &target_ref, &err_msg)) {
3547 zig_panic("unable to create target based on: %s", buf_ptr(&g->triple_str));
35213548 }
35223549
35233550
3524 char *native_cpu = LLVMZigGetHostCPUName();
3525 char *native_features = LLVMZigGetNativeFeatures();
3526
35273551 LLVMCodeGenOptLevel opt_level = g->is_release_build ? LLVMCodeGenLevelAggressive : LLVMCodeGenLevelNone;
35283552
35293553 LLVMRelocMode reloc_mode = g->is_static ? LLVMRelocStatic : LLVMRelocPIC;
35303554
3531 g->target_machine = LLVMCreateTargetMachine(target_ref, native_triple,
3532 native_cpu, native_features, opt_level, reloc_mode, LLVMCodeModelDefault);
3555 const char *target_specific_cpu_args;
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);
35333567
35343568 g->target_data_ref = LLVMGetTargetMachineData(g->target_machine);
35353569
......@@ -3902,7 +3936,7 @@ static void to_c_type(CodeGen *g, AstNode *type_node, Buf *out_buf) {
39023936 }
39033937}
39043938
3905static void generate_h_file(CodeGen *g) {
3939void codegen_generate_h_file(CodeGen *g) {
39063940 assert(!g->is_test_build);
39073941
39083942 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) {
39894023 if (fclose(out_h))
39904024 zig_panic("unable to close h file: %s", strerror(errno));
39914025}
3992
3993static 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
3999static 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
4005static 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
4037void 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 @@
1010
1111#include "parser.hpp"
1212#include "errmsg.hpp"
13#include "target.hpp"
1314
1415#include <stdio.h>
1516
16CodeGen *codegen_create(Buf *root_source_dir);
17CodeGen *codegen_create(Buf *root_source_dir, const ZigTarget *target);
1718
1819void codegen_set_clang_argv(CodeGen *codegen, const char **args, int len);
1920void 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);
2930void codegen_set_libc_static_lib_dir(CodeGen *g, Buf *libc_static_lib_dir);
3031void codegen_set_libc_include_dir(CodeGen *codegen, Buf *libc_include_dir);
3132void codegen_set_dynamic_linker(CodeGen *g, Buf *dynamic_linker);
33void codegen_set_linker_path(CodeGen *g, Buf *linker_path);
34void codegen_set_windows_subsystem(CodeGen *g, bool mwindows, bool mconsole);
35void codegen_set_windows_unicode(CodeGen *g, bool municode);
3236void codegen_add_lib_dir(CodeGen *codegen, const char *dir);
3337
3438void codegen_add_root_code(CodeGen *g, Buf *source_dir, Buf *source_basename, Buf *source_code);
3539
36void codegen_link(CodeGen *g, const char *out_file);
37
3840void codegen_parseh(CodeGen *g, Buf *src_dirname, Buf *src_basename, Buf *source_code);
3941void codegen_render_ast(CodeGen *g, FILE *f, int indent_size);
4042
43void codegen_generate_h_file(CodeGen *g);
44
4145#endif
src/config.h.in+1
......@@ -11,6 +11,7 @@
1111#define ZIG_LIBC_INCLUDE_DIR "@ZIG_LIBC_INCLUDE_DIR@"
1212#define ZIG_LIBC_LIB_DIR "@ZIG_LIBC_LIB_DIR@"
1313#define ZIG_LIBC_STATIC_LIB_DIR "@ZIG_LIBC_STATIC_LIB_DIR@"
14#define ZIG_LD_PATH "@ZIG_LD_PATH@"
1415#define ZIG_DYNAMIC_LINKER "@ZIG_DYNAMIC_LINKER@"
1516
1617#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
14struct 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
22static 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
28static 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
34static 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
67static 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
75static 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
83static 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
199static 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
204static 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
330static 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
404static 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
410void 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
13void codegen_link(CodeGen *g, const char *out_file);
14
15
16#endif
17
src/main.cpp+75-16
......@@ -11,6 +11,7 @@
1111#include "os.hpp"
1212#include "error.hpp"
1313#include "target.hpp"
14#include "link.hpp"
1415
1516#include <stdio.h>
1617
......@@ -31,26 +32,27 @@ static int usage(const char *arg0) {
3132 " --output [file] override destination path\n"
3233 " --verbose turn on compiler debug output\n"
3334 " --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-static-lib-dir [path] set the C compiler data path\n"
36 " --libc-include-dir [path] set the C compiler data path\n"
35 " --libc-lib-dir [path] directory where libc crt1.o resides\n"
36 " --libc-static-lib-dir [path] directory where libc crtbeginT.o resides\n"
37 " --libc-include-dir [path] directory where libc stdlib.h resides\n"
3738 " --dynamic-linker [path] set the path to ld.so\n"
39 " --ld-path [path] set the path to the linker\n"
3840 " -isystem [dir] add additional search path for other .h files\n"
3941 " -dirafter [dir] same as -isystem but do it last\n"
4042 " --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"
4149 , arg0);
4250 return EXIT_FAILURE;
4351}
4452
4553static int print_target_list(FILE *f) {
46 ZigLLVM_ArchType native_arch_type;
47 ZigLLVM_SubArchType native_sub_arch_type;
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 ZigTarget native;
55 get_native_target(&native);
5456
5557 fprintf(f, "Architectures:\n");
5658 int arch_count = target_arch_count();
......@@ -58,7 +60,7 @@ static int print_target_list(FILE *f) {
5860 const ArchType *arch = get_target_arch(arch_i);
5961 const char *sub_arch_str = (arch->sub_arch == ZigLLVM_NoSubArch) ?
6062 "" : 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) ?
6264 " (native)" : "";
6365 fprintf(f, " %s%s%s\n", ZigLLVMGetArchTypeName(arch->arch), sub_arch_str, native_str);
6466 }
......@@ -67,15 +69,15 @@ static int print_target_list(FILE *f) {
6769 int os_count = target_os_count();
6870 for (int i = 0; i < os_count; i += 1) {
6971 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)" : "";
7173 fprintf(f, " %s%s\n", get_target_os_name(os_type), native_str);
7274 }
7375
74 fprintf(f, "\nABIs:\n");
76 fprintf(f, "\nEnvironments:\n");
7577 int environ_count = target_environ_count();
7678 for (int i = 0; i < environ_count; i += 1) {
7779 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)" : "";
7981 fprintf(f, " %s%s\n", ZigLLVMGetEnvironmentTypeName(environ_type), native_str);
8082 }
8183
......@@ -107,9 +109,16 @@ int main(int argc, char **argv) {
107109 const char *libc_static_lib_dir = nullptr;
108110 const char *libc_include_dir = nullptr;
109111 const char *dynamic_linker = nullptr;
112 const char *linker_path = nullptr;
110113 ZigList<const char *> clang_argv = {0};
111114 ZigList<const char *> lib_dirs = {0};
112115 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;
113122
114123 for (int i = 1; i < argc; i += 1) {
115124 char *arg = argv[i];
......@@ -123,6 +132,12 @@ int main(int argc, char **argv) {
123132 is_static = true;
124133 } else if (strcmp(arg, "--verbose") == 0) {
125134 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;
126141 } else if (i + 1 >= argc) {
127142 return usage(arg0);
128143 } else {
......@@ -161,6 +176,8 @@ int main(int argc, char **argv) {
161176 libc_include_dir = argv[i];
162177 } else if (strcmp(arg, "--dynamic-linker") == 0) {
163178 dynamic_linker = argv[i];
179 } else if (strcmp(arg, "--ld-path") == 0) {
180 linker_path = argv[i];
164181 } else if (strcmp(arg, "-isystem") == 0) {
165182 clang_argv.append("-isystem");
166183 clang_argv.append(argv[i]);
......@@ -169,7 +186,14 @@ int main(int argc, char **argv) {
169186 clang_argv.append(argv[i]);
170187 } else if (strcmp(arg, "--library-path") == 0) {
171188 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];
172195 } else {
196 fprintf(stderr, "Invalid argument: %s\n", arg);
173197 return usage(arg0);
174198 }
175199 }
......@@ -216,6 +240,36 @@ int main(int argc, char **argv) {
216240 if (!in_file)
217241 return usage(arg0);
218242
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
219273 Buf in_file_buf = BUF_INIT;
220274 buf_init_from_str(&in_file_buf, in_file);
221275
......@@ -237,7 +291,7 @@ int main(int argc, char **argv) {
237291 }
238292 }
239293
240 CodeGen *g = codegen_create(&root_source_dir);
294 CodeGen *g = codegen_create(&root_source_dir, target);
241295 codegen_set_is_release(g, is_release_build);
242296 codegen_set_is_test(g, cmd == CmdTest);
243297
......@@ -262,6 +316,8 @@ int main(int argc, char **argv) {
262316 codegen_set_libc_include_dir(g, buf_create_from_str(libc_include_dir));
263317 if (dynamic_linker)
264318 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));
265321 codegen_set_verbose(g, verbose);
266322 codegen_set_errmsg_color(g, color);
267323
......@@ -269,6 +325,9 @@ int main(int argc, char **argv) {
269325 codegen_add_lib_dir(g, lib_dirs.at(i));
270326 }
271327
328 codegen_set_windows_subsystem(g, mwindows, mconsole);
329 codegen_set_windows_unicode(g, municode);
330
272331 if (cmd == CmdBuild) {
273332 codegen_add_root_code(g, &root_source_dir, &root_source_name, &root_source_code);
274333 codegen_link(g, out_file);
src/parseh.cpp+5
......@@ -1540,6 +1540,11 @@ int parse_h_file(ImportTableEntry *import, ZigList<ErrorMsg *> *errors, const ch
15401540 clang_argv.append("-Xclang");
15411541 clang_argv.append("-detailed-preprocessing-record");
15421542
1543 if (!c->codegen->is_native_target) {
1544 clang_argv.append("-target");
1545 clang_argv.append(buf_ptr(&c->codegen->triple_str));
1546 }
1547
15431548 clang_argv.append(target_file);
15441549
15451550 // to make the [start...end] argument work
src/target.cpp+127
......@@ -7,6 +7,9 @@
77
88#include "target.hpp"
99#include "util.hpp"
10#include "error.hpp"
11
12#include <stdio.h>
1013
1114static const ArchType arch_list[] = {
1215 {ZigLLVM_arm, ZigLLVM_ARMSubArch_v8_1a},
......@@ -158,3 +161,127 @@ int target_environ_count(void) {
158161ZigLLVM_EnvironmentType get_target_environ(int index) {
159162 return environ_list[index];
160163}
164
165void 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
175void 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
184int 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
199int 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
211int 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
223void init_all_targets(void) {
224 LLVMInitializeAllTargets();
225 LLVMInitializeAllTargetInfos();
226 LLVMInitializeAllTargetMCs();
227 LLVMInitializeAllAsmPrinters();
228 LLVMInitializeAllAsmParsers();
229}
230
231void 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
236static 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
247void 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 @@
1010
1111#include <zig_llvm.hpp>
1212
13struct Buf;
14
1315struct ArchType {
1416 ZigLLVM_ArchType arch;
1517 ZigLLVM_SubArchType sub_arch;
1618};
1719
20struct ZigTarget {
21 ArchType arch;
22 ZigLLVM_VendorType vendor;
23 ZigLLVM_OSType os;
24 ZigLLVM_EnvironmentType environ;
25 ZigLLVM_ObjectFormatType oformat;
26};
27
1828int target_arch_count(void);
1929const ArchType *get_target_arch(int index);
2030
......@@ -28,4 +38,18 @@ const char *get_target_os_name(ZigLLVM_OSType os_type);
2838int target_environ_count(void);
2939ZigLLVM_EnvironmentType get_target_environ(int index);
3040
41void get_native_target(ZigTarget *target);
42void get_unknown_target(ZigTarget *target);
43
44int parse_target_arch(const char *str, ArchType *arch);
45int parse_target_os(const char *str, ZigLLVM_OSType *os);
46int parse_target_environ(const char *str, ZigLLVM_EnvironmentType *environ);
47
48void init_all_targets(void);
49
50void get_target_triple(Buf *triple, const ZigTarget *target);
51
52void resolve_target_object_format(ZigTarget *target);
53
54
3155#endif
src/zig_llvm.cpp+26-1
......@@ -14,6 +14,7 @@
1414
1515#include "zig_llvm.hpp"
1616
17
1718/*
1819 * The point of this file is to contain all the LLVM C++ API interaction so that:
1920 * 1. The compile time of other files is kept under control.
......@@ -520,6 +521,11 @@ static_assert((Triple::VendorType)ZigLLVM_LastVendorType == Triple::LastVendorTy
520521static_assert((Triple::OSType)ZigLLVM_LastOSType == Triple::LastOSType, "");
521522static_assert((Triple::EnvironmentType)ZigLLVM_LastEnvironmentType == Triple::LastEnvironmentType, "");
522523
524static_assert((Triple::ObjectFormatType)ZigLLVM_UnknownObjectFormat == Triple::UnknownObjectFormat, "");
525static_assert((Triple::ObjectFormatType)ZigLLVM_COFF == Triple::COFF, "");
526static_assert((Triple::ObjectFormatType)ZigLLVM_ELF == Triple::ELF, "");
527static_assert((Triple::ObjectFormatType)ZigLLVM_MachO == Triple::MachO, "");
528
523529const char *ZigLLVMGetArchTypeName(ZigLLVM_ArchType arch) {
524530 return Triple::getArchTypeName((Triple::ArchType)arch);
525531}
......@@ -537,7 +543,8 @@ const char *ZigLLVMGetEnvironmentTypeName(ZigLLVM_EnvironmentType environ) {
537543}
538544
539545void 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)
541548{
542549 char *native_triple = LLVMGetDefaultTargetTriple();
543550 Triple triple(native_triple);
......@@ -547,6 +554,7 @@ void ZigLLVMGetNativeTarget(ZigLLVM_ArchType *arch_type, ZigLLVM_SubArchType *su
547554 *vendor_type = (ZigLLVM_VendorType)triple.getVendor();
548555 *os_type = (ZigLLVM_OSType)triple.getOS();
549556 *environ_type = (ZigLLVM_EnvironmentType)triple.getEnvironment();
557 *oformat = (ZigLLVM_ObjectFormatType)triple.getObjectFormat();
550558
551559 free(native_triple);
552560}
......@@ -594,6 +602,23 @@ const char *ZigLLVMGetSubArchTypeName(ZigLLVM_SubArchType sub_arch) {
594602
595603#include "buffer.hpp"
596604
605void 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
597622enum FloatAbi {
598623 FloatAbiHard,
599624 FloatAbiSoft,
src/zig_llvm.hpp+17-9
......@@ -189,6 +189,7 @@ enum ZigLLVM_ArchType {
189189 ZigLLVM_shave, // SHAVE: Movidius vector VLIW processors
190190 ZigLLVM_wasm32, // WebAssembly with 32-bit pointers
191191 ZigLLVM_wasm64, // WebAssembly with 64-bit pointers
192
192193 ZigLLVM_LastArchType = ZigLLVM_wasm64
193194};
194195
......@@ -227,6 +228,7 @@ enum ZigLLVM_VendorType {
227228 ZigLLVM_MipsTechnologies,
228229 ZigLLVM_NVIDIA,
229230 ZigLLVM_CSR,
231
230232 ZigLLVM_LastVendorType = ZigLLVM_CSR
231233};
232234enum ZigLLVM_OSType {
......@@ -256,6 +258,7 @@ enum ZigLLVM_OSType {
256258 ZigLLVM_NVCL, // NVIDIA OpenCL
257259 ZigLLVM_AMDHSA, // AMD HSA Runtime
258260 ZigLLVM_PS4,
261
259262 ZigLLVM_LastOSType = ZigLLVM_PS4
260263};
261264enum ZigLLVM_EnvironmentType {
......@@ -273,14 +276,15 @@ enum ZigLLVM_EnvironmentType {
273276 ZigLLVM_MSVC,
274277 ZigLLVM_Itanium,
275278 ZigLLVM_Cygnus,
276 ZigLLVM_LastEnvironmentType = ZigLLVM_Cygnus
279
280 ZigLLVM_LastEnvironmentType = ZigLLVM_Cygnus,
277281};
278282enum ZigLLVM_ObjectFormatType {
279 ZigLLVM_UnknownObjectFormat,
283 ZigLLVM_UnknownObjectFormat,
280284
281 ZigLLVM_COFF,
282 ZigLLVM_ELF,
283 ZigLLVM_MachO,
285 ZigLLVM_COFF,
286 ZigLLVM_ELF,
287 ZigLLVM_MachO,
284288};
285289
286290const char *ZigLLVMGetArchTypeName(ZigLLVM_ArchType arch);
......@@ -289,14 +293,18 @@ const char *ZigLLVMGetVendorTypeName(ZigLLVM_VendorType vendor);
289293const char *ZigLLVMGetOSTypeName(ZigLLVM_OSType os);
290294const char *ZigLLVMGetEnvironmentTypeName(ZigLLVM_EnvironmentType environ);
291295
292void 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
296296/*
297297 * This stuff is not LLVM API but it depends on the LLVM C++ API so we put it here.
298298 */
299299struct Buf;
300void 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);
303void 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
300308Buf *get_dynamic_linker(LLVMTargetMachineRef target_machine);
301309
302310#endif