aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/build_settings.cpp6
-rw-r--r--src/check_decl.cpp8
-rw-r--r--src/entity.cpp3
-rw-r--r--src/llvm_backend.cpp16
-rw-r--r--src/llvm_backend.hpp21
-rw-r--r--src/llvm_backend_opt.cpp49
-rw-r--r--src/llvm_backend_proc.cpp13
-rw-r--r--src/main.cpp19
8 files changed, 112 insertions, 23 deletions
diff --git a/src/build_settings.cpp b/src/build_settings.cpp
index a906f6712..e34330ea8 100644
--- a/src/build_settings.cpp
+++ b/src/build_settings.cpp
@@ -895,7 +895,11 @@ void init_build_context(TargetMetrics *cross_target) {
}
} else if (is_arch_wasm()) {
- bc->link_flags = str_lit("--no-entry --export-table --export-all --allow-undefined ");
+ if (bc->metrics.arch == TargetArch_wasm32) {
+ bc->link_flags = str_lit("--no-entry --export-table --export-all --allow-undefined ");
+ } else {
+ bc->link_flags = str_lit("--no-entry --export-table --export-all --allow-undefined -mwasm64 ");
+ }
} else {
gb_printf_err("Compiler Error: Unsupported architecture\n");;
gb_exit(1);
diff --git a/src/check_decl.cpp b/src/check_decl.cpp
index 0591eca4d..c2d23e70c 100644
--- a/src/check_decl.cpp
+++ b/src/check_decl.cpp
@@ -899,6 +899,10 @@ void check_proc_decl(CheckerContext *ctx, Entity *e, DeclInfo *d) {
mutex_unlock(&ctx->info->foreign_mutex);
}
}
+
+ if (e->Procedure.link_name.len > 0 ) {
+ e->flags |= EntityFlag_CustomLinkName;
+ }
}
void check_global_variable_decl(CheckerContext *ctx, Entity *&e, Ast *type_expr, Ast *init_expr) {
@@ -990,6 +994,10 @@ void check_global_variable_decl(CheckerContext *ctx, Entity *&e, Ast *type_expr,
string_map_set(fp, key, e);
}
}
+
+ if (e->Variable.link_name.len > 0) {
+ e->flags |= EntityFlag_CustomLinkName;
+ }
if (init_expr == nullptr) {
if (type_expr == nullptr) {
diff --git a/src/entity.cpp b/src/entity.cpp
index 86fefcf89..d95c74f22 100644
--- a/src/entity.cpp
+++ b/src/entity.cpp
@@ -74,9 +74,10 @@ enum EntityFlag : u64 {
EntityFlag_Test = 1ull<<30,
EntityFlag_Init = 1ull<<31,
+
+ EntityFlag_CustomLinkName = 1ull<<40,
EntityFlag_Overridden = 1ull<<63,
-
};
enum EntityState : u32 {
diff --git a/src/llvm_backend.cpp b/src/llvm_backend.cpp
index 7a70ee478..892f615df 100644
--- a/src/llvm_backend.cpp
+++ b/src/llvm_backend.cpp
@@ -1064,14 +1064,10 @@ struct lbLLVMModulePassWorkerData {
};
WORKER_TASK_PROC(lb_llvm_module_pass_worker_proc) {
- GB_ASSERT(MULTITHREAD_OBJECT_GENERATION);
-
auto wd = cast(lbLLVMModulePassWorkerData *)data;
-
LLVMPassManagerRef module_pass_manager = LLVMCreatePassManager();
lb_populate_module_pass_manager(wd->target_machine, module_pass_manager, build_context.optimization_level);
LLVMRunPassManager(module_pass_manager, wd->m->mod);
-
return 0;
}
@@ -1661,6 +1657,8 @@ 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);
auto wd = gb_alloc_item(permanent_allocator(), lbLLVMModulePassWorkerData);
wd->m = m;
@@ -1738,8 +1736,16 @@ void lb_generate_code(lbGenerator *gen) {
}
TIME_SECTION("LLVM Object Generation");
+
+ isize non_empty_module_count = 0;
+ for_array(j, gen->modules.entries) {
+ lbModule *m = gen->modules.entries[j].value;
+ if (!lb_is_module_empty(m)) {
+ non_empty_module_count += 1;
+ }
+ }
- if (do_threading) {
+ if (do_threading && non_empty_module_count > 1) {
for_array(j, gen->modules.entries) {
lbModule *m = gen->modules.entries[j].value;
if (lb_is_module_empty(m)) {
diff --git a/src/llvm_backend.hpp b/src/llvm_backend.hpp
index 9aa9920f2..5fc5dfebf 100644
--- a/src/llvm_backend.hpp
+++ b/src/llvm_backend.hpp
@@ -585,3 +585,24 @@ enum : LLVMAttributeIndex {
LLVMAttributeIndex_FunctionIndex = ~0u,
LLVMAttributeIndex_FirstArgIndex = 1,
};
+
+
+char const *llvm_linkage_strings[] = {
+ "external linkage",
+ "available externally linkage",
+ "link once any linkage",
+ "link once odr linkage",
+ "link once odr auto hide linkage",
+ "weak any linkage",
+ "weak odr linkage",
+ "appending linkage",
+ "internal linkage",
+ "private linkage",
+ "dllimport linkage",
+ "dllexport linkage",
+ "external weak linkage",
+ "ghost linkage",
+ "common linkage",
+ "linker private linkage",
+ "linker private weak linkage"
+}; \ No newline at end of file
diff --git a/src/llvm_backend_opt.cpp b/src/llvm_backend_opt.cpp
index d5ea90aea..25e290d70 100644
--- a/src/llvm_backend_opt.cpp
+++ b/src/llvm_backend_opt.cpp
@@ -355,3 +355,52 @@ void lb_run_function_pass_manager(LLVMPassManagerRef fpm, lbProcedure *p) {
// are not removed
lb_run_remove_dead_instruction_pass(p);
}
+
+
+void lb_run_remove_unused_function_pass(LLVMModuleRef mod) {
+ 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);
+ func != nullptr;
+ /**/
+ ) {
+ LLVMValueRef curr_func = func;
+ func = LLVMGetNextFunction(func);
+
+ LLVMUseRef first_use = LLVMGetFirstUse(curr_func);
+ if (first_use != nullptr) {
+ continue;
+ }
+ String name = {};
+ name.text = cast(u8 *)LLVMGetValueName2(curr_func, cast(size_t *)&name.len);
+
+ if (LLVMIsDeclaration(curr_func)) {
+ // Ignore for the time being
+ 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;
+ }
+ if (!was_dead_function) {
+ break;
+ }
+ }
+}
diff --git a/src/llvm_backend_proc.cpp b/src/llvm_backend_proc.cpp
index 15689da36..29f7b6655 100644
--- a/src/llvm_backend_proc.cpp
+++ b/src/llvm_backend_proc.cpp
@@ -195,13 +195,19 @@ lbProcedure *lb_create_procedure(lbModule *m, Entity *entity, bool ignore_body)
// then it is very likely it is required by LLVM and thus cannot have internal linkage
if (entity->pkg != nullptr && entity->pkg->kind == Package_Runtime && p->body != nullptr) {
GB_ASSERT(entity->kind == Entity_Procedure);
- if (entity->Procedure.link_name != "") {
- LLVMSetLinkage(p->value, LLVMExternalLinkage);
+ String link_name = entity->Procedure.link_name;
+ if (entity->flags & EntityFlag_CustomLinkName &&
+ link_name != "") {
+ if (string_starts_with(link_name, str_lit("__"))) {
+ LLVMSetLinkage(p->value, LLVMExternalLinkage);
+ } else {
+ LLVMSetLinkage(p->value, LLVMInternalLinkage);
+ }
}
}
}
}
-
+
if (p->is_foreign) {
if (is_arch_wasm()) {
char const *import_name = alloc_cstring(permanent_allocator(), p->name);
@@ -217,6 +223,7 @@ lbProcedure *lb_create_procedure(lbModule *m, Entity *entity, bool ignore_body)
LLVMAddTargetDependentFunctionAttr(p->value, "wasm-import-module", module_name);
}
}
+
// NOTE(bill): offset==0 is the return value
isize offset = 1;
diff --git a/src/main.cpp b/src/main.cpp
index fad749e34..7338ad45d 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -135,19 +135,12 @@ i32 linker_stage(lbGenerator *gen) {
if (is_arch_wasm()) {
timings_start_section(timings, str_lit("wasm-ld"));
-
- if (build_context.metrics.arch == TargetArch_wasm32) {
- result = system_exec_command_line_app("wasm-ld",
- "\"%.*s\\bin\\wasm-ld\" \"%.*s.wasm.o\" -o \"%.*s.wasm\" %.*s %.*s",
- LIT(build_context.ODIN_ROOT),
- LIT(output_base), LIT(output_base), LIT(build_context.link_flags), LIT(build_context.extra_linker_flags));
- } else {
- GB_ASSERT(build_context.metrics.arch == TargetArch_wasm64);
- result = system_exec_command_line_app("wasm-ld",
- "\"%.*s\\bin\\wasm-ld\" \"%.*s.wasm.o\" -o \"%.*s.wasm\" %.*s %.*s",
- LIT(build_context.ODIN_ROOT),
- LIT(output_base), LIT(output_base), LIT(build_context.link_flags), LIT(build_context.extra_linker_flags));
- }
+
+ GB_ASSERT(build_context.metrics.arch == TargetArch_wasm64);
+ result = system_exec_command_line_app("wasm-ld",
+ "\"%.*s\\bin\\wasm-ld\" \"%.*s.wasm.o\" -o \"%.*s.wasm\" %.*s %.*s",
+ LIT(build_context.ODIN_ROOT),
+ LIT(output_base), LIT(output_base), LIT(build_context.link_flags), LIT(build_context.extra_linker_flags));
return result;
}