mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-04 22:58:46 +00:00
Generate anonymous procedure literals
This commit is contained in:
+17
-7
@@ -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) {
|
gb_internal TB_Symbol *cg_find_symbol_from_entity(cgModule *m, Entity *e) {
|
||||||
if (e) {
|
GB_ASSERT(e != nullptr);
|
||||||
rw_mutex_lock(&m->values_mutex);
|
|
||||||
defer (rw_mutex_unlock(&m->values_mutex));
|
rw_mutex_lock(&m->values_mutex);
|
||||||
TB_Symbol **found = map_get(&m->symbols, e);
|
defer (rw_mutex_unlock(&m->values_mutex));
|
||||||
if (found) {
|
TB_Symbol **found = map_get(&m->symbols, e);
|
||||||
return *found;
|
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;
|
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_debug_type_map);
|
||||||
map_init(&m->proc_proto_map);
|
map_init(&m->proc_proto_map);
|
||||||
|
|
||||||
|
map_init(&m->anonymous_proc_lits_map);
|
||||||
|
|
||||||
array_init(&m->single_threaded_procedure_queue, heap_allocator());
|
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->debug_type_map);
|
||||||
map_destroy(&m->proc_debug_type_map);
|
map_destroy(&m->proc_debug_type_map);
|
||||||
map_destroy(&m->proc_proto_map);
|
map_destroy(&m->proc_proto_map);
|
||||||
|
map_destroy(&m->anonymous_proc_lits_map);
|
||||||
|
|
||||||
array_free(&m->single_threaded_procedure_queue);
|
array_free(&m->single_threaded_procedure_queue);
|
||||||
|
|
||||||
|
|||||||
@@ -227,6 +227,10 @@ struct cgModule {
|
|||||||
RecursiveMutex proc_proto_mutex;
|
RecursiveMutex proc_proto_mutex;
|
||||||
PtrMap<Type *, TB_FunctionPrototype *> proc_proto_map;
|
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
|
// NOTE(bill): no need to protect this with a mutex
|
||||||
PtrMap<uintptr, TB_FileID> file_id_map; // Key: AstFile.id (i32 cast to uintptr)
|
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_add_procedure_to_queue(cgProcedure *p);
|
||||||
gb_internal void cg_setup_type_info_data(cgModule *m);
|
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 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 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 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_Global * g, Type *type);
|
||||||
gb_internal cgValue cg_value(TB_External *e, Type *type);
|
gb_internal cgValue cg_value(TB_External *e, Type *type);
|
||||||
gb_internal cgValue cg_value(TB_Function *f, Type *type);
|
gb_internal cgValue cg_value(TB_Function *f, Type *type);
|
||||||
|
|||||||
+15
-8
@@ -911,17 +911,24 @@ gb_internal cgValue cg_const_value(cgProcedure *p, Type *type, ExactValue const
|
|||||||
case ExactValue_Procedure:
|
case ExactValue_Procedure:
|
||||||
{
|
{
|
||||||
Ast *expr = unparen_expr(value.value_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);
|
Entity *e = entity_of_node(expr);
|
||||||
if (e != nullptr) {
|
if (e != nullptr) {
|
||||||
cgValue found = cg_find_procedure_value_from_entity(p->module, e);
|
TB_Symbol *found = cg_find_symbol_from_entity(p->module, e);
|
||||||
GB_ASSERT_MSG(are_types_identical(type, found.type),
|
GB_ASSERT_MSG(found != nullptr, "could not find '%.*s'", LIT(e->token.string));
|
||||||
"%.*s %s == %s",
|
TB_Node *ptr = tb_inst_get_symbol_address(p->func, found);
|
||||||
LIT(p->name),
|
GB_ASSERT(type != nullptr);
|
||||||
type_to_string(type), type_to_string(found.type));
|
GB_ASSERT(are_types_identical(type, e->type));
|
||||||
GB_ASSERT(found.kind == cgValue_Symbol);
|
return cg_value(ptr, type);
|
||||||
return cg_flatten_value(p, found);
|
|
||||||
}
|
}
|
||||||
GB_PANIC("TODO(bill): cg_const_value ExactValue_Procedure");
|
|
||||||
|
GB_PANIC("TODO(bill): cg_const_value ExactValue_Procedure %s", expr_to_string(expr));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
+15
-1
@@ -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_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));
|
// GB_PANIC("%s\n", type_to_string(tv.type));
|
||||||
// }
|
// }
|
||||||
|
|
||||||
// NOTE(bill): Short on constant values
|
// NOTE(bill): Short on constant values
|
||||||
return cg_const_value(p, type, tv.value);
|
return cg_const_value(p, type, tv.value);
|
||||||
} else if (tv.mode == Addressing_Type) {
|
} 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);
|
case_ast_node(ta, TypeAssertion, expr);
|
||||||
return cg_build_type_assertion(p, expr, tv.type);
|
return cg_build_type_assertion(p, expr, tv.type);
|
||||||
case_end;
|
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 {};
|
return {};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+58
-1
@@ -161,6 +161,63 @@ gb_internal cgProcedure *cg_procedure_create_dummy(cgModule *m, String const &li
|
|||||||
return p;
|
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) {
|
gb_internal void cg_procedure_begin(cgProcedure *p) {
|
||||||
if (p == nullptr || p->func == nullptr) {
|
if (p == nullptr || p->func == nullptr) {
|
||||||
return;
|
return;
|
||||||
@@ -374,7 +431,7 @@ gb_internal void cg_procedure_generate(cgProcedure *p) {
|
|||||||
|
|
||||||
|
|
||||||
if (
|
if (
|
||||||
string_starts_with(p->name, str_lit("bug@main")) ||
|
// string_starts_with(p->name, str_lit("bug@main")) ||
|
||||||
false
|
false
|
||||||
) { // IR Printing
|
) { // IR Printing
|
||||||
TB_Arena *arena = tb_default_arena();
|
TB_Arena *arena = tb_default_arena();
|
||||||
|
|||||||
Reference in New Issue
Block a user