mirror of
https://github.com/ziglang/zig.git
synced 2025-01-31 06:11:07 +00:00
ability to cross compile
hello_libc.zig can produce a windows build
This commit is contained in:
parent
54a8b6a110
commit
2bf6c28bc3
@ -14,6 +14,14 @@ set(ZIG_VERSION_PATCH 0)
|
||||
set(ZIG_VERSION "${ZIG_VERSION_MAJOR}.${ZIG_VERSION_MINOR}.${ZIG_VERSION_PATCH}")
|
||||
message("Configuring zig version ${ZIG_VERSION}")
|
||||
|
||||
set(ZIG_LIBC_LIB_DIR "" CACHE STRING "Default native target libc directory where crt1.o can be found")
|
||||
set(ZIG_LIBC_STATIC_LIB_DIR "" CACHE STRING "Default native target libc directory where crtbeginT.o can be found")
|
||||
set(ZIG_LIBC_INCLUDE_DIR "/usr/include" CACHE STRING "Default native target libc include directory")
|
||||
set(ZIG_LD_PATH "ld" CACHE STRING "Path to ld for the native target")
|
||||
set(ZIG_DYNAMIC_LINKER "" CACHE STRING "Override dynamic linker for native target")
|
||||
|
||||
|
||||
|
||||
find_package(llvm)
|
||||
include_directories(${LLVM_INCLUDE_DIRS})
|
||||
link_directories(${LLVM_LIBDIRS})
|
||||
@ -27,6 +35,7 @@ include_directories(
|
||||
)
|
||||
|
||||
set(ZIG_SOURCES
|
||||
"${CMAKE_SOURCE_DIR}/src/link.cpp"
|
||||
"${CMAKE_SOURCE_DIR}/src/target.cpp"
|
||||
"${CMAKE_SOURCE_DIR}/src/ast_render.cpp"
|
||||
"${CMAKE_SOURCE_DIR}/src/bignum.cpp"
|
||||
|
@ -14,6 +14,7 @@
|
||||
#include "hash_map.hpp"
|
||||
#include "errmsg.hpp"
|
||||
#include "bignum.hpp"
|
||||
#include "target.hpp"
|
||||
|
||||
struct AstNode;
|
||||
struct ImportTableEntry;
|
||||
@ -1109,6 +1110,7 @@ struct CodeGen {
|
||||
TypeTableEntry *entry_pure_error;
|
||||
} builtin_types;
|
||||
|
||||
ZigTarget zig_target;
|
||||
LLVMTargetDataRef target_data_ref;
|
||||
unsigned pointer_size_bytes;
|
||||
bool is_big_endian;
|
||||
@ -1120,12 +1122,18 @@ struct CodeGen {
|
||||
Buf *libc_static_lib_dir;
|
||||
Buf *libc_include_dir;
|
||||
Buf *dynamic_linker;
|
||||
Buf *linker_path;
|
||||
Buf triple_str;
|
||||
bool is_release_build;
|
||||
bool is_test_build;
|
||||
LLVMTargetMachineRef target_machine;
|
||||
LLVMZigDIFile *dummy_di_file;
|
||||
bool is_native_target;
|
||||
Buf *root_source_dir;
|
||||
Buf *root_out_name;
|
||||
bool windows_subsystem_windows;
|
||||
bool windows_subsystem_console;
|
||||
bool windows_linker_unicode;
|
||||
|
||||
// The function definitions this module includes. There must be a corresponding
|
||||
// fn_protos entry.
|
||||
|
@ -5929,13 +5929,13 @@ bool handle_is_ptr(TypeTableEntry *type_entry) {
|
||||
void find_libc_path(CodeGen *g) {
|
||||
// later we can handle this better by reporting an error via the normal mechanism
|
||||
if (!g->libc_lib_dir || buf_len(g->libc_lib_dir) == 0) {
|
||||
zig_panic("Unable to determine libc lib path. probably need to reconfigure");
|
||||
zig_panic("Unable to determine libc lib path.");
|
||||
}
|
||||
if (!g->libc_static_lib_dir || buf_len(g->libc_static_lib_dir) == 0) {
|
||||
zig_panic("Unable to determine libc static lib path. probably need to reconfigure");
|
||||
zig_panic("Unable to determine libc static lib path.");
|
||||
}
|
||||
if (!g->libc_include_dir || buf_len(g->libc_include_dir) == 0) {
|
||||
zig_panic("Unable to determine libc include path. probably need to reconfigure");
|
||||
zig_panic("Unable to determine libc include path.");
|
||||
}
|
||||
}
|
||||
|
||||
|
333
src/codegen.cpp
333
src/codegen.cpp
@ -15,12 +15,14 @@
|
||||
#include "errmsg.hpp"
|
||||
#include "parseh.hpp"
|
||||
#include "ast_render.hpp"
|
||||
#include "target.hpp"
|
||||
#include "link.hpp"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
|
||||
|
||||
CodeGen *codegen_create(Buf *root_source_dir) {
|
||||
CodeGen *codegen_create(Buf *root_source_dir, const ZigTarget *target) {
|
||||
CodeGen *g = allocate<CodeGen>(1);
|
||||
g->link_table.init(32);
|
||||
g->import_table.init(32);
|
||||
@ -33,11 +35,29 @@ CodeGen *codegen_create(Buf *root_source_dir) {
|
||||
g->is_test_build = false;
|
||||
g->root_source_dir = root_source_dir;
|
||||
g->error_value_count = 1;
|
||||
g->dynamic_linker = buf_create_from_str(ZIG_DYNAMIC_LINKER);
|
||||
|
||||
g->libc_lib_dir = buf_create_from_str(ZIG_LIBC_LIB_DIR);
|
||||
g->libc_static_lib_dir = buf_create_from_str(ZIG_LIBC_STATIC_LIB_DIR);
|
||||
g->libc_include_dir = buf_create_from_str(ZIG_LIBC_INCLUDE_DIR);
|
||||
if (target) {
|
||||
// cross compiling, so we can't rely on all the configured stuff since
|
||||
// that's for native compilation
|
||||
g->zig_target = *target;
|
||||
resolve_target_object_format(&g->zig_target);
|
||||
|
||||
g->dynamic_linker = buf_create_from_str("");
|
||||
g->libc_lib_dir = buf_create_from_str("");
|
||||
g->libc_static_lib_dir = buf_create_from_str("");
|
||||
g->libc_include_dir = buf_create_from_str("");
|
||||
g->linker_path = buf_create_from_str("");
|
||||
} else {
|
||||
// native compilation, we can rely on the configuration stuff
|
||||
g->is_native_target = true;
|
||||
get_native_target(&g->zig_target);
|
||||
|
||||
g->dynamic_linker = buf_create_from_str(ZIG_DYNAMIC_LINKER);
|
||||
g->libc_lib_dir = buf_create_from_str(ZIG_LIBC_LIB_DIR);
|
||||
g->libc_static_lib_dir = buf_create_from_str(ZIG_LIBC_STATIC_LIB_DIR);
|
||||
g->libc_include_dir = buf_create_from_str(ZIG_LIBC_INCLUDE_DIR);
|
||||
g->linker_path = buf_create_from_str(ZIG_LD_PATH);
|
||||
}
|
||||
|
||||
return g;
|
||||
}
|
||||
@ -95,10 +115,23 @@ void codegen_set_dynamic_linker(CodeGen *g, Buf *dynamic_linker) {
|
||||
g->dynamic_linker = dynamic_linker;
|
||||
}
|
||||
|
||||
void codegen_set_linker_path(CodeGen *g, Buf *linker_path) {
|
||||
g->linker_path = linker_path;
|
||||
}
|
||||
|
||||
void codegen_add_lib_dir(CodeGen *g, const char *dir) {
|
||||
g->lib_dirs.append(dir);
|
||||
}
|
||||
|
||||
void codegen_set_windows_subsystem(CodeGen *g, bool mwindows, bool mconsole) {
|
||||
g->windows_subsystem_windows = mwindows;
|
||||
g->windows_subsystem_console = mconsole;
|
||||
}
|
||||
|
||||
void codegen_set_windows_unicode(CodeGen *g, bool municode) {
|
||||
g->windows_linker_unicode = municode;
|
||||
}
|
||||
|
||||
static LLVMValueRef gen_expr(CodeGen *g, AstNode *expr_node);
|
||||
static LLVMValueRef gen_lvalue(CodeGen *g, AstNode *expr_node, AstNode *node, TypeTableEntry **out_type_entry);
|
||||
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) {
|
||||
g->lib_search_paths.append(g->root_source_dir);
|
||||
g->lib_search_paths.append(buf_create_from_str(ZIG_STD_DIR));
|
||||
|
||||
LLVMInitializeAllTargets();
|
||||
LLVMInitializeAllTargetMCs();
|
||||
LLVMInitializeAllAsmPrinters();
|
||||
LLVMInitializeAllAsmParsers();
|
||||
LLVMInitializeNativeTarget();
|
||||
|
||||
char *native_triple = LLVMGetDefaultTargetTriple();
|
||||
|
||||
g->module = LLVMModuleCreateWithName(buf_ptr(source_path));
|
||||
|
||||
LLVMSetTarget(g->module, native_triple);
|
||||
get_target_triple(&g->triple_str, &g->zig_target);
|
||||
|
||||
LLVMSetTarget(g->module, buf_ptr(&g->triple_str));
|
||||
|
||||
LLVMTargetRef target_ref;
|
||||
char *err_msg = nullptr;
|
||||
if (LLVMGetTargetFromTriple(native_triple, &target_ref, &err_msg)) {
|
||||
zig_panic("unable to get target from triple: %s", err_msg);
|
||||
if (LLVMGetTargetFromTriple(buf_ptr(&g->triple_str), &target_ref, &err_msg)) {
|
||||
zig_panic("unable to create target based on: %s", buf_ptr(&g->triple_str));
|
||||
}
|
||||
|
||||
|
||||
char *native_cpu = LLVMZigGetHostCPUName();
|
||||
char *native_features = LLVMZigGetNativeFeatures();
|
||||
|
||||
LLVMCodeGenOptLevel opt_level = g->is_release_build ? LLVMCodeGenLevelAggressive : LLVMCodeGenLevelNone;
|
||||
|
||||
LLVMRelocMode reloc_mode = g->is_static ? LLVMRelocStatic : LLVMRelocPIC;
|
||||
|
||||
g->target_machine = LLVMCreateTargetMachine(target_ref, native_triple,
|
||||
native_cpu, native_features, opt_level, reloc_mode, LLVMCodeModelDefault);
|
||||
const char *target_specific_cpu_args;
|
||||
const char *target_specific_features;
|
||||
if (g->is_native_target) {
|
||||
target_specific_cpu_args = LLVMZigGetHostCPUName();
|
||||
target_specific_features = LLVMZigGetNativeFeatures();
|
||||
} else {
|
||||
target_specific_cpu_args = "";
|
||||
target_specific_features = "";
|
||||
}
|
||||
|
||||
g->target_machine = LLVMCreateTargetMachine(target_ref, buf_ptr(&g->triple_str),
|
||||
target_specific_cpu_args, target_specific_features, opt_level, reloc_mode, LLVMCodeModelDefault);
|
||||
|
||||
g->target_data_ref = LLVMGetTargetMachineData(g->target_machine);
|
||||
|
||||
@ -3902,7 +3936,7 @@ static void to_c_type(CodeGen *g, AstNode *type_node, Buf *out_buf) {
|
||||
}
|
||||
}
|
||||
|
||||
static void generate_h_file(CodeGen *g) {
|
||||
void codegen_generate_h_file(CodeGen *g) {
|
||||
assert(!g->is_test_build);
|
||||
|
||||
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) {
|
||||
if (fclose(out_h))
|
||||
zig_panic("unable to close h file: %s", strerror(errno));
|
||||
}
|
||||
|
||||
static const char *get_libc_file(CodeGen *g, const char *file) {
|
||||
Buf *out_buf = buf_alloc();
|
||||
os_path_join(g->libc_lib_dir, buf_create_from_str(file), out_buf);
|
||||
return buf_ptr(out_buf);
|
||||
}
|
||||
|
||||
static const char *get_libc_static_file(CodeGen *g, const char *file) {
|
||||
Buf *out_buf = buf_alloc();
|
||||
os_path_join(g->libc_static_lib_dir, buf_create_from_str(file), out_buf);
|
||||
return buf_ptr(out_buf);
|
||||
}
|
||||
|
||||
static Buf *build_o(CodeGen *parent_gen, const char *oname) {
|
||||
Buf *source_basename = buf_sprintf("%s.zig", oname);
|
||||
Buf *std_dir_path = buf_create_from_str(ZIG_STD_DIR);
|
||||
|
||||
CodeGen *child_gen = codegen_create(std_dir_path);
|
||||
child_gen->link_libc = parent_gen->link_libc;
|
||||
|
||||
codegen_set_is_release(child_gen, parent_gen->is_release_build);
|
||||
|
||||
codegen_set_strip(child_gen, parent_gen->strip_debug_symbols);
|
||||
codegen_set_is_static(child_gen, parent_gen->is_static);
|
||||
|
||||
codegen_set_out_type(child_gen, OutTypeObj);
|
||||
codegen_set_out_name(child_gen, buf_create_from_str(oname));
|
||||
|
||||
codegen_set_verbose(child_gen, parent_gen->verbose);
|
||||
codegen_set_errmsg_color(child_gen, parent_gen->err_color);
|
||||
|
||||
Buf *full_path = buf_alloc();
|
||||
os_path_join(std_dir_path, source_basename, full_path);
|
||||
Buf source_code = BUF_INIT;
|
||||
if (os_fetch_file_path(full_path, &source_code)) {
|
||||
zig_panic("unable to fetch file: %s\n", buf_ptr(full_path));
|
||||
}
|
||||
|
||||
codegen_add_root_code(child_gen, std_dir_path, source_basename, &source_code);
|
||||
Buf *o_out = buf_sprintf("%s.o", oname);
|
||||
codegen_link(child_gen, buf_ptr(o_out));
|
||||
|
||||
return o_out;
|
||||
}
|
||||
|
||||
void codegen_link(CodeGen *g, const char *out_file) {
|
||||
bool is_optimized = g->is_release_build;
|
||||
if (is_optimized) {
|
||||
if (g->verbose) {
|
||||
fprintf(stderr, "\nOptimization:\n");
|
||||
fprintf(stderr, "---------------\n");
|
||||
}
|
||||
|
||||
LLVMZigOptimizeModule(g->target_machine, g->module);
|
||||
|
||||
if (g->verbose) {
|
||||
LLVMDumpModule(g->module);
|
||||
}
|
||||
}
|
||||
if (g->verbose) {
|
||||
fprintf(stderr, "\nLink:\n");
|
||||
fprintf(stderr, "-------\n");
|
||||
}
|
||||
|
||||
if (!out_file) {
|
||||
assert(g->root_out_name);
|
||||
out_file = buf_ptr(g->root_out_name);
|
||||
}
|
||||
|
||||
Buf out_file_o = BUF_INIT;
|
||||
buf_init_from_str(&out_file_o, out_file);
|
||||
|
||||
if (g->out_type != OutTypeObj) {
|
||||
buf_append_str(&out_file_o, ".o");
|
||||
}
|
||||
|
||||
char *err_msg = nullptr;
|
||||
if (LLVMTargetMachineEmitToFile(g->target_machine, g->module, buf_ptr(&out_file_o),
|
||||
LLVMObjectFile, &err_msg))
|
||||
{
|
||||
zig_panic("unable to write object file: %s", err_msg);
|
||||
}
|
||||
|
||||
if (g->out_type == OutTypeObj) {
|
||||
if (g->verbose) {
|
||||
fprintf(stderr, "OK\n");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (g->out_type == OutTypeLib && g->is_static) {
|
||||
// invoke `ar`
|
||||
// example:
|
||||
// # static link into libfoo.a
|
||||
// ar rcs libfoo.a foo1.o foo2.o
|
||||
zig_panic("TODO invoke ar");
|
||||
return;
|
||||
}
|
||||
|
||||
bool link_in_crt = (g->link_libc && g->out_type == OutTypeExe);
|
||||
if (link_in_crt) {
|
||||
find_libc_path(g);
|
||||
}
|
||||
|
||||
|
||||
|
||||
// invoke `ld`
|
||||
ZigList<const char *> args = {0};
|
||||
|
||||
// TODO make this target dependent
|
||||
args.append("-m");
|
||||
args.append("elf_x86_64");
|
||||
|
||||
if (g->is_static) {
|
||||
args.append("-static");
|
||||
}
|
||||
|
||||
args.append("-o");
|
||||
args.append(out_file);
|
||||
|
||||
if (link_in_crt) {
|
||||
const char *crt1o;
|
||||
const char *crtbegino;
|
||||
if (g->is_static) {
|
||||
crt1o = "crt1.o";
|
||||
crtbegino = "crtbeginT.o";
|
||||
} else {
|
||||
crt1o = "Scrt1.o";
|
||||
crtbegino = "crtbegin.o";
|
||||
}
|
||||
args.append(get_libc_file(g, crt1o));
|
||||
args.append(get_libc_file(g, "crti.o"));
|
||||
args.append(get_libc_static_file(g, crtbegino));
|
||||
}
|
||||
|
||||
for (int i = 0; i < g->lib_dirs.length; i += 1) {
|
||||
const char *lib_dir = g->lib_dirs.at(i);
|
||||
args.append("-L");
|
||||
args.append(lib_dir);
|
||||
}
|
||||
|
||||
if (g->link_libc) {
|
||||
args.append("-L");
|
||||
args.append(buf_ptr(g->libc_lib_dir));
|
||||
|
||||
args.append("-L");
|
||||
args.append(buf_ptr(g->libc_static_lib_dir));
|
||||
}
|
||||
|
||||
if (g->dynamic_linker && buf_len(g->dynamic_linker) > 0) {
|
||||
args.append("-dynamic-linker");
|
||||
args.append(buf_ptr(g->dynamic_linker));
|
||||
} else {
|
||||
args.append("-dynamic-linker");
|
||||
args.append(buf_ptr(get_dynamic_linker(g->target_machine)));
|
||||
}
|
||||
|
||||
if (g->out_type == OutTypeLib) {
|
||||
Buf *out_lib_so = buf_sprintf("lib%s.so.%d.%d.%d",
|
||||
buf_ptr(g->root_out_name), g->version_major, g->version_minor, g->version_patch);
|
||||
Buf *soname = buf_sprintf("lib%s.so.%d", buf_ptr(g->root_out_name), g->version_major);
|
||||
args.append("-shared");
|
||||
args.append("-soname");
|
||||
args.append(buf_ptr(soname));
|
||||
out_file = buf_ptr(out_lib_so);
|
||||
}
|
||||
|
||||
// .o files
|
||||
args.append((const char *)buf_ptr(&out_file_o));
|
||||
|
||||
if (g->is_test_build) {
|
||||
const char *test_runner_name = g->link_libc ? "test_runner_libc" : "test_runner_nolibc";
|
||||
Buf *test_runner_o_path = build_o(g, test_runner_name);
|
||||
args.append(buf_ptr(test_runner_o_path));
|
||||
}
|
||||
|
||||
if (!g->link_libc && (g->out_type == OutTypeExe || g->out_type == OutTypeLib)) {
|
||||
Buf *builtin_o_path = build_o(g, "builtin");
|
||||
args.append(buf_ptr(builtin_o_path));
|
||||
}
|
||||
|
||||
auto it = g->link_table.entry_iterator();
|
||||
for (;;) {
|
||||
auto *entry = it.next();
|
||||
if (!entry)
|
||||
break;
|
||||
|
||||
// we handle libc explicitly, don't do it here
|
||||
if (!buf_eql_str(entry->key, "c")) {
|
||||
Buf *arg = buf_sprintf("-l%s", buf_ptr(entry->key));
|
||||
args.append(buf_ptr(arg));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// libc dep
|
||||
if (g->link_libc) {
|
||||
if (g->is_static) {
|
||||
args.append("--start-group");
|
||||
args.append("-lgcc");
|
||||
args.append("-lgcc_eh");
|
||||
args.append("-lc");
|
||||
args.append("--end-group");
|
||||
} else {
|
||||
args.append("-lgcc");
|
||||
args.append("--as-needed");
|
||||
args.append("-lgcc_s");
|
||||
args.append("--no-as-needed");
|
||||
args.append("-lc");
|
||||
args.append("-lgcc");
|
||||
args.append("--as-needed");
|
||||
args.append("-lgcc_s");
|
||||
args.append("--no-as-needed");
|
||||
}
|
||||
}
|
||||
|
||||
// crt end
|
||||
if (link_in_crt) {
|
||||
args.append(get_libc_static_file(g, "crtend.o"));
|
||||
args.append(get_libc_file(g, "crtn.o"));
|
||||
}
|
||||
|
||||
if (g->verbose) {
|
||||
fprintf(stderr, "ld");
|
||||
for (int i = 0; i < args.length; i += 1) {
|
||||
fprintf(stderr, " %s", args.at(i));
|
||||
}
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
|
||||
int return_code;
|
||||
Buf ld_stderr = BUF_INIT;
|
||||
Buf ld_stdout = BUF_INIT;
|
||||
os_exec_process("ld", args, &return_code, &ld_stderr, &ld_stdout);
|
||||
|
||||
if (return_code != 0) {
|
||||
fprintf(stderr, "ld failed with return code %d\n", return_code);
|
||||
fprintf(stderr, "ld ");
|
||||
for (int i = 0; i < args.length; i += 1) {
|
||||
fprintf(stderr, "%s ", args.at(i));
|
||||
}
|
||||
fprintf(stderr, "\n%s\n", buf_ptr(&ld_stderr));
|
||||
exit(1);
|
||||
} else if (buf_len(&ld_stderr)) {
|
||||
fprintf(stderr, "%s\n", buf_ptr(&ld_stderr));
|
||||
}
|
||||
|
||||
if (g->out_type == OutTypeLib) {
|
||||
generate_h_file(g);
|
||||
}
|
||||
|
||||
if (g->verbose) {
|
||||
fprintf(stderr, "OK\n");
|
||||
}
|
||||
}
|
||||
|
@ -10,10 +10,11 @@
|
||||
|
||||
#include "parser.hpp"
|
||||
#include "errmsg.hpp"
|
||||
#include "target.hpp"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
CodeGen *codegen_create(Buf *root_source_dir);
|
||||
CodeGen *codegen_create(Buf *root_source_dir, const ZigTarget *target);
|
||||
|
||||
void codegen_set_clang_argv(CodeGen *codegen, const char **args, int len);
|
||||
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);
|
||||
void codegen_set_libc_static_lib_dir(CodeGen *g, Buf *libc_static_lib_dir);
|
||||
void codegen_set_libc_include_dir(CodeGen *codegen, Buf *libc_include_dir);
|
||||
void codegen_set_dynamic_linker(CodeGen *g, Buf *dynamic_linker);
|
||||
void codegen_set_linker_path(CodeGen *g, Buf *linker_path);
|
||||
void codegen_set_windows_subsystem(CodeGen *g, bool mwindows, bool mconsole);
|
||||
void codegen_set_windows_unicode(CodeGen *g, bool municode);
|
||||
void codegen_add_lib_dir(CodeGen *codegen, const char *dir);
|
||||
|
||||
void codegen_add_root_code(CodeGen *g, Buf *source_dir, Buf *source_basename, Buf *source_code);
|
||||
|
||||
void codegen_link(CodeGen *g, const char *out_file);
|
||||
|
||||
void codegen_parseh(CodeGen *g, Buf *src_dirname, Buf *src_basename, Buf *source_code);
|
||||
void codegen_render_ast(CodeGen *g, FILE *f, int indent_size);
|
||||
|
||||
void codegen_generate_h_file(CodeGen *g);
|
||||
|
||||
#endif
|
||||
|
@ -11,6 +11,7 @@
|
||||
#define ZIG_LIBC_INCLUDE_DIR "@ZIG_LIBC_INCLUDE_DIR@"
|
||||
#define ZIG_LIBC_LIB_DIR "@ZIG_LIBC_LIB_DIR@"
|
||||
#define ZIG_LIBC_STATIC_LIB_DIR "@ZIG_LIBC_STATIC_LIB_DIR@"
|
||||
#define ZIG_LD_PATH "@ZIG_LD_PATH@"
|
||||
#define ZIG_DYNAMIC_LINKER "@ZIG_DYNAMIC_LINKER@"
|
||||
|
||||
#cmakedefine ZIG_LLVM_OLD_CXX_ABI
|
||||
|
518
src/link.cpp
Normal file
518
src/link.cpp
Normal file
@ -0,0 +1,518 @@
|
||||
/*
|
||||
* Copyright (c) 2015 Andrew Kelley
|
||||
*
|
||||
* This file is part of zig, which is MIT licensed.
|
||||
* See http://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
#include "link.hpp"
|
||||
#include "os.hpp"
|
||||
#include "config.h"
|
||||
#include "codegen.hpp"
|
||||
#include "analyze.hpp"
|
||||
|
||||
struct LinkJob {
|
||||
CodeGen *codegen;
|
||||
Buf out_file;
|
||||
ZigList<const char *> args;
|
||||
bool link_in_crt;
|
||||
Buf out_file_o;
|
||||
};
|
||||
|
||||
static const char *get_libc_file(CodeGen *g, const char *file) {
|
||||
Buf *out_buf = buf_alloc();
|
||||
os_path_join(g->libc_lib_dir, buf_create_from_str(file), out_buf);
|
||||
return buf_ptr(out_buf);
|
||||
}
|
||||
|
||||
static const char *get_libc_static_file(CodeGen *g, const char *file) {
|
||||
Buf *out_buf = buf_alloc();
|
||||
os_path_join(g->libc_static_lib_dir, buf_create_from_str(file), out_buf);
|
||||
return buf_ptr(out_buf);
|
||||
}
|
||||
|
||||
static Buf *build_o(CodeGen *parent_gen, const char *oname) {
|
||||
Buf *source_basename = buf_sprintf("%s.zig", oname);
|
||||
Buf *std_dir_path = buf_create_from_str(ZIG_STD_DIR);
|
||||
|
||||
ZigTarget *child_target = parent_gen->is_native_target ? nullptr : &parent_gen->zig_target;
|
||||
CodeGen *child_gen = codegen_create(std_dir_path, child_target);
|
||||
child_gen->link_libc = parent_gen->link_libc;
|
||||
|
||||
codegen_set_is_release(child_gen, parent_gen->is_release_build);
|
||||
|
||||
codegen_set_strip(child_gen, parent_gen->strip_debug_symbols);
|
||||
codegen_set_is_static(child_gen, parent_gen->is_static);
|
||||
|
||||
codegen_set_out_type(child_gen, OutTypeObj);
|
||||
codegen_set_out_name(child_gen, buf_create_from_str(oname));
|
||||
|
||||
codegen_set_verbose(child_gen, parent_gen->verbose);
|
||||
codegen_set_errmsg_color(child_gen, parent_gen->err_color);
|
||||
|
||||
Buf *full_path = buf_alloc();
|
||||
os_path_join(std_dir_path, source_basename, full_path);
|
||||
Buf source_code = BUF_INIT;
|
||||
if (os_fetch_file_path(full_path, &source_code)) {
|
||||
zig_panic("unable to fetch file: %s\n", buf_ptr(full_path));
|
||||
}
|
||||
|
||||
codegen_add_root_code(child_gen, std_dir_path, source_basename, &source_code);
|
||||
Buf *o_out = buf_sprintf("%s.o", oname);
|
||||
codegen_link(child_gen, buf_ptr(o_out));
|
||||
|
||||
return o_out;
|
||||
}
|
||||
|
||||
static const char *get_o_file_extension(CodeGen *g) {
|
||||
if (g->zig_target.environ == ZigLLVM_MSVC) {
|
||||
return ".obj";
|
||||
} else {
|
||||
return ".o";
|
||||
}
|
||||
}
|
||||
|
||||
static const char *get_exe_file_extension(CodeGen *g) {
|
||||
if (g->zig_target.os == ZigLLVM_Win32) {
|
||||
return ".exe";
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
static void construct_linker_job_linux(LinkJob *lj) {
|
||||
CodeGen *g = lj->codegen;
|
||||
|
||||
lj->args.append("-m");
|
||||
lj->args.append("elf_x86_64");
|
||||
|
||||
if (g->is_static) {
|
||||
lj->args.append("-static");
|
||||
}
|
||||
|
||||
lj->args.append("-o");
|
||||
lj->args.append(buf_ptr(&lj->out_file));
|
||||
|
||||
if (lj->link_in_crt) {
|
||||
const char *crt1o;
|
||||
const char *crtbegino;
|
||||
if (g->is_static) {
|
||||
crt1o = "crt1.o";
|
||||
crtbegino = "crtbeginT.o";
|
||||
} else {
|
||||
crt1o = "Scrt1.o";
|
||||
crtbegino = "crtbegin.o";
|
||||
}
|
||||
lj->args.append(get_libc_file(g, crt1o));
|
||||
lj->args.append(get_libc_file(g, "crti.o"));
|
||||
lj->args.append(get_libc_static_file(g, crtbegino));
|
||||
}
|
||||
|
||||
for (int i = 0; i < g->lib_dirs.length; i += 1) {
|
||||
const char *lib_dir = g->lib_dirs.at(i);
|
||||
lj->args.append("-L");
|
||||
lj->args.append(lib_dir);
|
||||
}
|
||||
|
||||
if (g->link_libc) {
|
||||
lj->args.append("-L");
|
||||
lj->args.append(buf_ptr(g->libc_lib_dir));
|
||||
|
||||
lj->args.append("-L");
|
||||
lj->args.append(buf_ptr(g->libc_static_lib_dir));
|
||||
}
|
||||
|
||||
if (g->dynamic_linker && buf_len(g->dynamic_linker) > 0) {
|
||||
lj->args.append("-dynamic-linker");
|
||||
lj->args.append(buf_ptr(g->dynamic_linker));
|
||||
} else {
|
||||
lj->args.append("-dynamic-linker");
|
||||
lj->args.append(buf_ptr(get_dynamic_linker(g->target_machine)));
|
||||
}
|
||||
|
||||
if (g->out_type == OutTypeLib) {
|
||||
buf_resize(&lj->out_file, 0);
|
||||
buf_appendf(&lj->out_file, "lib%s.so.%d.%d.%d",
|
||||
buf_ptr(g->root_out_name), g->version_major, g->version_minor, g->version_patch);
|
||||
Buf *soname = buf_sprintf("lib%s.so.%d", buf_ptr(g->root_out_name), g->version_major);
|
||||
lj->args.append("-shared");
|
||||
lj->args.append("-soname");
|
||||
lj->args.append(buf_ptr(soname));
|
||||
}
|
||||
|
||||
// .o files
|
||||
lj->args.append((const char *)buf_ptr(&lj->out_file_o));
|
||||
|
||||
if (g->is_test_build) {
|
||||
const char *test_runner_name = g->link_libc ? "test_runner_libc" : "test_runner_nolibc";
|
||||
Buf *test_runner_o_path = build_o(g, test_runner_name);
|
||||
lj->args.append(buf_ptr(test_runner_o_path));
|
||||
}
|
||||
|
||||
if (!g->link_libc && (g->out_type == OutTypeExe || g->out_type == OutTypeLib)) {
|
||||
Buf *builtin_o_path = build_o(g, "builtin");
|
||||
lj->args.append(buf_ptr(builtin_o_path));
|
||||
}
|
||||
|
||||
auto it = g->link_table.entry_iterator();
|
||||
for (;;) {
|
||||
auto *entry = it.next();
|
||||
if (!entry)
|
||||
break;
|
||||
|
||||
// we handle libc explicitly, don't do it here
|
||||
if (!buf_eql_str(entry->key, "c")) {
|
||||
Buf *arg = buf_sprintf("-l%s", buf_ptr(entry->key));
|
||||
lj->args.append(buf_ptr(arg));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// libc dep
|
||||
if (g->link_libc) {
|
||||
if (g->is_static) {
|
||||
lj->args.append("--start-group");
|
||||
lj->args.append("-lgcc");
|
||||
lj->args.append("-lgcc_eh");
|
||||
lj->args.append("-lc");
|
||||
lj->args.append("--end-group");
|
||||
} else {
|
||||
lj->args.append("-lgcc");
|
||||
lj->args.append("--as-needed");
|
||||
lj->args.append("-lgcc_s");
|
||||
lj->args.append("--no-as-needed");
|
||||
lj->args.append("-lc");
|
||||
lj->args.append("-lgcc");
|
||||
lj->args.append("--as-needed");
|
||||
lj->args.append("-lgcc_s");
|
||||
lj->args.append("--no-as-needed");
|
||||
}
|
||||
}
|
||||
|
||||
// crt end
|
||||
if (lj->link_in_crt) {
|
||||
lj->args.append(get_libc_static_file(g, "crtend.o"));
|
||||
lj->args.append(get_libc_file(g, "crtn.o"));
|
||||
}
|
||||
}
|
||||
|
||||
static bool is_target_cyg_mingw(const ZigTarget *target) {
|
||||
return (target->os == ZigLLVM_Win32 && target->environ == ZigLLVM_Cygnus) ||
|
||||
(target->os == ZigLLVM_Win32 && target->environ == ZigLLVM_GNU);
|
||||
}
|
||||
|
||||
static void construct_linker_job_mingw(LinkJob *lj) {
|
||||
CodeGen *g = lj->codegen;
|
||||
|
||||
if (g->zig_target.arch.arch == ZigLLVM_x86) {
|
||||
lj->args.append("-m");
|
||||
lj->args.append("i386pe");
|
||||
} else if (g->zig_target.arch.arch == ZigLLVM_x86_64) {
|
||||
lj->args.append("-m");
|
||||
lj->args.append("i386pep");
|
||||
} else if (g->zig_target.arch.arch == ZigLLVM_arm) {
|
||||
lj->args.append("-m");
|
||||
lj->args.append("thumb2pe");
|
||||
}
|
||||
|
||||
if (g->windows_subsystem_windows) {
|
||||
lj->args.append("--subsystem");
|
||||
lj->args.append("windows");
|
||||
} else if (g->windows_subsystem_console) {
|
||||
lj->args.append("--subsystem");
|
||||
lj->args.append("console");
|
||||
}
|
||||
|
||||
bool dll = g->out_type == OutTypeLib;
|
||||
bool shared = !g->is_static && dll;
|
||||
if (g->is_static) {
|
||||
lj->args.append("-Bstatic");
|
||||
} else {
|
||||
if (dll) {
|
||||
lj->args.append("--dll");
|
||||
} else if (shared) {
|
||||
lj->args.append("--shared");
|
||||
}
|
||||
lj->args.append("-Bdynamic");
|
||||
if (dll || shared) {
|
||||
lj->args.append("-e");
|
||||
if (g->zig_target.arch.arch == ZigLLVM_x86) {
|
||||
lj->args.append("_DllMainCRTStartup@12");
|
||||
} else {
|
||||
lj->args.append("DllMainCRTStartup");
|
||||
}
|
||||
lj->args.append("--enable-auto-image-base");
|
||||
}
|
||||
}
|
||||
|
||||
lj->args.append("-o");
|
||||
lj->args.append(buf_ptr(&lj->out_file));
|
||||
|
||||
if (lj->link_in_crt) {
|
||||
if (shared || dll) {
|
||||
lj->args.append(get_libc_file(g, "dllcrt2.o"));
|
||||
} else {
|
||||
if (g->windows_linker_unicode) {
|
||||
lj->args.append(get_libc_file(g, "crt2u.o"));
|
||||
} else {
|
||||
lj->args.append(get_libc_file(g, "crt2.o"));
|
||||
}
|
||||
}
|
||||
lj->args.append(get_libc_static_file(g, "crtbegin.o"));
|
||||
}
|
||||
|
||||
for (int i = 0; i < g->lib_dirs.length; i += 1) {
|
||||
const char *lib_dir = g->lib_dirs.at(i);
|
||||
lj->args.append("-L");
|
||||
lj->args.append(lib_dir);
|
||||
}
|
||||
|
||||
if (g->link_libc) {
|
||||
lj->args.append("-L");
|
||||
lj->args.append(buf_ptr(g->libc_lib_dir));
|
||||
|
||||
lj->args.append("-L");
|
||||
lj->args.append(buf_ptr(g->libc_static_lib_dir));
|
||||
}
|
||||
|
||||
lj->args.append((const char *)buf_ptr(&lj->out_file_o));
|
||||
|
||||
if (g->link_libc) {
|
||||
if (g->is_static) {
|
||||
lj->args.append("--start-group");
|
||||
}
|
||||
|
||||
lj->args.append("-lmingw32");
|
||||
|
||||
lj->args.append("-lgcc");
|
||||
bool is_android = (g->zig_target.environ == ZigLLVM_Android);
|
||||
bool is_cyg_ming = is_target_cyg_mingw(&g->zig_target);
|
||||
if (!g->is_static && !is_android) {
|
||||
if (!is_cyg_ming) {
|
||||
lj->args.append("--as-needed");
|
||||
}
|
||||
//lj->args.append("-lgcc_s");
|
||||
if (!is_cyg_ming) {
|
||||
lj->args.append("--no-as-needed");
|
||||
}
|
||||
}
|
||||
if (g->is_static && !is_android) {
|
||||
//lj->args.append("-lgcc_eh");
|
||||
}
|
||||
if (is_android && !g->is_static) {
|
||||
lj->args.append("-ldl");
|
||||
}
|
||||
|
||||
lj->args.append("-lmoldname");
|
||||
lj->args.append("-lmingwex");
|
||||
lj->args.append("-lmsvcrt");
|
||||
|
||||
|
||||
if (g->windows_subsystem_windows) {
|
||||
lj->args.append("-lgdi32");
|
||||
lj->args.append("-lcomdlg32");
|
||||
}
|
||||
lj->args.append("-ladvapi32");
|
||||
lj->args.append("-lshell32");
|
||||
lj->args.append("-luser32");
|
||||
lj->args.append("-lkernel32");
|
||||
|
||||
if (g->is_static) {
|
||||
lj->args.append("--end-group");
|
||||
}
|
||||
|
||||
if (lj->link_in_crt) {
|
||||
lj->args.append(get_libc_static_file(g, "crtend.o"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void construct_linker_job(LinkJob *lj) {
|
||||
switch (lj->codegen->zig_target.os) {
|
||||
case ZigLLVM_UnknownOS:
|
||||
zig_unreachable();
|
||||
case ZigLLVM_Linux:
|
||||
if (lj->codegen->zig_target.arch.arch == ZigLLVM_hexagon) {
|
||||
zig_panic("TODO construct hexagon_TC linker job");
|
||||
} else {
|
||||
return construct_linker_job_linux(lj);
|
||||
}
|
||||
case ZigLLVM_CloudABI:
|
||||
zig_panic("TODO construct CloudABI linker job");
|
||||
case ZigLLVM_Darwin:
|
||||
case ZigLLVM_MacOSX:
|
||||
case ZigLLVM_IOS:
|
||||
zig_panic("TODO construct DarwinClang linker job");
|
||||
case ZigLLVM_DragonFly:
|
||||
zig_panic("TODO construct DragonFly linker job");
|
||||
case ZigLLVM_OpenBSD:
|
||||
zig_panic("TODO construct OpenBSD linker job");
|
||||
case ZigLLVM_Bitrig:
|
||||
zig_panic("TODO construct Bitrig linker job");
|
||||
case ZigLLVM_NetBSD:
|
||||
zig_panic("TODO construct NetBSD linker job");
|
||||
case ZigLLVM_FreeBSD:
|
||||
zig_panic("TODO construct FreeBSD linker job");
|
||||
case ZigLLVM_Minix:
|
||||
zig_panic("TODO construct Minix linker job");
|
||||
case ZigLLVM_NaCl:
|
||||
zig_panic("TODO construct NaCl_TC linker job");
|
||||
case ZigLLVM_Solaris:
|
||||
zig_panic("TODO construct Solaris linker job");
|
||||
case ZigLLVM_Win32:
|
||||
switch (lj->codegen->zig_target.environ) {
|
||||
default:
|
||||
if (lj->codegen->zig_target.oformat == ZigLLVM_ELF) {
|
||||
zig_panic("TODO construct Generic_ELF linker job");
|
||||
} else if (lj->codegen->zig_target.oformat == ZigLLVM_MachO) {
|
||||
zig_panic("TODO construct MachO linker job");
|
||||
} else {
|
||||
zig_panic("TODO construct Generic_GCC linker job");
|
||||
}
|
||||
case ZigLLVM_GNU:
|
||||
return construct_linker_job_mingw(lj);
|
||||
case ZigLLVM_Itanium:
|
||||
zig_panic("TODO construct CrossWindowsToolChain linker job");
|
||||
case ZigLLVM_MSVC:
|
||||
case ZigLLVM_UnknownEnvironment:
|
||||
zig_panic("TODO construct MSVC linker job");
|
||||
}
|
||||
case ZigLLVM_CUDA:
|
||||
zig_panic("TODO construct Cuda linker job");
|
||||
default:
|
||||
// Of these targets, Hexagon is the only one that might have
|
||||
// an OS of Linux, in which case it got handled above already.
|
||||
if (lj->codegen->zig_target.arch.arch == ZigLLVM_tce) {
|
||||
zig_panic("TODO construct TCE linker job");
|
||||
} else if (lj->codegen->zig_target.arch.arch == ZigLLVM_hexagon) {
|
||||
zig_panic("TODO construct Hexagon_TC linker job");
|
||||
} else if (lj->codegen->zig_target.arch.arch == ZigLLVM_xcore) {
|
||||
zig_panic("TODO construct XCore linker job");
|
||||
} else if (lj->codegen->zig_target.arch.arch == ZigLLVM_shave) {
|
||||
zig_panic("TODO construct SHAVE linker job");
|
||||
} else if (lj->codegen->zig_target.oformat == ZigLLVM_ELF) {
|
||||
zig_panic("TODO construct Generic_ELF linker job");
|
||||
} else if (lj->codegen->zig_target.oformat == ZigLLVM_MachO) {
|
||||
zig_panic("TODO construct MachO linker job");
|
||||
} else {
|
||||
zig_panic("TODO construct Generic_GCC linker job");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
static void ensure_we_have_linker_path(CodeGen *g) {
|
||||
if (!g->linker_path || buf_len(g->linker_path) == 0) {
|
||||
zig_panic("zig does not know the path to the linker");
|
||||
}
|
||||
}
|
||||
|
||||
void codegen_link(CodeGen *g, const char *out_file) {
|
||||
LinkJob lj = {0};
|
||||
lj.codegen = g;
|
||||
if (out_file) {
|
||||
buf_init_from_str(&lj.out_file, out_file);
|
||||
} else {
|
||||
buf_resize(&lj.out_file, 0);
|
||||
}
|
||||
|
||||
bool is_optimized = g->is_release_build;
|
||||
if (is_optimized) {
|
||||
if (g->verbose) {
|
||||
fprintf(stderr, "\nOptimization:\n");
|
||||
fprintf(stderr, "---------------\n");
|
||||
}
|
||||
|
||||
LLVMZigOptimizeModule(g->target_machine, g->module);
|
||||
|
||||
if (g->verbose) {
|
||||
LLVMDumpModule(g->module);
|
||||
}
|
||||
}
|
||||
if (g->verbose) {
|
||||
fprintf(stderr, "\nLink:\n");
|
||||
fprintf(stderr, "-------\n");
|
||||
}
|
||||
|
||||
if (buf_len(&lj.out_file) == 0) {
|
||||
assert(g->root_out_name);
|
||||
buf_init_from_buf(&lj.out_file, g->root_out_name);
|
||||
buf_append_str(&lj.out_file, get_exe_file_extension(g));
|
||||
}
|
||||
|
||||
buf_init_from_buf(&lj.out_file_o, &lj.out_file);
|
||||
|
||||
if (g->out_type != OutTypeObj) {
|
||||
const char *o_ext = get_o_file_extension(g);
|
||||
buf_append_str(&lj.out_file_o, o_ext);
|
||||
}
|
||||
|
||||
char *err_msg = nullptr;
|
||||
if (LLVMTargetMachineEmitToFile(g->target_machine, g->module, buf_ptr(&lj.out_file_o),
|
||||
LLVMObjectFile, &err_msg))
|
||||
{
|
||||
zig_panic("unable to write object file: %s", err_msg);
|
||||
}
|
||||
|
||||
if (g->out_type == OutTypeObj) {
|
||||
if (g->verbose) {
|
||||
fprintf(stderr, "OK\n");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (g->out_type == OutTypeLib && g->is_static) {
|
||||
// invoke `ar`
|
||||
// example:
|
||||
// # static link into libfoo.a
|
||||
// ar rcs libfoo.a foo1.o foo2.o
|
||||
zig_panic("TODO invoke ar");
|
||||
return;
|
||||
}
|
||||
|
||||
lj.link_in_crt = (g->link_libc && g->out_type == OutTypeExe);
|
||||
if (lj.link_in_crt) {
|
||||
find_libc_path(g);
|
||||
}
|
||||
|
||||
|
||||
|
||||
// invoke `ld`
|
||||
ensure_we_have_linker_path(g);
|
||||
|
||||
construct_linker_job(&lj);
|
||||
|
||||
|
||||
if (g->verbose) {
|
||||
fprintf(stderr, "%s", buf_ptr(g->linker_path));
|
||||
for (int i = 0; i < lj.args.length; i += 1) {
|
||||
fprintf(stderr, " %s", lj.args.at(i));
|
||||
}
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
|
||||
int return_code;
|
||||
Buf ld_stderr = BUF_INIT;
|
||||
Buf ld_stdout = BUF_INIT;
|
||||
os_exec_process(buf_ptr(g->linker_path), lj.args, &return_code, &ld_stderr, &ld_stdout);
|
||||
|
||||
if (return_code != 0) {
|
||||
fprintf(stderr, "linker failed with return code %d\n", return_code);
|
||||
fprintf(stderr, "%s ", buf_ptr(g->linker_path));
|
||||
for (int i = 0; i < lj.args.length; i += 1) {
|
||||
fprintf(stderr, "%s ", lj.args.at(i));
|
||||
}
|
||||
fprintf(stderr, "\n%s\n", buf_ptr(&ld_stderr));
|
||||
exit(1);
|
||||
} else if (buf_len(&ld_stderr)) {
|
||||
fprintf(stderr, "%s\n", buf_ptr(&ld_stderr));
|
||||
}
|
||||
|
||||
if (g->out_type == OutTypeLib) {
|
||||
codegen_generate_h_file(g);
|
||||
}
|
||||
|
||||
if (g->verbose) {
|
||||
fprintf(stderr, "OK\n");
|
||||
}
|
||||
}
|
17
src/link.hpp
Normal file
17
src/link.hpp
Normal file
@ -0,0 +1,17 @@
|
||||
/*
|
||||
* Copyright (c) 2015 Andrew Kelley
|
||||
*
|
||||
* This file is part of zig, which is MIT licensed.
|
||||
* See http://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
#ifndef ZIG_LINK_HPP
|
||||
#define ZIG_LINK_HPP
|
||||
|
||||
#include "all_types.hpp"
|
||||
|
||||
void codegen_link(CodeGen *g, const char *out_file);
|
||||
|
||||
|
||||
#endif
|
||||
|
91
src/main.cpp
91
src/main.cpp
@ -11,6 +11,7 @@
|
||||
#include "os.hpp"
|
||||
#include "error.hpp"
|
||||
#include "target.hpp"
|
||||
#include "link.hpp"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
@ -31,26 +32,27 @@ static int usage(const char *arg0) {
|
||||
" --output [file] override destination path\n"
|
||||
" --verbose turn on compiler debug output\n"
|
||||
" --color [auto|off|on] enable or disable colored error messages\n"
|
||||
" --libc-lib-dir [path] set the C compiler data path\n"
|
||||
" --libc-static-lib-dir [path] set the C compiler data path\n"
|
||||
" --libc-include-dir [path] set the C compiler data path\n"
|
||||
" --libc-lib-dir [path] directory where libc crt1.o resides\n"
|
||||
" --libc-static-lib-dir [path] directory where libc crtbeginT.o resides\n"
|
||||
" --libc-include-dir [path] directory where libc stdlib.h resides\n"
|
||||
" --dynamic-linker [path] set the path to ld.so\n"
|
||||
" --ld-path [path] set the path to the linker\n"
|
||||
" -isystem [dir] add additional search path for other .h files\n"
|
||||
" -dirafter [dir] same as -isystem but do it last\n"
|
||||
" --library-path [dir] add a directory to the library search path\n"
|
||||
" --target-arch [name] specify target architecture\n"
|
||||
" --target-os [name] specify target operating system\n"
|
||||
" --target-environ [name] specify target environment\n"
|
||||
" -mwindows (windows only) --subsystem windows to the linker\n"
|
||||
" -mconsole (windows only) --subsystem console to the linker\n"
|
||||
" -municode (windows only) link with unicode\n"
|
||||
, arg0);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
static int print_target_list(FILE *f) {
|
||||
ZigLLVM_ArchType native_arch_type;
|
||||
ZigLLVM_SubArchType native_sub_arch_type;
|
||||
ZigLLVM_VendorType native_vendor_type;
|
||||
ZigLLVM_OSType native_os_type;
|
||||
ZigLLVM_EnvironmentType native_environ_type;
|
||||
|
||||
ZigLLVMGetNativeTarget(&native_arch_type, &native_sub_arch_type, &native_vendor_type,
|
||||
&native_os_type, &native_environ_type);
|
||||
ZigTarget native;
|
||||
get_native_target(&native);
|
||||
|
||||
fprintf(f, "Architectures:\n");
|
||||
int arch_count = target_arch_count();
|
||||
@ -58,7 +60,7 @@ static int print_target_list(FILE *f) {
|
||||
const ArchType *arch = get_target_arch(arch_i);
|
||||
const char *sub_arch_str = (arch->sub_arch == ZigLLVM_NoSubArch) ?
|
||||
"" : ZigLLVMGetSubArchTypeName(arch->sub_arch);
|
||||
const char *native_str = (native_arch_type == arch->arch && native_sub_arch_type == arch->sub_arch) ?
|
||||
const char *native_str = (native.arch.arch == arch->arch && native.arch.sub_arch == arch->sub_arch) ?
|
||||
" (native)" : "";
|
||||
fprintf(f, " %s%s%s\n", ZigLLVMGetArchTypeName(arch->arch), sub_arch_str, native_str);
|
||||
}
|
||||
@ -67,15 +69,15 @@ static int print_target_list(FILE *f) {
|
||||
int os_count = target_os_count();
|
||||
for (int i = 0; i < os_count; i += 1) {
|
||||
ZigLLVM_OSType os_type = get_target_os(i);
|
||||
const char *native_str = (native_os_type == os_type) ? " (native)" : "";
|
||||
const char *native_str = (native.os == os_type) ? " (native)" : "";
|
||||
fprintf(f, " %s%s\n", get_target_os_name(os_type), native_str);
|
||||
}
|
||||
|
||||
fprintf(f, "\nABIs:\n");
|
||||
fprintf(f, "\nEnvironments:\n");
|
||||
int environ_count = target_environ_count();
|
||||
for (int i = 0; i < environ_count; i += 1) {
|
||||
ZigLLVM_EnvironmentType environ_type = get_target_environ(i);
|
||||
const char *native_str = (native_environ_type == environ_type) ? " (native)" : "";
|
||||
const char *native_str = (native.environ == environ_type) ? " (native)" : "";
|
||||
fprintf(f, " %s%s\n", ZigLLVMGetEnvironmentTypeName(environ_type), native_str);
|
||||
}
|
||||
|
||||
@ -107,9 +109,16 @@ int main(int argc, char **argv) {
|
||||
const char *libc_static_lib_dir = nullptr;
|
||||
const char *libc_include_dir = nullptr;
|
||||
const char *dynamic_linker = nullptr;
|
||||
const char *linker_path = nullptr;
|
||||
ZigList<const char *> clang_argv = {0};
|
||||
ZigList<const char *> lib_dirs = {0};
|
||||
int err;
|
||||
const char *target_arch = nullptr;
|
||||
const char *target_os = nullptr;
|
||||
const char *target_environ = nullptr;
|
||||
bool mwindows = false;
|
||||
bool mconsole = false;
|
||||
bool municode = false;
|
||||
|
||||
for (int i = 1; i < argc; i += 1) {
|
||||
char *arg = argv[i];
|
||||
@ -123,6 +132,12 @@ int main(int argc, char **argv) {
|
||||
is_static = true;
|
||||
} else if (strcmp(arg, "--verbose") == 0) {
|
||||
verbose = true;
|
||||
} else if (strcmp(arg, "-mwindows") == 0) {
|
||||
mwindows = true;
|
||||
} else if (strcmp(arg, "-mconsole") == 0) {
|
||||
mconsole = true;
|
||||
} else if (strcmp(arg, "-municode") == 0) {
|
||||
municode = true;
|
||||
} else if (i + 1 >= argc) {
|
||||
return usage(arg0);
|
||||
} else {
|
||||
@ -161,6 +176,8 @@ int main(int argc, char **argv) {
|
||||
libc_include_dir = argv[i];
|
||||
} else if (strcmp(arg, "--dynamic-linker") == 0) {
|
||||
dynamic_linker = argv[i];
|
||||
} else if (strcmp(arg, "--ld-path") == 0) {
|
||||
linker_path = argv[i];
|
||||
} else if (strcmp(arg, "-isystem") == 0) {
|
||||
clang_argv.append("-isystem");
|
||||
clang_argv.append(argv[i]);
|
||||
@ -169,7 +186,14 @@ int main(int argc, char **argv) {
|
||||
clang_argv.append(argv[i]);
|
||||
} else if (strcmp(arg, "--library-path") == 0) {
|
||||
lib_dirs.append(argv[i]);
|
||||
} else if (strcmp(arg, "--target-arch") == 0) {
|
||||
target_arch = argv[i];
|
||||
} else if (strcmp(arg, "--target-os") == 0) {
|
||||
target_os = argv[i];
|
||||
} else if (strcmp(arg, "--target-environ") == 0) {
|
||||
target_environ = argv[i];
|
||||
} else {
|
||||
fprintf(stderr, "Invalid argument: %s\n", arg);
|
||||
return usage(arg0);
|
||||
}
|
||||
}
|
||||
@ -216,6 +240,36 @@ int main(int argc, char **argv) {
|
||||
if (!in_file)
|
||||
return usage(arg0);
|
||||
|
||||
init_all_targets();
|
||||
|
||||
ZigTarget alloc_target;
|
||||
ZigTarget *target;
|
||||
if (!target_arch && !target_os && !target_environ) {
|
||||
target = nullptr;
|
||||
} else {
|
||||
target = &alloc_target;
|
||||
get_unknown_target(target);
|
||||
if (target_arch) {
|
||||
if (parse_target_arch(target_arch, &target->arch)) {
|
||||
fprintf(stderr, "invalid --target-arch argument\n");
|
||||
return usage(arg0);
|
||||
}
|
||||
}
|
||||
if (target_os) {
|
||||
if (parse_target_os(target_os, &target->os)) {
|
||||
fprintf(stderr, "invalid --target-os argument\n");
|
||||
return usage(arg0);
|
||||
}
|
||||
}
|
||||
if (target_environ) {
|
||||
if (parse_target_environ(target_environ, &target->environ)) {
|
||||
fprintf(stderr, "invalid --target-environ argument\n");
|
||||
return usage(arg0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Buf in_file_buf = BUF_INIT;
|
||||
buf_init_from_str(&in_file_buf, in_file);
|
||||
|
||||
@ -237,7 +291,7 @@ int main(int argc, char **argv) {
|
||||
}
|
||||
}
|
||||
|
||||
CodeGen *g = codegen_create(&root_source_dir);
|
||||
CodeGen *g = codegen_create(&root_source_dir, target);
|
||||
codegen_set_is_release(g, is_release_build);
|
||||
codegen_set_is_test(g, cmd == CmdTest);
|
||||
|
||||
@ -262,6 +316,8 @@ int main(int argc, char **argv) {
|
||||
codegen_set_libc_include_dir(g, buf_create_from_str(libc_include_dir));
|
||||
if (dynamic_linker)
|
||||
codegen_set_dynamic_linker(g, buf_create_from_str(dynamic_linker));
|
||||
if (linker_path)
|
||||
codegen_set_linker_path(g, buf_create_from_str(linker_path));
|
||||
codegen_set_verbose(g, verbose);
|
||||
codegen_set_errmsg_color(g, color);
|
||||
|
||||
@ -269,6 +325,9 @@ int main(int argc, char **argv) {
|
||||
codegen_add_lib_dir(g, lib_dirs.at(i));
|
||||
}
|
||||
|
||||
codegen_set_windows_subsystem(g, mwindows, mconsole);
|
||||
codegen_set_windows_unicode(g, municode);
|
||||
|
||||
if (cmd == CmdBuild) {
|
||||
codegen_add_root_code(g, &root_source_dir, &root_source_name, &root_source_code);
|
||||
codegen_link(g, out_file);
|
||||
|
@ -1540,6 +1540,11 @@ int parse_h_file(ImportTableEntry *import, ZigList<ErrorMsg *> *errors, const ch
|
||||
clang_argv.append("-Xclang");
|
||||
clang_argv.append("-detailed-preprocessing-record");
|
||||
|
||||
if (!c->codegen->is_native_target) {
|
||||
clang_argv.append("-target");
|
||||
clang_argv.append(buf_ptr(&c->codegen->triple_str));
|
||||
}
|
||||
|
||||
clang_argv.append(target_file);
|
||||
|
||||
// to make the [start...end] argument work
|
||||
|
127
src/target.cpp
127
src/target.cpp
@ -7,6 +7,9 @@
|
||||
|
||||
#include "target.hpp"
|
||||
#include "util.hpp"
|
||||
#include "error.hpp"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
static const ArchType arch_list[] = {
|
||||
{ZigLLVM_arm, ZigLLVM_ARMSubArch_v8_1a},
|
||||
@ -158,3 +161,127 @@ int target_environ_count(void) {
|
||||
ZigLLVM_EnvironmentType get_target_environ(int index) {
|
||||
return environ_list[index];
|
||||
}
|
||||
|
||||
void get_native_target(ZigTarget *target) {
|
||||
ZigLLVMGetNativeTarget(
|
||||
&target->arch.arch,
|
||||
&target->arch.sub_arch,
|
||||
&target->vendor,
|
||||
&target->os,
|
||||
&target->environ,
|
||||
&target->oformat);
|
||||
}
|
||||
|
||||
void get_unknown_target(ZigTarget *target) {
|
||||
target->arch.arch = ZigLLVM_UnknownArch;
|
||||
target->arch.sub_arch = ZigLLVM_NoSubArch;
|
||||
target->vendor = ZigLLVM_UnknownVendor;
|
||||
target->os = ZigLLVM_UnknownOS;
|
||||
target->environ = ZigLLVM_UnknownEnvironment;
|
||||
target->oformat = ZigLLVM_UnknownObjectFormat;
|
||||
}
|
||||
|
||||
int parse_target_arch(const char *str, ArchType *out_arch) {
|
||||
for (int i = 0; i < array_length(arch_list); i += 1) {
|
||||
const ArchType *arch = &arch_list[i];
|
||||
char arch_name[50];
|
||||
const char *sub_str = (arch->sub_arch == ZigLLVM_NoSubArch) ?
|
||||
"" : ZigLLVMGetSubArchTypeName(arch->sub_arch);
|
||||
sprintf(arch_name, "%s%s", ZigLLVMGetArchTypeName(arch->arch), sub_str);
|
||||
if (strcmp(arch_name, str) == 0) {
|
||||
*out_arch = *arch;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return ErrorFileNotFound;
|
||||
}
|
||||
|
||||
int parse_target_os(const char *str, ZigLLVM_OSType *out_os) {
|
||||
for (int i = 0; i < array_length(os_list); i += 1) {
|
||||
ZigLLVM_OSType os = os_list[i];
|
||||
const char *os_name = get_target_os_name(os);
|
||||
if (strcmp(os_name, str) == 0) {
|
||||
*out_os = os;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return ErrorFileNotFound;
|
||||
}
|
||||
|
||||
int parse_target_environ(const char *str, ZigLLVM_EnvironmentType *out_environ) {
|
||||
for (int i = 0; i < array_length(environ_list); i += 1) {
|
||||
ZigLLVM_EnvironmentType environ = environ_list[i];
|
||||
const char *environ_name = ZigLLVMGetEnvironmentTypeName(environ);
|
||||
if (strcmp(environ_name, str) == 0) {
|
||||
*out_environ = environ;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return ErrorFileNotFound;
|
||||
}
|
||||
|
||||
void init_all_targets(void) {
|
||||
LLVMInitializeAllTargets();
|
||||
LLVMInitializeAllTargetInfos();
|
||||
LLVMInitializeAllTargetMCs();
|
||||
LLVMInitializeAllAsmPrinters();
|
||||
LLVMInitializeAllAsmParsers();
|
||||
}
|
||||
|
||||
void get_target_triple(Buf *triple, const ZigTarget *target) {
|
||||
ZigLLVMGetTargetTriple(triple, target->arch.arch, target->arch.sub_arch,
|
||||
target->vendor, target->os, target->environ, target->oformat);
|
||||
}
|
||||
|
||||
static bool is_os_darwin(ZigTarget *target) {
|
||||
switch (target->os) {
|
||||
case ZigLLVM_Darwin:
|
||||
case ZigLLVM_IOS:
|
||||
case ZigLLVM_MacOSX:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void resolve_target_object_format(ZigTarget *target) {
|
||||
if (target->oformat != ZigLLVM_UnknownObjectFormat) {
|
||||
return;
|
||||
}
|
||||
switch (target->arch.arch) {
|
||||
default:
|
||||
break;
|
||||
case ZigLLVM_hexagon:
|
||||
case ZigLLVM_mips:
|
||||
case ZigLLVM_mipsel:
|
||||
case ZigLLVM_mips64:
|
||||
case ZigLLVM_mips64el:
|
||||
case ZigLLVM_r600:
|
||||
case ZigLLVM_amdgcn:
|
||||
case ZigLLVM_sparc:
|
||||
case ZigLLVM_sparcv9:
|
||||
case ZigLLVM_systemz:
|
||||
case ZigLLVM_xcore:
|
||||
case ZigLLVM_ppc64le:
|
||||
target->oformat = ZigLLVM_ELF;
|
||||
return;
|
||||
|
||||
case ZigLLVM_ppc:
|
||||
case ZigLLVM_ppc64:
|
||||
if (is_os_darwin(target)) {
|
||||
target->oformat = ZigLLVM_MachO;
|
||||
return;
|
||||
}
|
||||
target->oformat = ZigLLVM_ELF;
|
||||
return;
|
||||
}
|
||||
|
||||
if (is_os_darwin(target)) {
|
||||
target->oformat = ZigLLVM_MachO;
|
||||
return;
|
||||
} else if (target->os == ZigLLVM_Win32) {
|
||||
target->oformat = ZigLLVM_COFF;
|
||||
return;
|
||||
}
|
||||
target->oformat = ZigLLVM_ELF;
|
||||
}
|
||||
|
@ -10,11 +10,21 @@
|
||||
|
||||
#include <zig_llvm.hpp>
|
||||
|
||||
struct Buf;
|
||||
|
||||
struct ArchType {
|
||||
ZigLLVM_ArchType arch;
|
||||
ZigLLVM_SubArchType sub_arch;
|
||||
};
|
||||
|
||||
struct ZigTarget {
|
||||
ArchType arch;
|
||||
ZigLLVM_VendorType vendor;
|
||||
ZigLLVM_OSType os;
|
||||
ZigLLVM_EnvironmentType environ;
|
||||
ZigLLVM_ObjectFormatType oformat;
|
||||
};
|
||||
|
||||
int target_arch_count(void);
|
||||
const ArchType *get_target_arch(int index);
|
||||
|
||||
@ -28,4 +38,18 @@ const char *get_target_os_name(ZigLLVM_OSType os_type);
|
||||
int target_environ_count(void);
|
||||
ZigLLVM_EnvironmentType get_target_environ(int index);
|
||||
|
||||
void get_native_target(ZigTarget *target);
|
||||
void get_unknown_target(ZigTarget *target);
|
||||
|
||||
int parse_target_arch(const char *str, ArchType *arch);
|
||||
int parse_target_os(const char *str, ZigLLVM_OSType *os);
|
||||
int parse_target_environ(const char *str, ZigLLVM_EnvironmentType *environ);
|
||||
|
||||
void init_all_targets(void);
|
||||
|
||||
void get_target_triple(Buf *triple, const ZigTarget *target);
|
||||
|
||||
void resolve_target_object_format(ZigTarget *target);
|
||||
|
||||
|
||||
#endif
|
||||
|
@ -14,6 +14,7 @@
|
||||
|
||||
#include "zig_llvm.hpp"
|
||||
|
||||
|
||||
/*
|
||||
* The point of this file is to contain all the LLVM C++ API interaction so that:
|
||||
* 1. The compile time of other files is kept under control.
|
||||
@ -520,6 +521,11 @@ static_assert((Triple::VendorType)ZigLLVM_LastVendorType == Triple::LastVendorTy
|
||||
static_assert((Triple::OSType)ZigLLVM_LastOSType == Triple::LastOSType, "");
|
||||
static_assert((Triple::EnvironmentType)ZigLLVM_LastEnvironmentType == Triple::LastEnvironmentType, "");
|
||||
|
||||
static_assert((Triple::ObjectFormatType)ZigLLVM_UnknownObjectFormat == Triple::UnknownObjectFormat, "");
|
||||
static_assert((Triple::ObjectFormatType)ZigLLVM_COFF == Triple::COFF, "");
|
||||
static_assert((Triple::ObjectFormatType)ZigLLVM_ELF == Triple::ELF, "");
|
||||
static_assert((Triple::ObjectFormatType)ZigLLVM_MachO == Triple::MachO, "");
|
||||
|
||||
const char *ZigLLVMGetArchTypeName(ZigLLVM_ArchType arch) {
|
||||
return Triple::getArchTypeName((Triple::ArchType)arch);
|
||||
}
|
||||
@ -537,7 +543,8 @@ const char *ZigLLVMGetEnvironmentTypeName(ZigLLVM_EnvironmentType environ) {
|
||||
}
|
||||
|
||||
void ZigLLVMGetNativeTarget(ZigLLVM_ArchType *arch_type, ZigLLVM_SubArchType *sub_arch_type,
|
||||
ZigLLVM_VendorType *vendor_type, ZigLLVM_OSType *os_type, ZigLLVM_EnvironmentType *environ_type)
|
||||
ZigLLVM_VendorType *vendor_type, ZigLLVM_OSType *os_type, ZigLLVM_EnvironmentType *environ_type,
|
||||
ZigLLVM_ObjectFormatType *oformat)
|
||||
{
|
||||
char *native_triple = LLVMGetDefaultTargetTriple();
|
||||
Triple triple(native_triple);
|
||||
@ -547,6 +554,7 @@ void ZigLLVMGetNativeTarget(ZigLLVM_ArchType *arch_type, ZigLLVM_SubArchType *su
|
||||
*vendor_type = (ZigLLVM_VendorType)triple.getVendor();
|
||||
*os_type = (ZigLLVM_OSType)triple.getOS();
|
||||
*environ_type = (ZigLLVM_EnvironmentType)triple.getEnvironment();
|
||||
*oformat = (ZigLLVM_ObjectFormatType)triple.getObjectFormat();
|
||||
|
||||
free(native_triple);
|
||||
}
|
||||
@ -594,6 +602,23 @@ const char *ZigLLVMGetSubArchTypeName(ZigLLVM_SubArchType sub_arch) {
|
||||
|
||||
#include "buffer.hpp"
|
||||
|
||||
void ZigLLVMGetTargetTriple(Buf *out_buf, ZigLLVM_ArchType arch_type, ZigLLVM_SubArchType sub_arch_type,
|
||||
ZigLLVM_VendorType vendor_type, ZigLLVM_OSType os_type, ZigLLVM_EnvironmentType environ_type,
|
||||
ZigLLVM_ObjectFormatType oformat)
|
||||
{
|
||||
Triple triple;
|
||||
|
||||
triple.setArch((Triple::ArchType)arch_type);
|
||||
// TODO how to set the sub arch?
|
||||
triple.setVendor((Triple::VendorType)vendor_type);
|
||||
triple.setOS((Triple::OSType)os_type);
|
||||
triple.setEnvironment((Triple::EnvironmentType)environ_type);
|
||||
triple.setObjectFormat((Triple::ObjectFormatType)oformat);
|
||||
|
||||
const std::string &str = triple.str();
|
||||
buf_init_from_mem(out_buf, str.c_str(), str.size());
|
||||
}
|
||||
|
||||
enum FloatAbi {
|
||||
FloatAbiHard,
|
||||
FloatAbiSoft,
|
||||
|
@ -189,6 +189,7 @@ enum ZigLLVM_ArchType {
|
||||
ZigLLVM_shave, // SHAVE: Movidius vector VLIW processors
|
||||
ZigLLVM_wasm32, // WebAssembly with 32-bit pointers
|
||||
ZigLLVM_wasm64, // WebAssembly with 64-bit pointers
|
||||
|
||||
ZigLLVM_LastArchType = ZigLLVM_wasm64
|
||||
};
|
||||
|
||||
@ -227,6 +228,7 @@ enum ZigLLVM_VendorType {
|
||||
ZigLLVM_MipsTechnologies,
|
||||
ZigLLVM_NVIDIA,
|
||||
ZigLLVM_CSR,
|
||||
|
||||
ZigLLVM_LastVendorType = ZigLLVM_CSR
|
||||
};
|
||||
enum ZigLLVM_OSType {
|
||||
@ -256,6 +258,7 @@ enum ZigLLVM_OSType {
|
||||
ZigLLVM_NVCL, // NVIDIA OpenCL
|
||||
ZigLLVM_AMDHSA, // AMD HSA Runtime
|
||||
ZigLLVM_PS4,
|
||||
|
||||
ZigLLVM_LastOSType = ZigLLVM_PS4
|
||||
};
|
||||
enum ZigLLVM_EnvironmentType {
|
||||
@ -273,14 +276,15 @@ enum ZigLLVM_EnvironmentType {
|
||||
ZigLLVM_MSVC,
|
||||
ZigLLVM_Itanium,
|
||||
ZigLLVM_Cygnus,
|
||||
ZigLLVM_LastEnvironmentType = ZigLLVM_Cygnus
|
||||
|
||||
ZigLLVM_LastEnvironmentType = ZigLLVM_Cygnus,
|
||||
};
|
||||
enum ZigLLVM_ObjectFormatType {
|
||||
ZigLLVM_UnknownObjectFormat,
|
||||
ZigLLVM_UnknownObjectFormat,
|
||||
|
||||
ZigLLVM_COFF,
|
||||
ZigLLVM_ELF,
|
||||
ZigLLVM_MachO,
|
||||
ZigLLVM_COFF,
|
||||
ZigLLVM_ELF,
|
||||
ZigLLVM_MachO,
|
||||
};
|
||||
|
||||
const char *ZigLLVMGetArchTypeName(ZigLLVM_ArchType arch);
|
||||
@ -289,14 +293,18 @@ const char *ZigLLVMGetVendorTypeName(ZigLLVM_VendorType vendor);
|
||||
const char *ZigLLVMGetOSTypeName(ZigLLVM_OSType os);
|
||||
const char *ZigLLVMGetEnvironmentTypeName(ZigLLVM_EnvironmentType environ);
|
||||
|
||||
void ZigLLVMGetNativeTarget(ZigLLVM_ArchType *arch_type, ZigLLVM_SubArchType *sub_arch_type,
|
||||
ZigLLVM_VendorType *vendor_type, ZigLLVM_OSType *os_type, ZigLLVM_EnvironmentType *environ_type);
|
||||
|
||||
|
||||
/*
|
||||
* This stuff is not LLVM API but it depends on the LLVM C++ API so we put it here.
|
||||
*/
|
||||
struct Buf;
|
||||
void ZigLLVMGetNativeTarget(ZigLLVM_ArchType *arch_type, ZigLLVM_SubArchType *sub_arch_type,
|
||||
ZigLLVM_VendorType *vendor_type, ZigLLVM_OSType *os_type, ZigLLVM_EnvironmentType *environ_type,
|
||||
ZigLLVM_ObjectFormatType *oformat);
|
||||
void ZigLLVMGetTargetTriple(Buf *out_buf, ZigLLVM_ArchType arch_type, ZigLLVM_SubArchType sub_arch_type,
|
||||
ZigLLVM_VendorType vendor_type, ZigLLVM_OSType os_type, ZigLLVM_EnvironmentType environ_type,
|
||||
ZigLLVM_ObjectFormatType oformat);
|
||||
|
||||
|
||||
Buf *get_dynamic_linker(LLVMTargetMachineRef target_machine);
|
||||
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user