aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorgingerBill <bill@gingerbill.org>2021-05-04 00:45:09 +0100
committergingerBill <bill@gingerbill.org>2021-05-04 00:45:09 +0100
commit17001bf38c85825c4f7191f5a784ab8a65baeb40 (patch)
tree904356136b3d4994ba0485bfae19e1d6b23f3e0a
parentb83e67f45f3bde2abab70154d76307a9e3d7f4e3 (diff)
Nearly approach full functionality for -use-separate-modules coupled with multithreading
-rw-r--r--src/llvm_backend.cpp217
-rw-r--r--src/thread_pool.cpp3
2 files changed, 129 insertions, 91 deletions
diff --git a/src/llvm_backend.cpp b/src/llvm_backend.cpp
index ceb470d75..a84c26c9b 100644
--- a/src/llvm_backend.cpp
+++ b/src/llvm_backend.cpp
@@ -13,7 +13,9 @@
#include "llvm_abi.cpp"
#include "llvm_backend_opt.cpp"
-gb_global lbAddr lb_global_type_info_data = {};
+gb_global ThreadPool lb_thread_pool = {};
+
+gb_global Entity *lb_global_type_info_data_entity = {};
gb_global lbAddr lb_global_type_info_member_types = {};
gb_global lbAddr lb_global_type_info_member_names = {};
gb_global lbAddr lb_global_type_info_member_offsets = {};
@@ -28,6 +30,12 @@ gb_global isize lb_global_type_info_member_usings_index = 0;
gb_global isize lb_global_type_info_member_tags_index = 0;
+lbValue lb_global_type_info_data_ptr(lbModule *m) {
+ lbValue v = lb_find_value_from_entity(m, lb_global_type_info_data_entity);
+ return v;
+}
+
+
struct lbLoopData {
lbAddr idx_addr;
lbValue idx;
@@ -2539,6 +2547,7 @@ void lb_ensure_abi_function_type(lbModule *m, lbProcedure *p) {
lbProcedure *lb_create_procedure(lbModule *m, Entity *entity, bool ignore_body) {
GB_ASSERT(entity != nullptr);
+ GB_ASSERT(entity->kind == Entity_Procedure);
String link_name = {};
@@ -5674,7 +5683,7 @@ lbValue lb_type_info(lbModule *m, Type *type) {
};
lbValue value = {};
- value.value = LLVMConstGEP(lb_global_type_info_data.addr.value, indices, gb_count_of(indices));
+ value.value = LLVMConstGEP(lb_global_type_info_data_ptr(m).value, indices, gb_count_of(indices));
value.type = t_type_info_ptr;
return value;
}
@@ -5736,7 +5745,7 @@ lbValue lb_find_procedure_value_from_entity(lbModule *m, Entity *e) {
lbValue lb_find_value_from_entity(lbModule *m, Entity *e) {
e = strip_entity_wrapping(e);
GB_ASSERT(e != nullptr);
- if (is_type_proc(e->type)) {
+ if (e->kind == Entity_Procedure) {
return lb_find_procedure_value_from_entity(m, e);
}
@@ -13184,7 +13193,7 @@ lbValue lb_get_type_info_ptr(lbModule *m, Type *type) {
lbValue res = {};
res.type = t_type_info_ptr;
- res.value = LLVMConstGEP(lb_global_type_info_data.addr.value, indices, cast(unsigned)gb_count_of(indices));
+ res.value = LLVMConstGEP(lb_global_type_info_data_ptr(m).value, indices, cast(unsigned)gb_count_of(indices));
return res;
}
@@ -13251,12 +13260,12 @@ void lb_setup_type_info_data(lbProcedure *p) { // NOTE(bill): Setup type_info da
{
// NOTE(bill): Set the type_table slice with the global backing array
lbValue global_type_table = lb_find_runtime_value(m, str_lit("type_table"));
- Type *type = base_type(lb_addr_type(lb_global_type_info_data));
+ Type *type = base_type(lb_global_type_info_data_entity->type);
GB_ASSERT(is_type_array(type));
LLVMValueRef indices[2] = {llvm_zero(m), llvm_zero(m)};
LLVMValueRef values[2] = {
- LLVMConstInBoundsGEP(lb_global_type_info_data.addr.value, indices, gb_count_of(indices)),
+ LLVMConstInBoundsGEP(lb_global_type_info_data_ptr(m).value, indices, gb_count_of(indices)),
LLVMConstInt(lb_type(m, t_int), type->Array.count, true),
};
LLVMValueRef slice = llvm_const_named_struct(llvm_addr_type(global_type_table), values, gb_count_of(values));
@@ -13288,7 +13297,7 @@ void lb_setup_type_info_data(lbProcedure *p) { // NOTE(bill): Setup type_info da
}
lbValue tag = {};
- lbValue ti_ptr = lb_emit_array_epi(p, lb_global_type_info_data.addr, cast(i32)entry_index);
+ lbValue ti_ptr = lb_emit_array_epi(p, lb_global_type_info_data_ptr(m), cast(i32)entry_index);
lbValue variant_ptr = lb_emit_struct_ep(p, ti_ptr, 4);
lbValue type_info_flags = lb_const_int(p->module, t_type_info_flags, type_info_flags_of_type(t));
@@ -14270,6 +14279,96 @@ WORKER_TASK_PROC(lb_llvm_emit_worker_proc) {
return 0;
}
+WORKER_TASK_PROC(lb_llvm_function_pass_worker_proc) {
+ GB_ASSERT(MULTITHREAD_OBJECT_GENERATION);
+
+ auto m = cast(lbModule *)data;
+
+ LLVMPassManagerRef default_function_pass_manager = LLVMCreateFunctionPassManagerForModule(m->mod);
+ LLVMPassManagerRef function_pass_manager_minimal = LLVMCreateFunctionPassManagerForModule(m->mod);
+ LLVMPassManagerRef function_pass_manager_size = LLVMCreateFunctionPassManagerForModule(m->mod);
+ LLVMPassManagerRef function_pass_manager_speed = LLVMCreateFunctionPassManagerForModule(m->mod);
+
+ LLVMInitializeFunctionPassManager(default_function_pass_manager);
+ LLVMInitializeFunctionPassManager(function_pass_manager_minimal);
+ LLVMInitializeFunctionPassManager(function_pass_manager_size);
+ LLVMInitializeFunctionPassManager(function_pass_manager_speed);
+
+ lb_populate_function_pass_manager(default_function_pass_manager, false, build_context.optimization_level);
+ lb_populate_function_pass_manager_specific(function_pass_manager_minimal, 0);
+ lb_populate_function_pass_manager_specific(function_pass_manager_size, 1);
+ lb_populate_function_pass_manager_specific(function_pass_manager_speed, 2);
+
+ LLVMFinalizeFunctionPassManager(default_function_pass_manager);
+ LLVMFinalizeFunctionPassManager(function_pass_manager_minimal);
+ LLVMFinalizeFunctionPassManager(function_pass_manager_size);
+ LLVMFinalizeFunctionPassManager(function_pass_manager_speed);
+
+
+ LLVMPassManagerRef default_function_pass_manager_without_memcpy = LLVMCreateFunctionPassManagerForModule(m->mod);
+ LLVMInitializeFunctionPassManager(default_function_pass_manager_without_memcpy);
+ lb_populate_function_pass_manager(default_function_pass_manager_without_memcpy, true, build_context.optimization_level);
+ LLVMFinalizeFunctionPassManager(default_function_pass_manager_without_memcpy);
+
+
+ for_array(i, m->procedures_to_generate) {
+ lbProcedure *p = m->procedures_to_generate[i];
+ if (p->body != nullptr) { // Build Procedure
+ if (p->flags & lbProcedureFlag_WithoutMemcpyPass) {
+ LLVMRunFunctionPassManager(default_function_pass_manager_without_memcpy, p->value);
+ } else {
+ if (p->entity && p->entity->kind == Entity_Procedure) {
+ switch (p->entity->Procedure.optimization_mode) {
+ case ProcedureOptimizationMode_None:
+ case ProcedureOptimizationMode_Minimal:
+ LLVMRunFunctionPassManager(function_pass_manager_minimal, p->value);
+ break;
+ case ProcedureOptimizationMode_Size:
+ LLVMRunFunctionPassManager(function_pass_manager_size, p->value);
+ break;
+ case ProcedureOptimizationMode_Speed:
+ LLVMRunFunctionPassManager(function_pass_manager_speed, p->value);
+ break;
+ default:
+ LLVMRunFunctionPassManager(default_function_pass_manager, p->value);
+ break;
+ }
+ } else {
+ LLVMRunFunctionPassManager(default_function_pass_manager, p->value);
+ }
+ }
+ }
+ }
+
+ for_array(i, m->equal_procs.entries) {
+ lbProcedure *p = m->equal_procs.entries[i].value;
+ LLVMRunFunctionPassManager(default_function_pass_manager, p->value);
+ }
+ for_array(i, m->hasher_procs.entries) {
+ lbProcedure *p = m->hasher_procs.entries[i].value;
+ LLVMRunFunctionPassManager(default_function_pass_manager, p->value);
+ }
+
+ return 0;
+}
+
+
+struct lbLLVMModulePassWorkerData {
+ lbModule *m;
+ LLVMTargetMachineRef target_machine;
+};
+
+WORKER_TASK_PROC(lb_llvm_module_pass_worker_proc) {
+ GB_ASSERT(MULTITHREAD_OBJECT_GENERATION);
+
+ auto wd = cast(lbLLVMModulePassWorkerData *)data;
+
+ 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);
+
+ return 0;
+}
void lb_generate_code(lbGenerator *gen) {
@@ -14278,6 +14377,14 @@ void lb_generate_code(lbGenerator *gen) {
TIME_SECTION("LLVM Initializtion");
+ isize thread_count = gb_max(build_context.thread_count, 1);
+ isize worker_count = thread_count-1;
+
+ LLVMBool do_threading = (LLVMIsMultithreaded() && USE_SEPARTE_MODULES && MULTITHREAD_OBJECT_GENERATION && worker_count > 0);
+
+ thread_pool_init(&lb_thread_pool, heap_allocator(), worker_count, "LLVMBackend");
+ defer (thread_pool_destroy(&lb_thread_pool));
+
lbModule *default_module = &gen->default_module;
CheckerInfo *info = gen->info;
@@ -14415,7 +14522,9 @@ void lb_generate_code(lbGenerator *gen) {
lbValue value = {};
value.value = g;
value.type = alloc_type_pointer(t);
- lb_global_type_info_data = lb_addr(value);
+
+ lb_global_type_info_data_entity = alloc_entity_variable(nullptr, blank_token, t, EntityState_Resolved);
+ lb_add_entity(m, lb_global_type_info_data_entity, value);
}
{ // Type info member buffer
// NOTE(bill): Removes need for heap allocation by making it global memory
@@ -14776,82 +14885,22 @@ void lb_generate_code(lbGenerator *gen) {
for_array(i, gen->modules.entries) {
lbModule *m = gen->modules.entries[i].value;
- LLVMPassManagerRef default_function_pass_manager = LLVMCreateFunctionPassManagerForModule(m->mod);
- LLVMPassManagerRef function_pass_manager_minimal = LLVMCreateFunctionPassManagerForModule(m->mod);
- LLVMPassManagerRef function_pass_manager_size = LLVMCreateFunctionPassManagerForModule(m->mod);
- LLVMPassManagerRef function_pass_manager_speed = LLVMCreateFunctionPassManagerForModule(m->mod);
-
- LLVMInitializeFunctionPassManager(default_function_pass_manager);
- LLVMInitializeFunctionPassManager(function_pass_manager_minimal);
- LLVMInitializeFunctionPassManager(function_pass_manager_size);
- LLVMInitializeFunctionPassManager(function_pass_manager_speed);
-
- lb_populate_function_pass_manager(default_function_pass_manager, false, build_context.optimization_level);
- lb_populate_function_pass_manager_specific(function_pass_manager_minimal, 0);
- lb_populate_function_pass_manager_specific(function_pass_manager_size, 1);
- lb_populate_function_pass_manager_specific(function_pass_manager_speed, 2);
-
- LLVMFinalizeFunctionPassManager(default_function_pass_manager);
- LLVMFinalizeFunctionPassManager(function_pass_manager_minimal);
- LLVMFinalizeFunctionPassManager(function_pass_manager_size);
- LLVMFinalizeFunctionPassManager(function_pass_manager_speed);
-
-
- LLVMPassManagerRef default_function_pass_manager_without_memcpy = LLVMCreateFunctionPassManagerForModule(m->mod);
- LLVMInitializeFunctionPassManager(default_function_pass_manager_without_memcpy);
- lb_populate_function_pass_manager(default_function_pass_manager_without_memcpy, true, build_context.optimization_level);
- LLVMFinalizeFunctionPassManager(default_function_pass_manager_without_memcpy);
-
-
- for_array(i, m->procedures_to_generate) {
- lbProcedure *p = m->procedures_to_generate[i];
- if (p->body != nullptr) { // Build Procedure
- if (p->flags & lbProcedureFlag_WithoutMemcpyPass) {
- LLVMRunFunctionPassManager(default_function_pass_manager_without_memcpy, p->value);
- } else {
- if (p->entity && p->entity->kind == Entity_Procedure) {
- switch (p->entity->Procedure.optimization_mode) {
- case ProcedureOptimizationMode_None:
- case ProcedureOptimizationMode_Minimal:
- LLVMRunFunctionPassManager(function_pass_manager_minimal, p->value);
- break;
- case ProcedureOptimizationMode_Size:
- LLVMRunFunctionPassManager(function_pass_manager_size, p->value);
- break;
- case ProcedureOptimizationMode_Speed:
- LLVMRunFunctionPassManager(function_pass_manager_speed, p->value);
- break;
- default:
- LLVMRunFunctionPassManager(default_function_pass_manager, p->value);
- break;
- }
- } else {
- LLVMRunFunctionPassManager(default_function_pass_manager, p->value);
- }
- }
- }
- }
-
- for_array(i, m->equal_procs.entries) {
- lbProcedure *p = m->equal_procs.entries[i].value;
- LLVMRunFunctionPassManager(default_function_pass_manager, p->value);
- }
- for_array(i, m->hasher_procs.entries) {
- lbProcedure *p = m->hasher_procs.entries[i].value;
- LLVMRunFunctionPassManager(default_function_pass_manager, p->value);
- }
+ lb_llvm_function_pass_worker_proc(m);
}
TIME_SECTION("LLVM Module Pass");
for_array(i, gen->modules.entries) {
- LLVMPassManagerRef module_pass_manager = LLVMCreatePassManager();
- auto target_machine = target_machines[i];
- lb_populate_module_pass_manager(target_machine, module_pass_manager, build_context.optimization_level);
lbModule *m = gen->modules.entries[i].value;
- LLVMRunPassManager(module_pass_manager, m->mod);
+
+ auto wd = gb_alloc_item(permanent_allocator(), lbLLVMModulePassWorkerData);
+ wd->m = m;
+ wd->target_machine = target_machines[i];
+
+ lb_llvm_module_pass_worker_proc(wd);
}
+
llvm_error = nullptr;
defer (LLVMDisposeMessage(llvm_error));
@@ -14921,15 +14970,7 @@ void lb_generate_code(lbGenerator *gen) {
TIME_SECTION("LLVM Object Generation");
- isize thread_count = gb_max(build_context.thread_count, 1);
- isize worker_count = thread_count-1;
-
- LLVMBool do_threading = LLVMIsMultithreaded();
- if (do_threading && USE_SEPARTE_MODULES && MULTITHREAD_OBJECT_GENERATION && worker_count > 0) {
- ThreadPool pool = {};
- thread_pool_init(&pool, heap_allocator(), worker_count, "LLVMEmitWork");
- defer (thread_pool_destroy(&pool));
-
+ if (do_threading) {
for_array(j, gen->modules.entries) {
lbModule *m = gen->modules.entries[j].value;
if (lb_is_module_empty(m)) {
@@ -14946,11 +14987,11 @@ void lb_generate_code(lbGenerator *gen) {
wd->code_gen_file_type = code_gen_file_type;
wd->filepath_obj = filepath_obj;
wd->m = m;
- thread_pool_add_task(&pool, lb_llvm_emit_worker_proc, wd);
+ thread_pool_add_task(&lb_thread_pool, lb_llvm_emit_worker_proc, wd);
}
- thread_pool_start(&pool);
- thread_pool_wait_to_process(&pool);
+ thread_pool_start(&lb_thread_pool);
+ thread_pool_wait_to_process(&lb_thread_pool);
} else {
for_array(j, gen->modules.entries) {
lbModule *m = gen->modules.entries[j].value;
diff --git a/src/thread_pool.cpp b/src/thread_pool.cpp
index 2467ba609..73118321b 100644
--- a/src/thread_pool.cpp
+++ b/src/thread_pool.cpp
@@ -35,8 +35,6 @@ void thread_pool_destroy(ThreadPool *pool);
void thread_pool_start(ThreadPool *pool);
void thread_pool_join(ThreadPool *pool);
void thread_pool_add_task(ThreadPool *pool, WorkerTaskProc *proc, void *data);
-void thread_pool_kick(ThreadPool *pool);
-void thread_pool_kick_and_wait(ThreadPool *pool);
GB_THREAD_PROC(worker_thread_internal);
void thread_pool_init(ThreadPool *pool, gbAllocator const &a, isize thread_count, char const *worker_prefix) {
@@ -181,4 +179,3 @@ GB_THREAD_PROC(worker_thread_internal) {
return 0;
}
-