From 89f4e7a8dbed4272f85f10568a542697aa3b38f8 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Mon, 13 Aug 2018 01:22:14 +0100 Subject: `-no-crt` flag for windows amd64 --- src/build_settings.cpp | 3 +- src/checker.cpp | 13 ++++++ src/ir.cpp | 114 ++++++++++++++++++++++++++++++++++--------------- src/ir_print.cpp | 9 ++++ src/main.cpp | 15 +++++-- src/tokenizer.cpp | 14 +++--- 6 files changed, 122 insertions(+), 46 deletions(-) diff --git a/src/build_settings.cpp b/src/build_settings.cpp index ee4466698..ca11468f8 100644 --- a/src/build_settings.cpp +++ b/src/build_settings.cpp @@ -85,6 +85,7 @@ struct BuildContext { bool keep_temp_files; bool no_bounds_check; bool no_output_files; + bool no_crt; gbAffinity affinity; isize thread_count; @@ -528,7 +529,7 @@ void init_build_context(void) { gbString llc_flags = gb_string_make_reserve(heap_allocator(), 64); if (bc->ODIN_DEBUG) { - llc_flags = gb_string_appendc(llc_flags, "-debug-compile "); + // llc_flags = gb_string_appendc(llc_flags, "-debug-compile "); } // NOTE(zangent): The linker flags to set the build architecture are different diff --git a/src/checker.cpp b/src/checker.cpp index acd23f3c0..a8ca75610 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -1314,6 +1314,19 @@ void generate_minimum_dependency_set(Checker *c, Entity *start) { add_dependency_to_set(c, scope_lookup(c->info.runtime_package->scope, required_runtime_entities[i])); } + if (build_context.no_crt) { + String required_no_crt_entities[] = { + // NOTE(bill): Only if these exist + str_lit("memcpy"), + str_lit("memmove"), + str_lit("memset"), + // str_lit("memcmp"), + }; + for (isize i = 0; i < gb_count_of(required_no_crt_entities); i++) { + add_dependency_to_set(c, scope_lookup(c->info.runtime_package->scope, required_no_crt_entities[i])); + } + } + AstPackage *mem = get_core_package(&c->info, str_lit("mem")); String required_mem_entities[] = { str_lit("zero"), diff --git a/src/ir.cpp b/src/ir.cpp index b351f8163..e6315e314 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -622,6 +622,7 @@ struct irGen { bool opt_called; String output_base; String output_name; + bool print_chkstk; }; @@ -1353,6 +1354,7 @@ void ir_add_foreign_library_path(irModule *m, Entity *e) { continue; } + bool ok = true; for_array(path_index, m->foreign_library_paths) { String path = m->foreign_library_paths[path_index]; #if defined(GB_SYSTEM_WINDOWS) @@ -1360,10 +1362,14 @@ void ir_add_foreign_library_path(irModule *m, Entity *e) { #else if (str_eq(path, library_path)) { #endif - continue; + ok = false; + break; } } - array_add(&m->foreign_library_paths, library_path); + + if (ok) { + array_add(&m->foreign_library_paths, library_path); + } } } @@ -8416,51 +8422,91 @@ void ir_gen_tree(irGen *s) { ir_emit_return(proc, v_zero32); } -#if 0 && defined(GB_SYSTEM_WINDOWS) - if (!m->build_context->is_dll && !has_win_main) { - // proc WinMain(inst, prev: rawptr, cmd_line: ^byte, cmd_show: i32) -> i32 - String name = str_lit("WinMain"); - Type *proc_params = alloc_type_tuple(); - Type *proc_results = alloc_type_tuple(); +#if defined(GB_SYSTEM_WINDOWS) + // if (!m->build_context->is_dll && !has_win_main) { + // // proc WinMain(inst, prev: rawptr, cmd_line: ^byte, cmd_show: i32) -> i32 + // String name = str_lit("WinMain"); + // Type *proc_params = alloc_type_tuple(); + // Type *proc_results = alloc_type_tuple(); - Scope *proc_scope = gb_alloc_item(a, Scope); + // Scope *proc_scope = gb_alloc_item(a, Scope); - proc_params->Tuple.variables = gb_alloc_array(a, Entity *, 4); - proc_params->Tuple.variable_count = 4; + // proc_params->Tuple.variables = gb_alloc_array(a, Entity *, 4); + // proc_params->Tuple.variable_count = 4; - proc_results->Tuple.variables = gb_alloc_array(a, Entity *, 1); - proc_results->Tuple.variable_count = 1; + // proc_results->Tuple.variables = gb_alloc_array(a, Entity *, 1); + // proc_results->Tuple.variable_count = 1; - proc_params->Tuple.variables[0] = alloc_entity_param(proc_scope, blank_token, t_rawptr, false); - proc_params->Tuple.variables[1] = alloc_entity_param(proc_scope, blank_token, t_rawptr, false); - proc_params->Tuple.variables[2] = alloc_entity_param(proc_scope, blank_token, t_u8_ptr, false); - proc_params->Tuple.variables[3] = alloc_entity_param(proc_scope, blank_token, t_i32, false); + // proc_params->Tuple.variables[0] = alloc_entity_param(proc_scope, blank_token, t_rawptr, false); + // proc_params->Tuple.variables[1] = alloc_entity_param(proc_scope, blank_token, t_rawptr, false); + // proc_params->Tuple.variables[2] = alloc_entity_param(proc_scope, blank_token, t_u8_ptr, false); + // proc_params->Tuple.variables[3] = alloc_entity_param(proc_scope, blank_token, t_i32, false); - proc_results->Tuple.variables[0] = alloc_entity_param(proc_scope, empty_token, t_i32, false); + // proc_results->Tuple.variables[0] = alloc_entity_param(proc_scope, empty_token, t_i32, false); - Type *proc_type = alloc_type_proc(a, proc_scope, - proc_params, 4, - proc_results, 1, false, ProcCC_Std); + // Type *proc_type = alloc_type_proc(a, proc_scope, + // proc_params, 4, + // proc_results, 1, false, ProcCC_Std); - Ast *body = alloc_ast_node(nullptr, Ast_Invalid); - Entity *e = alloc_entity_procedure(a, nullptr, make_token_ident(name), proc_type, 0); - irValue *p = ir_value_procedure(m, e, proc_type, nullptr, body, name); + // Ast *body = alloc_ast_node(nullptr, Ast_Invalid); + // Entity *e = alloc_entity_procedure(a, nullptr, make_token_ident(name), proc_type, 0); + // irValue *p = ir_value_procedure(m, e, proc_type, nullptr, body, name); - m->entry_point_entity = e; + // m->entry_point_entity = e; - map_set(&m->values, hash_entity(e), p); - map_set(&m->members, hash_string(name), p); + // map_set(&m->values, hash_entity(e), p); + // map_set(&m->members, hash_string(name), p); - irProcedure *proc = &p->Proc; - proc->tags = ProcTag_no_inline; // TODO(bill): is no_inline a good idea? - e->Procedure.link_name = name; + // irProcedure *proc = &p->Proc; + // proc->tags = ProcTag_no_inline; // TODO(bill): is no_inline a good idea? + // e->Procedure.link_name = name; - ir_begin_procedure_body(proc); - ir_emit_runtime_call(proc, "main", nullptr, 0); - ir_emit_return(proc, v_one32); - ir_end_procedure_body(proc); + // ir_begin_procedure_body(proc); + // ir_emit_runtime_call(proc, "main", nullptr, 0); + // ir_emit_return(proc, v_one32); + // ir_end_procedure_body(proc); + // } + if (!build_context.is_dll && build_context.no_crt) { + s->print_chkstk = true; + + { + // void mainCRTStartup(void) + String name = str_lit("mainCRTStartup"); + Type *proc_params = alloc_type_tuple(); + Type *proc_results = alloc_type_tuple(); + + + Type *proc_type = alloc_type_proc(nullptr, + nullptr, 0, + nullptr, 0, + false, + ProcCC_StdCall); + + Ast *body = alloc_ast_node(nullptr, Ast_Invalid); + Entity *e = alloc_entity_procedure(nullptr, make_token_ident(name), proc_type, 0); + irValue *p = ir_value_procedure(m, e, proc_type, nullptr, body, name); + + m->entry_point_entity = e; + + map_set(&m->values, hash_entity(e), p); + map_set(&m->members, hash_string(name), p); + + irProcedure *proc = &p->Proc; + // proc->tags = ProcTag_no_inline; // TODO(bill): is no_inline a good idea? + e->Procedure.link_name = name; + + ir_begin_procedure_body(proc); + ir_emit(proc, ir_alloc_instr(proc, irInstr_StartupRuntime)); + irValue **found = map_get(&proc->module->values, hash_entity(entry_point)); + if (found != nullptr) { + Array args = {}; + ir_emit_call(proc, *found, args); + } + ir_end_procedure_body(proc); + } } + #endif { // Startup Runtime // Cleanup(bill): probably better way of doing code insertion diff --git a/src/ir_print.cpp b/src/ir_print.cpp index ac1c20d90..46d351c8f 100644 --- a/src/ir_print.cpp +++ b/src/ir_print.cpp @@ -1737,6 +1737,15 @@ void print_llvm_ir(irGen *ir) { } } + if (ir->print_chkstk) { + // TODO(bill): Clean up this code + ir_write_str_lit(f, "\n\n"); + ir_write_str_lit(f, "define void @__chkstk() #0 {\n"); + ir_write_str_lit(f, "\tcall void asm sideeffect \"push %rcx \\09\\0Apush %rax \\09\\0Acmp $$0x1000,%rax \\09\\0Alea 24(%rsp),%rcx \\09\\0Ajb 1f \\09\\0A2: \\09\\0Asub $$0x1000,%rcx \\09\\0Aorl $$0,(%rcx) \\09\\0Asub $$0x1000,%rax \\09\\0Acmp $$0x1000,%rax \\09\\0Aja 2b \\09\\0A1: \\09\\0Asub %rax,%rcx \\09\\0Aorl $$0,(%rcx) \\09\\0Apop %rax \\09\\0Apop %rcx \\09\\0Aret \\09\\0A\", \"~{dirflag},~{fpsr},~{flags}\"()\n"); + ir_write_str_lit(f, "\tret void\n"); + ir_write_str_lit(f, "}\n\n"); + } + // NOTE(bill): Print procedures with bodies next for_array(member_index, m->members.entries) { auto *entry = &m->members.entries[member_index]; diff --git a/src/main.cpp b/src/main.cpp index aa50620d9..02237681c 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -22,7 +22,7 @@ i32 system_exec_command_line_app(char *name, bool is_silent, char *fmt, ...) { #if defined(GB_SYSTEM_WINDOWS) STARTUPINFOW start_info = {gb_size_of(STARTUPINFOW)}; PROCESS_INFORMATION pi = {0}; - char cmd_line[4096] = {0}; + char cmd_line[4*1024] = {0}; isize cmd_len; va_list va; gbTempArenaMemory tmp; @@ -212,6 +212,7 @@ enum BuildFlagKind { BuildFlag_CrossCompile, BuildFlag_CrossLibDir, BuildFlag_NoBoundsCheck, + BuildFlag_NoCRT, BuildFlag_COUNT, }; @@ -252,6 +253,7 @@ bool parse_build_flags(Array args) { add_flag(&build_flags, BuildFlag_CrossCompile, str_lit("cross-compile"), BuildFlagParam_String); add_flag(&build_flags, BuildFlag_CrossLibDir, str_lit("cross-lib-dir"), BuildFlagParam_String); add_flag(&build_flags, BuildFlag_NoBoundsCheck, str_lit("no-bounds-check"), BuildFlagParam_None); + add_flag(&build_flags, BuildFlag_NoCRT, str_lit("no-crt"), BuildFlagParam_None); GB_ASSERT(args.count >= 3); Array flag_args = array_slice(args, 3, args.count); @@ -551,6 +553,10 @@ bool parse_build_flags(Array args) { case BuildFlag_NoBoundsCheck: build_context.no_bounds_check = true; break; + + case BuildFlag_NoCRT: + build_context.no_crt = true; + break; } } @@ -840,7 +846,6 @@ int main(int arg_count, char **arg_ptr) { // defer (ir_gen_destroy(&ir_gen)); - timings_start_section(&timings, str_lit("llvm ir gen")); ir_gen_tree(&ir_gen); @@ -879,6 +884,7 @@ int main(int arg_count, char **arg_ptr) { for_array(i, ir_gen.module.foreign_library_paths) { String lib = ir_gen.module.foreign_library_paths[i]; + GB_ASSERT(lib.len < gb_count_of(lib_str_buf)-1); isize len = gb_snprintf(lib_str_buf, gb_size_of(lib_str_buf), " \"%.*s\"", LIT(lib)); lib_str = gb_string_appendc(lib_str, lib_str_buf); @@ -893,6 +899,9 @@ int main(int arg_count, char **arg_ptr) { link_settings = gb_string_append_fmt(link_settings, "/DLL"); } else { link_settings = gb_string_append_fmt(link_settings, "/ENTRY:mainCRTStartup"); + if (build_context.no_crt) { + link_settings = gb_string_append_fmt(link_settings, " /nodefaultlib"); + } } if (ir_gen.module.generate_debug_info) { @@ -913,7 +922,6 @@ int main(int arg_count, char **arg_ptr) { exit_code = system_exec_command_line_app("msvc-link", true, "link \"%.*s.obj\" \"%.*s.res\" -OUT:\"%.*s.%s\" %s " "/defaultlib:libcmt " - // "/nodefaultlib " "/nologo /incremental:no /opt:ref /subsystem:CONSOLE " " %.*s " " %s " @@ -926,7 +934,6 @@ int main(int arg_count, char **arg_ptr) { exit_code = system_exec_command_line_app("msvc-link", true, "link \"%.*s.obj\" -OUT:\"%.*s.%s\" %s " "/defaultlib:libcmt " - // "/nodefaultlib " "/nologo /incremental:no /opt:ref /subsystem:CONSOLE " " %.*s " " %s " diff --git a/src/tokenizer.cpp b/src/tokenizer.cpp index 2c233ee9b..507a4b45d 100644 --- a/src/tokenizer.cpp +++ b/src/tokenizer.cpp @@ -142,16 +142,15 @@ String const token_strings[] = { struct TokenPos { String file; - isize line; - isize column; + isize offset; // starting at 0 + isize line; // starting at 1 + isize column; // starting at 1 }; -TokenPos token_pos(String file, isize line, isize column) { - TokenPos pos = {file, line, column}; - return pos; -} - i32 token_pos_cmp(TokenPos const &a, TokenPos const &b) { + if (a.offset != b.offset) { + return (a.offset < b.offset) ? -1 : +1; + } if (a.line != b.line) { return (a.line < b.line) ? -1 : +1; } @@ -825,6 +824,7 @@ Token tokenizer_get_token(Tokenizer *t) { token.string = make_string(t->curr, 1); token.pos.file = t->fullpath; token.pos.line = t->line_count; + token.pos.offset = t->curr - t->start; token.pos.column = t->curr - t->line + 1; Rune curr_rune = t->curr_rune; -- cgit v1.2.3