Browse Source

Make `fields` et al an Array rather than a raw pointer

Ginger Bill 8 years ago
parent
commit
13bc6eeea4
6 changed files with 71 additions and 80 deletions
  1. 27 28
      src/check_expr.cpp
  2. 2 2
      src/checker.cpp
  3. 6 10
      src/ir.cpp
  4. 4 4
      src/ir_print.cpp
  5. 6 9
      src/ssa.cpp
  6. 26 27
      src/types.cpp

+ 27 - 28
src/check_expr.cpp

@@ -125,7 +125,7 @@ bool check_is_assignable_to_using_subtype(Type *src, Type *dst) {
 		return false;
 		return false;
 	}
 	}
 
 
-	for (isize i = 0; i < src->Struct.field_count; i++) {
+	for_array(i, src->Struct.fields) {
 		Entity *f = src->Struct.fields[i];
 		Entity *f = src->Struct.fields[i];
 		if (f->kind != Entity_Variable || (f->flags&EntityFlag_Using) == 0) {
 		if (f->kind != Entity_Variable || (f->flags&EntityFlag_Using) == 0) {
 			continue;
 			continue;
@@ -733,7 +733,7 @@ void populate_using_entity_map(Checker *c, AstNode *node, Type *t, Map<Entity *>
 	}
 	}
 
 
 	if (t->kind == Type_Struct) {
 	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];
 			Entity *f = t->Struct.fields[i];
 			GB_ASSERT(f->kind == Entity_Variable);
 			GB_ASSERT(f->kind == Entity_Variable);
 			String name = f->token.string;
 			String name = f->token.string;
@@ -1228,9 +1228,8 @@ void check_struct_type(Checker *c, Type *struct_type, AstNode *node, Array<Opera
 	struct_type->Struct.scope               = c->context.scope;
 	struct_type->Struct.scope               = c->context.scope;
 	struct_type->Struct.is_packed           = st->is_packed;
 	struct_type->Struct.is_packed           = st->is_packed;
 	struct_type->Struct.is_ordered          = st->is_ordered;
 	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.polymorphic_params  = polymorphic_params;
 	struct_type->Struct.is_polymorphic      = is_polymorphic;
 	struct_type->Struct.is_polymorphic      = is_polymorphic;
 	struct_type->Struct.is_poly_specialized = is_poly_specialized;
 	struct_type->Struct.is_poly_specialized = is_poly_specialized;
@@ -1245,8 +1244,9 @@ void check_struct_type(Checker *c, Type *struct_type, AstNode *node, Array<Opera
 			struct_type->Struct.offsets = nullptr;
 			struct_type->Struct.offsets = nullptr;
 			// NOTE(bill): Reorder fields for reduced size/performance
 			// 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<Entity *> 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];
 				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, Array<Opera
 			// TODO(bill): Probably make an inline sorting procedure rather than use global variables
 			// TODO(bill): Probably make an inline sorting procedure rather than use global variables
 			__checker_allocator = c->allocator;
 			__checker_allocator = c->allocator;
 			// NOTE(bill): compound literal order must match source not layout
 			// 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;
 				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);
 		check_open_scope(c, dummy_node);
 
 
 		isize field_count = 3;
 		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<Entity *> 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);
 		check_close_scope(c);
 
 
 		entry_type->Struct.fields              = fields;
 		entry_type->Struct.fields              = fields;
 		entry_type->Struct.fields_in_src_order = fields;
 		entry_type->Struct.fields_in_src_order = fields;
-		entry_type->Struct.field_count         = field_count;
 
 
 		type_set_offsets(a, entry_type);
 		type_set_offsets(a, entry_type);
 		type->Map.entry_type = 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 *hashes_type  = make_type_dynamic_array(a, t_int);
 		Type *entries_type = make_type_dynamic_array(a, type->Map.entry_type);
 		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<Entity *> 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);
 		check_close_scope(c);
 
 
 		generated_struct_type->Struct.fields              = fields;
 		generated_struct_type->Struct.fields              = fields;
 		generated_struct_type->Struct.fields_in_src_order = 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_set_offsets(a, generated_struct_type);
 		type->Map.generated_struct_type = 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 *dst = type_deref(dst_);
 	Type *src = type_deref(src_);
 	Type *src = type_deref(src_);
 	Type *dst_s = base_type(dst);
 	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];
 		Entity *f = dst_s->Struct.fields[i];
 		GB_ASSERT(f->kind == Entity_Variable && f->flags & EntityFlag_Field);
 		GB_ASSERT(f->kind == Entity_Variable && f->flags & EntityFlag_Field);
 		if (f->flags & EntityFlag_Using) {
 		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;
 			i64 max_count = 0;
 			switch (type->kind) {
 			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_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;
 		gbAllocator a = c->allocator;
 
 
 		Type *tuple = make_type_tuple(a);
 		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);
 		array_init_count(&tuple->Tuple.variables, a, variable_count);
 		// TODO(bill): Should I copy each of the entities or is this good enough?
 		// 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->type = tuple;
 		operand->mode = Addressing_Value;
 		operand->mode = Addressing_Value;
@@ -6533,7 +6532,7 @@ Entity *find_using_index_expr(Type *t) {
 		return nullptr;
 		return nullptr;
 	}
 	}
 
 
-	for (isize i = 0; i < t->Struct.field_count; i++) {
+	for_array(i, t->Struct.fields) {
 		Entity *f = t->Struct.fields[i];
 		Entity *f = t->Struct.fields[i];
 		if (f->kind == Entity_Variable &&
 		if (f->kind == Entity_Variable &&
 		    (f->flags & EntityFlag_Field) != 0 &&
 		    (f->flags & EntityFlag_Field) != 0 &&
@@ -7338,8 +7337,8 @@ ExprKind check_expr_base_internal(Checker *c, Operand *o, AstNode *node, Type *t
 			}
 			}
 
 
 			{ // Checker values
 			{ // 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--) {
 				for (isize i = min_field_count-1; i >= 0; i--) {
 					Entity *e = t->Struct.fields_in_src_order[i];
 					Entity *e = t->Struct.fields_in_src_order[i];
 					GB_ASSERT(e->kind == Entity_Variable);
 					GB_ASSERT(e->kind == Entity_Variable);
@@ -7412,7 +7411,7 @@ ExprKind check_expr_base_internal(Checker *c, Operand *o, AstNode *node, Type *t
 					}
 					}
 				} else {
 				} else {
 					bool all_fields_are_blank = true;
 					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];
 						Entity *field = t->Struct.fields_in_src_order[i];
 						if (!is_blank_ident(field->token)) {
 						if (!is_blank_ident(field->token)) {
 							all_fields_are_blank = false;
 							all_fields_are_blank = false;

+ 2 - 2
src/checker.cpp

@@ -1175,7 +1175,7 @@ void add_type_info_type(Checker *c, Type *t) {
 		break;
 		break;
 
 
 	case Type_Struct: {
 	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];
 			Entity *f = bt->Struct.fields[i];
 			add_type_info_type(c, f->type);
 			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 = type_info_enum_value->type;
 		t_type_info_enum_value_ptr = make_type_pointer(c->allocator, t_type_info_enum_value);
 		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];
 		Entity *type_info_variant = tis->fields_in_src_order[2];
 		Type *tiv_type = type_info_variant->type;
 		Type *tiv_type = type_info_variant->type;

+ 6 - 10
src/ir.cpp

@@ -663,7 +663,7 @@ bool ir_type_has_default_values(Type *t) {
 
 
 	case Type_Struct:
 	case Type_Struct:
 		if (!t->Struct.is_raw_union) {
 		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];
 				Entity *f = t->Struct.fields_in_src_order[i];
 				if (f->kind != Entity_Variable) continue;
 				if (f->kind != Entity_Variable) continue;
 				if (f->Variable.default_is_nil) {
 				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;
 	Type *result_type = nullptr;
 
 
 	if (is_type_struct(t)) {
 	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);
 		result_type = make_type_pointer(a, t->Struct.fields[index]->type);
 	} else if (is_type_union(t)) {
 	} else if (is_type_union(t)) {
 		GB_ASSERT(index == -1);
 		GB_ASSERT(index == -1);
@@ -2437,8 +2435,6 @@ irValue *ir_emit_struct_ev(irProcedure *proc, irValue *s, i32 index) {
 	Type *result_type = nullptr;
 	Type *result_type = nullptr;
 
 
 	if (is_type_struct(t)) {
 	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;
 		result_type = t->Struct.fields[index]->type;
 	} else if (is_type_union(t)) {
 	} else if (is_type_union(t)) {
 		GB_ASSERT(index == -1);
 		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;
 	// bool dst_is_ptr = dst != prev_dst;
 
 
 	GB_ASSERT(is_type_struct(src) || is_type_union(src));
 	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];
 		Entity *f = src->Struct.fields[i];
 		if (f->kind == Entity_Variable && f->flags & EntityFlag_Using) {
 		if (f->kind == Entity_Variable && f->flags & EntityFlag_Using) {
 			if (are_types_identical(dst, f->type)) {
 			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));
 		GB_ASSERT(is_type_tuple(tv.type));
 
 
 		irValue *tuple = ir_add_local_generated(proc, 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];
 			Entity *field = t->Struct.fields_in_src_order[src_index];
 			i32 field_index = field->Variable.field_index;
 			i32 field_index = field->Variable.field_index;
 			irValue *f = ir_emit_struct_ev(proc, s, 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);
 			Type *enum_ptr = make_type_pointer(a, t);
 			t = base_type(t);
 			t = base_type(t);
 			Type *core_elem = core_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 *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);
 			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;
 					count += t->Union.variants.count;
 					break;
 					break;
 				case Type_Struct:
 				case Type_Struct:
-					count += t->Struct.field_count;
+					count += t->Struct.fields.count;
 					break;
 					break;
 				case Type_Tuple:
 				case Type_Tuple:
 					count += t->Tuple.variables.count;
 					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);
 						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_types   = ir_type_info_member_types_offset  (proc, count);
 					irValue *memory_names   = ir_type_info_member_names_offset  (proc, count);
 					irValue *memory_names   = ir_type_info_member_names_offset  (proc, count);

+ 4 - 4
src/ir_print.cpp

@@ -314,11 +314,11 @@ void ir_print_type(irFileBuffer *f, irModule *m, Type *t) {
 			ir_fprintf(f, "{");
 			ir_fprintf(f, "{");
 			if (t->Struct.custom_align > 0) {
 			if (t->Struct.custom_align > 0) {
 				ir_fprintf(f, "[0 x <%lld x i8>]", t->Struct.custom_align);
 				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, ", ");
 					ir_fprintf(f, ", ");
 				}
 				}
 			}
 			}
-			for (isize i = 0; i < t->Struct.field_count; i++) {
+			for_array(i, t->Struct.fields) {
 				if (i > 0) {
 				if (i > 0) {
 					ir_fprintf(f, ", ");
 					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);
 			ExactValue *values = gb_alloc_array(m->tmp_allocator, ExactValue, value_count);
 			bool *visited = gb_alloc_array(m->tmp_allocator, bool, 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");
 			ir_fprintf(f, "zeroinitializer");
 		} else {
 		} else {
 			if (is_type_struct(type)) {
 			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, "<");
 				if (type->Struct.is_packed) ir_fprintf(f, "<");
 				ir_fprintf(f, "{");
 				ir_fprintf(f, "{");
 				if (type->Struct.custom_align > 0) {
 				if (type->Struct.custom_align > 0) {

+ 6 - 9
src/ssa.cpp

@@ -653,10 +653,10 @@ bool can_ssa_type(Type *t) {
 
 
 	case Type_Struct:
 	case Type_Struct:
 		if (!t->Struct.is_raw_union) {
 		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;
 				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)) {
 				if (!can_ssa_type(t->Struct.fields[i]->type)) {
 					return false;
 					return false;
 				}
 				}
@@ -810,8 +810,7 @@ ssaValue *ssa_emit_ptr_index(ssaProc *p, ssaValue *s, i64 index) {
 	Type *result_type = nullptr;
 	Type *result_type = nullptr;
 
 
 	if (is_type_struct(t)) {
 	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);
 		result_type = make_type_pointer(a, t->Struct.fields[index]->type);
 	} else if (is_type_tuple(t)) {
 	} else if (is_type_tuple(t)) {
 		GB_ASSERT(t->Tuple.variables.count > 0);
 		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;
 	Type *result_type = nullptr;
 
 
 	if (is_type_struct(t)) {
 	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;
 		result_type = t->Struct.fields[index]->type;
 	} else if (is_type_union(t)) {
 	} else if (is_type_union(t)) {
 		type_set_offsets(a, 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;
 		result_type = t->Struct.fields[index]->type;
 	} else if (is_type_tuple(t)) {
 	} else if (is_type_tuple(t)) {
 		GB_ASSERT(t->Tuple.variables.count > 0);
 		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");
 			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);
 		return ssa_const_nil(p, tv.type);
 	}
 	}
 
 

+ 26 - 27
src/types.cpp

@@ -69,13 +69,12 @@ struct BasicType {
 };
 };
 
 
 struct TypeStruct {
 struct TypeStruct {
-	Entity **fields;
-	i32      field_count; // == struct_offsets count
-	Entity **fields_in_src_order; // Entity_Variable
+	Array<Entity *> fields;
+	Array<Entity *> fields_in_src_order;
 	AstNode *node;
 	AstNode *node;
 	Scope *  scope;
 	Scope *  scope;
 
 
-	i64 *    offsets;
+	i64 *    offsets; // == fields.count
 	bool     are_offsets_set;
 	bool     are_offsets_set;
 	bool     are_offsets_being_processed;
 	bool     are_offsets_being_processed;
 	bool     is_packed;
 	bool     is_packed;
@@ -983,7 +982,7 @@ bool is_type_polymorphic(Type *t) {
 		if (t->Struct.is_polymorphic) {
 		if (t->Struct.is_polymorphic) {
 			return true;
 			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)) {
 		    if (is_type_polymorphic(t->Struct.fields[i]->type)) {
 		    	return true;
 		    	return true;
 		    }
 		    }
@@ -1131,12 +1130,12 @@ bool are_types_identical(Type *x, Type *y) {
 	case Type_Struct:
 	case Type_Struct:
 		if (y->kind == Type_Struct) {
 		if (y->kind == Type_Struct) {
 			if (x->Struct.is_raw_union == y->Struct.is_raw_union &&
 			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) {
 			    x->Struct.custom_align == y->Struct.custom_align) {
 				// TODO(bill); Fix the custom alignment rule
 				// 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 *xf = x->Struct.fields[i];
 					Entity *yf = y->Struct.fields[i];
 					Entity *yf = y->Struct.fields[i];
 					if (!are_types_identical(xf->type, yf->type)) {
 					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) {
 		if (type->Struct.is_raw_union) {
 			return false;
 			return false;
 		}
 		}
-		for (isize i = 0; i < type->Struct.field_count; i++) {
+		for_array(i, type->Struct.fields) {
 			Entity *v = type->Struct.fields[i];
 			Entity *v = type->Struct.fields[i];
 			if (!is_type_cte_safe(v->type)) {
 			if (!is_type_cte_safe(v->type)) {
 				return false;
 				return false;
@@ -1401,7 +1400,7 @@ Selection lookup_field_from_index(gbAllocator a, Type *type, i64 index) {
 
 
 	i64 max_count = 0;
 	i64 max_count = 0;
 	switch (type->kind) {
 	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_Tuple:    max_count = type->Tuple.variables.count; break;
 	case Type_BitField: max_count = type->BitField.field_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;
 			return sel;
 		}
 		}
 	} else if (type->kind == Type_Struct) {
 	} 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];
 			Entity *f = type->Struct.fields[i];
 			if (f->kind != Entity_Variable || (f->flags & EntityFlag_Field) == 0) {
 			if (f->kind != Entity_Variable || (f->flags & EntityFlag_Field) == 0) {
 				continue;
 				continue;
@@ -1842,7 +1841,7 @@ i64 type_align_of_internal(gbAllocator allocator, Type *t, TypePath *path) {
 	case Type_Struct: {
 	case Type_Struct: {
 		if (t->Struct.is_raw_union) {
 		if (t->Struct.is_raw_union) {
 			i64 max = 1;
 			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 *field_type = t->Struct.fields[i]->type;
 				type_path_push(path, field_type);
 				type_path_push(path, field_type);
 				if (path->failure) {
 				if (path->failure) {
@@ -1859,12 +1858,12 @@ i64 type_align_of_internal(gbAllocator allocator, Type *t, TypePath *path) {
 			if (t->Struct.custom_align > 0) {
 			if (t->Struct.custom_align > 0) {
 				return gb_clamp(t->Struct.custom_align, 1, build_context.max_align);
 				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;
 				i64 max = 1;
 				if (t->Struct.is_packed) {
 				if (t->Struct.is_packed) {
 					max = build_context.word_size;
 					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 *field_type = t->Struct.fields[i]->type;
 					type_path_push(path, field_type);
 					type_path_push(path, field_type);
 					if (path->failure) {
 					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);
 	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<Entity *> fields, bool is_packed, bool is_raw_union) {
+	i64 *offsets = gb_alloc_array(allocator, i64, fields.count);
 	i64 curr_offset = 0;
 	i64 curr_offset = 0;
 	if (is_raw_union) {
 	if (is_raw_union) {
-		for (isize i = 0; i < field_count; i++) {
+		for_array(i, fields) {
 			offsets[i] = 0;
 			offsets[i] = 0;
 		}
 		}
 	} else if (is_packed) {
 	} 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);
 			i64 size = type_size_of(allocator, fields[i]->type);
 			offsets[i] = curr_offset;
 			offsets[i] = curr_offset;
 			curr_offset += size;
 			curr_offset += size;
 		}
 		}
 	} else {
 	} 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 align = gb_max(type_align_of(allocator, fields[i]->type), 1);
 			i64 size  = gb_max(type_size_of(allocator, fields[i]->type), 0);
 			i64 size  = gb_max(type_size_of(allocator, fields[i]->type), 0);
 			curr_offset = align_formula(curr_offset, align);
 			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->kind == Type_Struct) {
 		if (!t->Struct.are_offsets_set) {
 		if (!t->Struct.are_offsets_set) {
 			t->Struct.are_offsets_being_processed = true;
 			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;
 			t->Struct.are_offsets_set = true;
 			return true;
 			return true;
 		}
 		}
 	} else if (is_type_tuple(t)) {
 	} else if (is_type_tuple(t)) {
 		if (!t->Tuple.are_offsets_set) {
 		if (!t->Tuple.are_offsets_set) {
 			t->Struct.are_offsets_being_processed = true;
 			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;
 			t->Tuple.are_offsets_set = true;
 			return true;
 			return true;
 		}
 		}
@@ -2086,7 +2085,7 @@ i64 type_size_of_internal(gbAllocator allocator, Type *t, TypePath *path) {
 
 
 	case Type_Struct: {
 	case Type_Struct: {
 		if (t->Struct.is_raw_union) {
 		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);
 			i64 align = type_align_of_internal(allocator, t, path);
 			if (path->failure) {
 			if (path->failure) {
 				return FAILURE_SIZE;
 				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?
 			// TODO(bill): Is this how it should work?
 			return align_formula(max, align);
 			return align_formula(max, align);
 		} else {
 		} else {
-			i64 count = t->Struct.field_count;
+			i64 count = t->Struct.fields.count;
 			if (count == 0) {
 			if (count == 0) {
 				return 0;
 				return 0;
 			}
 			}
@@ -2140,7 +2139,7 @@ i64 type_offset_of(gbAllocator allocator, Type *t, i32 index) {
 	t = base_type(t);
 	t = base_type(t);
 	if (t->kind == Type_Struct && !t->Struct.is_raw_union) {
 	if (t->kind == Type_Struct && !t->Struct.is_raw_union) {
 		type_set_offsets(allocator, t);
 		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];
 			return t->Struct.offsets[index];
 		}
 		}
 	} else if (t->kind == Type_Tuple) {
 	} else if (t->kind == Type_Tuple) {
@@ -2307,7 +2306,7 @@ gbString write_type_to_string(gbString str, Type *type) {
 	case Type_Struct: {
 	case Type_Struct: {
 		if (type->Struct.is_raw_union) {
 		if (type->Struct.is_raw_union) {
 			str = gb_string_appendc(str, "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];
 				Entity *f = type->Struct.fields[i];
 				GB_ASSERT(f->kind == Entity_Variable);
 				GB_ASSERT(f->kind == Entity_Variable);
 				if (i > 0) {
 				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, " #ordered");
 			}
 			}
 			str = gb_string_appendc(str, " {");
 			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];
 				Entity *f = type->Struct.fields[i];
 				GB_ASSERT(f->kind == Entity_Variable);
 				GB_ASSERT(f->kind == Entity_Variable);
 				if (i > 0) {
 				if (i > 0) {