Browse Source

Remove: string overloads; defer

Ginger Bill 8 years ago
parent
commit
3517f96668
18 changed files with 579 additions and 893 deletions
  1. 2 2
      build.bat
  2. 2 2
      misc/shell.bat
  3. 46 43
      src/checker/checker.cpp
  4. 21 16
      src/checker/decl.cpp
  5. 1 1
      src/checker/entity.cpp
  6. 161 151
      src/checker/expr.cpp
  7. 61 42
      src/checker/stmt.cpp
  8. 28 28
      src/checker/types.cpp
  9. 18 30
      src/common.cpp
  10. 1 1
      src/gb/gb.h
  11. 36 37
      src/main.cpp
  12. 52 48
      src/parser.cpp
  13. 78 70
      src/ssa.cpp
  14. 4 2
      src/ssa_opt.cpp
  15. 17 14
      src/ssa_print.cpp
  16. 24 20
      src/string.cpp
  17. 27 30
      src/tokenizer.cpp
  18. 0 356
      src/vm.cpp

+ 2 - 2
build.bat

@@ -47,8 +47,8 @@ rem pushd %build_dir%
 	del *.ilk > NUL 2> NUL
 
 	cl %compiler_settings% "src\main.cpp" ^
-		/link %linker_settings% -OUT:%exe_name% ^
-	&& odin run code/demo.odin
+		/link %linker_settings% -OUT:%exe_name%
+	rem && odin run code/demo.odin
 	rem odin run code/demo.odin
 
 

+ 2 - 2
misc/shell.bat

@@ -1,7 +1,7 @@
 @echo off
 
-call "C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\vcvarsall.bat" x64 1> NUL
-rem call "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" x64 1> NUL
+rem call "C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\vcvarsall.bat" x64 1> NUL
+call "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" x64 1> NUL
 rem call "C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\vcvarsall.bat" x86 1> NUL
 set _NO_DEBUG_HEAP=1
 

+ 46 - 43
src/checker/checker.cpp

@@ -508,10 +508,10 @@ void init_universal_scope(void) {
 	}
 
 // Constants
-	add_global_constant(a, make_string("true"),  t_untyped_bool, make_exact_value_bool(true));
-	add_global_constant(a, make_string("false"), t_untyped_bool, make_exact_value_bool(false));
+	add_global_constant(a, str_lit("true"),  t_untyped_bool, make_exact_value_bool(true));
+	add_global_constant(a, str_lit("false"), t_untyped_bool, make_exact_value_bool(false));
 
-	add_global_entity(make_entity_nil(a, make_string("nil"), t_untyped_nil));
+	add_global_entity(make_entity_nil(a, str_lit("nil"), t_untyped_nil));
 
 // Builtin Procedures
 	for (isize i = 0; i < gb_count_of(builtin_procs); i++) {
@@ -671,7 +671,7 @@ void add_entity_definition(CheckerInfo *i, AstNode *identifier, Entity *entity)
 }
 
 b32 add_entity(Checker *c, Scope *scope, AstNode *identifier, Entity *entity) {
-	if (entity->token.string != make_string("_")) {
+	if (str_ne(entity->token.string, str_lit("_"))) {
 		Entity *insert_entity = scope_insert_entity(scope, entity);
 		if (insert_entity) {
 			Entity *up = insert_entity->using_parent;
@@ -714,7 +714,7 @@ void add_entity_use(Checker *c, AstNode *identifier, Entity *entity) {
 
 
 void add_entity_and_decl_info(Checker *c, AstNode *identifier, Entity *e, DeclInfo *d) {
-	GB_ASSERT(identifier->Ident.string == e->token.string);
+	GB_ASSERT(str_eq(identifier->Ident.string, e->token.string));
 	add_entity(c, e->scope, identifier, e);
 	map_set(&c->info.entities, hash_pointer(e), d);
 }
@@ -925,7 +925,7 @@ void init_preload_types(Checker *c) {
 
 
 	if (t_type_info == NULL) {
-		Entity *e = current_scope_lookup_entity(c->global_scope, make_string("Type_Info"));
+		Entity *e = current_scope_lookup_entity(c->global_scope, str_lit("Type_Info"));
 		if (e == NULL) {
 			compiler_error("Could not find type declaration for `Type_Info`\n"
 			               "Is `runtime.odin` missing from the `core` directory relative to odin.exe?");
@@ -961,7 +961,7 @@ void init_preload_types(Checker *c) {
 	}
 
 	if (t_allocator == NULL) {
-		Entity *e = current_scope_lookup_entity(c->global_scope, make_string("Allocator"));
+		Entity *e = current_scope_lookup_entity(c->global_scope, str_lit("Allocator"));
 		if (e == NULL) {
 			compiler_error("Could not find type declaration for `Allocator`\n"
 			               "Is `runtime.odin` missing from the `core` directory relative to odin.exe?");
@@ -971,7 +971,7 @@ void init_preload_types(Checker *c) {
 	}
 
 	if (t_context == NULL) {
-		Entity *e = current_scope_lookup_entity(c->global_scope, make_string("Context"));
+		Entity *e = current_scope_lookup_entity(c->global_scope, str_lit("Context"));
 		if (e == NULL) {
 			compiler_error("Could not find type declaration for `Context`\n"
 			               "Is `runtime.odin` missing from the `core` directory relative to odin.exe?");
@@ -992,14 +992,42 @@ void add_implicit_value(Checker *c, ImplicitValueId id, String name, String back
 	c->info.implicit_values[id] = value;
 }
 
+
+void check_global_entity(Checker *c, EntityKind kind) {
+	PROF_SCOPED("check_global_entity");
+	for_array(i, c->info.entities.entries) {
+		auto *entry = &c->info.entities.entries[i];
+		Entity *e = cast(Entity *)cast(uintptr)entry->key.key;
+		if (e->kind == kind) {
+			DeclInfo *d = entry->value;
+
+			add_curr_ast_file(c, d->scope->file);
+
+			if (d->scope == e->scope) {
+				if (kind != Entity_Procedure && str_eq(e->token.string, str_lit("main"))) {
+					if (e->scope->is_init) {
+						error(e->token, "`main` is reserved as the entry point procedure in the initial scope");
+						continue;
+					}
+				} else if (e->scope->is_global && str_eq(e->token.string, str_lit("main"))) {
+					error(e->token, "`main` is reserved as the entry point procedure in the initial scope");
+					continue;
+				}
+
+				Scope *prev_scope = c->context.scope;
+				c->context.scope = d->scope;
+				check_entity_decl(c, e, d, NULL);
+			}
+		}
+	}
+}
+
 void check_parsed_files(Checker *c) {
 	Array<AstNode *> import_decls;
 	array_init(&import_decls, heap_allocator());
-	defer (array_free(&import_decls));
 
 	Map<Scope *> file_scopes; // Key: String (fullpath)
 	map_init(&file_scopes, heap_allocator());
-	defer (map_destroy(&file_scopes));
 
 	// Map full filepaths to Scopes
 	for_array(i, c->parser->files) {
@@ -1176,7 +1204,7 @@ void check_parsed_files(Checker *c) {
 				warning(id->token, "Multiple #import of the same file within this scope");
 			}
 
-			if (id->import_name.string == ".") {
+			if (str_eq(id->import_name.string, str_lit("."))) {
 				// NOTE(bill): Add imported entities to this file's scope
 				for_array(elem_index, scope->elements.entries) {
 					Entity *e = scope->elements.entries[elem_index].value;
@@ -1241,39 +1269,10 @@ void check_parsed_files(Checker *c) {
 		}
 	}
 
-	auto check_global_entity = [](Checker *c, EntityKind kind) {
-		PROF_SCOPED("check_global_entity");
-		for_array(i, c->info.entities.entries) {
-			auto *entry = &c->info.entities.entries[i];
-			Entity *e = cast(Entity *)cast(uintptr)entry->key.key;
-			if (e->kind == kind) {
-				DeclInfo *d = entry->value;
-
-				add_curr_ast_file(c, d->scope->file);
-
-				if (d->scope == e->scope) {
-					if (kind != Entity_Procedure && e->token.string == "main") {
-						if (e->scope->is_init) {
-							error(e->token, "`main` is reserved as the entry point procedure in the initial scope");
-							continue;
-						}
-					} else if (e->scope->is_global && e->token.string == "main") {
-						error(e->token, "`main` is reserved as the entry point procedure in the initial scope");
-						continue;
-					}
-
-					Scope *prev_scope = c->context.scope;
-					c->context.scope = d->scope;
-					check_entity_decl(c, e, d, NULL);
-				}
-			}
-		}
-	};
-
 	check_global_entity(c, Entity_TypeName);
 
 	init_preload_types(c);
-	add_implicit_value(c, ImplicitValue_context, make_string("context"), make_string("__context"), t_context);
+	add_implicit_value(c, ImplicitValue_context, str_lit("context"), str_lit("__context"), t_context);
 
 	check_global_entity(c, Entity_Constant);
 	check_global_entity(c, Entity_Procedure);
@@ -1299,8 +1298,8 @@ void check_parsed_files(Checker *c) {
 		b32 bounds_check    = (pi->tags & ProcTag_bounds_check)    != 0;
 		b32 no_bounds_check = (pi->tags & ProcTag_no_bounds_check) != 0;
 
-		auto prev_context = c->context;
-		defer (c->context = prev_context);
+		CheckerContext prev_context = c->context;
+
 		if (bounds_check) {
 			c->context.stmt_state_flags |= StmtStateFlag_bounds_check;
 			c->context.stmt_state_flags &= ~StmtStateFlag_no_bounds_check;
@@ -1310,6 +1309,8 @@ void check_parsed_files(Checker *c) {
 		}
 
 		check_proc_body(c, pi->token, pi->decl, pi->type, pi->body);
+
+		c->context = prev_context;
 	}
 
 	// Add untyped expression values
@@ -1365,6 +1366,8 @@ void check_parsed_files(Checker *c) {
 	// 	gb_printf("%td - %s\n", e->value, type_to_string(prev_type));
 	// }
 
+	map_destroy(&file_scopes);
+	array_free(&import_decls);
 }
 
 

+ 21 - 16
src/checker/decl.cpp

@@ -16,7 +16,6 @@ Type *check_init_variable(Checker *c, Entity *e, Operand *operand, String contex
 
 		if (operand->mode == Addressing_Builtin) {
 			gbString expr_str = expr_to_string(operand->expr);
-			defer (gb_string_free(expr_str));
 
 			// TODO(bill): is this a good enough error message?
 			error(ast_node_token(operand->expr),
@@ -25,6 +24,8 @@ Type *check_init_variable(Checker *c, Entity *e, Operand *operand, String contex
 			      LIT(context_name));
 
 			operand->mode = Addressing_Invalid;
+
+			gb_string_free(expr_str);
 		}
 
 
@@ -64,7 +65,6 @@ void check_init_variables(Checker *c, Entity **lhs, isize lhs_count, AstNodeArra
 	}
 
 	gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&c->tmp_arena);
-	defer (gb_temp_arena_memory_end(tmp));
 
 	// NOTE(bill): If there is a bad syntax error, rhs > lhs which would mean there would need to be
 	// an extra allocation
@@ -102,6 +102,8 @@ void check_init_variables(Checker *c, Entity **lhs, isize lhs_count, AstNodeArra
 	if (rhs_count > 0 && lhs_count != rhs_count) {
 		error(lhs[0]->token, "Assignment count mismatch `%td` := `%td`", lhs_count, rhs_count);
 	}
+
+	gb_temp_arena_memory_end(tmp);
 }
 
 
@@ -129,10 +131,9 @@ void check_entity_decl(Checker *c, Entity *e, DeclInfo *d, Type *named_type, Cyc
 		check_proc_decl(c, e, d);
 		return;
 	}
-	auto prev = c->context;
+	CheckerContext prev = c->context;
 	c->context.scope = d->scope;
 	c->context.decl  = d;
-	defer (c->context = prev);
 
 	switch (e->kind) {
 	case Entity_Constant:
@@ -145,6 +146,8 @@ void check_entity_decl(Checker *c, Entity *e, DeclInfo *d, Type *named_type, Cyc
 		check_type_decl(c, e, d->type_expr, named_type, cycle_checker);
 		break;
 	}
+
+	c->context = prev;
 }
 
 
@@ -165,7 +168,7 @@ void check_var_decl_node(Checker *c, AstNode *node) {
 			String str = token.string;
 			Entity *found = NULL;
 			// NOTE(bill): Ignore assignments to `_`
-			if (str != make_string("_")) {
+			if (str_ne(str, str_lit("_"))) {
 				found = current_scope_lookup_entity(c->context.scope, str);
 			}
 			if (found == NULL) {
@@ -208,7 +211,7 @@ void check_var_decl_node(Checker *c, AstNode *node) {
 			e->type = init_type;
 	}
 
-	check_init_variables(c, entities, entity_count, vd->values, make_string("variable declaration"));
+	check_init_variables(c, entities, entity_count, vd->values, str_lit("variable declaration"));
 
 	for_array(i, vd->names) {
 		if (entities[i] != NULL) {
@@ -256,7 +259,7 @@ void check_init_constant(Checker *c, Entity *e, Operand *operand) {
 		e->type = operand->type;
 	}
 
-	check_assignment(c, operand, e->type, make_string("constant declaration"));
+	check_assignment(c, operand, e->type, str_lit("constant declaration"));
 	if (operand->mode == Addressing_Invalid) {
 		return;
 	}
@@ -311,7 +314,6 @@ void check_type_decl(Checker *c, Entity *e, AstNode *type_expr, Type *def, Cycle
 	if (cycle_checker == NULL) {
 		cycle_checker = &local_cycle_checker;
 	}
-	defer (cycle_checker_destroy(&local_cycle_checker));
 
 	Type *bt = check_type(c, type_expr, named, cycle_checker_add(cycle_checker, e));
 	named->Named.base = bt;
@@ -319,6 +321,8 @@ void check_type_decl(Checker *c, Entity *e, AstNode *type_expr, Type *def, Cycle
 	if (named->Named.base == t_invalid) {
 		gb_printf("check_type_decl: %s\n", type_to_string(named));
 	}
+
+	cycle_checker_destroy(&local_cycle_checker);
 }
 
 
@@ -368,8 +372,8 @@ void check_proc_decl(Checker *c, Entity *e, DeclInfo *d) {
 	Type *proc_type = make_type_proc(c->allocator, e->scope, NULL, 0, NULL, 0, false);
 	e->type = proc_type;
 	ast_node(pd, ProcDecl, d->proc_decl);
+
 	check_open_scope(c, pd->type);
-	defer (check_close_scope(c));
 	check_procedure_type(c, proc_type, pd->type);
 
 	b32 is_foreign      = (pd->tags & ProcTag_foreign)   != 0;
@@ -378,16 +382,15 @@ void check_proc_decl(Checker *c, Entity *e, DeclInfo *d) {
 	b32 is_no_inline    = (pd->tags & ProcTag_no_inline) != 0;
 
 	if ((d->scope->is_file || d->scope->is_global) &&
-	    e->token.string == "main") {
+	    str_eq(e->token.string, str_lit("main"))) {
 		if (proc_type != NULL) {
 			auto *pt = &proc_type->Proc;
 			if (pt->param_count != 0 ||
 			    pt->result_count) {
 				gbString str = type_to_string(proc_type);
-				defer (gb_string_free(str));
-
 				error(e->token,
 				      "Procedure type of `main` was expected to be `proc()`, got %s", str);
+				gb_string_free(str);
 			}
 		}
 	}
@@ -455,6 +458,8 @@ void check_proc_decl(Checker *c, Entity *e, DeclInfo *d) {
 			map_set(fp, key, e);
 		}
 	}
+
+	check_close_scope(c);
 }
 
 void check_var_decl(Checker *c, Entity *e, Entity **entities, isize entity_count, AstNode *type_expr, AstNode *init_expr) {
@@ -482,7 +487,7 @@ void check_var_decl(Checker *c, Entity *e, Entity **entities, isize entity_count
 		GB_ASSERT(entities == NULL || entities[0] == e);
 		Operand operand = {};
 		check_expr(c, &operand, init_expr);
-		check_init_variable(c, e, &operand, make_string("variable declaration"));
+		check_init_variable(c, e, &operand, str_lit("variable declaration"));
 	}
 
 	if (type_expr != NULL) {
@@ -493,7 +498,7 @@ void check_var_decl(Checker *c, Entity *e, Entity **entities, isize entity_count
 	AstNodeArray inits;
 	array_init(&inits, c->allocator, 1);
 	array_add(&inits, init_expr);
-	check_init_variables(c, entities, entity_count, inits, make_string("variable declaration"));
+	check_init_variables(c, entities, entity_count, inits, str_lit("variable declaration"));
 }
 
 void check_proc_body(Checker *c, Token token, DeclInfo *decl, Type *type, AstNode *body) {
@@ -502,8 +507,6 @@ void check_proc_body(Checker *c, Token token, DeclInfo *decl, Type *type, AstNod
 	CheckerContext old_context = c->context;
 	c->context.scope = decl->scope;
 	c->context.decl = decl;
-	defer (c->context = old_context);
-
 
 	GB_ASSERT(type->kind == Type_Proc);
 	if (type->Proc.param_count > 0) {
@@ -552,6 +555,8 @@ void check_proc_body(Checker *c, Token token, DeclInfo *decl, Type *type, AstNod
 
 
 	check_scope_usage(c, c->context.scope);
+
+	c->context = old_context;
 }
 
 

+ 1 - 1
src/checker/entity.cpp

@@ -186,7 +186,7 @@ Entity *make_entity_implicit_value(gbAllocator a, String name, Type *type, Impli
 
 
 Entity *make_entity_dummy_variable(gbAllocator a, Scope *file_scope, Token token) {
-	token.string = make_string("_");
+	token.string = str_lit("_");
 	return make_entity_variable(a, file_scope, token, NULL);
 }
 

File diff suppressed because it is too large
+ 161 - 151
src/checker/expr.cpp


+ 61 - 42
src/checker/stmt.cpp

@@ -18,12 +18,11 @@ void check_stmt_list(Checker *c, AstNodeArray stmts, u32 flags) {
 	}
 
 	gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&c->tmp_arena);
-	defer (gb_temp_arena_memory_end(tmp));
 
-	struct Delay {
+	typedef struct {
 		Entity *e;
 		DeclInfo *d;
-	};
+	} 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);
 
@@ -95,6 +94,8 @@ void check_stmt_list(Checker *c, AstNodeArray stmts, u32 flags) {
 		}
 		check_stmt(c, n, new_flags);
 	}
+
+	gb_temp_arena_memory_end(tmp);
 }
 
 b32 check_is_terminating_list(AstNodeArray stmts) {
@@ -238,9 +239,9 @@ Type *check_assignment_variable(Checker *c, Operand *op_a, AstNode *lhs) {
 
 	// NOTE(bill): Ignore assignments to `_`
 	if (node->kind == AstNode_Ident &&
-	    node->Ident.string == "_") {
+	    str_eq(node->Ident.string, str_lit("_"))) {
 		add_entity_definition(&c->info, node, NULL);
-		check_assignment(c, op_a, NULL, make_string("assignment to `_` identifier"));
+		check_assignment(c, op_a, NULL, str_lit("assignment to `_` identifier"));
 		if (op_a->mode == Addressing_Invalid)
 			return NULL;
 		return op_a->type;
@@ -282,7 +283,6 @@ Type *check_assignment_variable(Checker *c, Operand *op_a, AstNode *lhs) {
 		}
 
 		gbString str = expr_to_string(op_b.expr);
-		defer (gb_string_free(str));
 		switch (op_b.mode) {
 		case Addressing_Value:
 			error(ast_node_token(op_b.expr), "Cannot assign to `%s`", str);
@@ -291,13 +291,14 @@ Type *check_assignment_variable(Checker *c, Operand *op_a, AstNode *lhs) {
 			error(ast_node_token(op_b.expr), "Cannot assign to `%s`", str);
 			break;
 		}
-
+		gb_string_free(str);
 	} break;
 	}
 
-	check_assignment(c, op_a, op_b.type, make_string("assignment"));
-	if (op_a->mode == Addressing_Invalid)
+	check_assignment(c, op_a, op_b.type, str_lit("assignment"));
+	if (op_a->mode == Addressing_Invalid) {
 		return NULL;
+	}
 
 	return op_a->type;
 }
@@ -314,15 +315,13 @@ b32 check_valid_type_match_type(Type *type, b32 *is_union_ptr, b32 *is_any) {
 	return false;
 }
 
-
+void check_stmt_internal(Checker *c, AstNode *node, u32 flags);
 void check_stmt(Checker *c, AstNode *node, u32 flags) {
 	u32 prev_stmt_state_flags = c->context.stmt_state_flags;
-	defer (c->context.stmt_state_flags = prev_stmt_state_flags);
 
 	if (node->stmt_state_flags != 0) {
 		u32 in = node->stmt_state_flags;
 		u32 out = c->context.stmt_state_flags;
-		defer (c->context.stmt_state_flags = out);
 
 		if (in & StmtStateFlag_bounds_check) {
 			out |= StmtStateFlag_bounds_check;
@@ -331,9 +330,16 @@ void check_stmt(Checker *c, AstNode *node, u32 flags) {
 			out |= StmtStateFlag_no_bounds_check;
 			out &= ~StmtStateFlag_bounds_check;
 		}
+
+		c->context.stmt_state_flags = out;
 	}
 
+	check_stmt_internal(c, node, flags);
+
+	c->context.stmt_state_flags = prev_stmt_state_flags;
+}
 
+void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
 	u32 mod_flags = flags & (~Stmt_FallthroughAllowed);
 	switch (node->kind) {
 	case_ast_node(_, EmptyStmt, node); case_end;
@@ -352,16 +358,15 @@ void check_stmt(Checker *c, AstNode *node, u32 flags) {
 		case Addressing_NoValue:
 			return;
 		default: {
-			gbString expr_str = expr_to_string(operand.expr);
-			defer (gb_string_free(expr_str));
 			if (kind == Expr_Stmt) {
 				return;
 			}
 			if (operand.expr->kind == AstNode_CallExpr) {
 				return;
 			}
-
+			gbString expr_str = expr_to_string(operand.expr);
 			error(ast_node_token(node), "Expression is not used: `%s`", expr_str);
+			gb_string_free(expr_str);
 		} break;
 		}
 	case_end;
@@ -403,7 +408,7 @@ void check_stmt(Checker *c, AstNode *node, u32 flags) {
 		ast_node(bl, BasicLit, &basic_lit);
 		*bl = ids->op;
 		bl->kind = Token_Integer;
-		bl->string = make_string("1");
+		bl->string = str_lit("1");
 
 		AstNode binary_expr = {AstNode_BinaryExpr};
 		ast_node(be, BinaryExpr, &binary_expr);
@@ -425,7 +430,6 @@ void check_stmt(Checker *c, AstNode *node, u32 flags) {
 			}
 
 			gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&c->tmp_arena);
-			defer (gb_temp_arena_memory_end(tmp));
 
 			// NOTE(bill): If there is a bad syntax error, rhs > lhs which would mean there would need to be
 			// an extra allocation
@@ -458,6 +462,8 @@ void check_stmt(Checker *c, AstNode *node, u32 flags) {
 			if (lhs_count != rhs_count) {
 				error(ast_node_token(as->lhs[0]), "Assignment count mismatch `%td` = `%td`", lhs_count, rhs_count);
 			}
+
+			gb_temp_arena_memory_end(tmp);
 		} break;
 
 		default: {
@@ -501,10 +507,10 @@ void check_stmt(Checker *c, AstNode *node, u32 flags) {
 		PROF_SCOPED("check_stmt - IfStmt");
 
 		check_open_scope(c, node);
-		defer (check_close_scope(c));
 
-		if (is->init != NULL)
+		if (is->init != NULL) {
 			check_stmt(c, is->init, 0);
+		}
 
 		Operand operand = {Addressing_Invalid};
 		check_expr(c, &operand, is->cond);
@@ -528,6 +534,8 @@ void check_stmt(Checker *c, AstNode *node, u32 flags) {
 				break;
 			}
 		}
+
+		check_close_scope(c);
 	case_end;
 
 	case_ast_node(rs, ReturnStmt, node);
@@ -558,7 +566,7 @@ void check_stmt(Checker *c, AstNode *node, u32 flags) {
 				error(ast_node_token(node), "Expected %td return values, got 0", result_count);
 			} else {
 				check_init_variables(c, variables, result_count,
-				                     rs->results, make_string("return statement"));
+				                     rs->results, str_lit("return statement"));
 			}
 		} else if (rs->results.count > 0) {
 			error(ast_node_token(rs->results[0]), "No return values expected");
@@ -570,10 +578,10 @@ void check_stmt(Checker *c, AstNode *node, u32 flags) {
 
 		u32 new_flags = mod_flags | Stmt_BreakAllowed | Stmt_ContinueAllowed;
 		check_open_scope(c, node);
-		defer (check_close_scope(c));
 
-		if (fs->init != NULL)
+		if (fs->init != NULL) {
 			check_stmt(c, fs->init, 0);
+		}
 		if (fs->cond) {
 			Operand operand = {Addressing_Invalid};
 			check_expr(c, &operand, fs->cond);
@@ -583,9 +591,12 @@ void check_stmt(Checker *c, AstNode *node, u32 flags) {
 				      "Non-boolean condition in `for` statement");
 			}
 		}
-		if (fs->post != NULL)
+		if (fs->post != NULL) {
 			check_stmt(c, fs->post, 0);
+		}
 		check_stmt(c, fs->body, new_flags);
+
+		check_close_scope(c);
 	case_end;
 
 	case_ast_node(ms, MatchStmt, node);
@@ -595,14 +606,13 @@ void check_stmt(Checker *c, AstNode *node, u32 flags) {
 
 		mod_flags |= Stmt_BreakAllowed;
 		check_open_scope(c, node);
-		defer (check_close_scope(c));
 
 		if (ms->init != NULL) {
 			check_stmt(c, ms->init, 0);
 		}
 		if (ms->tag != NULL) {
 			check_expr(c, &x, ms->tag);
-			check_assignment(c, &x, NULL, make_string("match expression"));
+			check_assignment(c, &x, NULL, str_lit("match expression"));
 		} else {
 			x.mode  = Addressing_Constant;
 			x.type  = t_bool;
@@ -610,7 +620,7 @@ void check_stmt(Checker *c, AstNode *node, u32 flags) {
 
 			Token token = {};
 			token.pos = ast_node_token(ms->body).pos;
-			token.string = make_string("true");
+			token.string = str_lit("true");
 			x.expr  = make_ident(c->curr_ast_file, token);
 		}
 
@@ -649,7 +659,7 @@ void check_stmt(Checker *c, AstNode *node, u32 flags) {
 
 		Map<TypeAndToken> seen = {}; // NOTE(bill): Multimap
 		map_init(&seen, heap_allocator());
-		defer (map_destroy(&seen));
+
 		for_array(i, bs->stmts) {
 			AstNode *stmt = bs->stmts[i];
 			if (stmt->kind != AstNode_CaseClause) {
@@ -689,8 +699,6 @@ void check_stmt(Checker *c, AstNode *node, u32 flags) {
 					auto *found = map_get(&seen, key);
 					if (found != NULL) {
 						gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&c->tmp_arena);
-						defer (gb_temp_arena_memory_end(tmp));
-
 						isize count = multi_map_count(&seen, key);
 						TypeAndToken *taps = gb_alloc_array(c->tmp_allocator, TypeAndToken, count);
 
@@ -713,6 +721,8 @@ void check_stmt(Checker *c, AstNode *node, u32 flags) {
 							}
 						}
 
+						gb_temp_arena_memory_end(tmp);
+
 						if (continue_outer) {
 							continue;
 						}
@@ -730,6 +740,10 @@ void check_stmt(Checker *c, AstNode *node, u32 flags) {
 			check_stmt_list(c, cc->stmts, ft_flags);
 			check_close_scope(c);
 		}
+
+		map_destroy(&seen);
+
+		check_close_scope(c);
 	case_end;
 
 	case_ast_node(ms, TypeMatchStmt, node);
@@ -739,18 +753,17 @@ void check_stmt(Checker *c, AstNode *node, u32 flags) {
 
 		mod_flags |= Stmt_BreakAllowed;
 		check_open_scope(c, node);
-		defer (check_close_scope(c));
 
 		b32 is_union_ptr = false;
 		b32 is_any = false;
 
 		check_expr(c, &x, ms->tag);
-		check_assignment(c, &x, NULL, make_string("type match expression"));
+		check_assignment(c, &x, NULL, str_lit("type match expression"));
 		if (!check_valid_type_match_type(x.type, &is_union_ptr, &is_any)) {
 			gbString str = type_to_string(x.type);
-			defer (gb_string_free(str));
 			error(ast_node_token(x.expr),
 			      "Invalid type for this type match expression, got `%s`", str);
+			gb_string_free(str);
 			break;
 		}
 
@@ -789,8 +802,6 @@ void check_stmt(Checker *c, AstNode *node, u32 flags) {
 
 		Map<b32> seen = {};
 		map_init(&seen, heap_allocator());
-		defer (map_destroy(&seen));
-
 
 		for_array(i, bs->stmts) {
 			AstNode *stmt = bs->stmts[i];
@@ -822,9 +833,9 @@ void check_stmt(Checker *c, AstNode *node, u32 flags) {
 					}
 					if (!tag_type_found) {
 						gbString type_str = type_to_string(y.type);
-						defer (gb_string_free(type_str));
 						error(ast_node_token(y.expr),
 						      "Unknown tag type, got `%s`", type_str);
+						gb_string_free(type_str);
 						continue;
 					}
 					case_type = y.type;
@@ -868,6 +879,9 @@ void check_stmt(Checker *c, AstNode *node, u32 flags) {
 			check_stmt_list(c, cc->stmts, mod_flags);
 			check_close_scope(c);
 		}
+		map_destroy(&seen);
+
+		check_close_scope(c);
 	case_end;
 
 
@@ -930,9 +944,6 @@ void check_stmt(Checker *c, AstNode *node, u32 flags) {
 				return;
 			}
 
-			gbString expr_str = expr_to_string(expr);
-			defer (gb_string_free(expr_str));
-
 			switch (e->kind) {
 			case Entity_TypeName: {
 				Type *t = base_type(e->type);
@@ -941,7 +952,9 @@ void check_stmt(Checker *c, AstNode *node, u32 flags) {
 						Entity *f = t->Record.other_fields[i];
 						Entity *found = scope_insert_entity(c->context.scope, f);
 						if (found != NULL) {
+							gbString expr_str = expr_to_string(expr);
 							error(us->token, "Namespace collision while `using` `%s` of: %.*s", expr_str, LIT(found->token.string));
+							gb_string_free(expr_str);
 							return;
 						}
 						f->using_parent = e;
@@ -951,7 +964,9 @@ void check_stmt(Checker *c, AstNode *node, u32 flags) {
 						Entity *f = t->Record.fields[i];
 						Entity *found = scope_insert_entity(c->context.scope, f);
 						if (found != NULL) {
+							gbString expr_str = expr_to_string(expr);
 							error(us->token, "Namespace collision while `using` `%s` of: %.*s", expr_str, LIT(found->token.string));
+							gb_string_free(expr_str);
 							return;
 						}
 						f->using_parent = e;
@@ -960,7 +975,9 @@ void check_stmt(Checker *c, AstNode *node, u32 flags) {
 						Entity *f = t->Record.other_fields[i];
 						Entity *found = scope_insert_entity(c->context.scope, f);
 						if (found != NULL) {
+							gbString expr_str = expr_to_string(expr);
 							error(us->token, "Namespace collision while `using` `%s` of: %.*s", expr_str, LIT(found->token.string));
+							gb_string_free(expr_str);
 							return;
 						}
 						f->using_parent = e;
@@ -974,6 +991,7 @@ void check_stmt(Checker *c, AstNode *node, u32 flags) {
 					Entity *decl = scope->elements.entries[i].value;
 					Entity *found = scope_insert_entity(c->context.scope, decl);
 					if (found != NULL) {
+						gbString expr_str = expr_to_string(expr);
 						error(us->token,
 						      "Namespace collision while `using` `%s` of: %.*s\n"
 						      "\tat %.*s(%td:%td)\n"
@@ -982,6 +1000,7 @@ void check_stmt(Checker *c, AstNode *node, u32 flags) {
 						      LIT(found->token.pos.file), found->token.pos.line, found->token.pos.column,
 						      LIT(decl->token.pos.file), decl->token.pos.line, decl->token.pos.column
 						      );
+						gb_string_free(expr_str);
 						return;
 					}
 				}
@@ -1001,7 +1020,9 @@ void check_stmt(Checker *c, AstNode *node, u32 flags) {
 							}
 							Entity *prev = scope_insert_entity(c->context.scope, uvar);
 							if (prev != NULL) {
+								gbString expr_str = expr_to_string(expr);
 								error(us->token, "Namespace collision while `using` `%s` of: %.*s", expr_str, LIT(prev->token.string));
+								gb_string_free(expr_str);
 								return;
 							}
 						}
@@ -1085,7 +1106,7 @@ void check_stmt(Checker *c, AstNode *node, u32 flags) {
 	case_ast_node(pa, PushAllocator, node);
 		Operand op = {};
 		check_expr(c, &op, pa->expr);
-		check_assignment(c, &op, t_allocator, make_string("argument to push_allocator"));
+		check_assignment(c, &op, t_allocator, str_lit("argument to push_allocator"));
 		check_stmt(c, pa->body, mod_flags);
 	case_end;
 
@@ -1093,7 +1114,7 @@ void check_stmt(Checker *c, AstNode *node, u32 flags) {
 	case_ast_node(pa, PushContext, node);
 		Operand op = {};
 		check_expr(c, &op, pa->expr);
-		check_assignment(c, &op, t_context, make_string("argument to push_context"));
+		check_assignment(c, &op, t_context, str_lit("argument to push_context"));
 		check_stmt(c, pa->body, mod_flags);
 	case_end;
 
@@ -1128,7 +1149,5 @@ void check_stmt(Checker *c, AstNode *node, u32 flags) {
 		add_entity_and_decl_info(c, pd->name, e, d);
 		check_entity_decl(c, e, d, NULL);
 	case_end;
-
-
 	}
 }

+ 28 - 28
src/checker/types.cpp

@@ -719,7 +719,7 @@ b32 are_types_identical(Type *x, Type *y) {
 							if (!are_types_identical(x->Record.fields[i]->type, y->Record.fields[i]->type)) {
 								return false;
 							}
-							if (x->Record.fields[i]->token.string != y->Record.fields[i]->token.string) {
+							if (str_ne(x->Record.fields[i]->token.string, y->Record.fields[i]->token.string)) {
 								return false;
 							}
 						}
@@ -836,7 +836,7 @@ gb_global Entity *entity__slice_capacity = NULL;
 Selection lookup_field(gbAllocator a, Type *type_, String field_name, b32 is_type, Selection sel = empty_selection) {
 	GB_ASSERT(type_ != NULL);
 
-	if (field_name == "_") {
+	if (str_eq(field_name, str_lit("_"))) {
 		return empty_selection;
 	}
 
@@ -849,8 +849,8 @@ Selection lookup_field(gbAllocator a, Type *type_, String field_name, b32 is_typ
 	if (type->kind == Type_Basic) {
 		switch (type->Basic.kind) {
 		case Basic_any: {
-			String type_info_str = make_string("type_info");
-			String data_str = make_string("data");
+			String type_info_str = str_lit("type_info");
+			String data_str = str_lit("data");
 			if (entity__any_type_info == NULL) {
 				entity__any_type_info = make_entity_field(a, NULL, make_token_ident(type_info_str), t_type_info_ptr, false, 0);
 			}
@@ -858,19 +858,19 @@ Selection lookup_field(gbAllocator a, Type *type_, String field_name, b32 is_typ
 				entity__any_data = make_entity_field(a, NULL, make_token_ident(data_str), t_rawptr, false, 1);
 			}
 
-			if (field_name == type_info_str) {
+			if (str_eq(field_name, type_info_str)) {
 				selection_add_index(&sel, 0);
 				sel.entity = entity__any_type_info;
 				return sel;
-			} else if (field_name == data_str) {
+			} else if (str_eq(field_name, data_str)) {
 				selection_add_index(&sel, 1);
 				sel.entity = entity__any_data;
 				return sel;
 			}
 		} break;
 		case Basic_string: {
-			String data_str = make_string("data");
-			String count_str = make_string("count");
+			String data_str = str_lit("data");
+			String count_str = str_lit("count");
 			if (entity__string_data == NULL) {
 				entity__string_data = make_entity_field(a, NULL, make_token_ident(data_str), make_type_pointer(a, t_u8), false, 0);
 			}
@@ -879,11 +879,11 @@ Selection lookup_field(gbAllocator a, Type *type_, String field_name, b32 is_typ
 				entity__string_count = make_entity_field(a, NULL, make_token_ident(count_str), t_int, false, 1);
 			}
 
-			if (field_name == data_str) {
+			if (str_eq(field_name, data_str)) {
 				selection_add_index(&sel, 0);
 				sel.entity = entity__string_data;
 				return sel;
-			} else if (field_name == count_str) {
+			} else if (str_eq(field_name, count_str)) {
 				selection_add_index(&sel, 1);
 				sel.entity = entity__string_count;
 				return sel;
@@ -893,17 +893,17 @@ Selection lookup_field(gbAllocator a, Type *type_, String field_name, b32 is_typ
 
 		return sel;
 	} else if (type->kind == Type_Array) {
-		String count_str = make_string("count");
+		String count_str = str_lit("count");
 		// NOTE(bill): Underlying memory address cannot be changed
-		if (field_name == count_str) {
+		if (str_eq(field_name, count_str)) {
 			// HACK(bill): Memory leak
 			sel.entity = make_entity_constant(a, NULL, make_token_ident(count_str), t_int, make_exact_value_integer(type->Array.count));
 			return sel;
 		}
 	} else if (type->kind == Type_Vector) {
-		String count_str = make_string("count");
+		String count_str = str_lit("count");
 		// NOTE(bill): Vectors are not addressable
-		if (field_name == count_str) {
+		if (str_eq(field_name, count_str)) {
 			// HACK(bill): Memory leak
 			sel.entity = make_entity_constant(a, NULL, make_token_ident(count_str), t_int, make_exact_value_integer(type->Vector.count));
 			return sel;
@@ -914,9 +914,9 @@ Selection lookup_field(gbAllocator a, Type *type_, String field_name, b32 is_typ
 			switch (type->Vector.count) {
 			#define _VECTOR_FIELD_CASE(_length, _name) \
 			case (_length): \
-				if (field_name == _name) { \
+				if (str_eq(field_name, str_lit(_name))) { \
 					selection_add_index(&sel, (_length)-1); \
-					sel.entity = make_entity_vector_elem(a, NULL, make_token_ident(make_string(_name)), type->Vector.elem, (_length)-1); \
+					sel.entity = make_entity_vector_elem(a, NULL, make_token_ident(str_lit(_name)), type->Vector.elem, (_length)-1); \
 					return sel; \
 				} \
 				/*fallthrough*/
@@ -932,16 +932,16 @@ Selection lookup_field(gbAllocator a, Type *type_, String field_name, b32 is_typ
 		}
 
 	} else if (type->kind == Type_Slice) {
-		String data_str     = make_string("data");
-		String count_str    = make_string("count");
-		String capacity_str = make_string("capacity");
+		String data_str     = str_lit("data");
+		String count_str    = str_lit("count");
+		String capacity_str = str_lit("capacity");
 
-		if (field_name == data_str) {
+		if (str_eq(field_name, data_str)) {
 			selection_add_index(&sel, 0);
 			// HACK(bill): Memory leak
 			sel.entity = make_entity_field(a, NULL, make_token_ident(data_str), make_type_pointer(a, type->Slice.elem), false, 0);
 			return sel;
-		} else if (field_name == count_str) {
+		} else if (str_eq(field_name, count_str)) {
 			selection_add_index(&sel, 1);
 			if (entity__slice_count == NULL) {
 				entity__slice_count = make_entity_field(a, NULL, make_token_ident(count_str), t_int, false, 1);
@@ -949,7 +949,7 @@ Selection lookup_field(gbAllocator a, Type *type_, String field_name, b32 is_typ
 
 			sel.entity = entity__slice_count;
 			return sel;
-		} else if (field_name == capacity_str) {
+		} else if (str_eq(field_name, capacity_str)) {
 			selection_add_index(&sel, 2);
 			if (entity__slice_capacity == NULL) {
 				entity__slice_capacity = make_entity_field(a, NULL, make_token_ident(capacity_str), t_int, false, 2);
@@ -972,7 +972,7 @@ Selection lookup_field(gbAllocator a, Type *type_, String field_name, b32 is_typ
 				GB_ASSERT(f->kind == Entity_TypeName);
 				String str = f->token.string;
 
-				if (field_name == str) {
+				if (str_eq(field_name, str)) {
 					sel.entity = f;
 					selection_add_index(&sel, i);
 					return sel;
@@ -985,7 +985,7 @@ Selection lookup_field(gbAllocator a, Type *type_, String field_name, b32 is_typ
 			GB_ASSERT(f->kind != Entity_Variable);
 			String str = f->token.string;
 
-			if (field_name == str) {
+			if (str_eq(field_name, str)) {
 				sel.entity = f;
 				selection_add_index(&sel, i);
 				return sel;
@@ -993,13 +993,13 @@ Selection lookup_field(gbAllocator a, Type *type_, String field_name, b32 is_typ
 		}
 
 		if (is_type_enum(type)) {
-			if (field_name == "count") {
+			if (str_eq(field_name, str_lit("count"))) {
 				sel.entity = type->Record.enum_count;
 				return sel;
-			} else if (field_name == "min_value") {
+			} else if (str_eq(field_name, str_lit("min_value"))) {
 				sel.entity = type->Record.min_value;
 				return sel;
-			} else if (field_name == "max_value") {
+			} else if (str_eq(field_name, str_lit("max_value"))) {
 				sel.entity = type->Record.max_value;
 				return sel;
 			}
@@ -1010,7 +1010,7 @@ Selection lookup_field(gbAllocator a, Type *type_, String field_name, b32 is_typ
 			Entity *f = type->Record.fields[i];
 			GB_ASSERT(f->kind == Entity_Variable && f->flags & EntityFlag_Field);
 			String str = f->token.string;
-			if (field_name == str) {
+			if (str_eq(field_name, str)) {
 				selection_add_index(&sel, i);  // HACK(bill): Leaky memory
 				sel.entity = f;
 				return sel;

+ 18 - 30
src/common.cpp

@@ -1,3 +1,4 @@
+#define GB_NO_DEFER
 #define GB_IMPLEMENTATION
 #include "gb/gb.h"
 
@@ -8,7 +9,7 @@ gbAllocator heap_allocator(void) {
 #include "string.cpp"
 #include "array.cpp"
 
-gb_global String global_module_path = {};
+gb_global String global_module_path = {0};
 gb_global b32 global_module_path_set = false;
 
 
@@ -19,7 +20,6 @@ String get_module_dir() {
 
 	Array<wchar_t> path_buf;
 	array_init(&path_buf, heap_allocator(), 300);
-	defer (array_free(&path_buf));
 	array_resize(&path_buf, 300);
 
 	isize len = 0;
@@ -35,7 +35,6 @@ String get_module_dir() {
 	}
 
 	gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&string_buffer_arena);
-	defer (gb_temp_arena_memory_end(tmp));
 
 	wchar_t *text = gb_alloc_array(string_buffer_allocator, wchar_t, len+1);
 
@@ -52,40 +51,29 @@ String get_module_dir() {
 	global_module_path = path;
 	global_module_path_set = true;
 
+	gb_temp_arena_memory_end(tmp);
+
+	array_free(&path_buf);
+
 	return path;
 }
 
 String path_to_fullpath(gbAllocator a, String s) {
 	gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&string_buffer_arena);
-	defer (gb_temp_arena_memory_end(tmp));
-
 	String16 string16 = string_to_string16(string_buffer_allocator, s);
+	String result = {0};
 
 	DWORD len = GetFullPathNameW(string16.text, 0, NULL, NULL);
-	if (len == 0) {
-		return make_string(NULL, 0);
+	if (len != 0) {
+		wchar_t *text = gb_alloc_array(string_buffer_allocator, wchar_t, len+1);
+		GetFullPathNameW(string16.text, len, text, NULL);
+		text[len] = 0;
+		result = string16_to_string(a, make_string16(text, len));
 	}
-	wchar_t *text = gb_alloc_array(string_buffer_allocator, wchar_t, len+1);
-	GetFullPathNameW(string16.text, len, text, NULL);
-	text[len] = 0;
-
-	return string16_to_string(a, make_string16(text, len));
+	gb_temp_arena_memory_end(tmp);
+	return result;
 }
 
-struct BlockTimer {
-	u64 start;
-	u64 finish;
-	char *msg;
-	BlockTimer(char *msg) : msg(msg) {
-		start = gb_utc_time_now();
-	}
-	~BlockTimer() {
-		finish = gb_utc_time_now();
-		gb_printf_err("%llu us\n", finish-start);
-	}
-};
-
-
 // Hasing
 enum HashKeyKind {
 	HashKey_Default,
@@ -103,7 +91,7 @@ struct HashKey {
 };
 
 gb_inline HashKey hashing_proc(void const *data, isize len) {
-	HashKey h = {};
+	HashKey h = {HashKey_Default};
 	h.kind = HashKey_Default;
 	// h.key = gb_murmur64(data, len);
 	h.key = gb_fnv64a(data, len);
@@ -118,7 +106,7 @@ gb_inline HashKey hash_string(String s) {
 }
 
 gb_inline HashKey hash_pointer(void *ptr) {
-	HashKey h = {};
+	HashKey h = {HashKey_Default};
 	h.key = cast(u64)cast(uintptr)ptr;
 	h.ptr = ptr;
 	h.kind = HashKey_Default;
@@ -130,7 +118,7 @@ b32 hash_key_equal(HashKey a, HashKey b) {
 		// NOTE(bill): If two string's hashes collide, compare the strings themselves
 		if (a.kind == HashKey_String) {
 			if (b.kind == HashKey_String) {
-				return a.string == b.string;
+				return str_eq(a.string, b.string);
 			}
 			return false;
 		}
@@ -364,7 +352,7 @@ gb_inline void map_grow(Map<T> *h) {
 template <typename T>
 void map_rehash(Map<T> *h, isize new_count) {
 	isize i, j;
-	Map<T> nh = {};
+	Map<T> nh = {0};
 	map_init(&nh, h->hashes.allocator);
 	array_resize(&nh.hashes, new_count);
 	array_reserve(&nh.entries, h->entries.count);

+ 1 - 1
src/gb/gb.h

@@ -615,7 +615,7 @@ extern "C++" {
 //
 // NOTE: C++11 (and above) only!
 //
-#if defined(__cplusplus) && ((defined(_MSC_VER) && _MSC_VER >= 1400) || (__cplusplus >= 201103L))
+#if !defined(GB_NO_DEFER) && defined(__cplusplus) && ((defined(_MSC_VER) && _MSC_VER >= 1400) || (__cplusplus >= 201103L))
 extern "C++" {
 	// NOTE(bill): Stupid fucking templates
 	template <typename T> struct gbRemoveReference       { typedef T Type; };

+ 36 - 37
src/main.cpp

@@ -16,12 +16,13 @@
 // NOTE(bill): `name` is used in debugging and profiling modes
 i32 win32_exec_command_line_app(char *name, char *fmt, ...) {
 	STARTUPINFOW start_info = {gb_size_of(STARTUPINFOW)};
-	PROCESS_INFORMATION pi = {};
-	char cmd_line[4096] = {};
+	PROCESS_INFORMATION pi = {0};
+	char cmd_line[4096] = {0};
 	isize cmd_len;
 	va_list va;
 	gbTempArenaMemory tmp;
 	String16 cmd;
+	i32 exit_code = 0;
 
 	start_info.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
 	start_info.wShowWindow = SW_SHOW;
@@ -35,57 +36,55 @@ i32 win32_exec_command_line_app(char *name, char *fmt, ...) {
 	// gb_printf("%.*s\n", cast(int)cmd_len, cmd_line);
 
 	tmp = gb_temp_arena_memory_begin(&string_buffer_arena);
-	defer (gb_temp_arena_memory_end(tmp));
 
 	cmd = string_to_string16(string_buffer_allocator, make_string(cast(u8 *)cmd_line, cmd_len-1));
 
 	if (CreateProcessW(NULL, cmd.text,
 	                   NULL, NULL, true, 0, NULL, NULL,
 	                   &start_info, &pi)) {
-		DWORD exit_code = 0;
-
 		WaitForSingleObject(pi.hProcess, INFINITE);
-		GetExitCodeProcess(pi.hProcess, &exit_code);
+		GetExitCodeProcess(pi.hProcess, cast(DWORD *)&exit_code);
 
 		CloseHandle(pi.hProcess);
 		CloseHandle(pi.hThread);
-
-		return cast(i32)exit_code;
 	} else {
 		// NOTE(bill): failed to create process
 		gb_printf_err("Failed to execute command:\n\t%s\n", cmd_line);
-		return -1;
+		exit_code = -1;
 	}
+
+	gb_temp_arena_memory_end(tmp);
+	return exit_code;
 }
 
-enum ArchKind {
+typedef enum {
 	ArchKind_x64,
 	ArchKind_x86,
-};
+} ArchKind;
 
-struct ArchData {
+typedef struct  {
 	BaseTypeSizes sizes;
 	String llc_flags;
 	String link_flags;
-};
+} ArchData;
 
 ArchData make_arch_data(ArchKind kind) {
-	ArchData data = {};
+	ArchData data = {0};
 
 	switch (kind) {
 	case ArchKind_x64:
 	default:
 		data.sizes.word_size = 8;
 		data.sizes.max_align = 16;
-		data.llc_flags = make_string("-march=x86-64 ");
-		data.link_flags = make_string("/machine:x64 ");
+		data.llc_flags = str_lit("-march=x86-64 ");
+		data.link_flags = str_lit("/machine:x64 ");
 		break;
 
 	case ArchKind_x86:
 		data.sizes.word_size = 4;
 		data.sizes.max_align = 8;
-		data.llc_flags = make_string("-march=x86 ");
-		data.link_flags = make_string("/machine:x86 ");
+		data.llc_flags = str_lit("-march=x86 ");
+		data.link_flags = str_lit("/machine:x86 ");
 		break;
 	}
 
@@ -110,9 +109,9 @@ int main(int argc, char **argv) {
 	}
 	prof_init();
 
-	Timings timings = {};
-	timings_init(&timings, make_string("Total Time"), 128);
-	defer (timings_destroy(&timings));
+	Timings timings = {0};
+	timings_init(&timings, str_lit("Total Time"), 128);
+	// defer (timings_destroy(&timings));
 
 #if 1
 	init_string_buffer_memory();
@@ -124,13 +123,13 @@ int main(int argc, char **argv) {
 
 	char *init_filename = NULL;
 	b32 run_output = false;
-	String arg1 = make_string(argv[1]);
-	if (arg1 == "run") {
+	String arg1 = make_string_c(argv[1]);
+	if (str_eq(arg1, str_lit("run"))) {
 		run_output = true;
 		init_filename = argv[2];
-	} else if (arg1 == "build") {
+	} else if (str_eq(arg1, str_lit("build"))) {
 		init_filename = argv[2];
-	} else if (arg1 == "version") {
+	} else if (str_eq(arg1, str_lit("version"))) {
 		gb_printf("%s version %s", argv[0], VERSION_STRING);
 		return 0;
 	} else {
@@ -140,7 +139,7 @@ int main(int argc, char **argv) {
 
 	// TODO(bill): prevent compiling without a linker
 
-	timings_start_section(&timings, make_string("parse files"));
+	timings_start_section(&timings, str_lit("parse files"));
 
 	Parser parser = {0};
 	if (!init_parser(&parser)) {
@@ -154,9 +153,9 @@ int main(int argc, char **argv) {
 
 
 #if 1
-	timings_start_section(&timings, make_string("type check"));
+	timings_start_section(&timings, str_lit("type check"));
 
-	Checker checker = {};
+	Checker checker = {0};
 	ArchData arch_data = make_arch_data(ArchKind_x64);
 
 	init_checker(&checker, &parser, arch_data.sizes);
@@ -168,25 +167,25 @@ int main(int argc, char **argv) {
 #endif
 #if 1
 
-	ssaGen ssa = {};
+	ssaGen ssa = {0};
 	if (!ssa_gen_init(&ssa, &checker)) {
 		return 1;
 	}
 	// defer (ssa_gen_destroy(&ssa));
 
-	timings_start_section(&timings, make_string("ssa gen"));
+	timings_start_section(&timings, str_lit("ssa gen"));
 	ssa_gen_tree(&ssa);
 
-	timings_start_section(&timings, make_string("ssa opt"));
+	timings_start_section(&timings, str_lit("ssa opt"));
 	ssa_opt_tree(&ssa);
 
-	timings_start_section(&timings, make_string("ssa print"));
+	timings_start_section(&timings, str_lit("ssa print"));
 	ssa_print_llvm_ir(&ssa);
 
 	// prof_print_all();
 
 #if 1
-	timings_start_section(&timings, make_string("llvm-opt"));
+	timings_start_section(&timings, str_lit("llvm-opt"));
 
 	char const *output_name = ssa.output_file.filename;
 	isize base_name_len = gb_path_extension(output_name)-1 - output_name;
@@ -213,7 +212,7 @@ int main(int argc, char **argv) {
 	}
 
 	#if 1
-	timings_start_section(&timings, make_string("llvm-llc"));
+	timings_start_section(&timings, str_lit("llvm-llc"));
 	// For more arguments: http://llvm.org/docs/CommandGuide/llc.html
 	exit_code = win32_exec_command_line_app("llvm-llc",
 		"%.*sbin/llc %.*s.bc -filetype=obj -O%d "
@@ -228,11 +227,11 @@ int main(int argc, char **argv) {
 		return exit_code;
 	}
 
-	timings_start_section(&timings, make_string("msvc-link"));
+	timings_start_section(&timings, str_lit("msvc-link"));
 
 	gbString lib_str = gb_string_make(heap_allocator(), "Kernel32.lib");
 	// defer (gb_string_free(lib_str));
-	char lib_str_buf[1024] = {};
+	char lib_str_buf[1024] = {0};
 	for_array(i, parser.foreign_libraries) {
 		String lib = parser.foreign_libraries[i];
 		isize len = gb_snprintf(lib_str_buf, gb_size_of(lib_str_buf),
@@ -243,7 +242,7 @@ int main(int argc, char **argv) {
 	exit_code = win32_exec_command_line_app("msvc-link",
 		"link %.*s.obj -OUT:%.*s.exe %s "
 		"/defaultlib:libcmt "
-		"/nologo /incremental:no /opt:ref /subsystem:console /debug "
+		"/nologo /incremental:no /opt:ref /subsystem:console "
 		" %.*s "
 		"",
 		LIT(output), LIT(output),

+ 52 - 48
src/parser.cpp

@@ -1133,7 +1133,7 @@ AstNode *parse_identifier(AstFile *f) {
 	if (token.kind == Token_Identifier) {
 		next_token(f);
 	} else {
-		token.string = make_string("_");
+		token.string = str_lit("_");
 		expect_token(f, Token_Identifier);
 	}
 	return make_ident(f, token);
@@ -1274,11 +1274,11 @@ void parse_proc_tags(AstFile *f, u64 *tags, String *foreign_name, String *link_n
 		String tag_name = te->name.string;
 
 		#define ELSE_IF_ADD_TAG(name) \
-		else if (tag_name == #name) { \
+		else if (str_eq(tag_name, str_lit(#name))) { \
 			check_proc_add_tag(f, tag_expr, tags, ProcTag_##name, tag_name); \
 		}
 
-		if (tag_name == "foreign") {
+		if (str_eq(tag_name, str_lit("foreign"))) {
 			check_proc_add_tag(f, tag_expr, tags, ProcTag_foreign, tag_name);
 			if (f->curr_token.kind == Token_String) {
 				*foreign_name = f->curr_token.string;
@@ -1289,7 +1289,7 @@ void parse_proc_tags(AstFile *f, u64 *tags, String *foreign_name, String *link_n
 
 				next_token(f);
 			}
-		} else if (tag_name == "link_name") {
+		} else if (str_eq(tag_name, str_lit("link_name"))) {
 			check_proc_add_tag(f, tag_expr, tags, ProcTag_link_name, tag_name);
 			if (f->curr_token.kind == Token_String) {
 				*link_name = f->curr_token.string;
@@ -1372,7 +1372,7 @@ AstNode *parse_operand(AstFile *f, b32 lhs) {
 	case Token_Hash: {
 		Token token = expect_token(f, Token_Hash);
 		Token name  = expect_token(f, Token_Identifier);
-		if (name.string == "rune") {
+		if (str_eq(name.string, str_lit("rune"))) {
 			if (f->curr_token.kind == Token_String) {
 				Token *s = &f->curr_token;
 
@@ -1384,19 +1384,19 @@ AstNode *parse_operand(AstFile *f, b32 lhs) {
 				expect_token(f, Token_String);
 			}
 			operand = parse_operand(f, lhs);
-		} else if (name.string == "file") {
+		} else if (str_eq(name.string, str_lit("file"))) {
 			Token token = name;
 			token.kind = Token_String;
 			token.string = token.pos.file;
 			return make_basic_lit(f, token);
-		} else if (name.string == "line") {
+		} else if (str_eq(name.string, str_lit("line"))) {
 			Token token = name;
 			token.kind = Token_Integer;
 			char *str = gb_alloc_array(gb_arena_allocator(&f->arena), char, 20);
 			gb_i64_to_str(token.pos.line, str, 10);
-			token.string = make_string(str);
+			token.string = make_string_c(str);
 			return make_basic_lit(f, token);
-		} else if (name.string == "run") {
+		} else if (str_eq(name.string, str_lit("run"))) {
 			AstNode *expr = parse_expr(f, false);
 			operand = make_run_expr(f, token, name, expr);
 			if (unparen_expr(expr)->kind != AstNode_CallExpr) {
@@ -1415,7 +1415,6 @@ AstNode *parse_operand(AstFile *f, b32 lhs) {
 		AstNode *curr_proc = f->curr_proc;
 		AstNode *type = parse_proc_type(f);
 		f->curr_proc = type;
-		defer (f->curr_proc = curr_proc);
 
 		u64 tags = 0;
 		String foreign_name = {};
@@ -1428,17 +1427,17 @@ AstNode *parse_operand(AstFile *f, b32 lhs) {
 			syntax_error(f->curr_token, "#link_name cannot be applied to procedure literals");
 		}
 
-		if (f->curr_token.kind != Token_OpenBrace) {
-			return type;
-		} else {
+		if (f->curr_token.kind == Token_OpenBrace) {
 			AstNode *body;
 
 			f->expr_level++;
 			body = parse_body(f);
 			f->expr_level--;
 
-			return make_proc_lit(f, type, body, tags);
+			type = make_proc_lit(f, type, body, tags);
 		}
+		f->curr_proc = curr_proc;
+		return type;
 	}
 
 	default: {
@@ -2087,12 +2086,12 @@ AstNode *parse_identifier_or_type(AstFile *f, u32 flags) {
 		b32 is_ordered = false;
 		while (allow_token(f, Token_Hash)) {
 			Token tag = expect_token_after(f, Token_Identifier, "`#`");
-			if (tag.string == "packed") {
+			if (str_eq(tag.string, str_lit("packed"))) {
 				if (is_packed) {
 					syntax_error(tag, "Duplicate struct tag `#%.*s`", LIT(tag.string));
 				}
 				is_packed = true;
-			} else if (tag.string == "ordered") {
+			} else if (str_eq(tag.string, str_lit("ordered"))) {
 				if (is_ordered) {
 					syntax_error(tag, "Duplicate struct tag `#%.*s`", LIT(tag.string));
 				}
@@ -2264,7 +2263,6 @@ AstNode *parse_proc_decl(AstFile *f, Token proc_token, AstNode *name) {
 
 	AstNode *curr_proc = f->curr_proc;
 	f->curr_proc = proc_type;
-	defer (f->curr_proc = curr_proc);
 
 	if (f->curr_token.kind == Token_OpenBrace) {
 		if ((tags & ProcTag_foreign) != 0) {
@@ -2273,6 +2271,7 @@ AstNode *parse_proc_decl(AstFile *f, Token proc_token, AstNode *name) {
 		body = parse_body(f);
 	}
 
+	f->curr_proc = curr_proc;
 	return make_proc_decl(f, name, proc_type, body, tags, foreign_name, link_name);
 }
 
@@ -2285,7 +2284,7 @@ AstNode *parse_decl(AstFile *f, AstNodeArray names) {
 		if (name->kind == AstNode_Ident) {
 			String n = name->Ident.string;
 			// NOTE(bill): Check for reserved identifiers
-			if (n == "context") {
+			if (str_eq(n, str_lit("context"))) {
 				syntax_error(ast_node_token(name), "`context` is a reserved identifier");
 				break;
 			}
@@ -2399,7 +2398,7 @@ AstNode *parse_if_stmt(AstFile *f) {
 		if (allow_token(f, Token_Semicolon)) {
 			cond = parse_expr(f, false);
 		} else {
-			cond = convert_stmt_to_expr(f, init, make_string("boolean expression"));
+			cond = convert_stmt_to_expr(f, init, str_lit("boolean expression"));
 			init = NULL;
 		}
 	}
@@ -2489,7 +2488,7 @@ AstNode *parse_for_stmt(AstFile *f) {
 	}
 	body = parse_block_stmt(f);
 
-	cond = convert_stmt_to_expr(f, cond, make_string("boolean expression"));
+	cond = convert_stmt_to_expr(f, cond, str_lit("boolean expression"));
 
 	return make_for_stmt(f, token, init, cond, end, body);
 }
@@ -2559,7 +2558,7 @@ AstNode *parse_match_stmt(AstFile *f) {
 		close = expect_token(f, Token_CloseBrace);
 		body = make_block_stmt(f, list, open, close);
 
-		tag = convert_stmt_to_expr(f, tag, make_string("type match expression"));
+		tag = convert_stmt_to_expr(f, tag, str_lit("type match expression"));
 		return make_type_match_stmt(f, token, tag, var, body);
 	} else {
 		if (f->curr_token.kind != Token_OpenBrace) {
@@ -2591,7 +2590,7 @@ AstNode *parse_match_stmt(AstFile *f) {
 
 		body = make_block_stmt(f, list, open, close);
 
-		tag = convert_stmt_to_expr(f, tag, make_string("match expression"));
+		tag = convert_stmt_to_expr(f, tag, str_lit("match expression"));
 		return make_match_stmt(f, token, init, tag, body);
 	}
 }
@@ -2747,14 +2746,14 @@ AstNode *parse_stmt(AstFile *f) {
 	case Token_Hash: {
 		s = parse_tag_stmt(f, NULL);
 		String tag = s->TagStmt.name.string;
-		if (tag == "shared_global_scope") {
+		if (str_eq(tag, str_lit("shared_global_scope"))) {
 			if (f->curr_proc == NULL) {
 				f->is_global_scope = true;
 				return make_empty_stmt(f, f->curr_token);
 			}
 			syntax_error(token, "You cannot use #shared_global_scope within a procedure. This must be done at the file scope");
 			return make_bad_decl(f, token, f->curr_token);
-		} else if (tag == "import") {
+		} else if (str_eq(tag, str_lit("import"))) {
 			// TODO(bill): better error messages
 			Token import_name = {};
 			Token file_path = expect_token_after(f, Token_String, "#import");
@@ -2768,7 +2767,7 @@ AstNode *parse_stmt(AstFile *f) {
 					import_name = expect_token_after(f, Token_Identifier, "`as` for import declaration");
 				}
 
-				if (import_name.string == "_") {
+				if (str_eq(import_name.string, str_lit("_"))) {
 					syntax_error(token, "Illegal import name: `_`");
 					return make_bad_decl(f, token, f->curr_token);
 				}
@@ -2779,32 +2778,32 @@ AstNode *parse_stmt(AstFile *f) {
 			}
 			syntax_error(token, "You cannot use #import within a procedure. This must be done at the file scope");
 			return make_bad_decl(f, token, file_path);
-		} else if (tag == "load") {
+		} else if (str_eq(tag, str_lit("load"))) {
 			// TODO(bill): better error messages
 			Token file_path = expect_token(f, Token_String);
 			Token import_name = file_path;
-			import_name.string = make_string(".");
+			import_name.string = str_lit(".");
 
 			if (f->curr_proc == NULL) {
 				return make_import_decl(f, s->TagStmt.token, file_path, import_name, true);
 			}
 			syntax_error(token, "You cannot use #load within a procedure. This must be done at the file scope");
 			return make_bad_decl(f, token, file_path);
-		} else if (tag == "foreign_system_library") {
+		} else if (str_eq(tag, str_lit("foreign_system_library"))) {
 			Token file_path = expect_token(f, Token_String);
 			if (f->curr_proc == NULL) {
 				return make_foreign_library(f, s->TagStmt.token, file_path, true);
 			}
 			syntax_error(token, "You cannot use #foreign_system_library within a procedure. This must be done at the file scope");
 			return make_bad_decl(f, token, file_path);
-		} else if (tag == "foreign_library") {
+		} else if (str_eq(tag, str_lit("foreign_library"))) {
 			Token file_path = expect_token(f, Token_String);
 			if (f->curr_proc == NULL) {
 				return make_foreign_library(f, s->TagStmt.token, file_path, false);
 			}
 			syntax_error(token, "You cannot use #foreign_library within a procedure. This must be done at the file scope");
 			return make_bad_decl(f, token, file_path);
-		} else if (tag == "thread_local") {
+		} else if (str_eq(tag, str_lit("thread_local"))) {
 			AstNode *var_decl = parse_simple_stmt(f);
 			if (var_decl->kind != AstNode_VarDecl) {
 				syntax_error(token, "#thread_local may only be applied to variable declarations");
@@ -2816,14 +2815,14 @@ AstNode *parse_stmt(AstFile *f) {
 			}
 			var_decl->VarDecl.tags |= VarDeclTag_thread_local;
 			return var_decl;
-		} else if (tag == "bounds_check") {
+		} else if (str_eq(tag, str_lit("bounds_check"))) {
 			s = parse_stmt(f);
 			s->stmt_state_flags |= StmtStateFlag_bounds_check;
 			if ((s->stmt_state_flags & StmtStateFlag_no_bounds_check) != 0) {
 				syntax_error(token, "#bounds_check and #no_bounds_check cannot be applied together");
 			}
 			return s;
-		} else if (tag == "no_bounds_check") {
+		} else if (str_eq(tag, str_lit("no_bounds_check"))) {
 			s = parse_stmt(f);
 			s->stmt_state_flags |= StmtStateFlag_no_bounds_check;
 			if ((s->stmt_state_flags & StmtStateFlag_bounds_check) != 0) {
@@ -2870,7 +2869,7 @@ AstNodeArray parse_stmt_list(AstFile *f) {
 
 
 ParseFileError init_ast_file(AstFile *f, String fullpath) {
-	if (!string_has_extension(fullpath, make_string("odin"))) {
+	if (!string_has_extension(fullpath, str_lit("odin"))) {
 		return ParseFile_WrongExtension;
 	}
 	TokenizerInitError err = init_tokenizer(&f->tokenizer, fullpath);
@@ -2951,11 +2950,10 @@ void destroy_parser(Parser *p) {
 // NOTE(bill): Returns true if it's added
 b32 try_add_import_path(Parser *p, String path, String rel_path, TokenPos pos) {
 	gb_mutex_lock(&p->mutex);
-	defer (gb_mutex_unlock(&p->mutex));
 
 	for_array(i, p->imports) {
 		String import = p->imports[i].path;
-		if (import == path) {
+		if (str_eq(import, path)) {
 			return false;
 		}
 	}
@@ -2965,52 +2963,59 @@ b32 try_add_import_path(Parser *p, String path, String rel_path, TokenPos pos) {
 	item.rel_path = rel_path;
 	item.pos = pos;
 	array_add(&p->imports, item);
+
+	gb_mutex_unlock(&p->mutex);
+
 	return true;
 }
 
 String get_fullpath_relative(gbAllocator a, String base_dir, String path) {
+	String res = {};
 	isize str_len = base_dir.len+path.len;
 
 	u8 *str = gb_alloc_array(heap_allocator(), u8, str_len+1);
-	defer (gb_free(heap_allocator(), str));
 
 	isize i = 0;
 	gb_memmove(str+i, base_dir.text, base_dir.len); i += base_dir.len;
 	gb_memmove(str+i, path.text, path.len);
 	str[str_len] = '\0';
-	return path_to_fullpath(a, make_string(str, str_len));
+	res = path_to_fullpath(a, make_string(str, str_len));
+	gb_free(heap_allocator(), str);
+	return res;
 }
 
 String get_fullpath_core(gbAllocator a, String path) {
 	String module_dir = get_module_dir();
+	String res = {};
 
 	char core[] = "core/";
 	isize core_len = gb_size_of(core)-1;
 
 	isize str_len = module_dir.len + core_len + path.len;
 	u8 *str = gb_alloc_array(heap_allocator(), u8, str_len+1);
-	defer (gb_free(heap_allocator(), str));
 
 	gb_memmove(str, module_dir.text, module_dir.len);
 	gb_memmove(str+module_dir.len, core, core_len);
 	gb_memmove(str+module_dir.len+core_len, path.text, path.len);
 	str[str_len] = '\0';
 
-	return path_to_fullpath(a, make_string(str, str_len));
+	res = path_to_fullpath(a, make_string(str, str_len));
+	gb_free(heap_allocator(), str);
+	return res;
 }
 
 // NOTE(bill): Returns true if it's added
 b32 try_add_foreign_library_path(Parser *p, String import_file) {
 	gb_mutex_lock(&p->mutex);
-	defer (gb_mutex_unlock(&p->mutex));
 
 	for_array(i, p->foreign_libraries) {
 		String import = p->foreign_libraries[i];
-		if (import == import_file) {
+		if (str_eq(import, import_file)) {
 			return false;
 		}
 	}
 	array_add(&p->foreign_libraries, import_file);
+	gb_mutex_unlock(&p->mutex);
 	return true;
 }
 
@@ -3064,7 +3069,7 @@ String get_filepath_extension(String path) {
 
 		if (c == '.') {
 			if (seen_slash) {
-				return make_string("");
+				return str_lit("");
 			}
 
 			dot = i;
@@ -3166,19 +3171,19 @@ void parse_file(Parser *p, AstFile *f) {
 
 ParseFileError parse_files(Parser *p, char *init_filename) {
 	char *fullpath_str = gb_path_get_full_name(heap_allocator(), init_filename);
-	String init_fullpath = make_string(fullpath_str);
+	String init_fullpath = make_string_c(fullpath_str);
 	TokenPos init_pos = {};
 	ImportedFile init_imported_file = {init_fullpath, init_fullpath, init_pos};
 	array_add(&p->imports, init_imported_file);
 	p->init_fullpath = init_fullpath;
 
 	{
-		String s = get_fullpath_core(heap_allocator(), make_string("_preload.odin"));
+		String s = get_fullpath_core(heap_allocator(), str_lit("_preload.odin"));
 		ImportedFile runtime_file = {s, s, init_pos};
 		array_add(&p->imports, runtime_file);
 	}
 	{
-		String s = get_fullpath_core(heap_allocator(), make_string("_soft_numbers.odin"));
+		String s = get_fullpath_core(heap_allocator(), str_lit("_soft_numbers.odin"));
 		ImportedFile runtime_file = {s, s, init_pos};
 		array_add(&p->imports, runtime_file);
 	}
@@ -3196,7 +3201,6 @@ ParseFileError parse_files(Parser *p, char *init_filename) {
 				gb_printf_err("%.*s(%td:%td) ", LIT(pos.file), pos.line, pos.column);
 			}
 			gb_printf_err("Failed to parse file: %.*s\n\t", LIT(import_rel_path));
-			defer (gb_printf_err("\n"));
 			switch (err) {
 			case ParseFile_WrongExtension:
 				gb_printf_err("Invalid file extension: File must have the extension `.odin`");
@@ -3217,16 +3221,16 @@ ParseFileError parse_files(Parser *p, char *init_filename) {
 				gb_printf_err("Invalid token found in file");
 				break;
 			}
+			gb_printf_err("\n");
 			return err;
 		}
 		parse_file(p, &file);
 
 		{
 			gb_mutex_lock(&p->mutex);
-			defer (gb_mutex_unlock(&p->mutex));
-
 			file.id = p->files.count;
 			array_add(&p->files, file);
+			gb_mutex_unlock(&p->mutex);
 		}
 	}
 

+ 78 - 70
src/ssa.cpp

@@ -1085,7 +1085,7 @@ ssaBlock *ssa_add_block(ssaProcedure *proc, AstNode *node, char *label) {
 	}
 
 	ssaValue *v = ssa_alloc_value(proc->module->allocator, ssaValue_Block);
-	v->Block.label  = make_string(label);
+	v->Block.label  = make_string_c(label);
 	v->Block.node   = node;
 	v->Block.scope  = scope;
 	v->Block.parent = proc;
@@ -1346,7 +1346,7 @@ ssaValue *ssa_emit_call(ssaProcedure *p, ssaValue *value, ssaValue **args, isize
 }
 
 ssaValue *ssa_emit_global_call(ssaProcedure *proc, char *name_, ssaValue **args, isize arg_count) {
-	String name = make_string(name_);
+	String name = make_string_c(name_);
 	ssaValue **found = map_get(&proc->module->members, hash_string(name));
 	GB_ASSERT_MSG(found != NULL, "%.*s", LIT(name));
 	ssaValue *gp = *found;
@@ -1425,7 +1425,7 @@ void ssa_emit_if(ssaProcedure *proc, ssaValue *cond, ssaBlock *true_block, ssaBl
 }
 
 void ssa_emit_startup_runtime(ssaProcedure *proc) {
-	GB_ASSERT(proc->parent == NULL && proc->name == "main");
+	GB_ASSERT(proc->parent == NULL && str_eq(proc->name, str_lit("main")));
 	ssa_emit(proc, ssa_alloc_instr(proc, ssaInstr_StartupRuntime));
 }
 
@@ -1896,7 +1896,7 @@ String lookup_polymorphic_field(CheckerInfo *info, Type *dst, Type *src) {
 			}
 		}
 	}
-	return make_string("");
+	return str_lit("");
 }
 
 ssaValue *ssa_emit_bitcast(ssaProcedure *proc, ssaValue *data, Type *type) {
@@ -2017,7 +2017,7 @@ ssaValue *ssa_emit_conv(ssaProcedure *proc, ssaValue *value, Type *t) {
 		for (isize i = 0; i < dst->Record.field_count; i++) {
 			Entity *f = dst->Record.fields[i];
 			if (are_types_identical(f->type, src_type)) {
-				ssa_emit_comment(proc, make_string("union - child to parent"));
+				ssa_emit_comment(proc, str_lit("union - child to parent"));
 				gbAllocator allocator = proc->module->allocator;
 				ssaValue *parent = ssa_add_local_generated(proc, t);
 				ssaValue *tag = ssa_make_const_int(allocator, i);
@@ -2047,7 +2047,7 @@ ssaValue *ssa_emit_conv(ssaProcedure *proc, ssaValue *value, Type *t) {
 				// NOTE(bill): It can be casted
 				Selection sel = lookup_field(proc->module->allocator, sb, field_name, false);
 				if (sel.entity != NULL) {
-					ssa_emit_comment(proc, make_string("cast - polymorphism"));
+					ssa_emit_comment(proc, str_lit("cast - polymorphism"));
 					if (src_is_ptr) {
 						value = ssa_emit_load(proc, value);
 					}
@@ -2230,7 +2230,6 @@ ssaValue *ssa_emit_down_cast(ssaProcedure *proc, ssaValue *value, Type *t) {
 	String field_name = check_down_cast_name(t, type_deref(ssa_type(value)));
 	GB_ASSERT(field_name.len > 0);
 	Selection sel = lookup_field(proc->module->allocator, t, field_name, false);
-	Type *t_u8_ptr = make_type_pointer(allocator, t_u8);
 	ssaValue *bytes = ssa_emit_conv(proc, value, t_u8_ptr);
 
 	i64 offset_ = type_offset_of_from_selection(proc->module->sizes, allocator, type_deref(t), sel);
@@ -2355,7 +2354,7 @@ isize ssa_type_info_index(CheckerInfo *info, Type *type) {
 }
 
 ssaValue *ssa_type_info(ssaProcedure *proc, Type *type) {
-	ssaValue **found = map_get(&proc->module->members, hash_string(make_string(SSA_TYPE_INFO_DATA_NAME)));
+	ssaValue **found = map_get(&proc->module->members, hash_string(str_lit(SSA_TYPE_INFO_DATA_NAME)));
 	GB_ASSERT(found != NULL);
 	ssaValue *type_info_data = *found;
 	CheckerInfo *info = proc->module->info;
@@ -2558,7 +2557,7 @@ void ssa_build_defer_stmt(ssaProcedure *proc, ssaDefer d) {
 		ssa_emit_jump(proc, b);
 	}
 	proc->curr_block = b;
-	ssa_emit_comment(proc, make_string("defer"));
+	ssa_emit_comment(proc, str_lit("defer"));
 	if (d.kind == ssaDefer_Node) {
 		ssa_build_stmt(proc, d.stmt);
 	} else if (d.kind == ssaDefer_Instr) {
@@ -2700,19 +2699,19 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue
 			return ssa_emit_logical_binary_expr(proc, expr);
 
 		case Token_as:
-			ssa_emit_comment(proc, make_string("cast - as"));
+			ssa_emit_comment(proc, str_lit("cast - as"));
 			return ssa_emit_conv(proc, left, type);
 
 		case Token_transmute:
-			ssa_emit_comment(proc, make_string("cast - transmute"));
+			ssa_emit_comment(proc, str_lit("cast - transmute"));
 			return ssa_emit_transmute(proc, left, type);
 
 		case Token_down_cast:
-			ssa_emit_comment(proc, make_string("cast - down_cast"));
+			ssa_emit_comment(proc, str_lit("cast - down_cast"));
 			return ssa_emit_down_cast(proc, left, type);
 
 		case Token_union_cast:
-			ssa_emit_comment(proc, make_string("cast - union_cast"));
+			ssa_emit_comment(proc, str_lit("cast - union_cast"));
 			return ssa_emit_union_cast(proc, left, type);
 
 		default:
@@ -2764,7 +2763,7 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue
 				} break;
 
 				case BuiltinProc_new: {
-					ssa_emit_comment(proc, make_string("new"));
+					ssa_emit_comment(proc, str_lit("new"));
 					// new :: proc(Type) -> ^Type
 					gbAllocator allocator = proc->module->allocator;
 
@@ -2783,7 +2782,7 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue
 				} break;
 
 				case BuiltinProc_new_slice: {
-					ssa_emit_comment(proc, make_string("new_slice"));
+					ssa_emit_comment(proc, str_lit("new_slice"));
 					// new_slice :: proc(Type, len: int[, cap: int]) -> ^Type
 					gbAllocator allocator = proc->module->allocator;
 
@@ -2825,7 +2824,7 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue
 				} break;
 
 				case BuiltinProc_assert: {
-					ssa_emit_comment(proc, make_string("assert"));
+					ssa_emit_comment(proc, str_lit("assert"));
 					ssaValue *cond = ssa_build_expr(proc, ce->args[0]);
 					GB_ASSERT(is_type_boolean(ssa_type(cond)));
 
@@ -2840,11 +2839,12 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue
 					Token token = ast_node_token(ce->args[0]);
 					TokenPos pos = token.pos;
 					gbString expr = expr_to_string(ce->args[0]);
-					defer (gb_string_free(expr));
 					isize expr_len = gb_string_length(expr);
 					String expr_str = {};
 					expr_str.text = cast(u8 *)gb_alloc_copy_align(proc->module->allocator, expr, expr_len, 1);
 					expr_str.len = expr_len;
+					gb_string_free(expr);
+
 
 					ssaValue **args = gb_alloc_array(proc->module->allocator, ssaValue *, 4);
 					args[0] = ssa_make_const_string(proc->module->allocator, pos.file);
@@ -2860,7 +2860,7 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue
 				} break;
 
 				case BuiltinProc_panic: {
-					ssa_emit_comment(proc, make_string("panic"));
+					ssa_emit_comment(proc, str_lit("panic"));
 					ssaValue *msg = ssa_build_expr(proc, ce->args[0]);
 					GB_ASSERT(is_type_string(ssa_type(msg)));
 
@@ -2879,7 +2879,7 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue
 
 
 				case BuiltinProc_copy: {
-					ssa_emit_comment(proc, make_string("copy"));
+					ssa_emit_comment(proc, str_lit("copy"));
 					// copy :: proc(dst, src: []Type) -> int
 					AstNode *dst_node = ce->args[0];
 					AstNode *src_node = ce->args[1];
@@ -2913,7 +2913,7 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue
 					return len;
 				} break;
 				case BuiltinProc_append: {
-					ssa_emit_comment(proc, make_string("append"));
+					ssa_emit_comment(proc, str_lit("append"));
 					// append :: proc(s: ^[]Type, item: Type) -> bool
 					AstNode *sptr_node = ce->args[0];
 					AstNode *item_node = ce->args[1];
@@ -2970,7 +2970,7 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue
 				} break;
 
 				case BuiltinProc_swizzle: {
-					ssa_emit_comment(proc, make_string("swizzle"));
+					ssa_emit_comment(proc, str_lit("swizzle"));
 					ssaValue *vector = ssa_build_expr(proc, ce->args[0]);
 					isize index_count = ce->args.count-1;
 					if (index_count == 0) {
@@ -2993,14 +2993,14 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue
 
 #if 0
 				case BuiltinProc_ptr_offset: {
-					ssa_emit_comment(proc, make_string("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]);
 					return ssa_emit_ptr_offset(proc, ptr, offset);
 				} break;
 
 				case BuiltinProc_ptr_sub: {
-					ssa_emit_comment(proc, make_string("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]);
 					Type *ptr_type = base_type(ssa_type(ptr_a));
@@ -3018,7 +3018,7 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue
 #endif
 
 				case BuiltinProc_slice_ptr: {
-					ssa_emit_comment(proc, make_string("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 *cap = len;
@@ -3040,7 +3040,7 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue
 				} break;
 
 				case BuiltinProc_min: {
-					ssa_emit_comment(proc, make_string("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]);
 					Type *t = base_type(ssa_type(x));
@@ -3049,7 +3049,7 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue
 				} break;
 
 				case BuiltinProc_max: {
-					ssa_emit_comment(proc, make_string("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]);
 					Type *t = base_type(ssa_type(x));
@@ -3058,7 +3058,7 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue
 				} break;
 
 				case BuiltinProc_abs: {
-					ssa_emit_comment(proc, make_string("abs"));
+					ssa_emit_comment(proc, str_lit("abs"));
 					gbAllocator a = proc->module->allocator;
 
 					ssaValue *x = ssa_build_expr(proc, ce->args[0]);
@@ -3099,7 +3099,7 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue
 				} break;
 
 				case BuiltinProc_enum_to_string: {
-					ssa_emit_comment(proc, make_string("enum_to_string"));
+					ssa_emit_comment(proc, str_lit("enum_to_string"));
 					ssaValue *x = ssa_build_expr(proc, ce->args[0]);
 					Type *t = ssa_type(x);
 					ssaValue *ti = ssa_type_info(proc, t);
@@ -3173,7 +3173,7 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue
 		}
 
 		if (variadic && !vari_expand) {
-			ssa_emit_comment(proc, make_string("variadic call argument generation"));
+			ssa_emit_comment(proc, str_lit("variadic call argument generation"));
 			gbAllocator allocator = proc->module->allocator;
 			Type *slice_type = pt->variables[type->param_count-1]->type;
 			Type *elem_type  = base_type(slice_type)->Slice.elem;
@@ -3301,7 +3301,7 @@ ssaAddr ssa_build_addr(ssaProcedure *proc, AstNode *expr) {
 	case_end;
 
 	case_ast_node(se, SelectorExpr, expr);
-		ssa_emit_comment(proc, make_string("SelectorExpr"));
+		ssa_emit_comment(proc, str_lit("SelectorExpr"));
 		String selector = unparen_expr(se->selector)->Ident.string;
 		Type *type = base_type(type_of_expr(proc->module->info, se->expr));
 
@@ -3335,7 +3335,7 @@ ssaAddr ssa_build_addr(ssaProcedure *proc, AstNode *expr) {
 	case_ast_node(be, BinaryExpr, expr);
 		switch (be->op.kind) {
 		case Token_as: {
-			ssa_emit_comment(proc, make_string("Cast - as"));
+			ssa_emit_comment(proc, str_lit("Cast - as"));
 			// NOTE(bill): Needed for dereference of pointer conversion
 			Type *type = type_of_expr(proc->module->info, expr);
 			ssaValue *v = ssa_add_local_generated(proc, type);
@@ -3343,7 +3343,7 @@ ssaAddr ssa_build_addr(ssaProcedure *proc, AstNode *expr) {
 			return ssa_make_addr(v, expr);
 		}
 		case Token_transmute: {
-			ssa_emit_comment(proc, make_string("Cast - transmute"));
+			ssa_emit_comment(proc, str_lit("Cast - transmute"));
 			// NOTE(bill): Needed for dereference of pointer conversion
 			Type *type = type_of_expr(proc->module->info, expr);
 			ssaValue *v = ssa_add_local_generated(proc, type);
@@ -3357,7 +3357,7 @@ ssaAddr ssa_build_addr(ssaProcedure *proc, AstNode *expr) {
 	case_end;
 
 	case_ast_node(ie, IndexExpr, expr);
-		ssa_emit_comment(proc, make_string("IndexExpr"));
+		ssa_emit_comment(proc, str_lit("IndexExpr"));
 		Type *t = base_type(type_of_expr(proc->module->info, ie->expr));
 		gbAllocator a = proc->module->allocator;
 
@@ -3459,7 +3459,7 @@ ssaAddr ssa_build_addr(ssaProcedure *proc, AstNode *expr) {
 	case_end;
 
 	case_ast_node(se, SliceExpr, expr);
-		ssa_emit_comment(proc, make_string("SliceExpr"));
+		ssa_emit_comment(proc, str_lit("SliceExpr"));
 		gbAllocator a = proc->module->allocator;
 		ssaValue *low  = v_zero;
 		ssaValue *high = NULL;
@@ -3564,7 +3564,7 @@ ssaAddr ssa_build_addr(ssaProcedure *proc, AstNode *expr) {
 	case_end;
 
 	case_ast_node(de, DemaybeExpr, expr);
-		ssa_emit_comment(proc, make_string("DemaybeExpr"));
+		ssa_emit_comment(proc, str_lit("DemaybeExpr"));
 		ssaValue *maybe = ssa_build_expr(proc, de->expr);
 		Type *t = default_type(type_of_expr(proc->module->info, expr));
 		GB_ASSERT(is_type_tuple(t));
@@ -3584,7 +3584,7 @@ ssaAddr ssa_build_addr(ssaProcedure *proc, AstNode *expr) {
 
 
 	case_ast_node(cl, CompoundLit, expr);
-		ssa_emit_comment(proc, make_string("CompoundLit"));
+		ssa_emit_comment(proc, str_lit("CompoundLit"));
 		Type *type = type_of_expr(proc->module->info, expr);
 		Type *bt = base_type(type);
 		ssaValue *v = ssa_add_local_generated(proc, type);
@@ -3700,7 +3700,6 @@ ssaAddr ssa_build_addr(ssaProcedure *proc, AstNode *expr) {
 				Type *elem_type = bt->Slice.elem;
 				Type *elem_ptr_type = make_type_pointer(proc->module->allocator, elem_type);
 				Type *elem_ptr_ptr_type = make_type_pointer(proc->module->allocator, elem_ptr_type);
-				Type *t_int_ptr = make_type_pointer(proc->module->allocator, t_int);
 				ssaValue *slice = ssa_add_module_constant(proc->module, type, make_exact_value_compound(expr));
 				GB_ASSERT(slice->kind == ssaValue_ConstantSlice);
 
@@ -3807,14 +3806,13 @@ void ssa_build_stmt_list(ssaProcedure *proc, AstNodeArray stmts) {
 	}
 }
 
+void ssa_build_stmt_internal(ssaProcedure *proc, AstNode *node);
 void ssa_build_stmt(ssaProcedure *proc, AstNode *node) {
 	u32 prev_stmt_state_flags = proc->module->stmt_state_flags;
-	defer (proc->module->stmt_state_flags = prev_stmt_state_flags);
 
 	if (node->stmt_state_flags != 0) {
 		u32 in = node->stmt_state_flags;
 		u32 out = proc->module->stmt_state_flags;
-		defer (proc->module->stmt_state_flags = out);
 
 		if (in & StmtStateFlag_bounds_check) {
 			out |= StmtStateFlag_bounds_check;
@@ -3823,9 +3821,16 @@ void ssa_build_stmt(ssaProcedure *proc, AstNode *node) {
 			out |= StmtStateFlag_no_bounds_check;
 			out &= ~StmtStateFlag_bounds_check;
 		}
+
+		proc->module->stmt_state_flags = out;
 	}
 
+	ssa_build_stmt_internal(proc, node);
+
+	proc->module->stmt_state_flags = prev_stmt_state_flags;
+}
 
+void ssa_build_stmt_internal(ssaProcedure *proc, AstNode *node) {
 	switch (node->kind) {
 	case_ast_node(bs, EmptyStmt, node);
 	case_end;
@@ -3840,7 +3845,6 @@ void ssa_build_stmt(ssaProcedure *proc, AstNode *node) {
 	case_ast_node(vd, VarDecl, node);
 		ssaModule *m = proc->module;
 		gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&m->tmp_arena);
-		defer (gb_temp_arena_memory_end(tmp));
 
 		if (vd->values.count == 0) { // declared and zero-initialized
 			for_array(i, vd->names) {
@@ -3889,6 +3893,8 @@ void ssa_build_stmt(ssaProcedure *proc, AstNode *node) {
 				ssa_addr_store(proc, lvals[i], v);
 			}
 		}
+
+		gb_temp_arena_memory_end(tmp);
 	case_end;
 
 	case_ast_node(pd, ProcDecl, node);
@@ -3985,7 +3991,7 @@ void ssa_build_stmt(ssaProcedure *proc, AstNode *node) {
 	case_end;
 
 	case_ast_node(ids, IncDecStmt, node);
-		ssa_emit_comment(proc, make_string("IncDecStmt"));
+		ssa_emit_comment(proc, str_lit("IncDecStmt"));
 		TokenKind op = ids->op.kind;
 		if (op == Token_Increment) {
 			op = Token_Add;
@@ -3999,11 +4005,10 @@ void ssa_build_stmt(ssaProcedure *proc, AstNode *node) {
 	case_end;
 
 	case_ast_node(as, AssignStmt, node);
-		ssa_emit_comment(proc, make_string("AssignStmt"));
+		ssa_emit_comment(proc, str_lit("AssignStmt"));
 
 		ssaModule *m = proc->module;
 		gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&m->tmp_arena);
-		defer (gb_temp_arena_memory_end(tmp));
 
 		switch (as->op.kind) {
 		case Token_Eq: {
@@ -4073,6 +4078,8 @@ void ssa_build_stmt(ssaProcedure *proc, AstNode *node) {
 			ssa_build_assign_op(proc, lhs, value, cast(TokenKind)op);
 		} break;
 		}
+
+		gb_temp_arena_memory_end(tmp);
 	case_end;
 
 	case_ast_node(es, ExprStmt, node);
@@ -4087,7 +4094,7 @@ void ssa_build_stmt(ssaProcedure *proc, AstNode *node) {
 	case_end;
 
 	case_ast_node(ds, DeferStmt, node);
-		ssa_emit_comment(proc, make_string("DeferStmt"));
+		ssa_emit_comment(proc, str_lit("DeferStmt"));
 		isize scope_index = proc->scope_index;
 		if (ds->stmt->kind == AstNode_BlockStmt) {
 			scope_index--;
@@ -4096,7 +4103,7 @@ void ssa_build_stmt(ssaProcedure *proc, AstNode *node) {
 	case_end;
 
 	case_ast_node(rs, ReturnStmt, node);
-		ssa_emit_comment(proc, make_string("ReturnStmt"));
+		ssa_emit_comment(proc, str_lit("ReturnStmt"));
 		ssaValue *v = NULL;
 		auto *return_type_tuple  = &proc->type->Proc.results->Tuple;
 		isize return_count = proc->type->Proc.result_count;
@@ -4107,7 +4114,6 @@ void ssa_build_stmt(ssaProcedure *proc, AstNode *node) {
 			v = ssa_emit_conv(proc, ssa_build_expr(proc, rs->results[0]), e->type);
 		} else {
 			gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&proc->module->tmp_arena);
-			defer (gb_temp_arena_memory_end(tmp));
 
 			Array<ssaValue *> results;
 			array_init(&results, proc->module->tmp_allocator, return_count);
@@ -4137,13 +4143,14 @@ void ssa_build_stmt(ssaProcedure *proc, AstNode *node) {
 
 			v = ssa_emit_load(proc, v);
 
+			gb_temp_arena_memory_end(tmp);
 		}
 		ssa_emit_return(proc, v);
 
 	case_end;
 
 	case_ast_node(is, IfStmt, node);
-		ssa_emit_comment(proc, make_string("IfStmt"));
+		ssa_emit_comment(proc, str_lit("IfStmt"));
 		if (is->init != NULL) {
 			ssaBlock *init = ssa_add_block(proc, node, "if.init");
 			ssa_emit_jump(proc, init);
@@ -4179,7 +4186,7 @@ void ssa_build_stmt(ssaProcedure *proc, AstNode *node) {
 	case_end;
 
 	case_ast_node(fs, ForStmt, node);
-		ssa_emit_comment(proc, make_string("ForStmt"));
+		ssa_emit_comment(proc, str_lit("ForStmt"));
 		if (fs->init != NULL) {
 			ssaBlock *init = ssa_add_block(proc, node, "for.init");
 			ssa_emit_jump(proc, init);
@@ -4227,7 +4234,7 @@ void ssa_build_stmt(ssaProcedure *proc, AstNode *node) {
 	case_end;
 
 	case_ast_node(ms, MatchStmt, node);
-		ssa_emit_comment(proc, make_string("MatchStmt"));
+		ssa_emit_comment(proc, str_lit("MatchStmt"));
 		if (ms->init != NULL) {
 			ssa_build_stmt(proc, ms->init);
 		}
@@ -4316,7 +4323,7 @@ void ssa_build_stmt(ssaProcedure *proc, AstNode *node) {
 
 
 	case_ast_node(ms, TypeMatchStmt, node);
-		ssa_emit_comment(proc, make_string("TypeMatchStmt"));
+		ssa_emit_comment(proc, str_lit("TypeMatchStmt"));
 		gbAllocator allocator = proc->module->allocator;
 
 		ssaValue *parent = ssa_build_expr(proc, ms->tag);
@@ -4327,7 +4334,7 @@ void ssa_build_stmt(ssaProcedure *proc, AstNode *node) {
 		ssaValue *tag_index = NULL;
 		ssaValue *union_data = NULL;
 		if (is_union_ptr) {
-			ssa_emit_comment(proc, make_string("get union's tag"));
+			ssa_emit_comment(proc, str_lit("get union's tag"));
 			tag_index = ssa_emit_load(proc, ssa_emit_union_tag_ptr(proc, parent));
 			union_data = ssa_emit_conv(proc, parent, t_rawptr);
 		}
@@ -4454,9 +4461,9 @@ void ssa_build_stmt(ssaProcedure *proc, AstNode *node) {
 			ssa_emit_defer_stmts(proc, ssaDeferExit_Branch, block);
 		}
 		switch (bs->token.kind) {
-		case Token_break:       ssa_emit_comment(proc, make_string("break"));       break;
-		case Token_continue:    ssa_emit_comment(proc, make_string("continue"));    break;
-		case Token_fallthrough: ssa_emit_comment(proc, make_string("fallthrough")); break;
+		case Token_break:       ssa_emit_comment(proc, str_lit("break"));       break;
+		case Token_continue:    ssa_emit_comment(proc, str_lit("continue"));    break;
+		case Token_fallthrough: ssa_emit_comment(proc, str_lit("fallthrough")); break;
 		}
 		ssa_emit_jump(proc, block);
 		ssa_emit_unreachable(proc);
@@ -4465,9 +4472,8 @@ void ssa_build_stmt(ssaProcedure *proc, AstNode *node) {
 
 
 	case_ast_node(pa, PushAllocator, node);
-		ssa_emit_comment(proc, make_string("PushAllocator"));
+		ssa_emit_comment(proc, str_lit("PushAllocator"));
 		ssa_open_scope(proc);
-		defer (ssa_close_scope(proc, ssaDeferExit_Default, NULL));
 
 		ssaValue *context_ptr = ssa_find_implicit_value_backing(proc, ImplicitValue_context);
 		ssaValue *prev_context = ssa_add_local_generated(proc, t_context);
@@ -4480,13 +4486,13 @@ void ssa_build_stmt(ssaProcedure *proc, AstNode *node) {
 
 		ssa_build_stmt(proc, pa->body);
 
+		ssa_close_scope(proc, ssaDeferExit_Default, NULL);
 	case_end;
 
 
 	case_ast_node(pa, PushContext, node);
-		ssa_emit_comment(proc, make_string("PushContext"));
+		ssa_emit_comment(proc, str_lit("PushContext"));
 		ssa_open_scope(proc);
-		defer (ssa_close_scope(proc, ssaDeferExit_Default, NULL));
 
 		ssaValue *context_ptr = ssa_find_implicit_value_backing(proc, ImplicitValue_context);
 		ssaValue *prev_context = ssa_add_local_generated(proc, t_context);
@@ -4497,6 +4503,8 @@ void ssa_build_stmt(ssaProcedure *proc, AstNode *node) {
 		ssa_emit_store(proc, context_ptr, ssa_build_expr(proc, pa->expr));
 
 		ssa_build_stmt(proc, pa->body);
+
+		ssa_close_scope(proc, ssaDeferExit_Default, NULL);
 	case_end;
 
 
@@ -4573,7 +4581,7 @@ void ssa_end_procedure_body(ssaProcedure *proc) {
 
 void ssa_insert_code_before_proc(ssaProcedure* proc, ssaProcedure *parent) {
 	if (parent == NULL) {
-		if (proc->name == "main") {
+		if (str_eq(proc->name, str_lit("main"))) {
 			ssa_emit_startup_runtime(proc);
 		}
 	}
@@ -4607,13 +4615,10 @@ void ssa_build_proc(ssaValue *value, ssaProcedure *parent) {
 
 	if (proc->body != NULL) {
 		u32 prev_stmt_state_flags = proc->module->stmt_state_flags;
-		defer (proc->module->stmt_state_flags = prev_stmt_state_flags);
 
 		if (proc->tags != 0) {
 			u32 in = proc->tags;
 			u32 out = proc->module->stmt_state_flags;
-			defer (proc->module->stmt_state_flags = out);
-
 			if (in & ProcTag_bounds_check) {
 				out |= StmtStateFlag_bounds_check;
 				out &= ~StmtStateFlag_no_bounds_check;
@@ -4621,6 +4626,7 @@ void ssa_build_proc(ssaValue *value, ssaProcedure *parent) {
 				out |= StmtStateFlag_no_bounds_check;
 				out &= ~StmtStateFlag_bounds_check;
 			}
+			proc->module->stmt_state_flags = out;
 		}
 
 
@@ -4628,6 +4634,8 @@ void ssa_build_proc(ssaValue *value, ssaProcedure *parent) {
 		ssa_insert_code_before_proc(proc, parent);
 		ssa_build_stmt(proc, proc->body);
 		ssa_end_procedure_body(proc);
+
+		proc->module->stmt_state_flags = prev_stmt_state_flags;
 	}
 }
 
@@ -4674,7 +4682,7 @@ void ssa_init_module(ssaModule *m, Checker *c) {
 	{
 		// Add type info data
 		{
-			String name = make_string(SSA_TYPE_INFO_DATA_NAME);
+			String name = str_lit(SSA_TYPE_INFO_DATA_NAME);
 			isize count = c->info.type_info_map.entries.count;
 			Entity *e = make_entity_variable(m->allocator, NULL, make_token_ident(name), make_type_array(m->allocator, t_type_info, count));
 			ssaValue *g = ssa_make_value_global(m->allocator, e, NULL);
@@ -4706,7 +4714,7 @@ void ssa_init_module(ssaModule *m, Checker *c) {
 				}
 			}
 
-			String name = make_string(SSA_TYPE_INFO_DATA_MEMBER_NAME);
+			String name = str_lit(SSA_TYPE_INFO_DATA_MEMBER_NAME);
 			Entity *e = make_entity_variable(m->allocator, NULL, make_token_ident(name),
 			                                 make_type_array(m->allocator, t_type_info_member, count));
 			ssaValue *g = ssa_make_value_global(m->allocator, e, NULL);
@@ -4718,7 +4726,7 @@ void ssa_init_module(ssaModule *m, Checker *c) {
 	{
 		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.producer = make_string("odin");
+		di->CompileUnit.producer = str_lit("odin");
 
 		map_set(&m->debug_info, hash_pointer(m), di);
 	}
@@ -4830,7 +4838,7 @@ void ssa_gen_tree(ssaGen *s) {
 		if (e->kind == Entity_Variable) {
 			global_variable_max_count++;
 		} else if (e->kind == Entity_Procedure) {
-			if (e->scope->is_init && name == "main") {
+			if (e->scope->is_init && str_eq(name, str_lit("main"))) {
 				entry_point = e;
 			}
 		}
@@ -4965,7 +4973,7 @@ void ssa_gen_tree(ssaGen *s) {
 
 	{ // Startup Runtime
 		// Cleanup(bill): probably better way of doing code insertion
-		String name = make_string(SSA_STARTUP_RUNTIME_PROC_NAME);
+		String name = str_lit(SSA_STARTUP_RUNTIME_PROC_NAME);
 		Type *proc_type = make_type_proc(a, gb_alloc_item(a, Scope),
 		                                 NULL, 0,
 		                                 NULL, 0, false);
@@ -5016,11 +5024,11 @@ void ssa_gen_tree(ssaGen *s) {
 			ssaValue *type_info_member_data = NULL;
 
 			ssaValue **found = NULL;
-			found = map_get(&proc->module->members, hash_string(make_string(SSA_TYPE_INFO_DATA_NAME)));
+			found = map_get(&proc->module->members, hash_string(str_lit(SSA_TYPE_INFO_DATA_NAME)));
 			GB_ASSERT(found != NULL);
 			type_info_data = *found;
 
-			found = map_get(&proc->module->members, hash_string(make_string(SSA_TYPE_INFO_DATA_MEMBER_NAME)));
+			found = map_get(&proc->module->members, hash_string(str_lit(SSA_TYPE_INFO_DATA_MEMBER_NAME)));
 			GB_ASSERT(found != NULL);
 			type_info_member_data = *found;
 
@@ -5421,6 +5429,6 @@ void ssa_gen_tree(ssaGen *s) {
 
 
 
-	// m->layout = make_string("e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64");
+	// m->layout = str_lit("e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64");
 }
 

+ 4 - 2
src/ssa_opt.cpp

@@ -274,7 +274,6 @@ void ssa_opt_blocks(ssaProcedure *proc) {
 }
 void ssa_opt_build_referrers(ssaProcedure *proc) {
 	gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&proc->module->tmp_arena);
-	defer (gb_temp_arena_memory_end(tmp));
 
 	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
@@ -296,6 +295,8 @@ void ssa_opt_build_referrers(ssaProcedure *proc) {
 			}
 		}
 	}
+
+	gb_temp_arena_memory_end(tmp);
 }
 
 
@@ -370,7 +371,6 @@ void ssa_opt_build_dom_tree(ssaProcedure *proc) {
 	// Based on this paper: http://jgaa.info/accepted/2006/GeorgiadisTarjanWerneck2006.10.1.pdf
 
 	gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&proc->module->tmp_arena);
-	defer (gb_temp_arena_memory_end(tmp));
 
 	isize n = proc->blocks.count;
 	ssaBlock **buf = gb_alloc_array(proc->module->tmp_allocator, ssaBlock *, 5*n);
@@ -450,6 +450,8 @@ void ssa_opt_build_dom_tree(ssaProcedure *proc) {
 	}
 
 	ssa_opt_number_dom_tree(root, 0, 0);
+
+	gb_temp_arena_memory_end(tmp);
 }
 
 void ssa_opt_mem2reg(ssaProcedure *proc) {

+ 17 - 14
src/ssa_print.cpp

@@ -90,7 +90,6 @@ void ssa_print_escape_string(ssaFileBuffer *f, String name, b32 print_quotes) {
 	isize buf_len = name.len + extra + 2;
 
 	gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&string_buffer_arena);
-	defer (gb_temp_arena_memory_end(tmp));
 
 	u8 *buf = gb_alloc_array(string_buffer_allocator, u8, buf_len);
 
@@ -117,6 +116,8 @@ void ssa_print_escape_string(ssaFileBuffer *f, String name, b32 print_quotes) {
 	}
 
 	ssa_file_write(f, buf, j);
+
+	gb_temp_arena_memory_end(tmp);
 }
 
 
@@ -128,7 +129,7 @@ void ssa_print_encoded_local(ssaFileBuffer *f, String name) {
 
 void ssa_print_encoded_global(ssaFileBuffer *f, String name, b32 global_scope) {
 	ssa_fprintf(f, "@");
-	if (!global_scope && name != make_string("main")) {
+	if (!global_scope && str_ne(name, str_lit("main"))) {
 		ssa_fprintf(f, ".");
 	}
 	ssa_print_escape_string(f, name, true);
@@ -482,7 +483,6 @@ void ssa_print_exact_value(ssaFileBuffer *f, ssaModule *m, ExactValue value, Typ
 			ssa_fprintf(f, ">");
 		} else if (is_type_struct(type)) {
 			gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&m->tmp_arena);
-			defer (gb_temp_arena_memory_end(tmp));
 
 			ast_node(cl, CompoundLit, value.value_compound);
 
@@ -543,6 +543,8 @@ void ssa_print_exact_value(ssaFileBuffer *f, ssaModule *m, ExactValue value, Typ
 			if (type->Record.struct_is_packed) {
 				ssa_fprintf(f, ">");
 			}
+
+			gb_temp_arena_memory_end(tmp);
 		} else {
 			ssa_fprintf(f, "zeroinitializer");
 		}
@@ -638,7 +640,7 @@ void ssa_print_instr(ssaFileBuffer *f, ssaModule *m, ssaValue *value) {
 	switch (instr->kind) {
 	case ssaInstr_StartupRuntime: {
 		ssa_fprintf(f, "call void ");
-		ssa_print_encoded_global(f, make_string(SSA_STARTUP_RUNTIME_PROC_NAME), false);
+		ssa_print_encoded_global(f, str_lit(SSA_STARTUP_RUNTIME_PROC_NAME), false);
 		ssa_fprintf(f, "()\n");
 	} break;
 
@@ -889,7 +891,7 @@ void ssa_print_instr(ssaFileBuffer *f, ssaModule *m, ssaValue *value) {
 				}
 
 				ssa_fprintf(f, " ");
-				ssa_print_encoded_global(f, make_string(runtime_proc), false);
+				ssa_print_encoded_global(f, make_string_c(runtime_proc), false);
 				ssa_fprintf(f, "(");
 				ssa_print_type(f, m, type);
 				ssa_fprintf(f, " ");
@@ -1090,7 +1092,7 @@ void ssa_print_instr(ssaFileBuffer *f, ssaModule *m, ssaValue *value) {
 	case ssaInstr_BoundsCheck: {
 		auto *bc = &instr->BoundsCheck;
 		ssa_fprintf(f, "call void ");
-		ssa_print_encoded_global(f, make_string("__bounds_check_error"), false);
+		ssa_print_encoded_global(f, str_lit("__bounds_check_error"), false);
 		ssa_fprintf(f, "(");
 		ssa_print_compound_element(f, m, make_exact_value_string(bc->pos.file), t_string);
 		ssa_fprintf(f, ", ");
@@ -1121,9 +1123,9 @@ void ssa_print_instr(ssaFileBuffer *f, ssaModule *m, ssaValue *value) {
 		auto *bc = &instr->SliceBoundsCheck;
 		ssa_fprintf(f, "call void ");
 		if (bc->is_substring) {
-			ssa_print_encoded_global(f, make_string("__substring_expr_error"), false);
+			ssa_print_encoded_global(f, str_lit("__substring_expr_error"), false);
 		} else {
-			ssa_print_encoded_global(f, make_string("__slice_expr_error"), false);
+			ssa_print_encoded_global(f, str_lit("__slice_expr_error"), false);
 		}
 
 		ssa_fprintf(f, "(");
@@ -1273,21 +1275,19 @@ void ssa_print_llvm_ir(ssaGen *ssa) {
 	ssaModule *m = &ssa->module;
 	ssaFileBuffer buf = {}, *f = &buf;
 	ssa_file_buffer_init(f, &ssa->output_file);
-	defer (ssa_file_buffer_destroy(f));
-
 
 	if (m->layout.len > 0) {
 		ssa_fprintf(f, "target datalayout = \"%.*s\"\n", LIT(m->layout));
 	}
 
-	ssa_print_encoded_local(f, make_string("..string"));
+	ssa_print_encoded_local(f, str_lit("..string"));
 	ssa_fprintf(f, " = type {i8*, ");
 	ssa_print_type(f, m, t_int);
 	ssa_fprintf(f, "} ; Basic_string\n");
-	ssa_print_encoded_local(f, make_string("..rawptr"));
+	ssa_print_encoded_local(f, str_lit("..rawptr"));
 	ssa_fprintf(f, " = type i8* ; Basic_rawptr\n");
 
-	ssa_print_encoded_local(f, make_string("..any"));
+	ssa_print_encoded_local(f, str_lit("..any"));
 	ssa_fprintf(f, " = type {");
 	ssa_print_type(f, m, t_type_info_ptr);
 	ssa_fprintf(f, ", ");
@@ -1379,7 +1379,6 @@ void ssa_print_llvm_ir(ssaGen *ssa) {
 			auto *entry = &m->debug_info.entries[di_index];
 			ssaDebugInfo *di = entry->value;
 			ssa_fprintf(f, "!%d = ", di->id);
-			defer (ssa_fprintf(f, "\n"));
 
 			switch (di->kind) {
 			case ssaDebugInfo_CompileUnit: {
@@ -1430,6 +1429,10 @@ void ssa_print_llvm_ir(ssaGen *ssa) {
 				ssa_fprintf(f, "}");
 				break;
 			}
+
+			ssa_fprintf(f, "\n");
 		}
 	}
+
+	ssa_file_buffer_destroy(f);
 }

+ 24 - 20
src/string.cpp

@@ -1,5 +1,5 @@
-gb_global gbArena string_buffer_arena = {};
-gb_global gbAllocator string_buffer_allocator = {};
+gb_global gbArena string_buffer_arena = {0};
+gb_global gbAllocator string_buffer_allocator = {0};
 
 void init_string_buffer_memory(void) {
 	// NOTE(bill): This should be enough memory for file systems
@@ -42,14 +42,12 @@ gb_inline String16 make_string16(wchar_t *text, isize len) {
 }
 
 
-gb_inline String make_string(char *text) {
+gb_inline String make_string_c(char *text) {
 	return make_string(cast(u8 *)cast(void *)text, gb_strlen(text));
 }
 
-template <size_t N>
-gb_inline String make_string(char const (&text)[N]) {
-	return make_string(cast(u8 *)cast(void *)text, N-1);
-}
+#define str_lit(c_str) make_string(cast(u8 *)c_str, gb_size_of(c_str)-1)
+
 
 gb_inline b32 are_strings_equal(String a, String b) {
 	if (a.len == b.len) {
@@ -58,7 +56,7 @@ gb_inline b32 are_strings_equal(String a, String b) {
 	return false;
 }
 
-gb_inline b32 are_strings_equal_ignore_case(String a, String b) {
+gb_inline b32 str_eq_ignore_case(String a, String b) {
 	if (a.len == b.len) {
 		for (isize i = 0; i < a.len; i++) {
 			char x = cast(char)a.text[i];
@@ -115,18 +113,24 @@ GB_COMPARE_PROC(string_cmp_proc) {
 }
 
 
-gb_inline bool operator ==(String a, String b) { return are_strings_equal(a, b) != 0; }
-gb_inline bool operator !=(String a, String b) { return !operator==(a, b); }
-gb_inline bool operator < (String a, String b) { return string_compare(a, b) < 0; }
-gb_inline bool operator > (String a, String b) { return string_compare(a, b) > 0; }
-gb_inline bool operator <=(String a, String b) { return string_compare(a, b) <= 0; }
-gb_inline bool operator >=(String a, String b) { return string_compare(a, b) >= 0; }
+// gb_inline bool operator ==(String a, String b) { return are_strings_equal(a, b) != 0; }
+// gb_inline bool operator !=(String a, String b) { return !operator==(a, b); }
+// gb_inline bool operator < (String a, String b) { return string_compare(a, b) < 0; }
+// gb_inline bool operator > (String a, String b) { return string_compare(a, b) > 0; }
+// gb_inline bool operator <=(String a, String b) { return string_compare(a, b) <= 0; }
+// gb_inline bool operator >=(String a, String b) { return string_compare(a, b) >= 0; }
 
-template <size_t N> gb_inline bool operator ==(String a, char const (&b)[N]) { return a == make_string(cast(u8 *)b, N-1); }
-template <size_t N> gb_inline bool operator !=(String a, char const (&b)[N]) { return a != make_string(cast(u8 *)b, N-1); }
-template <size_t N> gb_inline bool operator ==(char const (&a)[N], String b) { return make_string(cast(u8 *)a, N-1) == b; }
-template <size_t N> gb_inline bool operator !=(char const (&a)[N], String b) { return make_string(cast(u8 *)a, N-1) != b; }
+// template <size_t N> gb_inline bool operator ==(String a, char const (&b)[N]) { return a == make_string(cast(u8 *)b, N-1); }
+// template <size_t N> gb_inline bool operator !=(String a, char const (&b)[N]) { return a != make_string(cast(u8 *)b, N-1); }
+// template <size_t N> gb_inline bool operator ==(char const (&a)[N], String b) { return make_string(cast(u8 *)a, N-1) == b; }
+// template <size_t N> gb_inline bool operator !=(char const (&a)[N], String b) { return make_string(cast(u8 *)a, N-1) != b; }
 
+gb_inline bool str_eq(String a, String b) { return are_strings_equal(a, b) != 0; }
+gb_inline bool str_ne(String a, String b) { return !str_eq(a, b);                }
+gb_inline bool str_lt(String a, String b) { return string_compare(a, b) < 0;     }
+gb_inline bool str_gt(String a, String b) { return string_compare(a, b) > 0;     }
+gb_inline bool str_le(String a, String b) { return string_compare(a, b) <= 0;    }
+gb_inline bool str_ge(String a, String b) { return string_compare(a, b) >= 0;    }
 
 
 
@@ -385,12 +389,12 @@ i32 unquote_string(gbAllocator a, String *s_) {
 	}
 
 
-	u8 rune_temp[4] = {};
+	u8 rune_temp[4] = {0};
 	isize buf_len = 3*s.len / 2;
 	u8 *buf = gb_alloc_array(a, u8, buf_len);
 	isize offset = 0;
 	while (s.len > 0) {
-		String tail_string = {};
+		String tail_string = {0};
 		Rune r = 0;
 		b32 multiple_bytes = false;
 		b32 success = unquote_char(s, quote, &r, &multiple_bytes, &tail_string);

+ 27 - 30
src/tokenizer.cpp

@@ -180,7 +180,6 @@ void init_global_error_collector(void) {
 
 void warning(Token token, char *fmt, ...) {
 	gb_mutex_lock(&global_error_collector.mutex);
-	defer (gb_mutex_unlock(&global_error_collector.mutex));
 
 	global_error_collector.warning_count++;
 	// NOTE(bill): Duplicate error, skip it
@@ -195,11 +194,12 @@ void warning(Token token, char *fmt, ...) {
 		              gb_bprintf_va(fmt, va));
 		va_end(va);
 	}
+
+	gb_mutex_unlock(&global_error_collector.mutex);
 }
 
 void error(Token token, char *fmt, ...) {
 	gb_mutex_lock(&global_error_collector.mutex);
-	defer (gb_mutex_unlock(&global_error_collector.mutex));
 
 	global_error_collector.count++;
 	// NOTE(bill): Duplicate error, skip it
@@ -214,11 +214,12 @@ void error(Token token, char *fmt, ...) {
 		              gb_bprintf_va(fmt, va));
 		va_end(va);
 	}
+
+	gb_mutex_unlock(&global_error_collector.mutex);
 }
 
 void syntax_error(Token token, char *fmt, ...) {
 	gb_mutex_lock(&global_error_collector.mutex);
-	defer (gb_mutex_unlock(&global_error_collector.mutex));
 
 	global_error_collector.count++;
 	// NOTE(bill): Duplicate error, skip it
@@ -233,6 +234,8 @@ void syntax_error(Token token, char *fmt, ...) {
 		              gb_bprintf_va(fmt, va));
 		va_end(va);
 	}
+
+	gb_mutex_unlock(&global_error_collector.mutex);
 }
 
 
@@ -349,13 +352,12 @@ void advance_to_next_rune(Tokenizer *t) {
 TokenizerInitError init_tokenizer(Tokenizer *t, String fullpath) {
 	PROF_PROC();
 
+	TokenizerInitError err = TokenizerInit_None;
+
 	char *c_str = gb_alloc_array(heap_allocator(), char, fullpath.len+1);
 	memcpy(c_str, fullpath.text, fullpath.len);
 	c_str[fullpath.len] = '\0';
 
-	defer (gb_free(heap_allocator(), c_str));
-
-
 	// TODO(bill): Memory map rather than copy contents
 	gbFileContents fc = gb_file_read_contents(heap_allocator(), true, c_str);
 	gb_zero_item(t);
@@ -363,9 +365,7 @@ TokenizerInitError init_tokenizer(Tokenizer *t, String fullpath) {
 		t->start = cast(u8 *)fc.data;
 		t->line = t->read_curr = t->curr = t->start;
 		t->end = t->start + fc.size;
-
 		t->fullpath = fullpath;
-
 		t->line_count = 1;
 
 		advance_to_next_rune(t);
@@ -374,28 +374,25 @@ TokenizerInitError init_tokenizer(Tokenizer *t, String fullpath) {
 		}
 
 		array_init(&t->allocated_strings, heap_allocator());
+	} else {
+		gbFile f = {};
+		gbFileError file_err = gb_file_open(&f, c_str);
 
-		return TokenizerInit_None;
-	}
+		switch (file_err) {
+		case gbFileError_Invalid:    err = TokenizerInit_Invalid;    break;
+		case gbFileError_NotExists:  err = TokenizerInit_NotExists;  break;
+		case gbFileError_Permission: err = TokenizerInit_Permission; break;
+		}
 
-	gbFile f = {};
-	gbFileError err = gb_file_open(&f, c_str);
-	defer (gb_file_close(&f));
-
-	switch (err) {
-	case gbFileError_Invalid:
-		return TokenizerInit_Invalid;
-	case gbFileError_NotExists:
-		return TokenizerInit_NotExists;
-	case gbFileError_Permission:
-		return TokenizerInit_Permission;
-	}
+		if (err == TokenizerInit_None && gb_file_size(&f) == 0) {
+			err = TokenizerInit_Empty;
+		}
 
-	if (gb_file_size(&f) == 0) {
-		return TokenizerInit_Empty;
+		gb_file_close(&f);
 	}
 
-	return TokenizerInit_None;
+	gb_free(heap_allocator(), c_str);
+	return err;
 }
 
 gb_inline void destroy_tokenizer(Tokenizer *t) {
@@ -634,17 +631,17 @@ Token tokenizer_get_token(Tokenizer *t) {
 
 		// NOTE(bill): All keywords are > 1
 		if (token.string.len > 1) {
-			if (token.string == token_strings[Token_as]) {
+			if (str_eq(token.string, token_strings[Token_as])) {
 				token.kind = Token_as;
-			} else if (token.string == token_strings[Token_transmute]) {
+			} else if (str_eq(token.string, token_strings[Token_transmute])) {
 				token.kind = Token_transmute;
-			} else if (token.string == token_strings[Token_down_cast]) {
+			} else if (str_eq(token.string, token_strings[Token_down_cast])) {
 				token.kind = Token_down_cast;
-			} else if (token.string == token_strings[Token_union_cast]) {
+			} else if (str_eq(token.string, token_strings[Token_union_cast])) {
 				token.kind = Token_union_cast;
 			} else {
 				for (i32 k = Token__KeywordBegin+1; k < Token__KeywordEnd; k++) {
-					if (token.string == token_strings[k]) {
+					if (str_eq(token.string, token_strings[k])) {
 						token.kind = cast(TokenKind)k;
 						break;
 					}

+ 0 - 356
src/vm.cpp

@@ -1,356 +0,0 @@
-#if 0
-// TODO(bill): COMPLETELY REWORK THIS ENTIRE INTERPRETER
-#include "dyncall/include/dyncall.h"
-
-struct vmInterpreter;
-
-/*
-Types:
-boolean
-integer
-float
-pointer
-string
-any
-array
-vector
-slice
-maybe
-struct
-union
-raw_union
-enum
-tuple
-proc
-*/
-
-struct vmProcedure {
-	Type * type;
-	String name;
-	b32    is_external;
-};
-
-struct vmValue {
-	void *data;
-	i32   id;
-	Type *type;
-	union {
-		i64            v_int;
-		f32            v_f32;
-		f64            v_f64;
-		vmProcedure *  v_proc;
-	};
-};
-
-Array<vmValue> vm_empty_args = {};
-
-struct vmFrame {
-	vmInterpreter *i;
-	vmFrame *      caller;
-	ssaProcedure * proc;
-	ssaBlock *     block;
-	ssaBlock *     prev_block;
-	isize          instr_index; // For the current block
-
-	Array<void *>  env; // Index == instr id
-	vmValue        result;
-};
-
-struct vmInterpreter {
-	ssaModule *    module;
-	BaseTypeSizes  sizes;
-	gbArena        stack_arena;
-	gbAllocator    stack_allocator;
-	gbAllocator    heap_allocator;
-
-	Array<vmFrame> frame_stack;
-	Map<vmValue>   globals;
-};
-
-enum vmContinuation {
-	vmContinuation_Next,
-	vmContinuation_Return,
-	vmContinuation_Branch,
-};
-
-
-
-
-i64 vm_size_of(vmInterpreter *i, Type *type) {
-	return type_size_of(i->sizes, i->heap_allocator, type);
-}
-i64 vm_align_of(vmInterpreter *i, Type *type) {
-	return type_align_of(i->sizes, i->heap_allocator, type);
-}
-i64 vm_offset_of(vmInterpreter *i, Type *type, i64 index) {
-	return type_offset_of(i->sizes, i->heap_allocator, type, index);
-}
-
-
-
-
-
-
-Array<vmValue> vm_prepare_call(vmFrame *f, ssaInstr *instr, vmValue *proc) {
-	GB_ASSERT(instr->kind == ssaInstr_Call);
-
-	*proc = vm_get_value(f, instr->Call.value);
-
-	Array<vmValue> args = {};
-	array_init_count(&args, f->i->stack_allocator, instr->Call.arg_count);
-
-	for (isize i = 0; i < instr->Call.arg_count; i++) {
-		args[i] = vm_get_value(f, instr->Call.args[i]);
-	}
-
-	return args;
-}
-
-
-vmContinuation vm_visit_instr(vmFrame *f, ssaValue *value) {
-	ssaInstr *instr = &value->Instr;
-#if 1
-	if (instr->kind != ssaInstr_Comment) {
-		gb_printf("instr: %.*s\n", LIT(ssa_instr_strings[instr->kind]));
-	}
-#endif
-	switch (instr->kind) {
-	case ssaInstr_StartupRuntime: {
-
-	} break;
-
-	case ssaInstr_Comment: break;
-
-	case ssaInstr_Local: {
-		Type *type = ssa_type(value);
-		GB_ASSERT(is_type_pointer(type));
-		i64 size  = gb_max(1, vm_size_of(f->i, type));
-		i64 align = gb_max(1, vm_align_of(f->i, type));
-		void *mem = gb_alloc_align(f->i->stack_allocator, size, align);
-
-		array_add(&f->locals, mem);
-	} break;
-
-	case ssaInstr_ZeroInit: {
-		Type *pt = ssa_type(instr->ZeroInit.address);
-		GB_ASSERT(is_type_pointer(pt));
-		vmValue addr = vm_get_value(f, instr->ZeroInit.address);
-		GB_ASSERT(are_types_identical(addr.type, ptr));
-		i64 size = vm_size_of(vm, type_deref(pt));
-		gb_zero(addr.v_ptr, size);
-	} break;
-
-	case ssaInstr_Store: {
-		ssaValue *addr = instr->Store.Address;
-		ssaValue *value = instr->Store.Value;
-	} break;
-
-	case ssaInstr_Load: {
-		ssaValue *addr = instr->Load.Address;
-	} break;
-
-	case ssaInstr_ArrayElementPtr: {
-
-	} break;
-
-	case ssaInstr_StructElementPtr: {
-
-	} break;
-
-	case ssaInstr_PtrOffset: {
-
-	} break;
-
-	case ssaInstr_Phi:
-		for_array(i, f->block->preds) {
-			ssaBlock *pred = f->block->preds[i];
-			if (f->prev_block == pred) {
-				vmValue edge = vm_get_value(f, instr->Phi.edges[i]);
-				// vm_set_value(f, value, edge);
-				break;
-			}
-		}
-		break;
-
-	case ssaInstr_ArrayExtractValue: {
-
-	} break;
-
-	case ssaInstr_StructExtractValue: {
-
-	} break;
-
-	case ssaInstr_Jump:
-		f->prev_block = f->block;
-		f->block = instr->Jump.block;
-		return vmContinuation_Branch;
-
-	case ssaInstr_If:
-		f->prev_block = f->block;
-		if (vm_get_value(f, instr->If.cond).v_int != 0) {
-			f->block = instr->If.true_block;
-		} else {
-			f->block = instr->If.false_block;
-		}
-		return vmContinuation_Branch;
-
-	case ssaInstr_Return:
-		if (instr->Return.value != NULL) {
-			Type *type = base_type(ssa_type(instr->Return.value));
-			GB_ASSERT(is_type_tuple(type));
-			f->result = vm_get_value(f, instr->Return.value);
-			if (type->Tuple.variable_count == 1) {
-				f->result.type = type->Tuple.variables[0]->type;
-			}
-		}
-		f->block = NULL;
-		return vmContinuation_Return;
-
-	case ssaInstr_Conv: {
-
-	} break;
-
-	case ssaInstr_Unreachable: {
-		GB_PANIC("Unreachable");
-	} break;
-
-	case ssaInstr_BinaryOp: {
-
-	} break;
-
-	case ssaInstr_Call: {
-
-	} break;
-
-	case ssaInstr_Select: {
-
-	} break;
-
-	case ssaInstr_VectorExtractElement: {
-
-	} break;
-
-	case ssaInstr_VectorInsertElement: {
-
-	} break;
-
-	case ssaInstr_VectorShuffle: {
-
-	} break;
-
-	case ssaInstr_BoundsCheck: {
-
-	} break;
-
-	case ssaInstr_SliceBoundsCheck: {
-
-	} break;
-
-	default: {
-		GB_PANIC("<unknown instr> %d\n", instr->kind);
-	} break;
-	}
-
-	return vmContinuation_Next;
-}
-
-
-void vm_run_frame(vmFrame *f) {
-	for (;;) {
-		for_array(i, f->block->instrs) {
-			ssaValue *v = f->block->instrs[i];
-			GB_ASSERT(v->kind == ssaValue_Instr);
-			switch (vm_visit_instr(f, v)) {
-			case vmContinuation_Return:
-				return;
-			case vmContinuation_Next:
-				// Do nothing
-				break;
-			case vmContinuation_Branch:
-				goto end;
-			}
-		}
-	end:
-		;
-	}
-}
-
-ssaProcedure *vm_lookup_proc(vmInterpreter *i, String name) {
-	ssaValue **found = map_get(&i->module->members, hash_string(name));
-	if (found == NULL) {
-		return NULL;
-	}
-	ssaValue *v = *found;
-	if (v->kind != ssaValue_Proc) {
-		return NULL;
-	}
-
-	return &v->Proc;
-}
-
-vmValue vm_ext(vmFrame *caller, Array<vmValue> args) {
-	GB_PANIC("TODO(bill): vm_ext");
-	vmValue v = {};
-	return v;
-}
-
-vmValue vm_call(vmInterpreter *i, vmFrame *caller, ssaProcedure *proc, Array<vmValue> args) {
-	if (proc == NULL) {
-		GB_PANIC("Call to NULL procedure");
-	}
-
-	gb_printf("Call: %.*s", LIT(proc->name));
-
-	vmFrame f = {};
-	f.i = i;
-	f.caller = caller;
-	f.proc = proc;
-	if (proc->body == NULL) {
-		return vm_ext(&f, args);
-	}
-	f.block = proc->blocks[0];
-
-	map_init_with_reserve(&f.env, i->heap_allocator, 1.5*proc->instr_count);
-	defer (map_destroy(&f.env));
-
-	array_init_count(&f.locals, i->heap_allocator, proc->local_count);
-	defer (array_free(&f.locals));
-
-	for_array(i, proc->params) {
-		map_set(&f.env, hash_pointer(proc->params[i]), args[i]);
-	}
-
-	while (f.block != NULL) {
-		vm_run_frame(&f);
-	}
-
-	return f.result;
-}
-
-i32 vm_interpret(ssaModule *m) {
-	i32 exit_code = 2;
-
-	vmInterpreter i = {};
-
-	i.module = m;
-	i.sizes = m->sizes;
-
-	gb_arena_init_from_allocator(&i.stack_arena, heap_allocator(), gb_megabytes(64));
-	defer (gb_arena_free(&i.stack_arena));
-
-	i.stack_allocator = gb_arena_allocator(&i.stack_arena);
-	i.heap_allocator  = heap_allocator();
-
-	ssaProcedure *main_proc = vm_lookup_proc(&i, make_string("main"));
-	if (main_proc != NULL) {
-		vm_call(&i, NULL, main_proc, vm_empty_args);
-		exit_code = 0;
-	} else {
-		gb_printf_err("No main procedure.");
-		exit_code = 1;
-	}
-
-	return exit_code;
-}
-
-#endif

Some files were not shown because too many files changed in this diff