diff --git a/src/tilde.cpp b/src/tilde.cpp index 1969deaec..26bd69f4f 100644 --- a/src/tilde.cpp +++ b/src/tilde.cpp @@ -75,6 +75,7 @@ gb_internal TB_DataType cg_data_type(Type *t) { case Basic_f32be: return TB_TYPE_F32; case Basic_f64be: return TB_TYPE_F64; } + break; case Type_Pointer: case Type_MultiPointer: diff --git a/src/tilde.hpp b/src/tilde.hpp index f0e45bb97..0e5b3b551 100644 --- a/src/tilde.hpp +++ b/src/tilde.hpp @@ -166,9 +166,6 @@ struct cgProcedure { TB_FunctionPrototype *proto; TB_Symbol *symbol; - // includes parameters, pointers to return values, and context ptr - Slice param_nodes; - Entity * entity; cgModule *module; String name; @@ -309,11 +306,11 @@ gb_internal cgValue cg_emit_arith(cgProcedure *p, TokenKind op, cgValue lhs, cgV gb_internal bool cg_emit_goto(cgProcedure *p, TB_Node *control_region); - gb_internal TB_Node *cg_control_region(cgProcedure *p, char const *name); gb_internal isize cg_append_tuple_values(cgProcedure *p, Array *dst_values, cgValue src_value); +gb_internal cgValue cg_handle_param_value(cgProcedure *p, Type *parameter_type, ParameterValue const ¶m_value, TokenPos const &pos); gb_internal cgValue cg_builtin_len(cgProcedure *p, cgValue value); gb_internal cgValue cg_builtin_raw_data(cgProcedure *p, cgValue const &x); \ No newline at end of file diff --git a/src/tilde/tb.h b/src/tilde/tb.h index 8e5bc5567..abe3c5a1a 100644 --- a/src/tilde/tb.h +++ b/src/tilde/tb.h @@ -83,7 +83,6 @@ typedef enum TB_ABI { typedef enum TB_OutputFlavor { TB_FLAVOR_OBJECT, // .o .obj - TB_FLAVOR_ASSEMBLY, // .s .asm TB_FLAVOR_SHARED, // .so .dll TB_FLAVOR_STATIC, // .a .lib TB_FLAVOR_EXECUTABLE, // .exe @@ -951,7 +950,7 @@ TB_API TB_Node* tb_inst_sint(TB_Function* f, TB_DataType dt, int64_t imm); TB_API TB_Node* tb_inst_uint(TB_Function* f, TB_DataType dt, uint64_t imm); TB_API TB_Node* tb_inst_float32(TB_Function* f, float imm); TB_API TB_Node* tb_inst_float64(TB_Function* f, double imm); -TB_API TB_Node* tb_inst_cstring(TB_Function* f, const char* srt); +TB_API TB_Node* tb_inst_cstring(TB_Function* f, const char* str); TB_API TB_Node* tb_inst_string(TB_Function* f, size_t len, const char* str); // write 'val' over 'count' bytes on 'dst' diff --git a/src/tilde/tb.lib b/src/tilde/tb.lib index b9b9dbd44..a3c6ba044 100644 Binary files a/src/tilde/tb.lib and b/src/tilde/tb.lib differ diff --git a/src/tilde_const.cpp b/src/tilde_const.cpp index e066c72a3..6b1fb5c92 100644 --- a/src/tilde_const.cpp +++ b/src/tilde_const.cpp @@ -851,7 +851,7 @@ gb_internal cgValue cg_const_value(cgModule *m, cgProcedure *p, Type *type, Exac TB_Node *node = tb_inst_get_symbol_address(p->func, symbol); return cg_lvalue_addr(node, type); } else { - return cg_value(symbol, type); + return cg_value(symbol, alloc_type_pointer(type)); } } diff --git a/src/tilde_expr.cpp b/src/tilde_expr.cpp index c0ddc4e70..3d9054803 100644 --- a/src/tilde_expr.cpp +++ b/src/tilde_expr.cpp @@ -179,7 +179,7 @@ gb_internal cgValue cg_emit_transmute(cgProcedure *p, cgValue value, Type *type) TB_DataType dt = cg_data_type(type); switch (value.kind) { case cgValue_Value: - GB_ASSERT_MSG(!TB_IS_VOID_TYPE(dt), "%s", type_to_string(type)); + GB_ASSERT_MSG(!TB_IS_VOID_TYPE(dt), "%d %s -> %s", dt.type, type_to_string(value.type), type_to_string(type)); value.type = type; if (value.node->dt.raw != dt.raw) { value.node = tb_inst_bitcast(p->func, value.node, dt); diff --git a/src/tilde_proc.cpp b/src/tilde_proc.cpp index 8016e4dba..7c7bda197 100644 --- a/src/tilde_proc.cpp +++ b/src/tilde_proc.cpp @@ -89,11 +89,9 @@ gb_internal cgProcedure *cg_procedure_create(cgModule *m, Entity *entity, bool i if (p->symbol == nullptr) { p->func = tb_function_create(m->mod, link_name.len, cast(char const *)link_name.text, linkage, TB_COMDAT_NONE); - size_t out_param_count = 0; p->debug_type = cg_debug_type_for_proc(m, p->type); - TB_Node **params = tb_function_set_prototype_from_dbg(p->func, p->debug_type, cg_arena(), &out_param_count); - p->param_nodes = {params, cast(isize)out_param_count}; - p->proto = tb_function_get_prototype(p->func); + p->proto = tb_prototype_from_dbg(m->mod, p->debug_type); + tb_function_set_prototype(p->func, p->proto, cg_arena()); p->symbol = cast(TB_Symbol *)p->func; } @@ -142,12 +140,9 @@ gb_internal cgProcedure *cg_procedure_create_dummy(cgModule *m, String const &li p->func = tb_function_create(m->mod, link_name.len, cast(char const *)link_name.text, linkage, TB_COMDAT_NONE); - size_t out_param_count = 0; p->debug_type = cg_debug_type_for_proc(m, p->type); - TB_Node **params = tb_function_set_prototype_from_dbg(p->func, p->debug_type, cg_arena(), &out_param_count); - p->param_nodes = {params, cast(isize)out_param_count}; - p->proto = tb_function_get_prototype(p->func); - + p->proto = tb_prototype_from_dbg(m->mod, p->debug_type); + tb_function_set_prototype(p->func, p->proto, cg_arena()); p->symbol = cast(TB_Symbol *)p->func; @@ -179,25 +174,59 @@ gb_internal void cg_procedure_begin(cgProcedure *p) { GB_ASSERT(p->type->kind == Type_Proc); TypeProc *pt = &p->type->Proc; + bool is_odin_like_cc = is_calling_convention_odin(pt->calling_convention); int param_index = 0; + int param_count = p->proto->param_count; + + if (pt->results) { + Type *result_type = nullptr; + if (is_odin_like_cc) { + result_type = pt->results->Tuple.variables[pt->results->Tuple.variables.count-1]->type; + } else { + result_type = pt->results; + } + TB_DebugType *debug_type = cg_debug_type(p->module, result_type); + TB_PassingRule rule = tb_get_passing_rule_from_dbg(p->module->mod, debug_type, true); + if (rule == TB_PASSING_INDIRECT) { + param_index++; + } + } + if (pt->params != nullptr) for (Entity *e : pt->params->Tuple.variables) { if (e->kind != Entity_Variable) { continue; } - if (param_index >= p->param_nodes.count) { + GB_ASSERT_MSG(param_index < param_count, "%d < %d %.*s :: %s", param_index, param_count, LIT(p->name), type_to_string(p->type)); + + TB_Node *param_ptr = nullptr; + + TB_CharUnits size = cast(TB_CharUnits)type_size_of(e->type); + TB_CharUnits align = cast(TB_CharUnits)type_align_of(e->type); + TB_DebugType *debug_type = cg_debug_type(p->module, e->type); + TB_PassingRule rule = tb_get_passing_rule_from_dbg(p->module->mod, debug_type, false); + switch (rule) { + case TB_PASSING_DIRECT: { + TB_Node *param = tb_inst_param(p->func, param_index++); + param_ptr = tb_inst_local(p->func, size, align); + tb_inst_store(p->func, param->dt, param_ptr, param, align, false); + } break; + case TB_PASSING_INDIRECT: + // TODO(bill): does this need a copy? for non-odin calling convention stuff? + param_ptr = tb_inst_param(p->func, param_index++); break; + case TB_PASSING_IGNORE: + continue; } - TB_Node *param = p->param_nodes[param_index++]; - cgValue local = cg_value(param, alloc_type_pointer(e->type)); + GB_ASSERT(param_ptr->dt.type == TB_PTR); + + cgValue local = cg_value(param_ptr, alloc_type_pointer(e->type)); if (e != nullptr && e->token.string.len > 0 && e->token.string != "_") { // NOTE(bill): for debugging purposes only String name = e->token.string; - TB_DebugType *debug_type = cg_debug_type(p->module, e->type); - tb_node_append_attrib(param, tb_function_attrib_variable(p->func, name.len, cast(char const *)name.text, debug_type)); - + tb_node_append_attrib(param_ptr, tb_function_attrib_variable(p->func, name.len, cast(char const *)name.text, debug_type)); } cgAddr addr = cg_addr(local); if (e) { @@ -243,7 +272,9 @@ gb_internal void cg_procedure_begin(cgProcedure *p) { // } } - if (p->type->Proc.calling_convention == ProcCC_Odin) { + // isize split_offset = param_index; + + if (pt->calling_convention == ProcCC_Odin) { // NOTE(bill): Push context on to stack from implicit parameter String name = str_lit("__.context_ptr"); @@ -251,10 +282,8 @@ gb_internal void cg_procedure_begin(cgProcedure *p) { Entity *e = alloc_entity_param(nullptr, make_token_ident(name), t_context_ptr, false, false); e->flags |= EntityFlag_NoAlias; - TB_Node *param = p->param_nodes[p->param_nodes.count-1]; - param = tb_inst_load(p->func, TB_TYPE_PTR, param, cast(TB_CharUnits)build_context.ptr_size, false); - - cgValue local = cg_value(param, t_context_ptr); + TB_Node *param_ptr = tb_inst_param(p->func, param_count-1); + cgValue local = cg_value(param_ptr, t_context_ptr); cgAddr addr = cg_addr(local); map_set(&p->variable_map, e, addr); @@ -264,6 +293,26 @@ gb_internal void cg_procedure_begin(cgProcedure *p) { cd->scope_index = -1; cd->uses = +1; // make sure it has been used already } + + if (pt->has_named_results) { + auto const &results = pt->results->Tuple.variables; + for_array(i, results) { + Entity *e = results[i]; + GB_ASSERT(e->kind == Entity_Variable); + + if (e->token.string == "") { + continue; + } + GB_ASSERT(!is_blank_ident(e->token)); + + cgAddr res = cg_add_local(p, e->type, e, true); + + if (e->Variable.param_value.kind != ParameterValue_Invalid) { + cgValue c = cg_handle_param_value(p, e->type, e->Variable.param_value, e->token.pos); + cg_addr_store(p, res, c); + } + } + } } gb_internal void cg_procedure_end(cgProcedure *p) { @@ -276,7 +325,8 @@ gb_internal void cg_procedure_end(cgProcedure *p) { bool emit_asm = false; // if (p->name == "main") { if ( - p->name == "bug" ABI_PKG_NAME_SEPARATOR "main" || + p->name == "runtime" ABI_PKG_NAME_SEPARATOR "print_string" || + // p->name == "bug" ABI_PKG_NAME_SEPARATOR "main" || // p->name == "main" || false ) { @@ -301,18 +351,27 @@ gb_internal void cg_procedure_end(cgProcedure *p) { } } +gb_global String procedures_to_generate_list[] = { + str_lit("bug" ABI_PKG_NAME_SEPARATOR "main"), + str_lit("main"), +}; + 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" ABI_PKG_NAME_SEPARATOR "main" && - p->name != "main") { - return; + if ( + p->name == "runtime" ABI_PKG_NAME_SEPARATOR "print_string" || + // p->name == "bug" ABI_PKG_NAME_SEPARATOR "main" || + // p->name == "main" || + false + ) { + cg_procedure_begin(p); + cg_build_stmt(p, p->body); } - cg_build_stmt(p, p->body); + + cg_procedure_end(p); } diff --git a/src/tilde_stmt.cpp b/src/tilde_stmt.cpp index f0203e724..4fc00dd28 100644 --- a/src/tilde_stmt.cpp +++ b/src/tilde_stmt.cpp @@ -914,7 +914,10 @@ gb_internal void cg_build_assignment(cgProcedure *p, Array const &lvals, } Type *type = cg_addr_type(lval); - GB_ASSERT(are_types_identical(type, init.type)); + if (!cg_addr_is_empty(lval)) { + GB_ASSERT_MSG(are_types_identical(init.type, type), "%s = %s", type_to_string(init.type), type_to_string(type)); + } + if (init.kind == cgValue_Addr && !cg_addr_is_empty(lval)) { // NOTE(bill): This is needed for certain constructs such as this: