diff options
| author | Ginger Bill <bill@gingerbill.org> | 2016-12-08 17:33:30 +0000 |
|---|---|---|
| committer | Ginger Bill <bill@gingerbill.org> | 2016-12-08 17:33:30 +0000 |
| commit | fa89d2775a61b1e6943909ff5c96a1e01892d8c9 (patch) | |
| tree | d4e9fee9e27851a8eccc60913f9de7fe26832bfe /src | |
| parent | 60b6538a7a54d7b2af8142e127116939a7444646 (diff) | |
`build_dll`; Require an entry point procedure `main`
Diffstat (limited to 'src')
| -rw-r--r-- | src/build.c | 1 | ||||
| -rw-r--r-- | src/checker/checker.c | 50 | ||||
| -rw-r--r-- | src/checker/decl.c | 30 | ||||
| -rw-r--r-- | src/checker/entity.c | 10 | ||||
| -rw-r--r-- | src/checker/expr.c | 14 | ||||
| -rw-r--r-- | src/checker/stmt.c | 2 | ||||
| -rw-r--r-- | src/checker/types.c | 12 | ||||
| -rw-r--r-- | src/main.c | 51 | ||||
| -rw-r--r-- | src/parser.c | 61 | ||||
| -rw-r--r-- | src/ssa.c | 35 | ||||
| -rw-r--r-- | src/ssa_print.c | 49 |
11 files changed, 213 insertions, 102 deletions
diff --git a/src/build.c b/src/build.c index 7b40fde8f..7bf361b68 100644 --- a/src/build.c +++ b/src/build.c @@ -9,6 +9,7 @@ typedef struct BuildContext { i64 max_align; String llc_flags; String link_flags; + bool is_dll; } BuildContext; // TODO(bill): OS dependent versions for the BuildContext diff --git a/src/checker/checker.c b/src/checker/checker.c index 06caab6c4..fca1833e9 100644 --- a/src/checker/checker.c +++ b/src/checker/checker.c @@ -292,9 +292,17 @@ bool decl_info_has_init(DeclInfo *d) { return true; } if (d->proc_decl != NULL) { - ast_node(pd, ProcDecl, d->proc_decl); - if (pd->body != NULL) { - return true; + switch (d->proc_decl->kind) { + case_ast_node(pd, ProcDecl, d->proc_decl); + if (pd->body != NULL) { + return true; + } + case_end; + case_ast_node(pd, ProcLit, d->proc_decl); + if (pd->body != NULL) { + return true; + } + case_end; } } @@ -949,12 +957,15 @@ MapEntity generate_minimum_dependency_map(CheckerInfo *info, Entity *start) { MapEntity map = {0}; // Key: Entity * map_entity_init(&map, heap_allocator()); - for_array(i, info->entities.entries) { - MapDeclInfoEntry *entry = &info->entities.entries.e[i]; - Entity *e = cast(Entity *)cast(uintptr)entry->key.key; + for_array(i, info->definitions.entries) { + Entity *e = info->definitions.entries.e[i].value; if (e->scope->is_global) { // NOTE(bill): Require runtime stuff add_dependency_to_map(&map, info, e); + } else if (e->kind == Entity_Procedure) { + if ((e->Procedure.tags & ProcTag_export) != 0) { + add_dependency_to_map(&map, info, e); + } } } @@ -1189,7 +1200,7 @@ void check_global_collect_entities_from_file(Checker *c, Scope *parent_scope, As case_ast_node(pd, ProcDecl, decl); ast_node(n, Ident, pd->name); Token token = *n; - Entity *e = make_entity_procedure(c->allocator, parent_scope, token, NULL); + Entity *e = make_entity_procedure(c->allocator, parent_scope, token, NULL, pd->tags); e->identifier = pd->name; DeclInfo *d = make_declaration_info(c->allocator, e->scope); d->proc_decl = decl; @@ -1386,7 +1397,6 @@ void check_parsed_files(Checker *c) { check_import_entities(c, &file_scopes); - map_scope_destroy(&file_scopes); check_all_global_entities(c); init_preload(c); // NOTE(bill): This could be setup previously through the use of `type_info(_of_val)` @@ -1473,6 +1483,30 @@ void check_parsed_files(Checker *c) { i64 align = type_align_of(c->sizes, c->allocator, e->type); } } + + for_array(i, file_scopes.entries) { + Scope *s = file_scopes.entries.e[i].value; + if (s->is_init) { + Entity *e = current_scope_lookup_entity(s, str_lit("main")); + if (e == NULL) { + Token token = {0}; + if (s->file->tokens.count > 0) { + token = s->file->tokens.e[0]; + } else { + token.pos.file = s->file->tokenizer.fullpath; + token.pos.line = 1; + token.pos.column = 1; + } + + error(token, "Undefined entry point procedure `main`"); + } + + break; + } + } + + map_scope_destroy(&file_scopes); + } diff --git a/src/checker/decl.c b/src/checker/decl.c index 098abfe20..e2dd71daf 100644 --- a/src/checker/decl.c +++ b/src/checker/decl.c @@ -139,8 +139,9 @@ void check_var_decl_node(Checker *c, AstNode *node) { Type *init_type = NULL; if (vd->type) { init_type = check_type_extra(c, vd->type, NULL); - if (init_type == NULL) + if (init_type == NULL) { init_type = t_invalid; + } } for (isize i = 0; i < entity_count; i++) { @@ -180,7 +181,9 @@ void check_init_constant(Checker *c, Entity *e, Operand *operand) { if (operand->mode != Addressing_Constant) { // TODO(bill): better error - error_node(operand->expr, "`%.*s` is not a constant", LIT(ast_node_token(operand->expr).string)); + gbString str = expr_to_string(operand->expr); + error_node(operand->expr, "`%s` is not a constant", str); + gb_string_free(str); if (e->type == NULL) { e->type = t_invalid; } @@ -306,7 +309,7 @@ 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_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; @@ -315,10 +318,9 @@ void check_proc_decl(Checker *c, Entity *e, DeclInfo *d) { if (proc_type != NULL) { TypeProc *pt = &proc_type->Proc; if (pt->param_count != 0 || - pt->result_count) { + pt->result_count != 0) { gbString str = type_to_string(proc_type); - error(e->token, - "Procedure type of `main` was expected to be `proc()`, got %s", str); + error(e->token, "Procedure type of `main` was expected to be `proc()`, got %s", str); gb_string_free(str); } } @@ -328,8 +330,8 @@ 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_link_name) { - error_node(pd->type, "You cannot apply both `foreign` and `link_name` to a procedure"); + if (is_foreign && is_export) { + error_node(pd->type, "You cannot apply both `foreign` and `export_name` to a procedure"); } if (pd->body != NULL) { @@ -350,6 +352,10 @@ void check_proc_decl(Checker *c, Entity *e, DeclInfo *d) { if (proc_decl->foreign_name.len > 0) { name = proc_decl->foreign_name; } + + e->Procedure.is_foreign = true; + e->Procedure.foreign_name = name; + HashKey key = hash_string(name); Entity **found = map_entity_get(fp, key); if (found) { @@ -366,10 +372,12 @@ void check_proc_decl(Checker *c, Entity *e, DeclInfo *d) { } else { map_entity_set(fp, key, e); } - } else if (is_link_name) { + } else if (is_export) { MapEntity *fp = &c->info.foreign_procs; AstNodeProcDecl *proc_decl = &d->proc_decl->ProcDecl; - String name = proc_decl->link_name; + String name = proc_decl->export_name; + + e->Procedure.export_name = name; HashKey key = hash_string(name); Entity **found = map_entity_get(fp, key); @@ -377,7 +385,7 @@ void check_proc_decl(Checker *c, Entity *e, DeclInfo *d) { Entity *f = *found; TokenPos pos = f->token.pos; error_node(d->proc_decl, - "Non unique #link_name for procedure `%.*s`\n" + "Non unique #export name for procedure `%.*s`\n" "\tother at %.*s(%td:%td)", LIT(name), LIT(pos.file), pos.line, pos.column); } else { diff --git a/src/checker/entity.c b/src/checker/entity.c index e2d1cff57..db335dabb 100644 --- a/src/checker/entity.c +++ b/src/checker/entity.c @@ -59,7 +59,12 @@ struct Entity { i32 field_src_index; } Variable; i32 TypeName; - i32 Procedure; + struct { + bool is_foreign; + String foreign_name; + String export_name; + u64 tags; + } Procedure; struct { BuiltinProcId id; } Builtin; @@ -138,8 +143,9 @@ Entity *make_entity_vector_elem(gbAllocator a, Scope *scope, Token token, Type * return entity; } -Entity *make_entity_procedure(gbAllocator a, Scope *scope, Token token, Type *signature_type) { +Entity *make_entity_procedure(gbAllocator a, Scope *scope, Token token, Type *signature_type, u64 tags) { Entity *entity = alloc_entity(a, Entity_Procedure, scope, token, signature_type); + entity->Procedure.tags = tags; return entity; } diff --git a/src/checker/expr.c b/src/checker/expr.c index 5cb448eb1..c0c31452d 100644 --- a/src/checker/expr.c +++ b/src/checker/expr.c @@ -22,8 +22,9 @@ gb_inline Type *check_type(Checker *c, AstNode *expression) { typedef struct DelayedEntity { - Entity *entity; - DeclInfo *decl; + AstNode * ident; + Entity * entity; + DeclInfo * decl; } DelayedEntity; typedef struct DelayedOtherFields { @@ -104,7 +105,7 @@ void check_local_collect_entities(Checker *c, AstNodeArray nodes, DelayedEntitie add_entity_and_decl_info(c, name, e, d); - DelayedEntity delay = {e, d}; + DelayedEntity delay = {name, e, d}; array_add(delayed_entities, delay); } @@ -181,7 +182,7 @@ void check_local_collect_entities(Checker *c, AstNodeArray nodes, DelayedEntitie add_entity_and_decl_info(c, td->name, e, d); - DelayedEntity delay = {e, d}; + DelayedEntity delay = {td->name, e, d}; array_add(delayed_entities, delay); @@ -231,6 +232,7 @@ void check_scope_decls(Checker *c, AstNodeArray nodes, isize reserve_size, Delay for_array(i, delayed_entities) { DelayedEntity delayed = delayed_entities.e[i]; if (delayed.entity->kind == Entity_Constant) { + add_entity_and_decl_info(c, delayed.ident, delayed.entity, delayed.decl); check_entity_decl(c, delayed.entity, delayed.decl, NULL); } } @@ -1480,7 +1482,7 @@ bool check_value_is_expressible(Checker *c, ExactValue in_value, Type *type, Exa case Basic_i16: case Basic_i32: case Basic_i64: - case Basic_i128: + // case Basic_i128: case Basic_int: return gb_is_between(i, -imax, imax-1); @@ -1488,7 +1490,7 @@ bool check_value_is_expressible(Checker *c, ExactValue in_value, Type *type, Exa case Basic_u16: case Basic_u32: case Basic_u64: - case Basic_u128: + // case Basic_u128: case Basic_uint: return !(u < 0 || u > umax); diff --git a/src/checker/stmt.c b/src/checker/stmt.c index f944fd255..d39e6f29f 100644 --- a/src/checker/stmt.c +++ b/src/checker/stmt.c @@ -1095,7 +1095,7 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) { #if 1 // NOTE(bill): This must be handled here so it has access to the parent scope stuff // e.g. using - Entity *e = make_entity_procedure(c->allocator, c->context.scope, pd->name->Ident, NULL); + Entity *e = make_entity_procedure(c->allocator, c->context.scope, pd->name->Ident, NULL, pd->tags); e->identifier = pd->name; DeclInfo *d = make_declaration_info(c->allocator, e->scope); diff --git a/src/checker/types.c b/src/checker/types.c index f65f9cefe..45b40b8e0 100644 --- a/src/checker/types.c +++ b/src/checker/types.c @@ -11,8 +11,8 @@ typedef enum BasicKind { Basic_u32, Basic_i64, Basic_u64, - Basic_i128, - Basic_u128, + // Basic_i128, + // Basic_u128, // Basic_f16, Basic_f32, Basic_f64, @@ -205,8 +205,8 @@ gb_global Type basic_types[] = { {Type_Basic, {Basic_u32, BasicFlag_Integer | BasicFlag_Unsigned, 4, STR_LIT("u32")}}, {Type_Basic, {Basic_i64, BasicFlag_Integer, 8, STR_LIT("i64")}}, {Type_Basic, {Basic_u64, BasicFlag_Integer | BasicFlag_Unsigned, 8, STR_LIT("u64")}}, - {Type_Basic, {Basic_i128, BasicFlag_Integer, 16, STR_LIT("i128")}}, - {Type_Basic, {Basic_u128, BasicFlag_Integer | BasicFlag_Unsigned, 16, STR_LIT("u128")}}, + // {Type_Basic, {Basic_i128, BasicFlag_Integer, 16, STR_LIT("i128")}}, + // {Type_Basic, {Basic_u128, BasicFlag_Integer | BasicFlag_Unsigned, 16, STR_LIT("u128")}}, // {Type_Basic, {Basic_f16, BasicFlag_Float, 2, STR_LIT("f16")}}, {Type_Basic, {Basic_f32, BasicFlag_Float, 4, STR_LIT("f32")}}, {Type_Basic, {Basic_f64, BasicFlag_Float, 8, STR_LIT("f64")}}, @@ -239,8 +239,8 @@ gb_global Type *t_i32 = &basic_types[Basic_i32]; gb_global Type *t_u32 = &basic_types[Basic_u32]; gb_global Type *t_i64 = &basic_types[Basic_i64]; gb_global Type *t_u64 = &basic_types[Basic_u64]; -gb_global Type *t_i128 = &basic_types[Basic_i128]; -gb_global Type *t_u128 = &basic_types[Basic_u128]; +// gb_global Type *t_i128 = &basic_types[Basic_i128]; +// gb_global Type *t_u128 = &basic_types[Basic_u128]; // gb_global Type *t_f16 = &basic_types[Basic_f16]; gb_global Type *t_f32 = &basic_types[Basic_f32]; gb_global Type *t_f64 = &basic_types[Basic_f64]; diff --git a/src/main.c b/src/main.c index e173a2794..480d42397 100644 --- a/src/main.c +++ b/src/main.c @@ -16,7 +16,7 @@ extern "C" { // #include "vm.c" // NOTE(bill): `name` is used in debugging and profiling modes -i32 win32_exec_command_line_app(char *name, char *fmt, ...) { +i32 win32_exec_command_line_app(char *name, bool is_silent, char *fmt, ...) { STARTUPINFOW start_info = {gb_size_of(STARTUPINFOW)}; PROCESS_INFORMATION pi = {0}; char cmd_line[4096] = {0}; @@ -29,8 +29,8 @@ i32 win32_exec_command_line_app(char *name, char *fmt, ...) { start_info.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW; start_info.wShowWindow = SW_SHOW; start_info.hStdInput = GetStdHandle(STD_INPUT_HANDLE); - start_info.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE); - start_info.hStdError = GetStdHandle(STD_ERROR_HANDLE); + start_info.hStdOutput = is_silent ? NULL : GetStdHandle(STD_OUTPUT_HANDLE); + start_info.hStdError = is_silent ? NULL : GetStdHandle(STD_ERROR_HANDLE); va_start(va, fmt); cmd_len = gb_snprintf_va(cmd_line, gb_size_of(cmd_line), fmt, va); @@ -80,11 +80,11 @@ int main(int argc, char **argv) { Timings timings = {0}; timings_init(&timings, str_lit("Total Time"), 128); // defer (timings_destroy(&timings)); - -#if 1 init_string_buffer_memory(); init_global_error_collector(); +#if 1 + BuildContext build_context = {0}; init_build_context(&build_context); @@ -94,9 +94,24 @@ int main(int argc, char **argv) { bool run_output = false; String arg1 = make_string_c(argv[1]); if (str_eq(arg1, str_lit("run"))) { + if (argc != 3) { + usage(argv[0]); + return 1; + } + init_filename = argv[2]; run_output = true; + } else if (str_eq(arg1, str_lit("build_dll"))) { + if (argc != 3) { + usage(argv[0]); + return 1; + } init_filename = argv[2]; + build_context.is_dll = true; } else if (str_eq(arg1, str_lit("build"))) { + if (argc != 3) { + usage(argv[0]); + return 1; + } init_filename = argv[2]; } else if (str_eq(arg1, str_lit("version"))) { gb_printf("%s version %.*s", argv[0], LIT(build_context.ODIN_VERSION)); @@ -136,7 +151,7 @@ int main(int argc, char **argv) { #if 1 ssaGen ssa = {0}; - if (!ssa_gen_init(&ssa, &checker)) { + if (!ssa_gen_init(&ssa, &checker, &build_context)) { return 1; } // defer (ssa_gen_destroy(&ssa)); @@ -164,7 +179,7 @@ int main(int argc, char **argv) { i32 exit_code = 0; // For more passes arguments: http://llvm.org/docs/Passes.html - exit_code = win32_exec_command_line_app("llvm-opt", + exit_code = win32_exec_command_line_app("llvm-opt", false, "%.*sbin/opt %s -o %.*s.bc " "-mem2reg " "-memcpyopt " @@ -182,7 +197,7 @@ int main(int argc, char **argv) { #if 1 timings_start_section(&timings, str_lit("llvm-llc")); // For more arguments: http://llvm.org/docs/CommandGuide/llc.html - exit_code = win32_exec_command_line_app("llvm-llc", + exit_code = win32_exec_command_line_app("llvm-llc", false, "%.*sbin/llc %.*s.bc -filetype=obj -O%d " "%.*s " // "-debug-pass=Arguments " @@ -207,14 +222,24 @@ int main(int argc, char **argv) { lib_str = gb_string_appendc(lib_str, lib_str_buf); } - exit_code = win32_exec_command_line_app("msvc-link", - "link %.*s.obj -OUT:%.*s.exe %s " + char *output_ext = "exe"; + char *link_settings = ""; + if (build_context.is_dll) { + output_ext = "dll"; + link_settings = "/DLL"; + } + + 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 " " %.*s " + " %s " "", - LIT(output), LIT(output), - lib_str, LIT(build_context.link_flags)); + LIT(output), LIT(output), output_ext, + lib_str, LIT(build_context.link_flags), + link_settings + ); if (exit_code != 0) { return exit_code; } @@ -222,7 +247,7 @@ int main(int argc, char **argv) { // timings_print_all(&timings); if (run_output) { - win32_exec_command_line_app("odin run", "%.*s.exe", cast(int)base_name_len, output_name); + win32_exec_command_line_app("odin run", false, "%.*s.exe", cast(int)base_name_len, output_name); } #endif #endif diff --git a/src/parser.c b/src/parser.c index 9bb9e088a..708d336ed 100644 --- a/src/parser.c +++ b/src/parser.c @@ -65,15 +65,15 @@ typedef enum ProcTag { ProcTag_no_bounds_check = GB_BIT(1), ProcTag_foreign = GB_BIT(10), - ProcTag_link_name = GB_BIT(11), + 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_stdcall = GB_BIT(16), - ProcTag_fastcall = GB_BIT(17), - // ProcTag_cdecl = GB_BIT(18), + ProcTag_stdcall = GB_BIT(20), + ProcTag_fastcall = GB_BIT(21), + // ProcTag_cdecl = GB_BIT(22), } ProcTag; typedef enum VarDeclTag { @@ -106,7 +106,7 @@ AstNodeArray make_ast_node_array(AstFile *f) { AstNode *body; \ u64 tags; \ String foreign_name; \ - String link_name; \ + String export_name; \ }) \ AST_NODE_KIND(CompoundLit, "compound literal", struct { \ AstNode *type; \ @@ -246,7 +246,7 @@ AST_NODE_KIND(_DeclBegin, "", i32) \ AstNode *body; \ u64 tags; \ String foreign_name; \ - String link_name; \ + String export_name; \ AstNode *note; \ }) \ AST_NODE_KIND(TypeDecl, "type declaration", struct { \ @@ -686,13 +686,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 link_name) { +AstNode *make_proc_lit(AstFile *f, AstNode *type, AstNode *body, u64 tags, String foreign_name, String export_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.link_name = link_name; + result->ProcLit.export_name = export_name; return result; } @@ -926,14 +926,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 link_name) { +AstNode *make_proc_decl(AstFile *f, AstNode *name, AstNode *proc_type, AstNode *body, u64 tags, String foreign_name, String export_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.link_name = link_name; + result->ProcDecl.export_name = export_name; return result; } @@ -1364,10 +1364,10 @@ bool is_foreign_name_valid(String name) { return true; } -void parse_proc_tags(AstFile *f, u64 *tags, String *foreign_name, String *link_name) { +void parse_proc_tags(AstFile *f, u64 *tags, String *foreign_name, String *export_name) { // TODO(bill): Add this to procedure literals too GB_ASSERT(foreign_name != NULL); - GB_ASSERT(link_name != NULL); + GB_ASSERT(export_name != NULL); while (f->curr_token.kind == Token_Hash) { AstNode *tag_expr = parse_tag_expr(f, NULL); @@ -1390,13 +1390,13 @@ void parse_proc_tags(AstFile *f, u64 *tags, String *foreign_name, String *link_n next_token(f); } - } else if (str_eq(tag_name, str_lit("link_name"))) { - check_proc_add_tag(f, tag_expr, tags, ProcTag_link_name, tag_name); + } else if (str_eq(tag_name, str_lit("export"))) { + check_proc_add_tag(f, tag_expr, tags, ProcTag_export, tag_name); if (f->curr_token.kind == Token_String) { - *link_name = f->curr_token.string; + *export_name = f->curr_token.string; // TODO(bill): Check if valid string - if (!is_foreign_name_valid(*link_name)) { - syntax_error_node(tag_expr, "Invalid alternative link procedure name `%.*s`", LIT(*link_name)); + if (!is_foreign_name_valid(*export_name)) { + syntax_error_node(tag_expr, "Invalid alternative link procedure name `%.*s`", LIT(*export_name)); } next_token(f); @@ -1420,8 +1420,8 @@ void parse_proc_tags(AstFile *f, u64 *tags, String *foreign_name, String *link_n #undef ELSE_IF_ADD_TAG } - if ((*tags & ProcTag_foreign) && (*tags & ProcTag_link_name)) { - syntax_error(f->curr_token, "You cannot apply both #foreign and #link_name to a procedure"); + if ((*tags & ProcTag_foreign) && (*tags & ProcTag_export)) { + syntax_error(f->curr_token, "You cannot apply both #foreign and #export to a procedure"); } if ((*tags & ProcTag_inline) && (*tags & ProcTag_no_inline)) { @@ -1534,23 +1534,24 @@ AstNode *parse_operand(AstFile *f, bool lhs) { u64 tags = 0; String foreign_name = {0}; - String link_name = {0}; - parse_proc_tags(f, &tags, &foreign_name, &link_name); + String export_name = {0}; + parse_proc_tags(f, &tags, &foreign_name, &export_name); if (tags & ProcTag_foreign) { syntax_error(f->curr_token, "#foreign cannot be applied to procedure literals"); } - if (tags & ProcTag_link_name) { - syntax_error(f->curr_token, "#link_name cannot be applied to procedure literals"); + if (tags & ProcTag_export) { + syntax_error(f->curr_token, "#export cannot be applied to procedure literals"); } if (f->curr_token.kind == Token_OpenBrace) { AstNode *body; - f->expr_level++; - body = parse_body(f); - f->expr_level--; + if ((tags & ProcTag_foreign) != 0) { + syntax_error(f->curr_token, "A procedure tagged as `#foreign` cannot have a body"); + } - type = make_proc_lit(f, type, body, tags, foreign_name, link_name); + body = parse_body(f); + type = make_proc_lit(f, type, body, tags, foreign_name, export_name); } else if (type != NULL && type->kind == AstNode_ProcType) { type->ProcType.tags = tags; } @@ -2425,9 +2426,9 @@ AstNode *parse_proc_decl(AstFile *f, Token proc_token, AstNode *name) { AstNode *body = NULL; u64 tags = 0; String foreign_name = {0}; - String link_name = {0}; + String export_name = {0}; - parse_proc_tags(f, &tags, &foreign_name, &link_name); + parse_proc_tags(f, &tags, &foreign_name, &export_name); AstNode *curr_proc = f->curr_proc; f->curr_proc = proc_type; @@ -2442,7 +2443,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, link_name); + return make_proc_decl(f, name, proc_type, body, tags, foreign_name, export_name); } AstNode *parse_if_stmt(AstFile *f) { @@ -17,6 +17,7 @@ typedef Array(ssaValue *) ssaValueArray; typedef struct ssaModule { CheckerInfo * info; + BuildContext *build_context; BaseTypeSizes sizes; gbArena arena; gbArena tmp_arena; @@ -3188,11 +3189,6 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue ssa_emit_store(proc, ssa_emit_struct_ep(proc, slice, 2), len); } - if (args[0]->kind == ssaValue_Constant) { - ssaValueConstant *c = &args[0]->Constant; - gb_printf_err("%s %d\n", type_to_string(c->type), c->value.kind); - } - arg_count = type->param_count; args[arg_count-1] = ssa_emit_load(proc, slice); } @@ -3934,8 +3930,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->link_name.len > 0) { - pd_name = pd->link_name; + if (pd->export_name.len > 0) { + pd_name = pd->export_name; } isize name_len = proc->name.len + 1 + pd_name.len + 1 + 10 + 1; @@ -4676,7 +4672,7 @@ void ssa_module_add_value(ssaModule *m, Entity *e, ssaValue *v) { map_ssa_value_set(&m->values, hash_pointer(e), v); } -void ssa_init_module(ssaModule *m, Checker *c) { +void ssa_init_module(ssaModule *m, Checker *c, BuildContext *build_context) { // TODO(bill): Determine a decent size for the arena isize token_count = c->parser->total_token_count; isize arena_size = 4 * token_count * gb_size_of(ssaValue); @@ -4686,6 +4682,7 @@ void ssa_init_module(ssaModule *m, Checker *c) { m->tmp_allocator = gb_arena_allocator(&m->tmp_arena); m->info = &c->info; m->sizes = c->sizes; + m->build_context = build_context; map_ssa_value_init(&m->values, heap_allocator()); map_ssa_value_init(&m->members, heap_allocator()); @@ -4769,7 +4766,7 @@ void ssa_destroy_module(ssaModule *m) { //////////////////////////////////////////////////////////////// -bool ssa_gen_init(ssaGen *s, Checker *c) { +bool ssa_gen_init(ssaGen *s, Checker *c, BuildContext *build_context) { if (global_error_collector.count != 0) { return false; } @@ -4779,7 +4776,7 @@ bool ssa_gen_init(ssaGen *s, Checker *c) { return false; } - ssa_init_module(&s->module, c); + ssa_init_module(&s->module, c, build_context); s->module.generate_debug_info = false; // TODO(bill): generate appropriate output name @@ -4870,6 +4867,7 @@ void ssa_gen_tree(ssaGen *s) { } else if (e->kind == Entity_Procedure) { if (e->scope->is_init && str_eq(name, str_lit("main"))) { entry_point = e; + break; } } } @@ -4944,13 +4942,13 @@ void ssa_gen_tree(ssaGen *s) { AstNodeProcDecl *pd = &decl->proc_decl->ProcDecl; String original_name = name; AstNode *body = pd->body; - if (pd->tags & ProcTag_foreign) { - name = pd->name->Ident.string; + if (e->Procedure.is_foreign) { + name = e->token.string; // NOTE(bill): Don't use the mangled name } if (pd->foreign_name.len > 0) { name = pd->foreign_name; - } else if (pd->link_name.len > 0) { - name = pd->link_name; + } else if (pd->export_name.len > 0) { + name = pd->export_name; } ssaValue *p = ssa_make_value_procedure(a, m, e, e->type, decl->type_expr, body, name); @@ -4968,8 +4966,9 @@ void ssa_gen_tree(ssaGen *s) { for_array(i, m->members.entries) { MapSsaValueEntry *entry = &m->members.entries.e[i]; ssaValue *v = entry->value; - if (v->kind == ssaValue_Proc) + if (v->kind == ssaValue_Proc) { ssa_build_proc(v, NULL); + } } ssaDebugInfo *compile_unit = m->debug_info.entries.e[0].value; @@ -5011,7 +5010,7 @@ void ssa_gen_tree(ssaGen *s) { 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); + Entity *e = make_entity_procedure(a, NULL, token, proc_type, 0); map_ssa_value_set(&m->values, hash_pointer(e), p); map_ssa_value_set(&m->members, hash_string(name), p); @@ -5103,8 +5102,8 @@ void ssa_gen_tree(ssaGen *s) { case Basic_u32: case Basic_i64: case Basic_u64: - case Basic_i128: - case Basic_u128: + // case Basic_i128: + // case Basic_u128: case Basic_int: case Basic_uint: { tag = ssa_add_local_generated(proc, t_type_info_integer); diff --git a/src/ssa_print.c b/src/ssa_print.c index d1df0ed6c..a1eee845a 100644 --- a/src/ssa_print.c +++ b/src/ssa_print.c @@ -154,8 +154,8 @@ void ssa_print_type(ssaFileBuffer *f, ssaModule *m, Type *t) { case Basic_u32: ssa_fprintf(f, "i32"); break; case Basic_i64: ssa_fprintf(f, "i64"); break; case Basic_u64: ssa_fprintf(f, "i64"); break; - case Basic_i128: ssa_fprintf(f, "i128"); break; - case Basic_u128: ssa_fprintf(f, "i128"); break; + // case Basic_i128: ssa_fprintf(f, "i128"); break; + // case Basic_u128: ssa_fprintf(f, "i128"); break; // case Basic_f16: ssa_fprintf(f, "half"); break; case Basic_f32: ssa_fprintf(f, "float"); break; case Basic_f64: ssa_fprintf(f, "double"); break; @@ -623,7 +623,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_link_name)) != 0); + ssa_print_encoded_global(f, value->Proc.name, (value->Proc.tags & (ProcTag_foreign|ProcTag_export)) != 0); break; case ssaValue_Instr: ssa_fprintf(f, "%%%d", value->index); @@ -1226,11 +1226,14 @@ void ssa_print_proc(ssaFileBuffer *f, ssaModule *m, ssaProcedure *proc) { if (proc->tags & ProcTag_dll_import) { ssa_fprintf(f, "dllimport "); } - if (proc->tags & ProcTag_dll_export) { + } 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 "); } - } else { - ssa_fprintf(f, "\ndefine "); } if (proc->tags & ProcTag_stdcall) { @@ -1248,7 +1251,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_link_name)) != 0); + ssa_print_encoded_global(f, proc->name, (proc->tags & (ProcTag_foreign|ProcTag_export)) != 0); ssa_fprintf(f, "("); if (proc_type->param_count > 0) { @@ -1357,12 +1360,21 @@ void ssa_print_llvm_ir(ssaGen *ssa) { ssa_fprintf(f, "\n"); + bool dll_main_found = false; + for_array(member_index, m->members.entries) { MapSsaValueEntry *entry = &m->members.entries.e[member_index]; ssaValue *v = entry->value; if (v->kind != ssaValue_Proc) { 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); } @@ -1374,11 +1386,34 @@ void ssa_print_llvm_ir(ssaGen *ssa) { if (v->kind != ssaValue_Proc) { 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]; |