Browse Source

More improvements to minimize code gen size

gingerBill 3 weeks ago
parent
commit
9cf69576ab

+ 15 - 7
base/runtime/core_builtin.odin

@@ -166,11 +166,17 @@ remove_range :: proc(array: ^$D/[dynamic]$T, #any_int lo, hi: int, loc := #calle
 @builtin
 @builtin
 pop :: proc(array: ^$T/[dynamic]$E, loc := #caller_location) -> (res: E) #no_bounds_check {
 pop :: proc(array: ^$T/[dynamic]$E, loc := #caller_location) -> (res: E) #no_bounds_check {
 	assert(len(array) > 0, loc=loc)
 	assert(len(array) > 0, loc=loc)
-	res = array[len(array)-1]
-	(^Raw_Dynamic_Array)(array).len -= 1
+	_pop_type_erased(&res, (^Raw_Dynamic_Array)(array), size_of(E))
 	return res
 	return res
 }
 }
 
 
+_pop_type_erased :: proc(res: rawptr, array: ^Raw_Dynamic_Array, elem_size: int, loc := #caller_location) {
+	end := rawptr(uintptr(array.data) + uintptr(elem_size*(array.len-1)))
+	intrinsics.mem_copy_non_overlapping(res, end, elem_size)
+	array.len -= 1
+}
+
+
 
 
 // `pop_safe` trys to remove and return the end value of dynamic array `array` and reduces the length of `array` by 1.
 // `pop_safe` trys to remove and return the end value of dynamic array `array` and reduces the length of `array` by 1.
 // If the operation is not possible, it will return false.
 // If the operation is not possible, it will return false.
@@ -387,16 +393,18 @@ make_slice :: proc($T: typeid/[]$E, #any_int len: int, allocator := context.allo
 //
 //
 // Note: Prefer using the procedure group `make`.
 // Note: Prefer using the procedure group `make`.
 @(builtin, require_results)
 @(builtin, require_results)
-make_dynamic_array :: proc($T: typeid/[dynamic]$E, allocator := context.allocator, loc := #caller_location) -> (T, Allocator_Error) #optional_allocator_error {
-	return make_dynamic_array_len_cap(T, 0, 0, allocator, loc)
+make_dynamic_array :: proc($T: typeid/[dynamic]$E, allocator := context.allocator, loc := #caller_location) -> (array: T, err: Allocator_Error) #optional_allocator_error {
+	err = _make_dynamic_array_len_cap((^Raw_Dynamic_Array)(&array), size_of(E), align_of(E), 0, 0, allocator, loc)
+	return
 }
 }
 // `make_dynamic_array_len` allocates and initializes a dynamic array. Like `new`, the first argument is a type, not a value.
 // `make_dynamic_array_len` allocates and initializes a dynamic array. Like `new`, the first argument is a type, not a value.
 // Unlike `new`, `make`'s return value is the same as the type of its argument, not a pointer to it.
 // Unlike `new`, `make`'s return value is the same as the type of its argument, not a pointer to it.
 //
 //
 // Note: Prefer using the procedure group `make`.
 // Note: Prefer using the procedure group `make`.
 @(builtin, require_results)
 @(builtin, require_results)
-make_dynamic_array_len :: proc($T: typeid/[dynamic]$E, #any_int len: int, allocator := context.allocator, loc := #caller_location) -> (T, Allocator_Error) #optional_allocator_error {
-	return make_dynamic_array_len_cap(T, len, len, allocator, loc)
+make_dynamic_array_len :: proc($T: typeid/[dynamic]$E, #any_int len: int, allocator := context.allocator, loc := #caller_location) -> (array: T, err: Allocator_Error) #optional_allocator_error {
+	err = _make_dynamic_array_len_cap((^Raw_Dynamic_Array)(&array), size_of(E), align_of(E), len, len, allocator, loc)
+	return
 }
 }
 // `make_dynamic_array_len_cap` allocates and initializes a dynamic array. Like `new`, the first argument is a type, not a value.
 // `make_dynamic_array_len_cap` allocates and initializes a dynamic array. Like `new`, the first argument is a type, not a value.
 // Unlike `new`, `make`'s return value is the same as the type of its argument, not a pointer to it.
 // Unlike `new`, `make`'s return value is the same as the type of its argument, not a pointer to it.
@@ -501,7 +509,7 @@ clear_map :: proc "contextless" (m: ^$T/map[$K]$V) {
 // Note: Prefer the procedure group `reserve`
 // Note: Prefer the procedure group `reserve`
 @builtin
 @builtin
 reserve_map :: proc(m: ^$T/map[$K]$V, #any_int capacity: int, loc := #caller_location) -> Allocator_Error {
 reserve_map :: proc(m: ^$T/map[$K]$V, #any_int capacity: int, loc := #caller_location) -> Allocator_Error {
-	return __dynamic_map_reserve((^Raw_Map)(m), map_info(T), uint(capacity), loc) if m != nil else nil
+	return __dynamic_map_reserve((^Raw_Map)(m), map_info(T), uint(capacity), loc)
 }
 }
 
 
 // Shrinks the capacity of a map down to the current length.
 // Shrinks the capacity of a map down to the current length.

+ 3 - 0
base/runtime/dynamic_map_internal.odin

@@ -985,6 +985,9 @@ __dynamic_map_entry :: proc "odin" (#no_alias m: ^Raw_Map, #no_alias info: ^Map_
 // IMPORTANT: USED WITHIN THE COMPILER
 // IMPORTANT: USED WITHIN THE COMPILER
 @(private)
 @(private)
 __dynamic_map_reserve :: proc "odin" (#no_alias m: ^Raw_Map, #no_alias info: ^Map_Info, new_capacity: uint, loc := #caller_location) -> Allocator_Error {
 __dynamic_map_reserve :: proc "odin" (#no_alias m: ^Raw_Map, #no_alias info: ^Map_Info, new_capacity: uint, loc := #caller_location) -> Allocator_Error {
+	if m == nil {
+		return nil
+	}
 	return map_reserve_dynamic(m, info, uintptr(new_capacity), loc)
 	return map_reserve_dynamic(m, info, uintptr(new_capacity), loc)
 }
 }
 
 

+ 1 - 0
src/build_settings.cpp

@@ -555,6 +555,7 @@ struct BuildContext {
 	bool internal_no_inline;
 	bool internal_no_inline;
 	bool internal_by_value;
 	bool internal_by_value;
 	bool internal_weak_monomorphization;
 	bool internal_weak_monomorphization;
+	bool internal_ignore_llvm_verification;
 
 
 	bool   no_threaded_checker;
 	bool   no_threaded_checker;
 
 

+ 30 - 9
src/llvm_backend.cpp

@@ -8,7 +8,11 @@
 #endif
 #endif
 
 
 #ifndef LLVM_IGNORE_VERIFICATION
 #ifndef LLVM_IGNORE_VERIFICATION
-#define LLVM_IGNORE_VERIFICATION 0
+#define LLVM_IGNORE_VERIFICATION build_context.internal_ignore_llvm_verification
+#endif
+
+#ifndef LLVM_WEAK_MONOMORPHIZATION
+#define LLVM_WEAK_MONOMORPHIZATION build_context.internal_weak_monomorphization
 #endif
 #endif
 
 
 
 
@@ -620,6 +624,7 @@ gb_internal lbValue lb_hasher_proc_for_type(lbModule *m, Type *type) {
 
 
 #define LLVM_SET_VALUE_NAME(value, name) LLVMSetValueName2((value), (name), gb_count_of((name))-1);
 #define LLVM_SET_VALUE_NAME(value, name) LLVMSetValueName2((value), (name), gb_count_of((name))-1);
 
 
+
 gb_internal lbValue lb_map_get_proc_for_type(lbModule *m, Type *type) {
 gb_internal lbValue lb_map_get_proc_for_type(lbModule *m, Type *type) {
 	GB_ASSERT(!build_context.dynamic_map_calls);
 	GB_ASSERT(!build_context.dynamic_map_calls);
 	type = base_type(type);
 	type = base_type(type);
@@ -634,6 +639,9 @@ gb_internal lbValue lb_map_get_proc_for_type(lbModule *m, Type *type) {
 
 
 	lbProcedure *p = lb_create_dummy_procedure(m, proc_name, t_map_get_proc);
 	lbProcedure *p = lb_create_dummy_procedure(m, proc_name, t_map_get_proc);
 	string_map_set(&m->gen_procs, proc_name, p);
 	string_map_set(&m->gen_procs, proc_name, p);
+
+	p->internal_gen_type = type;
+
 	lb_begin_procedure_body(p);
 	lb_begin_procedure_body(p);
 	defer (lb_end_procedure_body(p));
 	defer (lb_end_procedure_body(p));
 
 
@@ -1891,6 +1899,10 @@ gb_internal void lb_verify_function(lbModule *m, lbProcedure *p, bool dump_ll=fa
 }
 }
 
 
 gb_internal WORKER_TASK_PROC(lb_llvm_module_verification_worker_proc) {
 gb_internal WORKER_TASK_PROC(lb_llvm_module_verification_worker_proc) {
+	if (LLVM_IGNORE_VERIFICATION) {
+		return 0;
+	}
+
 	char *llvm_error = nullptr;
 	char *llvm_error = nullptr;
 	defer (LLVMDisposeMessage(llvm_error));
 	defer (LLVMDisposeMessage(llvm_error));
 	lbModule *m = cast(lbModule *)data;
 	lbModule *m = cast(lbModule *)data;
@@ -2298,6 +2310,14 @@ gb_internal WORKER_TASK_PROC(lb_llvm_function_pass_per_module) {
 }
 }
 
 
 
 
+void lb_remove_unused_functions_and_globals(lbGenerator *gen) {
+	for (auto &entry : gen->modules) {
+		lbModule *m = entry.value;
+		lb_run_remove_unused_function_pass(m);
+		lb_run_remove_unused_globals_pass(m);
+	}
+}
+
 struct lbLLVMModulePassWorkerData {
 struct lbLLVMModulePassWorkerData {
 	lbModule *m;
 	lbModule *m;
 	LLVMTargetMachineRef target_machine;
 	LLVMTargetMachineRef target_machine;
@@ -2307,9 +2327,6 @@ struct lbLLVMModulePassWorkerData {
 gb_internal WORKER_TASK_PROC(lb_llvm_module_pass_worker_proc) {
 gb_internal WORKER_TASK_PROC(lb_llvm_module_pass_worker_proc) {
 	auto wd = cast(lbLLVMModulePassWorkerData *)data;
 	auto wd = cast(lbLLVMModulePassWorkerData *)data;
 
 
-	lb_run_remove_unused_function_pass(wd->m);
-	lb_run_remove_unused_globals_pass(wd->m);
-
 	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);
@@ -2386,6 +2403,10 @@ gb_internal WORKER_TASK_PROC(lb_llvm_module_pass_worker_proc) {
 	}
 	}
 #endif
 #endif
 
 
+	if (LLVM_IGNORE_VERIFICATION) {
+		return 0;
+	}
+
 	if (wd->do_threading) {
 	if (wd->do_threading) {
 		thread_pool_add_task(lb_llvm_module_verification_worker_proc, wd->m);
 		thread_pool_add_task(lb_llvm_module_verification_worker_proc, wd->m);
 	} else {
 	} else {
@@ -3464,12 +3485,14 @@ gb_internal bool lb_generate_code(lbGenerator *gen) {
 	TIME_SECTION("LLVM Function Pass");
 	TIME_SECTION("LLVM Function Pass");
 	lb_llvm_function_passes(gen, do_threading && !build_context.ODIN_DEBUG);
 	lb_llvm_function_passes(gen, do_threading && !build_context.ODIN_DEBUG);
 
 
+	TIME_SECTION("LLVM Remove Unused Functions and Globals");
+	lb_remove_unused_functions_and_globals(gen);
+
 	TIME_SECTION("LLVM Module Pass and Verification");
 	TIME_SECTION("LLVM Module Pass and Verification");
 	lb_llvm_module_passes_and_verification(gen, do_threading);
 	lb_llvm_module_passes_and_verification(gen, do_threading);
 
 
-	if (gen->module_verification_failed.load(std::memory_order_relaxed)) {
-		return false;
-	}
+	TIME_SECTION("LLVM Correct Entity Linkage");
+	lb_correct_entity_linkage(gen);
 
 
 	llvm_error = nullptr;
 	llvm_error = nullptr;
 	defer (LLVMDisposeMessage(llvm_error));
 	defer (LLVMDisposeMessage(llvm_error));
@@ -3497,8 +3520,6 @@ gb_internal bool lb_generate_code(lbGenerator *gen) {
 		}
 		}
 	}
 	}
 
 
-	TIME_SECTION("LLVM Correct Entity Linkage");
-	lb_correct_entity_linkage(gen);
 
 
 	////////////////////////////////////////////
 	////////////////////////////////////////////
 	for (auto const &entry: gen->modules) {
 	for (auto const &entry: gen->modules) {

+ 2 - 2
src/llvm_backend.hpp

@@ -241,8 +241,6 @@ struct lbGenerator : LinkerData {
 
 
 	isize used_module_count;
 	isize used_module_count;
 
 
-	std::atomic<bool> module_verification_failed;
-
 	lbProcedure *startup_runtime;
 	lbProcedure *startup_runtime;
 	lbProcedure *cleanup_runtime;
 	lbProcedure *cleanup_runtime;
 	lbProcedure *objc_names;
 	lbProcedure *objc_names;
@@ -409,6 +407,8 @@ struct lbProcedure {
 	void (*generate_body)(lbModule *m, lbProcedure *p);
 	void (*generate_body)(lbModule *m, lbProcedure *p);
 	Array<lbGlobalVariable> *global_variables;
 	Array<lbGlobalVariable> *global_variables;
 	lbProcedure *objc_names;
 	lbProcedure *objc_names;
+
+	Type *internal_gen_type; // map_set, map_get, etc.
 };
 };
 
 
 
 

+ 3 - 3
src/llvm_backend_general.cpp

@@ -154,7 +154,7 @@ gb_internal bool lb_init_generator(lbGenerator *gen, Checker *c) {
 			map_set(&gen->modules, cast(void *)pkg, m);
 			map_set(&gen->modules, cast(void *)pkg, m);
 			lb_init_module(m, c);
 			lb_init_module(m, c);
 
 
-			if (build_context.internal_weak_monomorphization) {
+			if (LLVM_WEAK_MONOMORPHIZATION) {
 				auto pm = gb_alloc_item(permanent_allocator(), lbModule);
 				auto pm = gb_alloc_item(permanent_allocator(), lbModule);
 				pm->pkg = pkg;
 				pm->pkg = pkg;
 				pm->gen = gen;
 				pm->gen = gen;
@@ -181,7 +181,7 @@ gb_internal bool lb_init_generator(lbGenerator *gen, Checker *c) {
 				lb_init_module(m, c);
 				lb_init_module(m, c);
 
 
 
 
-				if (build_context.internal_weak_monomorphization) {
+				if (LLVM_WEAK_MONOMORPHIZATION) {
 					auto pm  = gb_alloc_item(permanent_allocator(), lbModule);
 					auto pm  = gb_alloc_item(permanent_allocator(), lbModule);
 					pm->file = file;
 					pm->file = file;
 					pm->pkg  = pkg;
 					pm->pkg  = pkg;
@@ -469,7 +469,7 @@ gb_internal lbModule *lb_module_of_entity(lbGenerator *gen, Entity *e, lbModule
 	GB_ASSERT(curr_module != nullptr);
 	GB_ASSERT(curr_module != nullptr);
 	lbModule *m = lb_module_of_entity_internal(gen, e, curr_module);
 	lbModule *m = lb_module_of_entity_internal(gen, e, curr_module);
 
 
-	if (USE_SEPARATE_MODULES && build_context.internal_weak_monomorphization) {
+	if (USE_SEPARATE_MODULES) {
 		if (e->kind == Entity_Procedure && e->Procedure.generated_from_polymorphic) {
 		if (e->kind == Entity_Procedure && e->Procedure.generated_from_polymorphic) {
 			if (m->polymorphic_module) {
 			if (m->polymorphic_module) {
 				return m->polymorphic_module;
 				return m->polymorphic_module;

+ 6 - 0
src/main.cpp

@@ -404,6 +404,7 @@ enum BuildFlagKind {
 	BuildFlag_InternalNoInline,
 	BuildFlag_InternalNoInline,
 	BuildFlag_InternalByValue,
 	BuildFlag_InternalByValue,
 	BuildFlag_InternalWeakMonomorphization,
 	BuildFlag_InternalWeakMonomorphization,
+	BuildFlag_InternalLLVMVerification,
 
 
 	BuildFlag_Tilde,
 	BuildFlag_Tilde,
 
 
@@ -628,6 +629,7 @@ gb_internal bool parse_build_flags(Array<String> args) {
 	add_flag(&build_flags, BuildFlag_InternalNoInline,        str_lit("internal-no-inline"),        BuildFlagParam_None,    Command_all);
 	add_flag(&build_flags, BuildFlag_InternalNoInline,        str_lit("internal-no-inline"),        BuildFlagParam_None,    Command_all);
 	add_flag(&build_flags, BuildFlag_InternalByValue,         str_lit("internal-by-value"),         BuildFlagParam_None,    Command_all);
 	add_flag(&build_flags, BuildFlag_InternalByValue,         str_lit("internal-by-value"),         BuildFlagParam_None,    Command_all);
 	add_flag(&build_flags, BuildFlag_InternalWeakMonomorphization, str_lit("internal-weak-monomorphization"), BuildFlagParam_None, Command_all);
 	add_flag(&build_flags, BuildFlag_InternalWeakMonomorphization, str_lit("internal-weak-monomorphization"), BuildFlagParam_None, Command_all);
+	add_flag(&build_flags, BuildFlag_InternalLLVMVerification, str_lit("internal-ignore-llvm-verification"), BuildFlagParam_None, Command_all);
 
 
 #if ALLOW_TILDE
 #if ALLOW_TILDE
 	add_flag(&build_flags, BuildFlag_Tilde,                   str_lit("tilde"),                     BuildFlagParam_None,    Command__does_build);
 	add_flag(&build_flags, BuildFlag_Tilde,                   str_lit("tilde"),                     BuildFlagParam_None,    Command__does_build);
@@ -1589,6 +1591,10 @@ gb_internal bool parse_build_flags(Array<String> args) {
 						case BuildFlag_InternalWeakMonomorphization:
 						case BuildFlag_InternalWeakMonomorphization:
 							build_context.internal_weak_monomorphization = true;
 							build_context.internal_weak_monomorphization = true;
 							break;
 							break;
+						case BuildFlag_InternalLLVMVerification:
+							build_context.internal_ignore_llvm_verification = true;
+							break;
+
 
 
 						case BuildFlag_Tilde:
 						case BuildFlag_Tilde:
 							build_context.tilde_backend = true;
 							build_context.tilde_backend = true;