aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorgingerBill <bill@gingerbill.org>2021-11-04 12:40:50 +0000
committergingerBill <bill@gingerbill.org>2021-11-04 12:40:50 +0000
commit6ded538546cca4f1e50a011a64932f7f3c784cc2 (patch)
tree03ac73c9042cc45ab20da51a93de3f9bf6f8de0f /src
parent3fa7dabaa87e99386e469bd5e4badab23f89aaef (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.cpp18
-rw-r--r--src/checker.cpp55
-rw-r--r--src/checker.hpp1
-rw-r--r--src/entity.cpp6
-rw-r--r--src/llvm_backend.cpp4
-rw-r--r--src/llvm_backend.hpp4
-rw-r--r--src/llvm_backend_general.cpp13
-rw-r--r--src/llvm_backend_opt.cpp32
-rw-r--r--src/llvm_backend_proc.cpp2
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);