mirror of
https://github.com/odin-lang/Odin.git
synced 2026-01-16 09:37:02 +00:00
Multithread tilde backend
This commit is contained in:
@@ -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<TB_Arena *>(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<TB_Arena *>(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<cgProcedure *> 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) {
|
||||
|
||||
@@ -210,13 +210,14 @@ struct cgModule {
|
||||
CheckerInfo *info;
|
||||
LinkerData * linker_data;
|
||||
|
||||
RwMutex values_mutex;
|
||||
PtrMap<Entity *, cgValue> values;
|
||||
StringMap<cgValue> members;
|
||||
bool do_threading;
|
||||
Array<cgProcedure *> single_threaded_procedure_queue;
|
||||
|
||||
StringMap<cgProcedure *> procedures;
|
||||
RwMutex values_mutex;
|
||||
PtrMap<Entity *, cgValue> values;
|
||||
StringMap<cgValue> members;
|
||||
StringMap<cgProcedure *> procedures;
|
||||
PtrMap<TB_Function *, Entity *> procedure_values;
|
||||
Array<cgProcedure *> procedures_to_generate;
|
||||
|
||||
RecursiveMutex debug_type_mutex;
|
||||
PtrMap<Type *, TB_DebugType *> debug_type_map;
|
||||
@@ -225,6 +226,7 @@ struct cgModule {
|
||||
RecursiveMutex proc_proto_mutex;
|
||||
PtrMap<Type *, TB_FunctionPrototype *> proc_proto_map;
|
||||
|
||||
// NOTE(bill): no need to protect this with a mutex
|
||||
PtrMap<uintptr, TB_FileID> file_id_map; // Key: AstFile.id (i32 cast to uintptr)
|
||||
|
||||
std::atomic<u32> 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);
|
||||
|
||||
BIN
src/tilde/tb.lib
BIN
src/tilde/tb.lib
Binary file not shown.
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user