From 5c519f0e8dada6b15166a257d22a07f2316a394f Mon Sep 17 00:00:00 2001 From: gingerBill Date: Sun, 1 Jan 2023 16:19:21 +0000 Subject: Remove the synchronization primitive init/destroy calls --- src/llvm_backend_general.cpp | 1 - 1 file changed, 1 deletion(-) (limited to 'src/llvm_backend_general.cpp') diff --git a/src/llvm_backend_general.cpp b/src/llvm_backend_general.cpp index e5aa95f10..0508c6171 100644 --- a/src/llvm_backend_general.cpp +++ b/src/llvm_backend_general.cpp @@ -132,7 +132,6 @@ gb_internal bool lb_init_generator(lbGenerator *gen, Checker *c) { map_init(&gen->anonymous_proc_lits, heap_allocator(), 1024); - mutex_init(&gen->foreign_mutex); array_init(&gen->foreign_libraries, heap_allocator(), 0, 1024); ptr_set_init(&gen->foreign_libraries_set, heap_allocator(), 1024); -- cgit v1.2.3 From 529383f5b17d74f66bebb8679820a69476635b6a Mon Sep 17 00:00:00 2001 From: gingerBill Date: Mon, 2 Jan 2023 15:30:04 +0000 Subject: Correct a race condition when checking the procedure body --- src/build_settings.cpp | 1 + src/check_decl.cpp | 25 ++--- src/check_expr.cpp | 23 ++++- src/checker.cpp | 224 ++++++++++++++++++++++++++++++++++--------- src/checker.hpp | 21 +++- src/llvm_backend.cpp | 6 ++ src/llvm_backend.hpp | 1 + src/llvm_backend_expr.cpp | 6 +- src/llvm_backend_general.cpp | 5 +- src/llvm_backend_proc.cpp | 3 +- src/llvm_backend_stmt.cpp | 6 +- src/main.cpp | 5 + 12 files changed, 260 insertions(+), 66 deletions(-) (limited to 'src/llvm_backend_general.cpp') diff --git a/src/build_settings.cpp b/src/build_settings.cpp index 97b512b81..f59b5c0f7 100644 --- a/src/build_settings.cpp +++ b/src/build_settings.cpp @@ -291,6 +291,7 @@ struct BuildContext { bool show_error_line; bool ignore_lazy; + bool ignore_llvm_build; bool use_subsystem_windows; bool ignore_microsoft_magic; diff --git a/src/check_decl.cpp b/src/check_decl.cpp index 4e3c1b405..8f95c1a49 100644 --- a/src/check_decl.cpp +++ b/src/check_decl.cpp @@ -1419,9 +1419,9 @@ struct ProcUsingVar { }; -gb_internal void check_proc_body(CheckerContext *ctx_, Token token, DeclInfo *decl, Type *type, Ast *body) { +gb_internal bool check_proc_body(CheckerContext *ctx_, Token token, DeclInfo *decl, Type *type, Ast *body) { if (body == nullptr) { - return; + return false; } GB_ASSERT(body->kind == Ast_BlockStmt); @@ -1502,7 +1502,7 @@ gb_internal void check_proc_body(CheckerContext *ctx_, Token token, DeclInfo *de MUTEX_GUARD_BLOCK(ctx->scope->mutex) for_array(i, using_entities) { Entity *e = using_entities[i].e; Entity *uvar = using_entities[i].uvar; - Entity *prev = scope_insert(ctx->scope, uvar, false); + Entity *prev = scope_insert_no_mutex(ctx->scope, uvar); if (prev != nullptr) { error(e->token, "Namespace collision while 'using' procedure argument '%.*s' of: %.*s", LIT(e->token.string), LIT(prev->token.string)); error_line("%.*s != %.*s\n", LIT(uvar->token.string), LIT(prev->token.string)); @@ -1514,7 +1514,7 @@ gb_internal void check_proc_body(CheckerContext *ctx_, Token token, DeclInfo *de bool where_clause_ok = evaluate_where_clauses(ctx, nullptr, decl->scope, &decl->proc_lit->ProcLit.where_clauses, !decl->where_clauses_evaluated); if (!where_clause_ok) { // NOTE(bill, 2019-08-31): Don't check the body as the where clauses failed - return; + return false; } check_open_scope(ctx, body); @@ -1526,7 +1526,12 @@ gb_internal void check_proc_body(CheckerContext *ctx_, Token token, DeclInfo *de // NOTE(bill): Don't err here } - GB_ASSERT(decl->defer_use_checked == false); + GB_ASSERT(decl->proc_checked_state != ProcCheckedState_Checked); + if (decl->defer_use_checked) { + GB_ASSERT(is_type_polymorphic(type, true)); + error(token, "Defer Use Checked: %.*s", LIT(decl->entity->token.string)); + GB_ASSERT(decl->defer_use_checked == false); + } check_stmt_list(ctx, bs->stmts, Stmt_CheckScopeDecls); @@ -1575,10 +1580,8 @@ gb_internal void check_proc_body(CheckerContext *ctx_, Token token, DeclInfo *de if (decl->parent != nullptr) { Scope *ps = decl->parent->scope; if (ps->flags & (ScopeFlag_File & ScopeFlag_Pkg & ScopeFlag_Global)) { - return; - } else { - mutex_lock(&ctx->info->deps_mutex); - + return true; + } else MUTEX_GUARD_BLOCK(&ctx->info->deps_mutex) { // NOTE(bill): Add the dependencies from the procedure literal (lambda) // But only at the procedure level for (auto const &entry : decl->deps) { @@ -1589,8 +1592,8 @@ gb_internal void check_proc_body(CheckerContext *ctx_, Token token, DeclInfo *de Type *t = entry.ptr; ptr_set_add(&decl->parent->type_info_deps, t); } - - mutex_unlock(&ctx->info->deps_mutex); } } + + return true; } diff --git a/src/check_expr.cpp b/src/check_expr.cpp index eb9f76547..5445e73c7 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -86,7 +86,6 @@ gb_internal Entity * find_polymorphic_record_entity (CheckerContext *c, Type *or gb_internal void check_not_tuple (CheckerContext *c, Operand *operand); gb_internal void convert_to_typed (CheckerContext *c, Operand *operand, Type *target_type); gb_internal gbString expr_to_string (Ast *expression); -gb_internal void check_proc_body (CheckerContext *c, Token token, DeclInfo *decl, Type *type, Ast *body); gb_internal void update_untyped_expr_type (CheckerContext *c, Ast *e, Type *type, bool final); gb_internal bool check_is_terminating (Ast *node, String const &label); gb_internal bool check_has_break (Ast *stmt, String const &label, bool implicit); @@ -478,6 +477,22 @@ gb_internal bool find_or_generate_polymorphic_procedure(CheckerContext *old_c, E if (poly_proc_data) { poly_proc_data->gen_entity = other; } + + DeclInfo *decl = other->decl_info; + if (decl->proc_checked_state != ProcCheckedState_Checked) { + ProcInfo *proc_info = gb_alloc_item(permanent_allocator(), ProcInfo); + proc_info->file = other->file; + proc_info->token = other->token; + proc_info->decl = decl; + proc_info->type = other->type; + proc_info->body = decl->proc_lit->ProcLit.body; + proc_info->tags = other->Procedure.tags;; + proc_info->generated_from_polymorphic = true; + proc_info->poly_def_node = poly_def_node; + + check_procedure_later(nctx.checker, proc_info); + } + return true; } } @@ -518,7 +533,8 @@ gb_internal bool find_or_generate_polymorphic_procedure(CheckerContext *old_c, E d->gen_proc_type = final_proc_type; d->type_expr = pl->type; d->proc_lit = proc_lit; - d->proc_checked = false; + d->proc_checked_state = ProcCheckedState_Unchecked; + d->defer_use_checked = false; Entity *entity = alloc_entity_procedure(nullptr, token, final_proc_type, tags); entity->identifier = ident; @@ -528,7 +544,8 @@ gb_internal bool find_or_generate_polymorphic_procedure(CheckerContext *old_c, E entity->scope = scope->parent; entity->file = base_entity->file; entity->pkg = base_entity->pkg; - entity->flags &= ~EntityFlag_ProcBodyChecked; + entity->flags = 0; + d->entity = entity; AstFile *file = nullptr; { diff --git a/src/checker.cpp b/src/checker.cpp index d3a9c3d2c..f4c9b6822 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -1,3 +1,5 @@ +#define DEBUG_CHECK_ALL_PROCEDURES 1 + #include "entity.cpp" #include "types.cpp" @@ -179,6 +181,7 @@ gb_internal void import_graph_node_swap(ImportGraphNode **data, isize i, isize j gb_internal void init_decl_info(DeclInfo *d, Scope *scope, DeclInfo *parent) { + gb_zero_item(d); d->parent = parent; d->scope = scope; ptr_set_init(&d->deps, heap_allocator()); @@ -438,9 +441,44 @@ gb_internal Entity *scope_lookup(Scope *s, String const &name) { return entity; } +gb_internal Entity *scope_insert_with_name_no_mutex(Scope *s, String const &name, Entity *entity) { + if (name == "") { + return nullptr; + } + StringHashKey key = string_hash_string(name); + Entity **found = nullptr; + Entity *result = nullptr; + + found = string_map_get(&s->elements, key); + + if (found) { + if (entity != *found) { + result = *found; + } + goto end; + } + if (s->parent != nullptr && (s->parent->flags & ScopeFlag_Proc) != 0) { + found = string_map_get(&s->parent->elements, key); + if (found) { + if ((*found)->flags & EntityFlag_Result) { + if (entity != *found) { + result = *found; + } + goto end; + } + } + } + + string_map_set(&s->elements, key, entity); + if (entity->scope == nullptr) { + entity->scope = s; + } +end:; + return result; +} -gb_internal Entity *scope_insert_with_name(Scope *s, String const &name, Entity *entity, bool use_mutex=true) { +gb_internal Entity *scope_insert_with_name(Scope *s, String const &name, Entity *entity) { if (name == "") { return nullptr; } @@ -448,9 +486,8 @@ gb_internal Entity *scope_insert_with_name(Scope *s, String const &name, Entity Entity **found = nullptr; Entity *result = nullptr; - if (use_mutex) mutex_lock(&s->mutex); - defer (if (use_mutex) mutex_unlock(&s->mutex)); - + MUTEX_GUARD(&s->mutex); + found = string_map_get(&s->elements, key); if (found) { @@ -479,9 +516,14 @@ end:; return result; } -gb_internal Entity *scope_insert(Scope *s, Entity *entity, bool use_mutex) { +gb_internal Entity *scope_insert(Scope *s, Entity *entity) { String name = entity->token.string; - return scope_insert_with_name(s, name, entity, use_mutex); + return scope_insert_with_name(s, name, entity); +} + +gb_internal Entity *scope_insert_no_mutex(Scope *s, Entity *entity) { + String name = entity->token.string; + return scope_insert_with_name_no_mutex(s, name, entity); } @@ -1135,6 +1177,9 @@ gb_internal void init_checker_info(CheckerInfo *i) { map_init(&i->objc_msgSend_types, a); string_map_init(&i->load_file_cache, a); + + array_init(&i->all_procedures, heap_allocator()); + } gb_internal void destroy_checker_info(CheckerInfo *i) { @@ -1934,6 +1979,7 @@ gb_internal void add_type_info_type_internal(CheckerContext *c, Type *t) { gb_global std::atomic global_procedure_body_in_worker_queue = false; +gb_global std::atomic global_after_checking_procedure_bodies = false; gb_internal WORKER_TASK_PROC(check_proc_info_worker_proc); @@ -1941,12 +1987,24 @@ gb_internal void check_procedure_later(Checker *c, ProcInfo *info) { GB_ASSERT(info != nullptr); GB_ASSERT(info->decl != nullptr); - if (global_procedure_body_in_worker_queue) { + if (global_after_checking_procedure_bodies) { + Entity *e = info->decl->entity; + debugf("CHECK PROCEDURE LATER! %.*s :: %s {...}\n", LIT(e->token.string), type_to_string(e->type)); + } + + if (global_procedure_body_in_worker_queue.load()) { thread_pool_add_task(check_proc_info_worker_proc, info); } else { - GB_ASSERT(global_procedure_body_in_worker_queue == false); array_add(&c->procs_to_check, info); } + + if (DEBUG_CHECK_ALL_PROCEDURES) { + MUTEX_GUARD_BLOCK(&c->info.all_procedures_mutex) { + GB_ASSERT(info != nullptr); + GB_ASSERT(info->decl != nullptr); + array_add(&c->info.all_procedures, info); + } + } } gb_internal void check_procedure_later(Checker *c, AstFile *file, Token token, DeclInfo *decl, Type *type, Ast *body, u64 tags) { @@ -5010,24 +5068,26 @@ gb_internal bool check_proc_info(Checker *c, ProcInfo *pi, UntypedExprInfoMap *u if (pi->type == nullptr) { return false; } - Entity *e = pi->decl->entity; - MUTEX_GUARD_BLOCK(&pi->decl->proc_checked_mutex) { - if (pi->decl->proc_checked) { - if (e != nullptr) { - GB_ASSERT(e->flags & EntityFlag_ProcBodyChecked); - } - return true; - } - if (e != nullptr && (e->flags & EntityFlag_ProcBodyChecked) != 0) { - GB_ASSERT(pi->decl->proc_checked); - return true; + MUTEX_GUARD(&pi->decl->proc_checked_mutex); + + Entity *e = pi->decl->entity; + switch (pi->decl->proc_checked_state.load()) { + case ProcCheckedState_InProgress: + if (e) { + GB_ASSERT(global_procedure_body_in_worker_queue.load()); } - pi->decl->proc_checked = true; + return false; + case ProcCheckedState_Checked: if (e != nullptr) { - e->flags |= EntityFlag_ProcBodyChecked; + GB_ASSERT(e->flags & EntityFlag_ProcBodyChecked); } + return true; + case ProcCheckedState_Unchecked: + // okay + break; } + pi->decl->proc_checked_state.store(ProcCheckedState_InProgress); GB_ASSERT(pi->type->kind == Type_Proc); TypeProc *pt = &pi->type->Proc; @@ -5039,17 +5099,21 @@ gb_internal bool check_proc_info(Checker *c, ProcInfo *pi, UntypedExprInfoMap *u token = ast_token(pi->poly_def_node); } error(token, "Unspecialized polymorphic procedure '%.*s'", LIT(name)); + pi->decl->proc_checked_state.store(ProcCheckedState_Unchecked); return false; } if (pt->is_polymorphic && pt->is_poly_specialized) { + Entity *e = pi->decl->entity; + GB_ASSERT(e != nullptr); if ((e->flags & EntityFlag_Used) == 0) { // NOTE(bill, 2019-08-31): It was never used, don't check + // NOTE(bill, 2023-01-02): This may need to be checked again if it is used elsewhere? + pi->decl->proc_checked_state.store(ProcCheckedState_Unchecked); return false; } } - CheckerContext ctx = make_checker_context(c); defer (destroy_checker_context(&ctx)); reset_checker_context(&ctx, pi->file, untyped); @@ -5077,14 +5141,34 @@ gb_internal bool check_proc_info(Checker *c, ProcInfo *pi, UntypedExprInfoMap *u ctx.state_flags &= ~StateFlag_type_assert; } - check_proc_body(&ctx, pi->token, pi->decl, pi->type, pi->body); + bool body_was_checked = check_proc_body(&ctx, pi->token, pi->decl, pi->type, pi->body); + + if (body_was_checked) { + pi->decl->proc_checked_state.store(ProcCheckedState_Checked); + if (pi->body) { + Entity *e = pi->decl->entity; + if (e != nullptr) { + e->flags |= EntityFlag_ProcBodyChecked; + } + } + } else { + pi->decl->proc_checked_state.store(ProcCheckedState_Unchecked); + if (pi->body) { + Entity *e = pi->decl->entity; + if (e != nullptr) { + e->flags &= ~EntityFlag_ProcBodyChecked; + } + } + } + add_untyped_expressions(&c->info, ctx.untyped); + return true; } GB_STATIC_ASSERT(sizeof(isize) == sizeof(void *)); -gb_internal bool consume_proc_info_queue(Checker *c, ProcInfo *pi, UntypedExprInfoMap *untyped); +gb_internal bool consume_proc_info(Checker *c, ProcInfo *pi, UntypedExprInfoMap *untyped); gb_internal void check_unchecked_bodies(Checker *c) { // NOTE(2021-02-26, bill): Sanity checker @@ -5092,10 +5176,15 @@ gb_internal void check_unchecked_bodies(Checker *c) { // even ones which should not exist, due to the multithreaded nature of the parser // HACK TODO(2021-02-26, bill): Actually fix this race condition + GB_ASSERT(c->procs_to_check.count == 0); + UntypedExprInfoMap untyped = {}; map_init(&untyped, heap_allocator()); defer (map_destroy(&untyped)); + // use the `procs_to_check` array + global_procedure_body_in_worker_queue = false; + for (auto const &entry : c->info.minimum_dependency_set) { Entity *e = entry.ptr; if (e == nullptr || e->kind != Entity_Procedure) { @@ -5122,19 +5211,22 @@ gb_internal void check_unchecked_bodies(Checker *c) { } debugf("unchecked: %.*s\n", LIT(e->token.string)); - array_add(&c->procs_to_check, pi); + check_procedure_later(c, pi); } } - for (ProcInfo *pi : c->procs_to_check) { - Entity *e = pi->decl->entity; - if (consume_proc_info_queue(c, pi, &untyped)) { - add_dependency_to_set(c, e); - GB_ASSERT(e->flags & EntityFlag_ProcBodyChecked); + if (!global_procedure_body_in_worker_queue) { + for_array(i, c->procs_to_check) { + ProcInfo *pi = c->procs_to_check[i]; + consume_proc_info(c, pi, &untyped); } + array_clear(&c->procs_to_check); + } else { + thread_pool_wait(); } - thread_pool_wait(); + global_procedure_body_in_worker_queue = false; + global_after_checking_procedure_bodies = true; } gb_internal void check_test_procedures(Checker *c) { @@ -5172,8 +5264,15 @@ gb_internal void check_test_procedures(Checker *c) { gb_global std::atomic total_bodies_checked; -gb_internal bool consume_proc_info_queue(Checker *c, ProcInfo *pi, UntypedExprInfoMap *untyped) { +gb_internal bool consume_proc_info(Checker *c, ProcInfo *pi, UntypedExprInfoMap *untyped) { GB_ASSERT(pi->decl != nullptr); + switch (pi->decl->proc_checked_state.load()) { + case ProcCheckedState_InProgress: + return false; + case ProcCheckedState_Checked: + return true; + } + if (pi->decl->parent && pi->decl->parent->entity) { Entity *parent = pi->decl->parent->entity; // NOTE(bill): Only check a nested procedure if its parent's body has been checked first @@ -5187,9 +5286,11 @@ gb_internal bool consume_proc_info_queue(Checker *c, ProcInfo *pi, UntypedExprIn if (untyped) { map_clear(untyped); } - bool ok = check_proc_info(c, pi, untyped); - total_bodies_checked.fetch_add(1, std::memory_order_relaxed); - return ok; + if (check_proc_info(c, pi, untyped)) { + total_bodies_checked.fetch_add(1, std::memory_order_relaxed); + return true; + } + return false; } struct CheckProcedureBodyWorkerData { @@ -5218,9 +5319,11 @@ gb_internal WORKER_TASK_PROC(check_proc_info_worker_proc) { } } map_clear(untyped); - bool ok = check_proc_info(c, pi, untyped); - total_bodies_checked.fetch_add(1, std::memory_order_relaxed); - return !ok; + if (check_proc_info(c, pi, untyped)) { + total_bodies_checked.fetch_add(1, std::memory_order_relaxed); + return 0; + } + return 1; } @@ -5247,7 +5350,7 @@ gb_internal void check_procedure_bodies(Checker *c) { if (thread_count == 1) { UntypedExprInfoMap *untyped = &check_procedure_bodies_worker_data[0].untyped; for_array(i, c->procs_to_check) { - consume_proc_info_queue(c, c->procs_to_check[i], untyped); + consume_proc_info(c, c->procs_to_check[i], untyped); } array_clear(&c->procs_to_check); @@ -5266,9 +5369,6 @@ gb_internal void check_procedure_bodies(Checker *c) { thread_pool_wait(); - debugf("Total Procedure Bodies Checked: %td\n", total_bodies_checked.load(std::memory_order_relaxed)); - - global_procedure_body_in_worker_queue = false; } gb_internal void add_untyped_expressions(CheckerInfo *cinfo, UntypedExprInfoMap *untyped) { @@ -5662,9 +5762,6 @@ gb_internal void check_parsed_files(Checker *c) { TIME_SECTION("check test procedures"); check_test_procedures(c); - TIME_SECTION("check bodies have all been checked"); - check_unchecked_bodies(c); - TIME_SECTION("add type info for type definitions"); add_type_info_for_type_definitions(c); check_merge_queues_into_arrays(c); @@ -5672,6 +5769,12 @@ gb_internal void check_parsed_files(Checker *c) { TIME_SECTION("generate minimum dependency set"); generate_minimum_dependency_set(c, c->info.entry_point); + TIME_SECTION("check bodies have all been checked"); + check_unchecked_bodies(c); + + check_merge_queues_into_arrays(c); + + TIME_SECTION("check entry point"); if (build_context.build_mode == BuildMode_Executable && !build_context.no_entry_point && build_context.command_kind != Command_test) { Scope *s = c->info.init_scope; @@ -5694,11 +5797,39 @@ gb_internal void check_parsed_files(Checker *c) { } } + thread_pool_wait(); + GB_ASSERT(c->procs_to_check.count == 0); + + if (DEBUG_CHECK_ALL_PROCEDURES) { + UntypedExprInfoMap untyped = {}; + map_init(&untyped, heap_allocator()); + defer (map_destroy(&untyped)); + + for_array(i, c->info.all_procedures) { + ProcInfo *pi = c->info.all_procedures[i]; + GB_ASSERT(pi != nullptr); + GB_ASSERT(pi->decl != nullptr); + Entity *e = pi->decl->entity; + auto proc_checked_state = pi->decl->proc_checked_state.load(); + if (e && ((e->flags & EntityFlag_ProcBodyChecked) == 0)) { + if ((e->flags & EntityFlag_Used) != 0) { + debugf("%.*s :: %s\n", LIT(e->token.string), type_to_string(e->type)); + debugf("proc body unchecked\n"); + debugf("Checked State: %s\n\n", ProcCheckedState_strings[proc_checked_state]); + + consume_proc_info(c, pi, &untyped); + } + } + } + } + + debugf("Total Procedure Bodies Checked: %td\n", total_bodies_checked.load(std::memory_order_relaxed)); + TIME_SECTION("check unique package names"); check_unique_package_names(c); - TIME_SECTION("sanity checks"); + check_merge_queues_into_arrays(c); GB_ASSERT(c->info.entity_queue.count.load(std::memory_order_relaxed) == 0); GB_ASSERT(c->info.definition_queue.count.load(std::memory_order_relaxed) == 0); @@ -5717,5 +5848,6 @@ gb_internal void check_parsed_files(Checker *c) { } } + TIME_SECTION("type check finish"); } diff --git a/src/checker.hpp b/src/checker.hpp index eaad1fa63..37aff41b1 100644 --- a/src/checker.hpp +++ b/src/checker.hpp @@ -142,6 +142,20 @@ typedef DECL_ATTRIBUTE_PROC(DeclAttributeProc); gb_internal void check_decl_attributes(CheckerContext *c, Array const &attributes, DeclAttributeProc *proc, AttributeContext *ac); +enum ProcCheckedState : u8 { + ProcCheckedState_Unchecked, + ProcCheckedState_InProgress, + ProcCheckedState_Checked, + + ProcCheckedState_COUNT +}; + +char const *ProcCheckedState_strings[ProcCheckedState_COUNT] { + "Unchecked", + "In Progress", + "Checked", +}; + // DeclInfo is used to store information of certain declarations to allow for "any order" usage struct DeclInfo { DeclInfo * parent; // NOTE(bill): only used for procedure literals at the moment @@ -157,7 +171,7 @@ struct DeclInfo { Type * gen_proc_type; // Precalculated bool is_using; bool where_clauses_evaluated; - bool proc_checked; + std::atomic proc_checked_state; BlockingMutex proc_checked_mutex; isize defer_used; bool defer_use_checked; @@ -375,6 +389,9 @@ struct CheckerInfo { BlockingMutex load_file_mutex; StringMap load_file_cache; + + BlockingMutex all_procedures_mutex;; + Array all_procedures; }; struct CheckerContext { @@ -458,7 +475,7 @@ gb_internal Entity *entity_of_node(Ast *expr); gb_internal Entity *scope_lookup_current(Scope *s, String const &name); gb_internal Entity *scope_lookup (Scope *s, String const &name); gb_internal void scope_lookup_parent (Scope *s, String const &name, Scope **scope_, Entity **entity_); -gb_internal Entity *scope_insert (Scope *s, Entity *entity, bool use_mutex=true); +gb_internal Entity *scope_insert (Scope *s, Entity *entity); gb_internal void add_type_and_value (CheckerInfo *i, Ast *expression, AddressingMode mode, Type *type, ExactValue value); diff --git a/src/llvm_backend.cpp b/src/llvm_backend.cpp index 1c401552e..3e62f678a 100644 --- a/src/llvm_backend.cpp +++ b/src/llvm_backend.cpp @@ -2255,6 +2255,12 @@ gb_internal void lb_generate_code(lbGenerator *gen) { } } + if (build_context.ignore_llvm_build) { + gb_printf_err("LLVM SUCCESS!\n"); + gb_exit(1); + return; + } + if (do_threading && non_empty_module_count > 1) { for (auto const &entry : gen->modules) { lbModule *m = entry.value; diff --git a/src/llvm_backend.hpp b/src/llvm_backend.hpp index 9f7caa3bb..50fb5701f 100644 --- a/src/llvm_backend.hpp +++ b/src/llvm_backend.hpp @@ -301,6 +301,7 @@ struct lbProcedure { lbBlock * curr_block; lbTargetList * target_list; PtrMap direct_parameters; + PtrMap local_entity_map; Ast *curr_stmt; diff --git a/src/llvm_backend_expr.cpp b/src/llvm_backend_expr.cpp index d574caf4c..28a68b065 100644 --- a/src/llvm_backend_expr.cpp +++ b/src/llvm_backend_expr.cpp @@ -3404,7 +3404,11 @@ gb_internal lbAddr lb_build_addr_from_entity(lbProcedure *p, Entity *e, Ast *exp lbValue v = {}; - lbValue *found = map_get(&p->module->values, e); + lbValue *found = nullptr; + found = map_get(&p->local_entity_map, e); + if (found == nullptr) { + found = map_get(&p->module->values, e); + } if (found) { v = *found; } else if (e->kind == Entity_Variable && e->flags & EntityFlag_Using) { diff --git a/src/llvm_backend_general.cpp b/src/llvm_backend_general.cpp index 0508c6171..940c94a13 100644 --- a/src/llvm_backend_general.cpp +++ b/src/llvm_backend_general.cpp @@ -2714,7 +2714,6 @@ gb_internal lbValue lb_find_value_from_entity(lbModule *m, Entity *e) { return g; } } - GB_PANIC("\n\tError in: %s, missing value '%.*s'\n", token_pos_to_string(e->token.pos), LIT(e->token.string)); return {}; } @@ -2845,6 +2844,10 @@ gb_internal lbAddr lb_add_local(lbProcedure *p, Type *type, Entity *e, bool zero lb_mem_zero_ptr(p, ptr, type, alignment); } + if (e != nullptr) { + map_set(&p->local_entity_map, e, val); + } + return lb_addr(val); } diff --git a/src/llvm_backend_proc.cpp b/src/llvm_backend_proc.cpp index 384d29ca7..9691afebc 100644 --- a/src/llvm_backend_proc.cpp +++ b/src/llvm_backend_proc.cpp @@ -68,7 +68,7 @@ gb_internal lbProcedure *lb_create_procedure(lbModule *m, Entity *entity, bool i GB_ASSERT(entity != nullptr); GB_ASSERT(entity->kind == Entity_Procedure); if (!entity->Procedure.is_foreign) { - GB_ASSERT_MSG(entity->flags & EntityFlag_ProcBodyChecked, "%.*s :: %s", LIT(entity->token.string), type_to_string(entity->type)); + GB_ASSERT_MSG(entity->flags & EntityFlag_ProcBodyChecked, "%.*s :: %s (was parapoly: %d)", LIT(entity->token.string), type_to_string(entity->type), is_type_polymorphic(entity->type, true)); } String link_name = {}; @@ -487,6 +487,7 @@ gb_internal void lb_begin_procedure_body(lbProcedure *p) { lb_start_block(p, p->entry_block); map_init(&p->direct_parameters, heap_allocator()); + map_init(&p->local_entity_map, heap_allocator()); GB_ASSERT(p->type != nullptr); diff --git a/src/llvm_backend_stmt.cpp b/src/llvm_backend_stmt.cpp index 6400a8a9d..cdfb28aa7 100644 --- a/src/llvm_backend_stmt.cpp +++ b/src/llvm_backend_stmt.cpp @@ -1531,6 +1531,9 @@ gb_internal void lb_build_static_variables(lbProcedure *p, AstValueDecl *vd) { lbValue global_val = {global, alloc_type_pointer(e->type)}; lb_add_entity(p->module, e, global_val); lb_add_member(p->module, mangled_name, global_val); + if (e) { + map_set(&p->local_entity_map, e, global_val); + } } } gb_internal void lb_append_tuple_values(lbProcedure *p, Array *dst_values, lbValue src_value) { @@ -2188,9 +2191,10 @@ gb_internal void lb_build_stmt(lbProcedure *p, Ast *node) { for_array(i, vd->names) { Ast *name = vd->names[i]; if (!is_blank_ident(name)) { + GB_ASSERT(name->kind == Ast_Ident); Entity *e = entity_of_node(name); TokenPos pos = ast_token(name).pos; - GB_ASSERT_MSG(e != nullptr, "%s", token_pos_to_string(pos)); + GB_ASSERT_MSG(e != nullptr, "\n%s missing entity for %.*s", token_pos_to_string(pos), LIT(name->Ident.token.string)); if (e->flags & EntityFlag_Static) { // NOTE(bill): If one of the entities is static, they all are is_static = true; diff --git a/src/main.cpp b/src/main.cpp index 3ad0e160f..42d6f8e87 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -660,6 +660,7 @@ enum BuildFlagKind { // internal use only BuildFlag_InternalIgnoreLazy, + BuildFlag_InternalIgnoreLLVMBuild, #if defined(GB_SYSTEM_WINDOWS) BuildFlag_IgnoreVsSearch, @@ -832,6 +833,7 @@ gb_internal bool parse_build_flags(Array args) { add_flag(&build_flags, BuildFlag_ErrorPosStyle, str_lit("error-pos-style"), BuildFlagParam_String, Command_all); add_flag(&build_flags, BuildFlag_InternalIgnoreLazy, str_lit("internal-ignore-lazy"), BuildFlagParam_None, Command_all); + add_flag(&build_flags, BuildFlag_InternalIgnoreLLVMBuild, str_lit("internal-ignore-llvm-build"),BuildFlagParam_None, Command_all); #if defined(GB_SYSTEM_WINDOWS) add_flag(&build_flags, BuildFlag_IgnoreVsSearch, str_lit("ignore-vs-search"), BuildFlagParam_None, Command__does_build); @@ -1491,6 +1493,9 @@ gb_internal bool parse_build_flags(Array args) { case BuildFlag_InternalIgnoreLazy: build_context.ignore_lazy = true; break; + case BuildFlag_InternalIgnoreLLVMBuild: + build_context.ignore_llvm_build = true; + break; #if defined(GB_SYSTEM_WINDOWS) case BuildFlag_IgnoreVsSearch: { GB_ASSERT(value.kind == ExactValue_Invalid); -- cgit v1.2.3 From fa562ec5d60319f5cd7e85bb337bd21feb7ceeb8 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Mon, 2 Jan 2023 15:40:25 +0000 Subject: Remove unneeded `local_entity_map` --- src/llvm_backend.hpp | 1 - src/llvm_backend_expr.cpp | 6 +----- src/llvm_backend_general.cpp | 4 ---- src/llvm_backend_proc.cpp | 1 - src/llvm_backend_stmt.cpp | 3 --- 5 files changed, 1 insertion(+), 14 deletions(-) (limited to 'src/llvm_backend_general.cpp') diff --git a/src/llvm_backend.hpp b/src/llvm_backend.hpp index 50fb5701f..9f7caa3bb 100644 --- a/src/llvm_backend.hpp +++ b/src/llvm_backend.hpp @@ -301,7 +301,6 @@ struct lbProcedure { lbBlock * curr_block; lbTargetList * target_list; PtrMap direct_parameters; - PtrMap local_entity_map; Ast *curr_stmt; diff --git a/src/llvm_backend_expr.cpp b/src/llvm_backend_expr.cpp index 28a68b065..d574caf4c 100644 --- a/src/llvm_backend_expr.cpp +++ b/src/llvm_backend_expr.cpp @@ -3404,11 +3404,7 @@ gb_internal lbAddr lb_build_addr_from_entity(lbProcedure *p, Entity *e, Ast *exp lbValue v = {}; - lbValue *found = nullptr; - found = map_get(&p->local_entity_map, e); - if (found == nullptr) { - found = map_get(&p->module->values, e); - } + lbValue *found = map_get(&p->module->values, e); if (found) { v = *found; } else if (e->kind == Entity_Variable && e->flags & EntityFlag_Using) { diff --git a/src/llvm_backend_general.cpp b/src/llvm_backend_general.cpp index 940c94a13..22628e895 100644 --- a/src/llvm_backend_general.cpp +++ b/src/llvm_backend_general.cpp @@ -2844,10 +2844,6 @@ gb_internal lbAddr lb_add_local(lbProcedure *p, Type *type, Entity *e, bool zero lb_mem_zero_ptr(p, ptr, type, alignment); } - if (e != nullptr) { - map_set(&p->local_entity_map, e, val); - } - return lb_addr(val); } diff --git a/src/llvm_backend_proc.cpp b/src/llvm_backend_proc.cpp index 9691afebc..7245bdd80 100644 --- a/src/llvm_backend_proc.cpp +++ b/src/llvm_backend_proc.cpp @@ -487,7 +487,6 @@ gb_internal void lb_begin_procedure_body(lbProcedure *p) { lb_start_block(p, p->entry_block); map_init(&p->direct_parameters, heap_allocator()); - map_init(&p->local_entity_map, heap_allocator()); GB_ASSERT(p->type != nullptr); diff --git a/src/llvm_backend_stmt.cpp b/src/llvm_backend_stmt.cpp index cdfb28aa7..06abebc78 100644 --- a/src/llvm_backend_stmt.cpp +++ b/src/llvm_backend_stmt.cpp @@ -1531,9 +1531,6 @@ gb_internal void lb_build_static_variables(lbProcedure *p, AstValueDecl *vd) { lbValue global_val = {global, alloc_type_pointer(e->type)}; lb_add_entity(p->module, e, global_val); lb_add_member(p->module, mangled_name, global_val); - if (e) { - map_set(&p->local_entity_map, e, global_val); - } } } gb_internal void lb_append_tuple_values(lbProcedure *p, Array *dst_values, lbValue src_value) { -- cgit v1.2.3 From 600f2b7284b8974a18827242c18e790dab0cf06a Mon Sep 17 00:00:00 2001 From: gingerBill Date: Tue, 3 Jan 2023 11:53:59 +0000 Subject: Use heap_allocator for all hash set types --- src/build_settings.cpp | 2 +- src/check_builtin.cpp | 2 +- src/check_decl.cpp | 2 +- src/check_expr.cpp | 1 - src/check_stmt.cpp | 1 - src/checker.cpp | 24 +++++++----------------- src/llvm_backend_general.cpp | 2 +- src/llvm_backend_type.cpp | 2 +- src/main.cpp | 8 ++++---- src/parser.cpp | 2 +- src/ptr_set.cpp | 21 +++++++++++++++------ src/string_set.cpp | 18 +++++++++++++----- 12 files changed, 45 insertions(+), 40 deletions(-) (limited to 'src/llvm_backend_general.cpp') diff --git a/src/build_settings.cpp b/src/build_settings.cpp index 04d1ada93..75615a901 100644 --- a/src/build_settings.cpp +++ b/src/build_settings.cpp @@ -1369,7 +1369,7 @@ gb_internal bool init_build_paths(String init_filename) { // NOTE(Jeroen): We're pre-allocating BuildPathCOUNT slots so that certain paths are always at the same enumerated index. array_init(&bc->build_paths, permanent_allocator(), BuildPathCOUNT); - string_set_init(&bc->target_features_set, heap_allocator(), 1024); + string_set_init(&bc->target_features_set, 1024); // [BuildPathMainPackage] Turn given init path into a `Path`, which includes normalizing it into a full path. bc->build_paths[BuildPath_Main_Package] = path_from_string(ha, init_filename); diff --git a/src/check_builtin.cpp b/src/check_builtin.cpp index 99d956f5e..36dc9b7a1 100644 --- a/src/check_builtin.cpp +++ b/src/check_builtin.cpp @@ -3086,7 +3086,7 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As } } StringSet name_set = {}; - string_set_init(&name_set, heap_allocator(), 2*ce->args.count); + string_set_init(&name_set, 2*ce->args.count); for_array(i, ce->args) { String name = {}; diff --git a/src/check_decl.cpp b/src/check_decl.cpp index e3486924c..0c1a7c325 100644 --- a/src/check_decl.cpp +++ b/src/check_decl.cpp @@ -1235,7 +1235,7 @@ gb_internal void check_proc_group_decl(CheckerContext *ctx, Entity *&pg_entity, pg_entity->type = t_invalid; PtrSet entity_set = {}; - ptr_set_init(&entity_set, heap_allocator(), 2*pg->args.count); + ptr_set_init(&entity_set, 2*pg->args.count); for_array(i, pg->args) { Ast *arg = pg->args[i]; diff --git a/src/check_expr.cpp b/src/check_expr.cpp index 3c998fc44..7a00b5353 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -196,7 +196,6 @@ gb_internal void check_did_you_mean_objc_entity(String const &name, Entity *e, b MUTEX_GUARD(objc_metadata->mutex); StringSet set = {}; - string_set_init(&set, heap_allocator()); defer (string_set_destroy(&set)); populate_check_did_you_mean_objc_entity(&set, e, is_type); diff --git a/src/check_stmt.cpp b/src/check_stmt.cpp index cf111e84c..945ba8f02 100644 --- a/src/check_stmt.cpp +++ b/src/check_stmt.cpp @@ -1185,7 +1185,6 @@ gb_internal void check_type_switch_stmt(CheckerContext *ctx, Ast *node, u32 mod_ } PtrSet seen = {}; - ptr_set_init(&seen, heap_allocator()); defer (ptr_set_destroy(&seen)); for_array(i, bs->stmts) { diff --git a/src/checker.cpp b/src/checker.cpp index ccd0f3627..8da659461 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -72,7 +72,7 @@ gb_internal void entity_graph_node_set_destroy(EntityGraphNodeSet *s) { gb_internal void entity_graph_node_set_add(EntityGraphNodeSet *s, EntityGraphNode *n) { if (s->hashes.data == nullptr) { - ptr_set_init(s, heap_allocator()); + ptr_set_init(s); } ptr_set_add(s, n); } @@ -118,15 +118,10 @@ gb_internal void entity_graph_node_swap(EntityGraphNode **data, isize i, isize j gb_internal void import_graph_node_set_destroy(ImportGraphNodeSet *s) { - if (s->hashes.data != nullptr) { - ptr_set_destroy(s); - } + ptr_set_destroy(s); } gb_internal void import_graph_node_set_add(ImportGraphNodeSet *s, ImportGraphNode *n) { - if (s->hashes.data == nullptr) { - ptr_set_init(s, heap_allocator()); - } ptr_set_add(s, n); } @@ -185,8 +180,8 @@ gb_internal void init_decl_info(DeclInfo *d, Scope *scope, DeclInfo *parent) { gb_zero_item(d); d->parent = parent; d->scope = scope; - ptr_set_init(&d->deps, heap_allocator()); - ptr_set_init(&d->type_info_deps, heap_allocator()); + ptr_set_init(&d->deps); + ptr_set_init(&d->type_info_deps); array_init (&d->labels, heap_allocator()); } @@ -227,7 +222,7 @@ gb_internal Scope *create_scope(CheckerInfo *info, Scope *parent, isize init_ele Scope *s = gb_alloc_item(permanent_allocator(), Scope); s->parent = parent; string_map_init(&s->elements, heap_allocator(), init_elements_capacity); - ptr_set_init(&s->imported, heap_allocator(), 0); + ptr_set_init(&s->imported, 0); if (parent != nullptr && parent != builtin_pkg->scope) { Scope *prev_head_child = parent->head_child.exchange(s, std::memory_order_acq_rel); @@ -2270,8 +2265,8 @@ gb_internal void generate_minimum_dependency_set(Checker *c, Entity *start) { isize entity_count = c->info.entities.count; isize min_dep_set_cap = next_pow2_isize(entity_count*4); // empirically determined factor - ptr_set_init(&c->info.minimum_dependency_set, heap_allocator(), min_dep_set_cap); - ptr_set_init(&c->info.minimum_dependency_type_info_set, heap_allocator()); + ptr_set_init(&c->info.minimum_dependency_set, min_dep_set_cap); + ptr_set_init(&c->info.minimum_dependency_type_info_set); #define FORCE_ADD_RUNTIME_ENTITIES(condition, ...) do { \ if (condition) { \ @@ -3388,7 +3383,6 @@ gb_internal void check_decl_attributes(CheckerContext *c, Array const &at } StringSet set = {}; - string_set_init(&set, heap_allocator()); defer (string_set_destroy(&set)); for_array(i, attributes) { @@ -4759,7 +4753,6 @@ gb_internal void check_import_entities(Checker *c) { auto pq = priority_queue_create(dep_graph, import_graph_node_cmp, import_graph_node_swap); PtrSet emitted = {}; - ptr_set_init(&emitted, heap_allocator()); defer (ptr_set_destroy(&emitted)); Array package_order = {}; @@ -4773,7 +4766,6 @@ gb_internal void check_import_entities(Checker *c) { if (n->dep_count > 0) { PtrSet visited = {}; - ptr_set_init(&visited, heap_allocator()); defer (ptr_set_destroy(&visited)); auto path = find_import_path(c, pkg, pkg, &visited); @@ -4927,7 +4919,6 @@ gb_internal Array find_entity_path(Entity *start, Entity *end, PtrSet< bool made_visited = false; if (visited == nullptr) { made_visited = true; - ptr_set_init(&visited_, heap_allocator()); visited = &visited_; } defer (if (made_visited) { @@ -4990,7 +4981,6 @@ gb_internal void calculate_global_init_order(Checker *c) { auto pq = priority_queue_create(dep_graph, entity_graph_node_cmp, entity_graph_node_swap); PtrSet emitted = {}; - ptr_set_init(&emitted, heap_allocator()); defer (ptr_set_destroy(&emitted)); TIME_SECTION("calculate_global_init_order: queue sort"); diff --git a/src/llvm_backend_general.cpp b/src/llvm_backend_general.cpp index 22628e895..75675474a 100644 --- a/src/llvm_backend_general.cpp +++ b/src/llvm_backend_general.cpp @@ -133,7 +133,7 @@ gb_internal bool lb_init_generator(lbGenerator *gen, Checker *c) { array_init(&gen->foreign_libraries, heap_allocator(), 0, 1024); - ptr_set_init(&gen->foreign_libraries_set, heap_allocator(), 1024); + ptr_set_init(&gen->foreign_libraries_set, 1024); if (USE_SEPARATE_MODULES) { for (auto const &entry : gen->info->packages) { diff --git a/src/llvm_backend_type.cpp b/src/llvm_backend_type.cpp index 26bb614e6..c306cdead 100644 --- a/src/llvm_backend_type.cpp +++ b/src/llvm_backend_type.cpp @@ -2,7 +2,7 @@ gb_internal isize lb_type_info_index(CheckerInfo *info, Type *type, bool err_on_ auto *set = &info->minimum_dependency_type_info_set; isize index = type_info_index(info, type, err_on_not_found); if (index >= 0) { - isize i = ptr_entry_index(set, index); + isize i = ptr_set_entry_index(set, index); if (i >= 0) { return i+1; } diff --git a/src/main.cpp b/src/main.cpp index ad9d6b0ef..91dcbdb01 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -212,11 +212,11 @@ gb_internal i32 linker_stage(lbGenerator *gen) { StringSet libs = {}; - string_set_init(&libs, heap_allocator(), 64); + string_set_init(&libs, 64); defer (string_set_destroy(&libs)); StringSet asm_files = {}; - string_set_init(&asm_files, heap_allocator(), 64); + string_set_init(&asm_files, 64); defer (string_set_destroy(&asm_files)); for_array(j, gen->foreign_libraries) { @@ -371,7 +371,7 @@ gb_internal i32 linker_stage(lbGenerator *gen) { defer (gb_string_free(lib_str)); StringSet libs = {}; - string_set_init(&libs, heap_allocator(), 64); + string_set_init(&libs, 64); defer (string_set_destroy(&libs)); for_array(j, gen->foreign_libraries) { @@ -2518,7 +2518,7 @@ int main(int arg_count, char const **arg_ptr) { map_init(&build_context.defined_values, heap_allocator()); build_context.extra_packages.allocator = heap_allocator(); - string_set_init(&build_context.test_names, heap_allocator()); + string_set_init(&build_context.test_names); Array args = setup_args(arg_count, arg_ptr); diff --git a/src/parser.cpp b/src/parser.cpp index 4d2a8ecf4..046469c16 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -4854,7 +4854,7 @@ gb_internal void destroy_ast_file(AstFile *f) { gb_internal bool init_parser(Parser *p) { GB_ASSERT(p != nullptr); - string_set_init(&p->imported_files, heap_allocator()); + string_set_init(&p->imported_files); array_init(&p->packages, heap_allocator()); return true; } diff --git a/src/ptr_set.cpp b/src/ptr_set.cpp index 9ecf1043e..affde5c2f 100644 --- a/src/ptr_set.cpp +++ b/src/ptr_set.cpp @@ -6,11 +6,11 @@ struct PtrSetEntry { template struct PtrSet { - Slice hashes; + Slice hashes; Array> entries; }; -template gb_internal void ptr_set_init (PtrSet *s, gbAllocator a, isize capacity = 16); +template gb_internal void ptr_set_init (PtrSet *s, isize capacity = 16); template gb_internal void ptr_set_destroy(PtrSet *s); template gb_internal T ptr_set_add (PtrSet *s, T ptr); template gb_internal bool ptr_set_update (PtrSet *s, T ptr); // returns true if it previously existed @@ -21,15 +21,18 @@ template gb_internal void ptr_set_grow (PtrSet *s); template gb_internal void ptr_set_rehash (PtrSet *s, isize new_count); template gb_internal void ptr_set_reserve(PtrSet *h, isize cap); +gb_internal gbAllocator ptr_set_allocator(void) { + return heap_allocator(); +} template -gb_internal void ptr_set_init(PtrSet *s, gbAllocator a, isize capacity) { +gb_internal void ptr_set_init(PtrSet *s, isize capacity) { if (capacity != 0) { capacity = next_pow2_isize(gb_max(16, capacity)); } - slice_init(&s->hashes, a, capacity); - array_init(&s->entries, a, 0, capacity); + slice_init(&s->hashes, ptr_set_allocator(), capacity); + array_init(&s->entries, ptr_set_allocator(), 0, capacity); for (isize i = 0; i < capacity; i++) { s->hashes.data[i] = MAP_SENTINEL; } @@ -37,6 +40,9 @@ gb_internal void ptr_set_init(PtrSet *s, gbAllocator a, isize capacity) { template gb_internal void ptr_set_destroy(PtrSet *s) { + if (s->entries.allocator.proc == nullptr) { + s->entries.allocator = ptr_set_allocator(); + } slice_free(&s->hashes, s->entries.allocator); array_free(&s->entries); } @@ -118,6 +124,9 @@ gb_internal void ptr_set_reset_entries(PtrSet *s) { template gb_internal void ptr_set_reserve(PtrSet *s, isize cap) { + if (s->entries.allocator.proc == nullptr) { + s->entries.allocator = ptr_set_allocator(); + } array_reserve(&s->entries, cap); if (s->entries.count*2 < s->hashes.count) { return; @@ -139,7 +148,7 @@ gb_internal gb_inline bool ptr_set_exists(PtrSet *s, T ptr) { } template -gb_internal gb_inline isize ptr_entry_index(PtrSet *s, T ptr) { +gb_internal gb_inline isize ptr_set_entry_index(PtrSet *s, T ptr) { isize index = ptr_set__find(s, ptr).entry_index; if (index != MAP_SENTINEL) { return index; diff --git a/src/string_set.cpp b/src/string_set.cpp index 1c97d253e..753afa9bf 100644 --- a/src/string_set.cpp +++ b/src/string_set.cpp @@ -10,7 +10,7 @@ struct StringSet { }; -gb_internal void string_set_init (StringSet *s, gbAllocator a, isize capacity = 16); +gb_internal void string_set_init (StringSet *s, isize capacity = 16); gb_internal void string_set_destroy(StringSet *s); gb_internal void string_set_add (StringSet *s, String const &str); gb_internal bool string_set_update (StringSet *s, String const &str); // returns true if it previously existed @@ -20,18 +20,24 @@ gb_internal void string_set_clear (StringSet *s); gb_internal void string_set_grow (StringSet *s); gb_internal void string_set_rehash (StringSet *s, isize new_count); +gb_internal gbAllocator string_set_allocator(void) { + return heap_allocator(); +} -gb_internal gb_inline void string_set_init(StringSet *s, gbAllocator a, isize capacity) { +gb_internal gb_inline void string_set_init(StringSet *s, isize capacity) { capacity = next_pow2_isize(gb_max(16, capacity)); - slice_init(&s->hashes, a, capacity); - array_init(&s->entries, a, 0, capacity); + slice_init(&s->hashes, string_set_allocator(), capacity); + array_init(&s->entries, string_set_allocator(), 0, capacity); for (isize i = 0; i < capacity; i++) { s->hashes.data[i] = MAP_SENTINEL; } } gb_internal gb_inline void string_set_destroy(StringSet *s) { + if (s->entries.allocator.proc == nullptr) { + s->entries.allocator = string_set_allocator(); + } slice_free(&s->hashes, s->entries.allocator); array_free(&s->entries); } @@ -106,6 +112,9 @@ gb_internal void string_set_reset_entries(StringSet *s) { } gb_internal void string_set_reserve(StringSet *s, isize cap) { + if (s->entries.allocator.proc == nullptr) { + s->entries.allocator = string_set_allocator(); + } array_reserve(&s->entries, cap); if (s->entries.count*2 < s->hashes.count) { return; @@ -217,7 +226,6 @@ gb_internal gb_inline void string_set_clear(StringSet *s) { } - gb_internal StringSetEntry *begin(StringSet &m) { return m.entries.data; } -- cgit v1.2.3 From 252be0fb417f9cdde5e9c4b348cd995a20433aea Mon Sep 17 00:00:00 2001 From: gingerBill Date: Tue, 3 Jan 2023 11:59:52 +0000 Subject: Make all maps use heap allocator implicitly --- src/check_builtin.cpp | 2 +- src/check_expr.cpp | 3 +-- src/check_stmt.cpp | 1 - src/checker.cpp | 33 +++++++++++++++------------------ src/common.cpp | 2 +- src/docs_writer.cpp | 11 +++++------ src/llvm_backend_general.cpp | 44 ++++++++++++++++++++++---------------------- src/llvm_backend_proc.cpp | 10 +++++----- src/main.cpp | 2 +- src/ptr_map.cpp | 18 ++++++++++++++---- src/string_map.cpp | 18 ++++++++++++++---- 11 files changed, 79 insertions(+), 65 deletions(-) (limited to 'src/llvm_backend_general.cpp') diff --git a/src/check_builtin.cpp b/src/check_builtin.cpp index 36dc9b7a1..af196234e 100644 --- a/src/check_builtin.cpp +++ b/src/check_builtin.cpp @@ -1110,7 +1110,7 @@ gb_internal bool cache_load_file_directive(CheckerContext *c, Ast *call, String new_cache->path = path; new_cache->data = data; new_cache->file_error = file_error; - string_map_init(&new_cache->hashes, heap_allocator(), 32); + string_map_init(&new_cache->hashes, 32); string_map_set(&c->info->load_file_cache, path, new_cache); if (cache_) *cache_ = new_cache; } else { diff --git a/src/check_expr.cpp b/src/check_expr.cpp index 7a00b5353..030bfb8e6 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -5753,7 +5753,7 @@ gb_internal CallArgumentData check_call_arguments(CheckerContext *c, Operand *op // in order to improve the type inference system StringMap type_hint_map = {}; // Key: String - string_map_init(&type_hint_map, heap_allocator(), 2*args.count); + string_map_init(&type_hint_map, 2*args.count); defer (string_map_destroy(&type_hint_map)); Type *ptype = nullptr; @@ -8283,7 +8283,6 @@ gb_internal ExprKind check_compound_literal(CheckerContext *c, Operand *o, Ast * bool is_partial = cl->tag && (cl->tag->BasicDirective.name.string == "partial"); SeenMap seen = {}; // NOTE(bill): Multimap, Key: ExactValue - map_init(&seen, heap_allocator()); defer (map_destroy(&seen)); if (cl->elems.count > 0 && cl->elems[0]->kind == Ast_FieldValue) { diff --git a/src/check_stmt.cpp b/src/check_stmt.cpp index 945ba8f02..7192b16b5 100644 --- a/src/check_stmt.cpp +++ b/src/check_stmt.cpp @@ -929,7 +929,6 @@ gb_internal void check_switch_stmt(CheckerContext *ctx, Ast *node, u32 mod_flags } SeenMap seen = {}; // NOTE(bill): Multimap, Key: ExactValue - map_init(&seen, heap_allocator()); defer (map_destroy(&seen)); for_array(stmt_index, bs->stmts) { diff --git a/src/checker.cpp b/src/checker.cpp index 8da659461..8779d9d45 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -221,7 +221,7 @@ gb_internal DeclInfo *make_decl_info(Scope *scope, DeclInfo *parent) { gb_internal Scope *create_scope(CheckerInfo *info, Scope *parent, isize init_elements_capacity=DEFAULT_SCOPE_CAPACITY) { Scope *s = gb_alloc_item(permanent_allocator(), Scope); s->parent = parent; - string_map_init(&s->elements, heap_allocator(), init_elements_capacity); + string_map_init(&s->elements, init_elements_capacity); ptr_set_init(&s->imported, 0); if (parent != nullptr && parent != builtin_pkg->scope) { @@ -1135,14 +1135,14 @@ gb_internal void init_checker_info(CheckerInfo *i) { array_init(&i->definitions, a); array_init(&i->entities, a); - map_init(&i->global_untyped, a); - string_map_init(&i->foreigns, a); - map_init(&i->gen_procs, a); - map_init(&i->gen_types, a); + map_init(&i->global_untyped); + string_map_init(&i->foreigns); + map_init(&i->gen_procs); + map_init(&i->gen_types); array_init(&i->type_info_types, a); - map_init(&i->type_info_map, a); - string_map_init(&i->files, a); - string_map_init(&i->packages, a); + map_init(&i->type_info_map); + string_map_init(&i->files); + string_map_init(&i->packages); array_init(&i->variable_init_order, a); array_init(&i->testing_procedures, a, 0, 0); array_init(&i->init_procedures, a, 0, 0); @@ -1160,8 +1160,8 @@ gb_internal void init_checker_info(CheckerInfo *i) { mpmc_init(&i->intrinsics_entry_point_usage, a, 1<<10); // just waste some memory here, even if it probably never used - map_init(&i->objc_msgSend_types, a); - string_map_init(&i->load_file_cache, a); + map_init(&i->objc_msgSend_types); + string_map_init(&i->load_file_cache); array_init(&i->all_procedures, heap_allocator()); @@ -2490,7 +2490,7 @@ gb_internal bool is_entity_a_dependency(Entity *e) { gb_internal Array generate_entity_dependency_graph(CheckerInfo *info, gbAllocator allocator) { PtrMap M = {}; - map_init(&M, allocator, info->entities.count); + map_init(&M, info->entities.count); defer (map_destroy(&M)); for_array(i, info->entities) { Entity *e = info->entities[i]; @@ -4200,7 +4200,7 @@ gb_internal void add_import_dependency_node(Checker *c, Ast *decl, PtrMap generate_import_dependency_graph(Checker *c) { PtrMap M = {}; - map_init(&M, heap_allocator(), 2*c->parser->packages.count); + map_init(&M, 2*c->parser->packages.count); defer (map_destroy(&M)); for_array(i, c->parser->packages) { @@ -4688,7 +4688,7 @@ gb_internal void check_collect_entities_all(Checker *c) { auto *wd = &collect_entity_worker_data[i]; wd->c = c; wd->ctx = make_checker_context(c); - map_init(&wd->untyped, heap_allocator()); + map_init(&wd->untyped); } for (auto const &entry : c->info.files.entries) { @@ -4804,7 +4804,6 @@ gb_internal void check_import_entities(Checker *c) { CheckerContext ctx = make_checker_context(c); UntypedExprInfoMap untyped = {}; - map_init(&untyped, heap_allocator()); defer (map_destroy(&untyped)); isize min_pkg_index = 0; @@ -5159,7 +5158,6 @@ gb_internal void check_unchecked_bodies(Checker *c) { GB_ASSERT(c->procs_to_check.count == 0); UntypedExprInfoMap untyped = {}; - map_init(&untyped, heap_allocator()); defer (map_destroy(&untyped)); // use the `procs_to_check` array @@ -5212,7 +5210,6 @@ gb_internal void check_unchecked_bodies(Checker *c) { gb_internal void check_safety_all_procedures_for_unchecked(Checker *c) { GB_ASSERT(DEBUG_CHECK_ALL_PROCEDURES); UntypedExprInfoMap untyped = {}; - map_init(&untyped, heap_allocator()); defer (map_destroy(&untyped)); @@ -5345,7 +5342,7 @@ gb_internal void check_procedure_bodies(Checker *c) { for (isize i = 0; i < thread_count; i++) { check_procedure_bodies_worker_data[i].c = c; - map_init(&check_procedure_bodies_worker_data[i].untyped, heap_allocator()); + map_init(&check_procedure_bodies_worker_data[i].untyped); } defer (for (isize i = 0; i < thread_count; i++) { @@ -5545,7 +5542,7 @@ gb_internal void check_deferred_procedures(Checker *c) { gb_internal void check_unique_package_names(Checker *c) { StringMap pkgs = {}; // Key: package name - string_map_init(&pkgs, heap_allocator(), 2*c->info.packages.entries.count); + string_map_init(&pkgs, 2*c->info.packages.entries.count); defer (string_map_destroy(&pkgs)); for (auto const &entry : c->info.packages) { diff --git a/src/common.cpp b/src/common.cpp index 3b6ea59e8..199a263a1 100644 --- a/src/common.cpp +++ b/src/common.cpp @@ -373,7 +373,7 @@ gb_internal char const *string_intern(String const &string) { } gb_internal void init_string_interner(void) { - map_init(&string_intern_map, heap_allocator()); + map_init(&string_intern_map); } diff --git a/src/docs_writer.cpp b/src/docs_writer.cpp index bab97158d..2aefe29eb 100644 --- a/src/docs_writer.cpp +++ b/src/docs_writer.cpp @@ -53,13 +53,12 @@ gb_internal void odin_doc_writer_item_tracker_init(OdinDocWriterItemTracker * gb_internal void odin_doc_writer_prepare(OdinDocWriter *w) { w->state = OdinDocWriterState_Preparing; - gbAllocator a = heap_allocator(); - string_map_init(&w->string_cache, a); + string_map_init(&w->string_cache); - map_init(&w->file_cache, a); - map_init(&w->pkg_cache, a); - map_init(&w->entity_cache, a); - map_init(&w->type_cache, a); + map_init(&w->file_cache); + map_init(&w->pkg_cache); + map_init(&w->entity_cache); + map_init(&w->type_cache); odin_doc_writer_item_tracker_init(&w->files, 1); odin_doc_writer_item_tracker_init(&w->pkgs, 1); diff --git a/src/llvm_backend_general.cpp b/src/llvm_backend_general.cpp index 75675474a..a849929f0 100644 --- a/src/llvm_backend_general.cpp +++ b/src/llvm_backend_general.cpp @@ -55,30 +55,30 @@ gb_internal void lb_init_module(lbModule *m, Checker *c) { } gbAllocator a = heap_allocator(); - map_init(&m->types, a); - map_init(&m->func_raw_types, a); - map_init(&m->struct_field_remapping, a); - map_init(&m->values, a); - map_init(&m->soa_values, a); - string_map_init(&m->members, a); - map_init(&m->procedure_values, a); - string_map_init(&m->procedures, a); - string_map_init(&m->const_strings, a); - map_init(&m->function_type_map, a); - map_init(&m->equal_procs, a); - map_init(&m->hasher_procs, a); - map_init(&m->map_get_procs, a); - map_init(&m->map_set_procs, a); + map_init(&m->types); + map_init(&m->func_raw_types); + map_init(&m->struct_field_remapping); + map_init(&m->values); + map_init(&m->soa_values); + string_map_init(&m->members); + map_init(&m->procedure_values); + string_map_init(&m->procedures); + string_map_init(&m->const_strings); + map_init(&m->function_type_map); + map_init(&m->equal_procs); + map_init(&m->hasher_procs); + map_init(&m->map_get_procs); + map_init(&m->map_set_procs); array_init(&m->procedures_to_generate, a, 0, 1024); array_init(&m->missing_procedures_to_check, a, 0, 16); - map_init(&m->debug_values, a); + map_init(&m->debug_values); array_init(&m->debug_incomplete_types, a, 0, 1024); - string_map_init(&m->objc_classes, a); - string_map_init(&m->objc_selectors, a); + string_map_init(&m->objc_classes); + string_map_init(&m->objc_selectors); - map_init(&m->map_info_map, a, 0); - map_init(&m->map_cell_info_map, a, 0); + map_init(&m->map_info_map, 0); + map_init(&m->map_cell_info_map, 0); } @@ -127,9 +127,9 @@ gb_internal bool lb_init_generator(lbGenerator *gen, Checker *c) { gen->info = &c->info; - map_init(&gen->modules, permanent_allocator(), gen->info->packages.entries.count*2); - map_init(&gen->modules_through_ctx, permanent_allocator(), gen->info->packages.entries.count*2); - map_init(&gen->anonymous_proc_lits, heap_allocator(), 1024); + map_init(&gen->modules, gen->info->packages.entries.count*2); + map_init(&gen->modules_through_ctx, gen->info->packages.entries.count*2); + map_init(&gen->anonymous_proc_lits, 1024); array_init(&gen->foreign_libraries, heap_allocator(), 0, 1024); diff --git a/src/llvm_backend_proc.cpp b/src/llvm_backend_proc.cpp index 7245bdd80..c66462bc1 100644 --- a/src/llvm_backend_proc.cpp +++ b/src/llvm_backend_proc.cpp @@ -119,9 +119,9 @@ gb_internal lbProcedure *lb_create_procedure(lbModule *m, Entity *entity, bool i p->branch_blocks.allocator = a; p->context_stack.allocator = a; p->scope_stack.allocator = a; - map_init(&p->selector_values, a, 0); - map_init(&p->selector_addr, a, 0); - map_init(&p->tuple_fix_map, a, 0); + map_init(&p->selector_values, 0); + map_init(&p->selector_addr, 0); + map_init(&p->tuple_fix_map, 0); if (p->is_foreign) { lb_add_foreign_library_path(p->module, entity->Procedure.foreign_library); @@ -345,7 +345,7 @@ gb_internal lbProcedure *lb_create_dummy_procedure(lbModule *m, String link_name p->blocks.allocator = a; p->branch_blocks.allocator = a; p->context_stack.allocator = a; - map_init(&p->tuple_fix_map, a, 0); + map_init(&p->tuple_fix_map, 0); char *c_link_name = alloc_cstring(permanent_allocator(), p->name); @@ -486,7 +486,7 @@ gb_internal void lb_begin_procedure_body(lbProcedure *p) { p->entry_block = lb_create_block(p, "entry", true); lb_start_block(p, p->entry_block); - map_init(&p->direct_parameters, heap_allocator()); + map_init(&p->direct_parameters); GB_ASSERT(p->type != nullptr); diff --git a/src/main.cpp b/src/main.cpp index 91dcbdb01..7ac78241e 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2516,7 +2516,7 @@ int main(int arg_count, char const **arg_ptr) { add_library_collection(str_lit("core"), get_fullpath_relative(heap_allocator(), odin_root_dir(), str_lit("core"))); add_library_collection(str_lit("vendor"), get_fullpath_relative(heap_allocator(), odin_root_dir(), str_lit("vendor"))); - map_init(&build_context.defined_values, heap_allocator()); + map_init(&build_context.defined_values); build_context.extra_packages.allocator = heap_allocator(); string_set_init(&build_context.test_names); diff --git a/src/ptr_map.cpp b/src/ptr_map.cpp index 434680e91..083cd6697 100644 --- a/src/ptr_map.cpp +++ b/src/ptr_map.cpp @@ -46,7 +46,7 @@ gb_internal gb_inline u32 ptr_map_hash_key(void const *key) { } -template gb_internal void map_init (PtrMap *h, gbAllocator a, isize capacity = 16); +template gb_internal void map_init (PtrMap *h, isize capacity = 16); template gb_internal void map_destroy (PtrMap *h); template gb_internal V * map_get (PtrMap *h, K key); template gb_internal void map_set (PtrMap *h, K key, V const &value); @@ -68,11 +68,15 @@ template gb_internal void multi_map_remove (PtrMap< template gb_internal void multi_map_remove_all(PtrMap *h, K key); #endif +gb_internal gbAllocator map_allocator(void) { + return heap_allocator(); +} + template -gb_internal gb_inline void map_init(PtrMap *h, gbAllocator a, isize capacity) { +gb_internal gb_inline void map_init(PtrMap *h, isize capacity) { capacity = next_pow2_isize(capacity); - slice_init(&h->hashes, a, capacity); - array_init(&h->entries, a, 0, capacity); + slice_init(&h->hashes, map_allocator(), capacity); + array_init(&h->entries, map_allocator(), 0, capacity); for (isize i = 0; i < capacity; i++) { h->hashes.data[i] = MAP_SENTINEL; } @@ -80,6 +84,9 @@ gb_internal gb_inline void map_init(PtrMap *h, gbAllocator a, isize capaci template gb_internal gb_inline void map_destroy(PtrMap *h) { + if (h->entries.allocator.proc == nullptr) { + h->entries.allocator = map_allocator(); + } slice_free(&h->hashes, h->entries.allocator); array_free(&h->entries); } @@ -162,6 +169,9 @@ gb_internal void map_reset_entries(PtrMap *h) { template gb_internal void map_reserve(PtrMap *h, isize cap) { + if (h->entries.allocator.proc == nullptr) { + h->entries.allocator = map_allocator(); + } array_reserve(&h->entries, cap); if (h->entries.count*2 < h->hashes.count) { return; diff --git a/src/string_map.cpp b/src/string_map.cpp index 9f9374ece..b5db63e90 100644 --- a/src/string_map.cpp +++ b/src/string_map.cpp @@ -35,7 +35,7 @@ struct StringMap { }; -template gb_internal void string_map_init (StringMap *h, gbAllocator a, isize capacity = 16); +template gb_internal void string_map_init (StringMap *h, isize capacity = 16); template gb_internal void string_map_destroy (StringMap *h); template gb_internal T * string_map_get (StringMap *h, char const *key); @@ -56,11 +56,15 @@ template gb_internal void string_map_grow (StringMap template gb_internal void string_map_rehash (StringMap *h, isize new_count); template gb_internal void string_map_reserve (StringMap *h, isize cap); +gb_internal gbAllocator string_map_allocator(void) { + return heap_allocator(); +} + template -gb_internal gb_inline void string_map_init(StringMap *h, gbAllocator a, isize capacity) { +gb_internal gb_inline void string_map_init(StringMap *h, isize capacity) { capacity = next_pow2_isize(capacity); - slice_init(&h->hashes, a, capacity); - array_init(&h->entries, a, 0, capacity); + slice_init(&h->hashes, string_map_allocator(), capacity); + array_init(&h->entries, string_map_allocator(), 0, capacity); for (isize i = 0; i < capacity; i++) { h->hashes.data[i] = MAP_SENTINEL; } @@ -68,6 +72,9 @@ gb_internal gb_inline void string_map_init(StringMap *h, gbAllocator a, isize template gb_internal gb_inline void string_map_destroy(StringMap *h) { + if (h->entries.allocator.proc == nullptr) { + h->entries.allocator = string_map_allocator(); + } slice_free(&h->hashes, h->entries.allocator); array_free(&h->entries); } @@ -147,6 +154,9 @@ gb_internal void string_map_reset_entries(StringMap *h) { template gb_internal void string_map_reserve(StringMap *h, isize cap) { + if (h->entries.allocator.proc == nullptr) { + h->entries.allocator = string_map_allocator(); + } array_reserve(&h->entries, cap); if (h->entries.count*2 < h->hashes.count) { return; -- cgit v1.2.3 From 213a0499a1964e0bc5d2c48cd3b4450b45f59314 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Thu, 5 Jan 2023 12:29:16 +0000 Subject: Begin multithreading the llvm backend when `-use-separate-modules` is enabled --- src/llvm_backend.cpp | 46 +++++++++++++++++++++++++++++--------------- src/llvm_backend.hpp | 3 +++ src/llvm_backend_general.cpp | 21 +++++++++++++++++--- src/llvm_backend_stmt.cpp | 2 +- 4 files changed, 53 insertions(+), 19 deletions(-) (limited to 'src/llvm_backend_general.cpp') diff --git a/src/llvm_backend.cpp b/src/llvm_backend.cpp index 192e5cc56..f3c4dd50d 100644 --- a/src/llvm_backend.cpp +++ b/src/llvm_backend.cpp @@ -730,6 +730,8 @@ gb_internal lbValue lb_map_set_proc_for_type(lbModule *m, Type *type) { gb_internal lbValue lb_generate_anonymous_proc_lit(lbModule *m, String const &prefix_name, Ast *expr, lbProcedure *parent) { + MUTEX_GUARD(&m->gen->anonymous_proc_lits_mutex); + lbProcedure **found = map_get(&m->gen->anonymous_proc_lits, expr); if (found) { return lb_find_procedure_value_from_entity(m, (*found)->entity); @@ -1526,6 +1528,10 @@ 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); @@ -2155,29 +2161,47 @@ gb_internal void lb_generate_code(lbGenerator *gen) { } } + isize non_empty_module_count = 0; + for (auto const &entry : gen->modules) { + lbModule *m = entry.value; + if (!lb_is_module_empty(m)) { + non_empty_module_count += 1; + } + } + if (non_empty_module_count <= 1) { + do_threading = false; + } TIME_SECTION("LLVM Function Pass"); for (auto const &entry : gen->modules) { lbModule *m = entry.value; - lb_llvm_function_pass_worker_proc(m); + // if (do_threading) { + // thread_pool_add_task(lb_llvm_function_pass_worker_proc, m); + // } else { + lb_llvm_function_pass_worker_proc(m); + // } } + thread_pool_wait(); TIME_SECTION("LLVM Module Pass"); - for (auto const &entry : gen->modules) { lbModule *m = entry.value; - lb_run_remove_unused_function_pass(m); - lb_run_remove_unused_globals_pass(m); - auto wd = gb_alloc_item(permanent_allocator(), lbLLVMModulePassWorkerData); wd->m = m; wd->target_machine = m->target_machine; - lb_llvm_module_pass_worker_proc(wd); + if (do_threading) { + thread_pool_add_task(lb_llvm_module_pass_worker_proc, wd); + } else { + lb_llvm_module_pass_worker_proc(wd); + } } + thread_pool_wait(); + TIME_SECTION("LLVM Module Verification"); + llvm_error = nullptr; defer (LLVMDisposeMessage(llvm_error)); @@ -2245,21 +2269,13 @@ gb_internal void lb_generate_code(lbGenerator *gen) { TIME_SECTION("LLVM Object Generation"); - isize non_empty_module_count = 0; - for (auto const &entry : gen->modules) { - lbModule *m = entry.value; - if (!lb_is_module_empty(m)) { - non_empty_module_count += 1; - } - } - if (build_context.ignore_llvm_build) { gb_printf_err("LLVM SUCCESS!\n"); gb_exit(1); return; } - if (do_threading && non_empty_module_count > 1) { + if (do_threading) { for (auto const &entry : gen->modules) { lbModule *m = entry.value; if (lb_is_module_empty(m)) { diff --git a/src/llvm_backend.hpp b/src/llvm_backend.hpp index 9f7caa3bb..d824b99cf 100644 --- a/src/llvm_backend.hpp +++ b/src/llvm_backend.hpp @@ -132,6 +132,8 @@ struct lbModule { PtrMap struct_field_remapping; // Key: LLVMTypeRef or Type * i32 internal_type_level; + RecursiveMutex values_mutex; + PtrMap values; PtrMap soa_values; StringMap members; @@ -178,6 +180,7 @@ struct lbGenerator { PtrMap modules_through_ctx; lbModule default_module; + BlockingMutex anonymous_proc_lits_mutex; PtrMap anonymous_proc_lits; BlockingMutex foreign_mutex; diff --git a/src/llvm_backend_general.cpp b/src/llvm_backend_general.cpp index a849929f0..c09648825 100644 --- a/src/llvm_backend_general.cpp +++ b/src/llvm_backend_general.cpp @@ -316,6 +316,7 @@ gb_internal bool lb_is_instr_terminating(LLVMValueRef instr) { gb_internal lbModule *lb_pkg_module(lbGenerator *gen, AstPackage *pkg) { + // NOTE(bill): no need for a mutex since it's immutable auto *found = map_get(&gen->modules, pkg); if (found) { return *found; @@ -1354,7 +1355,7 @@ gb_internal String lb_mangle_name(lbModule *m, Entity *e) { return mangled_name; } -gb_internal String lb_set_nested_type_name_ir_mangled_name(Entity *e, lbProcedure *p) { +gb_internal String lb_set_nested_type_name_ir_mangled_name(Entity *e, lbProcedure *p, lbModule *module) { // NOTE(bill, 2020-03-08): A polymorphic procedure may take a nested type declaration // and as a result, the declaration does not have time to determine what it should be @@ -1421,7 +1422,7 @@ gb_internal String lb_get_entity_name(lbModule *m, Entity *e, String default_nam } if (e->kind == Entity_TypeName && (e->scope->flags & ScopeFlag_File) == 0) { - return lb_set_nested_type_name_ir_mangled_name(e, nullptr); + return lb_set_nested_type_name_ir_mangled_name(e, nullptr, m); } String name = {}; @@ -2164,19 +2165,25 @@ gb_internal void lb_ensure_abi_function_type(lbModule *m, lbProcedure *p) { gb_internal void lb_add_entity(lbModule *m, Entity *e, lbValue val) { if (e != nullptr) { + mutex_lock(&m->values_mutex); map_set(&m->values, e, val); + mutex_unlock(&m->values_mutex); } } gb_internal void lb_add_member(lbModule *m, String const &name, lbValue val) { if (name.len > 0) { + mutex_lock(&m->values_mutex); string_map_set(&m->members, name, val); + mutex_unlock(&m->values_mutex); } } gb_internal void lb_add_procedure_value(lbModule *m, lbProcedure *p) { + mutex_lock(&m->values_mutex); if (p->entity != nullptr) { map_set(&m->procedure_values, p->value, p->entity); } string_map_set(&m->procedures, p->name, p); + mutex_unlock(&m->values_mutex); } @@ -2519,6 +2526,8 @@ gb_internal lbValue lb_find_ident(lbProcedure *p, lbModule *m, Entity *e, Ast *e return *found; } } + mutex_lock(&m->values_mutex); + defer (mutex_unlock(&m->values_mutex)); auto *found = map_get(&m->values, e); if (found) { @@ -2538,7 +2547,6 @@ gb_internal lbValue lb_find_ident(lbProcedure *p, lbModule *m, Entity *e, Ast *e if (USE_SEPARATE_MODULES) { lbModule *other_module = lb_pkg_module(m->gen, e->pkg); if (other_module != m) { - String name = lb_get_entity_name(other_module, e); lb_set_entity_from_other_modules_linkage_correctly(other_module, e, name); @@ -2569,6 +2577,9 @@ gb_internal lbValue lb_find_procedure_value_from_entity(lbModule *m, Entity *e) e = strip_entity_wrapping(e); GB_ASSERT(e != nullptr); + mutex_lock(&m->values_mutex); + defer (mutex_unlock(&m->values_mutex)); + auto *found = map_get(&m->values, e); if (found) { return *found; @@ -2657,6 +2668,10 @@ gb_internal lbValue lb_find_value_from_entity(lbModule *m, Entity *e) { return lb_find_procedure_value_from_entity(m, e); } + mutex_lock(&m->values_mutex); + defer (mutex_unlock(&m->values_mutex)); + + auto *found = map_get(&m->values, e); if (found) { return *found; diff --git a/src/llvm_backend_stmt.cpp b/src/llvm_backend_stmt.cpp index 0e6f75118..73b4e251f 100644 --- a/src/llvm_backend_stmt.cpp +++ b/src/llvm_backend_stmt.cpp @@ -32,7 +32,7 @@ gb_internal void lb_build_constant_value_decl(lbProcedure *p, AstValueDecl *vd) continue; } - lb_set_nested_type_name_ir_mangled_name(e, p); + lb_set_nested_type_name_ir_mangled_name(e, p, p->module); } for_array(i, vd->names) { -- cgit v1.2.3 From 8ef406324bd500cfd9f3d857e3a5d51adce33374 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Thu, 5 Jan 2023 17:26:51 +0000 Subject: Multi thread more of the backend where possible --- src/llvm_backend.cpp | 126 ++++++++++++++++++++++++++++--------------- src/llvm_backend.hpp | 1 + src/llvm_backend_general.cpp | 1 + 3 files changed, 85 insertions(+), 43 deletions(-) (limited to 'src/llvm_backend_general.cpp') diff --git a/src/llvm_backend.cpp b/src/llvm_backend.cpp index 6109ca247..e959b4741 100644 --- a/src/llvm_backend.cpp +++ b/src/llvm_backend.cpp @@ -1159,7 +1159,24 @@ gb_internal lbProcedure *lb_create_startup_runtime(lbModule *main_module, lbProc return p; } -gb_internal void lb_create_global_procedures_and_types(lbGenerator *gen, CheckerInfo *info) { +gb_internal WORKER_TASK_PROC(lb_generate_procedures_and_types_per_module) { + lbModule *m = cast(lbModule *)data; + for (Entity *e : m->global_procedures_and_types_to_create) { + String mangled_name = lb_get_entity_name(m, e); + + switch (e->kind) { + case Entity_TypeName: + lb_type(m, e->type); + break; + case Entity_Procedure: + array_add(&m->procedures_to_generate, lb_create_procedure(m, e)); + break; + } + } + return 0; +} + +gb_internal void lb_create_global_procedures_and_types(lbGenerator *gen, CheckerInfo *info, bool do_threading) { auto *min_dep_set = &info->minimum_dependency_set; for (Entity *e : info->entities) { @@ -1208,20 +1225,19 @@ gb_internal void lb_create_global_procedures_and_types(lbGenerator *gen, Checker m = lb_pkg_module(gen, e->pkg); } - String mangled_name = lb_get_entity_name(m, e); + array_add(&m->global_procedures_and_types_to_create, e); + } - switch (e->kind) { - case Entity_TypeName: - lb_type(m, e->type); - break; - case Entity_Procedure: - { - lbProcedure *p = lb_create_procedure(m, e); - array_add(&m->procedures_to_generate, p); - } - break; + for (auto const &entry : gen->modules) { + lbModule *m = entry.value; + if (do_threading) { + thread_pool_add_task(lb_generate_procedures_and_types_per_module, m); + } else { + lb_generate_procedures_and_types_per_module(m); } } + + thread_pool_wait(); } gb_internal void lb_generate_procedure(lbModule *m, lbProcedure *p); @@ -1277,7 +1293,8 @@ gb_internal void lb_llvm_function_pass_per_function_internal(lbModule *module, l lb_run_function_pass_manager(pass_manager, p); } -gb_internal void lb_llvm_function_pass_per_module(lbModule *m) { +gb_internal WORKER_TASK_PROC(lb_llvm_function_pass_per_module) { + lbModule *m = cast(lbModule *)data; { GB_ASSERT(m->function_pass_managers[lbFunctionPassManager_default] == nullptr); @@ -1354,6 +1371,8 @@ gb_internal void lb_llvm_function_pass_per_module(lbModule *m) { lbProcedure *p = entry.value; lb_llvm_function_pass_per_function_internal(m, p); } + + return 0; } @@ -1432,10 +1451,14 @@ gb_internal void lb_debug_info_complete_types_and_finalize(lbGenerator *gen) { } } -gb_internal void lb_llvm_function_passes(lbGenerator *gen) { +gb_internal void lb_llvm_function_passes(lbGenerator *gen, bool do_threading) { for (auto const &entry : gen->modules) { lbModule *m = entry.value; - lb_llvm_function_pass_per_module(m); + if (do_threading) { + thread_pool_add_task(lb_llvm_function_pass_per_module, m); + } else { + lb_llvm_function_pass_per_module(m); + } } thread_pool_wait(); } @@ -1523,25 +1546,41 @@ gb_internal String lb_filepath_obj_for_module(lbModule *m) { return concatenate_strings(permanent_allocator(), path, ext); } -gb_internal bool lb_llvm_module_verification(lbGenerator *gen, char **llvm_error_ptr) { +gb_internal WORKER_TASK_PROC(lb_llvm_module_verification_worker_proc) { + char *llvm_error = nullptr; + defer (LLVMDisposeMessage(llvm_error)); + lbModule *m = cast(lbModule *)data; + if (LLVMVerifyModule(m->mod, LLVMReturnStatusAction, &llvm_error)) { + gb_printf_err("LLVM Error:\n%s\n", llvm_error); + if (build_context.keep_temp_files) { + TIME_SECTION("LLVM Print Module to File"); + 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); + gb_exit(1); + return false; + } + } + gb_exit(1); + return 1; + } + return 0; +} + + +gb_internal bool lb_llvm_module_verification(lbGenerator *gen, bool do_threading) { for (auto const &entry : gen->modules) { lbModule *m = entry.value; - if (LLVMVerifyModule(m->mod, LLVMReturnStatusAction, llvm_error_ptr)) { - gb_printf_err("LLVM Error:\n%s\n", *llvm_error_ptr); - if (build_context.keep_temp_files) { - TIME_SECTION("LLVM Print Module to File"); - String filepath_ll = lb_filepath_ll_for_module(m); - if (LLVMPrintModuleToFile(m->mod, cast(char const *)filepath_ll.text, llvm_error_ptr)) { - gb_printf_err("LLVM Error: %s\n", *llvm_error_ptr); - gb_exit(1); - return false; - } + if (do_threading) { + thread_pool_add_task(lb_llvm_module_verification_worker_proc, m); + } else { + if (lb_llvm_module_verification_worker_proc(m)) { + return false; } - gb_exit(1); - return false; } } - *llvm_error_ptr = nullptr; + thread_pool_wait(); + return true; } @@ -1558,7 +1597,12 @@ gb_internal void lb_add_foreign_library_paths(lbGenerator *gen) { } } -gb_internal bool lb_llvm_object_generation(lbGenerator *gen, LLVMCodeGenFileType code_gen_file_type, bool do_threading) { +gb_internal bool lb_llvm_object_generation(lbGenerator *gen, bool do_threading) { + LLVMCodeGenFileType code_gen_file_type = LLVMObjectFile; + if (build_context.build_mode == BuildMode_Assembly) { + code_gen_file_type = LLVMAssemblyFile; + } + char *llvm_error = nullptr; defer (LLVMDisposeMessage(llvm_error)); @@ -2281,13 +2325,13 @@ gb_internal bool lb_generate_code(lbGenerator *gen) { } } - TIME_SECTION("LLVM Global Procedures and Types"); - lb_create_global_procedures_and_types(gen, info); - if (gen->modules.entries.count <= 1) { do_threading = false; } + TIME_SECTION("LLVM Global Procedures and Types"); + lb_create_global_procedures_and_types(gen, info, do_threading); + TIME_SECTION("LLVM Procedure Generation"); lb_generate_procedures(gen, do_threading); @@ -2324,7 +2368,7 @@ gb_internal bool lb_generate_code(lbGenerator *gen) { TIME_SECTION("LLVM Function Pass"); - lb_llvm_function_passes(gen); + lb_llvm_function_passes(gen, do_threading); TIME_SECTION("LLVM Module Pass"); lb_llvm_module_passes(gen, do_threading); @@ -2332,18 +2376,14 @@ gb_internal bool lb_generate_code(lbGenerator *gen) { TIME_SECTION("LLVM Module Verification"); - llvm_error = nullptr; - defer (LLVMDisposeMessage(llvm_error)); - LLVMCodeGenFileType code_gen_file_type = LLVMObjectFile; - if (build_context.build_mode == BuildMode_Assembly) { - code_gen_file_type = LLVMAssemblyFile; - } - - if (!lb_llvm_module_verification(gen, &llvm_error)) { + if (!lb_llvm_module_verification(gen, do_threading)) { return false; } + llvm_error = nullptr; + defer (LLVMDisposeMessage(llvm_error)); + if (build_context.keep_temp_files || build_context.build_mode == BuildMode_LLVM_IR) { TIME_SECTION("LLVM Print Module to File"); @@ -2377,7 +2417,7 @@ gb_internal bool lb_generate_code(lbGenerator *gen) { gb_printf_err("LLVM object generation has been ignored!\n"); return false; } - if (!lb_llvm_object_generation(gen, code_gen_file_type, do_threading)) { + if (!lb_llvm_object_generation(gen, do_threading)) { return false; } diff --git a/src/llvm_backend.hpp b/src/llvm_backend.hpp index 98b657256..90dfbc311 100644 --- a/src/llvm_backend.hpp +++ b/src/llvm_backend.hpp @@ -163,6 +163,7 @@ struct lbModule { u32 nested_type_name_guid; Array procedures_to_generate; + Array global_procedures_and_types_to_create; lbProcedure *curr_procedure; diff --git a/src/llvm_backend_general.cpp b/src/llvm_backend_general.cpp index c09648825..dca8c829d 100644 --- a/src/llvm_backend_general.cpp +++ b/src/llvm_backend_general.cpp @@ -70,6 +70,7 @@ gb_internal void lb_init_module(lbModule *m, Checker *c) { map_init(&m->map_get_procs); map_init(&m->map_set_procs); array_init(&m->procedures_to_generate, a, 0, 1024); + array_init(&m->global_procedures_and_types_to_create, a, 0, 1024); array_init(&m->missing_procedures_to_check, a, 0, 16); map_init(&m->debug_values); array_init(&m->debug_incomplete_types, a, 0, 1024); -- cgit v1.2.3