diff --git a/src/tilde.cpp b/src/tilde.cpp index a7f37dc6f..9550374e8 100644 --- a/src/tilde.cpp +++ b/src/tilde.cpp @@ -238,14 +238,21 @@ gb_internal void cg_add_procedure_value(cgModule *m, cgProcedure *p) { } gb_internal TB_Symbol *cg_find_symbol_from_entity(cgModule *m, Entity *e) { - if (e) { - rw_mutex_lock(&m->values_mutex); - defer (rw_mutex_unlock(&m->values_mutex)); - TB_Symbol **found = map_get(&m->symbols, e); - if (found) { - return *found; - } + GB_ASSERT(e != nullptr); + + rw_mutex_lock(&m->values_mutex); + defer (rw_mutex_unlock(&m->values_mutex)); + TB_Symbol **found = map_get(&m->symbols, e); + if (found) { + return *found; } + + String link_name = cg_get_entity_name(m, e); + cgProcedure **proc_found = string_map_get(&m->procedures, link_name); + if (proc_found) { + return (*proc_found)->symbol; + } + GB_PANIC("could not find entity's symbol %.*s", LIT(e->token.string)); return nullptr; } @@ -397,6 +404,8 @@ gb_internal cgModule *cg_module_create(Checker *c) { map_init(&m->proc_debug_type_map); map_init(&m->proc_proto_map); + map_init(&m->anonymous_proc_lits_map); + array_init(&m->single_threaded_procedure_queue, heap_allocator()); @@ -417,6 +426,7 @@ gb_internal void cg_module_destroy(cgModule *m) { map_destroy(&m->debug_type_map); map_destroy(&m->proc_debug_type_map); map_destroy(&m->proc_proto_map); + map_destroy(&m->anonymous_proc_lits_map); array_free(&m->single_threaded_procedure_queue); diff --git a/src/tilde.hpp b/src/tilde.hpp index 857247305..087655d83 100644 --- a/src/tilde.hpp +++ b/src/tilde.hpp @@ -227,6 +227,10 @@ struct cgModule { RecursiveMutex proc_proto_mutex; PtrMap proc_proto_map; + BlockingMutex anonymous_proc_lits_mutex; + PtrMap anonymous_proc_lits_map; + + // NOTE(bill): no need to protect this with a mutex PtrMap file_id_map; // Key: AstFile.id (i32 cast to uintptr) @@ -259,11 +263,14 @@ gb_internal TB_Arena *cg_arena(void); gb_internal void cg_add_procedure_to_queue(cgProcedure *p); gb_internal void cg_setup_type_info_data(cgModule *m); +gb_internal cgProcedure *cg_procedure_generate_anonymous(cgModule *m, Ast *expr, cgProcedure *parent); gb_internal isize cg_global_const_calculate_region_count(ExactValue const &value, Type *type); gb_internal i64 cg_global_const_calculate_region_count_from_basic_type(Type *type); gb_internal bool cg_global_const_add_region(cgModule *m, ExactValue const &value, Type *type, TB_Global *global, i64 offset); +gb_internal String cg_get_entity_name(cgModule *m, Entity *e); + gb_internal cgValue cg_value(TB_Global * g, Type *type); gb_internal cgValue cg_value(TB_External *e, Type *type); gb_internal cgValue cg_value(TB_Function *f, Type *type); diff --git a/src/tilde_const.cpp b/src/tilde_const.cpp index 30038cfdf..05b57a97a 100644 --- a/src/tilde_const.cpp +++ b/src/tilde_const.cpp @@ -911,17 +911,24 @@ gb_internal cgValue cg_const_value(cgProcedure *p, Type *type, ExactValue const case ExactValue_Procedure: { Ast *expr = unparen_expr(value.value_procedure); + if (expr->kind == Ast_ProcLit) { + cgProcedure *anon = cg_procedure_generate_anonymous(p->module, expr, p); + TB_Node *ptr = tb_inst_get_symbol_address(p->func, anon->symbol); + GB_ASSERT(are_types_identical(type, anon->type)); + return cg_value(ptr, type); + } + Entity *e = entity_of_node(expr); if (e != nullptr) { - cgValue found = cg_find_procedure_value_from_entity(p->module, e); - GB_ASSERT_MSG(are_types_identical(type, found.type), - "%.*s %s == %s", - LIT(p->name), - type_to_string(type), type_to_string(found.type)); - GB_ASSERT(found.kind == cgValue_Symbol); - return cg_flatten_value(p, found); + TB_Symbol *found = cg_find_symbol_from_entity(p->module, e); + GB_ASSERT_MSG(found != nullptr, "could not find '%.*s'", LIT(e->token.string)); + TB_Node *ptr = tb_inst_get_symbol_address(p->func, found); + GB_ASSERT(type != nullptr); + GB_ASSERT(are_types_identical(type, e->type)); + return cg_value(ptr, type); } - GB_PANIC("TODO(bill): cg_const_value ExactValue_Procedure"); + + GB_PANIC("TODO(bill): cg_const_value ExactValue_Procedure %s", expr_to_string(expr)); } break; } diff --git a/src/tilde_expr.cpp b/src/tilde_expr.cpp index 551ffbfbb..4caf33ccf 100644 --- a/src/tilde_expr.cpp +++ b/src/tilde_expr.cpp @@ -3090,7 +3090,6 @@ gb_internal cgValue cg_build_expr_internal(cgProcedure *p, Ast *expr) { // gb_printf_err("%s %s : %s @ %p\n", token_pos_to_string(expr_pos), expr_to_string(expr), type_to_string(expr->tav.type), expr); // GB_PANIC("%s\n", type_to_string(tv.type)); // } - // NOTE(bill): Short on constant values return cg_const_value(p, type, tv.value); } else if (tv.mode == Addressing_Type) { @@ -3289,7 +3288,22 @@ gb_internal cgValue cg_build_expr_internal(cgProcedure *p, Ast *expr) { case_ast_node(ta, TypeAssertion, expr); return cg_build_type_assertion(p, expr, tv.type); case_end; + + case_ast_node(pl, ProcLit, expr); + cgProcedure *anon = cg_procedure_generate_anonymous(p->module, expr, p); + GB_ASSERT(anon != nullptr); + GB_ASSERT(anon->symbol != nullptr); + return cg_value(tb_inst_get_symbol_address(p->func, anon->symbol), type); + case_end; + } + TokenPos token_pos = ast_token(expr).pos; + GB_PANIC("Unexpected expression\n" + "\tAst: %.*s @ " + "%s\n", + LIT(ast_strings[expr->kind]), + token_pos_to_string(token_pos)); + return {}; } diff --git a/src/tilde_proc.cpp b/src/tilde_proc.cpp index 08cbcc631..3a0624583 100644 --- a/src/tilde_proc.cpp +++ b/src/tilde_proc.cpp @@ -161,6 +161,63 @@ gb_internal cgProcedure *cg_procedure_create_dummy(cgModule *m, String const &li return p; } +gb_internal cgProcedure *cg_procedure_generate_anonymous(cgModule *m, Ast *expr, cgProcedure *parent) { + expr = unparen_expr(expr); + ast_node(pl, ProcLit, expr); + + mutex_lock(&m->anonymous_proc_lits_mutex); + defer (mutex_unlock(&m->anonymous_proc_lits_mutex)); + + cgProcedure **found = map_get(&m->anonymous_proc_lits_map, expr); + if (found) { + return *found; + } + + TokenPos pos = ast_token(expr).pos; + + // NOTE(bill): Generate a new name + // parent$count + + String prefix_name = str_lit("proc_lit"); + if (parent) { + prefix_name = parent->name; + } + + isize name_len = prefix_name.len + 6 + 11; + char *name_text = gb_alloc_array(permanent_allocator(), char, name_len); + + static std::atomic name_id; + name_len = gb_snprintf(name_text, name_len, "%.*s$anon-%d", LIT(prefix_name), 1+name_id.fetch_add(1)); + String name = make_string((u8 *)name_text, name_len-1); + + Type *type = type_of_expr(expr); + + GB_ASSERT(pl->decl->entity == nullptr); + Token token = {}; + token.pos = ast_token(expr).pos; + token.kind = Token_Ident; + token.string = name; + Entity *e = alloc_entity_procedure(nullptr, token, type, pl->tags); + e->file = expr->file(); + + // NOTE(bill): this is to prevent a race condition since these procedure literals can be created anywhere at any time + e->decl_info = pl->decl; + pl->decl->entity = e; + e->flags |= EntityFlag_ProcBodyChecked; + + cgProcedure *p = cg_procedure_create(m, e); + + map_set(&m->anonymous_proc_lits_map, expr, p); + + if (parent != nullptr) { + array_add(&parent->children, p); + } + + cg_add_procedure_to_queue(p); + return p; + +} + gb_internal void cg_procedure_begin(cgProcedure *p) { if (p == nullptr || p->func == nullptr) { return; @@ -374,7 +431,7 @@ gb_internal void cg_procedure_generate(cgProcedure *p) { if ( - string_starts_with(p->name, str_lit("bug@main")) || + // string_starts_with(p->name, str_lit("bug@main")) || false ) { // IR Printing TB_Arena *arena = tb_default_arena();