aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorgingerBill <bill@gingerbill.org>2021-10-31 00:11:38 +0100
committergingerBill <bill@gingerbill.org>2021-10-31 00:11:38 +0100
commit8ef6f9dd7bbb1611dd7166c4e14034e53df4a8b6 (patch)
treed13e60bb55f8d8167ebd906ee66485a0097c208b
parent5bc8a491a7768da0019b7b17da637e681f2ace90 (diff)
Compile `wasm64`; Add `lb_run_remove_unused_function_pass`
-rw-r--r--core/runtime/default_temporary_allocator.odin25
-rw-r--r--core/runtime/internal.odin5
-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
10 files changed, 128 insertions, 37 deletions
diff --git a/core/runtime/default_temporary_allocator.odin b/core/runtime/default_temporary_allocator.odin
index b3602469d..afe3ee922 100644
--- a/core/runtime/default_temporary_allocator.odin
+++ b/core/runtime/default_temporary_allocator.odin
@@ -1,23 +1,12 @@
package runtime
-@(private)
-byte_slice :: #force_inline proc "contextless" (data: rawptr, len: int) -> []byte {
- return transmute([]u8)Raw_Slice{data=data, len=max(len, 0)}
-}
-
-
DEFAULT_TEMP_ALLOCATOR_BACKING_SIZE: int : #config(DEFAULT_TEMP_ALLOCATOR_BACKING_SIZE, 1<<22)
-Default_Temp_Allocator :: struct {
- data: []byte,
- curr_offset: int,
- prev_allocation: rawptr,
- backup_allocator: Allocator,
- leaked_allocations: [dynamic][]byte,
-}
-
when ODIN_OS == "freestanding" {
+ Default_Temp_Allocator :: struct {
+ }
+
default_temp_allocator_init :: proc(s: ^Default_Temp_Allocator, size: int, backup_allocator := context.allocator) {
}
@@ -30,6 +19,14 @@ when ODIN_OS == "freestanding" {
return nil, nil
}
} else {
+ Default_Temp_Allocator :: struct {
+ data: []byte,
+ curr_offset: int,
+ prev_allocation: rawptr,
+ backup_allocator: Allocator,
+ leaked_allocations: [dynamic][]byte,
+ }
+
default_temp_allocator_init :: proc(s: ^Default_Temp_Allocator, size: int, backup_allocator := context.allocator) {
s.data = make_aligned([]byte, size, 2*align_of(rawptr), backup_allocator)
s.curr_offset = 0
diff --git a/core/runtime/internal.odin b/core/runtime/internal.odin
index 4347f28c0..0a6d07467 100644
--- a/core/runtime/internal.odin
+++ b/core/runtime/internal.odin
@@ -2,6 +2,11 @@ package runtime
import "core:intrinsics"
+@(private)
+byte_slice :: #force_inline proc "contextless" (data: rawptr, len: int) -> []byte #no_bounds_check {
+ return ([^]byte)(data)[:max(len, 0)]
+}
+
bswap_16 :: proc "contextless" (x: u16) -> u16 {
return x>>8 | x<<8
}
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;
}