Browse Source

Remove Array<T> and replace with macro version

Ginger Bill 8 years ago
parent
commit
cb7b9a413d
14 changed files with 536 additions and 433 deletions
  1. 100 0
      src/array.cpp
  2. 31 31
      src/checker/checker.cpp
  3. 9 9
      src/checker/decl.cpp
  4. 87 87
      src/checker/expr.cpp
  5. 33 33
      src/checker/stmt.cpp
  6. 8 6
      src/checker/types.cpp
  7. 37 38
      src/common.cpp
  8. 1 1
      src/main.cpp
  9. 36 36
      src/parser.cpp
  10. 128 126
      src/ssa.cpp
  11. 41 41
      src/ssa_opt.cpp
  12. 18 18
      src/ssa_print.cpp
  13. 5 5
      src/timings.cpp
  14. 2 2
      src/tokenizer.cpp

+ 100 - 0
src/array.cpp

@@ -1,5 +1,104 @@
 #define ARRAY_GROW_FORMULA(x) (2*(x) + 8)
 #define ARRAY_GROW_FORMULA(x) (2*(x) + 8)
+GB_STATIC_ASSERT(ARRAY_GROW_FORMULA(0) > 0);
 
 
+#define Array(Type_) struct { \
+	gbAllocator allocator; \
+	Type_ *     e; \
+	isize       count; \
+	isize       capacity; \
+}
+
+typedef Array(void) ArrayVoid;
+
+#define array_init_reserve(x_, allocator_, init_capacity_) do { \
+	GB_ASSERT((x_) != NULL); \
+	void **e = cast(void **)&((x_)->e); \
+	(x_)->allocator = (allocator_); \
+	(x_)->count = 0; \
+	(x_)->capacity = (init_capacity_); \
+	*e = gb_alloc((allocator_), gb_size_of(*(x_)->e)*(init_capacity_)); \
+} while (0)
+
+#define array_init_count(x_, allocator_, init_count_) do { \
+	GB_ASSERT((x_) != NULL); \
+	void **e = cast(void **)&((x_)->e); \
+	(x_)->allocator = (allocator_); \
+	(x_)->count = (init_count_); \
+	(x_)->capacity = (init_count_); \
+	*e = gb_alloc((allocator_), gb_size_of(*(x_)->e)*(init_count_)); \
+} while (0)
+
+#define array_init(x_, allocator_)        do { array_init_reserve(x_, allocator_, ARRAY_GROW_FORMULA(0)); } while (0)
+#define array_free(x_)                    do { gb_free((x_)->allocator, (x_)->e); } while (0)
+#define array_set_capacity(x_, capacity_) do { array__set_capacity((x_), (capacity_), gb_size_of(*(x_)->e)); } while (0)
+
+#define array_grow(x_, min_capacity_) do { \
+	isize new_capacity = ARRAY_GROW_FORMULA((x_)->capacity); \
+	if (new_capacity < (min_capacity_)) { \
+		new_capacity = (min_capacity_); \
+	} \
+	array_set_capacity(x_, new_capacity); \
+} while (0)
+
+#define array_add(x_, item_) do { \
+	if ((x_)->capacity < (x_)->count+1) { \
+		array_grow(x_, 0); \
+	} \
+	(x_)->e[(x_)->count++] = item_; \
+} while (0)
+
+#define array_pop(x_)   do { GB_ASSERT((x_)->count > 0); (x_)->count--; } while (0)
+#define array_clear(x_) do { (x_)->count = 0; } while (0)
+
+#define array_resize(x_, new_count_) do { \
+	if ((x_)->capacity < (new_count_)) { \
+		array_grow((x_), (new_count_)); \
+	} \
+	(x_)->count = (new_count_); \
+} while (0)
+
+#define array_reserve(x_, new_capacity_) do { \
+	if ((x_)->capacity < (new_capacity_)) { \
+		array_set_capacity((x_), (new_capacity_)); \
+	} \
+} while (0)
+
+
+
+
+void array__set_capacity(void *ptr, isize capacity, isize element_size) {
+	GB_ASSERT(ptr != NULL);
+	ArrayVoid *x = cast(ArrayVoid *)ptr;
+
+	GB_ASSERT(element_size > 0);
+
+	if (capacity == x->capacity) {
+		return;
+	}
+
+	if (capacity < x->count) {
+		if (x->capacity < capacity) {
+			isize new_capacity = ARRAY_GROW_FORMULA(x->capacity);
+			if (new_capacity < capacity) {
+				new_capacity = capacity;
+			}
+			array__set_capacity(ptr, new_capacity, element_size);
+		}
+		x->count = capacity;
+	}
+
+	{
+		// TODO(bill): Resize rather than copy and delete
+		void *new_data = gb_alloc(x->allocator, element_size*capacity);
+		gb_memmove(new_data, x->e, element_size*x->count);
+		gb_free(x->allocator, x->e);
+		x->capacity = capacity;
+		x->e = new_data;
+	}
+}
+
+
+#if 0
 template <typename T>
 template <typename T>
 struct Array {
 struct Array {
 	gbAllocator allocator;
 	gbAllocator allocator;
@@ -133,3 +232,4 @@ void array_set_capacity(Array<T> *array, isize capacity) {
 
 
 
 
 
 
+#endif

+ 31 - 31
src/checker/checker.cpp

@@ -70,8 +70,8 @@ struct Scope {
 	Map<Entity *>  elements; // Key: String
 	Map<Entity *>  elements; // Key: String
 	Map<Entity *>  implicit; // Key: String
 	Map<Entity *>  implicit; // Key: String
 
 
-	Array<Scope *> shared;
-	Array<Scope *> imported;
+	Array(Scope *) shared;
+	Array(Scope *) imported;
 	b32            is_proc;
 	b32            is_proc;
 	b32            is_global;
 	b32            is_global;
 	b32            is_file;
 	b32            is_file;
@@ -211,7 +211,7 @@ struct Checker {
 	AstFile *              curr_ast_file;
 	AstFile *              curr_ast_file;
 	BaseTypeSizes          sizes;
 	BaseTypeSizes          sizes;
 	Scope *                global_scope;
 	Scope *                global_scope;
-	Array<ProcedureInfo>   procs; // NOTE(bill): Procedures to check
+	Array(ProcedureInfo)   procs; // NOTE(bill): Procedures to check
 
 
 	gbArena                arena;
 	gbArena                arena;
 	gbArena                tmp_arena;
 	gbArena                tmp_arena;
@@ -220,12 +220,12 @@ struct Checker {
 
 
 	CheckerContext         context;
 	CheckerContext         context;
 
 
-	Array<Type *>          proc_stack;
+	Array(Type *)          proc_stack;
 	b32                    in_defer; // TODO(bill): Actually handle correctly
 	b32                    in_defer; // TODO(bill): Actually handle correctly
 };
 };
 
 
 struct CycleChecker {
 struct CycleChecker {
-	Array<Entity *> path; // Entity_TypeName
+	Array(Entity *) path; // Entity_TypeName
 };
 };
 
 
 
 
@@ -235,7 +235,7 @@ CycleChecker *cycle_checker_add(CycleChecker *cc, Entity *e) {
 	if (cc == NULL) {
 	if (cc == NULL) {
 		return NULL;
 		return NULL;
 	}
 	}
-	if (cc->path.data == NULL) {
+	if (cc->path.e == NULL) {
 		array_init(&cc->path, heap_allocator());
 		array_init(&cc->path, heap_allocator());
 	}
 	}
 	GB_ASSERT(e != NULL && e->kind == Entity_TypeName);
 	GB_ASSERT(e != NULL && e->kind == Entity_TypeName);
@@ -244,7 +244,7 @@ CycleChecker *cycle_checker_add(CycleChecker *cc, Entity *e) {
 }
 }
 
 
 void cycle_checker_destroy(CycleChecker *cc) {
 void cycle_checker_destroy(CycleChecker *cc) {
-	if (cc != NULL && cc->path.data != NULL)  {
+	if (cc != NULL && cc->path.e != NULL)  {
 		array_free(&cc->path);
 		array_free(&cc->path);
 	}
 	}
 }
 }
@@ -299,7 +299,7 @@ Scope *make_scope(Scope *parent, gbAllocator allocator) {
 
 
 void destroy_scope(Scope *scope) {
 void destroy_scope(Scope *scope) {
 	for_array(i, scope->elements.entries) {
 	for_array(i, scope->elements.entries) {
-		Entity *e =scope->elements.entries[i].value;
+		Entity *e =scope->elements.entries.e[i].value;
 		if (e->kind == Entity_Variable) {
 		if (e->kind == Entity_Variable) {
 			if (!(e->flags & EntityFlag_Used)) {
 			if (!(e->flags & EntityFlag_Used)) {
 #if 0
 #if 0
@@ -371,7 +371,7 @@ void scope_lookup_parent_entity(Scope *scope, String name, Scope **scope_, Entit
 		} else {
 		} else {
 			// Check shared scopes - i.e. other files @ global scope
 			// Check shared scopes - i.e. other files @ global scope
 			for_array(i, s->shared) {
 			for_array(i, s->shared) {
-				Scope *shared = s->shared[i];
+				Scope *shared = s->shared.e[i];
 				Entity **found = map_get(&shared->elements, key);
 				Entity **found = map_get(&shared->elements, key);
 				if (found) {
 				if (found) {
 					Entity *e = *found;
 					Entity *e = *found;
@@ -414,7 +414,7 @@ Entity *current_scope_lookup_entity(Scope *s, String name) {
 		return *found;
 		return *found;
 	}
 	}
 	for_array(i, s->shared) {
 	for_array(i, s->shared) {
-		Entity **found = map_get(&s->shared[i]->elements, key);
+		Entity **found = map_get(&s->shared.e[i]->elements, key);
 		if (found) {
 		if (found) {
 			return *found;
 			return *found;
 		}
 		}
@@ -572,7 +572,7 @@ void init_checker(Checker *c, Parser *parser, BaseTypeSizes sizes) {
 	isize item_size = gb_max3(gb_size_of(Entity), gb_size_of(Type), gb_size_of(Scope));
 	isize item_size = gb_max3(gb_size_of(Entity), gb_size_of(Type), gb_size_of(Scope));
 	isize total_token_count = 0;
 	isize total_token_count = 0;
 	for_array(i, c->parser->files) {
 	for_array(i, c->parser->files) {
-		AstFile *f = &c->parser->files[i];
+		AstFile *f = &c->parser->files.e[i];
 		total_token_count += f->tokens.count;
 		total_token_count += f->tokens.count;
 	}
 	}
 	isize arena_size = 2 * item_size * total_token_count;
 	isize arena_size = 2 * item_size * total_token_count;
@@ -735,7 +735,7 @@ void add_type_info_type(Checker *c, Type *t) {
 
 
 	isize ti_index = -1;
 	isize ti_index = -1;
 	for_array(i, c->info.type_info_map.entries) {
 	for_array(i, c->info.type_info_map.entries) {
-		auto *e = &c->info.type_info_map.entries[i];
+		auto *e = &c->info.type_info_map.entries.e[i];
 		Type *prev_type = cast(Type *)e->key.ptr;
 		Type *prev_type = cast(Type *)e->key.ptr;
 		if (are_types_identical(t, prev_type)) {
 		if (are_types_identical(t, prev_type)) {
 			// Duplicate entry
 			// Duplicate entry
@@ -858,7 +858,7 @@ void pop_procedure(Checker *c) {
 Type *const curr_procedure(Checker *c) {
 Type *const curr_procedure(Checker *c) {
 	isize count = c->proc_stack.count;
 	isize count = c->proc_stack.count;
 	if (count > 0) {
 	if (count > 0) {
-		return c->proc_stack[count-1];
+		return c->proc_stack.e[count-1];
 	}
 	}
 	return NULL;
 	return NULL;
 }
 }
@@ -890,7 +890,7 @@ void add_dependency_to_map(Map<Entity *> *map, CheckerInfo *info, Entity *node)
 
 
 	DeclInfo *decl = *found;
 	DeclInfo *decl = *found;
 	for_array(i, decl->deps.entries) {
 	for_array(i, decl->deps.entries) {
-		Entity *e = cast(Entity *)decl->deps.entries[i].key.ptr;
+		Entity *e = cast(Entity *)decl->deps.entries.e[i].key.ptr;
 		add_dependency_to_map(map, info, e);
 		add_dependency_to_map(map, info, e);
 	}
 	}
 }
 }
@@ -900,7 +900,7 @@ Map<Entity *> generate_minimum_dependency_map(CheckerInfo *info, Entity *start)
 	map_init(&map, heap_allocator());
 	map_init(&map, heap_allocator());
 
 
 	for_array(i, info->entities.entries) {
 	for_array(i, info->entities.entries) {
-		auto *entry = &info->entities.entries[i];
+		auto *entry = &info->entities.entries.e[i];
 		Entity *e = cast(Entity *)cast(uintptr)entry->key.key;
 		Entity *e = cast(Entity *)cast(uintptr)entry->key.key;
 		if (e->scope->is_global) {
 		if (e->scope->is_global) {
 			// NOTE(bill): Require runtime stuff
 			// NOTE(bill): Require runtime stuff
@@ -996,7 +996,7 @@ void add_implicit_value(Checker *c, ImplicitValueId id, String name, String back
 void check_global_entity(Checker *c, EntityKind kind) {
 void check_global_entity(Checker *c, EntityKind kind) {
 	PROF_SCOPED("check_global_entity");
 	PROF_SCOPED("check_global_entity");
 	for_array(i, c->info.entities.entries) {
 	for_array(i, c->info.entities.entries) {
-		auto *entry = &c->info.entities.entries[i];
+		auto *entry = &c->info.entities.entries.e[i];
 		Entity *e = cast(Entity *)cast(uintptr)entry->key.key;
 		Entity *e = cast(Entity *)cast(uintptr)entry->key.key;
 		if (e->kind == kind) {
 		if (e->kind == kind) {
 			DeclInfo *d = entry->value;
 			DeclInfo *d = entry->value;
@@ -1023,7 +1023,7 @@ void check_global_entity(Checker *c, EntityKind kind) {
 }
 }
 
 
 void check_parsed_files(Checker *c) {
 void check_parsed_files(Checker *c) {
-	Array<AstNode *> import_decls;
+	AstNodeArray import_decls;
 	array_init(&import_decls, heap_allocator());
 	array_init(&import_decls, heap_allocator());
 
 
 	Map<Scope *> file_scopes; // Key: String (fullpath)
 	Map<Scope *> file_scopes; // Key: String (fullpath)
@@ -1031,7 +1031,7 @@ void check_parsed_files(Checker *c) {
 
 
 	// Map full filepaths to Scopes
 	// Map full filepaths to Scopes
 	for_array(i, c->parser->files) {
 	for_array(i, c->parser->files) {
-		AstFile *f = &c->parser->files[i];
+		AstFile *f = &c->parser->files.e[i];
 		Scope *scope = NULL;
 		Scope *scope = NULL;
 		scope = make_scope(c->global_scope, c->allocator);
 		scope = make_scope(c->global_scope, c->allocator);
 		scope->is_global = f->is_global_scope;
 		scope->is_global = f->is_global_scope;
@@ -1058,13 +1058,13 @@ void check_parsed_files(Checker *c) {
 	for_array(i, c->parser->files) {
 	for_array(i, c->parser->files) {
 		PROF_SCOPED("Collect Entities");
 		PROF_SCOPED("Collect Entities");
 
 
-		AstFile *f = &c->parser->files[i];
+		AstFile *f = &c->parser->files.e[i];
 		add_curr_ast_file(c, f);
 		add_curr_ast_file(c, f);
 
 
 		Scope *file_scope = f->scope;
 		Scope *file_scope = f->scope;
 
 
 		for_array(decl_index, f->decls) {
 		for_array(decl_index, f->decls) {
-			AstNode *decl = f->decls[decl_index];
+			AstNode *decl = f->decls.e[decl_index];
 			if (!is_ast_node_decl(decl)) {
 			if (!is_ast_node_decl(decl)) {
 				continue;
 				continue;
 			}
 			}
@@ -1081,8 +1081,8 @@ void check_parsed_files(Checker *c) {
 
 
 			case_ast_node(cd, ConstDecl, decl);
 			case_ast_node(cd, ConstDecl, decl);
 				for_array(i, cd->values) {
 				for_array(i, cd->values) {
-					AstNode *name = cd->names[i];
-					AstNode *value = cd->values[i];
+					AstNode *name = cd->names.e[i];
+					AstNode *value = cd->values.e[i];
 					ExactValue v = {ExactValue_Invalid};
 					ExactValue v = {ExactValue_Invalid};
 					Entity *e = make_entity_constant(c->allocator, file_scope, name->Ident, NULL, v);
 					Entity *e = make_entity_constant(c->allocator, file_scope, name->Ident, NULL, v);
 					e->identifier = name;
 					e->identifier = name;
@@ -1112,14 +1112,14 @@ void check_parsed_files(Checker *c) {
 					di->entities = entities;
 					di->entities = entities;
 					di->entity_count = entity_count;
 					di->entity_count = entity_count;
 					di->type_expr = vd->type;
 					di->type_expr = vd->type;
-					di->init_expr = vd->values[0];
+					di->init_expr = vd->values.e[0];
 				}
 				}
 
 
 				for_array(i, vd->names) {
 				for_array(i, vd->names) {
-					AstNode *name = vd->names[i];
+					AstNode *name = vd->names.e[i];
 					AstNode *value = NULL;
 					AstNode *value = NULL;
 					if (i < vd->values.count) {
 					if (i < vd->values.count) {
-						value = vd->values[i];
+						value = vd->values.e[i];
 					}
 					}
 					Entity *e = make_entity_variable(c->allocator, file_scope, name->Ident, NULL);
 					Entity *e = make_entity_variable(c->allocator, file_scope, name->Ident, NULL);
 					e->identifier = name;
 					e->identifier = name;
@@ -1167,13 +1167,13 @@ void check_parsed_files(Checker *c) {
 	for_array(i, c->parser->files) {
 	for_array(i, c->parser->files) {
 		PROF_SCOPED("Import Entities");
 		PROF_SCOPED("Import Entities");
 
 
-		AstFile *f = &c->parser->files[i];
+		AstFile *f = &c->parser->files.e[i];
 		add_curr_ast_file(c, f);
 		add_curr_ast_file(c, f);
 
 
 		Scope *file_scope = f->scope;
 		Scope *file_scope = f->scope;
 
 
 		for_array(decl_index, f->decls) {
 		for_array(decl_index, f->decls) {
-			AstNode *decl = f->decls[decl_index];
+			AstNode *decl = f->decls.e[decl_index];
 			if (decl->kind != AstNode_ImportDecl) {
 			if (decl->kind != AstNode_ImportDecl) {
 				continue;
 				continue;
 			}
 			}
@@ -1191,7 +1191,7 @@ void check_parsed_files(Checker *c) {
 
 
 			b32 previously_added = false;
 			b32 previously_added = false;
 			for_array(import_index, file_scope->imported) {
 			for_array(import_index, file_scope->imported) {
-				Scope *prev = file_scope->imported[import_index];
+				Scope *prev = file_scope->imported.e[import_index];
 				if (prev == scope) {
 				if (prev == scope) {
 					previously_added = true;
 					previously_added = true;
 					break;
 					break;
@@ -1207,7 +1207,7 @@ void check_parsed_files(Checker *c) {
 			if (str_eq(id->import_name.string, str_lit("."))) {
 			if (str_eq(id->import_name.string, str_lit("."))) {
 				// NOTE(bill): Add imported entities to this file's scope
 				// NOTE(bill): Add imported entities to this file's scope
 				for_array(elem_index, scope->elements.entries) {
 				for_array(elem_index, scope->elements.entries) {
-					Entity *e = scope->elements.entries[elem_index].value;
+					Entity *e = scope->elements.entries.e[elem_index].value;
 					if (e->scope == file_scope) {
 					if (e->scope == file_scope) {
 						continue;
 						continue;
 					}
 					}
@@ -1292,7 +1292,7 @@ void check_parsed_files(Checker *c) {
 
 
 	// Check procedure bodies
 	// Check procedure bodies
 	for_array(i, c->procs) {
 	for_array(i, c->procs) {
-		ProcedureInfo *pi = &c->procs[i];
+		ProcedureInfo *pi = &c->procs.e[i];
 		add_curr_ast_file(c, pi->file);
 		add_curr_ast_file(c, pi->file);
 
 
 		b32 bounds_check    = (pi->tags & ProcTag_bounds_check)    != 0;
 		b32 bounds_check    = (pi->tags & ProcTag_bounds_check)    != 0;
@@ -1317,7 +1317,7 @@ void check_parsed_files(Checker *c) {
 	for_array(i, c->info.untyped.entries) {
 	for_array(i, c->info.untyped.entries) {
 		PROF_SCOPED("Untyped expr values");
 		PROF_SCOPED("Untyped expr values");
 
 
-		auto *entry = &c->info.untyped.entries[i];
+		auto *entry = &c->info.untyped.entries.e[i];
 		HashKey key = entry->key;
 		HashKey key = entry->key;
 		AstNode *expr = cast(AstNode *)cast(uintptr)key.key;
 		AstNode *expr = cast(AstNode *)cast(uintptr)key.key;
 		ExpressionInfo *info = &entry->value;
 		ExpressionInfo *info = &entry->value;

+ 9 - 9
src/checker/decl.cpp

@@ -68,11 +68,11 @@ void check_init_variables(Checker *c, Entity **lhs, isize lhs_count, AstNodeArra
 
 
 	// NOTE(bill): If there is a bad syntax error, rhs > lhs which would mean there would need to be
 	// NOTE(bill): If there is a bad syntax error, rhs > lhs which would mean there would need to be
 	// an extra allocation
 	// an extra allocation
-	Array<Operand> operands;
-	array_init(&operands, c->tmp_allocator, 2*lhs_count);
+	Array(Operand) operands;
+	array_init_reserve(&operands, c->tmp_allocator, 2*lhs_count);
 
 
 	for_array(i, inits) {
 	for_array(i, inits) {
-		AstNode *rhs = inits[i];
+		AstNode *rhs = inits.e[i];
 		Operand o = {};
 		Operand o = {};
 		check_multi_expr(c, &o, rhs);
 		check_multi_expr(c, &o, rhs);
 		if (o.type->kind != Type_Tuple) {
 		if (o.type->kind != Type_Tuple) {
@@ -88,7 +88,7 @@ void check_init_variables(Checker *c, Entity **lhs, isize lhs_count, AstNodeArra
 
 
 	isize rhs_count = operands.count;
 	isize rhs_count = operands.count;
 	for_array(i, operands) {
 	for_array(i, operands) {
-		if (operands[i].mode == Addressing_Invalid) {
+		if (operands.e[i].mode == Addressing_Invalid) {
 			rhs_count--;
 			rhs_count--;
 		}
 		}
 	}
 	}
@@ -96,7 +96,7 @@ void check_init_variables(Checker *c, Entity **lhs, isize lhs_count, AstNodeArra
 
 
 	isize max = gb_min(lhs_count, rhs_count);
 	isize max = gb_min(lhs_count, rhs_count);
 	for (isize i = 0; i < max; i++) {
 	for (isize i = 0; i < max; i++) {
-		check_init_variable(c, lhs[i], &operands[i], context_name);
+		check_init_variable(c, lhs[i], &operands.e[i], context_name);
 	}
 	}
 
 
 	if (rhs_count > 0 && lhs_count != rhs_count) {
 	if (rhs_count > 0 && lhs_count != rhs_count) {
@@ -161,7 +161,7 @@ void check_var_decl_node(Checker *c, AstNode *node) {
 	Entity **entities = gb_alloc_array(c->allocator, Entity *, entity_count);
 	Entity **entities = gb_alloc_array(c->allocator, Entity *, entity_count);
 
 
 	for_array(i, vd->names) {
 	for_array(i, vd->names) {
-		AstNode *name = vd->names[i];
+		AstNode *name = vd->names.e[i];
 		Entity *entity = NULL;
 		Entity *entity = NULL;
 		if (name->kind == AstNode_Ident) {
 		if (name->kind == AstNode_Ident) {
 			Token token = name->Ident;
 			Token token = name->Ident;
@@ -215,7 +215,7 @@ void check_var_decl_node(Checker *c, AstNode *node) {
 
 
 	for_array(i, vd->names) {
 	for_array(i, vd->names) {
 		if (entities[i] != NULL) {
 		if (entities[i] != NULL) {
-			add_entity(c, c->context.scope, vd->names[i], entities[i]);
+			add_entity(c, c->context.scope, vd->names.e[i], entities[i]);
 		}
 		}
 	}
 	}
 
 
@@ -496,7 +496,7 @@ void check_var_decl(Checker *c, Entity *e, Entity **entities, isize entity_count
 	}
 	}
 
 
 	AstNodeArray inits;
 	AstNodeArray inits;
-	array_init(&inits, c->allocator, 1);
+	array_init_reserve(&inits, c->allocator, 1);
 	array_add(&inits, init_expr);
 	array_add(&inits, init_expr);
 	check_init_variables(c, entities, entity_count, inits, str_lit("variable declaration"));
 	check_init_variables(c, entities, entity_count, inits, str_lit("variable declaration"));
 }
 }
@@ -523,7 +523,7 @@ void check_proc_body(Checker *c, Token token, DeclInfo *decl, Type *type, AstNod
 				Scope **found = map_get(&c->info.scopes, hash_pointer(t->Record.node));
 				Scope **found = map_get(&c->info.scopes, hash_pointer(t->Record.node));
 				GB_ASSERT(found != NULL);
 				GB_ASSERT(found != NULL);
 				for_array(i, (*found)->elements.entries) {
 				for_array(i, (*found)->elements.entries) {
-					Entity *f = (*found)->elements.entries[i].value;
+					Entity *f = (*found)->elements.entries.e[i].value;
 					if (f->kind == Entity_Variable) {
 					if (f->kind == Entity_Variable) {
 						Entity *uvar = make_entity_using_variable(c->allocator, e, f->token, f->type);
 						Entity *uvar = make_entity_using_variable(c->allocator, e, f->token, f->type);
 						Entity *prev = scope_insert_entity(c->context.scope, uvar);
 						Entity *prev = scope_insert_entity(c->context.scope, uvar);

+ 87 - 87
src/checker/expr.cpp

@@ -258,15 +258,15 @@ void check_fields(Checker *c, AstNode *node, AstNodeArray decls,
 	Entity *using_index_expr = NULL;
 	Entity *using_index_expr = NULL;
 
 
 
 
-	struct Delay {
+	typedef struct {
 		Entity *e;
 		Entity *e;
 		AstNode *t;
 		AstNode *t;
-	};
-	Array<Delay> delayed_const; array_init(&delayed_const, c->tmp_allocator, other_field_count);
-	Array<Delay> delayed_type;  array_init(&delayed_type,  c->tmp_allocator, other_field_count);
+	} Delay;
+	Array(Delay) delayed_const; array_init_reserve(&delayed_const, c->tmp_allocator, other_field_count);
+	Array(Delay) delayed_type;  array_init_reserve(&delayed_type,  c->tmp_allocator, other_field_count);
 
 
 	for_array(decl_index, decls) {
 	for_array(decl_index, decls) {
-		AstNode *decl = decls[decl_index];
+		AstNode *decl = decls.e[decl_index];
 		if (decl->kind == AstNode_ConstDecl) {
 		if (decl->kind == AstNode_ConstDecl) {
 			ast_node(cd, ConstDecl, decl);
 			ast_node(cd, ConstDecl, decl);
 
 
@@ -275,8 +275,8 @@ void check_fields(Checker *c, AstNode *node, AstNodeArray decls,
 			Entity **entities = gb_alloc_array(c->allocator, Entity *, entity_count);
 			Entity **entities = gb_alloc_array(c->allocator, Entity *, entity_count);
 
 
 			for_array(i, cd->values) {
 			for_array(i, cd->values) {
-				AstNode *name = cd->names[i];
-				AstNode *value = cd->values[i];
+				AstNode *name = cd->names.e[i];
+				AstNode *value = cd->values.e[i];
 
 
 				GB_ASSERT(name->kind == AstNode_Ident);
 				GB_ASSERT(name->kind == AstNode_Ident);
 				ExactValue v = {ExactValue_Invalid};
 				ExactValue v = {ExactValue_Invalid};
@@ -299,7 +299,7 @@ void check_fields(Checker *c, AstNode *node, AstNodeArray decls,
 			}
 			}
 
 
 			for_array(i, cd->names) {
 			for_array(i, cd->names) {
-				AstNode *name = cd->names[i];
+				AstNode *name = cd->names.e[i];
 				Entity *e = entities[i];
 				Entity *e = entities[i];
 				Token name_token = name->Ident;
 				Token name_token = name->Ident;
 				if (str_eq(name_token.string, str_lit("_"))) {
 				if (str_eq(name_token.string, str_lit("_"))) {
@@ -342,17 +342,17 @@ void check_fields(Checker *c, AstNode *node, AstNodeArray decls,
 	}
 	}
 
 
 	for_array(i, delayed_type) {
 	for_array(i, delayed_type) {
-		check_const_decl(c, delayed_type[i].e, delayed_type[i].t, NULL);
+		check_const_decl(c, delayed_type.e[i].e, delayed_type.e[i].t, NULL);
 	}
 	}
 	for_array(i, delayed_const) {
 	for_array(i, delayed_const) {
-		check_type_decl(c, delayed_const[i].e, delayed_const[i].t, NULL, NULL);
+		check_type_decl(c, delayed_const.e[i].e, delayed_const.e[i].t, NULL, NULL);
 	}
 	}
 
 
 	if (node->kind == AstNode_UnionType) {
 	if (node->kind == AstNode_UnionType) {
 		isize field_index = 0;
 		isize field_index = 0;
 		fields[field_index++] = make_entity_type_name(c->allocator, c->context.scope, empty_token, NULL);
 		fields[field_index++] = make_entity_type_name(c->allocator, c->context.scope, empty_token, NULL);
 		for_array(decl_index, decls) {
 		for_array(decl_index, decls) {
-			AstNode *decl = decls[decl_index];
+			AstNode *decl = decls.e[decl_index];
 			if (decl->kind != AstNode_VarDecl) {
 			if (decl->kind != AstNode_VarDecl) {
 				continue;
 				continue;
 			}
 			}
@@ -361,7 +361,7 @@ void check_fields(Checker *c, AstNode *node, AstNodeArray decls,
 			Type *base_type = check_type(c, vd->type, NULL, cycle_checker);
 			Type *base_type = check_type(c, vd->type, NULL, cycle_checker);
 
 
 			for_array(name_index, vd->names) {
 			for_array(name_index, vd->names) {
-				AstNode *name = vd->names[name_index];
+				AstNode *name = vd->names.e[name_index];
 				Token name_token = name->Ident;
 				Token name_token = name->Ident;
 
 
 				Type *type = make_type_named(c->allocator, name_token.string, base_type, NULL);
 				Type *type = make_type_named(c->allocator, name_token.string, base_type, NULL);
@@ -388,7 +388,7 @@ void check_fields(Checker *c, AstNode *node, AstNodeArray decls,
 	} else {
 	} else {
 		isize field_index = 0;
 		isize field_index = 0;
 		for_array(decl_index, decls) {
 		for_array(decl_index, decls) {
-			AstNode *decl = decls[decl_index];
+			AstNode *decl = decls.e[decl_index];
 			if (decl->kind != AstNode_VarDecl) {
 			if (decl->kind != AstNode_VarDecl) {
 				continue;
 				continue;
 			}
 			}
@@ -398,13 +398,13 @@ void check_fields(Checker *c, AstNode *node, AstNodeArray decls,
 
 
 			if (vd->is_using) {
 			if (vd->is_using) {
 				if (vd->names.count > 1) {
 				if (vd->names.count > 1) {
-					error(ast_node_token(vd->names[0]),
+					error(ast_node_token(vd->names.e[0]),
 					      "Cannot apply `using` to more than one of the same type");
 					      "Cannot apply `using` to more than one of the same type");
 				}
 				}
 			}
 			}
 
 
 			for_array(name_index, vd->names) {
 			for_array(name_index, vd->names) {
-				AstNode *name = vd->names[name_index];
+				AstNode *name = vd->names.e[name_index];
 				Token name_token = name->Ident;
 				Token name_token = name->Ident;
 
 
 				Entity *e = make_entity_field(c->allocator, c->context.scope, name_token, type, vd->is_using, cast(i32)field_index);
 				Entity *e = make_entity_field(c->allocator, c->context.scope, name_token, type, vd->is_using, cast(i32)field_index);
@@ -429,14 +429,14 @@ void check_fields(Checker *c, AstNode *node, AstNodeArray decls,
 			if (vd->is_using) {
 			if (vd->is_using) {
 				Type *t = base_type(type_deref(type));
 				Type *t = base_type(type_deref(type));
 				if (!is_type_struct(t) && !is_type_raw_union(t)) {
 				if (!is_type_struct(t) && !is_type_raw_union(t)) {
-					Token name_token = vd->names[0]->Ident;
+					Token name_token = vd->names.e[0]->Ident;
 					if (is_type_indexable(t)) {
 					if (is_type_indexable(t)) {
 						b32 ok = true;
 						b32 ok = true;
 						for_array(emi, entity_map.entries) {
 						for_array(emi, entity_map.entries) {
-							Entity *e = entity_map.entries[emi].value;
+							Entity *e = entity_map.entries.e[emi].value;
 							if (e->kind == Entity_Variable && e->flags & EntityFlag_Anonymous) {
 							if (e->kind == Entity_Variable && e->flags & EntityFlag_Anonymous) {
 								if (is_type_indexable(e->type)) {
 								if (is_type_indexable(e->type)) {
-									if (e->identifier != vd->names[0]) {
+									if (e->identifier != vd->names.e[0]) {
 										ok = false;
 										ok = false;
 										using_index_expr = e;
 										using_index_expr = e;
 										break;
 										break;
@@ -505,7 +505,7 @@ void check_struct_type(Checker *c, Type *struct_type, AstNode *node, CycleChecke
 	isize field_count = 0;
 	isize field_count = 0;
 	isize other_field_count = 0;
 	isize other_field_count = 0;
 	for_array(decl_index, st->decls) {
 	for_array(decl_index, st->decls) {
-		AstNode *decl = st->decls[decl_index];
+		AstNode *decl = st->decls.e[decl_index];
 		switch (decl->kind) {
 		switch (decl->kind) {
 		case_ast_node(vd, VarDecl, decl);
 		case_ast_node(vd, VarDecl, decl);
 			field_count += vd->names.count;
 			field_count += vd->names.count;
@@ -571,7 +571,7 @@ void check_union_type(Checker *c, Type *union_type, AstNode *node, CycleChecker
 	isize field_count = 1;
 	isize field_count = 1;
 	isize other_field_count = 0;
 	isize other_field_count = 0;
 	for_array(decl_index, ut->decls) {
 	for_array(decl_index, ut->decls) {
-		AstNode *decl = ut->decls[decl_index];
+		AstNode *decl = ut->decls.e[decl_index];
 		switch (decl->kind) {
 		switch (decl->kind) {
 		case_ast_node(vd, VarDecl, decl);
 		case_ast_node(vd, VarDecl, decl);
 			field_count += vd->names.count;
 			field_count += vd->names.count;
@@ -608,7 +608,7 @@ void check_raw_union_type(Checker *c, Type *union_type, AstNode *node, CycleChec
 	isize field_count = 0;
 	isize field_count = 0;
 	isize other_field_count = 0;
 	isize other_field_count = 0;
 	for_array(decl_index, ut->decls) {
 	for_array(decl_index, ut->decls) {
-		AstNode *decl = ut->decls[decl_index];
+		AstNode *decl = ut->decls.e[decl_index];
 		switch (decl->kind) {
 		switch (decl->kind) {
 		case_ast_node(vd, VarDecl, decl);
 		case_ast_node(vd, VarDecl, decl);
 			field_count += vd->names.count;
 			field_count += vd->names.count;
@@ -699,7 +699,7 @@ void check_enum_type(Checker *c, Type *enum_type, Type *named_type, AstNode *nod
 	Entity *blank_entity = make_entity_constant(c->allocator, c->context.scope, blank_token, constant_type, make_exact_value_integer(0));;
 	Entity *blank_entity = make_entity_constant(c->allocator, c->context.scope, blank_token, constant_type, make_exact_value_integer(0));;
 
 
 	for_array(i, et->fields) {
 	for_array(i, et->fields) {
-		AstNode *field = et->fields[i];
+		AstNode *field = et->fields.e[i];
 
 
 		ast_node(f, FieldValue, field);
 		ast_node(f, FieldValue, field);
 		Token name_token = f->field->Ident;
 		Token name_token = f->field->Ident;
@@ -790,7 +790,7 @@ Type *check_get_params(Checker *c, Scope *scope, AstNodeArray params, b32 *is_va
 
 
 	isize variable_count = 0;
 	isize variable_count = 0;
 	for_array(i, params) {
 	for_array(i, params) {
-		AstNode *field = params[i];
+		AstNode *field = params.e[i];
 		ast_node(p, Parameter, field);
 		ast_node(p, Parameter, field);
 		variable_count += p->names.count;
 		variable_count += p->names.count;
 	}
 	}
@@ -798,7 +798,7 @@ Type *check_get_params(Checker *c, Scope *scope, AstNodeArray params, b32 *is_va
 	Entity **variables = gb_alloc_array(c->allocator, Entity *, variable_count);
 	Entity **variables = gb_alloc_array(c->allocator, Entity *, variable_count);
 	isize variable_index = 0;
 	isize variable_index = 0;
 	for_array(i, params) {
 	for_array(i, params) {
-		ast_node(p, Parameter, params[i]);
+		ast_node(p, Parameter, params.e[i]);
 		AstNode *type_expr = p->type;
 		AstNode *type_expr = p->type;
 		if (type_expr) {
 		if (type_expr) {
 			if (type_expr->kind == AstNode_Ellipsis) {
 			if (type_expr->kind == AstNode_Ellipsis) {
@@ -806,13 +806,13 @@ Type *check_get_params(Checker *c, Scope *scope, AstNodeArray params, b32 *is_va
 				if (i+1 == params.count) {
 				if (i+1 == params.count) {
 					is_variadic = true;
 					is_variadic = true;
 				} else {
 				} else {
-					error(ast_node_token(params[i]), "Invalid AST: Invalid variadic parameter");
+					error(ast_node_token(params.e[i]), "Invalid AST: Invalid variadic parameter");
 				}
 				}
 			}
 			}
 
 
 			Type *type = check_type(c, type_expr);
 			Type *type = check_type(c, type_expr);
 			for_array(j, p->names) {
 			for_array(j, p->names) {
-				AstNode *name = p->names[j];
+				AstNode *name = p->names.e[j];
 				if (name->kind == AstNode_Ident) {
 				if (name->kind == AstNode_Ident) {
 					Entity *param = make_entity_param(c->allocator, scope, name->Ident, type, p->is_using);
 					Entity *param = make_entity_param(c->allocator, scope, name->Ident, type, p->is_using);
 					add_entity(c, scope, name, param);
 					add_entity(c, scope, name, param);
@@ -853,7 +853,7 @@ Type *check_get_results(Checker *c, Scope *scope, AstNodeArray results) {
 	Entity **variables = gb_alloc_array(c->allocator, Entity *, results.count);
 	Entity **variables = gb_alloc_array(c->allocator, Entity *, results.count);
 	isize variable_index = 0;
 	isize variable_index = 0;
 	for_array(i, results) {
 	for_array(i, results) {
-		AstNode *item = results[i];
+		AstNode *item = results.e[i];
 		Type *type = check_type(c, item);
 		Type *type = check_type(c, item);
 		Token token = ast_node_token(item);
 		Token token = ast_node_token(item);
 		token.string = str_lit(""); // NOTE(bill): results are not named
 		token.string = str_lit(""); // NOTE(bill): results are not named
@@ -2610,17 +2610,17 @@ b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id)
 		// NOTE(bill): The first arg may be a Type, this will be checked case by case
 		// NOTE(bill): The first arg may be a Type, this will be checked case by case
 		break;
 		break;
 	default:
 	default:
-		check_multi_expr(c, operand, ce->args[0]);
+		check_multi_expr(c, operand, ce->args.e[0]);
 	}
 	}
 
 
 	switch (id) {
 	switch (id) {
 	case BuiltinProc_new: {
 	case BuiltinProc_new: {
 		// new :: proc(Type) -> ^Type
 		// new :: proc(Type) -> ^Type
 		Operand op = {};
 		Operand op = {};
-		check_expr_or_type(c, &op, ce->args[0]);
+		check_expr_or_type(c, &op, ce->args.e[0]);
 		Type *type = op.type;
 		Type *type = op.type;
 		if ((op.mode != Addressing_Type && type == NULL) || type == t_invalid) {
 		if ((op.mode != Addressing_Type && type == NULL) || type == t_invalid) {
-			error(ast_node_token(ce->args[0]), "Expected a type for `new`");
+			error(ast_node_token(ce->args.e[0]), "Expected a type for `new`");
 			return false;
 			return false;
 		}
 		}
 		operand->mode = Addressing_Value;
 		operand->mode = Addressing_Value;
@@ -2629,17 +2629,17 @@ b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id)
 	case BuiltinProc_new_slice: {
 	case BuiltinProc_new_slice: {
 		// new_slice :: proc(Type, len: int[, cap: int]) -> []Type
 		// new_slice :: proc(Type, len: int[, cap: int]) -> []Type
 		Operand op = {};
 		Operand op = {};
-		check_expr_or_type(c, &op, ce->args[0]);
+		check_expr_or_type(c, &op, ce->args.e[0]);
 		Type *type = op.type;
 		Type *type = op.type;
 		if ((op.mode != Addressing_Type && type == NULL) || type == t_invalid) {
 		if ((op.mode != Addressing_Type && type == NULL) || type == t_invalid) {
-			error(ast_node_token(ce->args[0]), "Expected a type for `new_slice`");
+			error(ast_node_token(ce->args.e[0]), "Expected a type for `new_slice`");
 			return false;
 			return false;
 		}
 		}
 
 
-		AstNode *len = ce->args[1];
+		AstNode *len = ce->args.e[1];
 		AstNode *cap = NULL;
 		AstNode *cap = NULL;
 		if (ce->args.count > 2) {
 		if (ce->args.count > 2) {
-			cap = ce->args[2];
+			cap = ce->args.e[2];
 		}
 		}
 
 
 		check_expr(c, &op, len);
 		check_expr(c, &op, len);
@@ -2681,9 +2681,9 @@ b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id)
 
 
 	case BuiltinProc_size_of: {
 	case BuiltinProc_size_of: {
 		// size_of :: proc(Type) -> untyped int
 		// size_of :: proc(Type) -> untyped int
-		Type *type = check_type(c, ce->args[0]);
+		Type *type = check_type(c, ce->args.e[0]);
 		if (type == NULL || type == t_invalid) {
 		if (type == NULL || type == t_invalid) {
-			error(ast_node_token(ce->args[0]), "Expected a type for `size_of`");
+			error(ast_node_token(ce->args.e[0]), "Expected a type for `size_of`");
 			return false;
 			return false;
 		}
 		}
 
 
@@ -2707,9 +2707,9 @@ b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id)
 
 
 	case BuiltinProc_align_of: {
 	case BuiltinProc_align_of: {
 		// align_of :: proc(Type) -> untyped int
 		// align_of :: proc(Type) -> untyped int
-		Type *type = check_type(c, ce->args[0]);
+		Type *type = check_type(c, ce->args.e[0]);
 		if (type == NULL || type == t_invalid) {
 		if (type == NULL || type == t_invalid) {
-			error(ast_node_token(ce->args[0]), "Expected a type for `align_of`");
+			error(ast_node_token(ce->args.e[0]), "Expected a type for `align_of`");
 			return false;
 			return false;
 		}
 		}
 		operand->mode = Addressing_Constant;
 		operand->mode = Addressing_Constant;
@@ -2732,14 +2732,14 @@ b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id)
 	case BuiltinProc_offset_of: {
 	case BuiltinProc_offset_of: {
 		// offset_of :: proc(Type, field) -> untyped int
 		// offset_of :: proc(Type, field) -> untyped int
 		Operand op = {};
 		Operand op = {};
-		Type *bt = check_type(c, ce->args[0]);
+		Type *bt = check_type(c, ce->args.e[0]);
 		Type *type = base_type(bt);
 		Type *type = base_type(bt);
 		if (type == NULL || type == t_invalid) {
 		if (type == NULL || type == t_invalid) {
-			error(ast_node_token(ce->args[0]), "Expected a type for `offset_of`");
+			error(ast_node_token(ce->args.e[0]), "Expected a type for `offset_of`");
 			return false;
 			return false;
 		}
 		}
 
 
-		AstNode *field_arg = unparen_expr(ce->args[1]);
+		AstNode *field_arg = unparen_expr(ce->args.e[1]);
 		if (field_arg == NULL ||
 		if (field_arg == NULL ||
 		    field_arg->kind != AstNode_Ident) {
 		    field_arg->kind != AstNode_Ident) {
 			error(ast_node_token(field_arg), "Expected an identifier for field argument");
 			error(ast_node_token(field_arg), "Expected an identifier for field argument");
@@ -2755,14 +2755,14 @@ b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id)
 		Selection sel = lookup_field(c->allocator, type, arg->string, operand->mode == Addressing_Type);
 		Selection sel = lookup_field(c->allocator, type, arg->string, operand->mode == Addressing_Type);
 		if (sel.entity == NULL) {
 		if (sel.entity == NULL) {
 			gbString type_str = type_to_string(bt);
 			gbString type_str = type_to_string(bt);
-			error(ast_node_token(ce->args[0]),
+			error(ast_node_token(ce->args.e[0]),
 			      "`%s` has no field named `%.*s`", type_str, LIT(arg->string));
 			      "`%s` has no field named `%.*s`", type_str, LIT(arg->string));
 			gb_string_free(type_str);
 			gb_string_free(type_str);
 			return false;
 			return false;
 		}
 		}
 		if (sel.indirect) {
 		if (sel.indirect) {
 			gbString type_str = type_to_string(bt);
 			gbString type_str = type_to_string(bt);
-			error(ast_node_token(ce->args[0]),
+			error(ast_node_token(ce->args.e[0]),
 			      "Field `%.*s` is embedded via a pointer in `%s`", LIT(arg->string), type_str);
 			      "Field `%.*s` is embedded via a pointer in `%s`", LIT(arg->string), type_str);
 			gb_string_free(type_str);
 			gb_string_free(type_str);
 			return false;
 			return false;
@@ -2775,7 +2775,7 @@ b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id)
 
 
 	case BuiltinProc_offset_of_val: {
 	case BuiltinProc_offset_of_val: {
 		// offset_of_val :: proc(val: expression) -> untyped int
 		// offset_of_val :: proc(val: expression) -> untyped int
-		AstNode *arg = unparen_expr(ce->args[0]);
+		AstNode *arg = unparen_expr(ce->args.e[0]);
 		if (arg->kind != AstNode_SelectorExpr) {
 		if (arg->kind != AstNode_SelectorExpr) {
 			gbString str = expr_to_string(arg);
 			gbString str = expr_to_string(arg);
 			error(ast_node_token(arg), "`%s` is not a selector expression", str);
 			error(ast_node_token(arg), "`%s` is not a selector expression", str);
@@ -2810,7 +2810,7 @@ b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id)
 		}
 		}
 		if (sel.indirect) {
 		if (sel.indirect) {
 			gbString type_str = type_to_string(type);
 			gbString type_str = type_to_string(type);
-			error(ast_node_token(ce->args[0]),
+			error(ast_node_token(ce->args.e[0]),
 			      "Field `%.*s` is embedded via a pointer in `%s`", LIT(i->string), type_str);
 			      "Field `%.*s` is embedded via a pointer in `%s`", LIT(i->string), type_str);
 			gb_string_free(type_str);
 			gb_string_free(type_str);
 			return false;
 			return false;
@@ -2835,7 +2835,7 @@ b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id)
 
 
 	case BuiltinProc_type_info: {
 	case BuiltinProc_type_info: {
 		// type_info :: proc(Type) -> ^Type_Info
 		// type_info :: proc(Type) -> ^Type_Info
-		AstNode *expr = ce->args[0];
+		AstNode *expr = ce->args.e[0];
 		Type *type = check_type(c, expr);
 		Type *type = check_type(c, expr);
 		if (type == NULL || type == t_invalid) {
 		if (type == NULL || type == t_invalid) {
 			error(ast_node_token(expr), "Invalid argument to `type_info`");
 			error(ast_node_token(expr), "Invalid argument to `type_info`");
@@ -2850,7 +2850,7 @@ b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id)
 
 
 	case BuiltinProc_type_info_of_val: {
 	case BuiltinProc_type_info_of_val: {
 		// type_info_of_val :: proc(val: Type) -> ^Type_Info
 		// type_info_of_val :: proc(val: Type) -> ^Type_Info
-		AstNode *expr = ce->args[0];
+		AstNode *expr = ce->args.e[0];
 
 
 		check_assignment(c, operand, NULL, str_lit("argument of `type_info_of_val`"));
 		check_assignment(c, operand, NULL, str_lit("argument of `type_info_of_val`"));
 		if (operand->mode == Addressing_Invalid || operand->mode == Addressing_Builtin)
 		if (operand->mode == Addressing_Invalid || operand->mode == Addressing_Builtin)
@@ -2867,13 +2867,13 @@ b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id)
 		// compile_assert :: proc(cond: bool)
 		// compile_assert :: proc(cond: bool)
 
 
 		if (!is_type_boolean(operand->type) && operand->mode != Addressing_Constant) {
 		if (!is_type_boolean(operand->type) && operand->mode != Addressing_Constant) {
-			gbString str = expr_to_string(ce->args[0]);
+			gbString str = expr_to_string(ce->args.e[0]);
 			error(ast_node_token(call), "`%s` is not a constant boolean", str);
 			error(ast_node_token(call), "`%s` is not a constant boolean", str);
 			gb_string_free(str);
 			gb_string_free(str);
 			return false;
 			return false;
 		}
 		}
 		if (!operand->value.value_bool) {
 		if (!operand->value.value_bool) {
-			gbString str = expr_to_string(ce->args[0]);
+			gbString str = expr_to_string(ce->args.e[0]);
 			error(ast_node_token(call), "Compile time assertion: `%s`", str);
 			error(ast_node_token(call), "Compile time assertion: `%s`", str);
 			gb_string_free(str);
 			gb_string_free(str);
 		}
 		}
@@ -2883,7 +2883,7 @@ b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id)
 		// assert :: proc(cond: bool)
 		// assert :: proc(cond: bool)
 
 
 		if (!is_type_boolean(operand->type)) {
 		if (!is_type_boolean(operand->type)) {
-			gbString str = expr_to_string(ce->args[0]);
+			gbString str = expr_to_string(ce->args.e[0]);
 			error(ast_node_token(call), "`%s` is not a boolean", str);
 			error(ast_node_token(call), "`%s` is not a boolean", str);
 			gb_string_free(str);
 			gb_string_free(str);
 			return false;
 			return false;
@@ -2896,7 +2896,7 @@ b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id)
 		// panic :: proc(msg: string)
 		// panic :: proc(msg: string)
 
 
 		if (!is_type_string(operand->type)) {
 		if (!is_type_string(operand->type)) {
-			gbString str = expr_to_string(ce->args[0]);
+			gbString str = expr_to_string(ce->args.e[0]);
 			error(ast_node_token(call), "`%s` is not a string", str);
 			error(ast_node_token(call), "`%s` is not a string", str);
 			gb_string_free(str);
 			gb_string_free(str);
 			return false;
 			return false;
@@ -2914,7 +2914,7 @@ b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id)
 			dest_type = d->Slice.elem;
 			dest_type = d->Slice.elem;
 		}
 		}
 		Operand op = {};
 		Operand op = {};
-		check_expr(c, &op, ce->args[1]);
+		check_expr(c, &op, ce->args.e[1]);
 		if (op.mode == Addressing_Invalid) {
 		if (op.mode == Addressing_Invalid) {
 			return false;
 			return false;
 		}
 		}
@@ -2929,8 +2929,8 @@ b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id)
 		}
 		}
 
 
 		if (!are_types_identical(dest_type, src_type)) {
 		if (!are_types_identical(dest_type, src_type)) {
-			gbString d_arg = expr_to_string(ce->args[0]);
-			gbString s_arg = expr_to_string(ce->args[1]);
+			gbString d_arg = expr_to_string(ce->args.e[0]);
+			gbString s_arg = expr_to_string(ce->args.e[1]);
 			gbString d_str = type_to_string(dest_type);
 			gbString d_str = type_to_string(dest_type);
 			gbString s_str = type_to_string(src_type);
 			gbString s_str = type_to_string(src_type);
 			error(ast_node_token(call),
 			error(ast_node_token(call),
@@ -2953,7 +2953,7 @@ b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id)
 		x_type = base_type(operand->type);
 		x_type = base_type(operand->type);
 
 
 		Operand op = {};
 		Operand op = {};
-		check_expr(c, &op, ce->args[1]);
+		check_expr(c, &op, ce->args.e[1]);
 		if (op.mode == Addressing_Invalid) {
 		if (op.mode == Addressing_Invalid) {
 			return false;
 			return false;
 		}
 		}
@@ -2966,8 +2966,8 @@ b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id)
 
 
 		Type *elem_type = x_type->Pointer.elem->Slice.elem;
 		Type *elem_type = x_type->Pointer.elem->Slice.elem;
 		if (!check_is_assignable_to(c, &op, elem_type)) {
 		if (!check_is_assignable_to(c, &op, elem_type)) {
-			gbString d_arg = expr_to_string(ce->args[0]);
-			gbString s_arg = expr_to_string(ce->args[1]);
+			gbString d_arg = expr_to_string(ce->args.e[0]);
+			gbString s_arg = expr_to_string(ce->args.e[1]);
 			gbString d_str = type_to_string(elem_type);
 			gbString d_str = type_to_string(elem_type);
 			gbString s_str = type_to_string(y_type);
 			gbString s_str = type_to_string(y_type);
 			error(ast_node_token(call),
 			error(ast_node_token(call),
@@ -3002,7 +3002,7 @@ b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id)
 			if (i == 0) {
 			if (i == 0) {
 				continue;
 				continue;
 			}
 			}
-			AstNode *arg = ce->args[i];
+			AstNode *arg = ce->args.e[i];
 			Operand op = {};
 			Operand op = {};
 			check_expr(c, &op, arg);
 			check_expr(c, &op, arg);
 			if (op.mode == Addressing_Invalid) {
 			if (op.mode == Addressing_Invalid) {
@@ -3057,7 +3057,7 @@ b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id)
 			return false;
 			return false;
 		}
 		}
 
 
-		AstNode *offset = ce->args[1];
+		AstNode *offset = ce->args.e[1];
 		Operand op = {};
 		Operand op = {};
 		check_expr(c, &op, offset);
 		check_expr(c, &op, offset);
 		if (op.mode == Addressing_Invalid)
 		if (op.mode == Addressing_Invalid)
@@ -3161,10 +3161,10 @@ b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id)
 			return false;
 			return false;
 		}
 		}
 
 
-		AstNode *len = ce->args[1];
+		AstNode *len = ce->args.e[1];
 		AstNode *cap = NULL;
 		AstNode *cap = NULL;
 		if (ce->args.count > 2) {
 		if (ce->args.count > 2) {
-			cap = ce->args[2];
+			cap = ce->args.e[2];
 		}
 		}
 
 
 		Operand op = {};
 		Operand op = {};
@@ -3215,7 +3215,7 @@ b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id)
 			return false;
 			return false;
 		}
 		}
 
 
-		AstNode *other_arg = ce->args[1];
+		AstNode *other_arg = ce->args.e[1];
 		Operand a = *operand;
 		Operand a = *operand;
 		Operand b = {};
 		Operand b = {};
 		check_expr(c, &b, other_arg);
 		check_expr(c, &b, other_arg);
@@ -3284,7 +3284,7 @@ b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id)
 			return false;
 			return false;
 		}
 		}
 
 
-		AstNode *other_arg = ce->args[1];
+		AstNode *other_arg = ce->args.e[1];
 		Operand a = *operand;
 		Operand a = *operand;
 		Operand b = {};
 		Operand b = {};
 		check_expr(c, &b, other_arg);
 		check_expr(c, &b, other_arg);
@@ -3446,18 +3446,18 @@ void check_call_arguments(Checker *c, Operand *operand, Type *proc_type, AstNode
 
 
 	gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&c->tmp_arena);
 	gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&c->tmp_arena);
 
 
-	Array<Operand> operands;
-	array_init(&operands, c->tmp_allocator, 2*param_count);
+	Array(Operand) operands;
+	array_init_reserve(&operands, c->tmp_allocator, 2*param_count);
 
 
 	for_array(i, ce->args) {
 	for_array(i, ce->args) {
 		Operand o = {};
 		Operand o = {};
-		check_multi_expr(c, &o, ce->args[i]);
+		check_multi_expr(c, &o, ce->args.e[i]);
 		if (o.type->kind != Type_Tuple) {
 		if (o.type->kind != Type_Tuple) {
 			array_add(&operands, o);
 			array_add(&operands, o);
 		} else {
 		} else {
 			auto *tuple = &o.type->Tuple;
 			auto *tuple = &o.type->Tuple;
 			if (variadic && i >= param_count) {
 			if (variadic && i >= param_count) {
-				error(ast_node_token(ce->args[i]),
+				error(ast_node_token(ce->args.e[i]),
 				      "`..` in a variadic procedure cannot be applied to a %td-valued expression", tuple->variable_count);
 				      "`..` in a variadic procedure cannot be applied to a %td-valued expression", tuple->variable_count);
 				operand->mode = Addressing_Invalid;
 				operand->mode = Addressing_Invalid;
 				goto end;
 				goto end;
@@ -3493,9 +3493,9 @@ void check_call_arguments(Checker *c, Operand *operand, Type *proc_type, AstNode
 	isize operand_index = 0;
 	isize operand_index = 0;
 	for (; operand_index < param_count; operand_index++) {
 	for (; operand_index < param_count; operand_index++) {
 		Type *arg_type = sig_params[operand_index]->type;
 		Type *arg_type = sig_params[operand_index]->type;
-		Operand o = operands[operand_index];
+		Operand o = operands.e[operand_index];
 		if (variadic) {
 		if (variadic) {
-			o = operands[operand_index];
+			o = operands.e[operand_index];
 		}
 		}
 		check_assignment(c, &o, arg_type, str_lit("argument"), true);
 		check_assignment(c, &o, arg_type, str_lit("argument"), true);
 	}
 	}
@@ -3507,7 +3507,7 @@ void check_call_arguments(Checker *c, Operand *operand, Type *proc_type, AstNode
 		Type *elem = base_type(slice)->Slice.elem;
 		Type *elem = base_type(slice)->Slice.elem;
 		Type *t = elem;
 		Type *t = elem;
 		for (; operand_index < operands.count; operand_index++) {
 		for (; operand_index < operands.count; operand_index++) {
-			Operand o = operands[operand_index];
+			Operand o = operands.e[operand_index];
 			if (vari_expand) {
 			if (vari_expand) {
 				variadic_expand = true;
 				variadic_expand = true;
 				t = slice;
 				t = slice;
@@ -3556,7 +3556,7 @@ ExprKind check_call_expr(Checker *c, Operand *operand, AstNode *call) {
 
 
 	if (operand->mode == Addressing_Invalid) {
 	if (operand->mode == Addressing_Invalid) {
 		for_array(i, ce->args) {
 		for_array(i, ce->args) {
-			check_expr_base(c, operand, ce->args[i]);
+			check_expr_base(c, operand, ce->args.e[i]);
 		}
 		}
 		operand->mode = Addressing_Invalid;
 		operand->mode = Addressing_Invalid;
 		operand->expr = call;
 		operand->expr = call;
@@ -3721,11 +3721,11 @@ ExprKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *type_hint
 			}
 			}
 			{ // Checker values
 			{ // Checker values
 				isize field_count = t->Record.field_count;
 				isize field_count = t->Record.field_count;
-				if (cl->elems[0]->kind == AstNode_FieldValue) {
+				if (cl->elems.e[0]->kind == AstNode_FieldValue) {
 					b32 *fields_visited = gb_alloc_array(c->allocator, b32, field_count);
 					b32 *fields_visited = gb_alloc_array(c->allocator, b32, field_count);
 
 
 					for_array(i, cl->elems) {
 					for_array(i, cl->elems) {
-						AstNode *elem = cl->elems[i];
+						AstNode *elem = cl->elems.e[i];
 						if (elem->kind != AstNode_FieldValue) {
 						if (elem->kind != AstNode_FieldValue) {
 							error(ast_node_token(elem),
 							error(ast_node_token(elem),
 							      "Mixture of `field = value` and value elements in a structure literal is not allowed");
 							      "Mixture of `field = value` and value elements in a structure literal is not allowed");
@@ -3754,16 +3754,16 @@ ExprKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *type_hint
 							continue;
 							continue;
 						}
 						}
 
 
-						Entity *field = t->Record.fields[sel.index[0]];
+						Entity *field = t->Record.fields[sel.index.e[0]];
 						add_entity_use(c, fv->field, field);
 						add_entity_use(c, fv->field, field);
 
 
-						if (fields_visited[sel.index[0]]) {
+						if (fields_visited[sel.index.e[0]]) {
 							error(ast_node_token(elem),
 							error(ast_node_token(elem),
 							      "Duplicate field `%.*s` in structure literal", LIT(name));
 							      "Duplicate field `%.*s` in structure literal", LIT(name));
 							continue;
 							continue;
 						}
 						}
 
 
-						fields_visited[sel.index[0]] = true;
+						fields_visited[sel.index.e[0]] = true;
 						check_expr(c, o, fv->value);
 						check_expr(c, o, fv->value);
 
 
 						if (base_type(field->type) == t_any) {
 						if (base_type(field->type) == t_any) {
@@ -3778,7 +3778,7 @@ ExprKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *type_hint
 					}
 					}
 				} else {
 				} else {
 					for_array(index, cl->elems) {
 					for_array(index, cl->elems) {
-						AstNode *elem = cl->elems[index];
+						AstNode *elem = cl->elems.e[index];
 						if (elem->kind == AstNode_FieldValue) {
 						if (elem->kind == AstNode_FieldValue) {
 							error(ast_node_token(elem),
 							error(ast_node_token(elem),
 							      "Mixture of `field = value` and value elements in a structure literal is not allowed");
 							      "Mixture of `field = value` and value elements in a structure literal is not allowed");
@@ -3836,7 +3836,7 @@ ExprKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *type_hint
 			}
 			}
 
 
 			for (; index < elem_count; index++) {
 			for (; index < elem_count; index++) {
-				AstNode *e = cl->elems[index];
+				AstNode *e = cl->elems.e[index];
 				if (e->kind == AstNode_FieldValue) {
 				if (e->kind == AstNode_FieldValue) {
 					error(ast_node_token(e),
 					error(ast_node_token(e),
 					      "`field = value` is only allowed in struct literals");
 					      "`field = value` is only allowed in struct literals");
@@ -3868,7 +3868,7 @@ ExprKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *type_hint
 
 
 			if (t->kind == Type_Vector) {
 			if (t->kind == Type_Vector) {
 				if (t->Vector.count > 1 && gb_is_between(index, 2, t->Vector.count-1)) {
 				if (t->Vector.count > 1 && gb_is_between(index, 2, t->Vector.count-1)) {
-					error(ast_node_token(cl->elems[0]),
+					error(ast_node_token(cl->elems.e[0]),
 					      "Expected either 1 (broadcast) or %td elements in vector literal, got %td", t->Vector.count, index);
 					      "Expected either 1 (broadcast) or %td elements in vector literal, got %td", t->Vector.count, index);
 				}
 				}
 			}
 			}
@@ -4274,12 +4274,12 @@ gbString write_expr_to_string(gbString str, AstNode *node);
 
 
 gbString write_params_to_string(gbString str, AstNodeArray params, char *sep) {
 gbString write_params_to_string(gbString str, AstNodeArray params, char *sep) {
 	for_array(i, params) {
 	for_array(i, params) {
-		ast_node(p, Parameter, params[i]);
+		ast_node(p, Parameter, params.e[i]);
 		if (i > 0) {
 		if (i > 0) {
 			str = gb_string_appendc(str, sep);
 			str = gb_string_appendc(str, sep);
 		}
 		}
 
 
-		str = write_expr_to_string(str, params[i]);
+		str = write_expr_to_string(str, params.e[i]);
 	}
 	}
 	return str;
 	return str;
 }
 }
@@ -4324,7 +4324,7 @@ gbString write_expr_to_string(gbString str, AstNode *node) {
 			if (i > 0) {
 			if (i > 0) {
 				str = gb_string_appendc(str, ", ");
 				str = gb_string_appendc(str, ", ");
 			}
 			}
-			str = write_expr_to_string(str, cl->elems[i]);
+			str = write_expr_to_string(str, cl->elems.e[i]);
 		}
 		}
 		str = gb_string_appendc(str, "}");
 		str = gb_string_appendc(str, "}");
 	case_end;
 	case_end;
@@ -4429,7 +4429,7 @@ gbString write_expr_to_string(gbString str, AstNode *node) {
 			str = gb_string_appendc(str, "using ");
 			str = gb_string_appendc(str, "using ");
 		}
 		}
 		for_array(i, p->names) {
 		for_array(i, p->names) {
-			AstNode *name = p->names[i];
+			AstNode *name = p->names.e[i];
 			if (i > 0)
 			if (i > 0)
 				str = gb_string_appendc(str, ", ");
 				str = gb_string_appendc(str, ", ");
 			str = write_expr_to_string(str, name);
 			str = write_expr_to_string(str, name);
@@ -4444,7 +4444,7 @@ gbString write_expr_to_string(gbString str, AstNode *node) {
 		str = gb_string_appendc(str, "(");
 		str = gb_string_appendc(str, "(");
 
 
 		for_array(i, ce->args) {
 		for_array(i, ce->args) {
-			AstNode *arg = ce->args[i];
+			AstNode *arg = ce->args.e[i];
 			if (i > 0) {
 			if (i > 0) {
 				str = gb_string_appendc(str, ", ");
 				str = gb_string_appendc(str, ", ");
 			}
 			}
@@ -4467,7 +4467,7 @@ gbString write_expr_to_string(gbString str, AstNode *node) {
 			if (i > 0) {
 			if (i > 0) {
 				str = gb_string_appendc(str, "; ");
 				str = gb_string_appendc(str, "; ");
 			}
 			}
-			str = write_expr_to_string(str, st->decls[i]);
+			str = write_expr_to_string(str, st->decls.e[i]);
 		}
 		}
 		// str = write_params_to_string(str, st->decl_list, ", ");
 		// str = write_params_to_string(str, st->decl_list, ", ");
 		str = gb_string_appendc(str, "}");
 		str = gb_string_appendc(str, "}");
@@ -4479,7 +4479,7 @@ gbString write_expr_to_string(gbString str, AstNode *node) {
 			if (i > 0) {
 			if (i > 0) {
 				str = gb_string_appendc(str, "; ");
 				str = gb_string_appendc(str, "; ");
 			}
 			}
-			str = write_expr_to_string(str, st->decls[i]);
+			str = write_expr_to_string(str, st->decls.e[i]);
 		}
 		}
 		// str = write_params_to_string(str, st->decl_list, ", ");
 		// str = write_params_to_string(str, st->decl_list, ", ");
 		str = gb_string_appendc(str, "}");
 		str = gb_string_appendc(str, "}");
@@ -4491,7 +4491,7 @@ gbString write_expr_to_string(gbString str, AstNode *node) {
 			if (i > 0) {
 			if (i > 0) {
 				str = gb_string_appendc(str, "; ");
 				str = gb_string_appendc(str, "; ");
 			}
 			}
-			str = write_expr_to_string(str, st->decls[i]);
+			str = write_expr_to_string(str, st->decls.e[i]);
 		}
 		}
 		// str = write_params_to_string(str, st->decl_list, ", ");
 		// str = write_params_to_string(str, st->decl_list, ", ");
 		str = gb_string_appendc(str, "}");
 		str = gb_string_appendc(str, "}");

+ 33 - 33
src/checker/stmt.cpp

@@ -23,16 +23,16 @@ void check_stmt_list(Checker *c, AstNodeArray stmts, u32 flags) {
 		Entity *e;
 		Entity *e;
 		DeclInfo *d;
 		DeclInfo *d;
 	} Delay;
 	} Delay;
-	Array<Delay> delayed_const; array_init(&delayed_const, c->tmp_allocator, stmts.count);
-	Array<Delay> delayed_type;  array_init(&delayed_type,  c->tmp_allocator, stmts.count);
+	Array(Delay) delayed_const; array_init_reserve(&delayed_const, c->tmp_allocator, stmts.count);
+	Array(Delay) delayed_type;  array_init_reserve(&delayed_type,  c->tmp_allocator, stmts.count);
 
 
 	for_array(i, stmts) {
 	for_array(i, stmts) {
-		AstNode *node = stmts[i];
+		AstNode *node = stmts.e[i];
 		switch (node->kind) {
 		switch (node->kind) {
 		case_ast_node(cd, ConstDecl, node);
 		case_ast_node(cd, ConstDecl, node);
 			for_array(i, cd->values) {
 			for_array(i, cd->values) {
-				AstNode *name = cd->names[i];
-				AstNode *value = cd->values[i];
+				AstNode *name = cd->names.e[i];
+				AstNode *value = cd->values.e[i];
 				ExactValue v = {ExactValue_Invalid};
 				ExactValue v = {ExactValue_Invalid};
 
 
 				Entity *e = make_entity_constant(c->allocator, c->context.scope, name->Ident, NULL, v);
 				Entity *e = make_entity_constant(c->allocator, c->context.scope, name->Ident, NULL, v);
@@ -74,17 +74,17 @@ void check_stmt_list(Checker *c, AstNodeArray stmts, u32 flags) {
 	}
 	}
 
 
 	for_array(i, delayed_type) {
 	for_array(i, delayed_type) {
-		check_entity_decl(c, delayed_type[i].e, delayed_type[i].d, NULL);
+		check_entity_decl(c, delayed_type.e[i].e, delayed_type.e[i].d, NULL);
 	}
 	}
 	for_array(i, delayed_const) {
 	for_array(i, delayed_const) {
-		check_entity_decl(c, delayed_const[i].e, delayed_const[i].d, NULL);
+		check_entity_decl(c, delayed_const.e[i].e, delayed_const.e[i].d, NULL);
 	}
 	}
 
 
 	b32 ft_ok = (flags & Stmt_FallthroughAllowed) != 0;
 	b32 ft_ok = (flags & Stmt_FallthroughAllowed) != 0;
 	u32 f = flags & (~Stmt_FallthroughAllowed);
 	u32 f = flags & (~Stmt_FallthroughAllowed);
 
 
 	for_array(i, stmts) {
 	for_array(i, stmts) {
-		AstNode *n = stmts[i];
+		AstNode *n = stmts.e[i];
 		if (n->kind == AstNode_EmptyStmt) {
 		if (n->kind == AstNode_EmptyStmt) {
 			continue;
 			continue;
 		}
 		}
@@ -102,7 +102,7 @@ b32 check_is_terminating_list(AstNodeArray stmts) {
 
 
 	// Iterate backwards
 	// Iterate backwards
 	for (isize n = stmts.count-1; n >= 0; n--) {
 	for (isize n = stmts.count-1; n >= 0; n--) {
-		AstNode *stmt = stmts[n];
+		AstNode *stmt = stmts.e[n];
 		if (stmt->kind != AstNode_EmptyStmt) {
 		if (stmt->kind != AstNode_EmptyStmt) {
 			return check_is_terminating(stmt);
 			return check_is_terminating(stmt);
 		}
 		}
@@ -113,7 +113,7 @@ b32 check_is_terminating_list(AstNodeArray stmts) {
 
 
 b32 check_has_break_list(AstNodeArray stmts, b32 implicit) {
 b32 check_has_break_list(AstNodeArray stmts, b32 implicit) {
 	for_array(i, stmts) {
 	for_array(i, stmts) {
-		AstNode *stmt = stmts[i];
+		AstNode *stmt = stmts.e[i];
 		if (check_has_break(stmt, implicit)) {
 		if (check_has_break(stmt, implicit)) {
 			return true;
 			return true;
 		}
 		}
@@ -187,7 +187,7 @@ b32 check_is_terminating(AstNode *node) {
 	case_ast_node(ms, MatchStmt, node);
 	case_ast_node(ms, MatchStmt, node);
 		b32 has_default = false;
 		b32 has_default = false;
 		for_array(i, ms->body->BlockStmt.stmts) {
 		for_array(i, ms->body->BlockStmt.stmts) {
-			AstNode *clause = ms->body->BlockStmt.stmts[i];
+			AstNode *clause = ms->body->BlockStmt.stmts.e[i];
 			ast_node(cc, CaseClause, clause);
 			ast_node(cc, CaseClause, clause);
 			if (cc->list.count == 0) {
 			if (cc->list.count == 0) {
 				has_default = true;
 				has_default = true;
@@ -203,7 +203,7 @@ b32 check_is_terminating(AstNode *node) {
 	case_ast_node(ms, TypeMatchStmt, node);
 	case_ast_node(ms, TypeMatchStmt, node);
 		b32 has_default = false;
 		b32 has_default = false;
 		for_array(i, ms->body->BlockStmt.stmts) {
 		for_array(i, ms->body->BlockStmt.stmts) {
-			AstNode *clause = ms->body->BlockStmt.stmts[i];
+			AstNode *clause = ms->body->BlockStmt.stmts.e[i];
 			ast_node(cc, CaseClause, clause);
 			ast_node(cc, CaseClause, clause);
 			if (cc->list.count == 0) {
 			if (cc->list.count == 0) {
 				has_default = true;
 				has_default = true;
@@ -433,11 +433,11 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
 
 
 			// NOTE(bill): If there is a bad syntax error, rhs > lhs which would mean there would need to be
 			// NOTE(bill): If there is a bad syntax error, rhs > lhs which would mean there would need to be
 			// an extra allocation
 			// an extra allocation
-			Array<Operand> operands;
-			array_init(&operands, c->tmp_allocator, 2 * as->lhs.count);
+			Array(Operand) operands;
+			array_init_reserve(&operands, c->tmp_allocator, 2 * as->lhs.count);
 
 
 			for_array(i, as->rhs) {
 			for_array(i, as->rhs) {
-				AstNode *rhs = as->rhs[i];
+				AstNode *rhs = as->rhs.e[i];
 				Operand o = {};
 				Operand o = {};
 				check_multi_expr(c, &o, rhs);
 				check_multi_expr(c, &o, rhs);
 				if (o.type->kind != Type_Tuple) {
 				if (o.type->kind != Type_Tuple) {
@@ -456,11 +456,11 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
 
 
 			isize operand_count = gb_min(as->lhs.count, operands.count);
 			isize operand_count = gb_min(as->lhs.count, operands.count);
 			for (isize i = 0; i < operand_count; i++) {
 			for (isize i = 0; i < operand_count; i++) {
-				AstNode *lhs = as->lhs[i];
-				check_assignment_variable(c, &operands[i], lhs);
+				AstNode *lhs = as->lhs.e[i];
+				check_assignment_variable(c, &operands.e[i], lhs);
 			}
 			}
 			if (lhs_count != rhs_count) {
 			if (lhs_count != rhs_count) {
-				error(ast_node_token(as->lhs[0]), "Assignment count mismatch `%td` = `%td`", lhs_count, rhs_count);
+				error(ast_node_token(as->lhs.e[0]), "Assignment count mismatch `%td` = `%td`", lhs_count, rhs_count);
 			}
 			}
 
 
 			gb_temp_arena_memory_end(tmp);
 			gb_temp_arena_memory_end(tmp);
@@ -484,15 +484,15 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
 			be->op = op;
 			be->op = op;
 			be->op.kind = cast(TokenKind)(cast(i32)be->op.kind - (Token_AddEq - Token_Add));
 			be->op.kind = cast(TokenKind)(cast(i32)be->op.kind - (Token_AddEq - Token_Add));
 			 // NOTE(bill): Only use the first one will be used
 			 // NOTE(bill): Only use the first one will be used
-			be->left  = as->lhs[0];
-			be->right = as->rhs[0];
+			be->left  = as->lhs.e[0];
+			be->right = as->rhs.e[0];
 
 
 			check_binary_expr(c, &operand, &binary_expr);
 			check_binary_expr(c, &operand, &binary_expr);
 			if (operand.mode == Addressing_Invalid) {
 			if (operand.mode == Addressing_Invalid) {
 				return;
 				return;
 			}
 			}
 			// NOTE(bill): Only use the first one will be used
 			// NOTE(bill): Only use the first one will be used
-			check_assignment_variable(c, &operand, as->lhs[0]);
+			check_assignment_variable(c, &operand, as->lhs.e[0]);
 		} break;
 		} break;
 		}
 		}
 	case_end;
 	case_end;
@@ -550,7 +550,7 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
 		}
 		}
 
 
 
 
-		Type *proc_type = c->proc_stack[c->proc_stack.count-1];
+		Type *proc_type = c->proc_stack.e[c->proc_stack.count-1];
 		isize result_count = 0;
 		isize result_count = 0;
 		if (proc_type->Proc.results) {
 		if (proc_type->Proc.results) {
 			result_count = proc_type->Proc.results->Tuple.variable_count;
 			result_count = proc_type->Proc.results->Tuple.variable_count;
@@ -569,7 +569,7 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
 				                     rs->results, str_lit("return statement"));
 				                     rs->results, str_lit("return statement"));
 			}
 			}
 		} else if (rs->results.count > 0) {
 		} else if (rs->results.count > 0) {
-			error(ast_node_token(rs->results[0]), "No return values expected");
+			error(ast_node_token(rs->results.e[0]), "No return values expected");
 		}
 		}
 	case_end;
 	case_end;
 
 
@@ -628,7 +628,7 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
 		AstNode *first_default = NULL;
 		AstNode *first_default = NULL;
 		ast_node(bs, BlockStmt, ms->body);
 		ast_node(bs, BlockStmt, ms->body);
 		for_array(i, bs->stmts) {
 		for_array(i, bs->stmts) {
-			AstNode *stmt = bs->stmts[i];
+			AstNode *stmt = bs->stmts.e[i];
 			AstNode *default_stmt = NULL;
 			AstNode *default_stmt = NULL;
 			if (stmt->kind == AstNode_CaseClause) {
 			if (stmt->kind == AstNode_CaseClause) {
 				ast_node(cc, CaseClause, stmt);
 				ast_node(cc, CaseClause, stmt);
@@ -661,7 +661,7 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
 		map_init(&seen, heap_allocator());
 		map_init(&seen, heap_allocator());
 
 
 		for_array(i, bs->stmts) {
 		for_array(i, bs->stmts) {
-			AstNode *stmt = bs->stmts[i];
+			AstNode *stmt = bs->stmts.e[i];
 			if (stmt->kind != AstNode_CaseClause) {
 			if (stmt->kind != AstNode_CaseClause) {
 				// NOTE(bill): error handled by above multiple default checker
 				// NOTE(bill): error handled by above multiple default checker
 				continue;
 				continue;
@@ -670,7 +670,7 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
 
 
 
 
 			for_array(j, cc->list) {
 			for_array(j, cc->list) {
-				AstNode *expr = cc->list[j];
+				AstNode *expr = cc->list.e[j];
 				Operand y = {};
 				Operand y = {};
 				Operand z = {};
 				Operand z = {};
 				Token eq = {Token_CmpEq};
 				Token eq = {Token_CmpEq};
@@ -772,7 +772,7 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
 		AstNode *first_default = NULL;
 		AstNode *first_default = NULL;
 		ast_node(bs, BlockStmt, ms->body);
 		ast_node(bs, BlockStmt, ms->body);
 		for_array(i, bs->stmts) {
 		for_array(i, bs->stmts) {
-			AstNode *stmt = bs->stmts[i];
+			AstNode *stmt = bs->stmts.e[i];
 			AstNode *default_stmt = NULL;
 			AstNode *default_stmt = NULL;
 			if (stmt->kind == AstNode_CaseClause) {
 			if (stmt->kind == AstNode_CaseClause) {
 				ast_node(cc, CaseClause, stmt);
 				ast_node(cc, CaseClause, stmt);
@@ -804,7 +804,7 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
 		map_init(&seen, heap_allocator());
 		map_init(&seen, heap_allocator());
 
 
 		for_array(i, bs->stmts) {
 		for_array(i, bs->stmts) {
-			AstNode *stmt = bs->stmts[i];
+			AstNode *stmt = bs->stmts.e[i];
 			if (stmt->kind != AstNode_CaseClause) {
 			if (stmt->kind != AstNode_CaseClause) {
 				// NOTE(bill): error handled by above multiple default checker
 				// NOTE(bill): error handled by above multiple default checker
 				continue;
 				continue;
@@ -815,7 +815,7 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
 			Type *bt = base_type(type_deref(x.type));
 			Type *bt = base_type(type_deref(x.type));
 
 
 
 
-			AstNode *type_expr = cc->list.count > 0 ? cc->list[0] : NULL;
+			AstNode *type_expr = cc->list.count > 0 ? cc->list.e[0] : NULL;
 			Type *case_type = NULL;
 			Type *case_type = NULL;
 			if (type_expr != NULL) { // Otherwise it's a default expression
 			if (type_expr != NULL) { // Otherwise it's a default expression
 				Operand y = {};
 				Operand y = {};
@@ -988,7 +988,7 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
 			case Entity_ImportName: {
 			case Entity_ImportName: {
 				Scope *scope = e->ImportName.scope;
 				Scope *scope = e->ImportName.scope;
 				for_array(i, scope->elements.entries) {
 				for_array(i, scope->elements.entries) {
-					Entity *decl = scope->elements.entries[i].value;
+					Entity *decl = scope->elements.entries.e[i].value;
 					Entity *found = scope_insert_entity(c->context.scope, decl);
 					Entity *found = scope_insert_entity(c->context.scope, decl);
 					if (found != NULL) {
 					if (found != NULL) {
 						gbString expr_str = expr_to_string(expr);
 						gbString expr_str = expr_to_string(expr);
@@ -1012,7 +1012,7 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
 					Scope **found = map_get(&c->info.scopes, hash_pointer(t->Record.node));
 					Scope **found = map_get(&c->info.scopes, hash_pointer(t->Record.node));
 					GB_ASSERT(found != NULL);
 					GB_ASSERT(found != NULL);
 					for_array(i, (*found)->elements.entries) {
 					for_array(i, (*found)->elements.entries) {
-						Entity *f = (*found)->elements.entries[i].value;
+						Entity *f = (*found)->elements.entries.e[i].value;
 						if (f->kind == Entity_Variable) {
 						if (f->kind == Entity_Variable) {
 							Entity *uvar = make_entity_using_variable(c->allocator, e, f->token, f->type);
 							Entity *uvar = make_entity_using_variable(c->allocator, e, f->token, f->type);
 							if (is_selector) {
 							if (is_selector) {
@@ -1068,7 +1068,7 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
 			check_var_decl_node(c, us->node);
 			check_var_decl_node(c, us->node);
 
 
 			for_array(name_index, vd->names) {
 			for_array(name_index, vd->names) {
-				AstNode *item = vd->names[name_index];
+				AstNode *item = vd->names.e[name_index];
 				ast_node(i, Ident, item);
 				ast_node(i, Ident, item);
 				String name = i->string;
 				String name = i->string;
 				Entity *e = scope_lookup_entity(c->context.scope, name);
 				Entity *e = scope_lookup_entity(c->context.scope, name);
@@ -1077,7 +1077,7 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
 					Scope **found = map_get(&c->info.scopes, hash_pointer(t->Record.node));
 					Scope **found = map_get(&c->info.scopes, hash_pointer(t->Record.node));
 					GB_ASSERT(found != NULL);
 					GB_ASSERT(found != NULL);
 					for_array(i, (*found)->elements.entries) {
 					for_array(i, (*found)->elements.entries) {
-						Entity *f = (*found)->elements.entries[i].value;
+						Entity *f = (*found)->elements.entries.e[i].value;
 						if (f->kind == Entity_Variable) {
 						if (f->kind == Entity_Variable) {
 							Entity *uvar = make_entity_using_variable(c->allocator, e, f->token, f->type);
 							Entity *uvar = make_entity_using_variable(c->allocator, e, f->token, f->type);
 							Entity *prev = scope_insert_entity(c->context.scope, uvar);
 							Entity *prev = scope_insert_entity(c->context.scope, uvar);

+ 8 - 6
src/checker/types.cpp

@@ -805,14 +805,16 @@ struct BaseTypeSizes {
 	i64 max_align;
 	i64 max_align;
 };
 };
 
 
+typedef Array(isize) Array_isize;
+
 struct Selection {
 struct Selection {
-	Entity *entity;
-	Array<isize> index;
-	b32 indirect; // Set if there was a pointer deref anywhere down the line
+	Entity *    entity;
+	Array_isize index;
+	b32         indirect; // Set if there was a pointer deref anywhere down the line
 };
 };
 Selection empty_selection = {};
 Selection empty_selection = {};
 
 
-Selection make_selection(Entity *entity, Array<isize> index, b32 indirect) {
+Selection make_selection(Entity *entity, Array_isize index, b32 indirect) {
 	Selection s = {entity, index, indirect};
 	Selection s = {entity, index, indirect};
 	return s;
 	return s;
 }
 }
@@ -820,7 +822,7 @@ Selection make_selection(Entity *entity, Array<isize> index, b32 indirect) {
 void selection_add_index(Selection *s, isize index) {
 void selection_add_index(Selection *s, isize index) {
 	// IMPORTANT NOTE(bill): this requires a stretchy buffer/dynamic array so it requires some form
 	// IMPORTANT NOTE(bill): this requires a stretchy buffer/dynamic array so it requires some form
 	// of heap allocation
 	// of heap allocation
-	if (s->index.data == NULL) {
+	if (s->index.e == NULL) {
 		array_init(&s->index, heap_allocator());
 		array_init(&s->index, heap_allocator());
 	}
 	}
 	array_add(&s->index, index);
 	array_add(&s->index, index);
@@ -1334,7 +1336,7 @@ i64 type_offset_of_from_selection(BaseTypeSizes s, gbAllocator allocator, Type *
 	Type *t = type;
 	Type *t = type;
 	i64 offset = 0;
 	i64 offset = 0;
 	for_array(i, sel.index) {
 	for_array(i, sel.index) {
-		isize index = sel.index[i];
+		isize index = sel.index.e[i];
 		t = base_type(t);
 		t = base_type(t);
 		offset += type_offset_of(s, allocator, t, index);
 		offset += type_offset_of(s, allocator, t, index);
 		if (t->kind == Type_Record && t->Record.kind == TypeRecord_Struct) {
 		if (t->kind == Type_Record && t->Record.kind == TypeRecord_Struct) {

+ 37 - 38
src/common.cpp

@@ -18,13 +18,12 @@ String get_module_dir() {
 		return global_module_path;
 		return global_module_path;
 	}
 	}
 
 
-	Array<wchar_t> path_buf;
-	array_init(&path_buf, heap_allocator(), 300);
-	array_resize(&path_buf, 300);
+	Array(wchar_t) path_buf;
+	array_init_count(&path_buf, heap_allocator(), 300);
 
 
 	isize len = 0;
 	isize len = 0;
 	for (;;) {
 	for (;;) {
-		len = GetModuleFileNameW(NULL, &path_buf[0], path_buf.count);
+		len = GetModuleFileNameW(NULL, &path_buf.e[0], path_buf.count);
 		if (len == 0) {
 		if (len == 0) {
 			return make_string(NULL, 0);
 			return make_string(NULL, 0);
 		}
 		}
@@ -250,8 +249,8 @@ struct MapEntry {
 
 
 template <typename T>
 template <typename T>
 struct Map {
 struct Map {
-	Array<isize> hashes;
-	Array<MapEntry<T> > entries;
+	Array(isize)       hashes;
+	Array(MapEntry<T>) entries;
 };
 };
 
 
 template <typename T> void map_init             (Map<T> *h, gbAllocator a);
 template <typename T> void map_init             (Map<T> *h, gbAllocator a);
@@ -284,8 +283,8 @@ gb_inline void map_init(Map<T> *h, gbAllocator a) {
 
 
 template <typename T>
 template <typename T>
 gb_inline void map_init_with_reserve(Map<T> *h, gbAllocator a, isize capacity) {
 gb_inline void map_init_with_reserve(Map<T> *h, gbAllocator a, isize capacity) {
-	array_init(&h->hashes,  a, capacity);
-	array_init(&h->entries, a, capacity);
+	array_init_reserve(&h->hashes,  a, capacity);
+	array_init_reserve(&h->entries, a, capacity);
 }
 }
 
 
 template <typename T>
 template <typename T>
@@ -308,13 +307,13 @@ gb_internal MapFindResult map__find(Map<T> *h, HashKey key) {
 	MapFindResult fr = {-1, -1, -1};
 	MapFindResult fr = {-1, -1, -1};
 	if (h->hashes.count > 0) {
 	if (h->hashes.count > 0) {
 		fr.hash_index  = key.key % h->hashes.count;
 		fr.hash_index  = key.key % h->hashes.count;
-		fr.entry_index = h->hashes[fr.hash_index];
+		fr.entry_index = h->hashes.e[fr.hash_index];
 		while (fr.entry_index >= 0) {
 		while (fr.entry_index >= 0) {
-			if (hash_key_equal(h->entries[fr.entry_index].key, key)) {
+			if (hash_key_equal(h->entries.e[fr.entry_index].key, key)) {
 				return fr;
 				return fr;
 			}
 			}
 			fr.entry_prev = fr.entry_index;
 			fr.entry_prev = fr.entry_index;
-			fr.entry_index = h->entries[fr.entry_index].next;
+			fr.entry_index = h->entries.e[fr.entry_index].next;
 		}
 		}
 	}
 	}
 	return fr;
 	return fr;
@@ -325,13 +324,13 @@ gb_internal MapFindResult map__find(Map<T> *h, MapEntry<T> *e) {
 	MapFindResult fr = {-1, -1, -1};
 	MapFindResult fr = {-1, -1, -1};
 	if (h->hashes.count > 0) {
 	if (h->hashes.count > 0) {
 		fr.hash_index  = e->key.key % h->hashes.count;
 		fr.hash_index  = e->key.key % h->hashes.count;
-		fr.entry_index = h->hashes[fr.hash_index];
+		fr.entry_index = h->hashes.e[fr.hash_index];
 		while (fr.entry_index >= 0) {
 		while (fr.entry_index >= 0) {
-			if (&h->entries[fr.entry_index] == e) {
+			if (&h->entries.e[fr.entry_index] == e) {
 				return fr;
 				return fr;
 			}
 			}
 			fr.entry_prev = fr.entry_index;
 			fr.entry_prev = fr.entry_index;
-			fr.entry_index = h->entries[fr.entry_index].next;
+			fr.entry_index = h->entries.e[fr.entry_index].next;
 		}
 		}
 	}
 	}
 	return fr;
 	return fr;
@@ -357,10 +356,10 @@ void map_rehash(Map<T> *h, isize new_count) {
 	array_resize(&nh.hashes, new_count);
 	array_resize(&nh.hashes, new_count);
 	array_reserve(&nh.entries, h->entries.count);
 	array_reserve(&nh.entries, h->entries.count);
 	for (i = 0; i < new_count; i++) {
 	for (i = 0; i < new_count; i++) {
-		nh.hashes[i] = -1;
+		nh.hashes.e[i] = -1;
 	}
 	}
 	for (i = 0; i < h->entries.count; i++) {
 	for (i = 0; i < h->entries.count; i++) {
-		MapEntry<T> *e = &h->entries[i];
+		MapEntry<T> *e = &h->entries.e[i];
 		MapFindResult fr;
 		MapFindResult fr;
 		if (nh.hashes.count == 0) {
 		if (nh.hashes.count == 0) {
 			map_grow(&nh);
 			map_grow(&nh);
@@ -368,12 +367,12 @@ void map_rehash(Map<T> *h, isize new_count) {
 		fr = map__find(&nh, e->key);
 		fr = map__find(&nh, e->key);
 		j = map__add_entry(&nh, e->key);
 		j = map__add_entry(&nh, e->key);
 		if (fr.entry_prev < 0) {
 		if (fr.entry_prev < 0) {
-			nh.hashes[fr.hash_index] = j;
+			nh.hashes.e[fr.hash_index] = j;
 		} else {
 		} else {
-			nh.entries[fr.entry_prev].next = j;
+			nh.entries.e[fr.entry_prev].next = j;
 		}
 		}
-		nh.entries[j].next = fr.entry_index;
-		nh.entries[j].value = e->value;
+		nh.entries.e[j].next = fr.entry_index;
+		nh.entries.e[j].value = e->value;
 		if (map__full(&nh)) {
 		if (map__full(&nh)) {
 			map_grow(&nh);
 			map_grow(&nh);
 		}
 		}
@@ -386,7 +385,7 @@ template <typename T>
 gb_inline T *map_get(Map<T> *h, HashKey key) {
 gb_inline T *map_get(Map<T> *h, HashKey key) {
 	isize index = map__find(h, key).entry_index;
 	isize index = map__find(h, key).entry_index;
 	if (index >= 0)
 	if (index >= 0)
-		return &h->entries[index].value;
+		return &h->entries.e[index].value;
 	return NULL;
 	return NULL;
 }
 }
 
 
@@ -402,12 +401,12 @@ void map_set(Map<T> *h, HashKey key, T value) {
 	} else {
 	} else {
 		index = map__add_entry(h, key);
 		index = map__add_entry(h, key);
 		if (fr.entry_prev >= 0) {
 		if (fr.entry_prev >= 0) {
-			h->entries[fr.entry_prev].next = index;
+			h->entries.e[fr.entry_prev].next = index;
 		} else {
 		} else {
-			h->hashes[fr.hash_index] = index;
+			h->hashes.e[fr.hash_index] = index;
 		}
 		}
 	}
 	}
-	h->entries[index].value = value;
+	h->entries.e[index].value = value;
 
 
 	if (map__full(h))
 	if (map__full(h))
 		map_grow(h);
 		map_grow(h);
@@ -418,20 +417,20 @@ void map_set(Map<T> *h, HashKey key, T value) {
 template <typename T>
 template <typename T>
 void map__erase(Map<T> *h, MapFindResult fr) {
 void map__erase(Map<T> *h, MapFindResult fr) {
 	if (fr.entry_prev < 0) {
 	if (fr.entry_prev < 0) {
-		h->hashes[fr.hash_index] = h->entries[fr.entry_index].next;
+		h->hashes.e[fr.hash_index] = h->entries.e[fr.entry_index].next;
 	} else {
 	} else {
-		h->entries[fr.entry_prev].next = h->entries[fr.entry_index].next;
+		h->entries.e[fr.entry_prev].next = h->entries.e[fr.entry_index].next;
 	}
 	}
 	if (fr.entry_index == h->entries.count-1) {
 	if (fr.entry_index == h->entries.count-1) {
 		array_pop(&h->entries);
 		array_pop(&h->entries);
 		return;
 		return;
 	}
 	}
-	h->entries[fr.entry_index] = h->entries[h->entries.count-1];
-	MapFindResult last = map__find(h, h->entries[fr.entry_index].key);
+	h->entries.e[fr.entry_index] = h->entries.e[h->entries.count-1];
+	MapFindResult last = map__find(h, h->entries.e[fr.entry_index].key);
 	if (last.entry_prev >= 0) {
 	if (last.entry_prev >= 0) {
-		h->entries[last.entry_prev].next = fr.entry_index;
+		h->entries.e[last.entry_prev].next = fr.entry_index;
 	} else {
 	} else {
-		h->hashes[last.hash_index] = fr.entry_index;
+		h->hashes.e[last.hash_index] = fr.entry_index;
 	}
 	}
 }
 }
 
 
@@ -457,17 +456,17 @@ MapEntry<T> *multi_map_find_first(Map<T> *h, HashKey key) {
 	if (i < 0) {
 	if (i < 0) {
 		return NULL;
 		return NULL;
 	}
 	}
-	return &h->entries[i];
+	return &h->entries.e[i];
 }
 }
 
 
 template <typename T>
 template <typename T>
 MapEntry<T> *multi_map_find_next(Map<T> *h, MapEntry<T> *e) {
 MapEntry<T> *multi_map_find_next(Map<T> *h, MapEntry<T> *e) {
 	isize i = e->next;
 	isize i = e->next;
 	while (i >= 0) {
 	while (i >= 0) {
-		if (hash_key_equal(h->entries[i].key, e->key)) {
-			return &h->entries[i];
+		if (hash_key_equal(h->entries.e[i].key, e->key)) {
+			return &h->entries.e[i];
 		}
 		}
-		i = h->entries[i].next;
+		i = h->entries.e[i].next;
 	}
 	}
 	return NULL;
 	return NULL;
 }
 }
@@ -501,12 +500,12 @@ void multi_map_insert(Map<T> *h, HashKey key, T value) {
 	MapFindResult fr = map__find(h, key);
 	MapFindResult fr = map__find(h, key);
 	isize i = map__add_entry(h, key);
 	isize i = map__add_entry(h, key);
 	if (fr.entry_prev < 0) {
 	if (fr.entry_prev < 0) {
-		h->hashes[fr.hash_index] = i;
+		h->hashes.e[fr.hash_index] = i;
 	} else {
 	} else {
-		h->entries[fr.entry_prev].next = i;
+		h->entries.e[fr.entry_prev].next = i;
 	}
 	}
-	h->entries[i].next = fr.entry_index;
-	h->entries[i].value = value;
+	h->entries.e[i].next = fr.entry_index;
+	h->entries.e[i].value = value;
 	if (map__full(h)) {
 	if (map__full(h)) {
 		map_grow(h);
 		map_grow(h);
 	}
 	}

+ 1 - 1
src/main.cpp

@@ -233,7 +233,7 @@ int main(int argc, char **argv) {
 	// defer (gb_string_free(lib_str));
 	// defer (gb_string_free(lib_str));
 	char lib_str_buf[1024] = {0};
 	char lib_str_buf[1024] = {0};
 	for_array(i, parser.foreign_libraries) {
 	for_array(i, parser.foreign_libraries) {
-		String lib = parser.foreign_libraries[i];
+		String lib = parser.foreign_libraries.e[i];
 		isize len = gb_snprintf(lib_str_buf, gb_size_of(lib_str_buf),
 		isize len = gb_snprintf(lib_str_buf, gb_size_of(lib_str_buf),
 		                        " %.*s.lib", LIT(lib));
 		                        " %.*s.lib", LIT(lib));
 		lib_str = gb_string_appendc(lib_str, lib_str_buf);
 		lib_str = gb_string_appendc(lib_str, lib_str_buf);

+ 36 - 36
src/parser.cpp

@@ -15,13 +15,13 @@ enum ParseFileError {
 	ParseFile_Count,
 	ParseFile_Count,
 };
 };
 
 
-typedef Array<AstNode *> AstNodeArray;
+typedef Array(AstNode *) AstNodeArray;
 
 
 struct AstFile {
 struct AstFile {
 	i32            id;
 	i32            id;
 	gbArena        arena;
 	gbArena        arena;
 	Tokenizer      tokenizer;
 	Tokenizer      tokenizer;
-	Array<Token>   tokens;
+	Array(Token)   tokens;
 	isize          curr_token_index;
 	isize          curr_token_index;
 	Token          curr_token;
 	Token          curr_token;
 	Token          prev_token; // previous non-comment
 	Token          prev_token; // previous non-comment
@@ -53,10 +53,10 @@ struct ImportedFile {
 
 
 struct Parser {
 struct Parser {
 	String              init_fullpath;
 	String              init_fullpath;
-	Array<AstFile>      files;
-	Array<ImportedFile> imports;
+	Array(AstFile)      files;
+	Array(ImportedFile) imports;
 	gbAtomic32          import_index;
 	gbAtomic32          import_index;
-	Array<String>       foreign_libraries;
+	Array(String)       foreign_libraries;
 	isize               total_token_count;
 	isize               total_token_count;
 	gbMutex             mutex;
 	gbMutex             mutex;
 };
 };
@@ -452,9 +452,9 @@ Token ast_node_token(AstNode *node) {
 	case AstNode_BadDecl:
 	case AstNode_BadDecl:
 		return node->BadDecl.begin;
 		return node->BadDecl.begin;
 	case AstNode_VarDecl:
 	case AstNode_VarDecl:
-		return ast_node_token(node->VarDecl.names[0]);
+		return ast_node_token(node->VarDecl.names.e[0]);
 	case AstNode_ConstDecl:
 	case AstNode_ConstDecl:
-		return ast_node_token(node->ConstDecl.names[0]);
+		return ast_node_token(node->ConstDecl.names.e[0]);
 	case AstNode_ProcDecl:
 	case AstNode_ProcDecl:
 		return node->ProcDecl.name->Ident;
 		return node->ProcDecl.name->Ident;
 	case AstNode_TypeDecl:
 	case AstNode_TypeDecl:
@@ -465,7 +465,7 @@ Token ast_node_token(AstNode *node) {
 		return node->ForeignLibrary.token;
 		return node->ForeignLibrary.token;
 	case AstNode_Parameter: {
 	case AstNode_Parameter: {
 		if (node->Parameter.names.count > 0) {
 		if (node->Parameter.names.count > 0) {
-			return ast_node_token(node->Parameter.names[0]);
+			return ast_node_token(node->Parameter.names.e[0]);
 		} else {
 		} else {
 			return ast_node_token(node->Parameter.type);
 			return ast_node_token(node->Parameter.type);
 		}
 		}
@@ -981,7 +981,7 @@ b32 next_token(AstFile *f) {
 		}
 		}
 
 
 		f->curr_token_index++;
 		f->curr_token_index++;
-		f->curr_token = f->tokens[f->curr_token_index];
+		f->curr_token = f->tokens.e[f->curr_token_index];
 		if (f->curr_token.kind == Token_Comment) {
 		if (f->curr_token.kind == Token_Comment) {
 			return next_token(f);
 			return next_token(f);
 		}
 		}
@@ -1518,8 +1518,8 @@ AstNode *parse_atom_expr(AstFile *f, b32 lhs) {
 				// TODO(bill): Handle this
 				// TODO(bill): Handle this
 			}
 			}
 			AstNode *proc = parse_identifier(f);
 			AstNode *proc = parse_identifier(f);
-			Array<AstNode *> args;
-			array_init(&args, gb_arena_allocator(&f->arena), 1);
+			AstNodeArray args;
+			array_init_reserve(&args, gb_arena_allocator(&f->arena), 1);
 			array_add(&args, operand);
 			array_add(&args, operand);
 			operand = make_call_expr(f, proc, args, ast_node_token(operand), op, empty_token);
 			operand = make_call_expr(f, proc, args, ast_node_token(operand), op, empty_token);
 		} break;
 		} break;
@@ -1719,8 +1719,8 @@ AstNode *parse_binary_expr(AstFile *f, b32 lhs, i32 prec_in) {
 					expression = call;
 					expression = call;
 				} else  */{
 				} else  */{
 					right = parse_binary_expr(f, false, prec+1);
 					right = parse_binary_expr(f, false, prec+1);
-					Array<AstNode *> args = {};
-					array_init(&args, gb_arena_allocator(&f->arena), 2);
+					AstNodeArray args = {};
+					array_init_reserve(&args, gb_arena_allocator(&f->arena), 2);
 					array_add(&args, expression);
 					array_add(&args, expression);
 					array_add(&args, right);
 					array_add(&args, right);
 					expression = make_call_expr(f, proc, args, op, ast_node_token(right), empty_token);
 					expression = make_call_expr(f, proc, args, op, ast_node_token(right), empty_token);
@@ -1831,12 +1831,12 @@ AstNode *parse_simple_stmt(AstFile *f) {
 			syntax_error(f->curr_token, "You cannot use a simple statement in the file scope");
 			syntax_error(f->curr_token, "You cannot use a simple statement in the file scope");
 			return make_bad_stmt(f, f->curr_token, f->curr_token);
 			return make_bad_stmt(f, f->curr_token, f->curr_token);
 		}
 		}
-		statement = make_inc_dec_stmt(f, token, lhs[0]);
+		statement = make_inc_dec_stmt(f, token, lhs.e[0]);
 		next_token(f);
 		next_token(f);
 		return statement;
 		return statement;
 	}
 	}
 
 
-	return make_expr_stmt(f, lhs[0]);
+	return make_expr_stmt(f, lhs.e[0]);
 }
 }
 
 
 
 
@@ -1858,7 +1858,7 @@ AstNode *convert_stmt_to_expr(AstFile *f, AstNode *statement, String kind) {
 		return statement->ExprStmt.expr;
 		return statement->ExprStmt.expr;
 
 
 	syntax_error(f->curr_token, "Expected `%.*s`, found a simple statement.", LIT(kind));
 	syntax_error(f->curr_token, "Expected `%.*s`, found a simple statement.", LIT(kind));
-	return make_bad_expr(f, f->curr_token, f->tokens[f->curr_token_index+1]);
+	return make_bad_expr(f, f->curr_token, f->tokens.e[f->curr_token_index+1]);
 }
 }
 
 
 AstNodeArray parse_identfier_list(AstFile *f) {
 AstNodeArray parse_identfier_list(AstFile *f) {
@@ -1998,11 +1998,11 @@ AstNodeArray parse_struct_params(AstFile *f, isize *decl_count_, b32 using_allow
 
 
 			if (decl->kind == AstNode_ProcDecl) {
 			if (decl->kind == AstNode_ProcDecl) {
 				syntax_error(f->curr_token, "Procedure declarations are not allowed within a structure");
 				syntax_error(f->curr_token, "Procedure declarations are not allowed within a structure");
-				decl = make_bad_decl(f, ast_node_token(names[0]), f->curr_token);
+				decl = make_bad_decl(f, ast_node_token(names.e[0]), f->curr_token);
 			}
 			}
 		} else {
 		} else {
 			syntax_error(f->curr_token, "Illegal structure field");
 			syntax_error(f->curr_token, "Illegal structure field");
-			decl = make_bad_decl(f, ast_node_token(names[0]), f->curr_token);
+			decl = make_bad_decl(f, ast_node_token(names.e[0]), f->curr_token);
 		}
 		}
 
 
 		expect_semicolon_after_stmt(f, decl);
 		expect_semicolon_after_stmt(f, decl);
@@ -2280,7 +2280,7 @@ AstNode *parse_decl(AstFile *f, AstNodeArray names) {
 	AstNode *type = NULL;
 	AstNode *type = NULL;
 
 
 	for_array(i, names) {
 	for_array(i, names) {
-		AstNode *name = names[i];
+		AstNode *name = names.e[i];
 		if (name->kind == AstNode_Ident) {
 		if (name->kind == AstNode_Ident) {
 			String n = name->Ident.string;
 			String n = name->Ident.string;
 			// NOTE(bill): Check for reserved identifiers
 			// NOTE(bill): Check for reserved identifiers
@@ -2318,8 +2318,8 @@ AstNode *parse_decl(AstFile *f, AstNodeArray names) {
 				next_token(f);
 				next_token(f);
 			}
 			}
 			if (names.count != 1) {
 			if (names.count != 1) {
-				syntax_error(ast_node_token(names[0]), "You can only declare one type at a time");
-				return make_bad_decl(f, names[0]->Ident, token);
+				syntax_error(ast_node_token(names.e[0]), "You can only declare one type at a time");
+				return make_bad_decl(f, names.e[0]->Ident, token);
 			}
 			}
 
 
 			if (type != NULL) {
 			if (type != NULL) {
@@ -2327,12 +2327,12 @@ AstNode *parse_decl(AstFile *f, AstNodeArray names) {
 				// NOTE(bill): Do not fail though
 				// NOTE(bill): Do not fail though
 			}
 			}
 
 
-			return make_type_decl(f, token, names[0], parse_type(f));
+			return make_type_decl(f, token, names.e[0], parse_type(f));
 		} else if (f->curr_token.kind == Token_proc &&
 		} else if (f->curr_token.kind == Token_proc &&
 		    is_mutable == false) {
 		    is_mutable == false) {
 		    // NOTE(bill): Procedure declarations
 		    // NOTE(bill): Procedure declarations
 			Token proc_token = f->curr_token;
 			Token proc_token = f->curr_token;
-			AstNode *name = names[0];
+			AstNode *name = names.e[0];
 			if (names.count != 1) {
 			if (names.count != 1) {
 				syntax_error(proc_token, "You can only declare one procedure at a time");
 				syntax_error(proc_token, "You can only declare one procedure at a time");
 				return make_bad_decl(f, name->Ident, proc_token);
 				return make_bad_decl(f, name->Ident, proc_token);
@@ -2364,7 +2364,7 @@ AstNode *parse_decl(AstFile *f, AstNodeArray names) {
 		}
 		}
 	}
 	}
 
 
-	if (values.data == NULL) {
+	if (values.e == NULL) {
 		values = make_ast_node_array(f);
 		values = make_ast_node_array(f);
 	}
 	}
 
 
@@ -2421,7 +2421,7 @@ AstNode *parse_if_stmt(AstFile *f) {
 			break;
 			break;
 		default:
 		default:
 			syntax_error(f->curr_token, "Expected if statement block statement");
 			syntax_error(f->curr_token, "Expected if statement block statement");
-			else_stmt = make_bad_stmt(f, f->curr_token, f->tokens[f->curr_token_index+1]);
+			else_stmt = make_bad_stmt(f, f->curr_token, f->tokens.e[f->curr_token_index+1]);
 			break;
 			break;
 		}
 		}
 	}
 	}
@@ -2443,7 +2443,7 @@ AstNode *parse_return_stmt(AstFile *f) {
 		results = parse_rhs_expr_list(f);
 		results = parse_rhs_expr_list(f);
 	}
 	}
 	if (f->curr_token.kind != Token_CloseBrace) {
 	if (f->curr_token.kind != Token_CloseBrace) {
-		expect_semicolon_after_stmt(f, results[0]);
+		expect_semicolon_after_stmt(f, results.e[0]);
 	}
 	}
 
 
 	return make_return_stmt(f, token, results);
 	return make_return_stmt(f, token, results);
@@ -2891,8 +2891,8 @@ ParseFileError init_ast_file(AstFile *f, String fullpath) {
 		}
 		}
 
 
 		f->curr_token_index = 0;
 		f->curr_token_index = 0;
-		f->prev_token = f->tokens[f->curr_token_index];
-		f->curr_token = f->tokens[f->curr_token_index];
+		f->prev_token = f->tokens.e[f->curr_token_index];
+		f->curr_token = f->tokens.e[f->curr_token_index];
 
 
 		// NOTE(bill): Is this big enough or too small?
 		// NOTE(bill): Is this big enough or too small?
 		isize arena_size = gb_size_of(AstNode);
 		isize arena_size = gb_size_of(AstNode);
@@ -2934,7 +2934,7 @@ b32 init_parser(Parser *p) {
 void destroy_parser(Parser *p) {
 void destroy_parser(Parser *p) {
 	// TODO(bill): Fix memory leak
 	// TODO(bill): Fix memory leak
 	for_array(i, p->files) {
 	for_array(i, p->files) {
-		destroy_ast_file(&p->files[i]);
+		destroy_ast_file(&p->files.e[i]);
 	}
 	}
 #if 1
 #if 1
 	for_array(i, p->imports) {
 	for_array(i, p->imports) {
@@ -2952,7 +2952,7 @@ b32 try_add_import_path(Parser *p, String path, String rel_path, TokenPos pos) {
 	gb_mutex_lock(&p->mutex);
 	gb_mutex_lock(&p->mutex);
 
 
 	for_array(i, p->imports) {
 	for_array(i, p->imports) {
-		String import = p->imports[i].path;
+		String import = p->imports.e[i].path;
 		if (str_eq(import, path)) {
 		if (str_eq(import, path)) {
 			return false;
 			return false;
 		}
 		}
@@ -3009,7 +3009,7 @@ b32 try_add_foreign_library_path(Parser *p, String import_file) {
 	gb_mutex_lock(&p->mutex);
 	gb_mutex_lock(&p->mutex);
 
 
 	for_array(i, p->foreign_libraries) {
 	for_array(i, p->foreign_libraries) {
-		String import = p->foreign_libraries[i];
+		String import = p->foreign_libraries.e[i];
 		if (str_eq(import, import_file)) {
 		if (str_eq(import, import_file)) {
 			return false;
 			return false;
 		}
 		}
@@ -3096,7 +3096,7 @@ void parse_file(Parser *p, AstFile *f) {
 	f->decls = parse_stmt_list(f);
 	f->decls = parse_stmt_list(f);
 
 
 	for_array(i, f->decls) {
 	for_array(i, f->decls) {
-		AstNode *node = f->decls[i];
+		AstNode *node = f->decls.e[i];
 		if (!is_ast_node_decl(node) &&
 		if (!is_ast_node_decl(node) &&
 		    node->kind != AstNode_BadStmt &&
 		    node->kind != AstNode_BadStmt &&
 		    node->kind != AstNode_EmptyStmt) {
 		    node->kind != AstNode_EmptyStmt) {
@@ -3114,7 +3114,7 @@ void parse_file(Parser *p, AstFile *f) {
 						syntax_error(ast_node_token(node), "Invalid #import path: `%.*s`", LIT(file_str));
 						syntax_error(ast_node_token(node), "Invalid #import path: `%.*s`", LIT(file_str));
 					}
 					}
 					// NOTE(bill): It's a naughty name
 					// NOTE(bill): It's a naughty name
-					f->decls[i] = make_bad_decl(f, id->token, id->token);
+					f->decls.e[i] = make_bad_decl(f, id->token, id->token);
 					continue;
 					continue;
 				}
 				}
 
 
@@ -3143,7 +3143,7 @@ void parse_file(Parser *p, AstFile *f) {
 						syntax_error(ast_node_token(node), "Invalid `foreign_library` path");
 						syntax_error(ast_node_token(node), "Invalid `foreign_library` path");
 					}
 					}
 					// NOTE(bill): It's a naughty name
 					// NOTE(bill): It's a naughty name
-					f->decls[i] = make_bad_decl(f, id->token, id->token);
+					f->decls.e[i] = make_bad_decl(f, id->token, id->token);
 					continue;
 					continue;
 				}
 				}
 
 
@@ -3189,7 +3189,7 @@ ParseFileError parse_files(Parser *p, char *init_filename) {
 	}
 	}
 
 
 	for_array(i, p->imports) {
 	for_array(i, p->imports) {
-		ImportedFile imported_file = p->imports[i];
+		ImportedFile imported_file = p->imports.e[i];
 		String import_path = imported_file.path;
 		String import_path = imported_file.path;
 		String import_rel_path = imported_file.rel_path;
 		String import_rel_path = imported_file.rel_path;
 		TokenPos pos = imported_file.pos;
 		TokenPos pos = imported_file.pos;
@@ -3235,7 +3235,7 @@ ParseFileError parse_files(Parser *p, char *init_filename) {
 	}
 	}
 
 
 	for_array(i, p->files) {
 	for_array(i, p->files) {
-		p->total_token_count += p->files[i].tokens.count;
+		p->total_token_count += p->files.e[i].tokens.count;
 	}
 	}
 
 
 
 

+ 128 - 126
src/ssa.cpp

@@ -1,7 +1,9 @@
-struct ssaProcedure;
-struct ssaBlock;
-struct ssaValue;
-struct ssaDebugInfo;
+typedef struct ssaProcedure ssaProcedure;
+typedef struct ssaBlock ssaBlock;
+typedef struct ssaValue ssaValue;
+typedef struct ssaDebugInfo ssaDebugInfo;
+
+typedef Array(ssaValue *) ssaValueArray;
 
 
 struct ssaModule {
 struct ssaModule {
 	CheckerInfo * info;
 	CheckerInfo * info;
@@ -27,14 +29,14 @@ struct ssaModule {
 	i32                   global_string_index;
 	i32                   global_string_index;
 	i32                   global_array_index; // For ConstantSlice
 	i32                   global_array_index; // For ConstantSlice
 
 
-	Array<ssaProcedure *> procs;             // NOTE(bill): All procedures with bodies
-	Array<ssaValue *>     procs_to_generate; // NOTE(bill): Procedures to generate
+	Array(ssaProcedure *) procs;             // NOTE(bill): All procedures with bodies
+	ssaValueArray         procs_to_generate; // NOTE(bill): Procedures to generate
 };
 };
 
 
 // NOTE(bill): For more info, see https://en.wikipedia.org/wiki/Dominator_(graph_theory)
 // NOTE(bill): For more info, see https://en.wikipedia.org/wiki/Dominator_(graph_theory)
 struct ssaDomNode {
 struct ssaDomNode {
 	ssaBlock *        idom; // Parent (Immediate Dominator)
 	ssaBlock *        idom; // Parent (Immediate Dominator)
-	Array<ssaBlock *> children;
+	Array(ssaBlock *) children;
 	i32               pre, post; // Ordering in tree
 	i32               pre, post; // Ordering in tree
 };
 };
 
 
@@ -49,11 +51,11 @@ struct ssaBlock {
 	ssaDomNode    dom;
 	ssaDomNode    dom;
 	i32           gaps;
 	i32           gaps;
 
 
-	Array<ssaValue *> instrs;
-	Array<ssaValue *> locals;
+	ssaValueArray instrs;
+	ssaValueArray locals;
 
 
-	Array<ssaBlock *> preds;
-	Array<ssaBlock *> succs;
+	Array(ssaBlock *) preds;
+	Array(ssaBlock *) succs;
 };
 };
 
 
 struct ssaTargetList {
 struct ssaTargetList {
@@ -86,7 +88,7 @@ struct ssaDefer {
 
 
 struct ssaProcedure {
 struct ssaProcedure {
 	ssaProcedure *        parent;
 	ssaProcedure *        parent;
-	Array<ssaProcedure *> children;
+	Array(ssaProcedure *) children;
 
 
 	Entity *              entity;
 	Entity *              entity;
 	ssaModule *           module;
 	ssaModule *           module;
@@ -96,15 +98,15 @@ struct ssaProcedure {
 	AstNode *             body;
 	AstNode *             body;
 	u64                   tags;
 	u64                   tags;
 
 
-	Array<ssaValue *>     params;
-	Array<ssaDefer>       defer_stmts;
-	Array<ssaBlock *>     blocks;
+	ssaValueArray     params;
+	Array(ssaDefer)       defer_stmts;
+	Array(ssaBlock *)     blocks;
 	i32                   scope_index;
 	i32                   scope_index;
 	ssaBlock *            decl_block;
 	ssaBlock *            decl_block;
 	ssaBlock *            entry_block;
 	ssaBlock *            entry_block;
 	ssaBlock *            curr_block;
 	ssaBlock *            curr_block;
 	ssaTargetList *       target_list;
 	ssaTargetList *       target_list;
-	Array<ssaValue *>     referrers;
+	ssaValueArray     referrers;
 
 
 	i32                   local_count;
 	i32                   local_count;
 	i32                   instr_count;
 	i32                   instr_count;
@@ -198,7 +200,7 @@ struct ssaInstr {
 			Entity *          entity;
 			Entity *          entity;
 			Type *            type;
 			Type *            type;
 			b32               zero_initialized;
 			b32               zero_initialized;
-			Array<ssaValue *> referrers;
+			ssaValueArray referrers;
 		} Local;
 		} Local;
 		struct {
 		struct {
 			ssaValue *address;
 			ssaValue *address;
@@ -271,7 +273,7 @@ struct ssaInstr {
 			ssaValue *false_value;
 			ssaValue *false_value;
 		} Select;
 		} Select;
 		struct {
 		struct {
-			Array<ssaValue *> edges;
+			ssaValueArray edges;
 			Type *type;
 			Type *type;
 		} Phi;
 		} Phi;
 		struct {
 		struct {
@@ -359,7 +361,7 @@ struct ssaValue {
 			Entity *          entity;
 			Entity *          entity;
 			Type *            type;
 			Type *            type;
 			ssaValue *        value;
 			ssaValue *        value;
-			Array<ssaValue *> referrers;
+			ssaValueArray referrers;
 			b8                is_constant;
 			b8                is_constant;
 			b8                is_private;
 			b8                is_private;
 			b8                is_thread_local;
 			b8                is_thread_local;
@@ -369,7 +371,7 @@ struct ssaValue {
 			ssaProcedure *    parent;
 			ssaProcedure *    parent;
 			Entity *          entity;
 			Entity *          entity;
 			Type *            type;
 			Type *            type;
-			Array<ssaValue *> referrers;
+			ssaValueArray referrers;
 		} Param;
 		} Param;
 		ssaProcedure Proc;
 		ssaProcedure Proc;
 		ssaBlock     Block;
 		ssaBlock     Block;
@@ -483,7 +485,7 @@ struct ssaDebugInfo {
 			TokenPos      pos;
 			TokenPos      pos;
 		} Proc;
 		} Proc;
 		struct {
 		struct {
-			Array<ssaDebugInfo *> procs;
+			Array(ssaDebugInfo *) procs;
 		} AllProcs;
 		} AllProcs;
 
 
 
 
@@ -495,7 +497,7 @@ struct ssaDebugInfo {
 		} BasicType;
 		} BasicType;
 		struct {
 		struct {
 			ssaDebugInfo *        return_type;
 			ssaDebugInfo *        return_type;
-			Array<ssaDebugInfo *> param_types;
+			Array(ssaDebugInfo *) param_types;
 		} ProcType;
 		} ProcType;
 		struct {
 		struct {
 			ssaDebugInfo *   base_type;
 			ssaDebugInfo *   base_type;
@@ -509,7 +511,7 @@ struct ssaDebugInfo {
 			TokenPos              pos;
 			TokenPos              pos;
 			i32                   size;
 			i32                   size;
 			i32                   align;
 			i32                   align;
-			Array<ssaDebugInfo *> elements;
+			Array(ssaDebugInfo *) elements;
 		} CompositeType;
 		} CompositeType;
 		struct {
 		struct {
 			String name;
 			String name;
@@ -649,7 +651,7 @@ ssaInstr *ssa_get_last_instr(ssaBlock *block) {
 	if (block != NULL) {
 	if (block != NULL) {
 		isize len = block->instrs.count;
 		isize len = block->instrs.count;
 		if (len > 0) {
 		if (len > 0) {
-			ssaValue *v = block->instrs[len-1];
+			ssaValue *v = block->instrs.e[len-1];
 			GB_ASSERT(v->kind == ssaValue_Instr);
 			GB_ASSERT(v->kind == ssaValue_Instr);
 			return &v->Instr;
 			return &v->Instr;
 		}
 		}
@@ -682,7 +684,7 @@ void ssa_set_instr_parent(ssaValue *instr, ssaBlock *parent) {
 	}
 	}
 }
 }
 
 
-Array<ssaValue *> *ssa_value_referrers(ssaValue *v) {
+ssaValueArray *ssa_value_referrers(ssaValue *v) {
 	switch (v->kind) {
 	switch (v->kind) {
 	case ssaValue_Global:
 	case ssaValue_Global:
 		return &v->Global.referrers;
 		return &v->Global.referrers;
@@ -927,7 +929,7 @@ ssaValue *ssa_make_instr_if(ssaProcedure *p, ssaValue *cond, ssaBlock *true_bloc
 }
 }
 
 
 
 
-ssaValue *ssa_make_instr_phi(ssaProcedure *p, Array<ssaValue *> edges, Type *type) {
+ssaValue *ssa_make_instr_phi(ssaProcedure *p, ssaValueArray edges, Type *type) {
 	ssaValue *v = ssa_alloc_instr(p, ssaInstr_Phi);
 	ssaValue *v = ssa_alloc_instr(p, ssaInstr_Phi);
 	ssaInstr *i = &v->Instr;
 	ssaInstr *i = &v->Instr;
 	i->Phi.edges = edges;
 	i->Phi.edges = edges;
@@ -1064,11 +1066,11 @@ ssaValue *ssa_make_value_procedure(gbAllocator a, ssaModule *m, Entity *entity,
 	v->Proc.type_expr = type_expr;
 	v->Proc.type_expr = type_expr;
 	v->Proc.body   = body;
 	v->Proc.body   = body;
 	v->Proc.name   = name;
 	v->Proc.name   = name;
-	array_init(&v->Proc.referrers, heap_allocator(), 0); // TODO(bill): replace heap allocator
+	array_init(&v->Proc.referrers, heap_allocator()); // TODO(bill): replace heap allocator
 
 
 	Type *t = base_type(type);
 	Type *t = base_type(type);
 	GB_ASSERT(is_type_proc(t));
 	GB_ASSERT(is_type_proc(t));
-	array_init(&v->Proc.params, heap_allocator(), t->Proc.param_count);
+	array_init_reserve(&v->Proc.params, heap_allocator(), t->Proc.param_count);
 
 
 	return v;
 	return v;
 }
 }
@@ -1359,7 +1361,7 @@ void ssa_emit_defer_stmts(ssaProcedure *proc, ssaDeferExitKind kind, ssaBlock *b
 	isize count = proc->defer_stmts.count;
 	isize count = proc->defer_stmts.count;
 	isize i = count;
 	isize i = count;
 	while (i --> 0) {
 	while (i --> 0) {
-		ssaDefer d = proc->defer_stmts[i];
+		ssaDefer d = proc->defer_stmts.e[i];
 		if (kind == ssaDeferExit_Default) {
 		if (kind == ssaDeferExit_Default) {
 			if (proc->scope_index == d.scope_index &&
 			if (proc->scope_index == d.scope_index &&
 			    d.scope_index > 1) {
 			    d.scope_index > 1) {
@@ -1686,7 +1688,7 @@ ssaValue *ssa_emit_deep_field_gep(ssaProcedure *proc, Type *type, ssaValue *e, S
 	GB_ASSERT(sel.index.count > 0);
 	GB_ASSERT(sel.index.count > 0);
 
 
 	for_array(i, sel.index) {
 	for_array(i, sel.index) {
-		i32 index = cast(i32)sel.index[i];
+		i32 index = cast(i32)sel.index.e[i];
 		if (is_type_pointer(type)) {
 		if (is_type_pointer(type)) {
 			type = type_deref(type);
 			type = type_deref(type);
 			e = ssa_emit_load(proc, e);
 			e = ssa_emit_load(proc, e);
@@ -1739,7 +1741,7 @@ ssaValue *ssa_emit_deep_field_ev(ssaProcedure *proc, Type *type, ssaValue *e, Se
 	GB_ASSERT(sel.index.count > 0);
 	GB_ASSERT(sel.index.count > 0);
 
 
 	for_array(i, sel.index) {
 	for_array(i, sel.index) {
-		isize index = sel.index[i];
+		i32 index = cast(i32)sel.index.e[i];
 		if (is_type_pointer(type)) {
 		if (is_type_pointer(type)) {
 			type = type_deref(type);
 			type = type_deref(type);
 			e = ssa_emit_load(proc, e);
 			e = ssa_emit_load(proc, e);
@@ -2336,7 +2338,7 @@ isize ssa_type_info_index(CheckerInfo *info, Type *type) {
 		// NOTE(bill): Do manual search
 		// NOTE(bill): Do manual search
 		// TODO(bill): This is O(n) and can be very slow
 		// TODO(bill): This is O(n) and can be very slow
 		for_array(i, info->type_info_map.entries){
 		for_array(i, info->type_info_map.entries){
-			auto *e = &info->type_info_map.entries[i];
+			auto *e = &info->type_info_map.entries.e[i];
 			Type *prev_type = cast(Type *)e->key.ptr;
 			Type *prev_type = cast(Type *)e->key.ptr;
 			if (are_types_identical(prev_type, type)) {
 			if (are_types_identical(prev_type, type)) {
 				entry_index = e->value;
 				entry_index = e->value;
@@ -2417,8 +2419,8 @@ ssaValue *ssa_emit_logical_binary_expr(ssaProcedure *proc, AstNode *expr) {
 		return ssa_build_expr(proc, be->right);
 		return ssa_build_expr(proc, be->right);
 	}
 	}
 
 
-	Array<ssaValue *> edges = {};
-	array_init(&edges, proc->module->allocator, done->preds.count+1);
+	ssaValueArray edges = {};
+	array_init_reserve(&edges, proc->module->allocator, done->preds.count+1);
 	for_array(i, done->preds) {
 	for_array(i, done->preds) {
 		array_add(&edges, short_circuit);
 		array_add(&edges, short_circuit);
 	}
 	}
@@ -2754,11 +2756,11 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue
 				Entity *e = *found;
 				Entity *e = *found;
 				switch (e->Builtin.id) {
 				switch (e->Builtin.id) {
 				case BuiltinProc_type_info: {
 				case BuiltinProc_type_info: {
-					Type *t = default_type(type_of_expr(proc->module->info, ce->args[0]));
+					Type *t = default_type(type_of_expr(proc->module->info, ce->args.e[0]));
 					return ssa_type_info(proc, t);
 					return ssa_type_info(proc, t);
 				} break;
 				} break;
 				case BuiltinProc_type_info_of_val: {
 				case BuiltinProc_type_info_of_val: {
-					Type *t = default_type(type_of_expr(proc->module->info, ce->args[0]));
+					Type *t = default_type(type_of_expr(proc->module->info, ce->args.e[0]));
 					return ssa_type_info(proc, t);
 					return ssa_type_info(proc, t);
 				} break;
 				} break;
 
 
@@ -2767,7 +2769,7 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue
 					// new :: proc(Type) -> ^Type
 					// new :: proc(Type) -> ^Type
 					gbAllocator allocator = proc->module->allocator;
 					gbAllocator allocator = proc->module->allocator;
 
 
-					Type *type = type_of_expr(proc->module->info, ce->args[0]);
+					Type *type = type_of_expr(proc->module->info, ce->args.e[0]);
 					Type *ptr_type = make_type_pointer(allocator, type);
 					Type *ptr_type = make_type_pointer(allocator, type);
 
 
 					i64 s = type_size_of(proc->module->sizes, allocator, type);
 					i64 s = type_size_of(proc->module->sizes, allocator, type);
@@ -2786,7 +2788,7 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue
 					// new_slice :: proc(Type, len: int[, cap: int]) -> ^Type
 					// new_slice :: proc(Type, len: int[, cap: int]) -> ^Type
 					gbAllocator allocator = proc->module->allocator;
 					gbAllocator allocator = proc->module->allocator;
 
 
-					Type *type = type_of_expr(proc->module->info, ce->args[0]);
+					Type *type = type_of_expr(proc->module->info, ce->args.e[0]);
 					Type *ptr_type = make_type_pointer(allocator, type);
 					Type *ptr_type = make_type_pointer(allocator, type);
 					Type *slice_type = make_type_slice(allocator, type);
 					Type *slice_type = make_type_slice(allocator, type);
 
 
@@ -2796,13 +2798,13 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue
 					ssaValue *elem_size  = ssa_make_const_int(allocator, s);
 					ssaValue *elem_size  = ssa_make_const_int(allocator, s);
 					ssaValue *elem_align = ssa_make_const_int(allocator, a);
 					ssaValue *elem_align = ssa_make_const_int(allocator, a);
 
 
-					ssaValue *len = ssa_emit_conv(proc, ssa_build_expr(proc, ce->args[1]), t_int);
+					ssaValue *len = ssa_emit_conv(proc, ssa_build_expr(proc, ce->args.e[1]), t_int);
 					ssaValue *cap = len;
 					ssaValue *cap = len;
 					if (ce->args.count == 3) {
 					if (ce->args.count == 3) {
-						cap = ssa_emit_conv(proc, ssa_build_expr(proc, ce->args[2]), t_int);
+						cap = ssa_emit_conv(proc, ssa_build_expr(proc, ce->args.e[2]), t_int);
 					}
 					}
 
 
-					ssa_emit_slice_bounds_check(proc, ast_node_token(ce->args[1]), v_zero, len, cap, false);
+					ssa_emit_slice_bounds_check(proc, ast_node_token(ce->args.e[1]), v_zero, len, cap, false);
 
 
 					ssaValue *slice_size = ssa_emit_arith(proc, Token_Mul, elem_size, cap, t_int);
 					ssaValue *slice_size = ssa_emit_arith(proc, Token_Mul, elem_size, cap, t_int);
 
 
@@ -2825,7 +2827,7 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue
 
 
 				case BuiltinProc_assert: {
 				case BuiltinProc_assert: {
 					ssa_emit_comment(proc, str_lit("assert"));
 					ssa_emit_comment(proc, str_lit("assert"));
-					ssaValue *cond = ssa_build_expr(proc, ce->args[0]);
+					ssaValue *cond = ssa_build_expr(proc, ce->args.e[0]);
 					GB_ASSERT(is_type_boolean(ssa_type(cond)));
 					GB_ASSERT(is_type_boolean(ssa_type(cond)));
 
 
 					cond = ssa_emit_comp(proc, Token_CmpEq, cond, v_false);
 					cond = ssa_emit_comp(proc, Token_CmpEq, cond, v_false);
@@ -2836,9 +2838,9 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue
 					proc->curr_block = err;
 					proc->curr_block = err;
 
 
 					// TODO(bill): Cleanup allocations here
 					// TODO(bill): Cleanup allocations here
-					Token token = ast_node_token(ce->args[0]);
+					Token token = ast_node_token(ce->args.e[0]);
 					TokenPos pos = token.pos;
 					TokenPos pos = token.pos;
-					gbString expr = expr_to_string(ce->args[0]);
+					gbString expr = expr_to_string(ce->args.e[0]);
 					isize expr_len = gb_string_length(expr);
 					isize expr_len = gb_string_length(expr);
 					String expr_str = {};
 					String expr_str = {};
 					expr_str.text = cast(u8 *)gb_alloc_copy_align(proc->module->allocator, expr, expr_len, 1);
 					expr_str.text = cast(u8 *)gb_alloc_copy_align(proc->module->allocator, expr, expr_len, 1);
@@ -2861,10 +2863,10 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue
 
 
 				case BuiltinProc_panic: {
 				case BuiltinProc_panic: {
 					ssa_emit_comment(proc, str_lit("panic"));
 					ssa_emit_comment(proc, str_lit("panic"));
-					ssaValue *msg = ssa_build_expr(proc, ce->args[0]);
+					ssaValue *msg = ssa_build_expr(proc, ce->args.e[0]);
 					GB_ASSERT(is_type_string(ssa_type(msg)));
 					GB_ASSERT(is_type_string(ssa_type(msg)));
 
 
-					Token token = ast_node_token(ce->args[0]);
+					Token token = ast_node_token(ce->args.e[0]);
 					TokenPos pos = token.pos;
 					TokenPos pos = token.pos;
 
 
 					ssaValue **args = gb_alloc_array(proc->module->allocator, ssaValue *, 4);
 					ssaValue **args = gb_alloc_array(proc->module->allocator, ssaValue *, 4);
@@ -2881,8 +2883,8 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue
 				case BuiltinProc_copy: {
 				case BuiltinProc_copy: {
 					ssa_emit_comment(proc, str_lit("copy"));
 					ssa_emit_comment(proc, str_lit("copy"));
 					// copy :: proc(dst, src: []Type) -> int
 					// copy :: proc(dst, src: []Type) -> int
-					AstNode *dst_node = ce->args[0];
-					AstNode *src_node = ce->args[1];
+					AstNode *dst_node = ce->args.e[0];
+					AstNode *src_node = ce->args.e[1];
 					ssaValue *dst_slice = ssa_build_expr(proc, dst_node);
 					ssaValue *dst_slice = ssa_build_expr(proc, dst_node);
 					ssaValue *src_slice = ssa_build_expr(proc, src_node);
 					ssaValue *src_slice = ssa_build_expr(proc, src_node);
 					Type *slice_type = base_type(ssa_type(dst_slice));
 					Type *slice_type = base_type(ssa_type(dst_slice));
@@ -2915,8 +2917,8 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue
 				case BuiltinProc_append: {
 				case BuiltinProc_append: {
 					ssa_emit_comment(proc, str_lit("append"));
 					ssa_emit_comment(proc, str_lit("append"));
 					// append :: proc(s: ^[]Type, item: Type) -> bool
 					// append :: proc(s: ^[]Type, item: Type) -> bool
-					AstNode *sptr_node = ce->args[0];
-					AstNode *item_node = ce->args[1];
+					AstNode *sptr_node = ce->args.e[0];
+					AstNode *item_node = ce->args.e[1];
 					ssaValue *slice_ptr = ssa_build_expr(proc, sptr_node);
 					ssaValue *slice_ptr = ssa_build_expr(proc, sptr_node);
 					ssaValue *slice = ssa_emit_load(proc, slice_ptr);
 					ssaValue *slice = ssa_emit_load(proc, slice_ptr);
 
 
@@ -2971,7 +2973,7 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue
 
 
 				case BuiltinProc_swizzle: {
 				case BuiltinProc_swizzle: {
 					ssa_emit_comment(proc, str_lit("swizzle"));
 					ssa_emit_comment(proc, str_lit("swizzle"));
-					ssaValue *vector = ssa_build_expr(proc, ce->args[0]);
+					ssaValue *vector = ssa_build_expr(proc, ce->args.e[0]);
 					isize index_count = ce->args.count-1;
 					isize index_count = ce->args.count-1;
 					if (index_count == 0) {
 					if (index_count == 0) {
 						return vector;
 						return vector;
@@ -2981,7 +2983,7 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue
 					isize index = 0;
 					isize index = 0;
 					for_array(i, ce->args) {
 					for_array(i, ce->args) {
 						if (i == 0) continue;
 						if (i == 0) continue;
-						TypeAndValue *tv = type_and_value_of_expression(proc->module->info, ce->args[i]);
+						TypeAndValue *tv = type_and_value_of_expression(proc->module->info, ce->args.e[i]);
 						GB_ASSERT(is_type_integer(tv->type));
 						GB_ASSERT(is_type_integer(tv->type));
 						GB_ASSERT(tv->value.kind == ExactValue_Integer);
 						GB_ASSERT(tv->value.kind == ExactValue_Integer);
 						indices[index++] = cast(i32)tv->value.value_integer;
 						indices[index++] = cast(i32)tv->value.value_integer;
@@ -2994,15 +2996,15 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue
 #if 0
 #if 0
 				case BuiltinProc_ptr_offset: {
 				case BuiltinProc_ptr_offset: {
 					ssa_emit_comment(proc, str_lit("ptr_offset"));
 					ssa_emit_comment(proc, str_lit("ptr_offset"));
-					ssaValue *ptr = ssa_build_expr(proc, ce->args[0]);
-					ssaValue *offset = ssa_build_expr(proc, ce->args[1]);
+					ssaValue *ptr = ssa_build_expr(proc, ce->args.e[0]);
+					ssaValue *offset = ssa_build_expr(proc, ce->args.e[1]);
 					return ssa_emit_ptr_offset(proc, ptr, offset);
 					return ssa_emit_ptr_offset(proc, ptr, offset);
 				} break;
 				} break;
 
 
 				case BuiltinProc_ptr_sub: {
 				case BuiltinProc_ptr_sub: {
 					ssa_emit_comment(proc, str_lit("ptr_sub"));
 					ssa_emit_comment(proc, str_lit("ptr_sub"));
-					ssaValue *ptr_a = ssa_build_expr(proc, ce->args[0]);
-					ssaValue *ptr_b = ssa_build_expr(proc, ce->args[1]);
+					ssaValue *ptr_a = ssa_build_expr(proc, ce->args.e[0]);
+					ssaValue *ptr_b = ssa_build_expr(proc, ce->args.e[1]);
 					Type *ptr_type = base_type(ssa_type(ptr_a));
 					Type *ptr_type = base_type(ssa_type(ptr_a));
 					GB_ASSERT(ptr_type->kind == Type_Pointer);
 					GB_ASSERT(ptr_type->kind == Type_Pointer);
 					isize elem_size = type_size_of(proc->module->sizes, proc->module->allocator, ptr_type->Pointer.elem);
 					isize elem_size = type_size_of(proc->module->sizes, proc->module->allocator, ptr_type->Pointer.elem);
@@ -3019,14 +3021,14 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue
 
 
 				case BuiltinProc_slice_ptr: {
 				case BuiltinProc_slice_ptr: {
 					ssa_emit_comment(proc, str_lit("slice_ptr"));
 					ssa_emit_comment(proc, str_lit("slice_ptr"));
-					ssaValue *ptr = ssa_build_expr(proc, ce->args[0]);
-					ssaValue *len = ssa_build_expr(proc, ce->args[1]);
+					ssaValue *ptr = ssa_build_expr(proc, ce->args.e[0]);
+					ssaValue *len = ssa_build_expr(proc, ce->args.e[1]);
 					ssaValue *cap = len;
 					ssaValue *cap = len;
 
 
 					len = ssa_emit_conv(proc, len, t_int);
 					len = ssa_emit_conv(proc, len, t_int);
 
 
 					if (ce->args.count == 3) {
 					if (ce->args.count == 3) {
-						cap = ssa_build_expr(proc, ce->args[2]);
+						cap = ssa_build_expr(proc, ce->args.e[2]);
 						cap = ssa_emit_conv(proc, cap, t_int);
 						cap = ssa_emit_conv(proc, cap, t_int);
 					}
 					}
 
 
@@ -3041,8 +3043,8 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue
 
 
 				case BuiltinProc_min: {
 				case BuiltinProc_min: {
 					ssa_emit_comment(proc, str_lit("min"));
 					ssa_emit_comment(proc, str_lit("min"));
-					ssaValue *x = ssa_build_expr(proc, ce->args[0]);
-					ssaValue *y = ssa_build_expr(proc, ce->args[1]);
+					ssaValue *x = ssa_build_expr(proc, ce->args.e[0]);
+					ssaValue *y = ssa_build_expr(proc, ce->args.e[1]);
 					Type *t = base_type(ssa_type(x));
 					Type *t = base_type(ssa_type(x));
 					ssaValue *cond = ssa_emit_comp(proc, Token_Lt, x, y);
 					ssaValue *cond = ssa_emit_comp(proc, Token_Lt, x, y);
 					return ssa_emit_select(proc, cond, x, y);
 					return ssa_emit_select(proc, cond, x, y);
@@ -3050,8 +3052,8 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue
 
 
 				case BuiltinProc_max: {
 				case BuiltinProc_max: {
 					ssa_emit_comment(proc, str_lit("max"));
 					ssa_emit_comment(proc, str_lit("max"));
-					ssaValue *x = ssa_build_expr(proc, ce->args[0]);
-					ssaValue *y = ssa_build_expr(proc, ce->args[1]);
+					ssaValue *x = ssa_build_expr(proc, ce->args.e[0]);
+					ssaValue *y = ssa_build_expr(proc, ce->args.e[1]);
 					Type *t = base_type(ssa_type(x));
 					Type *t = base_type(ssa_type(x));
 					ssaValue *cond = ssa_emit_comp(proc, Token_Gt, x, y);
 					ssaValue *cond = ssa_emit_comp(proc, Token_Gt, x, y);
 					return ssa_emit_select(proc, cond, x, y);
 					return ssa_emit_select(proc, cond, x, y);
@@ -3061,7 +3063,7 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue
 					ssa_emit_comment(proc, str_lit("abs"));
 					ssa_emit_comment(proc, str_lit("abs"));
 					gbAllocator a = proc->module->allocator;
 					gbAllocator a = proc->module->allocator;
 
 
-					ssaValue *x = ssa_build_expr(proc, ce->args[0]);
+					ssaValue *x = ssa_build_expr(proc, ce->args.e[0]);
 					Type *original_type = ssa_type(x);
 					Type *original_type = ssa_type(x);
 					Type *t = original_type;
 					Type *t = original_type;
 					i64 sz = type_size_of(proc->module->sizes, a, t);
 					i64 sz = type_size_of(proc->module->sizes, a, t);
@@ -3100,7 +3102,7 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue
 
 
 				case BuiltinProc_enum_to_string: {
 				case BuiltinProc_enum_to_string: {
 					ssa_emit_comment(proc, str_lit("enum_to_string"));
 					ssa_emit_comment(proc, str_lit("enum_to_string"));
-					ssaValue *x = ssa_build_expr(proc, ce->args[0]);
+					ssaValue *x = ssa_build_expr(proc, ce->args.e[0]);
 					Type *t = ssa_type(x);
 					Type *t = ssa_type(x);
 					ssaValue *ti = ssa_type_info(proc, t);
 					ssaValue *ti = ssa_type_info(proc, t);
 
 
@@ -3125,7 +3127,7 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue
 
 
 		isize arg_count = 0;
 		isize arg_count = 0;
 		for_array(i, ce->args) {
 		for_array(i, ce->args) {
-			AstNode *a = ce->args[i];
+			AstNode *a = ce->args.e[i];
 			Type *at = base_type(type_of_expr(proc->module->info, a));
 			Type *at = base_type(type_of_expr(proc->module->info, a));
 			if (at->kind == Type_Tuple) {
 			if (at->kind == Type_Tuple) {
 				arg_count += at->Tuple.variable_count;
 				arg_count += at->Tuple.variable_count;
@@ -3138,7 +3140,7 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue
 		b32 vari_expand = ce->ellipsis.pos.line != 0;
 		b32 vari_expand = ce->ellipsis.pos.line != 0;
 
 
 		for_array(i, ce->args) {
 		for_array(i, ce->args) {
-			ssaValue *a = ssa_build_expr(proc, ce->args[i]);
+			ssaValue *a = ssa_build_expr(proc, ce->args.e[i]);
 			Type *at = ssa_type(a);
 			Type *at = ssa_type(a);
 			if (at->kind == Type_Tuple) {
 			if (at->kind == Type_Tuple) {
 				for (isize i = 0; i < at->Tuple.variable_count; i++) {
 				for (isize i = 0; i < at->Tuple.variable_count; i++) {
@@ -3614,7 +3616,7 @@ ssaAddr ssa_build_addr(ssaProcedure *proc, AstNode *expr) {
 		case Type_Vector: {
 		case Type_Vector: {
 			ssaValue *result = ssa_add_module_constant(proc->module, type, make_exact_value_compound(expr));
 			ssaValue *result = ssa_add_module_constant(proc->module, type, make_exact_value_compound(expr));
 			for_array(index, cl->elems) {
 			for_array(index, cl->elems) {
-				AstNode *elem = cl->elems[index];
+				AstNode *elem = cl->elems.e[index];
 				if (is_elem_const(proc->module, elem, et)) {
 				if (is_elem_const(proc->module, elem, et)) {
 					continue;
 					continue;
 				}
 				}
@@ -3645,7 +3647,7 @@ ssaAddr ssa_build_addr(ssaProcedure *proc, AstNode *expr) {
 			if (cl->elems.count > 0) {
 			if (cl->elems.count > 0) {
 				ssa_emit_store(proc, v, ssa_add_module_constant(proc->module, type, make_exact_value_compound(expr)));
 				ssa_emit_store(proc, v, ssa_add_module_constant(proc->module, type, make_exact_value_compound(expr)));
 				for_array(field_index, cl->elems) {
 				for_array(field_index, cl->elems) {
-					AstNode *elem = cl->elems[field_index];
+					AstNode *elem = cl->elems.e[field_index];
 
 
 					ssaValue *field_expr = NULL;
 					ssaValue *field_expr = NULL;
 					Entity *field = NULL;
 					Entity *field = NULL;
@@ -3654,12 +3656,12 @@ ssaAddr ssa_build_addr(ssaProcedure *proc, AstNode *expr) {
 					if (elem->kind == AstNode_FieldValue) {
 					if (elem->kind == AstNode_FieldValue) {
 						ast_node(fv, FieldValue, elem);
 						ast_node(fv, FieldValue, elem);
 						Selection sel = lookup_field(proc->module->allocator, bt, fv->field->Ident.string, false);
 						Selection sel = lookup_field(proc->module->allocator, bt, fv->field->Ident.string, false);
-						index = sel.index[0];
+						index = sel.index.e[0];
 						elem = fv->value;
 						elem = fv->value;
 					} else {
 					} else {
 						TypeAndValue *tav = type_and_value_of_expression(proc->module->info, elem);
 						TypeAndValue *tav = type_and_value_of_expression(proc->module->info, elem);
 						Selection sel = lookup_field(proc->module->allocator, bt, st->fields_in_src_order[field_index]->token.string, false);
 						Selection sel = lookup_field(proc->module->allocator, bt, st->fields_in_src_order[field_index]->token.string, false);
-						index = sel.index[0];
+						index = sel.index.e[0];
 					}
 					}
 
 
 					field = st->fields[index];
 					field = st->fields[index];
@@ -3682,7 +3684,7 @@ ssaAddr ssa_build_addr(ssaProcedure *proc, AstNode *expr) {
 			if (cl->elems.count > 0) {
 			if (cl->elems.count > 0) {
 				ssa_emit_store(proc, v, ssa_add_module_constant(proc->module, type, make_exact_value_compound(expr)));
 				ssa_emit_store(proc, v, ssa_add_module_constant(proc->module, type, make_exact_value_compound(expr)));
 				for_array(i, cl->elems) {
 				for_array(i, cl->elems) {
-					AstNode *elem = cl->elems[i];
+					AstNode *elem = cl->elems.e[i];
 					if (is_elem_const(proc->module, elem, et)) {
 					if (is_elem_const(proc->module, elem, et)) {
 						continue;
 						continue;
 					}
 					}
@@ -3706,7 +3708,7 @@ ssaAddr ssa_build_addr(ssaProcedure *proc, AstNode *expr) {
 				ssaValue *data = ssa_emit_array_ep(proc, slice->ConstantSlice.backing_array, v_zero32);
 				ssaValue *data = ssa_emit_array_ep(proc, slice->ConstantSlice.backing_array, v_zero32);
 
 
 				for_array(i, cl->elems) {
 				for_array(i, cl->elems) {
-					AstNode *elem = cl->elems[i];
+					AstNode *elem = cl->elems.e[i];
 					if (is_elem_const(proc->module, elem, et)) {
 					if (is_elem_const(proc->module, elem, et)) {
 						continue;
 						continue;
 					}
 					}
@@ -3802,7 +3804,7 @@ void ssa_build_cond(ssaProcedure *proc, AstNode *cond, ssaBlock *true_block, ssa
 
 
 void ssa_build_stmt_list(ssaProcedure *proc, AstNodeArray stmts) {
 void ssa_build_stmt_list(ssaProcedure *proc, AstNodeArray stmts) {
 	for_array(i, stmts) {
 	for_array(i, stmts) {
-		ssa_build_stmt(proc, stmts[i]);
+		ssa_build_stmt(proc, stmts.e[i]);
 	}
 	}
 }
 }
 
 
@@ -3848,19 +3850,19 @@ void ssa_build_stmt_internal(ssaProcedure *proc, AstNode *node) {
 
 
 		if (vd->values.count == 0) { // declared and zero-initialized
 		if (vd->values.count == 0) { // declared and zero-initialized
 			for_array(i, vd->names) {
 			for_array(i, vd->names) {
-				AstNode *name = vd->names[i];
+				AstNode *name = vd->names.e[i];
 				if (!ssa_is_blank_ident(name)) {
 				if (!ssa_is_blank_ident(name)) {
 					ssa_add_local_for_identifier(proc, name, true);
 					ssa_add_local_for_identifier(proc, name, true);
 				}
 				}
 			}
 			}
 		} else { // Tuple(s)
 		} else { // Tuple(s)
-			Array<ssaAddr>  lvals;
-			Array<ssaValue *> inits;
-			array_init(&lvals, m->tmp_allocator, vd->names.count);
-			array_init(&inits, m->tmp_allocator, vd->names.count);
+			Array(ssaAddr) lvals;
+			ssaValueArray  inits;
+			array_init_reserve(&lvals, m->tmp_allocator, vd->names.count);
+			array_init_reserve(&inits, m->tmp_allocator, vd->names.count);
 
 
 			for_array(i, vd->names) {
 			for_array(i, vd->names) {
-				AstNode *name = vd->names[i];
+				AstNode *name = vd->names.e[i];
 				ssaAddr lval = ssa_make_addr(NULL, NULL);
 				ssaAddr lval = ssa_make_addr(NULL, NULL);
 				if (!ssa_is_blank_ident(name)) {
 				if (!ssa_is_blank_ident(name)) {
 					ssa_add_local_for_identifier(proc, name, false);
 					ssa_add_local_for_identifier(proc, name, false);
@@ -3871,7 +3873,7 @@ void ssa_build_stmt_internal(ssaProcedure *proc, AstNode *node) {
 			}
 			}
 
 
 			for_array(i, vd->values) {
 			for_array(i, vd->values) {
-				ssaValue *init = ssa_build_expr(proc, vd->values[i]);
+				ssaValue *init = ssa_build_expr(proc, vd->values.e[i]);
 				Type *t = ssa_type(init);
 				Type *t = ssa_type(init);
 				if (t->kind == Type_Tuple) {
 				if (t->kind == Type_Tuple) {
 					for (isize i = 0; i < t->Tuple.variable_count; i++) {
 					for (isize i = 0; i < t->Tuple.variable_count; i++) {
@@ -3886,11 +3888,11 @@ void ssa_build_stmt_internal(ssaProcedure *proc, AstNode *node) {
 
 
 
 
 			for_array(i, inits) {
 			for_array(i, inits) {
-				if (lvals[i].addr == NULL) {
+				if (lvals.e[i].addr == NULL) {
 					continue;
 					continue;
 				}
 				}
-				ssaValue *v = ssa_emit_conv(proc, inits[i], ssa_addr_type(lvals[i]));
-				ssa_addr_store(proc, lvals[i], v);
+				ssaValue *v = ssa_emit_conv(proc, inits.e[i], ssa_addr_type(lvals.e[i]));
+				ssa_addr_store(proc, lvals.e[i], v);
 			}
 			}
 		}
 		}
 
 
@@ -4012,11 +4014,11 @@ void ssa_build_stmt_internal(ssaProcedure *proc, AstNode *node) {
 
 
 		switch (as->op.kind) {
 		switch (as->op.kind) {
 		case Token_Eq: {
 		case Token_Eq: {
-			Array<ssaAddr> lvals;
+			Array(ssaAddr) lvals;
 			array_init(&lvals, m->tmp_allocator);
 			array_init(&lvals, m->tmp_allocator);
 
 
 			for_array(i, as->lhs) {
 			for_array(i, as->lhs) {
-				AstNode *lhs = as->lhs[i];
+				AstNode *lhs = as->lhs.e[i];
 				ssaAddr lval = {};
 				ssaAddr lval = {};
 				if (!ssa_is_blank_ident(lhs)) {
 				if (!ssa_is_blank_ident(lhs)) {
 					lval = ssa_build_addr(proc, lhs);
 					lval = ssa_build_addr(proc, lhs);
@@ -4026,28 +4028,28 @@ void ssa_build_stmt_internal(ssaProcedure *proc, AstNode *node) {
 
 
 			if (as->lhs.count == as->rhs.count) {
 			if (as->lhs.count == as->rhs.count) {
 				if (as->lhs.count == 1) {
 				if (as->lhs.count == 1) {
-					AstNode *rhs = as->rhs[0];
+					AstNode *rhs = as->rhs.e[0];
 					ssaValue *init = ssa_build_expr(proc, rhs);
 					ssaValue *init = ssa_build_expr(proc, rhs);
-					ssa_addr_store(proc, lvals[0], init);
+					ssa_addr_store(proc, lvals.e[0], init);
 				} else {
 				} else {
-					Array<ssaValue *> inits;
-					array_init(&inits, m->tmp_allocator, lvals.count);
+					ssaValueArray inits;
+					array_init_reserve(&inits, m->tmp_allocator, lvals.count);
 
 
 					for_array(i, as->rhs) {
 					for_array(i, as->rhs) {
-						ssaValue *init = ssa_build_expr(proc, as->rhs[i]);
+						ssaValue *init = ssa_build_expr(proc, as->rhs.e[i]);
 						array_add(&inits, init);
 						array_add(&inits, init);
 					}
 					}
 
 
 					for_array(i, inits) {
 					for_array(i, inits) {
-						ssa_addr_store(proc, lvals[i], inits[i]);
+						ssa_addr_store(proc, lvals.e[i], inits.e[i]);
 					}
 					}
 				}
 				}
 			} else {
 			} else {
-				Array<ssaValue *> inits;
-				array_init(&inits, m->tmp_allocator, lvals.count);
+				ssaValueArray inits;
+				array_init_reserve(&inits, m->tmp_allocator, lvals.count);
 
 
 				for_array(i, as->rhs) {
 				for_array(i, as->rhs) {
-					ssaValue *init = ssa_build_expr(proc, as->rhs[i]);
+					ssaValue *init = ssa_build_expr(proc, as->rhs.e[i]);
 					Type *t = ssa_type(init);
 					Type *t = ssa_type(init);
 					// TODO(bill): refactor for code reuse as this is repeated a bit
 					// TODO(bill): refactor for code reuse as this is repeated a bit
 					if (t->kind == Type_Tuple) {
 					if (t->kind == Type_Tuple) {
@@ -4062,7 +4064,7 @@ void ssa_build_stmt_internal(ssaProcedure *proc, AstNode *node) {
 				}
 				}
 
 
 				for_array(i, inits) {
 				for_array(i, inits) {
-					ssa_addr_store(proc, lvals[i], inits[i]);
+					ssa_addr_store(proc, lvals.e[i], inits.e[i]);
 				}
 				}
 			}
 			}
 
 
@@ -4073,8 +4075,8 @@ void ssa_build_stmt_internal(ssaProcedure *proc, AstNode *node) {
 			// +=, -=, etc
 			// +=, -=, etc
 			i32 op = cast(i32)as->op.kind;
 			i32 op = cast(i32)as->op.kind;
 			op += Token_Add - Token_AddEq; // Convert += to +
 			op += Token_Add - Token_AddEq; // Convert += to +
-			ssaAddr lhs = ssa_build_addr(proc, as->lhs[0]);
-			ssaValue *value = ssa_build_expr(proc, as->rhs[0]);
+			ssaAddr lhs = ssa_build_addr(proc, as->lhs.e[0]);
+			ssaValue *value = ssa_build_expr(proc, as->rhs.e[0]);
 			ssa_build_assign_op(proc, lhs, value, cast(TokenKind)op);
 			ssa_build_assign_op(proc, lhs, value, cast(TokenKind)op);
 		} break;
 		} break;
 		}
 		}
@@ -4111,15 +4113,15 @@ void ssa_build_stmt_internal(ssaProcedure *proc, AstNode *node) {
 			// No return values
 			// No return values
 		} else if (return_count == 1) {
 		} else if (return_count == 1) {
 			Entity *e = return_type_tuple->variables[0];
 			Entity *e = return_type_tuple->variables[0];
-			v = ssa_emit_conv(proc, ssa_build_expr(proc, rs->results[0]), e->type);
+			v = ssa_emit_conv(proc, ssa_build_expr(proc, rs->results.e[0]), e->type);
 		} else {
 		} else {
 			gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&proc->module->tmp_arena);
 			gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&proc->module->tmp_arena);
 
 
-			Array<ssaValue *> results;
-			array_init(&results, proc->module->tmp_allocator, return_count);
+			ssaValueArray results;
+			array_init_reserve(&results, proc->module->tmp_allocator, return_count);
 
 
 			for_array(res_index, rs->results) {
 			for_array(res_index, rs->results) {
-				ssaValue *res = ssa_build_expr(proc, rs->results[res_index]);
+				ssaValue *res = ssa_build_expr(proc, rs->results.e[res_index]);
 				Type *t = ssa_type(res);
 				Type *t = ssa_type(res);
 				if (t->kind == Type_Tuple) {
 				if (t->kind == Type_Tuple) {
 					for (isize i = 0; i < t->Tuple.variable_count; i++) {
 					for (isize i = 0; i < t->Tuple.variable_count; i++) {
@@ -4136,7 +4138,7 @@ void ssa_build_stmt_internal(ssaProcedure *proc, AstNode *node) {
 			v = ssa_add_local_generated(proc, ret_type);
 			v = ssa_add_local_generated(proc, ret_type);
 			for_array(i, results) {
 			for_array(i, results) {
 				Entity *e = return_type_tuple->variables[i];
 				Entity *e = return_type_tuple->variables[i];
-				ssaValue *res = ssa_emit_conv(proc, results[i], e->type);
+				ssaValue *res = ssa_emit_conv(proc, results.e[i], e->type);
 				ssaValue *field = ssa_emit_struct_ep(proc, v, i);
 				ssaValue *field = ssa_emit_struct_ep(proc, v, i);
 				ssa_emit_store(proc, field, res);
 				ssa_emit_store(proc, field, res);
 			}
 			}
@@ -4255,7 +4257,7 @@ void ssa_build_stmt_internal(ssaProcedure *proc, AstNode *node) {
 
 
 		isize case_count = body->stmts.count;
 		isize case_count = body->stmts.count;
 		for_array(i, body->stmts) {
 		for_array(i, body->stmts) {
-			AstNode *clause = body->stmts[i];
+			AstNode *clause = body->stmts.e[i];
 			ssaBlock *body = fall;
 			ssaBlock *body = fall;
 
 
 			ast_node(cc, CaseClause, clause);
 			ast_node(cc, CaseClause, clause);
@@ -4287,7 +4289,7 @@ void ssa_build_stmt_internal(ssaProcedure *proc, AstNode *node) {
 
 
 			ssaBlock *next_cond = NULL;
 			ssaBlock *next_cond = NULL;
 			for_array(j, cc->list) {
 			for_array(j, cc->list) {
-				AstNode *expr = cc->list[j];
+				AstNode *expr = cc->list.e[j];
 				next_cond = ssa_add_block(proc, clause, "match.case.next");
 				next_cond = ssa_add_block(proc, clause, "match.case.next");
 
 
 				ssaValue *cond = ssa_emit_comp(proc, Token_CmpEq, tag, ssa_build_expr(proc, expr));
 				ssaValue *cond = ssa_emit_comp(proc, Token_CmpEq, tag, ssa_build_expr(proc, expr));
@@ -4355,7 +4357,7 @@ void ssa_build_stmt_internal(ssaProcedure *proc, AstNode *node) {
 
 
 		isize case_count = body->stmts.count;
 		isize case_count = body->stmts.count;
 		for_array(i, body->stmts) {
 		for_array(i, body->stmts) {
-			AstNode *clause = body->stmts[i];
+			AstNode *clause = body->stmts.e[i];
 			ast_node(cc, CaseClause, clause);
 			ast_node(cc, CaseClause, clause);
 
 
 			if (cc->list.count == 0) {
 			if (cc->list.count == 0) {
@@ -4526,10 +4528,10 @@ void ssa_build_stmt_internal(ssaProcedure *proc, AstNode *node) {
 void ssa_number_proc_registers(ssaProcedure *proc) {
 void ssa_number_proc_registers(ssaProcedure *proc) {
 	i32 reg_index = 0;
 	i32 reg_index = 0;
 	for_array(i, proc->blocks) {
 	for_array(i, proc->blocks) {
-		ssaBlock *b = proc->blocks[i];
+		ssaBlock *b = proc->blocks.e[i];
 		b->index = i;
 		b->index = i;
 		for_array(j, b->instrs) {
 		for_array(j, b->instrs) {
-			ssaValue *value = b->instrs[j];
+			ssaValue *value = b->instrs.e[j];
 			GB_ASSERT(value->kind == ssaValue_Instr);
 			GB_ASSERT(value->kind == ssaValue_Instr);
 			ssaInstr *instr = &value->Instr;
 			ssaInstr *instr = &value->Instr;
 			if (ssa_instr_type(instr) == NULL) { // NOTE(bill): Ignore non-returning instructions
 			if (ssa_instr_type(instr) == NULL) { // NOTE(bill): Ignore non-returning instructions
@@ -4697,7 +4699,7 @@ void ssa_init_module(ssaModule *m, Checker *c) {
 			isize count = 0;
 			isize count = 0;
 
 
 			for_array(entry_index, m->info->type_info_map.entries) {
 			for_array(entry_index, m->info->type_info_map.entries) {
-				auto *entry = &m->info->type_info_map.entries[entry_index];
+				auto *entry = &m->info->type_info_map.entries.e[entry_index];
 				Type *t = cast(Type *)cast(uintptr)entry->key.key;
 				Type *t = cast(Type *)cast(uintptr)entry->key.key;
 
 
 				switch (t->kind) {
 				switch (t->kind) {
@@ -4725,7 +4727,7 @@ void ssa_init_module(ssaModule *m, Checker *c) {
 
 
 	{
 	{
 		ssaDebugInfo *di = ssa_alloc_debug_info(m->allocator, ssaDebugInfo_CompileUnit);
 		ssaDebugInfo *di = ssa_alloc_debug_info(m->allocator, ssaDebugInfo_CompileUnit);
-		di->CompileUnit.file = m->info->files.entries[0].value; // Zeroth is the init file
+		di->CompileUnit.file = m->info->files.entries.e[0].value; // Zeroth is the init file
 		di->CompileUnit.producer = str_lit("odin");
 		di->CompileUnit.producer = str_lit("odin");
 
 
 		map_set(&m->debug_info, hash_pointer(m), di);
 		map_set(&m->debug_info, hash_pointer(m), di);
@@ -4832,7 +4834,7 @@ void ssa_gen_tree(ssaGen *s) {
 	Entity *entry_point = NULL;
 	Entity *entry_point = NULL;
 
 
 	for_array(i, info->entities.entries) {
 	for_array(i, info->entities.entries) {
-		auto *entry = &info->entities.entries[i];
+		auto *entry = &info->entities.entries.e[i];
 		Entity *e = cast(Entity *)cast(uintptr)entry->key.key;
 		Entity *e = cast(Entity *)cast(uintptr)entry->key.key;
 		String name = e->token.string;
 		String name = e->token.string;
 		if (e->kind == Entity_Variable) {
 		if (e->kind == Entity_Variable) {
@@ -4844,17 +4846,17 @@ void ssa_gen_tree(ssaGen *s) {
 		}
 		}
 	}
 	}
 
 
-	struct ssaGlobalVariable {
+	typedef struct ssaGlobalVariable {
 		ssaValue *var, *init;
 		ssaValue *var, *init;
 		DeclInfo *decl;
 		DeclInfo *decl;
-	};
-	Array<ssaGlobalVariable> global_variables;
-	array_init(&global_variables, m->tmp_allocator, global_variable_max_count);
+	} ssaGlobalVariable;
+	Array(ssaGlobalVariable) global_variables;
+	array_init_reserve(&global_variables, m->tmp_allocator, global_variable_max_count);
 
 
 	m->min_dep_map = generate_minimum_dependency_map(info, entry_point);
 	m->min_dep_map = generate_minimum_dependency_map(info, entry_point);
 
 
 	for_array(i, info->entities.entries) {
 	for_array(i, info->entities.entries) {
-		auto *entry = &info->entities.entries[i];
+		auto *entry = &info->entities.entries.e[i];
 		Entity *e = cast(Entity *)entry->key.ptr;
 		Entity *e = cast(Entity *)entry->key.ptr;
 		String name = e->token.string;
 		String name = e->token.string;
 		DeclInfo *decl = entry->value;
 		DeclInfo *decl = entry->value;
@@ -4936,19 +4938,19 @@ void ssa_gen_tree(ssaGen *s) {
 	}
 	}
 
 
 	for_array(i, m->members.entries) {
 	for_array(i, m->members.entries) {
-		auto *entry = &m->members.entries[i];
+		auto *entry = &m->members.entries.e[i];
 		ssaValue *v = entry->value;
 		ssaValue *v = entry->value;
 		if (v->kind == ssaValue_Proc)
 		if (v->kind == ssaValue_Proc)
 			ssa_build_proc(v, NULL);
 			ssa_build_proc(v, NULL);
 	}
 	}
 
 
-	ssaDebugInfo *compile_unit = m->debug_info.entries[0].value;
+	ssaDebugInfo *compile_unit = m->debug_info.entries.e[0].value;
 	GB_ASSERT(compile_unit->kind == ssaDebugInfo_CompileUnit);
 	GB_ASSERT(compile_unit->kind == ssaDebugInfo_CompileUnit);
 	ssaDebugInfo *all_procs = ssa_alloc_debug_info(m->allocator, ssaDebugInfo_AllProcs);
 	ssaDebugInfo *all_procs = ssa_alloc_debug_info(m->allocator, ssaDebugInfo_AllProcs);
 
 
 	isize all_proc_max_count = 0;
 	isize all_proc_max_count = 0;
 	for_array(i, m->debug_info.entries) {
 	for_array(i, m->debug_info.entries) {
-		auto *entry = &m->debug_info.entries[i];
+		auto *entry = &m->debug_info.entries.e[i];
 		ssaDebugInfo *di = entry->value;
 		ssaDebugInfo *di = entry->value;
 		di->id = i;
 		di->id = i;
 		if (di->kind == ssaDebugInfo_Proc) {
 		if (di->kind == ssaDebugInfo_Proc) {
@@ -4956,13 +4958,13 @@ void ssa_gen_tree(ssaGen *s) {
 		}
 		}
 	}
 	}
 
 
-	array_init(&all_procs->AllProcs.procs, m->allocator, all_proc_max_count);
+	array_init_reserve(&all_procs->AllProcs.procs, m->allocator, all_proc_max_count);
 	map_set(&m->debug_info, hash_pointer(all_procs), all_procs); // NOTE(bill): This doesn't need to be mapped
 	map_set(&m->debug_info, hash_pointer(all_procs), all_procs); // NOTE(bill): This doesn't need to be mapped
 	compile_unit->CompileUnit.all_procs = all_procs;
 	compile_unit->CompileUnit.all_procs = all_procs;
 
 
 
 
 	for_array(i, m->debug_info.entries) {
 	for_array(i, m->debug_info.entries) {
-		auto *entry = &m->debug_info.entries[i];
+		auto *entry = &m->debug_info.entries.e[i];
 		ssaDebugInfo *di = entry->value;
 		ssaDebugInfo *di = entry->value;
 		di->id = i;
 		di->id = i;
 		if (di->kind == ssaDebugInfo_Proc) {
 		if (di->kind == ssaDebugInfo_Proc) {
@@ -4993,7 +4995,7 @@ void ssa_gen_tree(ssaGen *s) {
 
 
 		// TODO(bill): Should do a dependency graph do check which order to initialize them in?
 		// TODO(bill): Should do a dependency graph do check which order to initialize them in?
 		for_array(i, global_variables) {
 		for_array(i, global_variables) {
-			ssaGlobalVariable *var = &global_variables[i];
+			ssaGlobalVariable *var = &global_variables.e[i];
 			if (var->decl->init_expr != NULL) {
 			if (var->decl->init_expr != NULL) {
 				var->init = ssa_build_expr(proc, var->decl->init_expr);
 				var->init = ssa_build_expr(proc, var->decl->init_expr);
 			}
 			}
@@ -5001,7 +5003,7 @@ void ssa_gen_tree(ssaGen *s) {
 
 
 		// NOTE(bill): Initialize constants first
 		// NOTE(bill): Initialize constants first
 		for_array(i, global_variables) {
 		for_array(i, global_variables) {
-			ssaGlobalVariable *var = &global_variables[i];
+			ssaGlobalVariable *var = &global_variables.e[i];
 			if (var->init != NULL) {
 			if (var->init != NULL) {
 				if (var->init->kind == ssaValue_Constant) {
 				if (var->init->kind == ssaValue_Constant) {
 					ssa_emit_store(proc, var->var, var->init);
 					ssa_emit_store(proc, var->var, var->init);
@@ -5010,7 +5012,7 @@ void ssa_gen_tree(ssaGen *s) {
 		}
 		}
 
 
 		for_array(i, global_variables) {
 		for_array(i, global_variables) {
-			ssaGlobalVariable *var = &global_variables[i];
+			ssaGlobalVariable *var = &global_variables.e[i];
 			if (var->init != NULL) {
 			if (var->init != NULL) {
 				if (var->init->kind != ssaValue_Constant) {
 				if (var->init->kind != ssaValue_Constant) {
 					ssa_emit_store(proc, var->var, var->init);
 					ssa_emit_store(proc, var->var, var->init);
@@ -5055,7 +5057,7 @@ void ssa_gen_tree(ssaGen *s) {
 
 
 
 
 			for_array(type_info_map_index, info->type_info_map.entries) {
 			for_array(type_info_map_index, info->type_info_map.entries) {
-				auto *entry = &info->type_info_map.entries[type_info_map_index];
+				auto *entry = &info->type_info_map.entries.e[type_info_map_index];
 				Type *t = cast(Type *)cast(uintptr)entry->key.key;
 				Type *t = cast(Type *)cast(uintptr)entry->key.key;
 				t = default_type(t);
 				t = default_type(t);
 				isize entry_index = entry->value;
 				isize entry_index = entry->value;
@@ -5418,7 +5420,7 @@ void ssa_gen_tree(ssaGen *s) {
 	}
 	}
 
 
 	for_array(i, m->procs_to_generate) {
 	for_array(i, m->procs_to_generate) {
-		ssa_build_proc(m->procs_to_generate[i], m->procs_to_generate[i]->Proc.parent);
+		ssa_build_proc(m->procs_to_generate.e[i], m->procs_to_generate.e[i]->Proc.parent);
 	}
 	}
 
 
 	// {
 	// {

+ 41 - 41
src/ssa_opt.cpp

@@ -1,6 +1,6 @@
 // Optimizations for the SSA code
 // Optimizations for the SSA code
 
 
-void ssa_opt_add_operands(Array<ssaValue *> *ops, ssaInstr *i) {
+void ssa_opt_add_operands(ssaValueArray *ops, ssaInstr *i) {
 	switch (i->kind) {
 	switch (i->kind) {
 	case ssaInstr_Comment:
 	case ssaInstr_Comment:
 		break;
 		break;
@@ -51,7 +51,7 @@ void ssa_opt_add_operands(Array<ssaValue *> *ops, ssaInstr *i) {
 		break;
 		break;
 	case ssaInstr_Phi:
 	case ssaInstr_Phi:
 		for_array(j, i->Phi.edges) {
 		for_array(j, i->Phi.edges) {
-			array_add(ops, i->Phi.edges[j]);
+			array_add(ops, i->Phi.edges.e[j]);
 		}
 		}
 		break;
 		break;
 	case ssaInstr_Unreachable: break;
 	case ssaInstr_Unreachable: break;
@@ -99,24 +99,24 @@ void ssa_opt_add_operands(Array<ssaValue *> *ops, ssaInstr *i) {
 
 
 void ssa_opt_block_replace_pred(ssaBlock *b, ssaBlock *from, ssaBlock *to) {
 void ssa_opt_block_replace_pred(ssaBlock *b, ssaBlock *from, ssaBlock *to) {
 	for_array(i, b->preds) {
 	for_array(i, b->preds) {
-		ssaBlock *pred = b->preds[i];
+		ssaBlock *pred = b->preds.e[i];
 		if (pred == from) {
 		if (pred == from) {
-			b->preds[i] = to;
+			b->preds.e[i] = to;
 		}
 		}
 	}
 	}
 }
 }
 
 
 void ssa_opt_block_replace_succ(ssaBlock *b, ssaBlock *from, ssaBlock *to) {
 void ssa_opt_block_replace_succ(ssaBlock *b, ssaBlock *from, ssaBlock *to) {
 	for_array(i, b->succs) {
 	for_array(i, b->succs) {
-		ssaBlock *succ = b->succs[i];
+		ssaBlock *succ = b->succs.e[i];
 		if (succ == from) {
 		if (succ == from) {
-			b->succs[i] = to;
+			b->succs.e[i] = to;
 		}
 		}
 	}
 	}
 }
 }
 
 
 b32 ssa_opt_block_has_phi(ssaBlock *b) {
 b32 ssa_opt_block_has_phi(ssaBlock *b) {
-	return b->instrs[0]->Instr.kind == ssaInstr_Phi;
+	return b->instrs.e[0]->Instr.kind == ssaInstr_Phi;
 }
 }
 
 
 
 
@@ -128,10 +128,10 @@ b32 ssa_opt_block_has_phi(ssaBlock *b) {
 
 
 
 
 
 
-Array<ssaValue *> ssa_get_block_phi_nodes(ssaBlock *b) {
-	Array<ssaValue *> phis = {};
+ssaValueArray ssa_get_block_phi_nodes(ssaBlock *b) {
+	ssaValueArray phis = {};
 	for_array(i, b->instrs) {
 	for_array(i, b->instrs) {
-		ssaInstr *instr = &b->instrs[i]->Instr;
+		ssaInstr *instr = &b->instrs.e[i]->Instr;
 		if (instr->kind != ssaInstr_Phi) {
 		if (instr->kind != ssaInstr_Phi) {
 			phis = b->instrs;
 			phis = b->instrs;
 			phis.count = i;
 			phis.count = i;
@@ -145,19 +145,19 @@ void ssa_remove_pred(ssaBlock *b, ssaBlock *p) {
 	auto phis = ssa_get_block_phi_nodes(b);
 	auto phis = ssa_get_block_phi_nodes(b);
 	isize i = 0;
 	isize i = 0;
 	for_array(j, b->preds) {
 	for_array(j, b->preds) {
-		ssaBlock *pred = b->preds[j];
+		ssaBlock *pred = b->preds.e[j];
 		if (pred != p) {
 		if (pred != p) {
-			b->preds[i] = b->preds[j];
+			b->preds.e[i] = b->preds.e[j];
 			for_array(k, phis) {
 			for_array(k, phis) {
-				auto *phi = &phis[k]->Instr.Phi;
-				phi->edges[i] = phi->edges[j];
+				auto *phi = &phis.e[k]->Instr.Phi;
+				phi->edges.e[i] = phi->edges.e[j];
 			}
 			}
 			i++;
 			i++;
 		}
 		}
 	}
 	}
 	b->preds.count = i;
 	b->preds.count = i;
 	for_array(k, phis) {
 	for_array(k, phis) {
-		auto *phi = &phis[k]->Instr.Phi;
+		auto *phi = &phis.e[k]->Instr.Phi;
 		phi->edges.count = i;
 		phi->edges.count = i;
 	}
 	}
 
 
@@ -166,13 +166,13 @@ void ssa_remove_pred(ssaBlock *b, ssaBlock *p) {
 void ssa_remove_dead_blocks(ssaProcedure *proc) {
 void ssa_remove_dead_blocks(ssaProcedure *proc) {
 	isize j = 0;
 	isize j = 0;
 	for_array(i, proc->blocks) {
 	for_array(i, proc->blocks) {
-		ssaBlock *b = proc->blocks[i];
+		ssaBlock *b = proc->blocks.e[i];
 		if (b == NULL) {
 		if (b == NULL) {
 			continue;
 			continue;
 		}
 		}
 		// NOTE(bill): Swap order
 		// NOTE(bill): Swap order
 		b->index = j;
 		b->index = j;
-		proc->blocks[j++] = b;
+		proc->blocks.e[j++] = b;
 	}
 	}
 	proc->blocks.count = j;
 	proc->blocks.count = j;
 }
 }
@@ -182,7 +182,7 @@ void ssa_mark_reachable(ssaBlock *b) {
 	isize const BLACK = -1;
 	isize const BLACK = -1;
 	b->index = BLACK;
 	b->index = BLACK;
 	for_array(i, b->succs) {
 	for_array(i, b->succs) {
-		ssaBlock *succ = b->succs[i];
+		ssaBlock *succ = b->succs.e[i];
 		if (succ->index == WHITE) {
 		if (succ->index == WHITE) {
 			ssa_mark_reachable(succ);
 			ssa_mark_reachable(succ);
 		}
 		}
@@ -193,23 +193,23 @@ void ssa_remove_unreachable_blocks(ssaProcedure *proc) {
 	isize const WHITE =  0;
 	isize const WHITE =  0;
 	isize const BLACK = -1;
 	isize const BLACK = -1;
 	for_array(i, proc->blocks) {
 	for_array(i, proc->blocks) {
-		proc->blocks[i]->index = WHITE;
+		proc->blocks.e[i]->index = WHITE;
 	}
 	}
 
 
-	ssa_mark_reachable(proc->blocks[0]);
+	ssa_mark_reachable(proc->blocks.e[0]);
 
 
 	for_array(i, proc->blocks) {
 	for_array(i, proc->blocks) {
-		ssaBlock *b = proc->blocks[i];
+		ssaBlock *b = proc->blocks.e[i];
 		if (b->index == WHITE) {
 		if (b->index == WHITE) {
 			for_array(j, b->succs) {
 			for_array(j, b->succs) {
-				ssaBlock *c = b->succs[j];
+				ssaBlock *c = b->succs.e[j];
 				if (c->index == BLACK) {
 				if (c->index == BLACK) {
 					ssa_remove_pred(c, b);
 					ssa_remove_pred(c, b);
 				}
 				}
 			}
 			}
 			// NOTE(bill): Mark as empty but don't actually free it
 			// NOTE(bill): Mark as empty but don't actually free it
 			// As it's been allocated with an arena
 			// As it's been allocated with an arena
-			proc->blocks[i] = NULL;
+			proc->blocks.e[i] = NULL;
 		}
 		}
 	}
 	}
 	ssa_remove_dead_blocks(proc);
 	ssa_remove_dead_blocks(proc);
@@ -219,7 +219,7 @@ b32 ssa_opt_block_fusion(ssaProcedure *proc, ssaBlock *a) {
 	if (a->succs.count != 1) {
 	if (a->succs.count != 1) {
 		return false;
 		return false;
 	}
 	}
-	ssaBlock *b = a->succs[0];
+	ssaBlock *b = a->succs.e[0];
 	if (b->preds.count != 1) {
 	if (b->preds.count != 1) {
 		return false;
 		return false;
 	}
 	}
@@ -230,21 +230,21 @@ b32 ssa_opt_block_fusion(ssaProcedure *proc, ssaBlock *a) {
 
 
 	array_pop(&a->instrs); // Remove branch at end
 	array_pop(&a->instrs); // Remove branch at end
 	for_array(i, b->instrs) {
 	for_array(i, b->instrs) {
-		array_add(&a->instrs, b->instrs[i]);
-		ssa_set_instr_parent(b->instrs[i], a);
+		array_add(&a->instrs, b->instrs.e[i]);
+		ssa_set_instr_parent(b->instrs.e[i], a);
 	}
 	}
 
 
 	array_clear(&a->succs);
 	array_clear(&a->succs);
 	for_array(i, b->succs) {
 	for_array(i, b->succs) {
-		array_add(&a->succs, b->succs[i]);
+		array_add(&a->succs, b->succs.e[i]);
 	}
 	}
 
 
 	// Fix preds links
 	// Fix preds links
 	for_array(i, b->succs) {
 	for_array(i, b->succs) {
-		ssa_opt_block_replace_pred(b->succs[i], b, a);
+		ssa_opt_block_replace_pred(b->succs.e[i], b, a);
 	}
 	}
 
 
-	proc->blocks[b->index] = NULL;
+	proc->blocks.e[b->index] = NULL;
 	return true;
 	return true;
 }
 }
 
 
@@ -256,7 +256,7 @@ void ssa_opt_blocks(ssaProcedure *proc) {
 	while (changed) {
 	while (changed) {
 		changed = false;
 		changed = false;
 		for_array(i, proc->blocks) {
 		for_array(i, proc->blocks) {
-			ssaBlock *b = proc->blocks[i];
+			ssaBlock *b = proc->blocks.e[i];
 			if (b == NULL) {
 			if (b == NULL) {
 				continue;
 				continue;
 			}
 			}
@@ -275,16 +275,16 @@ void ssa_opt_blocks(ssaProcedure *proc) {
 void ssa_opt_build_referrers(ssaProcedure *proc) {
 void ssa_opt_build_referrers(ssaProcedure *proc) {
 	gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&proc->module->tmp_arena);
 	gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&proc->module->tmp_arena);
 
 
-	Array<ssaValue *> ops = {}; // NOTE(bill): Act as a buffer
-	array_init(&ops, proc->module->tmp_allocator, 64); // HACK(bill): This _could_ overflow the temp arena
+	ssaValueArray ops = {}; // NOTE(bill): Act as a buffer
+	array_init_reserve(&ops, proc->module->tmp_allocator, 64); // HACK(bill): This _could_ overflow the temp arena
 	for_array(i, proc->blocks) {
 	for_array(i, proc->blocks) {
-		ssaBlock *b = proc->blocks[i];
+		ssaBlock *b = proc->blocks.e[i];
 		for_array(j, b->instrs) {
 		for_array(j, b->instrs) {
-			ssaValue *instr = b->instrs[j];
+			ssaValue *instr = b->instrs.e[j];
 			array_clear(&ops);
 			array_clear(&ops);
 			ssa_opt_add_operands(&ops, &instr->Instr);
 			ssa_opt_add_operands(&ops, &instr->Instr);
 			for_array(k, ops) {
 			for_array(k, ops) {
-				ssaValue *op = ops[k];
+				ssaValue *op = ops.e[k];
 				if (op == NULL) {
 				if (op == NULL) {
 					continue;
 					continue;
 				}
 				}
@@ -326,7 +326,7 @@ i32 ssa_lt_depth_first_search(ssaLTState *lt, ssaBlock *p, i32 i, ssaBlock **pre
 	lt->sdom[p->index] = p;
 	lt->sdom[p->index] = p;
 	ssa_lt_link(lt, NULL, p);
 	ssa_lt_link(lt, NULL, p);
 	for_array(index, p->succs) {
 	for_array(index, p->succs) {
-		ssaBlock *q = p->succs[index];
+		ssaBlock *q = p->succs.e[index];
 		if (lt->sdom[q->index] == NULL) {
 		if (lt->sdom[q->index] == NULL) {
 			lt->parent[q->index] = p;
 			lt->parent[q->index] = p;
 			i = ssa_lt_depth_first_search(lt, q, i, preorder);
 			i = ssa_lt_depth_first_search(lt, q, i, preorder);
@@ -356,7 +356,7 @@ ssaDomPrePost ssa_opt_number_dom_tree(ssaBlock *v, i32 pre, i32 post) {
 
 
 	v->dom.pre = pre++;
 	v->dom.pre = pre++;
 	for_array(i, v->dom.children) {
 	for_array(i, v->dom.children) {
-		result = ssa_opt_number_dom_tree(v->dom.children[i], result.pre, result.post);
+		result = ssa_opt_number_dom_tree(v->dom.children.e[i], result.pre, result.post);
 	}
 	}
 	v->dom.post = post++;
 	v->dom.post = post++;
 
 
@@ -383,7 +383,7 @@ void ssa_opt_build_dom_tree(ssaProcedure *proc) {
 
 
 	ssaBlock **preorder = &buf[3*n];
 	ssaBlock **preorder = &buf[3*n];
 	ssaBlock **buckets  = &buf[4*n];
 	ssaBlock **buckets  = &buf[4*n];
-	ssaBlock *root = proc->blocks[0];
+	ssaBlock *root = proc->blocks.e[0];
 
 
 	// Step 1 - number vertices
 	// Step 1 - number vertices
 	i32 pre_num = ssa_lt_depth_first_search(&lt, root, 0, preorder);
 	i32 pre_num = ssa_lt_depth_first_search(&lt, root, 0, preorder);
@@ -405,7 +405,7 @@ void ssa_opt_build_dom_tree(ssaProcedure *proc) {
 		// Step 2 - Compute all sdoms
 		// Step 2 - Compute all sdoms
 		lt.sdom[w->index] = lt.parent[w->index];
 		lt.sdom[w->index] = lt.parent[w->index];
 		for_array(pred_index, w->preds) {
 		for_array(pred_index, w->preds) {
-			ssaBlock *v = w->preds[pred_index];
+			ssaBlock *v = w->preds.e[pred_index];
 			ssaBlock *u = ssa_lt_eval(&lt, v);
 			ssaBlock *u = ssa_lt_eval(&lt, v);
 			if (lt.sdom[u->index]->dom.pre < lt.sdom[w->index]->dom.pre) {
 			if (lt.sdom[u->index]->dom.pre < lt.sdom[w->index]->dom.pre) {
 				lt.sdom[w->index] = lt.sdom[u->index];
 				lt.sdom[w->index] = lt.sdom[u->index];
@@ -441,7 +441,7 @@ void ssa_opt_build_dom_tree(ssaProcedure *proc) {
 
 
 			// Calculate children relation as inverse of idom
 			// Calculate children relation as inverse of idom
 			auto *children = &w->dom.idom->dom.children;
 			auto *children = &w->dom.idom->dom.children;
-			if (children->data == NULL) {
+			if (children->e == NULL) {
 				// TODO(bill): Is this good enough for memory allocations?
 				// TODO(bill): Is this good enough for memory allocations?
 				array_init(children, heap_allocator());
 				array_init(children, heap_allocator());
 			}
 			}
@@ -464,7 +464,7 @@ void ssa_opt_tree(ssaGen *s) {
 	s->opt_called = true;
 	s->opt_called = true;
 
 
 	for_array(member_index, s->module.procs) {
 	for_array(member_index, s->module.procs) {
-		ssaProcedure *proc = s->module.procs[member_index];
+		ssaProcedure *proc = s->module.procs.e[member_index];
 		if (proc->blocks.count == 0) { // Prototype/external procedure
 		if (proc->blocks.count == 0) { // Prototype/external procedure
 			continue;
 			continue;
 		}
 		}

+ 18 - 18
src/ssa_print.cpp

@@ -435,7 +435,7 @@ void ssa_print_exact_value(ssaFileBuffer *f, ssaModule *m, ExactValue value, Typ
 				if (i > 0) {
 				if (i > 0) {
 					ssa_fprintf(f, ", ");
 					ssa_fprintf(f, ", ");
 				}
 				}
-				TypeAndValue *tav = type_and_value_of_expression(m->info, cl->elems[i]);
+				TypeAndValue *tav = type_and_value_of_expression(m->info, cl->elems.e[i]);
 				GB_ASSERT(tav != NULL);
 				GB_ASSERT(tav != NULL);
 				ssa_print_compound_element(f, m, tav->value, elem_type);
 				ssa_print_compound_element(f, m, tav->value, elem_type);
 			}
 			}
@@ -460,7 +460,7 @@ void ssa_print_exact_value(ssaFileBuffer *f, ssaModule *m, ExactValue value, Typ
 			Type *elem_type = type->Vector.elem;
 			Type *elem_type = type->Vector.elem;
 
 
 			if (elem_count == 1 && type->Vector.count > 1) {
 			if (elem_count == 1 && type->Vector.count > 1) {
-				TypeAndValue *tav = type_and_value_of_expression(m->info, cl->elems[0]);
+				TypeAndValue *tav = type_and_value_of_expression(m->info, cl->elems.e[0]);
 				GB_ASSERT(tav != NULL);
 				GB_ASSERT(tav != NULL);
 
 
 				for (isize i = 0; i < type->Vector.count; i++) {
 				for (isize i = 0; i < type->Vector.count; i++) {
@@ -474,7 +474,7 @@ void ssa_print_exact_value(ssaFileBuffer *f, ssaModule *m, ExactValue value, Typ
 					if (i > 0) {
 					if (i > 0) {
 						ssa_fprintf(f, ", ");
 						ssa_fprintf(f, ", ");
 					}
 					}
-					TypeAndValue *tav = type_and_value_of_expression(m->info, cl->elems[i]);
+					TypeAndValue *tav = type_and_value_of_expression(m->info, cl->elems.e[i]);
 					GB_ASSERT(tav != NULL);
 					GB_ASSERT(tav != NULL);
 					ssa_print_compound_element(f, m, tav->value, elem_type);
 					ssa_print_compound_element(f, m, tav->value, elem_type);
 				}
 				}
@@ -496,23 +496,23 @@ void ssa_print_exact_value(ssaFileBuffer *f, ssaModule *m, ExactValue value, Typ
 			ExactValue *values = gb_alloc_array(m->tmp_allocator, ExactValue, value_count);
 			ExactValue *values = gb_alloc_array(m->tmp_allocator, ExactValue, value_count);
 
 
 
 
-			if (cl->elems[0]->kind == AstNode_FieldValue) {
+			if (cl->elems.e[0]->kind == AstNode_FieldValue) {
 				isize elem_count = cl->elems.count;
 				isize elem_count = cl->elems.count;
 				for (isize i = 0; i < elem_count; i++) {
 				for (isize i = 0; i < elem_count; i++) {
-					ast_node(fv, FieldValue, cl->elems[i]);
+					ast_node(fv, FieldValue, cl->elems.e[i]);
 					String name = fv->field->Ident.string;
 					String name = fv->field->Ident.string;
 
 
 					TypeAndValue *tav = type_and_value_of_expression(m->info, fv->value);
 					TypeAndValue *tav = type_and_value_of_expression(m->info, fv->value);
 					GB_ASSERT(tav != NULL);
 					GB_ASSERT(tav != NULL);
 
 
 					Selection sel = lookup_field(m->allocator, type, name, false);
 					Selection sel = lookup_field(m->allocator, type, name, false);
-					Entity *f = type->Record.fields[sel.index[0]];
+					Entity *f = type->Record.fields[sel.index.e[0]];
 
 
 					values[f->Variable.field_index] = tav->value;
 					values[f->Variable.field_index] = tav->value;
 				}
 				}
 			} else {
 			} else {
 				for (isize i = 0; i < value_count; i++) {
 				for (isize i = 0; i < value_count; i++) {
-					TypeAndValue *tav = type_and_value_of_expression(m->info, cl->elems[i]);
+					TypeAndValue *tav = type_and_value_of_expression(m->info, cl->elems.e[i]);
 					GB_ASSERT(tav != NULL);
 					GB_ASSERT(tav != NULL);
 
 
 					Entity *f = type->Record.fields_in_src_order[i];
 					Entity *f = type->Record.fields_in_src_order[i];
@@ -754,11 +754,11 @@ void ssa_print_instr(ssaFileBuffer *f, ssaModule *m, ssaValue *value) {
 				ssa_fprintf(f, ", ");
 				ssa_fprintf(f, ", ");
 			}
 			}
 
 
-			ssaValue *edge = instr->Phi.edges[i];
+			ssaValue *edge = instr->Phi.edges.e[i];
 			ssaBlock *block = NULL;
 			ssaBlock *block = NULL;
 			if (instr->parent != NULL &&
 			if (instr->parent != NULL &&
 			    i < instr->parent->preds.count) {
 			    i < instr->parent->preds.count) {
-				block = instr->parent->preds[i];
+				block = instr->parent->preds.e[i];
 			}
 			}
 
 
 			ssa_fprintf(f, "[ ");
 			ssa_fprintf(f, "[ ");
@@ -1238,14 +1238,14 @@ void ssa_print_proc(ssaFileBuffer *f, ssaModule *m, ssaProcedure *proc) {
 
 
 		ssa_fprintf(f, "{\n");
 		ssa_fprintf(f, "{\n");
 		for_array(i, proc->blocks) {
 		for_array(i, proc->blocks) {
-			ssaBlock *block = proc->blocks[i];
+			ssaBlock *block = proc->blocks.e[i];
 
 
 			if (i > 0) ssa_fprintf(f, "\n");
 			if (i > 0) ssa_fprintf(f, "\n");
 			ssa_print_block_name(f, block);
 			ssa_print_block_name(f, block);
 			ssa_fprintf(f, ":\n");
 			ssa_fprintf(f, ":\n");
 
 
 			for_array(j, block->instrs) {
 			for_array(j, block->instrs) {
-				ssaValue *value = block->instrs[j];
+				ssaValue *value = block->instrs.e[j];
 				ssa_print_instr(f, m, value);
 				ssa_print_instr(f, m, value);
 			}
 			}
 		}
 		}
@@ -1255,7 +1255,7 @@ void ssa_print_proc(ssaFileBuffer *f, ssaModule *m, ssaProcedure *proc) {
 	}
 	}
 
 
 	for_array(i, proc->children) {
 	for_array(i, proc->children) {
-		ssa_print_proc(f, m, proc->children[i]);
+		ssa_print_proc(f, m, proc->children.e[i]);
 	}
 	}
 }
 }
 
 
@@ -1296,7 +1296,7 @@ void ssa_print_llvm_ir(ssaGen *ssa) {
 
 
 
 
 	for_array(member_index, m->members.entries) {
 	for_array(member_index, m->members.entries) {
-		auto *entry = &m->members.entries[member_index];
+		auto *entry = &m->members.entries.e[member_index];
 		ssaValue *v = entry->value;
 		ssaValue *v = entry->value;
 		if (v->kind != ssaValue_TypeName) {
 		if (v->kind != ssaValue_TypeName) {
 			continue;
 			continue;
@@ -1307,7 +1307,7 @@ void ssa_print_llvm_ir(ssaGen *ssa) {
 	ssa_fprintf(f, "\n");
 	ssa_fprintf(f, "\n");
 
 
 	for_array(member_index, m->members.entries) {
 	for_array(member_index, m->members.entries) {
-		auto *entry = &m->members.entries[member_index];
+		auto *entry = &m->members.entries.e[member_index];
 		ssaValue *v = entry->value;
 		ssaValue *v = entry->value;
 		if (v->kind != ssaValue_Proc) {
 		if (v->kind != ssaValue_Proc) {
 			continue;
 			continue;
@@ -1318,7 +1318,7 @@ void ssa_print_llvm_ir(ssaGen *ssa) {
 	}
 	}
 
 
 	for_array(member_index, m->members.entries) {
 	for_array(member_index, m->members.entries) {
-		auto *entry = &m->members.entries[member_index];
+		auto *entry = &m->members.entries.e[member_index];
 		ssaValue *v = entry->value;
 		ssaValue *v = entry->value;
 		if (v->kind != ssaValue_Proc) {
 		if (v->kind != ssaValue_Proc) {
 			continue;
 			continue;
@@ -1330,7 +1330,7 @@ void ssa_print_llvm_ir(ssaGen *ssa) {
 
 
 
 
 	for_array(member_index, m->members.entries) {
 	for_array(member_index, m->members.entries) {
-		auto *entry = &m->members.entries[member_index];
+		auto *entry = &m->members.entries.e[member_index];
 		ssaValue *v = entry->value;
 		ssaValue *v = entry->value;
 		if (v->kind != ssaValue_Global) {
 		if (v->kind != ssaValue_Global) {
 			continue;
 			continue;
@@ -1376,7 +1376,7 @@ void ssa_print_llvm_ir(ssaGen *ssa) {
 		ssa_fprintf(f, "!llvm.dbg.cu = !{!0}\n");
 		ssa_fprintf(f, "!llvm.dbg.cu = !{!0}\n");
 
 
 		for_array(di_index, m->debug_info.entries) {
 		for_array(di_index, m->debug_info.entries) {
-			auto *entry = &m->debug_info.entries[di_index];
+			auto *entry = &m->debug_info.entries.e[di_index];
 			ssaDebugInfo *di = entry->value;
 			ssaDebugInfo *di = entry->value;
 			ssa_fprintf(f, "!%d = ", di->id);
 			ssa_fprintf(f, "!%d = ", di->id);
 
 
@@ -1422,7 +1422,7 @@ void ssa_print_llvm_ir(ssaGen *ssa) {
 			case ssaDebugInfo_AllProcs:
 			case ssaDebugInfo_AllProcs:
 				ssa_fprintf(f, "!{");
 				ssa_fprintf(f, "!{");
 				for_array(proc_index, di->AllProcs.procs) {
 				for_array(proc_index, di->AllProcs.procs) {
-					ssaDebugInfo *p = di->AllProcs.procs[proc_index];
+					ssaDebugInfo *p = di->AllProcs.procs.e[proc_index];
 					if (proc_index > 0) {ssa_fprintf(f, ",");}
 					if (proc_index > 0) {ssa_fprintf(f, ",");}
 					ssa_fprintf(f, "!%d", p->id);
 					ssa_fprintf(f, "!%d", p->id);
 				}
 				}

+ 5 - 5
src/timings.cpp

@@ -6,7 +6,7 @@ struct TimeStamp {
 
 
 struct Timings {
 struct Timings {
 	TimeStamp        total;
 	TimeStamp        total;
-	Array<TimeStamp> sections;
+	Array(TimeStamp) sections;
 	u64              freq;
 	u64              freq;
 };
 };
 
 
@@ -51,7 +51,7 @@ TimeStamp make_time_stamp(String label) {
 }
 }
 
 
 void timings_init(Timings *t, String label, isize buffer_size) {
 void timings_init(Timings *t, String label, isize buffer_size) {
-	array_init(&t->sections, heap_allocator(), buffer_size);
+	array_init_reserve(&t->sections, heap_allocator(), buffer_size);
 	t->total = make_time_stamp(label);
 	t->total = make_time_stamp(label);
 	t->freq  = time_stamp__freq();
 	t->freq  = time_stamp__freq();
 }
 }
@@ -62,7 +62,7 @@ void timings_destroy(Timings *t) {
 
 
 void timings__stop_current_section(Timings *t) {
 void timings__stop_current_section(Timings *t) {
 	if (t->sections.count > 0) {
 	if (t->sections.count > 0) {
-		t->sections[t->sections.count-1].finish = time_stamp_time_now();
+		t->sections.e[t->sections.count-1].finish = time_stamp_time_now();
 	}
 	}
 }
 }
 
 
@@ -84,7 +84,7 @@ void timings_print_all(Timings *t) {
 
 
 	isize max_len = t->total.label.len;
 	isize max_len = t->total.label.len;
 	for_array(i, t->sections) {
 	for_array(i, t->sections) {
-		TimeStamp ts = t->sections[i];
+		TimeStamp ts = t->sections.e[i];
 		max_len = gb_max(max_len, ts.label.len);
 		max_len = gb_max(max_len, ts.label.len);
 	}
 	}
 
 
@@ -96,7 +96,7 @@ void timings_print_all(Timings *t) {
 	          time_stamp_as_ms(t->total, t->freq));
 	          time_stamp_as_ms(t->total, t->freq));
 
 
 	for_array(i, t->sections) {
 	for_array(i, t->sections) {
-		TimeStamp ts = t->sections[i];
+		TimeStamp ts = t->sections.e[i];
 		gb_printf("%.*s%.*s - %.3f ms\n",
 		gb_printf("%.*s%.*s - %.3f ms\n",
 		          LIT(ts.label),
 		          LIT(ts.label),
 	              cast(int)(max_len-ts.label.len), SPACES,
 	              cast(int)(max_len-ts.label.len), SPACES,

+ 2 - 2
src/tokenizer.cpp

@@ -296,7 +296,7 @@ struct Tokenizer {
 	isize line_count;
 	isize line_count;
 
 
 	isize error_count;
 	isize error_count;
-	Array<String> allocated_strings;
+	Array(String) allocated_strings;
 };
 };
 
 
 
 
@@ -400,7 +400,7 @@ gb_inline void destroy_tokenizer(Tokenizer *t) {
 		gb_free(heap_allocator(), t->start);
 		gb_free(heap_allocator(), t->start);
 	}
 	}
 	for_array(i, t->allocated_strings) {
 	for_array(i, t->allocated_strings) {
-		gb_free(heap_allocator(), t->allocated_strings[i].text);
+		gb_free(heap_allocator(), t->allocated_strings.e[i].text);
 	}
 	}
 	array_free(&t->allocated_strings);
 	array_free(&t->allocated_strings);
 }
 }