mirror of
https://github.com/Ed94/Odin.git
synced 2026-07-10 21:31:37 -07:00
+95
-4
@@ -135,7 +135,62 @@ String odin_root_dir(void) {
|
||||
return path;
|
||||
}
|
||||
#else
|
||||
#error Implement system
|
||||
|
||||
// NOTE: Linux / Unix is unfinished and not tested very well.
|
||||
#include <sys/stat.h>
|
||||
|
||||
String odin_root_dir(void) {
|
||||
String path = global_module_path;
|
||||
Array(char) path_buf;
|
||||
isize len, i;
|
||||
gbTempArenaMemory tmp;
|
||||
wchar_t *text;
|
||||
|
||||
if (global_module_path_set) {
|
||||
return global_module_path;
|
||||
}
|
||||
|
||||
array_init_count(&path_buf, heap_allocator(), 300);
|
||||
|
||||
len = 0;
|
||||
for (;;) {
|
||||
// This is not a 100% reliable system, but for the purposes
|
||||
// of this compiler, it should be _good enough_.
|
||||
// That said, there's no solid 100% method on Linux to get the program's
|
||||
// path without checking this link. Sorry.
|
||||
len = readlink("/proc/self/exe", &path_buf.e[0], path_buf.count);
|
||||
if(len == 0) {
|
||||
return make_string(NULL, 0);
|
||||
}
|
||||
if (len < path_buf.count) {
|
||||
break;
|
||||
}
|
||||
array_resize(&path_buf, 2*path_buf.count + 300);
|
||||
}
|
||||
|
||||
|
||||
tmp = gb_temp_arena_memory_begin(&string_buffer_arena);
|
||||
text = gb_alloc_array(string_buffer_allocator, u8, len + 1);
|
||||
gb_memmove(text, &path_buf.e[0], len);
|
||||
|
||||
path = make_string(text, len);
|
||||
for (i = path.len-1; i >= 0; i--) {
|
||||
u8 c = path.text[i];
|
||||
if (c == '/' || c == '\\') {
|
||||
break;
|
||||
}
|
||||
path.len--;
|
||||
}
|
||||
|
||||
global_module_path = path;
|
||||
global_module_path_set = true;
|
||||
|
||||
gb_temp_arena_memory_end(tmp);
|
||||
|
||||
array_free(&path_buf);
|
||||
|
||||
return path;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@@ -221,18 +276,54 @@ void init_build_context(void) {
|
||||
bc->ODIN_ARCH = str_lit("amd64");
|
||||
bc->ODIN_ENDIAN = str_lit("little");
|
||||
#else
|
||||
#error Implement system
|
||||
bc->ODIN_OS = str_lit("linux");
|
||||
bc->ODIN_ARCH = str_lit("amd64");
|
||||
bc->ODIN_ENDIAN = str_lit("little");
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
// NOTE(zangent): The linker flags to set the build architecture are different
|
||||
// across OSs. It doesn't make sense to allocate extra data on the heap
|
||||
// here, so I just #defined the linker flags to keep things concise.
|
||||
#if defined(GB_SYSTEM_WINDOWS)
|
||||
|
||||
#define LINK_FLAG_X64 "/machine:x64"
|
||||
#define LINK_FLAG_X86 "/machine:x86"
|
||||
|
||||
#elif defined(GB_SYSTEM_OSX)
|
||||
|
||||
// NOTE(zangent): MacOS systems are x64 only, so ld doesn't have
|
||||
// an architecture option. All compilation done on MacOS must be x64.
|
||||
GB_ASSERT(str_eq(bc->ODIN_ARCH, str_lit("amd64")));
|
||||
|
||||
#define LINK_FLAG_X64 ""
|
||||
#define LINK_FLAG_X86 ""
|
||||
#else
|
||||
// Linux, but also BSDs and the like.
|
||||
// NOTE(zangent): When clang is swapped out with ld as the linker,
|
||||
// the commented flags here should be used. Until then, we'll have
|
||||
// to use alternative build flags made for clang.
|
||||
/*
|
||||
#define LINK_FLAG_X64 "-m elf_x86_64"
|
||||
#define LINK_FLAG_X86 "-m elf_i386"
|
||||
*/
|
||||
#define LINK_FLAG_X64 "-arch x86-64"
|
||||
#define LINK_FLAG_X86 "-arch x86"
|
||||
#endif
|
||||
|
||||
if (str_eq(bc->ODIN_ARCH, str_lit("amd64"))) {
|
||||
bc->word_size = 8;
|
||||
bc->max_align = 16;
|
||||
bc->llc_flags = str_lit("-march=x86-64 ");
|
||||
bc->link_flags = str_lit("/machine:x64 ");
|
||||
bc->link_flags = str_lit(LINK_FLAG_X64 " ");
|
||||
} else if (str_eq(bc->ODIN_ARCH, str_lit("x86"))) {
|
||||
bc->word_size = 4;
|
||||
bc->max_align = 8;
|
||||
bc->llc_flags = str_lit("-march=x86 ");
|
||||
bc->link_flags = str_lit("/machine:x86 ");
|
||||
bc->link_flags = str_lit(LINK_FLAG_X86 " ");
|
||||
}
|
||||
|
||||
#undef LINK_FLAG_X64
|
||||
#undef LINK_FLAG_X86
|
||||
}
|
||||
|
||||
+14
-14
@@ -5,8 +5,8 @@ void check_stmt_list (Checker *c, AstNodeArray stmts, u32 flags);
|
||||
// NOTE(bill): `content_name` is for debugging and error messages
|
||||
Type *check_init_variable(Checker *c, Entity *e, Operand *operand, String context_name) {
|
||||
if (operand->mode == Addressing_Invalid ||
|
||||
operand->type == t_invalid ||
|
||||
e->type == t_invalid) {
|
||||
operand->type == t_invalid ||
|
||||
e->type == t_invalid) {
|
||||
|
||||
if (operand->mode == Addressing_Builtin) {
|
||||
gbString expr_str = expr_to_string(operand->expr);
|
||||
@@ -14,9 +14,9 @@ Type *check_init_variable(Checker *c, Entity *e, Operand *operand, String contex
|
||||
// TODO(bill): is this a good enough error message?
|
||||
// TODO(bill): Actually allow built in procedures to be passed around and thus be created on use
|
||||
error_node(operand->expr,
|
||||
"Cannot assign builtin procedure `%s` in %.*s",
|
||||
expr_str,
|
||||
LIT(context_name));
|
||||
"Cannot assign builtin procedure `%s` in %.*s",
|
||||
expr_str,
|
||||
LIT(context_name));
|
||||
|
||||
operand->mode = Addressing_Invalid;
|
||||
|
||||
@@ -86,8 +86,8 @@ void check_init_variables(Checker *c, Entity **lhs, isize lhs_count, AstNodeArra
|
||||
|
||||
void check_init_constant(Checker *c, Entity *e, Operand *operand) {
|
||||
if (operand->mode == Addressing_Invalid ||
|
||||
operand->type == t_invalid ||
|
||||
e->type == t_invalid) {
|
||||
operand->type == t_invalid ||
|
||||
e->type == t_invalid) {
|
||||
if (e->type == NULL) {
|
||||
e->type = t_invalid;
|
||||
}
|
||||
@@ -182,7 +182,7 @@ void check_const_decl(Checker *c, Entity *e, AstNode *type_expr, AstNode *init,
|
||||
check_init_constant(c, e, &operand);
|
||||
|
||||
if (operand.mode == Addressing_Invalid ||
|
||||
base_type(operand.type) == t_invalid) {
|
||||
base_type(operand.type) == t_invalid) {
|
||||
error(e->token, "Invalid declaration type");
|
||||
}
|
||||
}
|
||||
@@ -324,9 +324,9 @@ void check_proc_lit(Checker *c, Entity *e, DeclInfo *d) {
|
||||
Type *other_type = base_type(f->type);
|
||||
if (!are_signatures_similar_enough(this_type, other_type)) {
|
||||
error_node(d->proc_lit,
|
||||
"Redeclaration of #foreign procedure `%.*s` with different type signatures\n"
|
||||
"\tat %.*s(%td:%td)",
|
||||
LIT(name), LIT(pos.file), pos.line, pos.column);
|
||||
"Redeclaration of #foreign procedure `%.*s` with different type signatures\n"
|
||||
"\tat %.*s(%td:%td)",
|
||||
LIT(name), LIT(pos.file), pos.line, pos.column);
|
||||
}
|
||||
} else {
|
||||
map_entity_set(fp, key, e);
|
||||
@@ -349,9 +349,9 @@ void check_proc_lit(Checker *c, Entity *e, DeclInfo *d) {
|
||||
TokenPos pos = f->token.pos;
|
||||
// TODO(bill): Better error message?
|
||||
error_node(d->proc_lit,
|
||||
"Non unique linking name for procedure `%.*s`\n"
|
||||
"\tother at %.*s(%td:%td)",
|
||||
LIT(name), LIT(pos.file), pos.line, pos.column);
|
||||
"Non unique linking name for procedure `%.*s`\n"
|
||||
"\tother at %.*s(%td:%td)",
|
||||
LIT(name), LIT(pos.file), pos.line, pos.column);
|
||||
} else {
|
||||
map_entity_set(fp, key, e);
|
||||
}
|
||||
|
||||
+13
-3
@@ -1578,6 +1578,19 @@ void check_collect_entities(Checker *c, AstNodeArray nodes, bool is_file_scope)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (fl->cond != NULL) {
|
||||
Operand operand = {Addressing_Invalid};
|
||||
check_expr(c, &operand, fl->cond);
|
||||
if (operand.mode != Addressing_Constant || !is_type_boolean(operand.type)) {
|
||||
error_node(fl->cond, "Non-constant boolean `when` condition");
|
||||
continue;
|
||||
}
|
||||
if (operand.value.kind == ExactValue_Bool &&
|
||||
!operand.value.value_bool) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
DelayedDecl di = {c->context.scope, decl};
|
||||
array_add(&c->delayed_foreign_libraries, di);
|
||||
case_end;
|
||||
@@ -2004,6 +2017,3 @@ void check_parsed_files(Checker *c) {
|
||||
map_scope_destroy(&file_scopes);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
+17
-3
@@ -276,7 +276,9 @@ extern "C" {
|
||||
|
||||
// TODO(bill): How many of these headers do I really need?
|
||||
// #include <stdarg.h>
|
||||
// #include <stddef.h>
|
||||
#if !defined(GB_SYSTEM_WINDOWS)
|
||||
#include <stddef.h>
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
@@ -3644,6 +3646,13 @@ gb_inline void *gb_memcopy(void *dest, void const *source, isize n) {
|
||||
#if defined(_MSC_VER)
|
||||
// TODO(bill): Is this good enough?
|
||||
__movsb(cast(u8 *)dest, cast(u8 *)source, n);
|
||||
#elif defined(GB_SYSTEM_OSX) || defined(GB_SYSTEM_UNIX)
|
||||
// NOTE(zangent): I assume there's a reason this isn't being used elsewhere,
|
||||
// but casting pointers as arguments to an __asm__ call is considered an
|
||||
// error on MacOS and (I think) Linux
|
||||
// TODO(zangent): Figure out how to refactor the asm code so it works on MacOS,
|
||||
// since this is probably not the way the author intended this to work.
|
||||
memcpy(dest, source, n);
|
||||
#elif defined(GB_CPU_X86)
|
||||
__asm__ __volatile__("rep movsb" : "+D"(cast(u8 *)dest), "+S"(cast(u8 *)source), "+c"(n) : : "memory");
|
||||
#else
|
||||
@@ -4695,7 +4704,7 @@ gb_inline u32 gb_thread_current_id(void) {
|
||||
#elif defined(GB_ARCH_32_BIT) && defined(GB_CPU_X86)
|
||||
__asm__("mov %%gs:0x08,%0" : "=r"(thread_id));
|
||||
#elif defined(GB_ARCH_64_BIT) && defined(GB_CPU_X86)
|
||||
__asm__("mov %%gs:0x10,%0" : "=r"(thread_id));
|
||||
__asm__("mov %%fs:0x10,%0" : "=r"(thread_id));
|
||||
#else
|
||||
#error Unsupported architecture for gb_thread_current_id()
|
||||
#endif
|
||||
@@ -5019,7 +5028,10 @@ void gb_affinity_init(gbAffinity *a) {
|
||||
// Parsing /proc/cpuinfo to get the number of threads per core.
|
||||
// NOTE(zangent): This calls the CPU's threads "cores", although the wording
|
||||
// is kind of weird. This should be right, though.
|
||||
if (fopen("/proc/cpuinfo", "r") != NULL) {
|
||||
|
||||
FILE* cpu_info = fopen("/proc/cpuinfo", "r");
|
||||
|
||||
if (cpu_info != NULL) {
|
||||
for (;;) {
|
||||
// The 'temporary char'. Everything goes into this char,
|
||||
// so that we can check against EOF at the end of this loop.
|
||||
@@ -5050,6 +5062,8 @@ void gb_affinity_init(gbAffinity *a) {
|
||||
}
|
||||
#undef AF__CHECK
|
||||
}
|
||||
|
||||
fclose(cpu_info);
|
||||
}
|
||||
|
||||
if (threads == 0) {
|
||||
|
||||
@@ -6792,6 +6792,12 @@ void ir_gen_tree(irGen *s) {
|
||||
} else if (e->kind == Entity_Procedure && e->Procedure.link_name.len > 0) {
|
||||
// Handle later
|
||||
} else if (scope->is_init && e->kind == Entity_Procedure && str_eq(name, str_lit("main"))) {
|
||||
#ifdef GB_SYSTEM_OSX
|
||||
} else if (str_eq(name, str_lit("args")) && str_eq(e->token.pos.file, get_fullpath_core(heap_allocator(), str_lit("os_x.odin")))) {
|
||||
#endif
|
||||
#ifdef GB_SYSTEM_LINUX
|
||||
} else if (str_eq(name, str_lit("args")) && str_eq(e->token.pos.file, get_fullpath_core(heap_allocator(), str_lit("os_linux.odin")))) {
|
||||
#endif
|
||||
} else {
|
||||
name = ir_mangle_name(s, e->token.pos.file, e);
|
||||
}
|
||||
|
||||
+135
@@ -1385,6 +1385,134 @@ void ir_print_instr(irFileBuffer *f, irModule *m, irValue *value) {
|
||||
|
||||
|
||||
void ir_print_proc(irFileBuffer *f, irModule *m, irProcedure *proc) {
|
||||
|
||||
#ifndef GB_SYSTEM_WINDOWS
|
||||
bool is_main_proc = proc->parent == NULL && str_eq(proc->name, str_lit("main"));
|
||||
|
||||
AstFile fake_file;
|
||||
gb_arena_init_from_allocator(&fake_file.arena, heap_allocator(), gb_size_of(AstNode) * 4);
|
||||
|
||||
bool uses_args = false;
|
||||
if(is_main_proc)
|
||||
for(int i=0;i<proc->module->min_dep_map.entries.count;i++) {
|
||||
Entity *value = proc->module->min_dep_map.entries.e[i].value;
|
||||
if(value == NULL) continue;
|
||||
if(str_eq(str_lit("args"), value->token.string)) {
|
||||
uses_args = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO(zangent): THIS IS AN UGLY HACK
|
||||
// I _SERIOUSLY_ need to change this system, because this is just disgraceful.
|
||||
|
||||
if(uses_args) {
|
||||
|
||||
|
||||
ir_fprintf(f, "%s", "; Hack to give Linux/OSX launch arguments\n"
|
||||
"define i32 @main(i32 %argc, i8** %argv) {\n"
|
||||
"decls-0:\n"
|
||||
" %0 = alloca i32, align 4\n"
|
||||
" %1 = alloca i8**, align 8\n"
|
||||
" %2 = alloca i32, align 4\n"
|
||||
" %3 = alloca i8*, align 8\n"
|
||||
" %4 = alloca %..string, align 8\n"
|
||||
" store i32 zeroinitializer, i32* %0\n"
|
||||
" store i32 %argc, i32* %0\n"
|
||||
" store i8** zeroinitializer, i8*** %1\n"
|
||||
" store i8** %argv, i8*** %1\n"
|
||||
" call void @.__$startup_runtime()\n"
|
||||
" ; reserve\n"
|
||||
" ; SelectorExpr\n"
|
||||
" %5 = load i32, i32* %0, align 4\n"
|
||||
" %6 = sext i32 %5 to i64\n"
|
||||
" %7 = bitcast {%..string*, i64, i64,%Allocator}* @.args to %..rawptr\n"
|
||||
" %8 = call i1 @.__dynamic_array_reserve(%..rawptr %7, i64 16, i64 8, i64 %6)\n"
|
||||
" ; AssignStmt\n"
|
||||
" ; SelectorExpr\n"
|
||||
" ; SelectorExpr\n"
|
||||
" %9 = getelementptr inbounds {%..string*, i64, i64,%Allocator}, {%..string*, i64, i64,%Allocator}* @.args, i64 0, i32 1\n"
|
||||
" %10 = load i32, i32* %0, align 4\n"
|
||||
" ; cast - cast\n"
|
||||
" %11 = sext i32 %10 to i64\n"
|
||||
" store i64 %11, i64* %9\n"
|
||||
" ; i\n"
|
||||
" store i32 zeroinitializer, i32* %2\n"
|
||||
" store i32 0, i32* %2\n"
|
||||
" ; ForStmt\n"
|
||||
" br label %for.loop-1\n"
|
||||
"\n"
|
||||
"for.loop-1:\n"
|
||||
" %12 = load i32, i32* %2, align 4\n"
|
||||
" %13 = load i32, i32* %0, align 4\n"
|
||||
" %14 = icmp slt i32 %12, %13\n"
|
||||
" br i1 %14, label %for.body-2, label %for.done-6\n"
|
||||
"\n"
|
||||
"for.body-2:\n"
|
||||
" ; cstr\n"
|
||||
" store i8* zeroinitializer, i8** %3\n"
|
||||
" %15 = load i8**, i8*** %1, align 8\n"
|
||||
" %16 = load i32, i32* %2, align 4\n"
|
||||
" %17 = sext i32 %16 to i64\n"
|
||||
" %18 = getelementptr inbounds i8*, i8** %15, i64 %17\n"
|
||||
" %19 = getelementptr inbounds i8*, i8** %18, i64 0\n"
|
||||
" %20 = load i8*, i8** %19, align 8\n"
|
||||
" store i8* %20, i8** %3\n"
|
||||
" ; str\n"
|
||||
" store %..string zeroinitializer, %..string* %4\n"
|
||||
" ; AssignStmt\n"
|
||||
" ; SelectorExpr\n"
|
||||
" %21 = getelementptr inbounds %..string, %..string* %4, i64 0, i32 0\n"
|
||||
" %22 = load i8*, i8** %3, align 8\n"
|
||||
" store i8* %22, i8** %21\n"
|
||||
" ; ForStmt\n"
|
||||
" br label %for.loop-3\n"
|
||||
"\n"
|
||||
"for.loop-3:\n"
|
||||
" %23 = load i8*, i8** %3, align 8\n"
|
||||
" ; SelectorExpr\n"
|
||||
" %24 = getelementptr inbounds %..string, %..string* %4, i64 0, i32 1\n"
|
||||
" %25 = load i64, i64* %24, align 8\n"
|
||||
" %26 = getelementptr inbounds i8, i8* %23, i64 %25\n"
|
||||
" %27 = getelementptr inbounds i8, i8* %26, i64 0\n"
|
||||
" %28 = load i8, i8* %27, align 1\n"
|
||||
" %29 = icmp ne i8 %28, 0\n"
|
||||
" br i1 %29, label %for.body-4, label %for.done-5\n"
|
||||
"\n"
|
||||
"for.body-4:\n"
|
||||
" ; SelectorExpr\n"
|
||||
" %30 = getelementptr inbounds %..string, %..string* %4, i64 0, i32 1\n"
|
||||
" %31 = load i64, i64* %30, align 8\n"
|
||||
" %32 = add i64 %31, 1\n"
|
||||
" store i64 %32, i64* %30\n"
|
||||
" br label %for.loop-3\n"
|
||||
"\n"
|
||||
"for.done-5:\n"
|
||||
" ; AssignStmt\n"
|
||||
" ; IndexExpr\n"
|
||||
" ; SelectorExpr\n"
|
||||
" %33 = load {%..string*, i64, i64,%Allocator}, {%..string*, i64, i64,%Allocator}* @.args, align 8\n"
|
||||
" %34 = extractvalue {%..string*, i64, i64,%Allocator} %33, 0\n"
|
||||
" %35 = extractvalue {%..string*, i64, i64,%Allocator} %33, 1\n"
|
||||
" %36 = load i32, i32* %2, align 4\n"
|
||||
" %37 = sext i32 %36 to i64\n"
|
||||
" %38 = getelementptr inbounds %..string, %..string* %34, i64 %37\n"
|
||||
" %39 = load %..string, %..string* %4, align 8\n"
|
||||
" store %..string %39, %..string* %38\n"
|
||||
" ; AssignStmt\n"
|
||||
" %40 = load i32, i32* %2, align 4\n"
|
||||
" %41 = add i32 %40, 1\n"
|
||||
" store i32 %41, i32* %2\n"
|
||||
" br label %for.loop-1\n"
|
||||
"\n"
|
||||
"for.done-6:\n"
|
||||
" call void @.nix_argpatch_main()\n"
|
||||
" ret i32 0\n"
|
||||
"}\n"
|
||||
);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (proc->body == NULL) {
|
||||
ir_fprintf(f, "declare ");
|
||||
// if (proc->tags & ProcTag_dll_import) {
|
||||
@@ -1412,7 +1540,14 @@ void ir_print_proc(irFileBuffer *f, irModule *m, irProcedure *proc) {
|
||||
}
|
||||
|
||||
ir_fprintf(f, " ");
|
||||
|
||||
#ifndef GB_SYSTEM_WINDOWS
|
||||
if(uses_args)
|
||||
ir_fprintf(f, "@.nix_argpatch_main");
|
||||
else
|
||||
#endif
|
||||
ir_print_encoded_global(f, proc->name, ir_print_is_proc_global(m, proc));
|
||||
|
||||
ir_fprintf(f, "(");
|
||||
|
||||
if (proc_type->param_count > 0) {
|
||||
|
||||
+135
-2
@@ -16,6 +16,11 @@ extern "C" {
|
||||
#include "ir_print.c"
|
||||
// #include "vm.c"
|
||||
|
||||
#if defined(GB_SYSTEM_UNIX)
|
||||
// Required for intrinsics on GCC
|
||||
#include <xmmintrin.h>
|
||||
#endif
|
||||
|
||||
#if defined(GB_SYSTEM_WINDOWS)
|
||||
// NOTE(bill): `name` is used in debugging and profiling modes
|
||||
i32 system_exec_command_line_app(char *name, bool is_silent, char *fmt, ...) {
|
||||
@@ -102,6 +107,8 @@ i32 system_exec_command_line_app(char *name, bool is_silent, char *fmt, ...) {
|
||||
// }
|
||||
|
||||
// exit_code = status;
|
||||
|
||||
return exit_code;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -250,9 +257,11 @@ int main(int argc, char **argv) {
|
||||
optimization_level = gb_clamp(optimization_level, 0, 3);
|
||||
|
||||
i32 exit_code = 0;
|
||||
|
||||
#if defined(GB_SYSTEM_WINDOWS)
|
||||
// For more passes arguments: http://llvm.org/docs/Passes.html
|
||||
exit_code = system_exec_command_line_app("llvm-opt", false,
|
||||
"\"%.*sbin/opt\" \"%s\" -o \"%.*s.bc\" "
|
||||
"\"%.*sbin/opt\" \"%s\" -o \"%.*s\".bc "
|
||||
"-mem2reg "
|
||||
"-memcpyopt "
|
||||
"-die "
|
||||
@@ -265,6 +274,29 @@ int main(int argc, char **argv) {
|
||||
if (exit_code != 0) {
|
||||
return exit_code;
|
||||
}
|
||||
#else
|
||||
// NOTE(zangent): This is separate because it seems that LLVM tools are packaged
|
||||
// with the Windows version, while they will be system-provided on MacOS and GNU/Linux
|
||||
exit_code = system_exec_command_line_app("llvm-opt", false,
|
||||
"opt \"%s\" -o \"%.*s\".bc "
|
||||
"-mem2reg "
|
||||
"-memcpyopt "
|
||||
"-die "
|
||||
#if defined(GB_SYSTEM_OSX)
|
||||
// This sets a requirement of Mountain Lion and up, but the compiler doesn't work without this limit.
|
||||
// NOTE: If you change this (although this minimum is as low as you can go with Odin working)
|
||||
// make sure to also change the `macosx_version_min` param passed to `llc`
|
||||
"-mtriple=x86_64-apple-macosx10.8 "
|
||||
#endif
|
||||
// "-dse "
|
||||
// "-dce "
|
||||
// "-S "
|
||||
"",
|
||||
output_name, LIT(output));
|
||||
if (exit_code != 0) {
|
||||
return exit_code;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(GB_SYSTEM_WINDOWS)
|
||||
timings_start_section(&timings, str_lit("llvm-llc"));
|
||||
@@ -326,7 +358,108 @@ int main(int argc, char **argv) {
|
||||
}
|
||||
|
||||
#else
|
||||
#error Implement build stuff for this platform
|
||||
|
||||
// NOTE(zangent): Linux / Unix is unfinished and not tested very well.
|
||||
|
||||
|
||||
timings_start_section(&timings, str_lit("llvm-llc"));
|
||||
// For more arguments: http://llvm.org/docs/CommandGuide/llc.html
|
||||
exit_code = system_exec_command_line_app("llc", false,
|
||||
"llc \"%.*s.bc\" -filetype=obj -O%d "
|
||||
"%.*s "
|
||||
// "-debug-pass=Arguments "
|
||||
"",
|
||||
LIT(output),
|
||||
optimization_level,
|
||||
LIT(build_context.llc_flags));
|
||||
if (exit_code != 0) {
|
||||
return exit_code;
|
||||
}
|
||||
|
||||
timings_start_section(&timings, str_lit("ld-link"));
|
||||
|
||||
gbString lib_str = gb_string_make(heap_allocator(), "");
|
||||
// defer (gb_string_free(lib_str));
|
||||
char lib_str_buf[1024] = {0};
|
||||
for_array(i, ir_gen.module.foreign_library_paths) {
|
||||
String lib = ir_gen.module.foreign_library_paths.e[i];
|
||||
|
||||
// NOTE(zangent): Sometimes, you have to use -framework on MacOS.
|
||||
// This allows you to specify '-f' in a #foreign_system_library,
|
||||
// without having to implement any new syntax specifically for MacOS.
|
||||
#if defined(GB_SYSTEM_OSX)
|
||||
isize len;
|
||||
if(lib.len > 2 && lib.text[0] == '-' && lib.text[1] == 'f') {
|
||||
len = gb_snprintf(lib_str_buf, gb_size_of(lib_str_buf),
|
||||
" -framework %.*s ", (int)(lib.len) - 2, lib.text + 2);
|
||||
} else {
|
||||
len = gb_snprintf(lib_str_buf, gb_size_of(lib_str_buf),
|
||||
" -l%.*s ", LIT(lib));
|
||||
}
|
||||
#else
|
||||
isize len = gb_snprintf(lib_str_buf, gb_size_of(lib_str_buf),
|
||||
" -l%.*s ", LIT(lib));
|
||||
#endif
|
||||
lib_str = gb_string_appendc(lib_str, lib_str_buf);
|
||||
}
|
||||
|
||||
// Unlike the Win32 linker code, the output_ext includes the dot, because
|
||||
// typically executable files on *NIX systems don't have extensions.
|
||||
char *output_ext = "";
|
||||
char *link_settings = "";
|
||||
char *linker;
|
||||
if (build_context.is_dll) {
|
||||
// Shared libraries are .dylib on MacOS and .so on Linux.
|
||||
// TODO(zangent): Is that statement entirely truthful?
|
||||
#if defined(GB_SYSTEM_OSX)
|
||||
output_ext = ".dylib";
|
||||
#else
|
||||
output_ext = ".so";
|
||||
#endif
|
||||
|
||||
link_settings = "-shared";
|
||||
} else {
|
||||
// TODO: Do I need anything here?
|
||||
link_settings = "";
|
||||
}
|
||||
|
||||
#if defined(GB_SYSTEM_OSX)
|
||||
linker = "ld";
|
||||
#else
|
||||
// TODO(zangent): Figure out how to make ld work on Linux.
|
||||
// It probably has to do with including the entire CRT, but
|
||||
// that's quite a complicated issue to solve while remaining distro-agnostic.
|
||||
// Clang can figure out linker flags for us, and that's good enough _for now_.
|
||||
linker = "clang";
|
||||
#endif
|
||||
|
||||
exit_code = system_exec_command_line_app("ld-link", true,
|
||||
"%s \"%.*s\".o -o \"%.*s%s\" %s "
|
||||
"-lc "
|
||||
" %.*s "
|
||||
" %s "
|
||||
#if defined(GB_SYSTEM_OSX)
|
||||
// This sets a requirement of Mountain Lion and up, but the compiler doesn't work without this limit.
|
||||
// NOTE: If you change this (although this minimum is as low as you can go with Odin working)
|
||||
// make sure to also change the `mtriple` param passed to `opt`
|
||||
" -macosx_version_min 10.8.0 "
|
||||
// This points the linker to where the entry point is
|
||||
" -e _main "
|
||||
#endif
|
||||
, linker, LIT(output), LIT(output), output_ext,
|
||||
lib_str, LIT(build_context.link_flags),
|
||||
link_settings
|
||||
);
|
||||
if (exit_code != 0) {
|
||||
return exit_code;
|
||||
}
|
||||
|
||||
// timings_print_all(&timings);
|
||||
|
||||
if (run_output) {
|
||||
system_exec_command_line_app("odin run", false, "%.*s", cast(int)base_name_len, output_name);
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -1091,7 +1091,6 @@ typedef enum ProcTypeOverloadKind {
|
||||
|
||||
} ProcTypeOverloadKind;
|
||||
|
||||
|
||||
ProcTypeOverloadKind are_proc_types_overload_safe(Type *x, Type *y) {
|
||||
if (x == NULL && y == NULL) return ProcOverload_NotProcedure;
|
||||
if (x == NULL && y != NULL) return ProcOverload_NotProcedure;
|
||||
|
||||
Reference in New Issue
Block a user