diff options
| author | gingerBill <gingerBill@users.noreply.github.com> | 2017-04-09 22:01:22 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2017-04-09 22:01:22 +0100 |
| commit | 0683d2b4f4859a229b6a31790b5a744da577fcd6 (patch) | |
| tree | 5759dd6755ef660d0f22332870e66898f3debb99 /src | |
| parent | d7fdd3d7b8d310ee31a6f170964ce6847458a4c9 (diff) | |
| parent | 6b33b254e92993cd0d468351d09e9386de349c41 (diff) | |
Merge pull request #33 from zangent/master
Base of *nix port
Diffstat (limited to 'src')
| -rw-r--r-- | src/build_settings.c | 99 | ||||
| -rw-r--r-- | src/check_decl.c | 28 | ||||
| -rw-r--r-- | src/checker.c | 16 | ||||
| -rw-r--r-- | src/gb/gb.h | 20 | ||||
| -rw-r--r-- | src/ir.c | 6 | ||||
| -rw-r--r-- | src/ir_print.c | 135 | ||||
| -rw-r--r-- | src/main.c | 137 | ||||
| -rw-r--r-- | src/types.c | 1 |
8 files changed, 415 insertions, 27 deletions
diff --git a/src/build_settings.c b/src/build_settings.c index 0190bff55..6d7dbe939 100644 --- a/src/build_settings.c +++ b/src/build_settings.c @@ -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 } diff --git a/src/check_decl.c b/src/check_decl.c index 0a6c0e5b6..4522fb85e 100644 --- a/src/check_decl.c +++ b/src/check_decl.c @@ -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); } diff --git a/src/checker.c b/src/checker.c index 99d2b790f..22b48ca00 100644 --- a/src/checker.c +++ b/src/checker.c @@ -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); } - - - diff --git a/src/gb/gb.h b/src/gb/gb.h index ed20df1a4..892926a40 100644 --- a/src/gb/gb.h +++ b/src/gb/gb.h @@ -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); } diff --git a/src/ir_print.c b/src/ir_print.c index 9663f7042..22a575437 100644 --- a/src/ir_print.c +++ b/src/ir_print.c @@ -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) { diff --git a/src/main.c b/src/main.c index 118d0e50c..ccc2b4c3b 100644 --- a/src/main.c +++ b/src/main.c @@ -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 diff --git a/src/types.c b/src/types.c index 22bcbae83..773ef5efe 100644 --- a/src/types.c +++ b/src/types.c @@ -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; |