Browse Source

Compile `wasm64`; Add `lb_run_remove_unused_function_pass`

gingerBill 3 years ago
parent
commit
8ef6f9dd7b

+ 11 - 14
core/runtime/default_temporary_allocator.odin

@@ -1,23 +1,12 @@
 package runtime
 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_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" {
 when ODIN_OS == "freestanding" {
+	Default_Temp_Allocator :: struct {
+	}
+	
 	default_temp_allocator_init :: proc(s: ^Default_Temp_Allocator, size: int, backup_allocator := context.allocator) {
 	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		
 		return nil, nil		
 	}
 	}
 } else {
 } 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) {
 	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.data = make_aligned([]byte, size, 2*align_of(rawptr), backup_allocator)
 		s.curr_offset = 0
 		s.curr_offset = 0

+ 5 - 0
core/runtime/internal.odin

@@ -2,6 +2,11 @@ package runtime
 
 
 import "core:intrinsics"
 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 {
 bswap_16 :: proc "contextless" (x: u16) -> u16 {
 	return x>>8 | x<<8
 	return x>>8 | x<<8
 }
 }

+ 5 - 1
src/build_settings.cpp

@@ -895,7 +895,11 @@ void init_build_context(TargetMetrics *cross_target) {
 		}
 		}
 
 
 	} else if (is_arch_wasm()) {
 	} 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 {
 	} else {
 		gb_printf_err("Compiler Error: Unsupported architecture\n");;
 		gb_printf_err("Compiler Error: Unsupported architecture\n");;
 		gb_exit(1);
 		gb_exit(1);

+ 8 - 0
src/check_decl.cpp

@@ -899,6 +899,10 @@ void check_proc_decl(CheckerContext *ctx, Entity *e, DeclInfo *d) {
 			mutex_unlock(&ctx->info->foreign_mutex);
 			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) {
 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);
 			string_map_set(fp, key, e);
 		}
 		}
 	}
 	}
+	
+	if (e->Variable.link_name.len > 0) {
+		e->flags |= EntityFlag_CustomLinkName;
+	}
 
 
 	if (init_expr == nullptr) {
 	if (init_expr == nullptr) {
 		if (type_expr == nullptr) {
 		if (type_expr == nullptr) {

+ 2 - 1
src/entity.cpp

@@ -74,9 +74,10 @@ enum EntityFlag : u64 {
 
 
 	EntityFlag_Test          = 1ull<<30,
 	EntityFlag_Test          = 1ull<<30,
 	EntityFlag_Init          = 1ull<<31,
 	EntityFlag_Init          = 1ull<<31,
+	
+	EntityFlag_CustomLinkName = 1ull<<40,
 
 
 	EntityFlag_Overridden    = 1ull<<63,
 	EntityFlag_Overridden    = 1ull<<63,
-
 };
 };
 
 
 enum EntityState : u32 {
 enum EntityState : u32 {

+ 11 - 5
src/llvm_backend.cpp

@@ -1064,14 +1064,10 @@ struct lbLLVMModulePassWorkerData {
 };
 };
 
 
 WORKER_TASK_PROC(lb_llvm_module_pass_worker_proc) {
 WORKER_TASK_PROC(lb_llvm_module_pass_worker_proc) {
-	GB_ASSERT(MULTITHREAD_OBJECT_GENERATION);
-
 	auto wd = cast(lbLLVMModulePassWorkerData *)data;
 	auto wd = cast(lbLLVMModulePassWorkerData *)data;
-
 	LLVMPassManagerRef module_pass_manager = LLVMCreatePassManager();
 	LLVMPassManagerRef module_pass_manager = LLVMCreatePassManager();
 	lb_populate_module_pass_manager(wd->target_machine, module_pass_manager, build_context.optimization_level);
 	lb_populate_module_pass_manager(wd->target_machine, module_pass_manager, build_context.optimization_level);
 	LLVMRunPassManager(module_pass_manager, wd->m->mod);
 	LLVMRunPassManager(module_pass_manager, wd->m->mod);
-
 	return 0;
 	return 0;
 }
 }
 
 
@@ -1661,6 +1657,8 @@ void lb_generate_code(lbGenerator *gen) {
 
 
 	for_array(i, gen->modules.entries) {
 	for_array(i, gen->modules.entries) {
 		lbModule *m = gen->modules.entries[i].value;
 		lbModule *m = gen->modules.entries[i].value;
+		
+		lb_run_remove_unused_function_pass(m->mod);
 
 
 		auto wd = gb_alloc_item(permanent_allocator(), lbLLVMModulePassWorkerData);
 		auto wd = gb_alloc_item(permanent_allocator(), lbLLVMModulePassWorkerData);
 		wd->m = m;
 		wd->m = m;
@@ -1738,8 +1736,16 @@ void lb_generate_code(lbGenerator *gen) {
 	}
 	}
 
 
 	TIME_SECTION("LLVM Object Generation");
 	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) {
 		for_array(j, gen->modules.entries) {
 			lbModule *m = gen->modules.entries[j].value;
 			lbModule *m = gen->modules.entries[j].value;
 			if (lb_is_module_empty(m)) {
 			if (lb_is_module_empty(m)) {

+ 21 - 0
src/llvm_backend.hpp

@@ -585,3 +585,24 @@ enum : LLVMAttributeIndex {
 	LLVMAttributeIndex_FunctionIndex = ~0u,
 	LLVMAttributeIndex_FunctionIndex = ~0u,
 	LLVMAttributeIndex_FirstArgIndex = 1,
 	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"
+};

+ 49 - 0
src/llvm_backend_opt.cpp

@@ -355,3 +355,52 @@ void lb_run_function_pass_manager(LLVMPassManagerRef fpm, lbProcedure *p) {
 	// are not removed
 	// are not removed
 	lb_run_remove_dead_instruction_pass(p);
 	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;
+		}
+	}
+}

+ 10 - 3
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
 			// 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) {
 			if (entity->pkg != nullptr && entity->pkg->kind == Package_Runtime && p->body != nullptr) {
 				GB_ASSERT(entity->kind == Entity_Procedure);
 				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 (p->is_foreign) {
 		if (is_arch_wasm()) {
 		if (is_arch_wasm()) {
 			char const *import_name = alloc_cstring(permanent_allocator(), p->name);
 			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);
 			LLVMAddTargetDependentFunctionAttr(p->value, "wasm-import-module", module_name);
 		}
 		}
 	}
 	}
+	
 
 
 	// NOTE(bill): offset==0 is the return value
 	// NOTE(bill): offset==0 is the return value
 	isize offset = 1;
 	isize offset = 1;

+ 6 - 13
src/main.cpp

@@ -135,19 +135,12 @@ i32 linker_stage(lbGenerator *gen) {
 
 
 	if (is_arch_wasm()) {
 	if (is_arch_wasm()) {
 		timings_start_section(timings, str_lit("wasm-ld"));
 		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;
 		return result;
 	}
 	}