diff --git a/src/check_expr.cpp b/src/check_expr.cpp index 60c96b9ab..23c823186 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -125,7 +125,7 @@ bool check_is_assignable_to_using_subtype(Type *src, Type *dst) { return false; } - for (isize i = 0; i < src->Struct.field_count; i++) { + for_array(i, src->Struct.fields) { Entity *f = src->Struct.fields[i]; if (f->kind != Entity_Variable || (f->flags&EntityFlag_Using) == 0) { continue; @@ -733,7 +733,7 @@ void populate_using_entity_map(Checker *c, AstNode *node, Type *t, Map } if (t->kind == Type_Struct) { - for (isize i = 0; i < t->Struct.field_count; i++) { + for_array(i, t->Struct.fields) { Entity *f = t->Struct.fields[i]; GB_ASSERT(f->kind == Entity_Variable); String name = f->token.string; @@ -1228,9 +1228,8 @@ void check_struct_type(Checker *c, Type *struct_type, AstNode *node, ArrayStruct.scope = c->context.scope; struct_type->Struct.is_packed = st->is_packed; struct_type->Struct.is_ordered = st->is_ordered; - struct_type->Struct.fields = fields.data; - struct_type->Struct.fields_in_src_order = fields.data; - struct_type->Struct.field_count = fields.count; + struct_type->Struct.fields = fields; + struct_type->Struct.fields_in_src_order = fields; struct_type->Struct.polymorphic_params = polymorphic_params; struct_type->Struct.is_polymorphic = is_polymorphic; struct_type->Struct.is_poly_specialized = is_poly_specialized; @@ -1245,8 +1244,9 @@ void check_struct_type(Checker *c, Type *struct_type, AstNode *node, ArrayStruct.offsets = nullptr; // NOTE(bill): Reorder fields for reduced size/performance - Entity **reordered_fields = gb_alloc_array(c->allocator, Entity *, fields.count); - for (isize i = 0; i < fields.count; i++) { + Array reordered_fields = {}; + array_init_count(&reordered_fields, c->allocator, fields.count); + for_array(i, fields) { reordered_fields[i] = struct_type->Struct.fields_in_src_order[i]; } @@ -1254,9 +1254,9 @@ void check_struct_type(Checker *c, Type *struct_type, AstNode *node, Arrayallocator; // NOTE(bill): compound literal order must match source not layout - gb_sort_array(reordered_fields, fields.count, cmp_reorder_struct_fields); + gb_sort_array(reordered_fields.data, fields.count, cmp_reorder_struct_fields); - for (isize i = 0; i < fields.count; i++) { + for_array(i, fields) { reordered_fields[i]->Variable.field_index = i; } @@ -2767,16 +2767,16 @@ void check_map_type(Checker *c, Type *type, AstNode *node) { check_open_scope(c, dummy_node); isize field_count = 3; - Entity **fields = gb_alloc_array(a, Entity *, field_count); - fields[0] = make_entity_field(a, c->context.scope, make_token_ident(str_lit("key")), t_map_key, false, 0); - fields[1] = make_entity_field(a, c->context.scope, make_token_ident(str_lit("next")), t_int, false, 1); - fields[2] = make_entity_field(a, c->context.scope, make_token_ident(str_lit("value")), value, false, 2); + Array fields = {}; + array_init(&fields, a, 3); + array_add(&fields, make_entity_field(a, c->context.scope, make_token_ident(str_lit("key")), t_map_key, false, 0)); + array_add(&fields, make_entity_field(a, c->context.scope, make_token_ident(str_lit("next")), t_int, false, 1)); + array_add(&fields, make_entity_field(a, c->context.scope, make_token_ident(str_lit("value")), value, false, 2)); check_close_scope(c); entry_type->Struct.fields = fields; entry_type->Struct.fields_in_src_order = fields; - entry_type->Struct.field_count = field_count; type_set_offsets(a, entry_type); type->Map.entry_type = entry_type; @@ -2798,16 +2798,15 @@ void check_map_type(Checker *c, Type *type, AstNode *node) { Type *hashes_type = make_type_dynamic_array(a, t_int); Type *entries_type = make_type_dynamic_array(a, type->Map.entry_type); - isize field_count = 2; - Entity **fields = gb_alloc_array(a, Entity *, field_count); - fields[0] = make_entity_field(a, c->context.scope, make_token_ident(str_lit("hashes")), hashes_type, false, 0); - fields[1] = make_entity_field(a, c->context.scope, make_token_ident(str_lit("entries")), entries_type, false, 1); + Array fields = {}; + array_init(&fields, a, 2); + array_add(&fields, make_entity_field(a, c->context.scope, make_token_ident(str_lit("hashes")), hashes_type, false, 0)); + array_add(&fields, make_entity_field(a, c->context.scope, make_token_ident(str_lit("entries")), entries_type, false, 1)); check_close_scope(c); generated_struct_type->Struct.fields = fields; generated_struct_type->Struct.fields_in_src_order = fields; - generated_struct_type->Struct.field_count = field_count; type_set_offsets(a, generated_struct_type); type->Map.generated_struct_type = generated_struct_type; @@ -3686,8 +3685,8 @@ String check_down_cast_name(Type *dst_, Type *src_) { Type *dst = type_deref(dst_); Type *src = type_deref(src_); Type *dst_s = base_type(dst); - GB_ASSERT(is_type_struct(dst_s) || is_type_raw_union(dst_s)); - for (isize i = 0; i < dst_s->Struct.field_count; i++) { + GB_ASSERT(dst_s->kind == Type_Struct); + for_array(i, dst_s->Struct.fields) { Entity *f = dst_s->Struct.fields[i]; GB_ASSERT(f->kind == Entity_Variable && f->flags & EntityFlag_Field); if (f->flags & EntityFlag_Using) { @@ -4683,7 +4682,7 @@ Entity *check_selector(Checker *c, Operand *operand, AstNode *node, Type *type_h i64 max_count = 0; switch (type->kind) { - case Type_Struct: max_count = type->Struct.field_count; break; + case Type_Struct: max_count = type->Struct.fields.count; break; case Type_Tuple: max_count = type->Tuple.variables.count; break; } @@ -5582,10 +5581,10 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id gbAllocator a = c->allocator; Type *tuple = make_type_tuple(a); - i32 variable_count = type->Struct.field_count; + i32 variable_count = type->Struct.fields.count; array_init_count(&tuple->Tuple.variables, a, variable_count); // TODO(bill): Should I copy each of the entities or is this good enough? - gb_memcopy_array(tuple->Tuple.variables.data, type->Struct.fields_in_src_order, variable_count); + gb_memcopy_array(tuple->Tuple.variables.data, type->Struct.fields_in_src_order.data, variable_count); operand->type = tuple; operand->mode = Addressing_Value; @@ -6533,7 +6532,7 @@ Entity *find_using_index_expr(Type *t) { return nullptr; } - for (isize i = 0; i < t->Struct.field_count; i++) { + for_array(i, t->Struct.fields) { Entity *f = t->Struct.fields[i]; if (f->kind == Entity_Variable && (f->flags & EntityFlag_Field) != 0 && @@ -7338,8 +7337,8 @@ ExprKind check_expr_base_internal(Checker *c, Operand *o, AstNode *node, Type *t } { // Checker values - isize field_count = t->Struct.field_count; - isize min_field_count = t->Struct.field_count; + isize field_count = t->Struct.fields.count; + isize min_field_count = t->Struct.fields.count; for (isize i = min_field_count-1; i >= 0; i--) { Entity *e = t->Struct.fields_in_src_order[i]; GB_ASSERT(e->kind == Entity_Variable); @@ -7412,7 +7411,7 @@ ExprKind check_expr_base_internal(Checker *c, Operand *o, AstNode *node, Type *t } } else { bool all_fields_are_blank = true; - for (isize i = 0; i < t->Struct.field_count; i++) { + for_array(i, t->Struct.fields_in_src_order) { Entity *field = t->Struct.fields_in_src_order[i]; if (!is_blank_ident(field->token)) { all_fields_are_blank = false; diff --git a/src/checker.cpp b/src/checker.cpp index 99031ff99..0f628a84a 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -1175,7 +1175,7 @@ void add_type_info_type(Checker *c, Type *t) { break; case Type_Struct: { - for (isize i = 0; i < bt->Struct.field_count; i++) { + for_array(i, bt->Struct.fields) { Entity *f = bt->Struct.fields[i]; add_type_info_type(c, f->type); } @@ -1346,7 +1346,7 @@ void init_preload(Checker *c) { t_type_info_enum_value = type_info_enum_value->type; t_type_info_enum_value_ptr = make_type_pointer(c->allocator, t_type_info_enum_value); - GB_ASSERT(tis->field_count == 3); + GB_ASSERT(tis->fields.count == 3); Entity *type_info_variant = tis->fields_in_src_order[2]; Type *tiv_type = type_info_variant->type; diff --git a/src/ir.cpp b/src/ir.cpp index c13104479..36efefb94 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -663,7 +663,7 @@ bool ir_type_has_default_values(Type *t) { case Type_Struct: if (!t->Struct.is_raw_union) { - for (isize i = 0; i < t->Struct.field_count; i++) { + for_array(i, t->Struct.fields) { Entity *f = t->Struct.fields_in_src_order[i]; if (f->kind != Entity_Variable) continue; if (f->Variable.default_is_nil) { @@ -2375,8 +2375,6 @@ irValue *ir_emit_struct_ep(irProcedure *proc, irValue *s, i32 index) { Type *result_type = nullptr; if (is_type_struct(t)) { - GB_ASSERT(t->Struct.field_count > 0); - GB_ASSERT_MSG(gb_is_between(index, 0, t->Struct.field_count-1), "0..%d..%d", index, t->Struct.field_count); result_type = make_type_pointer(a, t->Struct.fields[index]->type); } else if (is_type_union(t)) { GB_ASSERT(index == -1); @@ -2437,8 +2435,6 @@ irValue *ir_emit_struct_ev(irProcedure *proc, irValue *s, i32 index) { Type *result_type = nullptr; if (is_type_struct(t)) { - GB_ASSERT(t->Struct.field_count > 0); - GB_ASSERT(gb_is_between(index, 0, t->Struct.field_count-1)); result_type = t->Struct.fields[index]->type; } else if (is_type_union(t)) { GB_ASSERT(index == -1); @@ -2755,7 +2751,7 @@ String ir_lookup_subtype_polymorphic_field(CheckerInfo *info, Type *dst, Type *s // bool dst_is_ptr = dst != prev_dst; GB_ASSERT(is_type_struct(src) || is_type_union(src)); - for (isize i = 0; i < src->Struct.field_count; i++) { + for_array(i, src->Struct.fields) { Entity *f = src->Struct.fields[i]; if (f->kind == Entity_Variable && f->flags & EntityFlag_Using) { if (are_types_identical(dst, f->type)) { @@ -4437,7 +4433,7 @@ irValue *ir_build_builtin_proc(irProcedure *proc, AstNode *expr, TypeAndValue tv GB_ASSERT(is_type_tuple(tv.type)); irValue *tuple = ir_add_local_generated(proc, tv.type); - for (isize src_index = 0; src_index < t->Struct.field_count; src_index++) { + for_array(src_index, t->Struct.fields) { Entity *field = t->Struct.fields_in_src_order[src_index]; i32 field_index = field->Variable.field_index; irValue *f = ir_emit_struct_ev(proc, s, field_index); @@ -6626,7 +6622,7 @@ void ir_build_stmt_internal(irProcedure *proc, AstNode *node) { Type *enum_ptr = make_type_pointer(a, t); t = base_type(t); Type *core_elem = core_type(t); - i64 enum_count = t->Struct.field_count; + i64 enum_count = t->Struct.fields.count; irValue *max_count = ir_const_int(a, enum_count); irValue *eti = ir_emit_union_cast(proc, ir_type_info(proc, t), t_type_info_enum_ptr, pos); @@ -7341,7 +7337,7 @@ void ir_init_module(irModule *m, Checker *c) { count += t->Union.variants.count; break; case Type_Struct: - count += t->Struct.field_count; + count += t->Struct.fields.count; break; case Type_Tuple: count += t->Tuple.variables.count; @@ -8184,7 +8180,7 @@ void ir_gen_tree(irGen *s) { ir_emit_store(proc, ir_emit_struct_ep(proc, tag, 7), is_custom_align); } - i32 count = t->Struct.field_count; + i32 count = t->Struct.fields.count; irValue *memory_types = ir_type_info_member_types_offset (proc, count); irValue *memory_names = ir_type_info_member_names_offset (proc, count); diff --git a/src/ir_print.cpp b/src/ir_print.cpp index 86af71f54..78090e6ac 100644 --- a/src/ir_print.cpp +++ b/src/ir_print.cpp @@ -314,11 +314,11 @@ void ir_print_type(irFileBuffer *f, irModule *m, Type *t) { ir_fprintf(f, "{"); if (t->Struct.custom_align > 0) { ir_fprintf(f, "[0 x <%lld x i8>]", t->Struct.custom_align); - if (t->Struct.field_count > 0) { + if (t->Struct.fields.count > 0) { ir_fprintf(f, ", "); } } - for (isize i = 0; i < t->Struct.field_count; i++) { + for_array(i, t->Struct.fields) { if (i > 0) { ir_fprintf(f, ", "); } @@ -585,7 +585,7 @@ void ir_print_exact_value(irFileBuffer *f, irModule *m, ExactValue value, Type * } - isize value_count = type->Struct.field_count; + isize value_count = type->Struct.fields.count; ExactValue *values = gb_alloc_array(m->tmp_allocator, ExactValue, value_count); bool *visited = gb_alloc_array(m->tmp_allocator, bool, value_count); @@ -670,7 +670,7 @@ void ir_print_exact_value(irFileBuffer *f, irModule *m, ExactValue value, Type * ir_fprintf(f, "zeroinitializer"); } else { if (is_type_struct(type)) { - i32 value_count = type->Struct.field_count; + i32 value_count = type->Struct.fields.count; if (type->Struct.is_packed) ir_fprintf(f, "<"); ir_fprintf(f, "{"); if (type->Struct.custom_align > 0) { diff --git a/src/ssa.cpp b/src/ssa.cpp index 1ba1f610d..d934bb644 100644 --- a/src/ssa.cpp +++ b/src/ssa.cpp @@ -653,10 +653,10 @@ bool can_ssa_type(Type *t) { case Type_Struct: if (!t->Struct.is_raw_union) { - if (t->Struct.field_count > SSA_MAX_STRUCT_FIELD_COUNT) { + if (t->Struct.fields.count > SSA_MAX_STRUCT_FIELD_COUNT) { return false; } - for (isize i = 0; i < t->Struct.field_count; i++) { + for_array(i, t->Struct.fields) { if (!can_ssa_type(t->Struct.fields[i]->type)) { return false; } @@ -810,8 +810,7 @@ ssaValue *ssa_emit_ptr_index(ssaProc *p, ssaValue *s, i64 index) { Type *result_type = nullptr; if (is_type_struct(t)) { - GB_ASSERT(t->Struct.field_count > 0); - GB_ASSERT(gb_is_between(index, 0, t->Struct.field_count-1)); + GB_ASSERT(t->Struct.fields.count > 0); result_type = make_type_pointer(a, t->Struct.fields[index]->type); } else if (is_type_tuple(t)) { GB_ASSERT(t->Tuple.variables.count > 0); @@ -868,13 +867,11 @@ ssaValue *ssa_emit_value_index(ssaProc *p, ssaValue *s, i64 index) { Type *result_type = nullptr; if (is_type_struct(t)) { - GB_ASSERT(t->Struct.field_count > 0); - GB_ASSERT(gb_is_between(index, 0, t->Struct.field_count-1)); + GB_ASSERT(t->Struct.fields.count > 0); result_type = t->Struct.fields[index]->type; } else if (is_type_union(t)) { type_set_offsets(a, t); - GB_ASSERT(t->Struct.field_count > 0); - GB_ASSERT(gb_is_between(index, 0, t->Struct.field_count-1)); + GB_ASSERT(t->Struct.fields.count > 0); result_type = t->Struct.fields[index]->type; } else if (is_type_tuple(t)) { GB_ASSERT(t->Tuple.variables.count > 0); @@ -1658,7 +1655,7 @@ ssaValue *ssa_build_expr(ssaProc *p, AstNode *expr) { default: GB_PANIC("Unknown float size"); } } - // IMPORTANT TODO(bill): Do constant struct/array literals correctly + // IMPORTANT TODO(bill): Do constant str/array literals correctly return ssa_const_nil(p, tv.type); } diff --git a/src/types.cpp b/src/types.cpp index 888cb12df..360b9ed15 100644 --- a/src/types.cpp +++ b/src/types.cpp @@ -69,13 +69,12 @@ struct BasicType { }; struct TypeStruct { - Entity **fields; - i32 field_count; // == struct_offsets count - Entity **fields_in_src_order; // Entity_Variable + Array fields; + Array fields_in_src_order; AstNode *node; Scope * scope; - i64 * offsets; + i64 * offsets; // == fields.count bool are_offsets_set; bool are_offsets_being_processed; bool is_packed; @@ -983,7 +982,7 @@ bool is_type_polymorphic(Type *t) { if (t->Struct.is_polymorphic) { return true; } - for (isize i = 0; i < t->Struct.field_count; i++) { + for_array(i, t->Struct.fields) { if (is_type_polymorphic(t->Struct.fields[i]->type)) { return true; } @@ -1131,12 +1130,12 @@ bool are_types_identical(Type *x, Type *y) { case Type_Struct: if (y->kind == Type_Struct) { if (x->Struct.is_raw_union == y->Struct.is_raw_union && - x->Struct.field_count == y->Struct.field_count && - x->Struct.is_packed == y->Struct.is_packed && - x->Struct.is_ordered == y->Struct.is_ordered && + x->Struct.fields.count == y->Struct.fields.count && + x->Struct.is_packed == y->Struct.is_packed && + x->Struct.is_ordered == y->Struct.is_ordered && x->Struct.custom_align == y->Struct.custom_align) { // TODO(bill); Fix the custom alignment rule - for (isize i = 0; i < x->Struct.field_count; i++) { + for_array(i, x->Struct.fields) { Entity *xf = x->Struct.fields[i]; Entity *yf = y->Struct.fields[i]; if (!are_types_identical(xf->type, yf->type)) { @@ -1279,7 +1278,7 @@ bool is_type_cte_safe(Type *type) { if (type->Struct.is_raw_union) { return false; } - for (isize i = 0; i < type->Struct.field_count; i++) { + for_array(i, type->Struct.fields) { Entity *v = type->Struct.fields[i]; if (!is_type_cte_safe(v->type)) { return false; @@ -1401,7 +1400,7 @@ Selection lookup_field_from_index(gbAllocator a, Type *type, i64 index) { i64 max_count = 0; switch (type->kind) { - case Type_Struct: max_count = type->Struct.field_count; break; + case Type_Struct: max_count = type->Struct.fields.count; break; case Type_Tuple: max_count = type->Tuple.variables.count; break; case Type_BitField: max_count = type->BitField.field_count; break; } @@ -1601,7 +1600,7 @@ Selection lookup_field_with_selection(gbAllocator a, Type *type_, String field_n return sel; } } else if (type->kind == Type_Struct) { - for (isize i = 0; i < type->Struct.field_count; i++) { + for_array(i, type->Struct.fields) { Entity *f = type->Struct.fields[i]; if (f->kind != Entity_Variable || (f->flags & EntityFlag_Field) == 0) { continue; @@ -1842,7 +1841,7 @@ i64 type_align_of_internal(gbAllocator allocator, Type *t, TypePath *path) { case Type_Struct: { if (t->Struct.is_raw_union) { i64 max = 1; - for (isize i = 0; i < t->Struct.field_count; i++) { + for_array(i, t->Struct.fields) { Type *field_type = t->Struct.fields[i]->type; type_path_push(path, field_type); if (path->failure) { @@ -1859,12 +1858,12 @@ i64 type_align_of_internal(gbAllocator allocator, Type *t, TypePath *path) { if (t->Struct.custom_align > 0) { return gb_clamp(t->Struct.custom_align, 1, build_context.max_align); } - if (t->Struct.field_count > 0) { + if (t->Struct.fields.count > 0) { i64 max = 1; if (t->Struct.is_packed) { max = build_context.word_size; } - for (isize i = 0; i < t->Struct.field_count; i++) { + for_array(i, t->Struct.fields) { Type *field_type = t->Struct.fields[i]->type; type_path_push(path, field_type); if (path->failure) { @@ -1896,21 +1895,21 @@ i64 type_align_of_internal(gbAllocator allocator, Type *t, TypePath *path) { return gb_clamp(next_pow2(type_size_of_internal(allocator, t, path)), 1, build_context.word_size); } -i64 *type_set_offsets_of(gbAllocator allocator, Entity **fields, isize field_count, bool is_packed, bool is_raw_union) { - i64 *offsets = gb_alloc_array(allocator, i64, field_count); +i64 *type_set_offsets_of(gbAllocator allocator, Array fields, bool is_packed, bool is_raw_union) { + i64 *offsets = gb_alloc_array(allocator, i64, fields.count); i64 curr_offset = 0; if (is_raw_union) { - for (isize i = 0; i < field_count; i++) { + for_array(i, fields) { offsets[i] = 0; } } else if (is_packed) { - for (isize i = 0; i < field_count; i++) { + for_array(i, fields) { i64 size = type_size_of(allocator, fields[i]->type); offsets[i] = curr_offset; curr_offset += size; } } else { - for (isize i = 0; i < field_count; i++) { + for_array(i, fields) { i64 align = gb_max(type_align_of(allocator, fields[i]->type), 1); i64 size = gb_max(type_size_of(allocator, fields[i]->type), 0); curr_offset = align_formula(curr_offset, align); @@ -1926,14 +1925,14 @@ bool type_set_offsets(gbAllocator allocator, Type *t) { if (t->kind == Type_Struct) { if (!t->Struct.are_offsets_set) { t->Struct.are_offsets_being_processed = true; - t->Struct.offsets = type_set_offsets_of(allocator, t->Struct.fields, t->Struct.field_count, t->Struct.is_packed, t->Struct.is_raw_union); + t->Struct.offsets = type_set_offsets_of(allocator, t->Struct.fields, t->Struct.is_packed, t->Struct.is_raw_union); t->Struct.are_offsets_set = true; return true; } } else if (is_type_tuple(t)) { if (!t->Tuple.are_offsets_set) { t->Struct.are_offsets_being_processed = true; - t->Tuple.offsets = type_set_offsets_of(allocator, t->Tuple.variables.data, t->Tuple.variables.count, false, false); + t->Tuple.offsets = type_set_offsets_of(allocator, t->Tuple.variables, false, false); t->Tuple.are_offsets_set = true; return true; } @@ -2086,7 +2085,7 @@ i64 type_size_of_internal(gbAllocator allocator, Type *t, TypePath *path) { case Type_Struct: { if (t->Struct.is_raw_union) { - i64 count = t->Struct.field_count; + i64 count = t->Struct.fields.count; i64 align = type_align_of_internal(allocator, t, path); if (path->failure) { return FAILURE_SIZE; @@ -2101,7 +2100,7 @@ i64 type_size_of_internal(gbAllocator allocator, Type *t, TypePath *path) { // TODO(bill): Is this how it should work? return align_formula(max, align); } else { - i64 count = t->Struct.field_count; + i64 count = t->Struct.fields.count; if (count == 0) { return 0; } @@ -2140,7 +2139,7 @@ i64 type_offset_of(gbAllocator allocator, Type *t, i32 index) { t = base_type(t); if (t->kind == Type_Struct && !t->Struct.is_raw_union) { type_set_offsets(allocator, t); - if (gb_is_between(index, 0, t->Struct.field_count-1)) { + if (gb_is_between(index, 0, t->Struct.fields.count-1)) { return t->Struct.offsets[index]; } } else if (t->kind == Type_Tuple) { @@ -2307,7 +2306,7 @@ gbString write_type_to_string(gbString str, Type *type) { case Type_Struct: { if (type->Struct.is_raw_union) { str = gb_string_appendc(str, "raw_union{"); - for (isize i = 0; i < type->Struct.field_count; i++) { + for_array(i, type->Struct.fields) { Entity *f = type->Struct.fields[i]; GB_ASSERT(f->kind == Entity_Variable); if (i > 0) { @@ -2327,7 +2326,7 @@ gbString write_type_to_string(gbString str, Type *type) { str = gb_string_appendc(str, " #ordered"); } str = gb_string_appendc(str, " {"); - for (isize i = 0; i < type->Struct.field_count; i++) { + for_array(i, type->Struct.fields) { Entity *f = type->Struct.fields[i]; GB_ASSERT(f->kind == Entity_Variable); if (i > 0) {