diff --git a/build.bat b/build.bat index 0c72bbb5e9f..c46e53ab8e7 100644 --- a/build.bat +++ b/build.bat @@ -48,8 +48,8 @@ rem pushd %build_dir% cl %compiler_settings% "src\main.c" ^ /link %linker_settings% -OUT:%exe_name% ^ + && odin build_dll code/example.odin ^ && odin run code/demo.odin - rem && odin build_dll code/example.odin ^ rem && odin run code/demo.odin diff --git a/code/demo.odin b/code/demo.odin index 296bbfa6e07..767eda25916 100644 --- a/code/demo.odin +++ b/code/demo.odin @@ -18,6 +18,7 @@ main :: proc() { } defer win32.FreeLibrary(lib) + proc_handle := get_proc(lib, "some_thing") if proc_handle == nil { fmt.println("Could not load 'some_thing'") @@ -25,5 +26,6 @@ main :: proc() { } some_thing := (proc_handle as proc()) + fmt.println(some_thing) some_thing() } diff --git a/core/mem.odin b/core/mem.odin index f26cef277d2..719c2c0733f 100644 --- a/core/mem.odin +++ b/core/mem.odin @@ -1,7 +1,7 @@ #import "fmt.odin" #import "os.odin" -set :: proc(data: rawptr, value: i32, len: int) -> rawptr #export "__mem_set" { +set :: proc(data: rawptr, value: i32, len: int) -> rawptr #link_name "__mem_set" { llvm_memset_64bit :: proc(dst: rawptr, val: byte, len: int, align: i32, is_volatile: bool) #foreign "llvm.memset.p0i8.i64" llvm_memset_64bit(data, value as byte, len, 1, false) return data @@ -11,14 +11,14 @@ zero :: proc(data: rawptr, len: int) -> rawptr { return set(data, 0, len) } -copy :: proc(dst, src: rawptr, len: int) -> rawptr #export "__mem_copy" { +copy :: proc(dst, src: rawptr, len: int) -> rawptr #link_name "__mem_copy" { // NOTE(bill): This _must_ implemented like C's memmove llvm_memmove_64bit :: proc(dst, src: rawptr, len: int, align: i32, is_volatile: bool) #foreign "llvm.memmove.p0i8.p0i8.i64" llvm_memmove_64bit(dst, src, len, 1, false) return dst } -copy_non_overlapping :: proc(dst, src: rawptr, len: int) -> rawptr #export "__mem_copy_non_overlapping" { +copy_non_overlapping :: proc(dst, src: rawptr, len: int) -> rawptr #link_name "__mem_copy_non_overlapping" { // NOTE(bill): This _must_ implemented like C's memcpy llvm_memcpy_64bit :: proc(dst, src: rawptr, len: int, align: i32, is_volatile: bool) #foreign "llvm.memcpy.p0i8.p0i8.i64" llvm_memcpy_64bit(dst, src, len, 1, false) @@ -26,7 +26,7 @@ copy_non_overlapping :: proc(dst, src: rawptr, len: int) -> rawptr #export "__me } -compare :: proc(dst, src: rawptr, n: int) -> int #export "__mem_compare" { +compare :: proc(dst, src: rawptr, n: int) -> int #link_name "__mem_compare" { // Translation of http://mgronhol.github.io/fast-strcmp/ a := slice_ptr(dst as ^byte, n) b := slice_ptr(src as ^byte, n) diff --git a/src/checker/decl.c b/src/checker/decl.c index e2dd71daf19..134bfb87b55 100644 --- a/src/checker/decl.c +++ b/src/checker/decl.c @@ -309,7 +309,8 @@ void check_proc_decl(Checker *c, Entity *e, DeclInfo *d) { check_procedure_type(c, proc_type, pd->type); bool is_foreign = (pd->tags & ProcTag_foreign) != 0; - bool is_export = (pd->tags & ProcTag_export) != 0; + bool is_link_name = (pd->tags & ProcTag_link_name) != 0; + bool is_export = (pd->tags & ProcTag_export) != 0; bool is_inline = (pd->tags & ProcTag_inline) != 0; bool is_no_inline = (pd->tags & ProcTag_no_inline) != 0; @@ -330,10 +331,13 @@ void check_proc_decl(Checker *c, Entity *e, DeclInfo *d) { error_node(pd->type, "You cannot apply both `inline` and `no_inline` to a procedure"); } - if (is_foreign && is_export) { - error_node(pd->type, "You cannot apply both `foreign` and `export_name` to a procedure"); + if (is_foreign && is_link_name) { + error_node(pd->type, "You cannot apply both `foreign` and `link_name` to a procedure"); + } else if (is_foreign && is_export) { + error_node(pd->type, "You cannot apply both `foreign` and `export` to a procedure"); } + if (pd->body != NULL) { if (is_foreign) { error_node(pd->body, "A procedure tagged as `#foreign` cannot have a body"); @@ -372,24 +376,31 @@ void check_proc_decl(Checker *c, Entity *e, DeclInfo *d) { } else { map_entity_set(fp, key, e); } - } else if (is_export) { - MapEntity *fp = &c->info.foreign_procs; - AstNodeProcDecl *proc_decl = &d->proc_decl->ProcDecl; - String name = proc_decl->export_name; + } else { + String name = e->token.string; + if (is_link_name) { + AstNodeProcDecl *proc_decl = &d->proc_decl->ProcDecl; + name = proc_decl->link_name; + } - e->Procedure.export_name = name; + if (is_link_name || is_export) { + MapEntity *fp = &c->info.foreign_procs; - HashKey key = hash_string(name); - Entity **found = map_entity_get(fp, key); - if (found) { - Entity *f = *found; - TokenPos pos = f->token.pos; - error_node(d->proc_decl, - "Non unique #export 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); + e->Procedure.link_name = name; + + HashKey key = hash_string(name); + Entity **found = map_entity_get(fp, key); + if (found) { + Entity *f = *found; + TokenPos pos = f->token.pos; + // TODO(bill): Better error message? + error_node(d->proc_decl, + "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/entity.c b/src/checker/entity.c index db335dabb4e..9da334ea872 100644 --- a/src/checker/entity.c +++ b/src/checker/entity.c @@ -62,7 +62,7 @@ struct Entity { struct { bool is_foreign; String foreign_name; - String export_name; + String link_name; u64 tags; } Procedure; struct { diff --git a/src/main.c b/src/main.c index 480d42397c4..a9f3c6d6bef 100644 --- a/src/main.c +++ b/src/main.c @@ -29,8 +29,8 @@ i32 win32_exec_command_line_app(char *name, bool is_silent, char *fmt, ...) { start_info.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW; start_info.wShowWindow = SW_SHOW; start_info.hStdInput = GetStdHandle(STD_INPUT_HANDLE); - start_info.hStdOutput = is_silent ? NULL : GetStdHandle(STD_OUTPUT_HANDLE); - start_info.hStdError = is_silent ? NULL : GetStdHandle(STD_ERROR_HANDLE); + start_info.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE); + start_info.hStdError = GetStdHandle(STD_ERROR_HANDLE); va_start(va, fmt); cmd_len = gb_snprintf_va(cmd_line, gb_size_of(cmd_line), fmt, va); @@ -232,7 +232,7 @@ int main(int argc, char **argv) { exit_code = win32_exec_command_line_app("msvc-link", true, "link %.*s.obj -OUT:%.*s.%s %s " "/defaultlib:libcmt " - "/nologo /incremental:no /opt:ref /subsystem:console " + "/nologo /incremental:no /opt:ref /subsystem:WINDOWS " " %.*s " " %s " "", diff --git a/src/parser.c b/src/parser.c index 708d336ed0d..6b09b9da6e5 100644 --- a/src/parser.c +++ b/src/parser.c @@ -66,10 +66,11 @@ typedef enum ProcTag { ProcTag_foreign = GB_BIT(10), ProcTag_export = GB_BIT(11), - ProcTag_inline = GB_BIT(12), - ProcTag_no_inline = GB_BIT(13), - ProcTag_dll_import = GB_BIT(14), - ProcTag_dll_export = GB_BIT(15), + ProcTag_link_name = GB_BIT(12), + ProcTag_inline = GB_BIT(13), + ProcTag_no_inline = GB_BIT(14), + ProcTag_dll_import = GB_BIT(15), + // ProcTag_dll_export = GB_BIT(16), ProcTag_stdcall = GB_BIT(20), ProcTag_fastcall = GB_BIT(21), @@ -106,7 +107,7 @@ AstNodeArray make_ast_node_array(AstFile *f) { AstNode *body; \ u64 tags; \ String foreign_name; \ - String export_name; \ + String link_name; \ }) \ AST_NODE_KIND(CompoundLit, "compound literal", struct { \ AstNode *type; \ @@ -246,7 +247,7 @@ AST_NODE_KIND(_DeclBegin, "", i32) \ AstNode *body; \ u64 tags; \ String foreign_name; \ - String export_name; \ + String link_name; \ AstNode *note; \ }) \ AST_NODE_KIND(TypeDecl, "type declaration", struct { \ @@ -686,13 +687,13 @@ AstNode *make_ellipsis(AstFile *f, Token token, AstNode *expr) { } -AstNode *make_proc_lit(AstFile *f, AstNode *type, AstNode *body, u64 tags, String foreign_name, String export_name) { +AstNode *make_proc_lit(AstFile *f, AstNode *type, AstNode *body, u64 tags, String foreign_name, String link_name) { AstNode *result = make_node(f, AstNode_ProcLit); result->ProcLit.type = type; result->ProcLit.body = body; result->ProcLit.tags = tags; result->ProcLit.foreign_name = foreign_name; - result->ProcLit.export_name = export_name; + result->ProcLit.link_name = link_name; return result; } @@ -926,14 +927,14 @@ AstNode *make_proc_type(AstFile *f, Token token, AstNodeArray params, AstNodeArr return result; } -AstNode *make_proc_decl(AstFile *f, AstNode *name, AstNode *proc_type, AstNode *body, u64 tags, String foreign_name, String export_name) { +AstNode *make_proc_decl(AstFile *f, AstNode *name, AstNode *proc_type, AstNode *body, u64 tags, String foreign_name, String link_name) { AstNode *result = make_node(f, AstNode_ProcDecl); result->ProcDecl.name = name; result->ProcDecl.type = proc_type; result->ProcDecl.body = body; result->ProcDecl.tags = tags; result->ProcDecl.foreign_name = foreign_name; - result->ProcDecl.export_name = export_name; + result->ProcDecl.link_name = link_name; return result; } @@ -1364,10 +1365,10 @@ bool is_foreign_name_valid(String name) { return true; } -void parse_proc_tags(AstFile *f, u64 *tags, String *foreign_name, String *export_name) { +void parse_proc_tags(AstFile *f, u64 *tags, String *foreign_name, String *link_name) { // TODO(bill): Add this to procedure literals too GB_ASSERT(foreign_name != NULL); - GB_ASSERT(export_name != NULL); + GB_ASSERT(link_name != NULL); while (f->curr_token.kind == Token_Hash) { AstNode *tag_expr = parse_tag_expr(f, NULL); @@ -1390,13 +1391,13 @@ void parse_proc_tags(AstFile *f, u64 *tags, String *foreign_name, String *export next_token(f); } - } else if (str_eq(tag_name, str_lit("export"))) { - check_proc_add_tag(f, tag_expr, tags, ProcTag_export, tag_name); + } else if (str_eq(tag_name, str_lit("link_name"))) { + check_proc_add_tag(f, tag_expr, tags, ProcTag_link_name, tag_name); if (f->curr_token.kind == Token_String) { - *export_name = f->curr_token.string; + *link_name = f->curr_token.string; // TODO(bill): Check if valid string - if (!is_foreign_name_valid(*export_name)) { - syntax_error_node(tag_expr, "Invalid alternative link procedure name `%.*s`", LIT(*export_name)); + if (!is_foreign_name_valid(*link_name)) { + syntax_error_node(tag_expr, "Invalid alternative link procedure name `%.*s`", LIT(*link_name)); } next_token(f); @@ -1404,12 +1405,13 @@ void parse_proc_tags(AstFile *f, u64 *tags, String *foreign_name, String *export expect_token(f, Token_String); } } + ELSE_IF_ADD_TAG(export) ELSE_IF_ADD_TAG(bounds_check) ELSE_IF_ADD_TAG(no_bounds_check) ELSE_IF_ADD_TAG(inline) ELSE_IF_ADD_TAG(no_inline) ELSE_IF_ADD_TAG(dll_import) - ELSE_IF_ADD_TAG(dll_export) + // ELSE_IF_ADD_TAG(dll_export) ELSE_IF_ADD_TAG(stdcall) ELSE_IF_ADD_TAG(fastcall) // ELSE_IF_ADD_TAG(cdecl) @@ -1534,8 +1536,8 @@ AstNode *parse_operand(AstFile *f, bool lhs) { u64 tags = 0; String foreign_name = {0}; - String export_name = {0}; - parse_proc_tags(f, &tags, &foreign_name, &export_name); + String link_name = {0}; + parse_proc_tags(f, &tags, &foreign_name, &link_name); if (tags & ProcTag_foreign) { syntax_error(f->curr_token, "#foreign cannot be applied to procedure literals"); } @@ -1551,7 +1553,7 @@ AstNode *parse_operand(AstFile *f, bool lhs) { } body = parse_body(f); - type = make_proc_lit(f, type, body, tags, foreign_name, export_name); + type = make_proc_lit(f, type, body, tags, foreign_name, link_name); } else if (type != NULL && type->kind == AstNode_ProcType) { type->ProcType.tags = tags; } @@ -2426,9 +2428,9 @@ AstNode *parse_proc_decl(AstFile *f, Token proc_token, AstNode *name) { AstNode *body = NULL; u64 tags = 0; String foreign_name = {0}; - String export_name = {0}; + String link_name = {0}; - parse_proc_tags(f, &tags, &foreign_name, &export_name); + parse_proc_tags(f, &tags, &foreign_name, &link_name); AstNode *curr_proc = f->curr_proc; f->curr_proc = proc_type; @@ -2443,7 +2445,7 @@ AstNode *parse_proc_decl(AstFile *f, Token proc_token, AstNode *name) { } f->curr_proc = curr_proc; - return make_proc_decl(f, name, proc_type, body, tags, foreign_name, export_name); + return make_proc_decl(f, name, proc_type, body, tags, foreign_name, link_name); } AstNode *parse_if_stmt(AstFile *f) { diff --git a/src/ssa.c b/src/ssa.c index 89fd46d0ded..e4b8a8e849a 100644 --- a/src/ssa.c +++ b/src/ssa.c @@ -39,6 +39,8 @@ typedef struct ssaModule { i32 global_string_index; i32 global_array_index; // For ConstantSlice + Entity * entry_point_entity; + Array(ssaProcedure *) procs; // NOTE(bill): All procedures with bodies ssaValueArray procs_to_generate; // NOTE(bill): Procedures to generate } ssaModule; @@ -97,7 +99,6 @@ typedef struct ssaDefer { }; } ssaDefer; -typedef struct ssaProcedure ssaProcedure; struct ssaProcedure { ssaProcedure * parent; Array(ssaProcedure *) children; @@ -110,7 +111,7 @@ struct ssaProcedure { AstNode * body; u64 tags; - ssaValueArray params; + ssaValueArray params; Array(ssaDefer) defer_stmts; Array(ssaBlock *) blocks; i32 scope_index; @@ -118,7 +119,7 @@ struct ssaProcedure { ssaBlock * entry_block; ssaBlock * curr_block; ssaTargetList * target_list; - ssaValueArray referrers; + ssaValueArray referrers; i32 local_count; i32 instr_count; @@ -3930,8 +3931,8 @@ void ssa_build_stmt_internal(ssaProcedure *proc, AstNode *node) { // parent.name-guid String original_name = pd->name->Ident.string; String pd_name = original_name; - if (pd->export_name.len > 0) { - pd_name = pd->export_name; + if (pd->link_name.len > 0) { + pd_name = pd->link_name; } isize name_len = proc->name.len + 1 + pd_name.len + 1 + 10 + 1; @@ -4571,8 +4572,11 @@ void ssa_begin_procedure_body(ssaProcedure *proc) { TypeTuple *params = &proc->type->Proc.params->Tuple; for (isize i = 0; i < params->variable_count; i++) { Entity *e = params->variables[i]; - ssaValue *param = ssa_add_param(proc, e); - array_add(&proc->params, param); + if (!str_eq(e->token.string, str_lit("")) && + !str_eq(e->token.string, str_lit("_"))) { + ssaValue *param = ssa_add_param(proc, e); + array_add(&proc->params, param); + } } } } @@ -4857,6 +4861,8 @@ void ssa_gen_tree(ssaGen *s) { isize global_variable_max_count = 0; Entity *entry_point = NULL; + bool has_dll_main = false; + bool has_win_main = false; for_array(i, info->entities.entries) { MapDeclInfoEntry *entry = &info->entities.entries.e[i]; @@ -4864,10 +4870,18 @@ void ssa_gen_tree(ssaGen *s) { String name = e->token.string; if (e->kind == Entity_Variable) { global_variable_max_count++; - } else if (e->kind == Entity_Procedure) { + } else if (e->kind == Entity_Procedure && !e->scope->is_global) { if (e->scope->is_init && str_eq(name, str_lit("main"))) { entry_point = e; - break; + } + if ((e->Procedure.tags & ProcTag_export) != 0 || + (e->Procedure.link_name.len > 0) || + (e->scope->is_file && e->Procedure.link_name.len > 0)) { + if (!has_dll_main && str_eq(name, str_lit("DllMain"))) { + has_dll_main = true; + } else if (!has_win_main && str_eq(name, str_lit("WinMain"))) { + has_win_main = true; + } } } } @@ -4879,6 +4893,7 @@ void ssa_gen_tree(ssaGen *s) { Array(ssaGlobalVariable) global_variables; array_init_reserve(&global_variables, m->tmp_allocator, global_variable_max_count); + m->entry_point_entity = entry_point; m->min_dep_map = generate_minimum_dependency_map(info, entry_point); for_array(i, info->entities.entries) { @@ -4897,8 +4912,13 @@ void ssa_gen_tree(ssaGen *s) { continue; } - if (!scope->is_global && !scope->is_init) { - name = ssa_mangle_name(s, e->token.pos.file, name); + if (!scope->is_global) { + if (e->kind == Entity_Procedure && (e->Procedure.tags & ProcTag_export) != 0) { + } else if (e->kind == Entity_Procedure && e->Procedure.link_name.len > 0) { + } else if (scope->is_init && e->kind == Entity_Procedure && str_eq(name, str_lit("main"))) { + } else { + name = ssa_mangle_name(s, e->token.pos.file, name); + } } @@ -4947,8 +4967,8 @@ void ssa_gen_tree(ssaGen *s) { } if (pd->foreign_name.len > 0) { name = pd->foreign_name; - } else if (pd->export_name.len > 0) { - name = pd->export_name; + } else if (pd->link_name.len > 0) { + name = pd->link_name; } ssaValue *p = ssa_make_value_procedure(a, m, e, e->type, decl->type_expr, body, name); @@ -4999,7 +5019,93 @@ void ssa_gen_tree(ssaGen *s) { } } +#if defined(GB_SYSTEM_WINDOWS) + if (m->build_context->is_dll && !has_dll_main) { + // DllMain :: proc(inst: rawptr, reason: u32, reserved: rawptr) -> i32 + String name = str_lit("DllMain"); + Type *proc_params = make_type_tuple(a); + Type *proc_results = make_type_tuple(a); + + Scope *proc_scope = gb_alloc_item(a, Scope); + + proc_params->Tuple.variables = gb_alloc_array(a, Entity *, 3); + proc_params->Tuple.variable_count = 3; + + proc_results->Tuple.variables = gb_alloc_array(a, Entity *, 1); + proc_results->Tuple.variable_count = 1; + + proc_params->Tuple.variables[0] = make_entity_param(a, proc_scope, blank_token, t_rawptr, false); + proc_params->Tuple.variables[1] = make_entity_param(a, proc_scope, blank_token, t_u32, false); + proc_params->Tuple.variables[2] = make_entity_param(a, proc_scope, blank_token, t_rawptr, false); + + proc_results->Tuple.variables[0] = make_entity_param(a, proc_scope, empty_token, t_i32, false); + + + Type *proc_type = make_type_proc(a, proc_scope, + proc_params, 3, + proc_results, 1, false); + + AstNode *body = gb_alloc_item(a, AstNode); + Entity *e = make_entity_procedure(a, NULL, make_token_ident(name), proc_type, 0); + ssaValue *p = ssa_make_value_procedure(a, m, e, proc_type, NULL, body, name); + + map_ssa_value_set(&m->values, hash_pointer(e), p); + map_ssa_value_set(&m->members, hash_string(name), p); + + ssaProcedure *proc = &p->Proc; + proc->tags = ProcTag_no_inline | ProcTag_stdcall; // TODO(bill): is no_inline a good idea? + e->Procedure.link_name = name; + + ssa_begin_procedure_body(proc); + ssa_emit_global_call(proc, "main", NULL, 0); + ssa_emit_return(proc, v_one32); + ssa_end_procedure_body(proc); + } +#endif +#if defined(GB_SYSTEM_WINDOWS) + if (!m->build_context->is_dll && !has_win_main) { + // WinMain :: proc(inst, prev: rawptr, cmd_line: ^byte, cmd_show: i32) -> i32 + String name = str_lit("WinMain"); + Type *proc_params = make_type_tuple(a); + Type *proc_results = make_type_tuple(a); + + 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_results->Tuple.variables = gb_alloc_array(a, Entity *, 1); + proc_results->Tuple.variable_count = 1; + + proc_params->Tuple.variables[0] = make_entity_param(a, proc_scope, blank_token, t_rawptr, false); + proc_params->Tuple.variables[1] = make_entity_param(a, proc_scope, blank_token, t_rawptr, false); + proc_params->Tuple.variables[2] = make_entity_param(a, proc_scope, blank_token, t_u8_ptr, false); + proc_params->Tuple.variables[3] = make_entity_param(a, proc_scope, blank_token, t_i32, false); + + proc_results->Tuple.variables[0] = make_entity_param(a, proc_scope, empty_token, t_i32, false); + + + Type *proc_type = make_type_proc(a, proc_scope, + proc_params, 4, + proc_results, 1, false); + + AstNode *body = gb_alloc_item(a, AstNode); + Entity *e = make_entity_procedure(a, NULL, make_token_ident(name), proc_type, 0); + ssaValue *p = ssa_make_value_procedure(a, m, e, proc_type, NULL, body, name); + + map_ssa_value_set(&m->values, hash_pointer(e), p); + map_ssa_value_set(&m->members, hash_string(name), p); + + ssaProcedure *proc = &p->Proc; + proc->tags = ProcTag_no_inline | ProcTag_stdcall; // TODO(bill): is no_inline a good idea? + e->Procedure.link_name = name; + ssa_begin_procedure_body(proc); + ssa_emit_global_call(proc, "main", NULL, 0); + ssa_emit_return(proc, v_one32); + ssa_end_procedure_body(proc); + } +#endif { // Startup Runtime // Cleanup(bill): probably better way of doing code insertion String name = str_lit(SSA_STARTUP_RUNTIME_PROC_NAME); @@ -5007,10 +5113,8 @@ void ssa_gen_tree(ssaGen *s) { NULL, 0, NULL, 0, false); AstNode *body = gb_alloc_item(a, AstNode); - ssaValue *p = ssa_make_value_procedure(a, m, NULL, proc_type, NULL, body, name); - Token token = {0}; - token.string = name; - Entity *e = make_entity_procedure(a, NULL, token, proc_type, 0); + Entity *e = make_entity_procedure(a, NULL, make_token_ident(name), proc_type, 0); + ssaValue *p = ssa_make_value_procedure(a, m, e, proc_type, NULL, body, name); map_ssa_value_set(&m->values, hash_pointer(e), p); map_ssa_value_set(&m->members, hash_string(name), p); @@ -5431,13 +5535,6 @@ void ssa_gen_tree(ssaGen *s) { ssa_build_proc(m->procs_to_generate.e[i], m->procs_to_generate.e[i]->Proc.parent); } - // { - // DWORD old_protect = 0; - // DWORD new_protect = PAGE_READONLY; - // BOOL ok = VirtualProtect(m->arena.physical_start, m->arena.total_size, new_protect, &old_protect); - // } - - // m->layout = str_lit("e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"); } diff --git a/src/ssa_print.c b/src/ssa_print.c index a1eee845a3d..17ec1c9b1b1 100644 --- a/src/ssa_print.c +++ b/src/ssa_print.c @@ -127,9 +127,9 @@ void ssa_print_encoded_local(ssaFileBuffer *f, String name) { ssa_print_escape_string(f, name, true); } -void ssa_print_encoded_global(ssaFileBuffer *f, String name, bool global_scope) { +void ssa_print_encoded_global(ssaFileBuffer *f, String name, bool remove_prefix) { ssa_fprintf(f, "@"); - if (!global_scope && str_ne(name, str_lit("main"))) { + if (!remove_prefix) { ssa_fprintf(f, "."); } ssa_print_escape_string(f, name, true); @@ -567,6 +567,20 @@ void ssa_print_block_name(ssaFileBuffer *f, ssaBlock *b) { } } +bool ssa_print_is_proc_global(ssaModule *m, ssaProcedure *proc) { + if (proc->entity != NULL && + proc->entity->kind == Entity_Procedure) { + if (m->entry_point_entity == proc->entity) { + // TODO(bill): This may not be needed during windows + return true; + } + if (proc->entity->Procedure.link_name.len > 0) { + return true; + } + } + return (proc->tags & (ProcTag_foreign|ProcTag_export)) != 0; +} + void ssa_print_value(ssaFileBuffer *f, ssaModule *m, ssaValue *value, Type *type_hint) { if (value == NULL) { ssa_fprintf(f, "!!!NULL_VALUE"); @@ -623,7 +637,7 @@ void ssa_print_value(ssaFileBuffer *f, ssaModule *m, ssaValue *value, Type *type ssa_print_encoded_local(f, value->Param.entity->token.string); break; case ssaValue_Proc: - ssa_print_encoded_global(f, value->Proc.name, (value->Proc.tags & (ProcTag_foreign|ProcTag_export)) != 0); + ssa_print_encoded_global(f, value->Proc.name, ssa_print_is_proc_global(m, &value->Proc)); break; case ssaValue_Instr: ssa_fprintf(f, "%%%d", value->index); @@ -1229,10 +1243,11 @@ void ssa_print_proc(ssaFileBuffer *f, ssaModule *m, ssaProcedure *proc) { } else { ssa_fprintf(f, "\n"); ssa_fprintf(f, "define "); - if (proc->tags & ProcTag_export) { - ssa_fprintf(f, "dllexport "); - } else if (proc->tags & ProcTag_dll_export) { - ssa_fprintf(f, "dllexport "); + if (m->build_context->is_dll) { + // if (proc->tags & (ProcTag_export|ProcTag_dll_export)) { + if (proc->tags & (ProcTag_export)) { + ssa_fprintf(f, "dllexport "); + } } } @@ -1251,7 +1266,7 @@ void ssa_print_proc(ssaFileBuffer *f, ssaModule *m, ssaProcedure *proc) { } ssa_fprintf(f, " "); - ssa_print_encoded_global(f, proc->name, (proc->tags & (ProcTag_foreign|ProcTag_export)) != 0); + ssa_print_encoded_global(f, proc->name, ssa_print_is_proc_global(m, proc)); ssa_fprintf(f, "("); if (proc_type->param_count > 0) { @@ -1263,7 +1278,10 @@ void ssa_print_proc(ssaFileBuffer *f, ssaModule *m, ssaProcedure *proc) { } ssa_print_type(f, m, e->type); if (proc->body != NULL) { - ssa_fprintf(f, " %%%.*s", LIT(e->token.string)); + if (!str_eq(e->token.string, str_lit("")) && + !str_eq(e->token.string, str_lit("_"))) { + ssa_fprintf(f, " %%%.*s", LIT(e->token.string)); + } } } } @@ -1369,12 +1387,6 @@ void ssa_print_llvm_ir(ssaGen *ssa) { continue; } -#if defined(GB_SYSTEM_WINDOWS) - if (str_eq(v->Proc.name, str_lit("DllMain"))) { - dll_main_found = true; - } -#endif - if (v->Proc.body == NULL) { ssa_print_proc(f, m, &v->Proc); } @@ -1387,34 +1399,11 @@ void ssa_print_llvm_ir(ssaGen *ssa) { continue; } -#if defined(GB_SYSTEM_WINDOWS) - if (str_eq(v->Proc.name, str_lit("DllMain"))) { - dll_main_found = true; - } -#endif - if (v->Proc.body != NULL) { ssa_print_proc(f, m, &v->Proc); } } - if (m->build_context->is_dll) { -#if !defined(GB_SYSTEM_WINDOWS) -#error Setup dll initialization on linux if appropriate -#else - if (!dll_main_found) { - ssa_fprintf(f, - "define i32 @DllMain(%%..rawptr %%inst, i32 %%reason, %%..rawptr %%reserved) {\n" - "entry:\n" - " call void @main()\n" - " ret i32 1\n" - "}\n" - ); - } -#endif - } - - for_array(member_index, m->members.entries) { MapSsaValueEntry *entry = &m->members.entries.e[member_index]; ssaValue *v = entry->value;