diff options
| author | gingerBill <bill@gingerbill.org> | 2021-11-04 12:40:50 +0000 |
|---|---|---|
| committer | gingerBill <bill@gingerbill.org> | 2021-11-04 12:40:50 +0000 |
| commit | 6ded538546cca4f1e50a011a64932f7f3c784cc2 (patch) | |
| tree | 03ac73c9042cc45ab20da51a93de3f9bf6f8de0f /src | |
| parent | 3fa7dabaa87e99386e469bd5e4badab23f89aaef (diff) | |
`@(linkage=<string>)` for procedures and variables; `@(require)` for procedures; `package runtime` linkage improvements; Subsequence improvements to `lb_run_remove_unused_function_pass`
Diffstat (limited to 'src')
| -rw-r--r-- | src/check_decl.cpp | 18 | ||||
| -rw-r--r-- | src/checker.cpp | 55 | ||||
| -rw-r--r-- | src/checker.hpp | 1 | ||||
| -rw-r--r-- | src/entity.cpp | 6 | ||||
| -rw-r--r-- | src/llvm_backend.cpp | 4 | ||||
| -rw-r--r-- | src/llvm_backend.hpp | 4 | ||||
| -rw-r--r-- | src/llvm_backend_general.cpp | 13 | ||||
| -rw-r--r-- | src/llvm_backend_opt.cpp | 32 | ||||
| -rw-r--r-- | src/llvm_backend_proc.cpp | 2 |
9 files changed, 109 insertions, 26 deletions
diff --git a/src/check_decl.cpp b/src/check_decl.cpp index 33e85edf7..134dbb35b 100644 --- a/src/check_decl.cpp +++ b/src/check_decl.cpp @@ -730,7 +730,6 @@ void check_proc_decl(CheckerContext *ctx, Entity *e, DeclInfo *d) { if (ac.set_cold) { e->flags |= EntityFlag_Cold; } - e->Procedure.optimization_mode = cast(ProcedureOptimizationMode)ac.optimization_mode; @@ -760,6 +759,22 @@ void check_proc_decl(CheckerContext *ctx, Entity *e, DeclInfo *d) { bool is_foreign = e->Procedure.is_foreign; bool is_export = e->Procedure.is_export; + + if (ac.linkage.len != 0) { + if (ac.linkage == "internal") { e->flags |= EntityFlag_CustomLinkage_Internal; } + else if (ac.linkage == "strong") { e->flags |= EntityFlag_CustomLinkage_Strong; } + else if (ac.linkage == "weak") { e->flags |= EntityFlag_CustomLinkage_Weak; } + else if (ac.linkage == "link_once") { e->flags |= EntityFlag_CustomLinkage_LinkOnce; } + + if (is_foreign && (e->flags & EntityFlag_CustomLinkage_Internal)) { + error(e->token, "A foreign procedure may not have an \"internal\" linkage"); + } + } + + if (ac.require_declaration) { + e->flags |= EntityFlag_Require; + } + if (e->pkg != nullptr && e->token.string == "main") { if (pt->param_count != 0 || @@ -943,6 +958,7 @@ void check_global_variable_decl(CheckerContext *ctx, Entity *&e, Ast *type_expr, } if (ac.require_declaration) { + e->flags |= EntityFlag_Require; mpmc_enqueue(&ctx->info->required_global_variable_queue, e); } diff --git a/src/checker.cpp b/src/checker.cpp index 92e38a643..591377726 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -783,6 +783,7 @@ void init_universal(void) { add_global_bool_constant("ODIN_DEFAULT_TO_NIL_ALLOCATOR", bc->ODIN_DEFAULT_TO_NIL_ALLOCATOR); add_global_bool_constant("ODIN_NO_DYNAMIC_LITERALS", bc->no_dynamic_literals); add_global_bool_constant("ODIN_NO_CRT", bc->no_crt); + add_global_bool_constant("ODIN_USE_SEPARATE_MODULES", bc->use_separate_modules); add_global_bool_constant("ODIN_TEST", bc->command_kind == Command_test); @@ -1388,7 +1389,9 @@ bool could_entity_be_lazy(Entity *e, DeclInfo *d) { return false; } else if (name == "init") { return false; - } + } else if (name == "linkage") { + return false; + } } } } @@ -2658,6 +2661,32 @@ DECL_ATTRIBUTE_PROC(proc_decl_attribute) { return false; } return true; + } else if (name == "linkage") { + ExactValue ev = check_decl_attribute_value(c, value); + if (ev.kind != ExactValue_String) { + error(value, "Expected either a string 'linkage'"); + return false; + } + String linkage = ev.value_string; + if (linkage == "internal" || + linkage == "strong" || + linkage == "weak" || + linkage == "link_once") { + ac->linkage = linkage; + } else { + error(elem, "Invalid linkage '%.*s'. Valid kinds:", LIT(linkage)); + error_line("\tinternal\n"); + error_line("\tstrong\n"); + error_line("\tweak\n"); + error_line("\tlink_once\n"); + } + return true; + } else if (name == "require") { + if (value != nullptr) { + error(elem, "'require' does not have any parameters"); + } + ac->require_declaration = true; + return true; } else if (name == "init") { if (value != nullptr) { error(value, "'%.*s' expects no parameter, or a string literal containing \"file\" or \"package\"", LIT(name)); @@ -2894,7 +2923,7 @@ DECL_ATTRIBUTE_PROC(var_decl_attribute) { if (name == "require") { if (value != nullptr) { - error(elem, "'static' does not have any parameters"); + error(elem, "'require' does not have any parameters"); } ac->require_declaration = true; return true; @@ -2912,6 +2941,26 @@ DECL_ATTRIBUTE_PROC(var_decl_attribute) { error(elem, "An exported variable cannot be thread local"); } return true; + } else if (name == "linkage") { + ExactValue ev = check_decl_attribute_value(c, value); + if (ev.kind != ExactValue_String) { + error(value, "Expected either a string 'linkage'"); + return false; + } + String linkage = ev.value_string; + if (linkage == "internal" || + linkage == "strong" || + linkage == "weak" || + linkage == "link_once") { + ac->linkage = linkage; + } else { + error(elem, "Invalid linkage '%.*s'. Valid kinds:", LIT(linkage)); + error_line("\tinternal\n"); + error_line("\tstrong\n"); + error_line("\tweak\n"); + error_line("\tlink_once\n"); + } + return true; } else if (name == "link_name") { if (ev.kind == ExactValue_String) { ac->link_name = ev.value_string; @@ -3959,6 +4008,8 @@ DECL_ATTRIBUTE_PROC(foreign_import_decl_attribute) { if (name == "force" || name == "require") { if (value != nullptr) { error(elem, "Expected no parameter for '%.*s'", LIT(name)); + } else if (name == "force") { + warning(elem, "'force' is deprecated and is identical to 'require'"); } ac->require_declaration = true; return true; diff --git a/src/checker.hpp b/src/checker.hpp index 97631c547..c65d766ba 100644 --- a/src/checker.hpp +++ b/src/checker.hpp @@ -102,6 +102,7 @@ struct AttributeContext { String link_name; String link_prefix; String link_section; + String linkage; isize init_expr_list_count; String thread_local_model; String deprecated_message; diff --git a/src/entity.cpp b/src/entity.cpp index d95c74f22..ef4f7e0fa 100644 --- a/src/entity.cpp +++ b/src/entity.cpp @@ -76,6 +76,12 @@ enum EntityFlag : u64 { EntityFlag_Init = 1ull<<31, EntityFlag_CustomLinkName = 1ull<<40, + EntityFlag_CustomLinkage_Internal = 1ull<<41, + EntityFlag_CustomLinkage_Strong = 1ull<<42, + EntityFlag_CustomLinkage_Weak = 1ull<<43, + EntityFlag_CustomLinkage_LinkOnce = 1ull<<44, + + EntityFlag_Require = 1ull<<50, EntityFlag_Overridden = 1ull<<63, }; diff --git a/src/llvm_backend.cpp b/src/llvm_backend.cpp index c0a7b60df..928efbb54 100644 --- a/src/llvm_backend.cpp +++ b/src/llvm_backend.cpp @@ -1498,6 +1498,8 @@ void lb_generate_code(lbGenerator *gen) { LLVMSetLinkage(g.value, LLVMInternalLinkage); } } + lb_set_linkage_from_entity_flags(m, g.value, e->flags); + if (e->Variable.link_section.len > 0) { LLVMSetSection(g.value, alloc_cstring(permanent_allocator(), e->Variable.link_section)); } @@ -1675,7 +1677,7 @@ void lb_generate_code(lbGenerator *gen) { for_array(i, gen->modules.entries) { lbModule *m = gen->modules.entries[i].value; - lb_run_remove_unused_function_pass(m->mod); + lb_run_remove_unused_function_pass(m); auto wd = gb_alloc_item(permanent_allocator(), lbLLVMModulePassWorkerData); wd->m = m; diff --git a/src/llvm_backend.hpp b/src/llvm_backend.hpp index 5fc5dfebf..16c9f752e 100644 --- a/src/llvm_backend.hpp +++ b/src/llvm_backend.hpp @@ -605,4 +605,6 @@ char const *llvm_linkage_strings[] = { "common linkage", "linker private linkage", "linker private weak linkage" -};
\ No newline at end of file +}; + +#define ODIN_METADATA_REQUIRE "odin-metadata-require", 21 diff --git a/src/llvm_backend_general.cpp b/src/llvm_backend_general.cpp index b1c1f924b..5c664f0e0 100644 --- a/src/llvm_backend_general.cpp +++ b/src/llvm_backend_general.cpp @@ -2692,3 +2692,16 @@ lbAddr lb_add_local_generated_temp(lbProcedure *p, Type *type, i64 min_alignment lb_try_update_alignment(res.addr, cast(unsigned)min_alignment); return res; } + + +void lb_set_linkage_from_entity_flags(lbModule *m, LLVMValueRef value, u64 flags) { + if (flags & EntityFlag_CustomLinkage_Internal) { + LLVMSetLinkage(value, LLVMInternalLinkage); + } else if (flags & EntityFlag_CustomLinkage_Strong) { + LLVMSetLinkage(value, LLVMExternalLinkage); + } else if (flags & EntityFlag_CustomLinkage_Weak) { + LLVMSetLinkage(value, LLVMExternalWeakLinkage); + } else if (flags & EntityFlag_CustomLinkage_LinkOnce) { + LLVMSetLinkage(value, LLVMLinkOnceAnyLinkage); + } +} diff --git a/src/llvm_backend_opt.cpp b/src/llvm_backend_opt.cpp index 75a377e5b..2648863e2 100644 --- a/src/llvm_backend_opt.cpp +++ b/src/llvm_backend_opt.cpp @@ -357,14 +357,14 @@ void lb_run_function_pass_manager(LLVMPassManagerRef fpm, lbProcedure *p) { } -void lb_run_remove_unused_function_pass(LLVMModuleRef mod) { +void lb_run_remove_unused_function_pass(lbModule *m) { isize removal_count = 0; isize pass_count = 0; isize const max_pass_count = 10; // Custom remove dead function pass for (; pass_count < max_pass_count; pass_count++) { bool was_dead_function = false; - for (LLVMValueRef func = LLVMGetFirstFunction(mod); + for (LLVMValueRef func = LLVMGetFirstFunction(m->mod); func != nullptr; /**/ ) { @@ -382,30 +382,20 @@ void lb_run_remove_unused_function_pass(LLVMModuleRef mod) { // Ignore for the time being continue; } - - if (name == "memset" || - name == "memmove" || - name == "memcpy") { + LLVMLinkage linkage = LLVMGetLinkage(curr_func); + if (linkage != LLVMInternalLinkage) { continue; } - if (is_arch_wasm()) { - if (name == "__ashlti3") { - LLVMSetLinkage(curr_func, LLVMExternalLinkage); + + Entity **found = map_get(&m->procedure_values, hash_pointer(curr_func)); + if (found && *found) { + Entity *e = *found; + bool is_required = (e->flags & EntityFlag_Require) == EntityFlag_Require; + if (is_required) { continue; } } - - LLVMLinkage linkage = LLVMGetLinkage(curr_func); - - switch (linkage) { - case LLVMExternalLinkage: - case LLVMDLLImportLinkage: - case LLVMDLLExportLinkage: - default: - continue; - case LLVMInternalLinkage: - break; - } + LLVMDeleteFunction(curr_func); was_dead_function = true; removal_count += 1; diff --git a/src/llvm_backend_proc.cpp b/src/llvm_backend_proc.cpp index ed9aa4b8b..ee5b94cec 100644 --- a/src/llvm_backend_proc.cpp +++ b/src/llvm_backend_proc.cpp @@ -203,6 +203,8 @@ lbProcedure *lb_create_procedure(lbModule *m, Entity *entity, bool ignore_body) } } } + lb_set_linkage_from_entity_flags(p->module, p->value, entity->flags); + if (p->is_foreign) { lb_set_wasm_import_attributes(p->value, entity, p->name); |