mirror of
https://github.com/odin-lang/Odin.git
synced 2026-01-04 20:17:48 +00:00
Basic context creation
This commit is contained in:
@@ -446,295 +446,6 @@ struct cgGlobalVariable {
|
||||
bool is_initialized;
|
||||
};
|
||||
|
||||
|
||||
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(¶ms, 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->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);
|
||||
}
|
||||
|
||||
|
||||
#include "tilde_const.cpp"
|
||||
#include "tilde_expr.cpp"
|
||||
#include "tilde_proc.cpp"
|
||||
|
||||
@@ -113,7 +113,11 @@ enum cgDeferExitKind {
|
||||
cgDeferExit_Branch,
|
||||
};
|
||||
|
||||
|
||||
struct cgContextData {
|
||||
cgAddr ctx;
|
||||
isize scope_index;
|
||||
isize uses;
|
||||
};
|
||||
|
||||
struct cgProcedure {
|
||||
u32 flags;
|
||||
@@ -144,6 +148,12 @@ struct cgProcedure {
|
||||
|
||||
cgTargetList * target_list;
|
||||
Array<cgBranchBlocks> branch_blocks;
|
||||
|
||||
Scope *curr_scope;
|
||||
i32 scope_index;
|
||||
|
||||
Array<Scope *> scope_stack;
|
||||
Array<cgContextData> context_stack;
|
||||
};
|
||||
|
||||
|
||||
@@ -214,4 +224,6 @@ gb_internal cgAddr cg_add_local(cgProcedure *p, Type *type, Entity *e, bool zero
|
||||
|
||||
gb_internal cgValue cg_build_call_expr(cgProcedure *p, Ast *expr);
|
||||
|
||||
gb_internal cgValue cg_find_procedure_value_from_entity(cgModule *m, Entity *e);
|
||||
gb_internal cgValue cg_find_procedure_value_from_entity(cgModule *m, Entity *e);
|
||||
|
||||
gb_internal TB_DebugType *cg_debug_type(cgModule *m, Type *type);
|
||||
@@ -1,3 +1,89 @@
|
||||
gb_internal cgContextData *cg_push_context_onto_stack(cgProcedure *p, cgAddr ctx) {
|
||||
ctx.kind = cgAddr_Context;
|
||||
cgContextData *cd = array_add_and_get(&p->context_stack);
|
||||
cd->ctx = ctx;
|
||||
cd->scope_index = p->scope_index;
|
||||
return cd;
|
||||
}
|
||||
|
||||
gb_internal cgAddr cg_find_or_generate_context_ptr(cgProcedure *p) {
|
||||
if (p->context_stack.count > 0) {
|
||||
return p->context_stack[p->context_stack.count-1].ctx;
|
||||
}
|
||||
|
||||
Type *pt = base_type(p->type);
|
||||
GB_ASSERT(pt->kind == Type_Proc);
|
||||
GB_ASSERT(pt->Proc.calling_convention != ProcCC_Odin);
|
||||
|
||||
cgAddr c = cg_add_local(p, t_context, nullptr, true);
|
||||
tb_node_append_attrib(c.addr.node, tb_function_attrib_variable(p->func, -1, "context", cg_debug_type(p->module, t_context)));
|
||||
c.kind = cgAddr_Context;
|
||||
// lb_emit_init_context(p, c);
|
||||
cg_push_context_onto_stack(p, c);
|
||||
// lb_add_debug_context_variable(p, c);
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
gb_internal cgValue cg_find_value_from_entity(cgModule *m, Entity *e) {
|
||||
e = strip_entity_wrapping(e);
|
||||
GB_ASSERT(e != nullptr);
|
||||
|
||||
GB_ASSERT(e->token.string != "_");
|
||||
|
||||
if (e->kind == Entity_Procedure) {
|
||||
return cg_find_procedure_value_from_entity(m, e);
|
||||
}
|
||||
|
||||
cgValue *found = nullptr;
|
||||
rw_mutex_shared_lock(&m->values_mutex);
|
||||
found = map_get(&m->values, e);
|
||||
rw_mutex_shared_unlock(&m->values_mutex);
|
||||
if (found) {
|
||||
return *found;
|
||||
}
|
||||
|
||||
// GB_PANIC("\n\tError in: %s, missing value '%.*s'\n", token_pos_to_string(e->token.pos), LIT(e->token.string));
|
||||
return {};
|
||||
}
|
||||
|
||||
gb_internal cgAddr cg_build_addr_from_entity(cgProcedure *p, Entity *e, Ast *expr) {
|
||||
GB_ASSERT(e != nullptr);
|
||||
if (e->kind == Entity_Constant) {
|
||||
Type *t = default_type(type_of_expr(expr));
|
||||
cgValue v = cg_const_value(p, t, e->Constant.value);
|
||||
GB_PANIC("TODO(bill): cg_add_global_generated");
|
||||
// return cg_add_global_generated(p->module, t, v);
|
||||
return {};
|
||||
}
|
||||
|
||||
|
||||
cgValue v = {};
|
||||
|
||||
cgModule *m = p->module;
|
||||
|
||||
rw_mutex_lock(&m->values_mutex);
|
||||
cgValue *found = map_get(&m->values, e);
|
||||
rw_mutex_unlock(&m->values_mutex);
|
||||
if (found) {
|
||||
v = *found;
|
||||
} else if (e->kind == Entity_Variable && e->flags & EntityFlag_Using) {
|
||||
GB_PANIC("TODO(bill): cg_get_using_variable");
|
||||
// NOTE(bill): Calculate the using variable every time
|
||||
// v = cg_get_using_variable(p, e);
|
||||
} else if (e->flags & EntityFlag_SoaPtrField) {
|
||||
GB_PANIC("TODO(bill): cg_get_soa_variable_addr");
|
||||
// return cg_get_soa_variable_addr(p, e);
|
||||
}
|
||||
|
||||
|
||||
if (v.node == nullptr) {
|
||||
return cg_addr(cg_find_value_from_entity(m, e));
|
||||
}
|
||||
|
||||
return cg_addr(v);
|
||||
}
|
||||
|
||||
gb_internal cgValue cg_typeid(cgModule *m, Type *t) {
|
||||
GB_ASSERT("TODO(bill): cg_typeid");
|
||||
return {};
|
||||
@@ -248,6 +334,65 @@ gb_internal cgValue cg_build_expr_internal(cgProcedure *p, Ast *expr) {
|
||||
}
|
||||
|
||||
|
||||
gb_internal cgAddr cg_build_addr_internal(cgProcedure *p, Ast *expr);
|
||||
gb_internal cgAddr cg_build_addr(cgProcedure *p, Ast *expr) {
|
||||
return {};
|
||||
expr = unparen_expr(expr);
|
||||
|
||||
// IMPORTANT NOTE(bill):
|
||||
// Selector Call Expressions (foo->bar(...))
|
||||
// must only evaluate `foo` once as it gets transformed into
|
||||
// `foo.bar(foo, ...)`
|
||||
// And if `foo` is a procedure call or something more complex, storing the value
|
||||
// once is a very good idea
|
||||
// If a stored value is found, it must be removed from the cache
|
||||
if (expr->state_flags & StateFlag_SelectorCallExpr) {
|
||||
// lbAddr *pp = map_get(&p->selector_addr, expr);
|
||||
// if (pp != nullptr) {
|
||||
// lbAddr res = *pp;
|
||||
// map_remove(&p->selector_addr, expr);
|
||||
// return res;
|
||||
// }
|
||||
}
|
||||
cgAddr addr = cg_build_addr_internal(p, expr);
|
||||
if (expr->state_flags & StateFlag_SelectorCallExpr) {
|
||||
// map_set(&p->selector_addr, expr, addr);
|
||||
}
|
||||
return addr;
|
||||
}
|
||||
|
||||
|
||||
gb_internal cgAddr cg_build_addr_internal(cgProcedure *p, Ast *expr) {
|
||||
switch (expr->kind) {
|
||||
case_ast_node(i, Implicit, expr);
|
||||
cgAddr v = {};
|
||||
switch (i->kind) {
|
||||
case Token_context:
|
||||
v = cg_find_or_generate_context_ptr(p);
|
||||
break;
|
||||
}
|
||||
|
||||
GB_ASSERT(v.addr.node != nullptr);
|
||||
return v;
|
||||
case_end;
|
||||
|
||||
case_ast_node(i, Ident, expr);
|
||||
if (is_blank_ident(expr)) {
|
||||
cgAddr val = {};
|
||||
return val;
|
||||
}
|
||||
String name = i->token.string;
|
||||
Entity *e = entity_of_node(expr);
|
||||
return cg_build_addr_from_entity(p, e, expr);
|
||||
case_end;
|
||||
}
|
||||
|
||||
TokenPos token_pos = ast_token(expr).pos;
|
||||
GB_PANIC("Unexpected address expression\n"
|
||||
"\tAst: %.*s @ "
|
||||
"%s\n",
|
||||
LIT(ast_strings[expr->kind]),
|
||||
token_pos_to_string(token_pos));
|
||||
|
||||
|
||||
return {};
|
||||
}
|
||||
@@ -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(¶ms, 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);
|
||||
|
||||
@@ -549,7 +549,7 @@ gb_internal void cg_build_stmt(cgProcedure *p, Ast *node) {
|
||||
case_end;
|
||||
|
||||
case_ast_node(as, AssignStmt, node);
|
||||
// cg_build_assign_stmt(p, as);
|
||||
cg_build_assign_stmt(p, as);
|
||||
case_end;
|
||||
|
||||
case_ast_node(rs, ReturnStmt, node);
|
||||
|
||||
Reference in New Issue
Block a user