aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorgingerBill <bill@gingerbill.org>2023-07-25 13:31:22 +0100
committergingerBill <bill@gingerbill.org>2023-07-25 13:31:22 +0100
commitbaea6a1da88444db322f83b8300b5d64d117cfd1 (patch)
tree9e0e4b3db70e49d49f688ad3e93ac0aad5ab59b0 /src
parentba48093666e2862e861203b38d3dbc35aa7532ff (diff)
Generate anonymous procedure literals
Diffstat (limited to 'src')
-rw-r--r--src/tilde.cpp24
-rw-r--r--src/tilde.hpp7
-rw-r--r--src/tilde_const.cpp23
-rw-r--r--src/tilde_expr.cpp16
-rw-r--r--src/tilde_proc.cpp59
5 files changed, 112 insertions, 17 deletions
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<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);
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<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();