diff --git a/src/tilde.cpp b/src/tilde.cpp index 4fd891b17..8bd7e0b43 100644 --- a/src/tilde.cpp +++ b/src/tilde.cpp @@ -7,6 +7,13 @@ gb_internal TB_Arena *cg_arena(void) { return global_tb_arenas[current_thread_index()]; } +gb_internal void cg_global_arena_init(void) { + global_tb_arenas = slice_make(permanent_allocator(), global_thread_pool.threads.count); + for_array(i, global_tb_arenas) { + global_tb_arenas[i] = tb_default_arena(); + } +} + // returns TB_TYPE_VOID if not trivially possible gb_internal TB_DataType cg_data_type(Type *t) { GB_ASSERT(t != nullptr); @@ -535,7 +542,6 @@ gb_internal cgModule *cg_module_create(Checker *c) { tb_module_set_tls_index(m->mod, 10, "_tls_index"); map_init(&m->values); - array_init(&m->procedures_to_generate, heap_allocator()); map_init(&m->file_id_map); @@ -543,6 +549,8 @@ gb_internal cgModule *cg_module_create(Checker *c) { map_init(&m->proc_debug_type_map); map_init(&m->proc_proto_map); + array_init(&m->single_threaded_procedure_queue, heap_allocator()); + for_array(id, global_files) { if (AstFile *f = global_files[id]) { @@ -556,12 +564,13 @@ gb_internal cgModule *cg_module_create(Checker *c) { gb_internal void cg_module_destroy(cgModule *m) { map_destroy(&m->values); - array_free(&m->procedures_to_generate); map_destroy(&m->file_id_map); map_destroy(&m->debug_type_map); map_destroy(&m->proc_debug_type_map); map_destroy(&m->proc_proto_map); + array_free(&m->single_threaded_procedure_queue); + tb_module_destroy(m->mod); } @@ -772,6 +781,21 @@ gb_internal String cg_filepath_obj_for_module(cgModule *m) { } +gb_internal WORKER_TASK_PROC(cg_procedure_generate_worker_proc) { + cgProcedure *p = cast(cgProcedure *)data; + cg_procedure_generate(p); + return 0; +} + +gb_internal void cg_add_procedure_to_queue(cgProcedure *p) { + cgModule *m = p->module; + if (m->do_threading) { + thread_pool_add_task(cg_procedure_generate_worker_proc, p); + } else { + array_add(&m->single_threaded_procedure_queue, p); + } +} + gb_internal bool cg_generate_code(Checker *c, LinkerData *linker_data) { TIME_SECTION("Tilde Module Initializtion"); @@ -779,14 +803,13 @@ gb_internal bool cg_generate_code(Checker *c, LinkerData *linker_data) { linker_data_init(linker_data, info, c->parser->init_fullpath); - global_tb_arenas = slice_make(permanent_allocator(), global_thread_pool.threads.count); - for_array(i, global_tb_arenas) { - global_tb_arenas[i] = tb_default_arena(); - } + cg_global_arena_init(); cgModule *m = cg_module_create(c); defer (cg_module_destroy(m)); + m->do_threading = true; + TIME_SECTION("Tilde Global Variables"); bool already_has_entry_point = cg_global_variables_create(m); @@ -798,6 +821,7 @@ gb_internal bool cg_generate_code(Checker *c, LinkerData *linker_data) { p->is_startup = true; cg_procedure_begin(p); + tb_inst_ret(p->func, 0, nullptr); cg_procedure_end(p); } @@ -807,14 +831,19 @@ gb_internal bool cg_generate_code(Checker *c, LinkerData *linker_data) { p->is_startup = true; cg_procedure_begin(p); + tb_inst_ret(p->func, 0, nullptr); cg_procedure_end(p); } auto *min_dep_set = &info->minimum_dependency_set; + Array procedures_to_generate = {}; + array_init(&procedures_to_generate, heap_allocator()); + defer (array_free(&procedures_to_generate)); + for (Entity *e : info->entities) { - String name = e->token.string; - Scope * scope = e->scope; + String name = e->token.string; + Scope *scope = e->scope; if ((scope->flags & ScopeFlag_File) == 0) { continue; @@ -832,15 +861,24 @@ gb_internal bool cg_generate_code(Checker *c, LinkerData *linker_data) { continue; } if (cgProcedure *p = cg_procedure_create(m, e)) { - array_add(&m->procedures_to_generate, p); + array_add(&procedures_to_generate, p); } } - - for (isize i = 0; i < m->procedures_to_generate.count; i++) { - cg_procedure_generate(m->procedures_to_generate[i]); + for (cgProcedure *p : procedures_to_generate) { + cg_add_procedure_to_queue(p); } + if (!m->do_threading) { + for (isize i = 0; i < m->single_threaded_procedure_queue.count; i++) { + cgProcedure *p = m->single_threaded_procedure_queue[i]; + cg_procedure_generate(p); + } + } + + thread_pool_wait(); + + TB_DebugFormat debug_format = TB_DEBUGFMT_NONE; if (build_context.ODIN_DEBUG || true) { switch (build_context.metrics.os) { diff --git a/src/tilde.hpp b/src/tilde.hpp index 44da86c35..ce87f2dfe 100644 --- a/src/tilde.hpp +++ b/src/tilde.hpp @@ -210,13 +210,14 @@ struct cgModule { CheckerInfo *info; LinkerData * linker_data; - RwMutex values_mutex; - PtrMap values; - StringMap members; + bool do_threading; + Array single_threaded_procedure_queue; - StringMap procedures; + RwMutex values_mutex; + PtrMap values; + StringMap members; + StringMap procedures; PtrMap procedure_values; - Array procedures_to_generate; RecursiveMutex debug_type_mutex; PtrMap debug_type_map; @@ -225,6 +226,7 @@ struct cgModule { RecursiveMutex proc_proto_mutex; PtrMap proc_proto_map; + // NOTE(bill): no need to protect this with a mutex PtrMap file_id_map; // Key: AstFile.id (i32 cast to uintptr) std::atomic nested_type_name_guid; @@ -252,6 +254,8 @@ gb_global isize cg_global_type_info_member_tags_index = 0; gb_internal TB_Arena *cg_arena(void); +gb_internal void cg_add_procedure_to_queue(cgProcedure *p); + gb_internal cgValue cg_value(TB_Global * g, Type *type); gb_internal cgValue cg_value(TB_External *e, Type *type); gb_internal cgValue cg_value(TB_Function *f, Type *type); diff --git a/src/tilde/tb.lib b/src/tilde/tb.lib index f5464cab0..a60475d1c 100644 Binary files a/src/tilde/tb.lib and b/src/tilde/tb.lib differ diff --git a/src/tilde_proc.cpp b/src/tilde_proc.cpp index fec77733d..fe9c6c766 100644 --- a/src/tilde_proc.cpp +++ b/src/tilde_proc.cpp @@ -35,7 +35,9 @@ gb_internal cgProcedure *cg_procedure_create(cgModule *m, Entity *entity, bool i cgValue *found = string_map_get(&m->members, key); if (found) { cg_add_entity(m, entity, *found); + rw_mutex_lock(&m->values_mutex); p = string_map_must_get(&m->procedures, key); + rw_mutex_unlock(&m->values_mutex); if (!ignore_body && p->func != nullptr) { return nullptr; } @@ -96,7 +98,6 @@ gb_internal cgProcedure *cg_procedure_create(cgModule *m, Entity *entity, bool i p->debug_type = cg_debug_type_for_proc(m, p->type); p->proto = tb_prototype_from_dbg(m->mod, p->debug_type); - tb_function_set_prototype(p->func, p->proto, cg_arena()); p->symbol = cast(TB_Symbol *)p->func; } @@ -148,7 +149,6 @@ gb_internal cgProcedure *cg_procedure_create_dummy(cgModule *m, String const &li p->debug_type = cg_debug_type_for_proc(m, p->type); p->proto = tb_prototype_from_dbg(m->mod, p->debug_type); - tb_function_set_prototype(p->func, p->proto, cg_arena()); p->symbol = cast(TB_Symbol *)p->func; @@ -164,6 +164,8 @@ gb_internal void cg_procedure_begin(cgProcedure *p) { return; } + tb_function_set_prototype(p->func, p->proto, cg_arena()); + if (p->body == nullptr) { return; } @@ -324,19 +326,11 @@ gb_internal void cg_procedure_begin(cgProcedure *p) { } } -gb_internal void cg_procedure_end(cgProcedure *p) { - if (p == nullptr || p->func == nullptr) { - return; - } - if (tb_inst_get_control(p->func)) { - GB_ASSERT(p->type->Proc.result_count == 0); - tb_inst_ret(p->func, 0, nullptr); - } - bool emit_asm = false; - if (string_starts_with(p->name, str_lit("runtime@_os_write"))) { - // emit_asm = true; - } +gb_internal WORKER_TASK_PROC(cg_procedure_compile_worker_proc) { + cgProcedure *p = cast(cgProcedure *)data; + + bool emit_asm = false; TB_FunctionOutput *output = tb_module_compile_function(p->module->mod, p->func, TB_ISEL_FAST, emit_asm); if (emit_asm) { @@ -346,6 +340,24 @@ gb_internal void cg_procedure_end(cgProcedure *p) { } gb_printf_err("\n"); } + + return 0; +} + +gb_internal void cg_procedure_end(cgProcedure *p) { + if (p == nullptr || p->func == nullptr) { + return; + } + if (tb_inst_get_control(p->func)) { + GB_ASSERT(p->type->Proc.result_count == 0); + tb_inst_ret(p->func, 0, nullptr); + } + + if (p->module->do_threading) { + thread_pool_add_task(cg_procedure_compile_worker_proc, p); + } else { + cg_procedure_compile_worker_proc(p); + } } gb_internal void cg_procedure_generate(cgProcedure *p) { @@ -353,10 +365,12 @@ gb_internal void cg_procedure_generate(cgProcedure *p) { return; } + cg_procedure_begin(p); cg_build_stmt(p, p->body); cg_procedure_end(p); + if ( // string_starts_with(p->name, str_lit("runtime@_os_write")) || false @@ -408,7 +422,7 @@ gb_internal void cg_build_nested_proc(cgProcedure *p, AstProcLit *pd, Entity *e) cg_add_entity(m, e, value); array_add(&p->children, nested_proc); - array_add(&m->procedures_to_generate, nested_proc); + cg_add_procedure_to_queue(nested_proc); } diff --git a/src/tilde_stmt.cpp b/src/tilde_stmt.cpp index b25be089d..6cef37ad4 100644 --- a/src/tilde_stmt.cpp +++ b/src/tilde_stmt.cpp @@ -2036,9 +2036,9 @@ gb_internal void cg_build_constant_value_decl(cgProcedure *p, AstValueDecl *vd) cgValue value = p->value; - array_add(&p->module->procedures_to_generate, nested_proc); array_add(&p->children, nested_proc); string_map_set(&p->module->members, name, value); + cg_add_procedure_to_queue(nested_proc); } } }