diff options
| author | gingerBill <gingerBill@users.noreply.github.com> | 2025-09-18 20:58:24 +0100 |
|---|---|---|
| committer | gingerBill <gingerBill@users.noreply.github.com> | 2025-09-18 20:58:24 +0100 |
| commit | 9cf69576ab8cb220af5802a04a0aa53dc92046a5 (patch) | |
| tree | dc605f939116c61c23af6f0912fbfeae220ccf96 | |
| parent | 4b0a07ba27abf76aa35c364a4c7b71745a1969d7 (diff) | |
More improvements to minimize code gen size
| -rw-r--r-- | base/runtime/core_builtin.odin | 22 | ||||
| -rw-r--r-- | base/runtime/dynamic_map_internal.odin | 3 | ||||
| -rw-r--r-- | src/build_settings.cpp | 1 | ||||
| -rw-r--r-- | src/llvm_backend.cpp | 39 | ||||
| -rw-r--r-- | src/llvm_backend.hpp | 4 | ||||
| -rw-r--r-- | src/llvm_backend_general.cpp | 6 | ||||
| -rw-r--r-- | src/main.cpp | 6 |
7 files changed, 60 insertions, 21 deletions
diff --git a/base/runtime/core_builtin.odin b/base/runtime/core_builtin.odin index 497c4b147..903ea7ed7 100644 --- a/base/runtime/core_builtin.odin +++ b/base/runtime/core_builtin.odin @@ -166,11 +166,17 @@ remove_range :: proc(array: ^$D/[dynamic]$T, #any_int lo, hi: int, loc := #calle @builtin pop :: proc(array: ^$T/[dynamic]$E, loc := #caller_location) -> (res: E) #no_bounds_check { 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 } +_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. // 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`. @(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. // 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`. @(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. // 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` @builtin 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. diff --git a/base/runtime/dynamic_map_internal.odin b/base/runtime/dynamic_map_internal.odin index 7b65a2fa0..e288d1f53 100644 --- a/base/runtime/dynamic_map_internal.odin +++ b/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 @(private) __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) } diff --git a/src/build_settings.cpp b/src/build_settings.cpp index 867c80ac1..54f11a42d 100644 --- a/src/build_settings.cpp +++ b/src/build_settings.cpp @@ -555,6 +555,7 @@ struct BuildContext { bool internal_no_inline; bool internal_by_value; bool internal_weak_monomorphization; + bool internal_ignore_llvm_verification; bool no_threaded_checker; diff --git a/src/llvm_backend.cpp b/src/llvm_backend.cpp index 46c319a90..5d2accd90 100644 --- a/src/llvm_backend.cpp +++ b/src/llvm_backend.cpp @@ -8,7 +8,11 @@ #endif #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 @@ -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); + gb_internal lbValue lb_map_get_proc_for_type(lbModule *m, Type *type) { GB_ASSERT(!build_context.dynamic_map_calls); 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); string_map_set(&m->gen_procs, proc_name, p); + + p->internal_gen_type = type; + lb_begin_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) { + if (LLVM_IGNORE_VERIFICATION) { + return 0; + } + char *llvm_error = nullptr; defer (LLVMDisposeMessage(llvm_error)); 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 { lbModule *m; LLVMTargetMachineRef target_machine; @@ -2307,9 +2327,6 @@ struct lbLLVMModulePassWorkerData { gb_internal WORKER_TASK_PROC(lb_llvm_module_pass_worker_proc) { 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(); lb_populate_module_pass_manager(wd->target_machine, module_pass_manager, build_context.optimization_level); LLVMRunPassManager(module_pass_manager, wd->m->mod); @@ -2386,6 +2403,10 @@ gb_internal WORKER_TASK_PROC(lb_llvm_module_pass_worker_proc) { } #endif + if (LLVM_IGNORE_VERIFICATION) { + return 0; + } + if (wd->do_threading) { thread_pool_add_task(lb_llvm_module_verification_worker_proc, wd->m); } else { @@ -3464,12 +3485,14 @@ gb_internal bool lb_generate_code(lbGenerator *gen) { TIME_SECTION("LLVM Function Pass"); 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"); 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; 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) { diff --git a/src/llvm_backend.hpp b/src/llvm_backend.hpp index 5d6f56433..698e7657f 100644 --- a/src/llvm_backend.hpp +++ b/src/llvm_backend.hpp @@ -241,8 +241,6 @@ struct lbGenerator : LinkerData { isize used_module_count; - std::atomic<bool> module_verification_failed; - lbProcedure *startup_runtime; lbProcedure *cleanup_runtime; lbProcedure *objc_names; @@ -409,6 +407,8 @@ struct lbProcedure { void (*generate_body)(lbModule *m, lbProcedure *p); Array<lbGlobalVariable> *global_variables; lbProcedure *objc_names; + + Type *internal_gen_type; // map_set, map_get, etc. }; diff --git a/src/llvm_backend_general.cpp b/src/llvm_backend_general.cpp index 3ac405e0b..fb9fa4cea 100644 --- a/src/llvm_backend_general.cpp +++ b/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); lb_init_module(m, c); - if (build_context.internal_weak_monomorphization) { + if (LLVM_WEAK_MONOMORPHIZATION) { auto pm = gb_alloc_item(permanent_allocator(), lbModule); pm->pkg = pkg; pm->gen = gen; @@ -181,7 +181,7 @@ gb_internal bool lb_init_generator(lbGenerator *gen, Checker *c) { lb_init_module(m, c); - if (build_context.internal_weak_monomorphization) { + if (LLVM_WEAK_MONOMORPHIZATION) { auto pm = gb_alloc_item(permanent_allocator(), lbModule); pm->file = file; pm->pkg = pkg; @@ -469,7 +469,7 @@ gb_internal lbModule *lb_module_of_entity(lbGenerator *gen, Entity *e, lbModule GB_ASSERT(curr_module != nullptr); 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 (m->polymorphic_module) { return m->polymorphic_module; diff --git a/src/main.cpp b/src/main.cpp index 130c3f31d..bbaf6f23f 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -404,6 +404,7 @@ enum BuildFlagKind { BuildFlag_InternalNoInline, BuildFlag_InternalByValue, BuildFlag_InternalWeakMonomorphization, + BuildFlag_InternalLLVMVerification, 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_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_InternalLLVMVerification, str_lit("internal-ignore-llvm-verification"), BuildFlagParam_None, Command_all); #if ALLOW_TILDE 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: build_context.internal_weak_monomorphization = true; break; + case BuildFlag_InternalLLVMVerification: + build_context.internal_ignore_llvm_verification = true; + break; + case BuildFlag_Tilde: build_context.tilde_backend = true; |