aboutsummaryrefslogtreecommitdiff
path: root/src/tilde_proc.cpp
diff options
context:
space:
mode:
authorgingerBill <bill@gingerbill.org>2023-07-15 13:30:31 +0100
committergingerBill <bill@gingerbill.org>2023-07-15 13:30:31 +0100
commitccb736411bc61a0ccde6835cbbf1876a2616e3e1 (patch)
tree408813f7c1a044fb8550162392dcdcee4ecc2787 /src/tilde_proc.cpp
parente2e5641a450f4d7ea67eae468f1bd479361ec198 (diff)
Basic `context` creation
Diffstat (limited to 'src/tilde_proc.cpp')
-rw-r--r--src/tilde_proc.cpp290
1 files changed, 290 insertions, 0 deletions
diff --git a/src/tilde_proc.cpp b/src/tilde_proc.cpp
index dbebae853..b60e797c3 100644
--- a/src/tilde_proc.cpp
+++ b/src/tilde_proc.cpp
@@ -1,3 +1,293 @@
+gb_internal TB_FunctionPrototype *cg_procedure_type_as_prototype(cgModule *m, Type *type) {
+ GB_ASSERT(type != nullptr);
+ type = base_type(type);
+ GB_ASSERT(type->kind == Type_Proc);
+ TypeProc *pt = &type->Proc;
+
+ auto params = array_make<TB_PrototypeParam>(heap_allocator(), 0, pt->param_count);
+ if (pt->params) for (Entity *e : pt->params->Tuple.variables) {
+ TB_PrototypeParam param = {};
+
+ Type *t = core_type(e->type);
+ i64 sz = type_size_of(t);
+ switch (t->kind) {
+ case Type_Basic:
+ switch (t->Basic.kind) {
+ case Basic_bool:
+ case Basic_b8:
+ case Basic_b16:
+ case Basic_b32:
+ case Basic_b64:
+ case Basic_i8:
+ case Basic_u8:
+ case Basic_i16:
+ case Basic_u16:
+ case Basic_i32:
+ case Basic_u32:
+ case Basic_i64:
+ case Basic_u64:
+ case Basic_i128:
+ case Basic_u128:
+ case Basic_rune:
+ case Basic_int:
+ case Basic_uint:
+ case Basic_uintptr:
+ param.dt = TB_TYPE_INTN(cast(u16)(8*sz));
+ break;
+
+ case Basic_f16: param.dt = TB_TYPE_I16; break;
+ case Basic_f32: param.dt = TB_TYPE_F32; break;
+ case Basic_f64: param.dt = TB_TYPE_F64; break;
+
+ case Basic_complex32:
+ case Basic_complex64:
+ case Basic_complex128:
+ case Basic_quaternion64:
+ case Basic_quaternion128:
+ case Basic_quaternion256:
+ param.dt = TB_TYPE_PTR;
+ break;
+
+
+ case Basic_rawptr:
+ param.dt = TB_TYPE_PTR;
+ break;
+ case Basic_string: // ^u8 + int
+ param.dt = TB_TYPE_PTR;
+ break;
+ case Basic_cstring: // ^u8
+ param.dt = TB_TYPE_PTR;
+ break;
+ case Basic_any: // rawptr + ^Type_Info
+ param.dt = TB_TYPE_PTR;
+ break;
+
+ case Basic_typeid:
+ param.dt = TB_TYPE_INTN(cast(u16)(8*sz));
+ break;
+
+ // Endian Specific Types
+ case Basic_i16le:
+ case Basic_u16le:
+ case Basic_i32le:
+ case Basic_u32le:
+ case Basic_i64le:
+ case Basic_u64le:
+ case Basic_i128le:
+ case Basic_u128le:
+ case Basic_i16be:
+ case Basic_u16be:
+ case Basic_i32be:
+ case Basic_u32be:
+ case Basic_i64be:
+ case Basic_u64be:
+ case Basic_i128be:
+ case Basic_u128be:
+ param.dt = TB_TYPE_INTN(cast(u16)(8*sz));
+ break;
+
+ case Basic_f16le: param.dt = TB_TYPE_I16; break;
+ case Basic_f32le: param.dt = TB_TYPE_F32; break;
+ case Basic_f64le: param.dt = TB_TYPE_F64; break;
+
+ case Basic_f16be: param.dt = TB_TYPE_I16; break;
+ case Basic_f32be: param.dt = TB_TYPE_F32; break;
+ case Basic_f64be: param.dt = TB_TYPE_F64; break;
+ }
+
+ case Type_Pointer:
+ case Type_MultiPointer:
+ case Type_Proc:
+ param.dt = TB_TYPE_PTR;
+ break;
+
+ default:
+ switch (sz) {
+ case 1: param.dt = TB_TYPE_I8; break;
+ case 2: param.dt = TB_TYPE_I16; break;
+ case 4: param.dt = TB_TYPE_I32; break;
+ case 8: param.dt = TB_TYPE_I64; break;
+ default:
+ param.dt = TB_TYPE_PTR;
+ break;
+ }
+ }
+
+ if (param.dt.width != 0) {
+ if (is_blank_ident(e->token)) {
+ param.name = alloc_cstring(temporary_allocator(), e->token.string);
+ }
+ array_add(&params, param);
+ }
+ }
+
+ auto results = array_make<TB_PrototypeParam>(heap_allocator(), 0, pt->result_count);
+ // if (pt->results) for (Entity *e : pt->params->Tuple.variables) {
+ // // TODO(bill):
+ // }
+
+
+ return tb_prototype_create(m->mod, TB_CDECL, params.count, params.data, results.count, results.data, pt->c_vararg);
+}
+
+gb_internal cgProcedure *cg_procedure_create(cgModule *m, Entity *entity, bool ignore_body=false) {
+ GB_ASSERT(entity != nullptr);
+ GB_ASSERT(entity->kind == Entity_Procedure);
+ if (!entity->Procedure.is_foreign) {
+ if ((entity->flags & EntityFlag_ProcBodyChecked) == 0) {
+ GB_PANIC("%.*s :: %s (was parapoly: %d %d)", LIT(entity->token.string), type_to_string(entity->type), is_type_polymorphic(entity->type, true), is_type_polymorphic(entity->type, false));
+ }
+ }
+
+ String link_name = cg_get_entity_name(m, entity);
+
+ cgProcedure *p = nullptr;
+ {
+ StringHashKey key = string_hash_string(link_name);
+ cgValue *found = string_map_get(&m->members, key);
+ if (found) {
+ cg_add_entity(m, entity, *found);
+ p = string_map_must_get(&m->procedures, key);
+ if (!ignore_body && p->func != nullptr) {
+ return nullptr;
+ }
+ }
+ }
+
+ if (p == nullptr) {
+ p = gb_alloc_item(permanent_allocator(), cgProcedure);
+ }
+
+ p->module = m;
+ p->entity = entity;
+ p->name = link_name;
+
+ DeclInfo *decl = entity->decl_info;
+
+ ast_node(pl, ProcLit, decl->proc_lit);
+ Type *pt = base_type(entity->type);
+ GB_ASSERT(pt->kind == Type_Proc);
+
+ p->type = entity->type;
+ p->type_expr = decl->type_expr;
+ p->body = pl->body;
+ p->inlining = pl->inlining;
+ p->is_foreign = entity->Procedure.is_foreign;
+ p->is_export = entity->Procedure.is_export;
+ p->is_entry_point = false;
+
+ gbAllocator a = heap_allocator();
+ p->children.allocator = a;
+ // p->defer_stmts.allocator = a;
+ // p->blocks.allocator = a;
+ // p->branch_blocks.allocator = a;
+ p->context_stack.allocator = a;
+ p->scope_stack.allocator = a;
+ // map_init(&p->tuple_fix_map, 0);
+
+ TB_Linkage linkage = TB_LINKAGE_PRIVATE;
+ if (p->is_export) {
+ linkage = TB_LINKAGE_PUBLIC;
+ } else if (p->is_foreign || ignore_body) {
+ if (ignore_body) {
+ linkage = TB_LINKAGE_PUBLIC;
+ }
+ p->symbol = cast(TB_Symbol *)tb_extern_create(m->mod, link_name.len, cast(char const *)link_name.text, TB_EXTERNAL_SO_LOCAL);
+ }
+
+ if (p->symbol == nullptr) {
+ p->func = tb_function_create(m->mod, link_name.len, cast(char const *)link_name.text, linkage, TB_COMDAT_NONE);
+ tb_function_set_prototype(p->func, cg_procedure_type_as_prototype(m, p->type), tb_default_arena());
+ p->symbol = cast(TB_Symbol *)p->func;
+ }
+
+ cgValue proc_value = cg_value(p->symbol, p->type);
+ cg_add_entity(m, entity, proc_value);
+ cg_add_member(m, p->name, proc_value);
+ cg_add_procedure_value(m, p);
+
+
+ return p;
+}
+
+gb_internal cgProcedure *cg_procedure_create_dummy(cgModule *m, String const &link_name, Type *type) {
+ auto *prev_found = string_map_get(&m->members, link_name);
+ GB_ASSERT_MSG(prev_found == nullptr, "failed to create dummy procedure for: %.*s", LIT(link_name));
+
+ cgProcedure *p = gb_alloc_item(permanent_allocator(), cgProcedure);
+
+ p->module = m;
+ p->name = link_name;
+
+ p->type = type;
+ p->type_expr = nullptr;
+ p->body = nullptr;
+ p->tags = 0;
+ p->inlining = ProcInlining_none;
+ p->is_foreign = false;
+ p->is_export = false;
+ p->is_entry_point = false;
+
+ gbAllocator a = heap_allocator();
+ p->children.allocator = a;
+ // p->defer_stmts.allocator = a;
+ // p->blocks.allocator = a;
+ // p->branch_blocks.allocator = a;
+ p->scope_stack.allocator = a;
+ p->context_stack.allocator = a;
+ // map_init(&p->tuple_fix_map, 0);
+
+
+ TB_Linkage linkage = TB_LINKAGE_PRIVATE;
+
+ p->func = tb_function_create(m->mod, link_name.len, cast(char const *)link_name.text, linkage, TB_COMDAT_NONE);
+ tb_function_set_prototype(p->func, cg_procedure_type_as_prototype(m, p->type), tb_default_arena());
+ p->symbol = cast(TB_Symbol *)p->func;
+
+ cgValue proc_value = cg_value(p->symbol, p->type);
+ cg_add_member(m, p->name, proc_value);
+ cg_add_procedure_value(m, p);
+
+ return p;
+}
+
+gb_internal void cg_procedure_begin(cgProcedure *p) {
+ if (p == nullptr || p->func == nullptr) {
+ return;
+ }
+}
+
+gb_internal void cg_procedure_end(cgProcedure *p) {
+ if (p == nullptr || p->func == nullptr) {
+ return;
+ }
+ tb_inst_ret(p->func, 0, nullptr);
+ if (p->name == "main") {
+ TB_Arena *arena = tb_default_arena();
+ defer (arena->free(arena));
+ TB_FuncOpt *opt = tb_funcopt_enter(p->func, arena);
+ defer (tb_funcopt_exit(opt));
+ tb_funcopt_print(opt);
+ }
+ tb_module_compile_function(p->module->mod, p->func, TB_ISEL_FAST);
+}
+
+gb_internal void cg_procedure_generate(cgProcedure *p) {
+ if (p->body == nullptr) {
+ return;
+ }
+ cg_procedure_begin(p);
+ defer (cg_procedure_end(p));
+
+ if (p->name != "bug.main" &&
+ p->name != "main") {
+ return;
+ }
+ cg_build_stmt(p, p->body);
+}
+
+
+
gb_internal cgValue cg_find_procedure_value_from_entity(cgModule *m, Entity *e) {
GB_ASSERT(is_type_proc(e->type));
e = strip_entity_wrapping(e);