Generate anonymous procedure literals

This commit is contained in:
gingerBill
2023-07-25 13:31:22 +01:00
parent ba48093666
commit baea6a1da8
5 changed files with 112 additions and 17 deletions

View File

@@ -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);

View File

@@ -227,6 +227,10 @@ struct cgModule {
RecursiveMutex proc_proto_mutex;
PtrMap<Type *, TB_FunctionPrototype *> proc_proto_map;
BlockingMutex anonymous_proc_lits_mutex;
PtrMap<Ast *, cgProcedure *> anonymous_proc_lits_map;
// NOTE(bill): no need to protect this with a mutex
PtrMap<uintptr, TB_FileID> file_id_map; // Key: AstFile.id (i32 cast to uintptr)
@@ -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);

View File

@@ -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;
}

View File

@@ -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 {};
}

View File

@@ -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<i32> 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();