diff --git a/src/check_expr.cpp b/src/check_expr.cpp index 98154f33d..d5e5f7952 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -5985,8 +5985,8 @@ gb_internal bool check_call_arguments_single(CheckerContext *c, Ast *call, Opera } Entity *entity_to_use = data->gen_entity != nullptr ? data->gen_entity : e; + add_entity_use(c, ident, entity_to_use); if (!return_on_failure && entity_to_use != nullptr) { - add_entity_use(c, ident, entity_to_use); update_untyped_expr_type(c, operand->expr, entity_to_use->type, true); add_type_and_value(c, operand->expr, operand->mode, entity_to_use->type, operand->value); } @@ -7174,6 +7174,7 @@ gb_internal ExprKind check_call_expr(CheckerContext *c, Operand *operand, Ast *c c->decl->defer_used += 1; } } + add_entity_use(c, operand->expr, initial_entity); } if (operand->mode != Addressing_ProcGroup) { diff --git a/src/tilde.hpp b/src/tilde.hpp index 72d5048bb..7f2ee8076 100644 --- a/src/tilde.hpp +++ b/src/tilde.hpp @@ -309,7 +309,8 @@ gb_internal cgValue cg_addr_get_ptr(cgProcedure *p, cgAddr const &addr); gb_internal cgValue cg_emit_load(cgProcedure *p, cgValue const &ptr, bool is_volatile=false); gb_internal void cg_emit_store(cgProcedure *p, cgValue dst, cgValue src, bool is_volatile=false); -gb_internal cgAddr cg_add_local(cgProcedure *p, Type *type, Entity *e, bool zero_init); +gb_internal cgAddr cg_add_local (cgProcedure *p, Type *type, Entity *e, bool zero_init); +gb_internal cgAddr cg_add_global(cgProcedure *p, Type *type, Entity *e); gb_internal cgValue cg_address_from_load_or_generate_local(cgProcedure *p, cgValue value); gb_internal cgValue cg_copy_value_to_ptr(cgProcedure *p, cgValue value, Type *original_type, isize min_alignment); diff --git a/src/tilde_debug.cpp b/src/tilde_debug.cpp index e6e60be96..708476377 100644 --- a/src/tilde_debug.cpp +++ b/src/tilde_debug.cpp @@ -76,9 +76,18 @@ gb_internal TB_DebugType *cg_debug_type_internal_record(cgModule *m, Type *type, type_set_offsets(bt); TB_DebugType *record = tb_debug_create_struct(m->mod, 0, ""); - TB_DebugType **fields = tb_debug_record_begin(record, bt->Tuple.variables.count); + isize record_count = 0; + for (Entity *e : bt->Tuple.variables) { + if (e->kind == Entity_Variable) { + record_count += 1; + } + } + TB_DebugType **fields = tb_debug_record_begin(record, record_count); for_array(i, bt->Tuple.variables) { Entity *e = bt->Tuple.variables[i]; + if (e->kind != Entity_Variable) { + continue; + } Type *type = e->type; if (is_type_proc(type)) { type = t_rawptr; diff --git a/src/tilde_expr.cpp b/src/tilde_expr.cpp index 96f17bfcf..1966dcd8e 100644 --- a/src/tilde_expr.cpp +++ b/src/tilde_expr.cpp @@ -2399,7 +2399,12 @@ cgAddr cg_build_addr_compound_lit(cgProcedure *p, Ast *expr) { Type *type = type_of_expr(expr); Type *bt = base_type(type); - cgAddr v = cg_add_local(p, type, nullptr, true); + cgAddr v = {}; + if (p->is_startup) { + v = cg_add_global(p, type, nullptr); + } else { + v = cg_add_local(p, type, nullptr, true); + } if (cl->elems.count == 0) { // No need to create it @@ -2424,8 +2429,6 @@ cgAddr cg_build_addr_compound_lit(cgProcedure *p, Ast *expr) { } TokenPos pos = ast_token(expr).pos; - if (cl->elems.count == 0) { - } switch (bt->kind) { default: GB_PANIC("Unknown CompoundLit type: %s", type_to_string(type)); break; @@ -2493,21 +2496,22 @@ cgAddr cg_build_addr_compound_lit(cgProcedure *p, Ast *expr) { return v; } - // case Type_Map: { - // GB_ASSERT(!build_context.no_dynamic_literals); + case Type_Map: { + GB_ASSERT(!build_context.no_dynamic_literals); + GB_PANIC("TODO(bill): map literals"); - // cgValue err = cg_dynamic_map_reserve(p, v.addr, 2*cl->elems.count, pos); - // gb_unused(err); + // cgValue err = cg_dynamic_map_reserve(p, v.addr, 2*cl->elems.count, pos); + // gb_unused(err); - // for (Ast *elem : cl->elems) { - // ast_node(fv, FieldValue, elem); + // for (Ast *elem : cl->elems) { + // ast_node(fv, FieldValue, elem); - // cgValue key = cg_build_expr(p, fv->field); - // cgValue value = cg_build_expr(p, fv->value); - // cg_internal_dynamic_map_set(p, v.addr, type, key, value, elem); - // } - // break; - // } + // cgValue key = cg_build_expr(p, fv->field); + // cgValue value = cg_build_expr(p, fv->value); + // cg_internal_dynamic_map_set(p, v.addr, type, key, value, elem); + // } + break; + } case Type_Array: { auto temp_data = array_make(temporary_allocator(), 0, cl->elems.count); @@ -2523,23 +2527,21 @@ cgAddr cg_build_addr_compound_lit(cgProcedure *p, Ast *expr) { assign_array(p, temp_data); break; } - // case Type_EnumeratedArray: { - // cg_addr_store(p, v, cg_const_value(p->module, type, exact_value_compound(expr))); + case Type_EnumeratedArray: { + auto temp_data = array_make(temporary_allocator(), 0, cl->elems.count); - // auto temp_data = array_make(temporary_allocator(), 0, cl->elems.count); + populate(p, cl->elems, &temp_data, type); - // populate(p, cl->elems, &temp_data, type); + cgValue dst_ptr = cg_addr_get_ptr(p, v); + i64 index_offset = exact_value_to_i64(*bt->EnumeratedArray.min_value); + for_array(i, temp_data) { + i32 index = cast(i32)(temp_data[i].elem_index - index_offset); + temp_data[i].gep = cg_emit_array_epi(p, dst_ptr, index); + } - // cgValue dst_ptr = cg_addr_get_ptr(p, v); - // i64 index_offset = exact_value_to_i64(*bt->EnumeratedArray.min_value); - // for_array(i, temp_data) { - // i32 index = cast(i32)(temp_data[i].elem_index - index_offset); - // temp_data[i].gep = cg_emit_array_epi(p, dst_ptr, index); - // } - - // assign_array(p, temp_data); - // break; - // } + assign_array(p, temp_data); + break; + } case Type_Slice: { isize count = gb_max(cl->elems.count, cl->max_count); @@ -2570,88 +2572,89 @@ cgAddr cg_build_addr_compound_lit(cgProcedure *p, Ast *expr) { return v; } - // case Type_DynamicArray: { - // GB_ASSERT(!build_context.no_dynamic_literals); + case Type_DynamicArray: { + GB_ASSERT(!build_context.no_dynamic_literals); - // Type *et = bt->DynamicArray.elem; - // cgValue size = cg_const_int(p->module, t_int, type_size_of(et)); - // cgValue align = cg_const_int(p->module, t_int, type_align_of(et)); + Type *et = bt->DynamicArray.elem; + cgValue size = cg_const_int(p, t_int, type_size_of(et)); + cgValue align = cg_const_int(p, t_int, type_align_of(et)); - // i64 item_count = gb_max(cl->max_count, cl->elems.count); - // { + i64 item_count = gb_max(cl->max_count, cl->elems.count); + { - // auto args = array_make(temporary_allocator(), 5); - // args[0] = cg_emit_conv(p, cg_addr_get_ptr(p, v), t_rawptr); - // args[1] = size; - // args[2] = align; - // args[3] = cg_const_int(p->module, t_int, item_count); - // args[4] = cg_emit_source_code_location_as_global(p, proc_name, pos); - // cg_emit_runtime_call(p, "__dynamic_array_reserve", args); - // } + auto args = slice_make(temporary_allocator(), 5); + args[0] = cg_emit_conv(p, cg_addr_get_ptr(p, v), t_rawptr); + args[1] = size; + args[2] = align; + args[3] = cg_const_int(p, t_int, item_count); + args[4] = cg_emit_source_code_location_as_global(p, proc_name, pos); + cg_emit_runtime_call(p, "__dynamic_array_reserve", args); + } - // cgValue items = cg_generate_local_array(p, et, item_count); + Type *array_type = alloc_type_array(et, item_count); + cgAddr items_addr = cg_add_local(p, array_type, nullptr, true); + cgValue items = cg_addr_get_ptr(p, items_addr); - // auto temp_data = array_make(temporary_allocator(), 0, cl->elems.count); - // populate(p, cl->elems, &temp_data, type); + auto temp_data = array_make(temporary_allocator(), 0, cl->elems.count); + populate(p, cl->elems, &temp_data, type); - // for_array(i, temp_data) { - // temp_data[i].gep = cg_emit_array_epi(p, items, temp_data[i].elem_index); - // } - // assign_array(p, temp_data); + for_array(i, temp_data) { + temp_data[i].gep = cg_emit_array_epi(p, items, temp_data[i].elem_index); + } + assign_array(p, temp_data); - // { - // auto args = array_make(temporary_allocator(), 6); - // args[0] = cg_emit_conv(p, v.addr, t_rawptr); - // args[1] = size; - // args[2] = align; - // args[3] = cg_emit_conv(p, items, t_rawptr); - // args[4] = cg_const_int(p->module, t_int, item_count); - // args[5] = cg_emit_source_code_location_as_global(p, proc_name, pos); - // cg_emit_runtime_call(p, "__dynamic_array_append", args); - // } - // break; - // } + { + auto args = slice_make(temporary_allocator(), 6); + args[0] = cg_emit_conv(p, v.addr, t_rawptr); + args[1] = size; + args[2] = align; + args[3] = cg_emit_conv(p, items, t_rawptr); + args[4] = cg_const_int(p, t_int, item_count); + args[5] = cg_emit_source_code_location_as_global(p, proc_name, pos); + cg_emit_runtime_call(p, "__dynamic_array_append", args); + } + break; + } - // case Type_Basic: { - // GB_ASSERT(is_type_any(bt)); - // cg_addr_store(p, v, cg_const_value(p->module, type, exact_value_compound(expr))); - // String field_names[2] = { - // str_lit("data"), - // str_lit("id"), - // }; - // Type *field_types[2] = { - // t_rawptr, - // t_typeid, - // }; + case Type_Basic: { + GB_ASSERT(is_type_any(bt)); + String field_names[2] = { + str_lit("data"), + str_lit("id"), + }; + Type *field_types[2] = { + t_rawptr, + t_typeid, + }; - // for_array(field_index, cl->elems) { - // Ast *elem = cl->elems[field_index]; + for_array(field_index, cl->elems) { + Ast *elem = cl->elems[field_index]; - // cgValue field_expr = {}; - // isize index = field_index; + cgValue field_expr = {}; + isize index = field_index; - // if (elem->kind == Ast_FieldValue) { - // ast_node(fv, FieldValue, elem); - // Selection sel = lookup_field(bt, fv->field->Ident.token.string, false); - // index = sel.index[0]; - // elem = fv->value; - // } else { - // TypeAndValue tav = type_and_value_of_expr(elem); - // Selection sel = lookup_field(bt, field_names[field_index], false); - // index = sel.index[0]; - // } + if (elem->kind == Ast_FieldValue) { + ast_node(fv, FieldValue, elem); + Selection sel = lookup_field(bt, fv->field->Ident.token.string, false); + index = sel.index[0]; + elem = fv->value; + } else { + TypeAndValue tav = type_and_value_of_expr(elem); + Selection sel = lookup_field(bt, field_names[field_index], false); + index = sel.index[0]; + } - // field_expr = cg_build_expr(p, elem); + field_expr = cg_build_expr(p, elem); - // GB_ASSERT(field_expr.type->kind != Type_Tuple); + GB_ASSERT(field_expr.type->kind != Type_Tuple); - // Type *ft = field_types[index]; - // cgValue fv = cg_emit_conv(p, field_expr, ft); - // cgValue gep = cg_emit_struct_ep(p, cg_addr_get_ptr(p, v), cast(i32)index); - // cg_emit_store(p, gep, fv); - // } - // break; - // } + Type *ft = field_types[index]; + cgValue fv = cg_emit_conv(p, field_expr, ft); + cgValue gep = cg_emit_struct_ep(p, cg_addr_get_ptr(p, v), index); + cg_emit_store(p, gep, fv); + } + break; + } case Type_BitSet: { i64 sz = type_size_of(type); @@ -2679,48 +2682,41 @@ cgAddr cg_build_addr_compound_lit(cgProcedure *p, Ast *expr) { return v; } - // case Type_Matrix: { - // cg_addr_store(p, v, cg_const_value(p->module, type, exact_value_compound(expr))); + case Type_Matrix: { + auto temp_data = array_make(temporary_allocator(), 0, cl->elems.count); - // auto temp_data = array_make(temporary_allocator(), 0, cl->elems.count); + populate(p, cl->elems, &temp_data, type); - // populate(p, cl->elems, &temp_data, type); + cgValue dst_ptr = cg_addr_get_ptr(p, v); + for_array(i, temp_data) { + temp_data[i].gep = cg_emit_array_epi(p, dst_ptr, temp_data[i].elem_index); + } - // cgValue dst_ptr = cg_addr_get_ptr(p, v); - // for_array(i, temp_data) { - // temp_data[i].gep = cg_emit_array_epi(p, dst_ptr, temp_data[i].elem_index); - // } + assign_array(p, temp_data); + break; + } - // assign_array(p, temp_data); - // break; - // } + case Type_SimdVector: { + // auto temp_data = array_make(temporary_allocator(), 0, cl->elems.count); - // case Type_SimdVector: { - // cgValue vector_value = cg_const_value(p->module, type, exact_value_compound(expr)); - // defer (cg_addr_store(p, v, vector_value)); + // populate(p, cl->elems, &temp_data, type); - // auto temp_data = array_make(temporary_allocator(), 0, cl->elems.count); + // // TODO(bill): reduce the need for individual `insertelement` if a `shufflevector` + // // might be a better option + // for (auto const &td : temp_data) if (td.value.node != nullptr) { + // if (td.elem_length > 0) { + // for (i64 k = 0; k < td.elem_length; k++) { + // LLVMValueRef index = cg_const_int(p->module, t_u32, td.elem_index + k).value; + // vector_value.value = LLVMBuildInsertElement(p->builder, vector_value.value, td.value.value, index, ""); + // } + // } else { + // LLVMValueRef index = cg_const_int(p->module, t_u32, td.elem_index).value; + // vector_value.value = LLVMBuildInsertElement(p->builder, vector_value.value, td.value.value, index, ""); - // populate(p, cl->elems, &temp_data, type); - - // // TODO(bill): reduce the need for individual `insertelement` if a `shufflevector` - // // might be a better option - // for (auto const &td : temp_data) { - // if (td.value.value != nullptr) { - // if (td.elem_length > 0) { - // for (i64 k = 0; k < td.elem_length; k++) { - // LLVMValueRef index = cg_const_int(p->module, t_u32, td.elem_index + k).value; - // vector_value.value = LLVMBuildInsertElement(p->builder, vector_value.value, td.value.value, index, ""); - // } - // } else { - // LLVMValueRef index = cg_const_int(p->module, t_u32, td.elem_index).value; - // vector_value.value = LLVMBuildInsertElement(p->builder, vector_value.value, td.value.value, index, ""); - - // } - // } - // } - // break; - // } + // } + // } + break; + } } return v; diff --git a/src/tilde_proc.cpp b/src/tilde_proc.cpp index 80948adea..7e751ac82 100644 --- a/src/tilde_proc.cpp +++ b/src/tilde_proc.cpp @@ -582,8 +582,13 @@ gb_internal cgValue cg_emit_call(cgProcedure * p, cgValue value, Slice params[param_index++] = local; } } + isize param_entity_index = 0; for_array(i, args) { - Type *param_type = param_entities[i]->type; + Entity *param_entity = nullptr; + do { + param_entity = param_entities[param_entity_index++]; + } while (param_entity->kind != Entity_Variable); + Type *param_type = param_entity->type; cgValue arg = args[i]; arg = cg_emit_conv(p, arg, param_type); arg = cg_flatten_value(p, arg); @@ -839,7 +844,15 @@ gb_internal cgValue cg_build_call_expr_internal(cgProcedure *p, Ast *expr) { GB_ASSERT(ce->split_args != nullptr); - auto args = array_make(temporary_allocator(), 0, pt->param_count); + isize internal_param_count = 0; + if (pt->params) for (Entity *e : pt->params->Tuple.variables) { + if (e->kind == Entity_Variable) { + internal_param_count += 1; + } + } + GB_ASSERT(internal_param_count <= pt->param_count); + + auto args = array_make(temporary_allocator(), 0, internal_param_count); bool vari_expand = (ce->ellipsis.pos.line != 0); bool is_c_vararg = pt->c_vararg; @@ -918,7 +931,7 @@ gb_internal cgValue cg_build_call_expr_internal(cgProcedure *p, Ast *expr) { } if (!is_c_vararg) { - array_resize(&args, pt->param_count); + array_resize(&args, internal_param_count); } for (Ast *arg : ce->split_args->named) { @@ -938,39 +951,39 @@ gb_internal cgValue cg_build_call_expr_internal(cgProcedure *p, Ast *expr) { if (pt->params != nullptr) { - isize min_count = pt->params->Tuple.variables.count; + isize min_count = internal_param_count; if (is_c_vararg) { min_count -= 1; } - GB_ASSERT(args.count >= min_count); - for_array(arg_index, pt->params->Tuple.variables) { - Entity *e = pt->params->Tuple.variables[arg_index]; - if (pt->variadic && arg_index == pt->variadic_index) { + GB_ASSERT_MSG(args.count >= min_count, "in %.*s", LIT(p->name)); + isize arg_index = 0; + for_array(param_index, pt->params->Tuple.variables) { + Entity *e = pt->params->Tuple.variables[param_index]; + if (e->kind == Entity_TypeName) { + continue; + } else if (e->kind == Entity_Constant) { + continue; + } + GB_ASSERT(e->kind == Entity_Variable); + + if (pt->variadic && param_index == pt->variadic_index) { if (!is_c_vararg && args[arg_index].node == nullptr) { - args[arg_index] = cg_const_nil(p, e->type); + args[arg_index++] = cg_const_nil(p, e->type); } continue; } cgValue arg = args[arg_index]; if (arg.node == nullptr) { - switch (e->kind) { - case Entity_TypeName: - case Entity_Constant: - break; - case Entity_Variable: - args[arg_index] = cg_handle_param_value(p, e->type, e->Variable.param_value, pos); - break; - default: - GB_PANIC("Unknown entity kind %.*s\n", LIT(entity_strings[e->kind])); - } + GB_ASSERT(e->kind == Entity_Variable); + args[arg_index++] = cg_handle_param_value(p, e->type, e->Variable.param_value, pos); } else { - args[arg_index] = cg_emit_conv(p, arg, e->type); + args[arg_index++] = cg_emit_conv(p, arg, e->type); } } } - isize final_count = is_c_vararg ? args.count : pt->param_count; + isize final_count = is_c_vararg ? args.count : internal_param_count; auto call_args = slice(args, 0, final_count); return cg_emit_call(p, value, call_args); diff --git a/src/tilde_stmt.cpp b/src/tilde_stmt.cpp index 88c266689..0b5f122d4 100644 --- a/src/tilde_stmt.cpp +++ b/src/tilde_stmt.cpp @@ -747,6 +747,34 @@ gb_internal cgAddr cg_add_local(cgProcedure *p, Type *type, Entity *e, bool zero return addr; } +gb_internal cgAddr cg_add_global(cgProcedure *p, Type *type, Entity *e) { + GB_ASSERT(type != nullptr); + + isize size = type_size_of(type); + TB_CharUnits alignment = cast(TB_CharUnits)type_align_of(type); + if (is_type_matrix(type)) { + alignment *= 2; // NOTE(bill): Just in case + } + + TB_Global *global = tb_global_create(p->module->mod, 0, "", nullptr, TB_LINKAGE_PRIVATE); + tb_global_set_storage(p->module->mod, tb_module_get_data(p->module->mod), global, size, alignment, 0); + TB_Node *local = tb_inst_get_symbol_address(p->func, cast(TB_Symbol *)global); + + 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, type); + tb_node_append_attrib(local, tb_function_attrib_variable(p->func, name.len, cast(char const *)name.text, debug_type)); + } + + cgAddr addr = cg_addr(cg_value(local, alloc_type_pointer(type))); + if (e) { + map_set(&p->variable_map, e, addr); + } + return addr; +} + + gb_internal cgValue cg_copy_value_to_ptr(cgProcedure *p, cgValue value, Type *original_type, isize min_alignment) { TB_CharUnits size = cast(TB_CharUnits)type_size_of(original_type); TB_CharUnits align = cast(TB_CharUnits)gb_max(type_align_of(original_type), min_alignment); diff --git a/src/types.cpp b/src/types.cpp index 17945b109..f6e377cdc 100644 --- a/src/types.cpp +++ b/src/types.cpp @@ -3646,18 +3646,26 @@ gb_internal i64 *type_set_offsets_of(Slice const &fields, bool is_pack } } else if (is_packed) { for_array(i, fields) { - i64 size = type_size_of(fields[i]->type); - offsets[i] = curr_offset; - curr_offset += size; + if (fields[i]->kind != Entity_Variable) { + offsets[i] = -1; + } else { + i64 size = type_size_of(fields[i]->type); + offsets[i] = curr_offset; + curr_offset += size; + } } } else { for_array(i, fields) { - Type *t = fields[i]->type; - i64 align = gb_max(type_align_of(t), 1); - i64 size = gb_max(type_size_of( t), 0); - curr_offset = align_formula(curr_offset, align); - offsets[i] = curr_offset; - curr_offset += size; + if (fields[i]->kind != Entity_Variable) { + offsets[i] = -1; + } else { + Type *t = fields[i]->type; + i64 align = gb_max(type_align_of(t), 1); + i64 size = gb_max(type_size_of( t), 0); + curr_offset = align_formula(curr_offset, align); + offsets[i] = curr_offset; + curr_offset += size; + } } } return offsets; @@ -3924,7 +3932,9 @@ gb_internal i64 type_offset_of(Type *t, i64 index, Type **field_type_) { if (gb_is_between(index, 0, t->Tuple.variables.count-1)) { GB_ASSERT(t->Tuple.offsets != nullptr); if (field_type_) *field_type_ = t->Tuple.variables[index]->type; - return t->Tuple.offsets[index]; + i64 offset = t->Tuple.offsets[index]; + GB_ASSERT(offset >= 0); + return offset; } break;