mirror of
https://github.com/odin-lang/Odin.git
synced 2026-08-26 06:51:34 +00:00
Merge pull request #7391 from kalsprite/codegen_worker_exit
codegen worker must not exit process with running siblings
This commit is contained in:
@@ -2003,7 +2003,8 @@ gb_internal void lb_verify_function(lbModule *m, lbProcedure *p, bool dump_ll=fa
|
||||
}
|
||||
}
|
||||
LLVMVerifyFunction(p->value, LLVMPrintMessageAction);
|
||||
exit_with_errors();
|
||||
lb_record_worker_failure();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2023,11 +2024,11 @@ gb_internal WORKER_TASK_PROC(lb_llvm_module_verification_worker_proc) {
|
||||
String filepath_ll = lb_filepath_ll_for_module(m);
|
||||
if (LLVMPrintModuleToFile(m->mod, cast(char const *)filepath_ll.text, &llvm_error)) {
|
||||
gb_printf_err("LLVM Error: %s\n", llvm_error);
|
||||
exit_with_errors();
|
||||
return false;
|
||||
lb_record_worker_failure();
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
exit_with_errors();
|
||||
lb_record_worker_failure();
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
@@ -2390,11 +2391,13 @@ gb_internal WORKER_TASK_PROC(lb_llvm_emit_worker_proc) {
|
||||
if (build_context.lto_kind != LTO_None) {
|
||||
if (LLVMWriteBitcodeToFile(wd->m->mod, cast(char *)wd->filepath_obj.text)) {
|
||||
gb_printf_err("Failed to write bitcode file: %.*s\n", LIT(wd->filepath_obj));
|
||||
exit_with_errors();
|
||||
lb_record_worker_failure();
|
||||
return 1;
|
||||
}
|
||||
} else if (LLVMTargetMachineEmitToFile(wd->target_machine, wd->m->mod, cast(char *)wd->filepath_obj.text, wd->code_gen_file_type, &llvm_error)) {
|
||||
gb_printf_err("LLVM Error: %s\n", llvm_error);
|
||||
exit_with_errors();
|
||||
lb_record_worker_failure();
|
||||
return 1;
|
||||
}
|
||||
debugf("Generated File: %.*s\n", LIT(wd->filepath_obj));
|
||||
return 0;
|
||||
@@ -2561,7 +2564,7 @@ gb_internal WORKER_TASK_PROC(lb_llvm_module_pass_worker_proc) {
|
||||
gb_printf_err("LLVM Error: %s\n", llvm_error);
|
||||
}
|
||||
}
|
||||
exit_with_errors();
|
||||
lb_record_worker_failure();
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -2602,6 +2605,8 @@ gb_internal void lb_generate_procedures(lbGenerator *gen, bool do_threading) {
|
||||
lb_generate_procedures_worker_proc(m);
|
||||
}
|
||||
}
|
||||
|
||||
lb_exit_if_worker_failed();
|
||||
}
|
||||
|
||||
gb_internal WORKER_TASK_PROC(lb_generate_missing_procedures_to_check_worker_proc) {
|
||||
@@ -2674,6 +2679,8 @@ gb_internal void lb_llvm_function_passes(lbGenerator *gen, bool do_threading) {
|
||||
lb_llvm_function_pass_per_module(m);
|
||||
}
|
||||
}
|
||||
|
||||
lb_exit_if_worker_failed();
|
||||
}
|
||||
|
||||
|
||||
@@ -2699,6 +2706,8 @@ gb_internal void lb_llvm_module_passes_and_verification(lbGenerator *gen, bool d
|
||||
lb_llvm_module_pass_worker_proc(wd);
|
||||
}
|
||||
}
|
||||
|
||||
lb_exit_if_worker_failed();
|
||||
}
|
||||
|
||||
gb_internal String lb_filepath_ll_for_module(lbModule *m) {
|
||||
@@ -2829,6 +2838,7 @@ gb_internal bool lb_llvm_object_generation(lbGenerator *gen, bool do_threading)
|
||||
}
|
||||
|
||||
thread_pool_wait(&global_thread_pool);
|
||||
lb_exit_if_worker_failed();
|
||||
} else {
|
||||
for (auto const &entry : gen->modules) {
|
||||
lbModule *m = entry.value;
|
||||
|
||||
@@ -16,6 +16,41 @@ gb_global isize lb_global_type_info_member_offsets_index = 0;
|
||||
gb_global isize lb_global_type_info_member_usings_index = 0;
|
||||
gb_global isize lb_global_type_info_member_tags_index = 0;
|
||||
|
||||
// A backend worker must not end the process: its siblings are still inside LLVM, and tearing the
|
||||
// process down under them is what turns a reported error into a crash. A failing worker records the
|
||||
// failure and returns; the driver exits once the pool has drained. Work stealing can run a task on
|
||||
// the main thread, so this must not depend on which thread is executing
|
||||
gb_global std::atomic<bool> lb_worker_failure;
|
||||
|
||||
gb_internal void lb_record_worker_failure(void) {
|
||||
lb_worker_failure.store(true, std::memory_order_release);
|
||||
}
|
||||
|
||||
gb_internal void lb_exit_if_worker_failed(void) {
|
||||
if (lb_worker_failure.load(std::memory_order_acquire)) {
|
||||
exit_with_errors();
|
||||
}
|
||||
}
|
||||
|
||||
// Without a handler installed, LLVM prints an error of its own and calls exit(1) from whichever
|
||||
// thread it is on.
|
||||
gb_internal void lb_llvm_diagnostic_handler(LLVMDiagnosticInfoRef di, void *) {
|
||||
char *description = LLVMGetDiagInfoDescription(di);
|
||||
defer (LLVMDisposeMessage(description));
|
||||
|
||||
switch (LLVMGetDiagInfoSeverity(di)) {
|
||||
case LLVMDSError:
|
||||
gb_printf_err("LLVM Error: %s\n", description);
|
||||
lb_record_worker_failure();
|
||||
break;
|
||||
case LLVMDSWarning:
|
||||
gb_printf_err("LLVM Warning: %s\n", description);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
gb_internal WORKER_TASK_PROC(lb_init_module_worker_proc) {
|
||||
lbModule *m = cast(lbModule *)data;
|
||||
Checker *c = m->checker;
|
||||
@@ -58,6 +93,7 @@ gb_internal WORKER_TASK_PROC(lb_init_module_worker_proc) {
|
||||
|
||||
m->module_name = module_name;
|
||||
m->ctx = LLVMContextCreate();
|
||||
LLVMContextSetDiagnosticHandler(m->ctx, lb_llvm_diagnostic_handler, nullptr);
|
||||
m->mod = LLVMModuleCreateWithNameInContext(m->module_name, m->ctx);
|
||||
// m->debug_builder = nullptr;
|
||||
if (build_context.no_plt) {
|
||||
|
||||
Reference in New Issue
Block a user